]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
e35892551ccd46e658e2df084894badee48f32f7
[thirdparty/kernel/stable-queue.git] /
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
7
8 upstream commit: f9ed88549e2ec73922b788e3865282d221233662
9
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
13 tx & rx resources
14
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>
18 CC: stable@kernel.org
19 Signed-off-by: David S. Miller <davem@davemloft.net>
20 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
21 ---
22 drivers/net/ixgbe/ixgbe_ethtool.c | 103 +++++++++++++++++++++-----------------
23 1 file changed, 59 insertions(+), 44 deletions(-)
24
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)
29 {
30 struct ixgbe_adapter *adapter = netdev_priv(netdev);
31 - struct ixgbe_ring *temp_ring;
32 + struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
33 int i, err;
34 u32 new_rx_count, new_tx_count;
35 + bool need_update = false;
36
37 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
38 return -EINVAL;
39 @@ -712,80 +713,94 @@ static int ixgbe_set_ringparam(struct ne
40 return 0;
41 }
42
43 - temp_ring = kcalloc(adapter->num_tx_queues,
44 - sizeof(struct ixgbe_ring), GFP_KERNEL);
45 - if (!temp_ring)
46 - return -ENOMEM;
47 -
48 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
49 msleep(1);
50
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) {
55 + err = -ENOMEM;
56 + goto err_setup;
57 + }
58 +
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,
67 + &temp_tx_ring[i]);
68 if (err) {
69 while (i) {
70 i--;
71 ixgbe_free_tx_resources(adapter,
72 - &temp_ring[i]);
73 + &temp_tx_ring[i]);
74 }
75 goto err_setup;
76 }
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;
79 }
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;
87 - temp_ring = NULL;
88 - adapter->tx_ring_count = new_tx_count;
89 - }
90 -
91 - temp_ring = kcalloc(adapter->num_rx_queues,
92 - sizeof(struct ixgbe_ring), GFP_KERNEL);
93 - if (!temp_ring) {
94 - if (netif_running(netdev))
95 - netdev->netdev_ops->ndo_open(netdev);
96 - return -ENOMEM;
97 + need_update = true;
98 }
99
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);
107 + err = -ENOMEM;
108 + goto err_setup;
109 + }
110 +
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,
119 + &temp_rx_ring[i]);
120 if (err) {
121 while (i) {
122 i--;
123 ixgbe_free_rx_resources(adapter,
124 - &temp_ring[i]);
125 + &temp_rx_ring[i]);
126 }
127 goto err_setup;
128 }
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;
131 }
132 + need_update = true;
133 + }
134 +
135 + /* if rings need to be updated, here's the place to do it in one shot */
136 + if (need_update) {
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;
144 - temp_ring = NULL;
145 + ixgbe_down(adapter);
146 +
147 + /* tx */
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;
153 + }
154
155 - adapter->rx_ring_count = new_rx_count;
156 + /* rx */
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;
162 + }
163 }
164
165 /* success! */
166 err = 0;
167 -err_setup:
168 - ixgbe_init_interrupt_scheme(adapter);
169 if (netif_running(netdev))
170 - netdev->netdev_ops->ndo_open(netdev);
171 + ixgbe_up(adapter);
172
173 +err_setup:
174 clear_bit(__IXGBE_RESETTING, &adapter->state);
175 return err;
176 }