ia64/xen-unstable

view patches/linux-2.6.16.29/net-gso-2-checksum-fix.patch @ 12273:b223ba940ed1

PV-on-HVM: Fix PV-on-HVM drivers need maddr.h included for defn of maddr_t.
Signed-off-by: Takanori Kasai <Kasai.Takanori@jp.fujitsu.com>
Signed-off-by: Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Tue Nov 07 09:29:53 2006 +0000 (2006-11-07)
parents 041be3f6b38e
children
line source
1 diff -pruN ../orig-linux-2.6.16.29/drivers/net/bnx2.c ./drivers/net/bnx2.c
2 --- ../orig-linux-2.6.16.29/drivers/net/bnx2.c 2006-09-19 13:59:20.000000000 +0100
3 +++ ./drivers/net/bnx2.c 2006-09-19 13:59:46.000000000 +0100
4 @@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
5 skb = tx_buf->skb;
6 #ifdef BCM_TSO
7 /* partial BD completions possible with TSO packets */
8 - if (skb_shinfo(skb)->gso_size) {
9 + if (skb_is_gso(skb)) {
10 u16 last_idx, last_ring_idx;
12 last_idx = sw_cons +
13 diff -pruN ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c ./drivers/net/chelsio/sge.c
14 --- ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c 2006-09-19 13:59:20.000000000 +0100
15 +++ ./drivers/net/chelsio/sge.c 2006-09-19 13:59:46.000000000 +0100
16 @@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
17 struct cpl_tx_pkt *cpl;
19 #ifdef NETIF_F_TSO
20 - if (skb_shinfo(skb)->gso_size) {
21 + if (skb_is_gso(skb)) {
22 int eth_type;
23 struct cpl_tx_pkt_lso *hdr;
25 diff -pruN ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c ./drivers/net/e1000/e1000_main.c
26 --- ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c 2006-09-19 13:59:20.000000000 +0100
27 +++ ./drivers/net/e1000/e1000_main.c 2006-09-19 13:59:46.000000000 +0100
28 @@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
29 uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
30 int err;
32 - if (skb_shinfo(skb)->gso_size) {
33 + if (skb_is_gso(skb)) {
34 if (skb_header_cloned(skb)) {
35 err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
36 if (err)
37 @@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
38 * tso gets written back prematurely before the data is fully
39 * DMAd to the controller */
40 if (!skb->data_len && tx_ring->last_tx_tso &&
41 - !skb_shinfo(skb)->gso_size) {
42 + !skb_is_gso(skb)) {
43 tx_ring->last_tx_tso = 0;
44 size -= 4;
45 }
46 @@ -2934,8 +2934,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
48 #ifdef NETIF_F_TSO
49 /* Controller Erratum workaround */
50 - if (!skb->data_len && tx_ring->last_tx_tso &&
51 - !skb_shinfo(skb)->gso_size)
52 + if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
53 count++;
54 #endif
56 diff -pruN ../orig-linux-2.6.16.29/drivers/net/forcedeth.c ./drivers/net/forcedeth.c
57 --- ../orig-linux-2.6.16.29/drivers/net/forcedeth.c 2006-09-19 13:59:20.000000000 +0100
58 +++ ./drivers/net/forcedeth.c 2006-09-19 13:59:46.000000000 +0100
59 @@ -1105,7 +1105,7 @@ static int nv_start_xmit(struct sk_buff
60 np->tx_skbuff[nr] = skb;
62 #ifdef NETIF_F_TSO
63 - if (skb_shinfo(skb)->gso_size)
64 + if (skb_is_gso(skb))
65 tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
66 else
67 #endif
68 diff -pruN ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c ./drivers/net/ixgb/ixgb_main.c
69 --- ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c 2006-09-19 13:59:20.000000000 +0100
70 +++ ./drivers/net/ixgb/ixgb_main.c 2006-09-19 13:59:46.000000000 +0100
71 @@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
72 uint16_t ipcse, tucse, mss;
73 int err;
75 - if(likely(skb_shinfo(skb)->gso_size)) {
76 + if (likely(skb_is_gso(skb))) {
77 if (skb_header_cloned(skb)) {
78 err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
79 if (err)
80 diff -pruN ../orig-linux-2.6.16.29/drivers/net/loopback.c ./drivers/net/loopback.c
81 --- ../orig-linux-2.6.16.29/drivers/net/loopback.c 2006-09-19 13:59:20.000000000 +0100
82 +++ ./drivers/net/loopback.c 2006-09-19 13:59:46.000000000 +0100
83 @@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff
84 #endif
86 #ifdef LOOPBACK_TSO
87 - if (skb_shinfo(skb)->gso_size) {
88 + if (skb_is_gso(skb)) {
89 BUG_ON(skb->protocol != htons(ETH_P_IP));
90 BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
92 diff -pruN ../orig-linux-2.6.16.29/drivers/net/sky2.c ./drivers/net/sky2.c
93 --- ../orig-linux-2.6.16.29/drivers/net/sky2.c 2006-09-19 13:59:20.000000000 +0100
94 +++ ./drivers/net/sky2.c 2006-09-19 13:59:46.000000000 +0100
95 @@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
96 count = sizeof(dma_addr_t) / sizeof(u32);
97 count += skb_shinfo(skb)->nr_frags * count;
99 - if (skb_shinfo(skb)->gso_size)
100 + if (skb_is_gso(skb))
101 ++count;
103 if (skb->ip_summed == CHECKSUM_HW)
104 diff -pruN ../orig-linux-2.6.16.29/drivers/net/typhoon.c ./drivers/net/typhoon.c
105 --- ../orig-linux-2.6.16.29/drivers/net/typhoon.c 2006-09-19 13:59:20.000000000 +0100
106 +++ ./drivers/net/typhoon.c 2006-09-19 13:59:46.000000000 +0100
107 @@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
108 * If problems develop with TSO, check this first.
109 */
110 numDesc = skb_shinfo(skb)->nr_frags + 1;
111 - if(skb_tso_size(skb))
112 + if (skb_is_gso(skb))
113 numDesc++;
115 /* When checking for free space in the ring, we need to also
116 @@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
117 TYPHOON_TX_PF_VLAN_TAG_SHIFT);
118 }
120 - if(skb_tso_size(skb)) {
121 + if (skb_is_gso(skb)) {
122 first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
123 first_txd->numDesc++;
125 diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c ./drivers/s390/net/qeth_main.c
126 --- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c 2006-09-19 13:59:20.000000000 +0100
127 +++ ./drivers/s390/net/qeth_main.c 2006-09-19 13:59:46.000000000 +0100
128 @@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
129 queue = card->qdio.out_qs
130 [qeth_get_priority_queue(card, skb, ipv, cast_type)];
132 - if (skb_shinfo(skb)->gso_size)
133 + if (skb_is_gso(skb))
134 large_send = card->options.large_send;
136 /*are we able to do TSO ? If so ,prepare and send it from here */
137 @@ -4501,8 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
138 card->stats.tx_packets++;
139 card->stats.tx_bytes += skb->len;
140 #ifdef CONFIG_QETH_PERF_STATS
141 - if (skb_shinfo(skb)->gso_size &&
142 - !(large_send == QETH_LARGE_SEND_NO)) {
143 + if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) {
144 card->perf_stats.large_send_bytes += skb->len;
145 card->perf_stats.large_send_cnt++;
146 }
147 diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h ./include/linux/netdevice.h
148 --- ../orig-linux-2.6.16.29/include/linux/netdevice.h 2006-09-19 13:59:20.000000000 +0100
149 +++ ./include/linux/netdevice.h 2006-09-19 13:59:46.000000000 +0100
150 @@ -541,6 +541,7 @@ struct packet_type {
151 struct net_device *);
152 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
153 int features);
154 + int (*gso_send_check)(struct sk_buff *skb);
155 void *af_packet_priv;
156 struct list_head list;
157 };
158 @@ -1001,14 +1002,15 @@ extern void linkwatch_run_queue(void);
160 static inline int skb_gso_ok(struct sk_buff *skb, int features)
161 {
162 - int feature = skb_shinfo(skb)->gso_size ?
163 - skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
164 + int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
165 return (features & feature) == feature;
166 }
168 static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
169 {
170 - return !skb_gso_ok(skb, dev->features);
171 + return skb_is_gso(skb) &&
172 + (!skb_gso_ok(skb, dev->features) ||
173 + unlikely(skb->ip_summed != CHECKSUM_HW));
174 }
176 #endif /* __KERNEL__ */
177 diff -pruN ../orig-linux-2.6.16.29/include/linux/skbuff.h ./include/linux/skbuff.h
178 --- ../orig-linux-2.6.16.29/include/linux/skbuff.h 2006-09-19 13:59:20.000000000 +0100
179 +++ ./include/linux/skbuff.h 2006-09-19 13:59:46.000000000 +0100
180 @@ -1403,5 +1403,10 @@ static inline void nf_bridge_get(struct
181 static inline void nf_reset(struct sk_buff *skb) {}
182 #endif /* CONFIG_NETFILTER */
184 +static inline int skb_is_gso(const struct sk_buff *skb)
185 +{
186 + return skb_shinfo(skb)->gso_size;
187 +}
188 +
189 #endif /* __KERNEL__ */
190 #endif /* _LINUX_SKBUFF_H */
191 diff -pruN ../orig-linux-2.6.16.29/include/net/protocol.h ./include/net/protocol.h
192 --- ../orig-linux-2.6.16.29/include/net/protocol.h 2006-09-19 13:59:20.000000000 +0100
193 +++ ./include/net/protocol.h 2006-09-19 13:59:46.000000000 +0100
194 @@ -37,6 +37,7 @@
195 struct net_protocol {
196 int (*handler)(struct sk_buff *skb);
197 void (*err_handler)(struct sk_buff *skb, u32 info);
198 + int (*gso_send_check)(struct sk_buff *skb);
199 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
200 int features);
201 int no_policy;
202 diff -pruN ../orig-linux-2.6.16.29/include/net/tcp.h ./include/net/tcp.h
203 --- ../orig-linux-2.6.16.29/include/net/tcp.h 2006-09-19 13:59:20.000000000 +0100
204 +++ ./include/net/tcp.h 2006-09-19 13:59:46.000000000 +0100
205 @@ -1063,6 +1063,7 @@ extern struct request_sock_ops tcp_reque
207 extern int tcp_v4_destroy_sock(struct sock *sk);
209 +extern int tcp_v4_gso_send_check(struct sk_buff *skb);
210 extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
212 #ifdef CONFIG_PROC_FS
213 diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_forward.c ./net/bridge/br_forward.c
214 --- ../orig-linux-2.6.16.29/net/bridge/br_forward.c 2006-09-19 13:59:20.000000000 +0100
215 +++ ./net/bridge/br_forward.c 2006-09-19 13:59:46.000000000 +0100
216 @@ -32,7 +32,7 @@ static inline int should_deliver(const s
217 int br_dev_queue_push_xmit(struct sk_buff *skb)
218 {
219 /* drop mtu oversized packets except tso */
220 - if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
221 + if (skb->len > skb->dev->mtu && !skb_is_gso(skb))
222 kfree_skb(skb);
223 else {
224 #ifdef CONFIG_BRIDGE_NETFILTER
225 diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c ./net/bridge/br_netfilter.c
226 --- ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c 2006-09-19 13:59:20.000000000 +0100
227 +++ ./net/bridge/br_netfilter.c 2006-09-19 13:59:46.000000000 +0100
228 @@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
229 {
230 if (skb->protocol == htons(ETH_P_IP) &&
231 skb->len > skb->dev->mtu &&
232 - !skb_shinfo(skb)->gso_size)
233 + !skb_is_gso(skb))
234 return ip_fragment(skb, br_dev_queue_push_xmit);
235 else
236 return br_dev_queue_push_xmit(skb);
237 diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
238 --- ../orig-linux-2.6.16.29/net/core/dev.c 2006-09-19 13:59:20.000000000 +0100
239 +++ ./net/core/dev.c 2006-09-19 13:59:46.000000000 +0100
240 @@ -1083,9 +1083,17 @@ int skb_checksum_help(struct sk_buff *sk
241 unsigned int csum;
242 int ret = 0, offset = skb->h.raw - skb->data;
244 - if (inward) {
245 - skb->ip_summed = CHECKSUM_NONE;
246 - goto out;
247 + if (inward)
248 + goto out_set_summed;
249 +
250 + if (unlikely(skb_shinfo(skb)->gso_size)) {
251 + static int warned;
252 +
253 + WARN_ON(!warned);
254 + warned = 1;
255 +
256 + /* Let GSO fix up the checksum. */
257 + goto out_set_summed;
258 }
260 if (skb_cloned(skb)) {
261 @@ -1102,6 +1110,8 @@ int skb_checksum_help(struct sk_buff *sk
262 BUG_ON(skb->csum + 2 > offset);
264 *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
265 +
266 +out_set_summed:
267 skb->ip_summed = CHECKSUM_NONE;
268 out:
269 return ret;
270 @@ -1122,17 +1132,35 @@ struct sk_buff *skb_gso_segment(struct s
271 struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
272 struct packet_type *ptype;
273 int type = skb->protocol;
274 + int err;
276 BUG_ON(skb_shinfo(skb)->frag_list);
277 - BUG_ON(skb->ip_summed != CHECKSUM_HW);
279 skb->mac.raw = skb->data;
280 skb->mac_len = skb->nh.raw - skb->data;
281 __skb_pull(skb, skb->mac_len);
283 + if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
284 + static int warned;
285 +
286 + WARN_ON(!warned);
287 + warned = 1;
288 +
289 + if (skb_header_cloned(skb) &&
290 + (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
291 + return ERR_PTR(err);
292 + }
293 +
294 rcu_read_lock();
295 list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
296 if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
297 + if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
298 + err = ptype->gso_send_check(skb);
299 + segs = ERR_PTR(err);
300 + if (err || skb_gso_ok(skb, features))
301 + break;
302 + __skb_push(skb, skb->data - skb->nh.raw);
303 + }
304 segs = ptype->gso_segment(skb, features);
305 break;
306 }
307 diff -pruN ../orig-linux-2.6.16.29/net/ipv4/af_inet.c ./net/ipv4/af_inet.c
308 --- ../orig-linux-2.6.16.29/net/ipv4/af_inet.c 2006-09-19 13:59:20.000000000 +0100
309 +++ ./net/ipv4/af_inet.c 2006-09-19 13:59:46.000000000 +0100
310 @@ -1085,6 +1085,40 @@ int inet_sk_rebuild_header(struct sock *
312 EXPORT_SYMBOL(inet_sk_rebuild_header);
314 +static int inet_gso_send_check(struct sk_buff *skb)
315 +{
316 + struct iphdr *iph;
317 + struct net_protocol *ops;
318 + int proto;
319 + int ihl;
320 + int err = -EINVAL;
321 +
322 + if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
323 + goto out;
324 +
325 + iph = skb->nh.iph;
326 + ihl = iph->ihl * 4;
327 + if (ihl < sizeof(*iph))
328 + goto out;
329 +
330 + if (unlikely(!pskb_may_pull(skb, ihl)))
331 + goto out;
332 +
333 + skb->h.raw = __skb_pull(skb, ihl);
334 + iph = skb->nh.iph;
335 + proto = iph->protocol & (MAX_INET_PROTOS - 1);
336 + err = -EPROTONOSUPPORT;
337 +
338 + rcu_read_lock();
339 + ops = rcu_dereference(inet_protos[proto]);
340 + if (likely(ops && ops->gso_send_check))
341 + err = ops->gso_send_check(skb);
342 + rcu_read_unlock();
343 +
344 +out:
345 + return err;
346 +}
347 +
348 static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
349 {
350 struct sk_buff *segs = ERR_PTR(-EINVAL);
351 @@ -1142,6 +1176,7 @@ static struct net_protocol igmp_protocol
352 static struct net_protocol tcp_protocol = {
353 .handler = tcp_v4_rcv,
354 .err_handler = tcp_v4_err,
355 + .gso_send_check = tcp_v4_gso_send_check,
356 .gso_segment = tcp_tso_segment,
357 .no_policy = 1,
358 };
359 @@ -1188,6 +1223,7 @@ static int ipv4_proc_init(void);
360 static struct packet_type ip_packet_type = {
361 .type = __constant_htons(ETH_P_IP),
362 .func = ip_rcv,
363 + .gso_send_check = inet_gso_send_check,
364 .gso_segment = inet_gso_segment,
365 };
367 diff -pruN ../orig-linux-2.6.16.29/net/ipv4/ip_output.c ./net/ipv4/ip_output.c
368 --- ../orig-linux-2.6.16.29/net/ipv4/ip_output.c 2006-09-19 13:59:20.000000000 +0100
369 +++ ./net/ipv4/ip_output.c 2006-09-19 13:59:46.000000000 +0100
370 @@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
371 return dst_output(skb);
372 }
373 #endif
374 - if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
375 + if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
376 return ip_fragment(skb, ip_finish_output2);
377 else
378 return ip_finish_output2(skb);
379 @@ -1095,7 +1095,7 @@ ssize_t ip_append_page(struct sock *sk,
380 while (size > 0) {
381 int i;
383 - if (skb_shinfo(skb)->gso_size)
384 + if (skb_is_gso(skb))
385 len = size;
386 else {
388 diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c ./net/ipv4/tcp_ipv4.c
389 --- ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c 2006-09-12 19:02:10.000000000 +0100
390 +++ ./net/ipv4/tcp_ipv4.c 2006-09-19 13:59:46.000000000 +0100
391 @@ -495,6 +495,24 @@ void tcp_v4_send_check(struct sock *sk,
392 }
393 }
395 +int tcp_v4_gso_send_check(struct sk_buff *skb)
396 +{
397 + struct iphdr *iph;
398 + struct tcphdr *th;
399 +
400 + if (!pskb_may_pull(skb, sizeof(*th)))
401 + return -EINVAL;
402 +
403 + iph = skb->nh.iph;
404 + th = skb->h.th;
405 +
406 + th->check = 0;
407 + th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
408 + skb->csum = offsetof(struct tcphdr, check);
409 + skb->ip_summed = CHECKSUM_HW;
410 + return 0;
411 +}
412 +
413 /*
414 * This routine will send an RST to the other tcp.
415 *
416 diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
417 --- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c 2006-09-19 13:59:20.000000000 +0100
418 +++ ./net/ipv4/xfrm4_output.c 2006-09-19 13:59:46.000000000 +0100
419 @@ -195,7 +195,7 @@ static int xfrm4_output_finish(struct sk
420 }
421 #endif
423 - if (!skb_shinfo(skb)->gso_size)
424 + if (!skb_is_gso(skb))
425 return xfrm4_output_finish2(skb);
427 skb->protocol = htons(ETH_P_IP);
428 diff -pruN ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c ./net/ipv6/ip6_output.c
429 --- ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c 2006-09-19 13:59:20.000000000 +0100
430 +++ ./net/ipv6/ip6_output.c 2006-09-19 13:59:46.000000000 +0100
431 @@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
433 int ip6_output(struct sk_buff *skb)
434 {
435 - if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
436 + if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
437 dst_allfrag(skb->dst))
438 return ip6_fragment(skb, ip6_output2);
439 else
440 diff -pruN ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c ./net/ipv6/xfrm6_output.c
441 --- ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c 2006-09-19 13:59:20.000000000 +0100
442 +++ ./net/ipv6/xfrm6_output.c 2006-09-19 13:59:46.000000000 +0100
443 @@ -179,7 +179,7 @@ static int xfrm6_output_finish(struct sk
444 {
445 struct sk_buff *segs;
447 - if (!skb_shinfo(skb)->gso_size)
448 + if (!skb_is_gso(skb))
449 return xfrm6_output_finish2(skb);
451 skb->protocol = htons(ETH_P_IP);