summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/iavf/iavf_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/iavf/iavf_main.c')
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c90
1 files changed, 34 insertions, 56 deletions
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 86c1964f42e1..dad001abc908 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -186,31 +186,6 @@ static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
}
/**
- * iavf_wait_for_reset - Wait for reset to finish.
- * @adapter: board private structure
- *
- * Returns 0 if reset finished successfully, negative on timeout or interrupt.
- */
-int iavf_wait_for_reset(struct iavf_adapter *adapter)
-{
- int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
- !iavf_is_reset_in_progress(adapter),
- msecs_to_jiffies(5000));
-
- /* If ret < 0 then it means wait was interrupted.
- * If ret == 0 then it means we got a timeout while waiting
- * for reset to finish.
- * If ret > 0 it means reset has finished.
- */
- if (ret > 0)
- return 0;
- else if (ret < 0)
- return -EINTR;
- else
- return -EBUSY;
-}
-
-/**
* iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to fill out
@@ -782,10 +757,13 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
adapter->num_vlan_filters++;
iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER);
} else if (f->state == IAVF_VLAN_REMOVE) {
- /* IAVF_VLAN_REMOVE means that VLAN wasn't yet removed.
- * We can safely only change the state here.
+ /* Re-add the filter since we cannot tell whether the
+ * pending delete has already been processed by the PF.
+ * A duplicate add is harmless.
*/
- f->state = IAVF_VLAN_ACTIVE;
+ f->state = IAVF_VLAN_ADD;
+ iavf_schedule_aq_request(adapter,
+ IAVF_FLAG_AQ_ADD_VLAN_FILTER);
}
clearout:
@@ -3036,6 +3014,8 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED;
+ iavf_ptp_release(adapter);
+
/* We don't use netif_running() because it may be true prior to
* ndo_open() returning, so we can't assume it means all our open
* tasks have finished, since we're not holding the rtnl_lock here.
@@ -3111,18 +3091,16 @@ static void iavf_reconfig_qs_bw(struct iavf_adapter *adapter)
}
/**
- * iavf_reset_task - Call-back task to handle hardware reset
- * @work: pointer to work_struct
+ * iavf_reset_step - Perform the VF reset sequence
+ * @adapter: board private structure
*
- * During reset we need to shut down and reinitialize the admin queue
- * before we can use it to communicate with the PF again. We also clear
- * and reinit the rings because that context is lost as well.
- **/
-static void iavf_reset_task(struct work_struct *work)
+ * Requests a reset from PF, polls for completion, and reconfigures
+ * the driver. Caller must hold the netdev instance lock.
+ *
+ * This can sleep for several seconds while polling HW registers.
+ */
+void iavf_reset_step(struct iavf_adapter *adapter)
{
- struct iavf_adapter *adapter = container_of(work,
- struct iavf_adapter,
- reset_task);
struct virtchnl_vf_resource *vfres = adapter->vf_res;
struct net_device *netdev = adapter->netdev;
struct iavf_hw *hw = &adapter->hw;
@@ -3133,7 +3111,7 @@ static void iavf_reset_task(struct work_struct *work)
int i = 0, err;
bool running;
- netdev_lock(netdev);
+ netdev_assert_locked(netdev);
iavf_misc_irq_disable(adapter);
if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
@@ -3178,7 +3156,6 @@ static void iavf_reset_task(struct work_struct *work)
dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
reg_val);
iavf_disable_vf(adapter);
- netdev_unlock(netdev);
return; /* Do not attempt to reinit. It's dead, Jim. */
}
@@ -3190,7 +3167,6 @@ continue_reset:
iavf_startup(adapter);
queue_delayed_work(adapter->wq, &adapter->watchdog_task,
msecs_to_jiffies(30));
- netdev_unlock(netdev);
return;
}
@@ -3211,6 +3187,8 @@ continue_reset:
iavf_change_state(adapter, __IAVF_RESETTING);
adapter->flags &= ~IAVF_FLAG_RESET_PENDING;
+ iavf_ptp_release(adapter);
+
/* free the Tx/Rx rings and descriptors, might be better to just
* re-use them sometime in the future
*/
@@ -3331,9 +3309,6 @@ continue_reset:
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
- wake_up(&adapter->reset_waitqueue);
- netdev_unlock(netdev);
-
return;
reset_err:
if (running) {
@@ -3342,10 +3317,21 @@ reset_err:
}
iavf_disable_vf(adapter);
- netdev_unlock(netdev);
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
}
+static void iavf_reset_task(struct work_struct *work)
+{
+ struct iavf_adapter *adapter = container_of(work,
+ struct iavf_adapter,
+ reset_task);
+ struct net_device *netdev = adapter->netdev;
+
+ netdev_lock(netdev);
+ iavf_reset_step(adapter);
+ netdev_unlock(netdev);
+}
+
/**
* iavf_adminq_task - worker thread to clean the admin queue
* @work: pointer to work_struct containing our data
@@ -4611,22 +4597,17 @@ static int iavf_close(struct net_device *netdev)
static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
- int ret = 0;
netdev_dbg(netdev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
WRITE_ONCE(netdev->mtu, new_mtu);
if (netif_running(netdev)) {
- iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
- ret = iavf_wait_for_reset(adapter);
- if (ret < 0)
- netdev_warn(netdev, "MTU change interrupted waiting for reset");
- else if (ret)
- netdev_warn(netdev, "MTU change timed out waiting for reset");
+ adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+ iavf_reset_step(adapter);
}
- return ret;
+ return 0;
}
/**
@@ -5431,9 +5412,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Setup the wait queue for indicating transition to down status */
init_waitqueue_head(&adapter->down_waitqueue);
- /* Setup the wait queue for indicating transition to running state */
- init_waitqueue_head(&adapter->reset_waitqueue);
-
/* Setup the wait queue for indicating virtchannel events */
init_waitqueue_head(&adapter->vc_waitqueue);