Skip to content

Commit 6533e55

Browse files
ksornekanguy11
authored andcommitted
i40e: Fix reset path while removing the driver
Fix the crash in kernel while dereferencing the NULL pointer, when the driver is unloaded and simultaneously the VSI rings are being stopped. The hardware requires 50msec in order to finish RX queues disable. For this purpose the driver spins in mdelay function for the operation to be completed. For example changing number of queues which requires reset would fail in the following call stack: 1) i40e_prep_for_reset 2) i40e_pf_quiesce_all_vsi 3) i40e_quiesce_vsi 4) i40e_vsi_close 5) i40e_down 6) i40e_vsi_stop_rings 7) i40e_vsi_control_rx -> disable requires the delay of 50msecs 8) continue back in i40e_down function where i40e_clean_tx_ring(vsi->tx_rings[i]) is going to crash When the driver was spinning vsi_release called i40e_vsi_free_arrays where the vsi->tx_rings resources were freed and the pointer was set to NULL. Fixes: 5b6d4a7 ("i40e: Fix crash during removing i40e driver") Signed-off-by: Slawomir Laba <[email protected]> Signed-off-by: Sylwester Dziedziuch <[email protected]> Signed-off-by: Karen Sornek <[email protected]> Tested-by: Gurucharan G <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 3d25046 commit 6533e55

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ enum i40e_state_t {
144144
__I40E_VIRTCHNL_OP_PENDING,
145145
__I40E_RECOVERY_MODE,
146146
__I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */
147+
__I40E_IN_REMOVE,
147148
__I40E_VFS_RELEASING,
148149
/* This must be last as it determines the size of the BITMAP */
149150
__I40E_STATE_SIZE__,

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10863,6 +10863,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
1086310863
bool lock_acquired)
1086410864
{
1086510865
int ret;
10866+
10867+
if (test_bit(__I40E_IN_REMOVE, pf->state))
10868+
return;
1086610869
/* Now we wait for GRST to settle out.
1086710870
* We don't have to delete the VEBs or VSIs from the hw switch
1086810871
* because the reset will make them disappear.
@@ -12222,6 +12225,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
1222212225

1222312226
vsi->req_queue_pairs = queue_count;
1222412227
i40e_prep_for_reset(pf);
12228+
if (test_bit(__I40E_IN_REMOVE, pf->state))
12229+
return pf->alloc_rss_size;
1222512230

1222612231
pf->alloc_rss_size = new_rss_size;
1222712232

@@ -13048,6 +13053,10 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
1304813053
if (need_reset)
1304913054
i40e_prep_for_reset(pf);
1305013055

13056+
/* VSI shall be deleted in a moment, just return EINVAL */
13057+
if (test_bit(__I40E_IN_REMOVE, pf->state))
13058+
return -EINVAL;
13059+
1305113060
old_prog = xchg(&vsi->xdp_prog, prog);
1305213061

1305313062
if (need_reset) {
@@ -15938,8 +15947,13 @@ static void i40e_remove(struct pci_dev *pdev)
1593815947
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
1593915948
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
1594015949

15941-
while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
15950+
/* Grab __I40E_RESET_RECOVERY_PENDING and set __I40E_IN_REMOVE
15951+
* flags, once they are set, i40e_rebuild should not be called as
15952+
* i40e_prep_for_reset always returns early.
15953+
*/
15954+
while (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
1594215955
usleep_range(1000, 2000);
15956+
set_bit(__I40E_IN_REMOVE, pf->state);
1594315957

1594415958
if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
1594515959
set_bit(__I40E_VF_RESETS_DISABLED, pf->state);
@@ -16138,6 +16152,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev)
1613816152
{
1613916153
struct i40e_pf *pf = pci_get_drvdata(pdev);
1614016154

16155+
if (test_bit(__I40E_IN_REMOVE, pf->state))
16156+
return;
16157+
1614116158
i40e_reset_and_rebuild(pf, false, false);
1614216159
}
1614316160

0 commit comments

Comments
 (0)