diff options
author | Avinash Dayanand <avinash.dayanand@intel.com> | 2017-12-18 05:16:43 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2018-01-23 14:29:19 -0500 |
commit | 06aa040f039404a0039a5158cd12f41187487a1f (patch) | |
tree | a33d8669e8178bd89f74e659fbac996762cfdb2d | |
parent | a558566befaae03f64fd0e4271e6e4d17514644c (diff) |
i40evf: Don't schedule reset_task when device is being removed
When a host disables and enables a PF device, all the associated
VFs are removed and added back in. It also generates a PFR which in turn
resets all the connected VFs. This behaviour is different from that of
Linux guest on Linux host. Hence we end up in a situation where there's
a PFR and device removal at the same time. And watchdog doesn't have a
clue about this and schedules a reset_task. This patch adds code to send
signal to reset_task that the device is currently being removed.
Signed-off-by: Avinash Dayanand <avinash.dayanand@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 |
2 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 47040ab2e298..33c0ffcc8b13 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h | |||
@@ -187,6 +187,7 @@ enum i40evf_state_t { | |||
187 | enum i40evf_critical_section_t { | 187 | enum i40evf_critical_section_t { |
188 | __I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */ | 188 | __I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */ |
189 | __I40EVF_IN_CLIENT_TASK, | 189 | __I40EVF_IN_CLIENT_TASK, |
190 | __I40EVF_IN_REMOVE_TASK, /* device being removed */ | ||
190 | }; | 191 | }; |
191 | 192 | ||
192 | /* board specific private data structure */ | 193 | /* board specific private data structure */ |
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 647211663c0c..0e5df197fc69 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c | |||
@@ -1803,6 +1803,12 @@ static void i40evf_reset_task(struct work_struct *work) | |||
1803 | int i = 0, err; | 1803 | int i = 0, err; |
1804 | bool running; | 1804 | bool running; |
1805 | 1805 | ||
1806 | /* When device is being removed it doesn't make sense to run the reset | ||
1807 | * task, just return in such a case. | ||
1808 | */ | ||
1809 | if (test_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section)) | ||
1810 | return; | ||
1811 | |||
1806 | while (test_and_set_bit(__I40EVF_IN_CLIENT_TASK, | 1812 | while (test_and_set_bit(__I40EVF_IN_CLIENT_TASK, |
1807 | &adapter->crit_section)) | 1813 | &adapter->crit_section)) |
1808 | usleep_range(500, 1000); | 1814 | usleep_range(500, 1000); |
@@ -3053,7 +3059,8 @@ static void i40evf_remove(struct pci_dev *pdev) | |||
3053 | struct i40evf_mac_filter *f, *ftmp; | 3059 | struct i40evf_mac_filter *f, *ftmp; |
3054 | struct i40e_hw *hw = &adapter->hw; | 3060 | struct i40e_hw *hw = &adapter->hw; |
3055 | int err; | 3061 | int err; |
3056 | 3062 | /* Indicate we are in remove and not to run reset_task */ | |
3063 | set_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section); | ||
3057 | cancel_delayed_work_sync(&adapter->init_task); | 3064 | cancel_delayed_work_sync(&adapter->init_task); |
3058 | cancel_work_sync(&adapter->reset_task); | 3065 | cancel_work_sync(&adapter->reset_task); |
3059 | cancel_delayed_work_sync(&adapter->client_task); | 3066 | cancel_delayed_work_sync(&adapter->client_task); |