| From d90c162430159bf49140202236c49980add34447 Mon Sep 17 00:00:00 2001 |
| From: Francesco Ruggeri <fruggeri@arista.com> |
| Date: Thu, 2 Jul 2020 15:39:06 -0700 |
| Subject: [PATCH] igb: reinit_locked() should be called with rtnl_lock |
| |
| commit 024a8168b749db7a4aa40a5fbdfa04bf7e77c1c0 upstream. |
| |
| We observed two panics involving races with igb_reset_task. |
| The first panic is caused by this race condition: |
| |
| kworker reboot -f |
| |
| igb_reset_task |
| igb_reinit_locked |
| igb_down |
| napi_synchronize |
| __igb_shutdown |
| igb_clear_interrupt_scheme |
| igb_free_q_vectors |
| igb_free_q_vector |
| adapter->q_vector[v_idx] = NULL; |
| napi_disable |
| Panics trying to access |
| adapter->q_vector[v_idx].napi_state |
| |
| The second panic (a divide error) is caused by this race: |
| |
| kworker reboot -f tx packet |
| |
| igb_reset_task |
| __igb_shutdown |
| rtnl_lock() |
| ... |
| igb_clear_interrupt_scheme |
| igb_free_q_vectors |
| adapter->num_tx_queues = 0 |
| ... |
| rtnl_unlock() |
| rtnl_lock() |
| igb_reinit_locked |
| igb_down |
| igb_up |
| netif_tx_start_all_queues |
| dev_hard_start_xmit |
| igb_xmit_frame |
| igb_tx_queue_mapping |
| Panics on |
| r_idx % adapter->num_tx_queues |
| |
| This commit applies to igb_reset_task the same changes that |
| were applied to ixgbe in commit 2f90b8657ec9 ("ixgbe: this patch |
| adds support for DCB to the kernel and ixgbe driver"), |
| commit 8f4c5c9fb87a ("ixgbe: reinit_locked() should be called with |
| rtnl_lock") and commit 88adce4ea8f9 ("ixgbe: fix possible race in |
| reset subtask"). |
| |
| Signed-off-by: Francesco Ruggeri <fruggeri@arista.com> |
| Tested-by: Aaron Brown <aaron.f.brown@intel.com> |
| Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c |
| index a7e52e33c90a..879ade3adefc 100644 |
| --- a/drivers/net/ethernet/intel/igb/igb_main.c |
| +++ b/drivers/net/ethernet/intel/igb/igb_main.c |
| @@ -6205,9 +6205,18 @@ static void igb_reset_task(struct work_struct *work) |
| struct igb_adapter *adapter; |
| adapter = container_of(work, struct igb_adapter, reset_task); |
| |
| + rtnl_lock(); |
| + /* If we're already down or resetting, just bail */ |
| + if (test_bit(__IGB_DOWN, &adapter->state) || |
| + test_bit(__IGB_RESETTING, &adapter->state)) { |
| + rtnl_unlock(); |
| + return; |
| + } |
| + |
| igb_dump(adapter); |
| netdev_err(adapter->netdev, "Reset adapter\n"); |
| igb_reinit_locked(adapter); |
| + rtnl_unlock(); |
| } |
| |
| /** |
| -- |
| 2.27.0 |
| |