| From foo@baz Sun Nov 22 12:00:04 PM CET 2020 |
| From: Sven Van Asbroeck <thesven73@gmail.com> |
| Date: Thu, 12 Nov 2020 13:59:49 -0500 |
| Subject: lan743x: fix issue causing intermittent kernel log warnings |
| |
| From: Sven Van Asbroeck <thesven73@gmail.com> |
| |
| [ 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] [<c0111a38>] (unwind_backtrace) from [<c010be28>] (show_stack+0x10/0x14) |
| [ 50.179162] [<c010be28>] (show_stack) from [<c05b9dec>] (dump_stack+0xac/0xd8) |
| [ 50.186408] [<c05b9dec>] (dump_stack) from [<c0122e40>] (__warn+0xd0/0x10c) |
| [ 50.193391] [<c0122e40>] (__warn) from [<c0123238>] (warn_slowpath_fmt+0x98/0xc4) |
| [ 50.200892] [<c0123238>] (warn_slowpath_fmt) from [<c012b010>] (__local_bh_enable_ip+0x100/0x184) |
| [ 50.209860] [<c012b010>] (__local_bh_enable_ip) from [<bf09ecbc>] (destroy_conntrack+0x48/0xd8 [nf_conntrack]) |
| [ 50.220038] [<bf09ecbc>] (destroy_conntrack [nf_conntrack]) from [<c0ac9b58>] (nf_conntrack_destroy+0x94/0x168) |
| [ 50.230160] [<c0ac9b58>] (nf_conntrack_destroy) from [<c0a4aaa0>] (skb_release_head_state+0xa0/0xd0) |
| [ 50.239314] [<c0a4aaa0>] (skb_release_head_state) from [<c0a4aadc>] (skb_release_all+0xc/0x24) |
| [ 50.247946] [<c0a4aadc>] (skb_release_all) from [<c0a4b4cc>] (consume_skb+0x74/0x17c) |
| [ 50.255796] [<c0a4b4cc>] (consume_skb) from [<c081a2dc>] (lan743x_tx_release_desc+0x120/0x124) |
| [ 50.264428] [<c081a2dc>] (lan743x_tx_release_desc) from [<c081a98c>] (lan743x_tx_napi_poll+0x5c/0x18c) |
| [ 50.273755] [<c081a98c>] (lan743x_tx_napi_poll) from [<c0a6b050>] (net_rx_action+0x118/0x4a4) |
| [ 50.282306] [<c0a6b050>] (net_rx_action) from [<c0101364>] (__do_softirq+0x13c/0x53c) |
| [ 50.290157] [<c0101364>] (__do_softirq) from [<c012b29c>] (irq_exit+0x150/0x17c) |
| [ 50.297575] [<c012b29c>] (irq_exit) from [<c0196a08>] (__handle_domain_irq+0x60/0xb0) |
| [ 50.305423] [<c0196a08>] (__handle_domain_irq) from [<c05d44fc>] (gic_handle_irq+0x4c/0x90) |
| [ 50.313790] [<c05d44fc>] (gic_handle_irq) from [<c0100ed4>] (__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): [<c0a6afec>] net_rx_action+0xb4/0x4a4 |
| [ 50.360892] hardirqs last disabled at (2525027): [<c0d6d2fc>] _raw_spin_lock_irqsave+0x1c/0x50 |
| [ 50.369517] softirqs last enabled at (2524660): [<c01015b4>] __do_softirq+0x38c/0x53c |
| [ 50.377446] softirqs last disabled at (2524693): [<c012b29c>] 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 <thesven73@gmail.com> |
| Link: https://lore.kernel.org/r/20201112185949.11315-1-TheSven73@gmail.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/microchip/lan743x_main.c | 10 +++++----- |
| 1 file changed, 5 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/net/ethernet/microchip/lan743x_main.c |
| +++ b/drivers/net/ethernet/microchip/lan743x_main.c |
| @@ -1245,13 +1245,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; |
| @@ -1561,7 +1561,7 @@ static netdev_tx_t lan743x_tx_xmit_frame |
| 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; |
| @@ -1594,7 +1594,7 @@ static netdev_tx_t lan743x_tx_xmit_frame |
| start_frame_length, |
| do_timestamp, |
| skb->ip_summed == CHECKSUM_PARTIAL)) { |
| - dev_kfree_skb(skb); |
| + dev_kfree_skb_irq(skb); |
| goto unlock; |
| } |
| |
| @@ -1614,7 +1614,7 @@ static netdev_tx_t lan743x_tx_xmit_frame |
| * frame assembler clean up was performed inside |
| * lan743x_tx_frame_add_fragment |
| */ |
| - dev_kfree_skb(skb); |
| + dev_kfree_skb_irq(skb); |
| goto unlock; |
| } |
| } |