aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bnx2x/bnx2x.h4
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c1
-rw-r--r--drivers/net/bnx2x/bnx2x_stats.c37
-rw-r--r--drivers/net/bonding/bond_alb.c2
-rw-r--r--drivers/net/igb/igb_main.c9
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c9
-rw-r--r--drivers/net/macvlan.c10
-rw-r--r--drivers/net/macvtap.c18
-rw-r--r--drivers/net/s2io.h2
-rw-r--r--drivers/net/tun.c14
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h1
-rw-r--r--drivers/net/wimax/i2400m/usb.c2
-rw-r--r--include/linux/if_macvlan.h2
-rw-r--r--include/net/tc_act/tc_mirred.h1
-rw-r--r--net/core/dev.c1
-rw-r--r--net/core/skbuff.c7
-rw-r--r--net/ipv6/addrconf.c14
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/sched/act_mirred.c43
19 files changed, 147 insertions, 32 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 817b0887f8cd..53af9c93e75c 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -863,6 +863,10 @@ struct bnx2x {
863 863
864 /* used to synchronize stats collecting */ 864 /* used to synchronize stats collecting */
865 int stats_state; 865 int stats_state;
866
867 /* used for synchronization of concurrent threads statistics handling */
868 spinlock_t stats_lock;
869
866 /* used by dmae command loader */ 870 /* used by dmae command loader */
867 struct dmae_command stats_dmae; 871 struct dmae_command stats_dmae;
868 int executer_idx; 872 int executer_idx;
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 75568f111754..b4ec2b02a465 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -6714,6 +6714,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
6714 6714
6715 mutex_init(&bp->port.phy_mutex); 6715 mutex_init(&bp->port.phy_mutex);
6716 mutex_init(&bp->fw_mb_mutex); 6716 mutex_init(&bp->fw_mb_mutex);
6717 spin_lock_init(&bp->stats_lock);
6717#ifdef BCM_CNIC 6718#ifdef BCM_CNIC
6718 mutex_init(&bp->cnic_mutex); 6719 mutex_init(&bp->cnic_mutex);
6719#endif 6720#endif
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index 3f5127720423..c74724461020 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -156,6 +156,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
156 struct eth_query_ramrod_data ramrod_data = {0}; 156 struct eth_query_ramrod_data ramrod_data = {0};
157 int i, rc; 157 int i, rc;
158 158
159 spin_lock_bh(&bp->stats_lock);
160
159 ramrod_data.drv_counter = bp->stats_counter++; 161 ramrod_data.drv_counter = bp->stats_counter++;
160 ramrod_data.collect_port = bp->port.pmf ? 1 : 0; 162 ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
161 for_each_queue(bp, i) 163 for_each_queue(bp, i)
@@ -169,6 +171,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
169 bp->spq_left++; 171 bp->spq_left++;
170 bp->stats_pending = 1; 172 bp->stats_pending = 1;
171 } 173 }
174
175 spin_unlock_bh(&bp->stats_lock);
172 } 176 }
173} 177}
174 178
@@ -734,6 +738,14 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
734 struct host_func_stats *fstats = bnx2x_sp(bp, func_stats); 738 struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
735 struct bnx2x_eth_stats *estats = &bp->eth_stats; 739 struct bnx2x_eth_stats *estats = &bp->eth_stats;
736 int i; 740 int i;
741 u16 cur_stats_counter;
742
743 /* Make sure we use the value of the counter
744 * used for sending the last stats ramrod.
745 */
746 spin_lock_bh(&bp->stats_lock);
747 cur_stats_counter = bp->stats_counter - 1;
748 spin_unlock_bh(&bp->stats_lock);
737 749
738 memcpy(&(fstats->total_bytes_received_hi), 750 memcpy(&(fstats->total_bytes_received_hi),
739 &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi), 751 &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
@@ -761,25 +773,22 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
761 u32 diff; 773 u32 diff;
762 774
763 /* are storm stats valid? */ 775 /* are storm stats valid? */
764 if ((u16)(le16_to_cpu(xclient->stats_counter) + 1) != 776 if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
765 bp->stats_counter) {
766 DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm" 777 DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
767 " xstorm counter (0x%x) != stats_counter (0x%x)\n", 778 " xstorm counter (0x%x) != stats_counter (0x%x)\n",
768 i, xclient->stats_counter, bp->stats_counter); 779 i, xclient->stats_counter, cur_stats_counter + 1);
769 return -1; 780 return -1;
770 } 781 }
771 if ((u16)(le16_to_cpu(tclient->stats_counter) + 1) != 782 if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
772 bp->stats_counter) {
773 DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm" 783 DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
774 " tstorm counter (0x%x) != stats_counter (0x%x)\n", 784 " tstorm counter (0x%x) != stats_counter (0x%x)\n",
775 i, tclient->stats_counter, bp->stats_counter); 785 i, tclient->stats_counter, cur_stats_counter + 1);
776 return -2; 786 return -2;
777 } 787 }
778 if ((u16)(le16_to_cpu(uclient->stats_counter) + 1) != 788 if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
779 bp->stats_counter) {
780 DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm" 789 DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
781 " ustorm counter (0x%x) != stats_counter (0x%x)\n", 790 " ustorm counter (0x%x) != stats_counter (0x%x)\n",
782 i, uclient->stats_counter, bp->stats_counter); 791 i, uclient->stats_counter, cur_stats_counter + 1);
783 return -4; 792 return -4;
784 } 793 }
785 794
@@ -1216,16 +1225,18 @@ static const struct {
1216 1225
1217void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) 1226void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
1218{ 1227{
1219 enum bnx2x_stats_state state = bp->stats_state; 1228 enum bnx2x_stats_state state;
1220 1229
1221 if (unlikely(bp->panic)) 1230 if (unlikely(bp->panic))
1222 return; 1231 return;
1223 1232
1224 bnx2x_stats_stm[state][event].action(bp); 1233 /* Protect a state change flow */
1234 spin_lock_bh(&bp->stats_lock);
1235 state = bp->stats_state;
1225 bp->stats_state = bnx2x_stats_stm[state][event].next_state; 1236 bp->stats_state = bnx2x_stats_stm[state][event].next_state;
1237 spin_unlock_bh(&bp->stats_lock);
1226 1238
1227 /* Make sure the state has been "changed" */ 1239 bnx2x_stats_stm[state][event].action(bp);
1228 smp_wmb();
1229 1240
1230 if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) 1241 if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
1231 DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", 1242 DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index e3b35d0b4284..c746b331771d 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -815,7 +815,7 @@ static int rlb_initialize(struct bonding *bond)
815 815
816 /*initialize packet type*/ 816 /*initialize packet type*/
817 pk_type->type = cpu_to_be16(ETH_P_ARP); 817 pk_type->type = cpu_to_be16(ETH_P_ARP);
818 pk_type->dev = NULL; 818 pk_type->dev = bond->dev;
819 pk_type->func = rlb_arp_recv; 819 pk_type->func = rlb_arp_recv;
820 820
821 /* register to receive ARPs */ 821 /* register to receive ARPs */
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 94656179441d..667b527b0312 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1722,6 +1722,15 @@ static int __devinit igb_probe(struct pci_dev *pdev,
1722 u16 eeprom_apme_mask = IGB_EEPROM_APME; 1722 u16 eeprom_apme_mask = IGB_EEPROM_APME;
1723 u32 part_num; 1723 u32 part_num;
1724 1724
1725 /* Catch broken hardware that put the wrong VF device ID in
1726 * the PCIe SR-IOV capability.
1727 */
1728 if (pdev->is_virtfn) {
1729 WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
1730 pci_name(pdev), pdev->vendor, pdev->device);
1731 return -EINVAL;
1732 }
1733
1725 err = pci_enable_device_mem(pdev); 1734 err = pci_enable_device_mem(pdev);
1726 if (err) 1735 if (err)
1727 return err; 1736 return err;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index e92acbf5a307..7d6a415bcf88 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -6539,6 +6539,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
6539#endif 6539#endif
6540 u32 part_num, eec; 6540 u32 part_num, eec;
6541 6541
6542 /* Catch broken hardware that put the wrong VF device ID in
6543 * the PCIe SR-IOV capability.
6544 */
6545 if (pdev->is_virtfn) {
6546 WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
6547 pci_name(pdev), pdev->vendor, pdev->device);
6548 return -EINVAL;
6549 }
6550
6542 err = pci_enable_device_mem(pdev); 6551 err = pci_enable_device_mem(pdev);
6543 if (err) 6552 if (err)
6544 return err; 6553 return err;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 1b28aaec0a5a..6e9da96a87b2 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -515,7 +515,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
515 .ndo_validate_addr = eth_validate_addr, 515 .ndo_validate_addr = eth_validate_addr,
516}; 516};
517 517
518static void macvlan_setup(struct net_device *dev) 518void macvlan_common_setup(struct net_device *dev)
519{ 519{
520 ether_setup(dev); 520 ether_setup(dev);
521 521
@@ -524,6 +524,12 @@ static void macvlan_setup(struct net_device *dev)
524 dev->destructor = free_netdev; 524 dev->destructor = free_netdev;
525 dev->header_ops = &macvlan_hard_header_ops, 525 dev->header_ops = &macvlan_hard_header_ops,
526 dev->ethtool_ops = &macvlan_ethtool_ops; 526 dev->ethtool_ops = &macvlan_ethtool_ops;
527}
528EXPORT_SYMBOL_GPL(macvlan_common_setup);
529
530static void macvlan_setup(struct net_device *dev)
531{
532 macvlan_common_setup(dev);
527 dev->tx_queue_len = 0; 533 dev->tx_queue_len = 0;
528} 534}
529 535
@@ -735,7 +741,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
735 /* common fields */ 741 /* common fields */
736 ops->priv_size = sizeof(struct macvlan_dev); 742 ops->priv_size = sizeof(struct macvlan_dev);
737 ops->get_tx_queues = macvlan_get_tx_queues; 743 ops->get_tx_queues = macvlan_get_tx_queues;
738 ops->setup = macvlan_setup;
739 ops->validate = macvlan_validate; 744 ops->validate = macvlan_validate;
740 ops->maxtype = IFLA_MACVLAN_MAX; 745 ops->maxtype = IFLA_MACVLAN_MAX;
741 ops->policy = macvlan_policy; 746 ops->policy = macvlan_policy;
@@ -749,6 +754,7 @@ EXPORT_SYMBOL_GPL(macvlan_link_register);
749 754
750static struct rtnl_link_ops macvlan_link_ops = { 755static struct rtnl_link_ops macvlan_link_ops = {
751 .kind = "macvlan", 756 .kind = "macvlan",
757 .setup = macvlan_setup,
752 .newlink = macvlan_newlink, 758 .newlink = macvlan_newlink,
753 .dellink = macvlan_dellink, 759 .dellink = macvlan_dellink,
754}; 760};
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 2b4d59b58b2c..3b1c54a9c6ef 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -180,11 +180,18 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
180{ 180{
181 struct macvtap_queue *q = macvtap_get_queue(dev, skb); 181 struct macvtap_queue *q = macvtap_get_queue(dev, skb);
182 if (!q) 182 if (!q)
183 return -ENOLINK; 183 goto drop;
184
185 if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len)
186 goto drop;
184 187
185 skb_queue_tail(&q->sk.sk_receive_queue, skb); 188 skb_queue_tail(&q->sk.sk_receive_queue, skb);
186 wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); 189 wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
187 return 0; 190 return NET_RX_SUCCESS;
191
192drop:
193 kfree_skb(skb);
194 return NET_RX_DROP;
188} 195}
189 196
190/* 197/*
@@ -235,8 +242,15 @@ static void macvtap_dellink(struct net_device *dev,
235 macvlan_dellink(dev, head); 242 macvlan_dellink(dev, head);
236} 243}
237 244
245static void macvtap_setup(struct net_device *dev)
246{
247 macvlan_common_setup(dev);
248 dev->tx_queue_len = TUN_READQ_SIZE;
249}
250
238static struct rtnl_link_ops macvtap_link_ops __read_mostly = { 251static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
239 .kind = "macvtap", 252 .kind = "macvtap",
253 .setup = macvtap_setup,
240 .newlink = macvtap_newlink, 254 .newlink = macvtap_newlink,
241 .dellink = macvtap_dellink, 255 .dellink = macvtap_dellink,
242}; 256};
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 3645fb3673db..0af033533905 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -65,7 +65,7 @@ static int debug_level = ERR_DBG;
65 65
66/* DEBUG message print. */ 66/* DEBUG message print. */
67#define DBG_PRINT(dbg_level, fmt, args...) do { \ 67#define DBG_PRINT(dbg_level, fmt, args...) do { \
68 if (dbg_level >= debug_level) \ 68 if (dbg_level <= debug_level) \
69 pr_info(fmt, ##args); \ 69 pr_info(fmt, ##args); \
70 } while (0) 70 } while (0)
71 71
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 6ad6fe706312..63042596f0cf 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -736,8 +736,18 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
736 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 736 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
737 else if (sinfo->gso_type & SKB_GSO_UDP) 737 else if (sinfo->gso_type & SKB_GSO_UDP)
738 gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; 738 gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
739 else 739 else {
740 BUG(); 740 printk(KERN_ERR "tun: unexpected GSO type: "
741 "0x%x, gso_size %d, hdr_len %d\n",
742 sinfo->gso_type, gso.gso_size,
743 gso.hdr_len);
744 print_hex_dump(KERN_ERR, "tun: ",
745 DUMP_PREFIX_NONE,
746 16, 1, skb->head,
747 min((int)gso.hdr_len, 64), true);
748 WARN_ON_ONCE(1);
749 return -EINVAL;
750 }
741 if (sinfo->gso_type & SKB_GSO_TCP_ECN) 751 if (sinfo->gso_type & SKB_GSO_TCP_ECN)
742 gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; 752 gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
743 } else 753 } else
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
index 2d7c96d7e865..eb80243e22df 100644
--- a/drivers/net/wimax/i2400m/i2400m-usb.h
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -152,6 +152,7 @@ enum {
152 /* Device IDs */ 152 /* Device IDs */
153 USB_DEVICE_ID_I6050 = 0x0186, 153 USB_DEVICE_ID_I6050 = 0x0186,
154 USB_DEVICE_ID_I6050_2 = 0x0188, 154 USB_DEVICE_ID_I6050_2 = 0x0188,
155 USB_DEVICE_ID_I6250 = 0x0187,
155}; 156};
156 157
157 158
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 0d5081d77dc0..d3365ac85dde 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -491,6 +491,7 @@ int i2400mu_probe(struct usb_interface *iface,
491 switch (id->idProduct) { 491 switch (id->idProduct) {
492 case USB_DEVICE_ID_I6050: 492 case USB_DEVICE_ID_I6050:
493 case USB_DEVICE_ID_I6050_2: 493 case USB_DEVICE_ID_I6050_2:
494 case USB_DEVICE_ID_I6250:
494 i2400mu->i6050 = 1; 495 i2400mu->i6050 = 1;
495 break; 496 break;
496 default: 497 default:
@@ -739,6 +740,7 @@ static
739struct usb_device_id i2400mu_id_table[] = { 740struct usb_device_id i2400mu_id_table[] = {
740 { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, 741 { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
741 { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, 742 { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
743 { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },
742 { USB_DEVICE(0x8086, 0x0181) }, 744 { USB_DEVICE(0x8086, 0x0181) },
743 { USB_DEVICE(0x8086, 0x1403) }, 745 { USB_DEVICE(0x8086, 0x1403) },
744 { USB_DEVICE(0x8086, 0x1405) }, 746 { USB_DEVICE(0x8086, 0x1405) },
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index e24ce6ea1fa3..35280b302290 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -72,6 +72,8 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
72 } 72 }
73} 73}
74 74
75extern void macvlan_common_setup(struct net_device *dev);
76
75extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, 77extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
76 struct nlattr *tb[], struct nlattr *data[], 78 struct nlattr *tb[], struct nlattr *data[],
77 int (*receive)(struct sk_buff *skb), 79 int (*receive)(struct sk_buff *skb),
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
index ceac661cdfd5..cfe2943690ff 100644
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -9,6 +9,7 @@ struct tcf_mirred {
9 int tcfm_ifindex; 9 int tcfm_ifindex;
10 int tcfm_ok_push; 10 int tcfm_ok_push;
11 struct net_device *tcfm_dev; 11 struct net_device *tcfm_dev;
12 struct list_head tcfm_list;
12}; 13};
13#define to_mirred(pc) \ 14#define to_mirred(pc) \
14 container_of(pc, struct tcf_mirred, common) 15 container_of(pc, struct tcf_mirred, common)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6e1b4370781c..b74fcd3e9365 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1484,6 +1484,7 @@ static inline void net_timestamp_check(struct sk_buff *skb)
1484int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) 1484int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1485{ 1485{
1486 skb_orphan(skb); 1486 skb_orphan(skb);
1487 nf_reset(skb);
1487 1488
1488 if (!(dev->flags & IFF_UP) || 1489 if (!(dev->flags & IFF_UP) ||
1489 (skb->len > (dev->mtu + dev->hard_header_len))) { 1490 (skb->len > (dev->mtu + dev->hard_header_len))) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7da58a25ad92..3a2513f0d0c3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -843,7 +843,9 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
843 skb->network_header += off; 843 skb->network_header += off;
844 if (skb_mac_header_was_set(skb)) 844 if (skb_mac_header_was_set(skb))
845 skb->mac_header += off; 845 skb->mac_header += off;
846 skb->csum_start += nhead; 846 /* Only adjust this if it actually is csum_start rather than csum */
847 if (skb->ip_summed == CHECKSUM_PARTIAL)
848 skb->csum_start += nhead;
847 skb->cloned = 0; 849 skb->cloned = 0;
848 skb->hdr_len = 0; 850 skb->hdr_len = 0;
849 skb->nohdr = 0; 851 skb->nohdr = 0;
@@ -930,7 +932,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
930 copy_skb_header(n, skb); 932 copy_skb_header(n, skb);
931 933
932 off = newheadroom - oldheadroom; 934 off = newheadroom - oldheadroom;
933 n->csum_start += off; 935 if (n->ip_summed == CHECKSUM_PARTIAL)
936 n->csum_start += off;
934#ifdef NET_SKBUFF_DATA_USES_OFFSET 937#ifdef NET_SKBUFF_DATA_USES_OFFSET
935 n->transport_header += off; 938 n->transport_header += off;
936 n->network_header += off; 939 n->network_header += off;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e81155d2f251..ab70a3fbcafa 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1763,7 +1763,10 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
1763 1763
1764 idev = ipv6_find_idev(dev); 1764 idev = ipv6_find_idev(dev);
1765 if (!idev) 1765 if (!idev)
1766 return NULL; 1766 return ERR_PTR(-ENOBUFS);
1767
1768 if (idev->cnf.disable_ipv6)
1769 return ERR_PTR(-EACCES);
1767 1770
1768 /* Add default multicast route */ 1771 /* Add default multicast route */
1769 addrconf_add_mroute(dev); 1772 addrconf_add_mroute(dev);
@@ -2132,8 +2135,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2132 if (!dev) 2135 if (!dev)
2133 return -ENODEV; 2136 return -ENODEV;
2134 2137
2135 if ((idev = addrconf_add_dev(dev)) == NULL) 2138 idev = addrconf_add_dev(dev);
2136 return -ENOBUFS; 2139 if (IS_ERR(idev))
2140 return PTR_ERR(idev);
2137 2141
2138 scope = ipv6_addr_scope(pfx); 2142 scope = ipv6_addr_scope(pfx);
2139 2143
@@ -2380,7 +2384,7 @@ static void addrconf_dev_config(struct net_device *dev)
2380 } 2384 }
2381 2385
2382 idev = addrconf_add_dev(dev); 2386 idev = addrconf_add_dev(dev);
2383 if (idev == NULL) 2387 if (IS_ERR(idev))
2384 return; 2388 return;
2385 2389
2386 memset(&addr, 0, sizeof(struct in6_addr)); 2390 memset(&addr, 0, sizeof(struct in6_addr));
@@ -2471,7 +2475,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
2471 ASSERT_RTNL(); 2475 ASSERT_RTNL();
2472 2476
2473 idev = addrconf_add_dev(dev); 2477 idev = addrconf_add_dev(dev);
2474 if (!idev) { 2478 if (IS_ERR(idev)) {
2475 printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); 2479 printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
2476 return; 2480 return;
2477 } 2481 }
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a3f3325df9f2..db4d9340c846 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -632,7 +632,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
632 skb->dev = sta->sdata->dev; 632 skb->dev = sta->sdata->dev;
633 skb->protocol = eth_type_trans(skb, sta->sdata->dev); 633 skb->protocol = eth_type_trans(skb, sta->sdata->dev);
634 memset(skb->cb, 0, sizeof(skb->cb)); 634 memset(skb->cb, 0, sizeof(skb->cb));
635 netif_rx(skb); 635 netif_rx_ni(skb);
636} 636}
637 637
638static void sta_apply_parameters(struct ieee80211_local *local, 638static void sta_apply_parameters(struct ieee80211_local *local,
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index a16b0175f890..11f195af2da0 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -33,6 +33,7 @@
33static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1]; 33static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
34static u32 mirred_idx_gen; 34static u32 mirred_idx_gen;
35static DEFINE_RWLOCK(mirred_lock); 35static DEFINE_RWLOCK(mirred_lock);
36static LIST_HEAD(mirred_list);
36 37
37static struct tcf_hashinfo mirred_hash_info = { 38static struct tcf_hashinfo mirred_hash_info = {
38 .htab = tcf_mirred_ht, 39 .htab = tcf_mirred_ht,
@@ -47,7 +48,9 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
47 m->tcf_bindcnt--; 48 m->tcf_bindcnt--;
48 m->tcf_refcnt--; 49 m->tcf_refcnt--;
49 if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) { 50 if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
50 dev_put(m->tcfm_dev); 51 list_del(&m->tcfm_list);
52 if (m->tcfm_dev)
53 dev_put(m->tcfm_dev);
51 tcf_hash_destroy(&m->common, &mirred_hash_info); 54 tcf_hash_destroy(&m->common, &mirred_hash_info);
52 return 1; 55 return 1;
53 } 56 }
@@ -134,8 +137,10 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
134 m->tcfm_ok_push = ok_push; 137 m->tcfm_ok_push = ok_push;
135 } 138 }
136 spin_unlock_bh(&m->tcf_lock); 139 spin_unlock_bh(&m->tcf_lock);
137 if (ret == ACT_P_CREATED) 140 if (ret == ACT_P_CREATED) {
141 list_add(&m->tcfm_list, &mirred_list);
138 tcf_hash_insert(pc, &mirred_hash_info); 142 tcf_hash_insert(pc, &mirred_hash_info);
143 }
139 144
140 return ret; 145 return ret;
141} 146}
@@ -164,9 +169,14 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
164 m->tcf_bstats.packets++; 169 m->tcf_bstats.packets++;
165 170
166 dev = m->tcfm_dev; 171 dev = m->tcfm_dev;
172 if (!dev) {
173 printk_once(KERN_NOTICE "tc mirred: target device is gone\n");
174 goto out;
175 }
176
167 if (!(dev->flags & IFF_UP)) { 177 if (!(dev->flags & IFF_UP)) {
168 if (net_ratelimit()) 178 if (net_ratelimit())
169 pr_notice("tc mirred to Houston: device %s is gone!\n", 179 pr_notice("tc mirred to Houston: device %s is down\n",
170 dev->name); 180 dev->name);
171 goto out; 181 goto out;
172 } 182 }
@@ -230,6 +240,28 @@ nla_put_failure:
230 return -1; 240 return -1;
231} 241}
232 242
243static int mirred_device_event(struct notifier_block *unused,
244 unsigned long event, void *ptr)
245{
246 struct net_device *dev = ptr;
247 struct tcf_mirred *m;
248
249 if (event == NETDEV_UNREGISTER)
250 list_for_each_entry(m, &mirred_list, tcfm_list) {
251 if (m->tcfm_dev == dev) {
252 dev_put(dev);
253 m->tcfm_dev = NULL;
254 }
255 }
256
257 return NOTIFY_DONE;
258}
259
260static struct notifier_block mirred_device_notifier = {
261 .notifier_call = mirred_device_event,
262};
263
264
233static struct tc_action_ops act_mirred_ops = { 265static struct tc_action_ops act_mirred_ops = {
234 .kind = "mirred", 266 .kind = "mirred",
235 .hinfo = &mirred_hash_info, 267 .hinfo = &mirred_hash_info,
@@ -250,12 +282,17 @@ MODULE_LICENSE("GPL");
250 282
251static int __init mirred_init_module(void) 283static int __init mirred_init_module(void)
252{ 284{
285 int err = register_netdevice_notifier(&mirred_device_notifier);
286 if (err)
287 return err;
288
253 pr_info("Mirror/redirect action on\n"); 289 pr_info("Mirror/redirect action on\n");
254 return tcf_register_action(&act_mirred_ops); 290 return tcf_register_action(&act_mirred_ops);
255} 291}
256 292
257static void __exit mirred_cleanup_module(void) 293static void __exit mirred_cleanup_module(void)
258{ 294{
295 unregister_netdevice_notifier(&mirred_device_notifier);
259 tcf_unregister_action(&act_mirred_ops); 296 tcf_unregister_action(&act_mirred_ops);
260} 297}
261 298