aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2009-10-26 07:31:47 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-26 19:08:56 -0400
commit6d9f4fc420571ab67c962ef0d94449127218f66e (patch)
treeae459220577e6435473a7a94e0a32947b826bf5b
parentd3da68310a2cf934c2ea8a99a519d8b1ccca4c56 (diff)
igb: fix memory leak when setting ring size while interface is down
Changing ring sizes while the interface was down was causing a double allocation of the receive and transmit rings. This issue is amplified when there are multiple rings enabled. To prevent this we need to add an additional check which will just update the ring counts when the interface is not up and skip the allocation steps. 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/igb/igb_ethtool.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index d004c359244c..aab3d971af51 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -731,7 +731,7 @@ static int igb_set_ringparam(struct net_device *netdev,
731{ 731{
732 struct igb_adapter *adapter = netdev_priv(netdev); 732 struct igb_adapter *adapter = netdev_priv(netdev);
733 struct igb_ring *temp_ring; 733 struct igb_ring *temp_ring;
734 int i, err; 734 int i, err = 0;
735 u32 new_rx_count, new_tx_count; 735 u32 new_rx_count, new_tx_count;
736 736
737 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 737 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -751,18 +751,30 @@ static int igb_set_ringparam(struct net_device *netdev,
751 return 0; 751 return 0;
752 } 752 }
753 753
754 while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
755 msleep(1);
756
757 if (!netif_running(adapter->netdev)) {
758 for (i = 0; i < adapter->num_tx_queues; i++)
759 adapter->tx_ring[i].count = new_tx_count;
760 for (i = 0; i < adapter->num_rx_queues; i++)
761 adapter->rx_ring[i].count = new_rx_count;
762 adapter->tx_ring_count = new_tx_count;
763 adapter->rx_ring_count = new_rx_count;
764 goto clear_reset;
765 }
766
754 if (adapter->num_tx_queues > adapter->num_rx_queues) 767 if (adapter->num_tx_queues > adapter->num_rx_queues)
755 temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); 768 temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
756 else 769 else
757 temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); 770 temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
758 if (!temp_ring)
759 return -ENOMEM;
760 771
761 while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 772 if (!temp_ring) {
762 msleep(1); 773 err = -ENOMEM;
774 goto clear_reset;
775 }
763 776
764 if (netif_running(adapter->netdev)) 777 igb_down(adapter);
765 igb_down(adapter);
766 778
767 /* 779 /*
768 * We can't just free everything and then setup again, 780 * We can't just free everything and then setup again,
@@ -819,14 +831,11 @@ static int igb_set_ringparam(struct net_device *netdev,
819 831
820 adapter->rx_ring_count = new_rx_count; 832 adapter->rx_ring_count = new_rx_count;
821 } 833 }
822
823 err = 0;
824err_setup: 834err_setup:
825 if (netif_running(adapter->netdev)) 835 igb_up(adapter);
826 igb_up(adapter);
827
828 clear_bit(__IGB_RESETTING, &adapter->state);
829 vfree(temp_ring); 836 vfree(temp_ring);
837clear_reset:
838 clear_bit(__IGB_RESETTING, &adapter->state);
830 return err; 839 return err;
831} 840}
832 841