@@ -255,6 +255,7 @@ struct iavf_adapter {
struct workqueue_struct *wq;
struct work_struct reset_task;
struct work_struct adminq_task;
+ struct delayed_work set_interrupt_capability;
struct delayed_work client_task;
wait_queue_head_t down_waitqueue;
wait_queue_head_t reset_waitqueue;
@@ -1707,9 +1707,32 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
err = iavf_acquire_msix_vectors(adapter, v_budget);
out:
+ if (rtnl_trylock()) {
+ netif_set_real_num_rx_queues(adapter->netdev, pairs);
+ netif_set_real_num_tx_queues(adapter->netdev, pairs);
+ rtnl_unlock();
+ } else {
+ schedule_delayed_work(&adapter->set_interrupt_capability,
+ msecs_to_jiffies(30));
+ }
+
+ return err;
+}
+
+/**
+ * iavf_delayed_set_interrupt_capability - schedule the update of the netdev
+ * @work: pointer to work_struct containing our data
+ **/
+static void iavf_delayed_set_interrupt_capability(struct work_struct *work)
+{
+ struct iavf_adapter *adapter = container_of(work, struct iavf_adapter,
+ set_interrupt_capability.work);
+ int pairs = adapter->num_active_queues;
+
+ rtnl_lock();
netif_set_real_num_rx_queues(adapter->netdev, pairs);
netif_set_real_num_tx_queues(adapter->netdev, pairs);
- return err;
+ rtnl_unlock();
}
/**
@@ -1930,10 +1953,8 @@ int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
"Unable to allocate memory for queues\n");
goto err_alloc_queues;
}
-
- rtnl_lock();
err = iavf_set_interrupt_capability(adapter);
- rtnl_unlock();
+
if (err) {
dev_err(&adapter->pdev->dev,
"Unable to setup interrupt capabilities\n");
@@ -4983,6 +5004,8 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->reset_task, iavf_reset_task);
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
+ INIT_DELAYED_WORK(&adapter->set_interrupt_capability,
+ iavf_delayed_set_interrupt_capability);
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
queue_delayed_work(adapter->wq, &adapter->watchdog_task,
@@ -5156,6 +5179,7 @@ static void iavf_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->reset_task);
cancel_delayed_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->adminq_task);
+ cancel_delayed_work_sync(&adapter->set_interrupt_capability);
cancel_delayed_work_sync(&adapter->client_task);
adapter->aq_required = 0;