1 From stable-bounces@linux.kernel.org Fri Apr 3 04:35:21 2009
2 Date: Fri, 3 Apr 2009 04:35:17 GMT
3 Message-Id: <200904030435.n334ZHY4010519@hera.kernel.org>
4 From: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
5 To: jejb@kernel.org, stable@kernel.org
6 Subject: ixgbe: Fix potential memory leak/driver panic issue while setting up Tx & Rx ring parameters
8 upstream commit: f9ed88549e2ec73922b788e3865282d221233662
10 While setting up the ring parameters using ethtool the driver can
11 panic or leak memory as ixgbe_open tries to setup tx & rx resources.
12 The updated logic will use ixgbe_down/up after successful allocation of
15 Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
16 Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
17 Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
19 Signed-off-by: David S. Miller <davem@davemloft.net>
20 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
22 drivers/net/ixgbe/ixgbe_ethtool.c | 103 +++++++++++++++++++++-----------------
23 1 file changed, 59 insertions(+), 44 deletions(-)
25 --- a/drivers/net/ixgbe/ixgbe_ethtool.c
26 +++ b/drivers/net/ixgbe/ixgbe_ethtool.c
27 @@ -691,9 +691,10 @@ static int ixgbe_set_ringparam(struct ne
28 struct ethtool_ringparam *ring)
30 struct ixgbe_adapter *adapter = netdev_priv(netdev);
31 - struct ixgbe_ring *temp_ring;
32 + struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
34 u32 new_rx_count, new_tx_count;
35 + bool need_update = false;
37 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
39 @@ -712,80 +713,94 @@ static int ixgbe_set_ringparam(struct ne
43 - temp_ring = kcalloc(adapter->num_tx_queues,
44 - sizeof(struct ixgbe_ring), GFP_KERNEL);
48 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
51 - if (new_tx_count != adapter->tx_ring->count) {
52 + temp_tx_ring = kcalloc(adapter->num_tx_queues,
53 + sizeof(struct ixgbe_ring), GFP_KERNEL);
54 + if (!temp_tx_ring) {
59 + if (new_tx_count != adapter->tx_ring_count) {
60 + memcpy(temp_tx_ring, adapter->tx_ring,
61 + adapter->num_tx_queues * sizeof(struct ixgbe_ring));
62 for (i = 0; i < adapter->num_tx_queues; i++) {
63 - temp_ring[i].count = new_tx_count;
64 - err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]);
65 + temp_tx_ring[i].count = new_tx_count;
66 + err = ixgbe_setup_tx_resources(adapter,
71 ixgbe_free_tx_resources(adapter,
77 - temp_ring[i].v_idx = adapter->tx_ring[i].v_idx;
78 + temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
80 - if (netif_running(netdev))
81 - netdev->netdev_ops->ndo_stop(netdev);
82 - ixgbe_reset_interrupt_capability(adapter);
83 - ixgbe_napi_del_all(adapter);
84 - INIT_LIST_HEAD(&netdev->napi_list);
85 - kfree(adapter->tx_ring);
86 - adapter->tx_ring = temp_ring;
88 - adapter->tx_ring_count = new_tx_count;
91 - temp_ring = kcalloc(adapter->num_rx_queues,
92 - sizeof(struct ixgbe_ring), GFP_KERNEL);
94 - if (netif_running(netdev))
95 - netdev->netdev_ops->ndo_open(netdev);
100 - if (new_rx_count != adapter->rx_ring->count) {
101 + temp_rx_ring = kcalloc(adapter->num_rx_queues,
102 + sizeof(struct ixgbe_ring), GFP_KERNEL);
103 + if ((!temp_rx_ring) && (need_update)) {
104 + for (i = 0; i < adapter->num_tx_queues; i++)
105 + ixgbe_free_tx_resources(adapter, &temp_tx_ring[i]);
106 + kfree(temp_tx_ring);
111 + if (new_rx_count != adapter->rx_ring_count) {
112 + memcpy(temp_rx_ring, adapter->rx_ring,
113 + adapter->num_rx_queues * sizeof(struct ixgbe_ring));
114 for (i = 0; i < adapter->num_rx_queues; i++) {
115 - temp_ring[i].count = new_rx_count;
116 - err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);
117 + temp_rx_ring[i].count = new_rx_count;
118 + err = ixgbe_setup_rx_resources(adapter,
123 ixgbe_free_rx_resources(adapter,
129 - temp_ring[i].v_idx = adapter->rx_ring[i].v_idx;
130 + temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
132 + need_update = true;
135 + /* if rings need to be updated, here's the place to do it in one shot */
137 if (netif_running(netdev))
138 - netdev->netdev_ops->ndo_stop(netdev);
139 - ixgbe_reset_interrupt_capability(adapter);
140 - ixgbe_napi_del_all(adapter);
141 - INIT_LIST_HEAD(&netdev->napi_list);
142 - kfree(adapter->rx_ring);
143 - adapter->rx_ring = temp_ring;
145 + ixgbe_down(adapter);
148 + if (new_tx_count != adapter->tx_ring_count) {
149 + kfree(adapter->tx_ring);
150 + adapter->tx_ring = temp_tx_ring;
151 + temp_tx_ring = NULL;
152 + adapter->tx_ring_count = new_tx_count;
155 - adapter->rx_ring_count = new_rx_count;
157 + if (new_rx_count != adapter->rx_ring_count) {
158 + kfree(adapter->rx_ring);
159 + adapter->rx_ring = temp_rx_ring;
160 + temp_rx_ring = NULL;
161 + adapter->rx_ring_count = new_rx_count;
168 - ixgbe_init_interrupt_scheme(adapter);
169 if (netif_running(netdev))
170 - netdev->netdev_ops->ndo_open(netdev);
174 clear_bit(__IXGBE_RESETTING, &adapter->state);