]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.drivers/igp-fix-ring-on-suspend.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / igp-fix-ring-on-suspend.patch
CommitLineData
00e5a55c
BS
1Subject: Fix tx/rx_ring_count parameters for igb on suspend/resume/ring resize
2Patch-mainline: 2.6.29-rc3
3References: bnc#465049
4From: Alexander Duyck <alexander.h.duyck@intel.com>
5
6When suspending the device the ring structure is freed which causes it to
7loose track of the count. To resolve this we need to move the ring count
8outside of the ring structure and store it in the adapter struct.
9
10In addition to resolving the suspend/resume issue this patch also addresses
11issues seen in the event of memory allocation errors causing uneven ring
12sizes on multiple queues.
13
14Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
15Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
16Signed-off-by: David S. Miller <davem@davemloft.net>
17Signed-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