diff options
| author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-10-26 07:32:25 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-10-26 19:09:01 -0400 |
| commit | 39305965f31e080d6ed96e0ff51ed11e7639d52e (patch) | |
| tree | e01872ac6287905362f611324ae78cc245499cba | |
| parent | 759884b4d4cbafcd3f222b29cd6e0c2cbc542d2b (diff) | |
igbvf: fix memory leak when ring size changed while interface down
This patch resolves a memory leak which occurs while changing the ring size
while the interface is down.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/igbvf/ethtool.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index ee17a097d1ca..c68265bd0d1a 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c | |||
| @@ -279,7 +279,7 @@ static int igbvf_set_ringparam(struct net_device *netdev, | |||
| 279 | { | 279 | { |
| 280 | struct igbvf_adapter *adapter = netdev_priv(netdev); | 280 | struct igbvf_adapter *adapter = netdev_priv(netdev); |
| 281 | struct igbvf_ring *temp_ring; | 281 | struct igbvf_ring *temp_ring; |
| 282 | int err; | 282 | int err = 0; |
| 283 | u32 new_rx_count, new_tx_count; | 283 | u32 new_rx_count, new_tx_count; |
| 284 | 284 | ||
| 285 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) | 285 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
| @@ -299,15 +299,22 @@ static int igbvf_set_ringparam(struct net_device *netdev, | |||
| 299 | return 0; | 299 | return 0; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | temp_ring = vmalloc(sizeof(struct igbvf_ring)); | ||
| 303 | if (!temp_ring) | ||
| 304 | return -ENOMEM; | ||
| 305 | |||
| 306 | while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state)) | 302 | while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state)) |
| 307 | msleep(1); | 303 | msleep(1); |
| 308 | 304 | ||
| 309 | if (netif_running(adapter->netdev)) | 305 | if (!netif_running(adapter->netdev)) { |
| 310 | igbvf_down(adapter); | 306 | adapter->tx_ring->count = new_tx_count; |
| 307 | adapter->rx_ring->count = new_rx_count; | ||
| 308 | goto clear_reset; | ||
| 309 | } | ||
| 310 | |||
| 311 | temp_ring = vmalloc(sizeof(struct igbvf_ring)); | ||
| 312 | if (!temp_ring) { | ||
| 313 | err = -ENOMEM; | ||
| 314 | goto clear_reset; | ||
| 315 | } | ||
| 316 | |||
| 317 | igbvf_down(adapter); | ||
| 311 | 318 | ||
| 312 | /* | 319 | /* |
| 313 | * We can't just free everything and then setup again, | 320 | * We can't just free everything and then setup again, |
| @@ -339,14 +346,11 @@ static int igbvf_set_ringparam(struct net_device *netdev, | |||
| 339 | 346 | ||
| 340 | memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring)); | 347 | memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring)); |
| 341 | } | 348 | } |
| 342 | |||
| 343 | err = 0; | ||
| 344 | err_setup: | 349 | err_setup: |
| 345 | if (netif_running(adapter->netdev)) | 350 | igbvf_up(adapter); |
| 346 | igbvf_up(adapter); | ||
| 347 | |||
| 348 | clear_bit(__IGBVF_RESETTING, &adapter->state); | ||
| 349 | vfree(temp_ring); | 351 | vfree(temp_ring); |
| 352 | clear_reset: | ||
| 353 | clear_bit(__IGBVF_RESETTING, &adapter->state); | ||
| 350 | return err; | 354 | return err; |
| 351 | } | 355 | } |
| 352 | 356 | ||
