]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/igp-fix-ring-on-suspend.patch
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / igp-fix-ring-on-suspend.patch
1 Subject: Fix tx/rx_ring_count parameters for igb on suspend/resume/ring resize
2 Patch-mainline: 2.6.29-rc3
3 References: bnc#465049
4 From: Alexander Duyck <alexander.h.duyck@intel.com>
5
6 When suspending the device the ring structure is freed which causes it to
7 loose track of the count. To resolve this we need to move the ring count
8 outside of the ring structure and store it in the adapter struct.
9
10 In addition to resolving the suspend/resume issue this patch also addresses
11 issues seen in the event of memory allocation errors causing uneven ring
12 sizes on multiple queues.
13
14 Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
15 Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
16 Signed-off-by: David S. Miller <davem@davemloft.net>
17 Signed-off-by: Pavel Machek <pavel@suse.cz>
18
19
20
21 ---
22 drivers/net/igb/igb.h | 4 +
23 drivers/net/igb/igb_ethtool.c | 102 ++++++++++++++++++++----------------------
24 drivers/net/igb/igb_main.c | 10 ++--
25 3 files changed, 59 insertions(+), 57 deletions(-)
26
27 --- a/drivers/net/igb/igb_ethtool.c
28 +++ b/drivers/net/igb/igb_ethtool.c
29 @@ -714,15 +714,13 @@ static void igb_get_ringparam(struct net
30 struct ethtool_ringparam *ring)
31 {
32 struct igb_adapter *adapter = netdev_priv(netdev);
33 - struct igb_ring *tx_ring = adapter->tx_ring;
34 - struct igb_ring *rx_ring = adapter->rx_ring;
35
36 ring->rx_max_pending = IGB_MAX_RXD;
37 ring->tx_max_pending = IGB_MAX_TXD;
38 ring->rx_mini_max_pending = 0;
39 ring->rx_jumbo_max_pending = 0;
40 - ring->rx_pending = rx_ring->count;
41 - ring->tx_pending = tx_ring->count;
42 + ring->rx_pending = adapter->rx_ring_count;
43 + ring->tx_pending = adapter->tx_ring_count;
44 ring->rx_mini_pending = 0;
45 ring->rx_jumbo_pending = 0;
46 }
47 @@ -731,12 +729,9 @@ static int igb_set_ringparam(struct net_
48 struct ethtool_ringparam *ring)
49 {
50 struct igb_adapter *adapter = netdev_priv(netdev);
51 - struct igb_buffer *old_buf;
52 - struct igb_buffer *old_rx_buf;
53 - void *old_desc;
54 + struct igb_ring *temp_ring;
55 int i, err;
56 - u32 new_rx_count, new_tx_count, old_size;
57 - dma_addr_t old_dma;
58 + u32 new_rx_count, new_tx_count;
59
60 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
61 return -EINVAL;
62 @@ -749,12 +744,19 @@ static int igb_set_ringparam(struct net_
63 new_tx_count = min(new_tx_count, (u32)IGB_MAX_TXD);
64 new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
65
66 - if ((new_tx_count == adapter->tx_ring->count) &&
67 - (new_rx_count == adapter->rx_ring->count)) {
68 + if ((new_tx_count == adapter->tx_ring_count) &&
69 + (new_rx_count == adapter->rx_ring_count)) {
70 /* nothing to do */
71 return 0;
72 }
73
74 + if (adapter->num_tx_queues > adapter->num_rx_queues)
75 + temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
76 + else
77 + temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
78 + if (!temp_ring)
79 + return -ENOMEM;
80 +
81 while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
82 msleep(1);
83
84 @@ -766,62 +768,55 @@ static int igb_set_ringparam(struct net_
85 * because the ISRs in MSI-X mode get passed pointers
86 * to the tx and rx ring structs.
87 */
88 - if (new_tx_count != adapter->tx_ring->count) {
89 + if (new_tx_count != adapter->tx_ring_count) {
90 + memcpy(temp_ring, adapter->tx_ring,
91 + adapter->num_tx_queues * sizeof(struct igb_ring));
92 +
93 for (i = 0; i < adapter->num_tx_queues; i++) {
94 - /* Save existing descriptor ring */
95 - old_buf = adapter->tx_ring[i].buffer_info;
96 - old_desc = adapter->tx_ring[i].desc;
97 - old_size = adapter->tx_ring[i].size;
98 - old_dma = adapter->tx_ring[i].dma;
99 - /* Try to allocate a new one */
100 - adapter->tx_ring[i].buffer_info = NULL;
101 - adapter->tx_ring[i].desc = NULL;
102 - adapter->tx_ring[i].count = new_tx_count;
103 - err = igb_setup_tx_resources(adapter,
104 - &adapter->tx_ring[i]);
105 + temp_ring[i].count = new_tx_count;
106 + err = igb_setup_tx_resources(adapter, &temp_ring[i]);
107 if (err) {
108 - /* Restore the old one so at least
109 - the adapter still works, even if
110 - we failed the request */
111 - adapter->tx_ring[i].buffer_info = old_buf;
112 - adapter->tx_ring[i].desc = old_desc;
113 - adapter->tx_ring[i].size = old_size;
114 - adapter->tx_ring[i].dma = old_dma;
115 + while (i) {
116 + i--;
117 + igb_free_tx_resources(&temp_ring[i]);
118 + }
119 goto err_setup;
120 }
121 - /* Free the old buffer manually */
122 - vfree(old_buf);
123 - pci_free_consistent(adapter->pdev, old_size,
124 - old_desc, old_dma);
125 }
126 +
127 + for (i = 0; i < adapter->num_tx_queues; i++)
128 + igb_free_tx_resources(&adapter->tx_ring[i]);
129 +
130 + memcpy(adapter->tx_ring, temp_ring,
131 + adapter->num_tx_queues * sizeof(struct igb_ring));
132 +
133 + adapter->tx_ring_count = new_tx_count;
134 }
135
136 if (new_rx_count != adapter->rx_ring->count) {
137 - for (i = 0; i < adapter->num_rx_queues; i++) {
138 + memcpy(temp_ring, adapter->rx_ring,
139 + adapter->num_rx_queues * sizeof(struct igb_ring));
140
141 - old_rx_buf = adapter->rx_ring[i].buffer_info;
142 - old_desc = adapter->rx_ring[i].desc;
143 - old_size = adapter->rx_ring[i].size;
144 - old_dma = adapter->rx_ring[i].dma;
145 -
146 - adapter->rx_ring[i].buffer_info = NULL;
147 - adapter->rx_ring[i].desc = NULL;
148 - adapter->rx_ring[i].dma = 0;
149 - adapter->rx_ring[i].count = new_rx_count;
150 - err = igb_setup_rx_resources(adapter,
151 - &adapter->rx_ring[i]);
152 + for (i = 0; i < adapter->num_rx_queues; i++) {
153 + temp_ring[i].count = new_rx_count;
154 + err = igb_setup_rx_resources(adapter, &temp_ring[i]);
155 if (err) {
156 - adapter->rx_ring[i].buffer_info = old_rx_buf;
157 - adapter->rx_ring[i].desc = old_desc;
158 - adapter->rx_ring[i].size = old_size;
159 - adapter->rx_ring[i].dma = old_dma;
160 + while (i) {
161 + i--;
162 + igb_free_rx_resources(&temp_ring[i]);
163 + }
164 goto err_setup;
165 }
166
167 - vfree(old_rx_buf);
168 - pci_free_consistent(adapter->pdev, old_size, old_desc,
169 - old_dma);
170 }
171 +
172 + for (i = 0; i < adapter->num_rx_queues; i++)
173 + igb_free_rx_resources(&adapter->rx_ring[i]);
174 +
175 + memcpy(adapter->rx_ring, temp_ring,
176 + adapter->num_rx_queues * sizeof(struct igb_ring));
177 +
178 + adapter->rx_ring_count = new_rx_count;
179 }
180
181 err = 0;
182 @@ -830,6 +825,7 @@ err_setup:
183 igb_up(adapter);
184
185 clear_bit(__IGB_RESETTING, &adapter->state);
186 + vfree(temp_ring);
187 return err;
188 }
189
190 --- a/drivers/net/igb/igb.h
191 +++ b/drivers/net/igb/igb.h
192 @@ -294,6 +294,8 @@ struct igb_adapter {
193 unsigned int lro_flushed;
194 unsigned int lro_no_desc;
195 #endif
196 + unsigned int tx_ring_count;
197 + unsigned int rx_ring_count;
198 };
199
200 #define IGB_FLAG_HAS_MSI (1 << 0)
201 @@ -325,6 +327,8 @@ extern void igb_reset(struct igb_adapter
202 extern int igb_set_spd_dplx(struct igb_adapter *, u16);
203 extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *);
204 extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *);
205 +extern void igb_free_tx_resources(struct igb_ring *);
206 +extern void igb_free_rx_resources(struct igb_ring *);
207 extern void igb_update_stats(struct igb_adapter *);
208 extern void igb_set_ethtool_ops(struct net_device *);
209
210 --- a/drivers/net/igb/igb_main.c
211 +++ b/drivers/net/igb/igb_main.c
212 @@ -75,8 +75,6 @@ static int igb_setup_all_tx_resources(st
213 static int igb_setup_all_rx_resources(struct igb_adapter *);
214 static void igb_free_all_tx_resources(struct igb_adapter *);
215 static void igb_free_all_rx_resources(struct igb_adapter *);
216 -static void igb_free_tx_resources(struct igb_ring *);
217 -static void igb_free_rx_resources(struct igb_ring *);
218 void igb_update_stats(struct igb_adapter *);
219 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
220 static void __devexit igb_remove(struct pci_dev *pdev);
221 @@ -258,11 +256,13 @@ static int igb_alloc_queues(struct igb_a
222
223 for (i = 0; i < adapter->num_tx_queues; i++) {
224 struct igb_ring *ring = &(adapter->tx_ring[i]);
225 + ring->count = adapter->tx_ring_count;
226 ring->adapter = adapter;
227 ring->queue_index = i;
228 }
229 for (i = 0; i < adapter->num_rx_queues; i++) {
230 struct igb_ring *ring = &(adapter->rx_ring[i]);
231 + ring->count = adapter->rx_ring_count;
232 ring->adapter = adapter;
233 ring->queue_index = i;
234 ring->itr_register = E1000_ITR;
235 @@ -1374,6 +1374,8 @@ static int __devinit igb_sw_init(struct
236
237 pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);
238
239 + adapter->tx_ring_count = IGB_DEFAULT_TXD;
240 + adapter->rx_ring_count = IGB_DEFAULT_RXD;
241 adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
242 adapter->rx_ps_hdr_size = 0; /* disable packet split */
243 adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
244 @@ -1962,7 +1964,7 @@ static void igb_configure_rx(struct igb_
245 *
246 * Free all transmit software resources
247 **/
248 -static void igb_free_tx_resources(struct igb_ring *tx_ring)
249 +void igb_free_tx_resources(struct igb_ring *tx_ring)
250 {
251 struct pci_dev *pdev = tx_ring->adapter->pdev;
252
253 @@ -2062,7 +2064,7 @@ static void igb_clean_all_tx_rings(struc
254 *
255 * Free all receive software resources
256 **/
257 -static void igb_free_rx_resources(struct igb_ring *rx_ring)
258 +void igb_free_rx_resources(struct igb_ring *rx_ring)
259 {
260 struct pci_dev *pdev = rx_ring->adapter->pdev;
261