aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvinash Dayanand <avinash.dayanand@intel.com>2017-12-18 05:16:43 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-01-23 14:29:19 -0500
commit06aa040f039404a0039a5158cd12f41187487a1f (patch)
treea33d8669e8178bd89f74e659fbac996762cfdb2d
parenta558566befaae03f64fd0e4271e6e4d17514644c (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.h1
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c9
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 {
187enum i40evf_critical_section_t { 187enum 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);