Browse Source

Merge commit master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 of HEAD

* HEAD:
  [AX.25]: Use kzalloc
  [ATM] net/atm/clip.c: fix PROC_FS=n compile
  [PKT_SCHED]: act_api: Fix module leak while flushing actions
  [NET]: Fix IPv4/DECnet routing rule dumping
  [NET] gso: Fix up GSO packets with broken checksums
  [NET] gso: Add skb_is_gso
  [IRDA]: fix drivers/net/irda/ali-ircc.c:ali_ircc_init()
  [ATM]: fix possible recursive locking in skb_migrate()
  [ATM]: Typo in drivers/atm/Kconfig...
  [TG3]: add amd8131 to "write reorder" chipsets
  [NET]: Fix network device interface printk message priority
Linus Torvalds 19 years ago
parent
commit
09075ef0fd

+ 1 - 1
drivers/atm/Kconfig

@@ -398,7 +398,7 @@ config ATM_FORE200E_USE_TASKLET
 	default n
 	default n
 	help
 	help
 	  This defers work to be done by the interrupt handler to a
 	  This defers work to be done by the interrupt handler to a
-	  tasklet instead of hanlding everything at interrupt time.  This
+	  tasklet instead of handling everything at interrupt time.  This
 	  may improve the responsive of the host.
 	  may improve the responsive of the host.
 
 
 config ATM_FORE200E_TX_RETRY
 config ATM_FORE200E_TX_RETRY

+ 1 - 1
drivers/net/bnx2.c

@@ -1639,7 +1639,7 @@ bnx2_tx_int(struct bnx2 *bp)
 		skb = tx_buf->skb;
 		skb = tx_buf->skb;
 #ifdef BCM_TSO 
 #ifdef BCM_TSO 
 		/* partial BD completions possible with TSO packets */
 		/* partial BD completions possible with TSO packets */
-		if (skb_shinfo(skb)->gso_size) {
+		if (skb_is_gso(skb)) {
 			u16 last_idx, last_ring_idx;
 			u16 last_idx, last_ring_idx;
 
 
 			last_idx = sw_cons +
 			last_idx = sw_cons +

+ 1 - 1
drivers/net/chelsio/sge.c

@@ -1417,7 +1417,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct cpl_tx_pkt *cpl;
 	struct cpl_tx_pkt *cpl;
 
 
 #ifdef NETIF_F_TSO
 #ifdef NETIF_F_TSO
-	if (skb_shinfo(skb)->gso_size) {
+	if (skb_is_gso(skb)) {
 		int eth_type;
 		int eth_type;
 		struct cpl_tx_pkt_lso *hdr;
 		struct cpl_tx_pkt_lso *hdr;
 
 

+ 3 - 4
drivers/net/e1000/e1000_main.c

@@ -2524,7 +2524,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	int err;
 	int err;
 
 
-	if (skb_shinfo(skb)->gso_size) {
+	if (skb_is_gso(skb)) {
 		if (skb_header_cloned(skb)) {
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
 			if (err)
@@ -2649,7 +2649,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 		 * tso gets written back prematurely before the data is fully
 		 * tso gets written back prematurely before the data is fully
 		 * DMA'd to the controller */
 		 * DMA'd to the controller */
 		if (!skb->data_len && tx_ring->last_tx_tso &&
 		if (!skb->data_len && tx_ring->last_tx_tso &&
-		    !skb_shinfo(skb)->gso_size) {
+		    !skb_is_gso(skb)) {
 			tx_ring->last_tx_tso = 0;
 			tx_ring->last_tx_tso = 0;
 			size -= 4;
 			size -= 4;
 		}
 		}
@@ -2937,8 +2937,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 
 #ifdef NETIF_F_TSO
 #ifdef NETIF_F_TSO
 	/* Controller Erratum workaround */
 	/* Controller Erratum workaround */
-	if (!skb->data_len && tx_ring->last_tx_tso &&
-	    !skb_shinfo(skb)->gso_size)
+	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
 		count++;
 		count++;
 #endif
 #endif
 
 

+ 1 - 1
drivers/net/forcedeth.c

@@ -1495,7 +1495,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	np->tx_skbuff[nr] = skb;
 	np->tx_skbuff[nr] = skb;
 
 
 #ifdef NETIF_F_TSO
 #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);
 		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
 	else
 	else
 #endif
 #endif

+ 2 - 1
drivers/net/irda/ali-ircc.c

@@ -146,7 +146,7 @@ static int __init ali_ircc_init(void)
 {
 {
 	ali_chip_t *chip;
 	ali_chip_t *chip;
 	chipio_t info;
 	chipio_t info;
-	int ret = -ENODEV;
+	int ret;
 	int cfg, cfg_base;
 	int cfg, cfg_base;
 	int reg, revision;
 	int reg, revision;
 	int i = 0;
 	int i = 0;
@@ -160,6 +160,7 @@ static int __init ali_ircc_init(void)
                 return ret;
                 return ret;
         }
         }
 
 
+	ret = -ENODEV;
 	
 	
 	/* Probe for all the ALi chipsets we know about */
 	/* Probe for all the ALi chipsets we know about */
 	for (chip= chips; chip->name; chip++, i++) 
 	for (chip= chips; chip->name; chip++, i++) 

+ 1 - 1
drivers/net/ixgb/ixgb_main.c

@@ -1173,7 +1173,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 	uint16_t ipcse, tucse, mss;
 	uint16_t ipcse, tucse, mss;
 	int err;
 	int err;
 
 
-	if(likely(skb_shinfo(skb)->gso_size)) {
+	if (likely(skb_is_gso(skb))) {
 		if (skb_header_cloned(skb)) {
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
 			if (err)

+ 1 - 1
drivers/net/loopback.c

@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
 #endif
 
 
 #ifdef LOOPBACK_TSO
 #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->protocol != htons(ETH_P_IP));
 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
 
 

+ 1 - 1
drivers/net/myri10ge/myri10ge.c

@@ -2116,7 +2116,7 @@ abort_linearize:
 		}
 		}
 		idx = (idx + 1) & tx->mask;
 		idx = (idx + 1) & tx->mask;
 	} while (idx != last_idx);
 	} while (idx != last_idx);
-	if (skb_shinfo(skb)->gso_size) {
+	if (skb_is_gso(skb)) {
 		printk(KERN_ERR
 		printk(KERN_ERR
 		       "myri10ge: %s: TSO but wanted to linearize?!?!?\n",
 		       "myri10ge: %s: TSO but wanted to linearize?!?!?\n",
 		       mgp->dev->name);
 		       mgp->dev->name);

+ 1 - 1
drivers/net/sky2.c

@@ -1159,7 +1159,7 @@ static unsigned tx_le_req(const struct sk_buff *skb)
 	count = sizeof(dma_addr_t) / sizeof(u32);
 	count = sizeof(dma_addr_t) / sizeof(u32);
 	count += skb_shinfo(skb)->nr_frags * count;
 	count += skb_shinfo(skb)->nr_frags * count;
 
 
-	if (skb_shinfo(skb)->gso_size)
+	if (skb_is_gso(skb))
 		++count;
 		++count;
 
 
 	if (skb->ip_summed == CHECKSUM_HW)
 	if (skb->ip_summed == CHECKSUM_HW)

+ 2 - 0
drivers/net/tg3.c

@@ -10078,6 +10078,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	static struct pci_device_id write_reorder_chipsets[] = {
 	static struct pci_device_id write_reorder_chipsets[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
 		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
 		             PCI_DEVICE_ID_AMD_FE_GATE_700C) },
 		             PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
+		             PCI_DEVICE_ID_AMD_8131_BRIDGE) },
 		{ PCI_DEVICE(PCI_VENDOR_ID_VIA,
 		{ PCI_DEVICE(PCI_VENDOR_ID_VIA,
 			     PCI_DEVICE_ID_VIA_8385_0) },
 			     PCI_DEVICE_ID_VIA_8385_0) },
 		{ },
 		{ },

+ 2 - 2
drivers/net/typhoon.c

@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
 	 * If problems develop with TSO, check this first.
 	 * If problems develop with TSO, check this first.
 	 */
 	 */
 	numDesc = skb_shinfo(skb)->nr_frags + 1;
 	numDesc = skb_shinfo(skb)->nr_frags + 1;
-	if(skb_tso_size(skb))
+	if (skb_is_gso(skb))
 		numDesc++;
 		numDesc++;
 
 
 	/* When checking for free space in the ring, we need to also
 	/* When checking for free space in the ring, we need to also
@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
 				TYPHOON_TX_PF_VLAN_TAG_SHIFT);
 				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->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
 		first_txd->numDesc++;
 		first_txd->numDesc++;
 
 

+ 1 - 1
drivers/s390/net/qeth_main.c

@@ -4457,7 +4457,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
 	queue = card->qdio.out_qs
 	queue = card->qdio.out_qs
 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
 		[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;
 		large_send = card->options.large_send;
 
 
 	/*are we able to do TSO ? If so ,prepare and send it from here */
 	/*are we able to do TSO ? If so ,prepare and send it from here */

+ 5 - 3
include/linux/netdevice.h

@@ -549,6 +549,7 @@ struct packet_type {
 					 struct net_device *);
 					 struct net_device *);
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
 						int features);
 						int features);
+	int			(*gso_send_check)(struct sk_buff *skb);
 	void			*af_packet_priv;
 	void			*af_packet_priv;
 	struct list_head	list;
 	struct list_head	list;
 };
 };
@@ -1001,13 +1002,14 @@ static inline int net_gso_ok(int features, int gso_type)
 
 
 static inline int skb_gso_ok(struct sk_buff *skb, int features)
 static inline int skb_gso_ok(struct sk_buff *skb, int features)
 {
 {
-	return net_gso_ok(features, skb_shinfo(skb)->gso_size ?
-				    skb_shinfo(skb)->gso_type : 0);
+	return net_gso_ok(features, skb_shinfo(skb)->gso_type);
 }
 }
 
 
 static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 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__ */
 #endif /* __KERNEL__ */

+ 5 - 0
include/linux/skbuff.h

@@ -1455,5 +1455,10 @@ static inline void skb_init_secmark(struct sk_buff *skb)
 { }
 { }
 #endif
 #endif
 
 
+static inline int skb_is_gso(const struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->gso_size;
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
 #endif	/* _LINUX_SKBUFF_H */

+ 2 - 0
include/net/protocol.h

@@ -36,6 +36,7 @@
 struct net_protocol {
 struct net_protocol {
 	int			(*handler)(struct sk_buff *skb);
 	int			(*handler)(struct sk_buff *skb);
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 	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,
 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
 					       int features);
 					       int features);
 	int			no_policy;
 	int			no_policy;
@@ -51,6 +52,7 @@ struct inet6_protocol
 			       int type, int code, int offset,
 			       int type, int code, int offset,
 			       __u32 info);
 			       __u32 info);
 
 
+	int	(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff *(*gso_segment)(struct sk_buff *skb,
 	struct sk_buff *(*gso_segment)(struct sk_buff *skb,
 				       int features);
 				       int features);
 
 

+ 1 - 0
include/net/tcp.h

@@ -1086,6 +1086,7 @@ extern struct request_sock_ops tcp_request_sock_ops;
 
 
 extern int tcp_v4_destroy_sock(struct sock *sk);
 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);
 extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
 
 
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_PROC_FS

+ 9 - 4
net/atm/clip.c

@@ -962,7 +962,6 @@ static struct file_operations arp_seq_fops = {
 
 
 static int __init atm_clip_init(void)
 static int __init atm_clip_init(void)
 {
 {
-	struct proc_dir_entry *p;
 	neigh_table_init_no_netlink(&clip_tbl);
 	neigh_table_init_no_netlink(&clip_tbl);
 
 
 	clip_tbl_hook = &clip_tbl;
 	clip_tbl_hook = &clip_tbl;
@@ -972,9 +971,15 @@ static int __init atm_clip_init(void)
 
 
 	setup_timer(&idle_timer, idle_timer_check, 0);
 	setup_timer(&idle_timer, idle_timer_check, 0);
 
 
-	p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
-	if (p)
-		p->proc_fops = &arp_seq_fops;
+#ifdef CONFIG_PROC_FS
+	{
+		struct proc_dir_entry *p;
+
+		p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
+		if (p)
+			p->proc_fops = &arp_seq_fops;
+	}
+#endif
 
 
 	return 0;
 	return 0;
 }
 }

+ 11 - 6
net/atm/ipcommon.c

@@ -25,22 +25,27 @@
 /*
 /*
  * skb_migrate appends the list at "from" to "to", emptying "from" in the
  * skb_migrate appends the list at "from" to "to", emptying "from" in the
  * process. skb_migrate is atomic with respect to all other skb operations on
  * process. skb_migrate is atomic with respect to all other skb operations on
- * "from" and "to". Note that it locks both lists at the same time, so beware
- * of potential deadlocks.
+ * "from" and "to". Note that it locks both lists at the same time, so to deal
+ * with the lock ordering, the locks are taken in address order.
  *
  *
  * This function should live in skbuff.c or skbuff.h.
  * This function should live in skbuff.c or skbuff.h.
  */
  */
 
 
 
 
-void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
+void skb_migrate(struct sk_buff_head *from, struct sk_buff_head *to)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 	struct sk_buff *skb_from = (struct sk_buff *) from;
 	struct sk_buff *skb_from = (struct sk_buff *) from;
 	struct sk_buff *skb_to = (struct sk_buff *) to;
 	struct sk_buff *skb_to = (struct sk_buff *) to;
 	struct sk_buff *prev;
 	struct sk_buff *prev;
 
 
-	spin_lock_irqsave(&from->lock,flags);
-	spin_lock(&to->lock);
+	if ((unsigned long) from < (unsigned long) to) {
+		spin_lock_irqsave(&from->lock, flags);
+		spin_lock_nested(&to->lock, SINGLE_DEPTH_NESTING);
+	} else {
+		spin_lock_irqsave(&to->lock, flags);
+		spin_lock_nested(&from->lock, SINGLE_DEPTH_NESTING);
+	}
 	prev = from->prev;
 	prev = from->prev;
 	from->next->prev = to->prev;
 	from->next->prev = to->prev;
 	prev->next = skb_to;
 	prev->next = skb_to;
@@ -51,7 +56,7 @@ void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to)
 	from->prev = skb_from;
 	from->prev = skb_from;
 	from->next = skb_from;
 	from->next = skb_from;
 	from->qlen = 0;
 	from->qlen = 0;
-	spin_unlock_irqrestore(&from->lock,flags);
+	spin_unlock_irqrestore(&from->lock, flags);
 }
 }
 
 
 
 

+ 1 - 2
net/ax25/af_ax25.c

@@ -486,10 +486,9 @@ ax25_cb *ax25_create_cb(void)
 {
 {
 	ax25_cb *ax25;
 	ax25_cb *ax25;
 
 
-	if ((ax25 = kmalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
+	if ((ax25 = kzalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
 		return NULL;
 		return NULL;
 
 
-	memset(ax25, 0x00, sizeof(*ax25));
 	atomic_set(&ax25->refcount, 1);
 	atomic_set(&ax25->refcount, 1);
 
 
 	skb_queue_head_init(&ax25->write_queue);
 	skb_queue_head_init(&ax25->write_queue);

+ 1 - 3
net/ax25/ax25_dev.c

@@ -55,15 +55,13 @@ void ax25_dev_device_up(struct net_device *dev)
 {
 {
 	ax25_dev *ax25_dev;
 	ax25_dev *ax25_dev;
 
 
-	if ((ax25_dev = kmalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
+	if ((ax25_dev = kzalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
 		printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
 		printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
 		return;
 		return;
 	}
 	}
 
 
 	ax25_unregister_sysctl();
 	ax25_unregister_sysctl();
 
 
-	memset(ax25_dev, 0x00, sizeof(*ax25_dev));
-
 	dev->ax25_ptr     = ax25_dev;
 	dev->ax25_ptr     = ax25_dev;
 	ax25_dev->dev     = dev;
 	ax25_dev->dev     = dev;
 	dev_hold(dev);
 	dev_hold(dev);

+ 1 - 1
net/bridge/br_forward.c

@@ -35,7 +35,7 @@ static inline unsigned packet_length(const struct sk_buff *skb)
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
 {
 	/* drop mtu oversized packets except gso */
 	/* drop mtu oversized packets except gso */
-	if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
+	if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
 		kfree_skb(skb);
 		kfree_skb(skb);
 	else {
 	else {
 #ifdef CONFIG_BRIDGE_NETFILTER
 #ifdef CONFIG_BRIDGE_NETFILTER

+ 1 - 1
net/bridge/br_netfilter.c

@@ -761,7 +761,7 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
 {
 {
 	if (skb->protocol == htons(ETH_P_IP) &&
 	if (skb->protocol == htons(ETH_P_IP) &&
 	    skb->len > skb->dev->mtu &&
 	    skb->len > skb->dev->mtu &&
-	    !skb_shinfo(skb)->gso_size)
+	    !skb_is_gso(skb))
 		return ip_fragment(skb, br_dev_queue_push_xmit);
 		return ip_fragment(skb, br_dev_queue_push_xmit);
 	else
 	else
 		return br_dev_queue_push_xmit(skb);
 		return br_dev_queue_push_xmit(skb);

+ 35 - 7
net/core/dev.c

@@ -1162,9 +1162,17 @@ int skb_checksum_help(struct sk_buff *skb, int inward)
 	unsigned int csum;
 	unsigned int csum;
 	int ret = 0, offset = skb->h.raw - skb->data;
 	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)) {
 	if (skb_cloned(skb)) {
@@ -1181,6 +1189,8 @@ int skb_checksum_help(struct sk_buff *skb, int inward)
 	BUG_ON(skb->csum + 2 > offset);
 	BUG_ON(skb->csum + 2 > offset);
 
 
 	*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
 	*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+
+out_set_summed:
 	skb->ip_summed = CHECKSUM_NONE;
 	skb->ip_summed = CHECKSUM_NONE;
 out:	
 out:	
 	return ret;
 	return ret;
@@ -1201,17 +1211,35 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_type *ptype;
 	struct packet_type *ptype;
 	int type = skb->protocol;
 	int type = skb->protocol;
+	int err;
 
 
 	BUG_ON(skb_shinfo(skb)->frag_list);
 	BUG_ON(skb_shinfo(skb)->frag_list);
-	BUG_ON(skb->ip_summed != CHECKSUM_HW);
 
 
 	skb->mac.raw = skb->data;
 	skb->mac.raw = skb->data;
 	skb->mac_len = skb->nh.raw - skb->data;
 	skb->mac_len = skb->nh.raw - skb->data;
 	__skb_pull(skb, skb->mac_len);
 	__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();
 	rcu_read_lock();
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
 		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
 		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);
 			segs = ptype->gso_segment(skb, features);
 			break;
 			break;
 		}
 		}
@@ -1727,7 +1755,7 @@ static int ing_filter(struct sk_buff *skb)
 	if (dev->qdisc_ingress) {
 	if (dev->qdisc_ingress) {
 		__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
 		__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
 		if (MAX_RED_LOOP < ttl++) {
 		if (MAX_RED_LOOP < ttl++) {
-			printk("Redir loop detected Dropping packet (%s->%s)\n",
+			printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n",
 				skb->input_dev->name, skb->dev->name);
 				skb->input_dev->name, skb->dev->name);
 			return TC_ACT_SHOT;
 			return TC_ACT_SHOT;
 		}
 		}
@@ -2922,7 +2950,7 @@ int register_netdevice(struct net_device *dev)
 	/* Fix illegal SG+CSUM combinations. */
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
 	if ((dev->features & NETIF_F_SG) &&
 	    !(dev->features & NETIF_F_ALL_CSUM)) {
 	    !(dev->features & NETIF_F_ALL_CSUM)) {
-		printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
+		printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no checksum feature.\n",
 		       dev->name);
 		       dev->name);
 		dev->features &= ~NETIF_F_SG;
 		dev->features &= ~NETIF_F_SG;
 	}
 	}
@@ -2930,7 +2958,7 @@ int register_netdevice(struct net_device *dev)
 	/* TSO requires that SG is present as well. */
 	/* TSO requires that SG is present as well. */
 	if ((dev->features & NETIF_F_TSO) &&
 	if ((dev->features & NETIF_F_TSO) &&
 	    !(dev->features & NETIF_F_SG)) {
 	    !(dev->features & NETIF_F_SG)) {
-		printk("%s: Dropping NETIF_F_TSO since no SG feature.\n",
+		printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no SG feature.\n",
 		       dev->name);
 		       dev->name);
 		dev->features &= ~NETIF_F_TSO;
 		dev->features &= ~NETIF_F_TSO;
 	}
 	}

+ 2 - 1
net/decnet/dn_rules.c

@@ -399,9 +399,10 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
 	rcu_read_lock();
 	rcu_read_lock();
 	hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
 	hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
 		if (idx < s_idx)
 		if (idx < s_idx)
-			continue;
+			goto next;
 		if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
 		if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
 			break;
 			break;
+next:
 		idx++;
 		idx++;
 	}
 	}
 	rcu_read_unlock();
 	rcu_read_unlock();

+ 36 - 0
net/ipv4/af_inet.c

@@ -1097,6 +1097,40 @@ int inet_sk_rebuild_header(struct sock *sk)
 
 
 EXPORT_SYMBOL(inet_sk_rebuild_header);
 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)
 static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 {
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -1162,6 +1196,7 @@ static struct net_protocol igmp_protocol = {
 static struct net_protocol tcp_protocol = {
 static struct net_protocol tcp_protocol = {
 	.handler =	tcp_v4_rcv,
 	.handler =	tcp_v4_rcv,
 	.err_handler =	tcp_v4_err,
 	.err_handler =	tcp_v4_err,
+	.gso_send_check = tcp_v4_gso_send_check,
 	.gso_segment =	tcp_tso_segment,
 	.gso_segment =	tcp_tso_segment,
 	.no_policy =	1,
 	.no_policy =	1,
 };
 };
@@ -1208,6 +1243,7 @@ static int ipv4_proc_init(void);
 static struct packet_type ip_packet_type = {
 static struct packet_type ip_packet_type = {
 	.type = __constant_htons(ETH_P_IP),
 	.type = __constant_htons(ETH_P_IP),
 	.func = ip_rcv,
 	.func = ip_rcv,
+	.gso_send_check = inet_gso_send_check,
 	.gso_segment = inet_gso_segment,
 	.gso_segment = inet_gso_segment,
 };
 };
 
 

+ 2 - 2
net/ipv4/fib_rules.c

@@ -457,13 +457,13 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
 
 
 	rcu_read_lock();
 	rcu_read_lock();
 	hlist_for_each_entry(r, node, &fib_rules, hlist) {
 	hlist_for_each_entry(r, node, &fib_rules, hlist) {
-
 		if (idx < s_idx)
 		if (idx < s_idx)
-			continue;
+			goto next;
 		if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
 		if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
 				   cb->nlh->nlmsg_seq,
 				   cb->nlh->nlmsg_seq,
 				   RTM_NEWRULE, NLM_F_MULTI) < 0)
 				   RTM_NEWRULE, NLM_F_MULTI) < 0)
 			break;
 			break;
+next:
 		idx++;
 		idx++;
 	}
 	}
 	rcu_read_unlock();
 	rcu_read_unlock();

+ 2 - 2
net/ipv4/ip_output.c

@@ -209,7 +209,7 @@ static inline int ip_finish_output(struct sk_buff *skb)
 		return dst_output(skb);
 		return dst_output(skb);
 	}
 	}
 #endif
 #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);
 		return ip_fragment(skb, ip_finish_output2);
 	else
 	else
 		return ip_finish_output2(skb);
 		return ip_finish_output2(skb);
@@ -1095,7 +1095,7 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 	while (size > 0) {
 	while (size > 0) {
 		int i;
 		int i;
 
 
-		if (skb_shinfo(skb)->gso_size)
+		if (skb_is_gso(skb))
 			len = size;
 			len = size;
 		else {
 		else {
 
 

+ 18 - 0
net/ipv4/tcp_ipv4.c

@@ -496,6 +496,24 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
 	}
 	}
 }
 }
 
 
+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;
+}
+
 /*
 /*
  *	This routine will send an RST to the other tcp.
  *	This routine will send an RST to the other tcp.
  *
  *

+ 1 - 1
net/ipv4/xfrm4_output.c

@@ -134,7 +134,7 @@ static int xfrm4_output_finish(struct sk_buff *skb)
 	}
 	}
 #endif
 #endif
 
 
-	if (!skb_shinfo(skb)->gso_size)
+	if (!skb_is_gso(skb))
 		return xfrm4_output_finish2(skb);
 		return xfrm4_output_finish2(skb);
 
 
 	skb->protocol = htons(ETH_P_IP);
 	skb->protocol = htons(ETH_P_IP);

+ 2 - 2
net/ipv6/ip6_output.c

@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *skb)
 
 
 int ip6_output(struct sk_buff *skb)
 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))
 				dst_allfrag(skb->dst))
 		return ip6_fragment(skb, ip6_output2);
 		return ip6_fragment(skb, ip6_output2);
 	else
 	else
@@ -229,7 +229,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	skb->priority = sk->sk_priority;
 	skb->priority = sk->sk_priority;
 
 
 	mtu = dst_mtu(dst);
 	mtu = dst_mtu(dst);
-	if ((skb->len <= mtu) || ipfragok || skb_shinfo(skb)->gso_size) {
+	if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
 		IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 		IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 		return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
 		return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 				dst_output);

+ 61 - 28
net/ipv6/ipv6_sockglue.c

@@ -57,29 +57,11 @@
 
 
 DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
 DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
 
 
-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
+static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
+						    int proto)
 {
 {
-	struct sk_buff *segs = ERR_PTR(-EINVAL);
-	struct ipv6hdr *ipv6h;
-	struct inet6_protocol *ops;
-	int proto;
+	struct inet6_protocol *ops = NULL;
 
 
-	if (unlikely(skb_shinfo(skb)->gso_type &
-		     ~(SKB_GSO_UDP |
-		       SKB_GSO_DODGY |
-		       SKB_GSO_TCP_ECN |
-		       SKB_GSO_TCPV6 |
-		       0)))
-		goto out;
-
-	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
-		goto out;
-
-	ipv6h = skb->nh.ipv6h;
-	proto = ipv6h->nexthdr;
-	__skb_pull(skb, sizeof(*ipv6h));
-
-	rcu_read_lock();
 	for (;;) {
 	for (;;) {
 		struct ipv6_opt_hdr *opth;
 		struct ipv6_opt_hdr *opth;
 		int len;
 		int len;
@@ -88,30 +70,80 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
 			ops = rcu_dereference(inet6_protos[proto]);
 			ops = rcu_dereference(inet6_protos[proto]);
 
 
 			if (unlikely(!ops))
 			if (unlikely(!ops))
-				goto unlock;
+				break;
 
 
 			if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
 			if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
 				break;
 				break;
 		}
 		}
 
 
 		if (unlikely(!pskb_may_pull(skb, 8)))
 		if (unlikely(!pskb_may_pull(skb, 8)))
-			goto unlock;
+			break;
 
 
 		opth = (void *)skb->data;
 		opth = (void *)skb->data;
 		len = opth->hdrlen * 8 + 8;
 		len = opth->hdrlen * 8 + 8;
 
 
 		if (unlikely(!pskb_may_pull(skb, len)))
 		if (unlikely(!pskb_may_pull(skb, len)))
-			goto unlock;
+			break;
 
 
 		proto = opth->nexthdr;
 		proto = opth->nexthdr;
 		__skb_pull(skb, len);
 		__skb_pull(skb, len);
 	}
 	}
 
 
-	skb->h.raw = skb->data;
-	if (likely(ops->gso_segment))
-		segs = ops->gso_segment(skb, features);
+	return ops;
+}
+
+static int ipv6_gso_send_check(struct sk_buff *skb)
+{
+	struct ipv6hdr *ipv6h;
+	struct inet6_protocol *ops;
+	int err = -EINVAL;
+
+	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+		goto out;
 
 
-unlock:
+	ipv6h = skb->nh.ipv6h;
+	__skb_pull(skb, sizeof(*ipv6h));
+	err = -EPROTONOSUPPORT;
+
+	rcu_read_lock();
+	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+	if (likely(ops && ops->gso_send_check)) {
+		skb->h.raw = skb->data;
+		err = ops->gso_send_check(skb);
+	}
+	rcu_read_unlock();
+
+out:
+	return err;
+}
+
+static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
+{
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	struct ipv6hdr *ipv6h;
+	struct inet6_protocol *ops;
+
+	if (unlikely(skb_shinfo(skb)->gso_type &
+		     ~(SKB_GSO_UDP |
+		       SKB_GSO_DODGY |
+		       SKB_GSO_TCP_ECN |
+		       SKB_GSO_TCPV6 |
+		       0)))
+		goto out;
+
+	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+		goto out;
+
+	ipv6h = skb->nh.ipv6h;
+	__skb_pull(skb, sizeof(*ipv6h));
+	segs = ERR_PTR(-EPROTONOSUPPORT);
+
+	rcu_read_lock();
+	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+	if (likely(ops && ops->gso_segment)) {
+		skb->h.raw = skb->data;
+		segs = ops->gso_segment(skb, features);
+	}
 	rcu_read_unlock();
 	rcu_read_unlock();
 
 
 	if (unlikely(IS_ERR(segs)))
 	if (unlikely(IS_ERR(segs)))
@@ -130,6 +162,7 @@ out:
 static struct packet_type ipv6_packet_type = {
 static struct packet_type ipv6_packet_type = {
 	.type = __constant_htons(ETH_P_IPV6), 
 	.type = __constant_htons(ETH_P_IPV6), 
 	.func = ipv6_rcv,
 	.func = ipv6_rcv,
+	.gso_send_check = ipv6_gso_send_check,
 	.gso_segment = ipv6_gso_segment,
 	.gso_segment = ipv6_gso_segment,
 };
 };
 
 

+ 19 - 0
net/ipv6/tcp_ipv6.c

@@ -552,6 +552,24 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
 	}
 	}
 }
 }
 
 
+static int tcp_v6_gso_send_check(struct sk_buff *skb)
+{
+	struct ipv6hdr *ipv6h;
+	struct tcphdr *th;
+
+	if (!pskb_may_pull(skb, sizeof(*th)))
+		return -EINVAL;
+
+	ipv6h = skb->nh.ipv6h;
+	th = skb->h.th;
+
+	th->check = 0;
+	th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+				     IPPROTO_TCP, 0);
+	skb->csum = offsetof(struct tcphdr, check);
+	skb->ip_summed = CHECKSUM_HW;
+	return 0;
+}
 
 
 static void tcp_v6_send_reset(struct sk_buff *skb)
 static void tcp_v6_send_reset(struct sk_buff *skb)
 {
 {
@@ -1603,6 +1621,7 @@ struct proto tcpv6_prot = {
 static struct inet6_protocol tcpv6_protocol = {
 static struct inet6_protocol tcpv6_protocol = {
 	.handler	=	tcp_v6_rcv,
 	.handler	=	tcp_v6_rcv,
 	.err_handler	=	tcp_v6_err,
 	.err_handler	=	tcp_v6_err,
+	.gso_send_check	=	tcp_v6_gso_send_check,
 	.gso_segment	=	tcp_tso_segment,
 	.gso_segment	=	tcp_tso_segment,
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 };

+ 1 - 1
net/ipv6/xfrm6_output.c

@@ -122,7 +122,7 @@ static int xfrm6_output_finish(struct sk_buff *skb)
 {
 {
 	struct sk_buff *segs;
 	struct sk_buff *segs;
 
 
-	if (!skb_shinfo(skb)->gso_size)
+	if (!skb_is_gso(skb))
 		return xfrm6_output_finish2(skb);
 		return xfrm6_output_finish2(skb);
 
 
 	skb->protocol = htons(ETH_P_IP);
 	skb->protocol = htons(ETH_P_IP);

+ 1 - 3
net/netrom/af_netrom.c

@@ -1382,14 +1382,12 @@ static int __init nr_proto_init(void)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	dev_nr = kmalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+	dev_nr = kzalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL);
 	if (dev_nr == NULL) {
 	if (dev_nr == NULL) {
 		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n");
 		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n");
 		return -1;
 		return -1;
 	}
 	}
 
 
-	memset(dev_nr, 0x00, nr_ndevs * sizeof(struct net_device *));
-
 	for (i = 0; i < nr_ndevs; i++) {
 	for (i = 0; i < nr_ndevs; i++) {
 		char name[IFNAMSIZ];
 		char name[IFNAMSIZ];
 		struct net_device *dev;
 		struct net_device *dev;

+ 1 - 2
net/rose/af_rose.c

@@ -1490,14 +1490,13 @@ static int __init rose_proto_init(void)
 
 
 	rose_callsign = null_ax25_address;
 	rose_callsign = null_ax25_address;
 
 
-	dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+	dev_rose = kzalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
 	if (dev_rose == NULL) {
 	if (dev_rose == NULL) {
 		printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
 		printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
 		rc = -ENOMEM;
 		rc = -ENOMEM;
 		goto out_proto_unregister;
 		goto out_proto_unregister;
 	}
 	}
 
 
-	memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*));
 	for (i = 0; i < rose_ndevs; i++) {
 	for (i = 0; i < rose_ndevs; i++) {
 		struct net_device *dev;
 		struct net_device *dev;
 		char name[IFNAMSIZ];
 		char name[IFNAMSIZ];

+ 1 - 1
net/sched/act_api.c

@@ -602,8 +602,8 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
 	return err;
 	return err;
 
 
 rtattr_failure:
 rtattr_failure:
-	module_put(a->ops->owner);
 nlmsg_failure:
 nlmsg_failure:
+	module_put(a->ops->owner);
 err_out:
 err_out:
 	kfree_skb(skb);
 	kfree_skb(skb);
 	kfree(a);
 	kfree(a);