提交 02ef6e1d 编写于 作者: C Carolyn Wyborny 提交者: Jeff Kirsher

igb: Fix queue allocation method to accommodate changing during runtime

When changing number of queues using ethtool's set_channels during runtime,
a queue allocation could fail, which can leave the device in a down state.
In order to preserve the usability of the device in this scenario, this patch
changes the driver to allocate the  number of queues only if they have not
been allocated already. The first allocation is then done for the max number
of queues, which is the default queues for this driver.   With this change,
queue quantity changes are not subject to queue allocation failures.
Signed-off-by: NCarolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: NAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: NJeff Kirsher <jeffrey.t.kirsher@intel.com>
上级 22dd81c5
......@@ -983,43 +983,61 @@ static int igb_request_msix(struct igb_adapter *adapter)
return err;
}
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
{
if (adapter->msix_entries) {
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
} else if (adapter->flags & IGB_FLAG_HAS_MSI) {
pci_disable_msi(adapter->pdev);
}
}
/**
* igb_free_q_vector - Free memory allocated for specific interrupt vector
* @adapter: board private structure to initialize
* @v_idx: Index of vector to be freed
*
* This function frees the memory allocated to the q_vector. In addition if
* NAPI is enabled it will delete any references to the NAPI struct prior
* to freeing the q_vector.
* This function frees the memory allocated to the q_vector.
**/
static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
{
struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
adapter->q_vector[v_idx] = NULL;
/* igb_get_stats64() might access the rings on this vector,
* we must wait a grace period before freeing it.
*/
kfree_rcu(q_vector, rcu);
}
/**
* igb_reset_q_vector - Reset config for interrupt vector
* @adapter: board private structure to initialize
* @v_idx: Index of vector to be reset
*
* If NAPI is enabled it will delete any references to the
* NAPI struct. This is preparation for igb_free_q_vector.
**/
static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
{
struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
if (q_vector->tx.ring)
adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
if (q_vector->rx.ring)
adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
adapter->q_vector[v_idx] = NULL;
netif_napi_del(&q_vector->napi);
/* igb_get_stats64() might access the rings on this vector,
* we must wait a grace period before freeing it.
*/
kfree_rcu(q_vector, rcu);
}
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
{
int v_idx = adapter->num_q_vectors;
if (adapter->msix_entries) {
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
} else if (adapter->flags & IGB_FLAG_HAS_MSI) {
pci_disable_msi(adapter->pdev);
}
while (v_idx--)
igb_reset_q_vector(adapter, v_idx);
}
/**
......@@ -1038,8 +1056,10 @@ static void igb_free_q_vectors(struct igb_adapter *adapter)
adapter->num_rx_queues = 0;
adapter->num_q_vectors = 0;
while (v_idx--)
while (v_idx--) {
igb_reset_q_vector(adapter, v_idx);
igb_free_q_vector(adapter, v_idx);
}
}
/**
......@@ -1172,7 +1192,9 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
(sizeof(struct igb_ring) * ring_count);
/* allocate q_vector and rings */
q_vector = kzalloc(size, GFP_KERNEL);
q_vector = adapter->q_vector[v_idx];
if (!q_vector)
q_vector = kzalloc(size, GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
......@@ -8037,7 +8059,7 @@ int igb_reinit_queues(struct igb_adapter *adapter)
if (netif_running(netdev))
igb_close(netdev);
igb_clear_interrupt_scheme(adapter);
igb_reset_interrupt_capability(adapter);
if (igb_init_interrupt_scheme(adapter, true)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册