# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID bcd09a8690af89f3c8ac1bc92a003d2a9cddb0c6
# Parent 968ced1469e8cbf36d00f437ac084bf064f6df00
Backport the fix in current xen-unstable tree.
Signed-off-by: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
---
---
drivers/net/bnx2.c | 2 +-
drivers/net/chelsio/sge.c | 2 +-
drivers/net/e1000/e1000_main.c | 2 +-
drivers/net/forcedeth.c | 2 +-
drivers/net/ixgb/ixgb_main.c | 2 +-
drivers/net/loopback.c | 2 +-
drivers/net/sky2.c | 2 +-
drivers/net/typhoon.c | 4 ++--
drivers/s390/net/qeth_main.c | 2 +-
include/linux/netdevice.h | 14 ++++++++------
include/linux/skbuff.h | 5 +++++
include/net/protocol.h | 1 +
include/net/tcp.h | 1 +
net/bridge/br_netfilter.c | 2 +-
net/core/dev.c | 36 ++++++++++++++++++++++++++++++++----
net/ipv4/af_inet.c | 36 ++++++++++++++++++++++++++++++++++++
net/ipv4/ip_output.c | 4 ++--
net/ipv4/tcp_ipv4.c | 18 ++++++++++++++++++
net/ipv4/xfrm4_output.c | 2 +-
net/ipv6/ip6_output.c | 2 +-
net/ipv6/xfrm6_output.c | 2 +-
21 files changed, 117 insertions(+), 26 deletions(-)
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/bnx2.c
--- a/drivers/net/bnx2.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/bnx2.c Tue Oct 24 06:10:42 2006 -0400
@@ -1640,7 +1640,7 @@ bnx2_tx_int(struct bnx2 *bp)
skb = tx_buf->skb;
#ifdef BCM_TSO
/* partial BD completions possible with TSO packets */
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
u16 last_idx, last_ring_idx;
last_idx = sw_cons +
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/chelsio/sge.c
--- a/drivers/net/chelsio/sge.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/chelsio/sge.c Tue Oct 24 06:10:42 2006 -0400
@@ -1418,7 +1418,7 @@ int t1_start_xmit(struct sk_buff *skb, s
struct cpl_tx_pkt *cpl;
#ifdef NETIF_F_TSO
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/e1000/e1000_main.c Tue Oct 24 06:10:42 2006 -0400
@@ -2394,7 +2394,7 @@ e1000_tso(struct e1000_adapter *adapter,
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/forcedeth.c Tue Oct 24 06:10:42 2006 -0400
@@ -1495,7 +1495,7 @@ static int nv_start_xmit(struct sk_buff
np->tx_skbuff[nr] = skb;
#ifdef NETIF_F_TSO
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size <<
NV_TX2_TSO_SHIFT);
else
#endif
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/ixgb/ixgb_main.c Tue Oct 24 06:10:42 2006 -0400
@@ -1173,7 +1173,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
uint16_t ipcse, tucse, mss;
int err;
- if(likely(skb_shinfo(skb)->gso_size)) {
+ if (likely(skb_is_gso(skb))) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/loopback.c
--- a/drivers/net/loopback.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/loopback.c Tue Oct 24 06:10:42 2006 -0400
@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff
#endif
#ifdef LOOPBACK_TSO
- if (skb_shinfo(skb)->gso_size) {
+ if (skb_is_gso(skb)) {
BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/sky2.c
--- a/drivers/net/sky2.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/sky2.c Tue Oct 24 06:10:42 2006 -0400
@@ -1160,7 +1160,7 @@ static unsigned tx_le_req(const struct s
count = sizeof(dma_addr_t) / sizeof(u32);
count += skb_shinfo(skb)->nr_frags * count;
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
++count;
if (skb->ip_summed == CHECKSUM_HW)
diff -r 968ced1469e8 -r bcd09a8690af drivers/net/typhoon.c
--- a/drivers/net/typhoon.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/net/typhoon.c Tue Oct 24 06:10:42 2006 -0400
@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
* If problems develop with TSO, check this first.
*/
numDesc = skb_shinfo(skb)->nr_frags + 1;
- if(skb_tso_size(skb))
+ if (skb_is_gso(skb))
numDesc++;
/* When checking for free space in the ring, we need to also
@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
TYPHOON_TX_PF_VLAN_TAG_SHIFT);
}
- if(skb_tso_size(skb)) {
+ if (skb_is_gso(skb)) {
first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
first_txd->numDesc++;
diff -r 968ced1469e8 -r bcd09a8690af drivers/s390/net/qeth_main.c
--- a/drivers/s390/net/qeth_main.c Tue Oct 17 17:03:31 2006 -0400
+++ b/drivers/s390/net/qeth_main.c Tue Oct 24 06:10:42 2006 -0400
@@ -4453,7 +4453,7 @@ qeth_send_packet(struct qeth_card *card,
queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
large_send = card->options.large_send;
/*are we able to do TSO ? If so ,prepare and send it from here */
diff -r 968ced1469e8 -r bcd09a8690af include/linux/netdevice.h
--- a/include/linux/netdevice.h Tue Oct 17 17:03:31 2006 -0400
+++ b/include/linux/netdevice.h Tue Oct 24 06:10:42 2006 -0400
@@ -547,6 +547,7 @@ struct packet_type {
struct net_device *);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
int features);
+ int (*gso_send_check)(struct sk_buff *skb);
void *af_packet_priv;
struct list_head list;
};
@@ -921,10 +922,10 @@ static inline void netif_tx_lock_bh(stru
static inline int netif_tx_trylock(struct net_device *dev)
{
- int err = spin_trylock(&dev->_xmit_lock);
- if (!err)
+ int ok = spin_trylock(&dev->_xmit_lock);
+ if (likely(ok))
dev->xmit_lock_owner = smp_processor_id();
- return err;
+ return ok;
}
static inline void netif_tx_unlock(struct net_device *dev)
@@ -993,14 +994,15 @@ extern void linkwatch_run_queue(void);
static inline int skb_gso_ok(struct sk_buff *skb, int features)
{
- int feature = skb_shinfo(skb)->gso_size ?
- skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
+ int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
return (features & feature) == feature;
}
static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
- return !skb_gso_ok(skb, dev->features);
+ return skb_is_gso(skb) &&
+ (!skb_gso_ok(skb, dev->features) ||
+ unlikely(skb->ip_summed != CHECKSUM_HW));
}
#endif /* __KERNEL__ */
diff -r 968ced1469e8 -r bcd09a8690af include/linux/skbuff.h
--- a/include/linux/skbuff.h Tue Oct 17 17:03:31 2006 -0400
+++ b/include/linux/skbuff.h Tue Oct 24 06:10:42 2006 -0400
@@ -1459,5 +1459,10 @@ static inline void skb_init_secmark(stru
{ }
#endif
+static inline int skb_is_gso(const struct sk_buff *skb)
+{
+ return skb_shinfo(skb)->gso_size;
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */
diff -r 968ced1469e8 -r bcd09a8690af include/net/protocol.h
--- a/include/net/protocol.h Tue Oct 17 17:03:31 2006 -0400
+++ b/include/net/protocol.h Tue Oct 24 06:10:42 2006 -0400
@@ -36,6 +36,7 @@ struct net_protocol {
struct net_protocol {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
+ int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
int features);
int no_policy;
diff -r 968ced1469e8 -r bcd09a8690af include/net/tcp.h
--- a/include/net/tcp.h Tue Oct 17 17:03:31 2006 -0400
+++ b/include/net/tcp.h Tue Oct 24 06:10:42 2006 -0400
@@ -1086,6 +1086,7 @@ extern struct request_sock_ops tcp_reque
extern int tcp_v4_destroy_sock(struct sock *sk);
+extern int tcp_v4_gso_send_check(struct sk_buff *skb);
extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
#ifdef CONFIG_PROC_FS
diff -r 968ced1469e8 -r bcd09a8690af net/bridge/br_netfilter.c
--- a/net/bridge/br_netfilter.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/bridge/br_netfilter.c Tue Oct 24 06:10:42 2006 -0400
@@ -761,7 +761,7 @@ static int br_nf_dev_queue_xmit(struct s
{
if (skb->protocol == htons(ETH_P_IP) &&
skb->len > skb->dev->mtu &&
- !skb_shinfo(skb)->gso_size)
+ !skb_is_gso(skb))
return ip_fragment(skb, br_dev_queue_push_xmit);
else
return br_dev_queue_push_xmit(skb);
diff -r 968ced1469e8 -r bcd09a8690af net/core/dev.c
--- a/net/core/dev.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/core/dev.c Tue Oct 24 06:10:42 2006 -0400
@@ -1169,9 +1169,17 @@ int skb_checksum_help(struct sk_buff *sk
unsigned int csum;
int ret = 0, offset = skb->h.raw - skb->data;
- if (inward) {
- skb->ip_summed = CHECKSUM_NONE;
- goto out;
+ if (inward)
+ goto out_set_summed;
+
+ if (unlikely(skb_shinfo(skb)->gso_size)) {
+ static int warned;
+
+ WARN_ON(!warned);
+ warned = 1;
+
+ /* Let GSO fix up the checksum. */
+ goto out_set_summed;
}
if (skb_cloned(skb)) {
@@ -1188,6 +1196,8 @@ int skb_checksum_help(struct sk_buff *sk
BUG_ON(skb->csum + 2 > offset);
*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+
+out_set_summed:
skb->ip_summed = CHECKSUM_NONE;
out:
return ret;
@@ -1208,17 +1218,35 @@ struct sk_buff *skb_gso_segment(struct s
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
struct packet_type *ptype;
int type = skb->protocol;
+ int err;
BUG_ON(skb_shinfo(skb)->frag_list);
- BUG_ON(skb->ip_summed != CHECKSUM_HW);
skb->mac.raw = skb->data;
skb->mac_len = skb->nh.raw - skb->data;
__skb_pull(skb, skb->mac_len);
+ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
+ static int warned;
+
+ WARN_ON(!warned);
+ warned = 1;
+
+ if (skb_header_cloned(skb) &&
+ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ return ERR_PTR(err);
+ }
+
rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
+ err = ptype->gso_send_check(skb);
+ segs = ERR_PTR(err);
+ if (err || skb_gso_ok(skb, features))
+ break;
+ __skb_push(skb, skb->data - skb->nh.raw);
+ }
segs = ptype->gso_segment(skb, features);
break;
}
diff -r 968ced1469e8 -r bcd09a8690af net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv4/af_inet.c Tue Oct 24 06:10:42 2006 -0400
@@ -1097,6 +1097,40 @@ int inet_sk_rebuild_header(struct sock *
EXPORT_SYMBOL(inet_sk_rebuild_header);
+static int inet_gso_send_check(struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct net_protocol *ops;
+ int proto;
+ int ihl;
+ int err = -EINVAL;
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
+ goto out;
+
+ iph = skb->nh.iph;
+ ihl = iph->ihl * 4;
+ if (ihl < sizeof(*iph))
+ goto out;
+
+ if (unlikely(!pskb_may_pull(skb, ihl)))
+ goto out;
+
+ skb->h.raw = __skb_pull(skb, ihl);
+ iph = skb->nh.iph;
+ proto = iph->protocol & (MAX_INET_PROTOS - 1);
+ err = -EPROTONOSUPPORT;
+
+ rcu_read_lock();
+ ops = rcu_dereference(inet_protos[proto]);
+ if (likely(ops && ops->gso_send_check))
+ err = ops->gso_send_check(skb);
+ rcu_read_unlock();
+
+out:
+ return err;
+}
+
static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
{
struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -1154,6 +1188,7 @@ static struct net_protocol tcp_protocol
static struct net_protocol tcp_protocol = {
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
+ .gso_send_check = tcp_v4_gso_send_check,
.gso_segment = tcp_tso_segment,
.no_policy = 1,
};
@@ -1200,6 +1235,7 @@ static struct packet_type ip_packet_type
static struct packet_type ip_packet_type = {
.type = __constant_htons(ETH_P_IP),
.func = ip_rcv,
+ .gso_send_check = inet_gso_send_check,
.gso_segment = inet_gso_segment,
};
diff -r 968ced1469e8 -r bcd09a8690af net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv4/ip_output.c Tue Oct 24 06:10:42 2006 -0400
@@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
return dst_output(skb);
}
#endif
- if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
+ if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
return ip_fragment(skb, ip_finish_output2);
else
return ip_finish_output2(skb);
@@ -1096,7 +1096,7 @@ ssize_t ip_append_page(struct sock *sk,
while (size > 0) {
int i;
- if (skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
len = size;
else {
diff -r 968ced1469e8 -r bcd09a8690af net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv4/tcp_ipv4.c Tue Oct 24 06:10:42 2006 -0400
@@ -494,6 +494,24 @@ void tcp_v4_send_check(struct sock *sk,
th->doff << 2,
skb->csum));
}
+}
+
+int tcp_v4_gso_send_check(struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct tcphdr *th;
+
+ if (!pskb_may_pull(skb, sizeof(*th)))
+ return -EINVAL;
+
+ iph = skb->nh.iph;
+ th = skb->h.th;
+
+ th->check = 0;
+ th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
+ skb->csum = offsetof(struct tcphdr, check);
+ skb->ip_summed = CHECKSUM_HW;
+ return 0;
}
/*
diff -r 968ced1469e8 -r bcd09a8690af net/ipv4/xfrm4_output.c
--- a/net/ipv4/xfrm4_output.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv4/xfrm4_output.c Tue Oct 24 06:10:42 2006 -0400
@@ -140,7 +140,7 @@ static int xfrm4_output_finish(struct sk
}
#endif
- if (!skb_shinfo(skb)->gso_size)
+ if (!skb_is_gso(skb))
return xfrm4_output_finish2(skb);
skb->protocol = htons(ETH_P_IP);
diff -r 968ced1469e8 -r bcd09a8690af net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv6/ip6_output.c Tue Oct 24 06:10:42 2006 -0400
@@ -148,7 +148,7 @@ static int ip6_output2(struct sk_buff *s
int ip6_output(struct sk_buff *skb)
{
- if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
+ if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
diff -r 968ced1469e8 -r bcd09a8690af net/ipv6/xfrm6_output.c
--- a/net/ipv6/xfrm6_output.c Tue Oct 17 17:03:31 2006 -0400
+++ b/net/ipv6/xfrm6_output.c Tue Oct 24 06:10:42 2006 -0400
@@ -122,7 +122,7 @@ static int xfrm6_output_finish(struct sk
{
struct sk_buff *segs;
- if (!skb_shinfo(skb)->gso_size)
+ if (!skb_is_gso(skb))
return xfrm6_output_finish2(skb);
skb->protocol = htons(ETH_P_IP);
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|