diff options
author | Mitch Williams <mitch.a.williams@intel.com> | 2014-04-24 10:41:37 +0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2014-06-05 13:13:01 +0400 |
commit | d732a18445071fea4e062c3d66e2fc21f1bd1290 (patch) | |
tree | c8b273d1907855ccdb7e4351151acf075bf5c49f /drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | |
parent | 337eb08e5ad0c3e7929d1f1745165af412e7d6eb (diff) | |
download | linux-d732a18445071fea4e062c3d66e2fc21f1bd1290.tar.xz |
i40evf: fix crash when changing ring sizes
i40evf_set_ringparam was broken in several ways. First, it only changed
the size of the first ring, and second, changing the ring size would
often result in a panic because it would change the count before
deallocating resources, causing the driver to either free nonexistent
buffers, or leak leftover buffers.
Fix this by storing the descriptor count in the adapter structure, and
updating the count for each ring each time we allocate them. This
ensures that we always free the right size ring, and always end up with
the requested count when the device is (re)opened.
Change-ID: I298396cd3d452ba8509d9f2d33a93f25868a9a55
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 18 |
1 files changed, 7 insertions, 11 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index 9cd381a6c4be..8d41a88f1666 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -224,13 +224,11 @@ static void i40evf_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct i40evf_adapter *adapter = netdev_priv(netdev); - struct i40e_ring *tx_ring = adapter->tx_rings[0]; - struct i40e_ring *rx_ring = adapter->rx_rings[0]; ring->rx_max_pending = I40EVF_MAX_RXD; ring->tx_max_pending = I40EVF_MAX_TXD; - ring->rx_pending = rx_ring->count; - ring->tx_pending = tx_ring->count; + ring->rx_pending = adapter->rx_desc_count; + ring->tx_pending = adapter->tx_desc_count; } /** @@ -246,7 +244,6 @@ static int i40evf_set_ringparam(struct net_device *netdev, { struct i40evf_adapter *adapter = netdev_priv(netdev); u32 new_rx_count, new_tx_count; - int i; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; @@ -262,17 +259,16 @@ static int i40evf_set_ringparam(struct net_device *netdev, new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE); /* if nothing to do return success */ - if ((new_tx_count == adapter->tx_rings[0]->count) && - (new_rx_count == adapter->rx_rings[0]->count)) + if ((new_tx_count == adapter->tx_desc_count) && + (new_rx_count == adapter->rx_desc_count)) return 0; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { - adapter->tx_rings[0]->count = new_tx_count; - adapter->rx_rings[0]->count = new_rx_count; - } + adapter->tx_desc_count = new_tx_count; + adapter->rx_desc_count = new_rx_count; if (netif_running(netdev)) i40evf_reinit_locked(adapter); + return 0; } |