From: Sven Van Asbroeck Date: Thu, 12 Nov 2020 18:59:49 +0000 (-0500) Subject: lan743x: fix issue causing intermittent kernel log warnings X-Git-Tag: v5.9.11~244 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9fa50915c00ca6cffaf2d3db05cfecf08ac963a;p=thirdparty%2Fkernel%2Fstable.git lan743x: fix issue causing intermittent kernel log warnings [ Upstream commit e35df62e04cc6fc4b9d90d054732f138349ff9b1 ] When running this chip on arm imx6, we intermittently observe the following kernel warning in the log, especially when the system is under high load: [ 50.119484] ------------[ cut here ]------------ [ 50.124377] WARNING: CPU: 0 PID: 303 at kernel/softirq.c:169 __local_bh_enable_ip+0x100/0x184 [ 50.132925] IRQs not enabled as expected [ 50.159250] CPU: 0 PID: 303 Comm: rngd Not tainted 5.7.8 #1 [ 50.164837] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) [ 50.171395] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 50.179162] [] (show_stack) from [] (dump_stack+0xac/0xd8) [ 50.186408] [] (dump_stack) from [] (__warn+0xd0/0x10c) [ 50.193391] [] (__warn) from [] (warn_slowpath_fmt+0x98/0xc4) [ 50.200892] [] (warn_slowpath_fmt) from [] (__local_bh_enable_ip+0x100/0x184) [ 50.209860] [] (__local_bh_enable_ip) from [] (destroy_conntrack+0x48/0xd8 [nf_conntrack]) [ 50.220038] [] (destroy_conntrack [nf_conntrack]) from [] (nf_conntrack_destroy+0x94/0x168) [ 50.230160] [] (nf_conntrack_destroy) from [] (skb_release_head_state+0xa0/0xd0) [ 50.239314] [] (skb_release_head_state) from [] (skb_release_all+0xc/0x24) [ 50.247946] [] (skb_release_all) from [] (consume_skb+0x74/0x17c) [ 50.255796] [] (consume_skb) from [] (lan743x_tx_release_desc+0x120/0x124) [ 50.264428] [] (lan743x_tx_release_desc) from [] (lan743x_tx_napi_poll+0x5c/0x18c) [ 50.273755] [] (lan743x_tx_napi_poll) from [] (net_rx_action+0x118/0x4a4) [ 50.282306] [] (net_rx_action) from [] (__do_softirq+0x13c/0x53c) [ 50.290157] [] (__do_softirq) from [] (irq_exit+0x150/0x17c) [ 50.297575] [] (irq_exit) from [] (__handle_domain_irq+0x60/0xb0) [ 50.305423] [] (__handle_domain_irq) from [] (gic_handle_irq+0x4c/0x90) [ 50.313790] [] (gic_handle_irq) from [] (__irq_usr+0x54/0x80) [ 50.321287] Exception stack(0xecd99fb0 to 0xecd99ff8) [ 50.326355] 9fa0: 1cf1aa74 00000001 00000001 00000000 [ 50.334547] 9fc0: 00000001 00000000 00000000 00000000 00000000 00000000 00004097 b6d17d14 [ 50.342738] 9fe0: 00000001 b6d17c60 00000000 b6e71f94 800b0010 ffffffff [ 50.349364] irq event stamp: 2525027 [ 50.352955] hardirqs last enabled at (2525026): [] net_rx_action+0xb4/0x4a4 [ 50.360892] hardirqs last disabled at (2525027): [] _raw_spin_lock_irqsave+0x1c/0x50 [ 50.369517] softirqs last enabled at (2524660): [] __do_softirq+0x38c/0x53c [ 50.377446] softirqs last disabled at (2524693): [] irq_exit+0x150/0x17c [ 50.385027] ---[ end trace c0b571db4bc8087d ]--- The driver is calling dev_kfree_skb() from code inside a spinlock, where h/w interrupts are disabled. This is forbidden, as documented in include/linux/netdevice.h. The correct function to use dev_kfree_skb_irq(), or dev_kfree_skb_any(). Fix by using the correct dev_kfree_skb_xxx() functions: in lan743x_tx_release_desc(): called by lan743x_tx_release_completed_descriptors() called by in lan743x_tx_napi_poll() which holds a spinlock called by lan743x_tx_release_all_descriptors() called by lan743x_tx_close() which can-sleep conclusion: use dev_kfree_skb_any() in lan743x_tx_xmit_frame(): which holds a spinlock conclusion: use dev_kfree_skb_irq() in lan743x_tx_close(): which can-sleep conclusion: use dev_kfree_skb() in lan743x_rx_release_ring_element(): called by lan743x_rx_close() which can-sleep called by lan743x_rx_open() which can-sleep conclusion: use dev_kfree_skb() Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver") Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20201112185949.11315-1-TheSven73@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index bc368136bccc6..0a58389c68f14 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1308,13 +1308,13 @@ clean_up_data_descriptor: goto clear_active; if (!(buffer_info->flags & TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) { - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb_any(buffer_info->skb); goto clear_skb; } if (cleanup) { lan743x_ptp_unrequest_tx_timestamp(tx->adapter); - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb_any(buffer_info->skb); } else { ignore_sync = (buffer_info->flags & TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0; @@ -1624,7 +1624,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, if (required_number_of_descriptors > lan743x_tx_get_avail_desc(tx)) { if (required_number_of_descriptors > (tx->ring_size - 1)) { - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } else { /* save to overflow buffer */ tx->overflow_skb = skb; @@ -1657,7 +1657,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, start_frame_length, do_timestamp, skb->ip_summed == CHECKSUM_PARTIAL)) { - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); goto unlock; } @@ -1676,7 +1676,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, * frame assembler clean up was performed inside * lan743x_tx_frame_add_fragment */ - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); goto unlock; } }