aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 21:09:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 21:09:01 -0400
commit1e30c1b3866968ff584ae3cd3909ef93957bb215 (patch)
tree0ee70a264f7bed4047f68ed3aeb68d6c4cf4e136 /net
parenta1857ebe752d77d96c89d964500a9528df6d320e (diff)
parentc7109986db3c945f50ceed884a30e0fd8af3b89b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking updates and fixes from David Miller: 1) Reinstate the no-ref optimization for input route lookups in ipv4 to fix some routing cache removal perf regressions. 2) Make TCP socket pre-demux work on ipv6 side too, from Eric Dumazet. 3) Get RX hash value from correct place in be2net driver, from Sarveshwar Bandi. 4) Validation of FIB cached routes missing critical check, from Eric Dumazet. 5) EEH support in mlx4 driver, from Kleber Sacilotto de Souza. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (23 commits) ipv6: Early TCP socket demux ipv4: Fix input route performance regression. pch_gbe: vlan skb len fix pch_gbe: add extra clean tx pch_gbe: fix transmit watchdog timeout ixgbe: fix panic while dumping packets on Tx hang with IOMMU be2net: Fix to parse RSS hash from Receive completions correctly. net/mlx4_en: Limit the RFS filter IDs to be < RPS_NO_FILTER hyperv: Add error handling to rndis_filter_device_add() hyperv: Add a check for ring_size value ipv4: rt_cache_valid must check expired routes net/pch_gpe: Cannot disable ethernet autonegation qeth: repair crash in qeth_l3_vlan_rx_kill_vid() netiucv: cleanup attribute usage net: wiznet add missing HAS_IOMEM dependency be2net: Missing byteswap in be_get_fw_log_level causes oops on PowerPC mlx4: Add support for EEH error recovery cdc-ncm: tag Ericsson WWAN devices (eg F5521gw) with FLAG_WWAN wanmain: comparing array with NULL caif: fix NULL pointer check ...
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/fib_semantics.c4
-rw-r--r--net/ipv4/ip_fragment.c4
-rw-r--r--net/ipv4/ip_input.c10
-rw-r--r--net/ipv4/route.c56
-rw-r--r--net/ipv4/tcp_ipv4.c9
-rw-r--r--net/ipv4/xfrm4_input.c4
-rw-r--r--net/ipv6/ip6_input.c13
-rw-r--r--net/ipv6/tcp_ipv6.c38
-rw-r--r--net/wanrouter/wanmain.c51
10 files changed, 115 insertions, 76 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index a0124eb7dbea..77e87aff419a 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -827,7 +827,7 @@ static int arp_process(struct sk_buff *skb)
827 } 827 }
828 828
829 if (arp->ar_op == htons(ARPOP_REQUEST) && 829 if (arp->ar_op == htons(ARPOP_REQUEST) &&
830 ip_route_input(skb, tip, sip, 0, dev) == 0) { 830 ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
831 831
832 rt = skb_rtable(skb); 832 rt = skb_rtable(skb);
833 addr_type = rt->rt_type; 833 addr_type = rt->rt_type;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e55171f184f9..da0cc2e6b250 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -172,9 +172,9 @@ static void free_fib_info_rcu(struct rcu_head *head)
172 if (nexthop_nh->nh_exceptions) 172 if (nexthop_nh->nh_exceptions)
173 free_nh_exceptions(nexthop_nh); 173 free_nh_exceptions(nexthop_nh);
174 if (nexthop_nh->nh_rth_output) 174 if (nexthop_nh->nh_rth_output)
175 dst_release(&nexthop_nh->nh_rth_output->dst); 175 dst_free(&nexthop_nh->nh_rth_output->dst);
176 if (nexthop_nh->nh_rth_input) 176 if (nexthop_nh->nh_rth_input)
177 dst_release(&nexthop_nh->nh_rth_input->dst); 177 dst_free(&nexthop_nh->nh_rth_input->dst);
178 } endfor_nexthops(fi); 178 } endfor_nexthops(fi);
179 179
180 release_net(fi->fib_net); 180 release_net(fi->fib_net);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 7ad88e5e7110..8d07c973409c 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -258,8 +258,8 @@ static void ip_expire(unsigned long arg)
258 /* skb dst is stale, drop it, and perform route lookup again */ 258 /* skb dst is stale, drop it, and perform route lookup again */
259 skb_dst_drop(head); 259 skb_dst_drop(head);
260 iph = ip_hdr(head); 260 iph = ip_hdr(head);
261 err = ip_route_input(head, iph->daddr, iph->saddr, 261 err = ip_route_input_noref(head, iph->daddr, iph->saddr,
262 iph->tos, head->dev); 262 iph->tos, head->dev);
263 if (err) 263 if (err)
264 goto out_rcu_unlock; 264 goto out_rcu_unlock;
265 265
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 4ebc6feee250..981ff1eef28c 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -314,6 +314,7 @@ drop:
314} 314}
315 315
316int sysctl_ip_early_demux __read_mostly = 1; 316int sysctl_ip_early_demux __read_mostly = 1;
317EXPORT_SYMBOL(sysctl_ip_early_demux);
317 318
318static int ip_rcv_finish(struct sk_buff *skb) 319static int ip_rcv_finish(struct sk_buff *skb)
319{ 320{
@@ -326,8 +327,11 @@ static int ip_rcv_finish(struct sk_buff *skb)
326 327
327 rcu_read_lock(); 328 rcu_read_lock();
328 ipprot = rcu_dereference(inet_protos[protocol]); 329 ipprot = rcu_dereference(inet_protos[protocol]);
329 if (ipprot && ipprot->early_demux) 330 if (ipprot && ipprot->early_demux) {
330 ipprot->early_demux(skb); 331 ipprot->early_demux(skb);
332 /* must reload iph, skb->head might have changed */
333 iph = ip_hdr(skb);
334 }
331 rcu_read_unlock(); 335 rcu_read_unlock();
332 } 336 }
333 337
@@ -336,8 +340,8 @@ static int ip_rcv_finish(struct sk_buff *skb)
336 * how the packet travels inside Linux networking. 340 * how the packet travels inside Linux networking.
337 */ 341 */
338 if (!skb_dst(skb)) { 342 if (!skb_dst(skb)) {
339 int err = ip_route_input(skb, iph->daddr, iph->saddr, 343 int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
340 iph->tos, skb->dev); 344 iph->tos, skb->dev);
341 if (unlikely(err)) { 345 if (unlikely(err)) {
342 if (err == -EXDEV) 346 if (err == -EXDEV)
343 NET_INC_STATS_BH(dev_net(skb->dev), 347 NET_INC_STATS_BH(dev_net(skb->dev),
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6bcb8fc71cbc..fc1a81ca79a7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -444,7 +444,7 @@ static inline int ip_rt_proc_init(void)
444} 444}
445#endif /* CONFIG_PROC_FS */ 445#endif /* CONFIG_PROC_FS */
446 446
447static inline int rt_is_expired(struct rtable *rth) 447static inline bool rt_is_expired(const struct rtable *rth)
448{ 448{
449 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 449 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
450} 450}
@@ -1199,10 +1199,9 @@ restart:
1199 fnhe->fnhe_stamp = jiffies; 1199 fnhe->fnhe_stamp = jiffies;
1200} 1200}
1201 1201
1202static inline void rt_release_rcu(struct rcu_head *head) 1202static inline void rt_free(struct rtable *rt)
1203{ 1203{
1204 struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); 1204 call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
1205 dst_release(dst);
1206} 1205}
1207 1206
1208static void rt_cache_route(struct fib_nh *nh, struct rtable *rt) 1207static void rt_cache_route(struct fib_nh *nh, struct rtable *rt)
@@ -1216,15 +1215,23 @@ static void rt_cache_route(struct fib_nh *nh, struct rtable *rt)
1216 1215
1217 prev = cmpxchg(p, orig, rt); 1216 prev = cmpxchg(p, orig, rt);
1218 if (prev == orig) { 1217 if (prev == orig) {
1219 dst_clone(&rt->dst);
1220 if (orig) 1218 if (orig)
1221 call_rcu_bh(&orig->dst.rcu_head, rt_release_rcu); 1219 rt_free(orig);
1220 } else {
1221 /* Routes we intend to cache in the FIB nexthop have
1222 * the DST_NOCACHE bit clear. However, if we are
1223 * unsuccessful at storing this route into the cache
1224 * we really need to set it.
1225 */
1226 rt->dst.flags |= DST_NOCACHE;
1222 } 1227 }
1223} 1228}
1224 1229
1225static bool rt_cache_valid(struct rtable *rt) 1230static bool rt_cache_valid(const struct rtable *rt)
1226{ 1231{
1227 return (rt && rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK); 1232 return rt &&
1233 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
1234 !rt_is_expired(rt);
1228} 1235}
1229 1236
1230static void rt_set_nexthop(struct rtable *rt, __be32 daddr, 1237static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
@@ -1243,7 +1250,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
1243#ifdef CONFIG_IP_ROUTE_CLASSID 1250#ifdef CONFIG_IP_ROUTE_CLASSID
1244 rt->dst.tclassid = nh->nh_tclassid; 1251 rt->dst.tclassid = nh->nh_tclassid;
1245#endif 1252#endif
1246 if (!(rt->dst.flags & DST_HOST)) 1253 if (!(rt->dst.flags & DST_NOCACHE))
1247 rt_cache_route(nh, rt); 1254 rt_cache_route(nh, rt);
1248 } 1255 }
1249 1256
@@ -1259,7 +1266,7 @@ static struct rtable *rt_dst_alloc(struct net_device *dev,
1259 bool nopolicy, bool noxfrm, bool will_cache) 1266 bool nopolicy, bool noxfrm, bool will_cache)
1260{ 1267{
1261 return dst_alloc(&ipv4_dst_ops, dev, 1, DST_OBSOLETE_FORCE_CHK, 1268 return dst_alloc(&ipv4_dst_ops, dev, 1, DST_OBSOLETE_FORCE_CHK,
1262 (will_cache ? 0 : DST_HOST) | DST_NOCACHE | 1269 (will_cache ? 0 : (DST_HOST | DST_NOCACHE)) |
1263 (nopolicy ? DST_NOPOLICY : 0) | 1270 (nopolicy ? DST_NOPOLICY : 0) |
1264 (noxfrm ? DST_NOXFRM : 0)); 1271 (noxfrm ? DST_NOXFRM : 0));
1265} 1272}
@@ -1364,8 +1371,7 @@ static void ip_handle_martian_source(struct net_device *dev,
1364static int __mkroute_input(struct sk_buff *skb, 1371static int __mkroute_input(struct sk_buff *skb,
1365 const struct fib_result *res, 1372 const struct fib_result *res,
1366 struct in_device *in_dev, 1373 struct in_device *in_dev,
1367 __be32 daddr, __be32 saddr, u32 tos, 1374 __be32 daddr, __be32 saddr, u32 tos)
1368 struct rtable **result)
1369{ 1375{
1370 struct rtable *rth; 1376 struct rtable *rth;
1371 int err; 1377 int err;
@@ -1416,7 +1422,7 @@ static int __mkroute_input(struct sk_buff *skb,
1416 if (!itag) { 1422 if (!itag) {
1417 rth = FIB_RES_NH(*res).nh_rth_input; 1423 rth = FIB_RES_NH(*res).nh_rth_input;
1418 if (rt_cache_valid(rth)) { 1424 if (rt_cache_valid(rth)) {
1419 dst_hold(&rth->dst); 1425 skb_dst_set_noref(skb, &rth->dst);
1420 goto out; 1426 goto out;
1421 } 1427 }
1422 do_cache = true; 1428 do_cache = true;
@@ -1443,8 +1449,8 @@ static int __mkroute_input(struct sk_buff *skb,
1443 rth->dst.output = ip_output; 1449 rth->dst.output = ip_output;
1444 1450
1445 rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag); 1451 rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag);
1452 skb_dst_set(skb, &rth->dst);
1446out: 1453out:
1447 *result = rth;
1448 err = 0; 1454 err = 0;
1449 cleanup: 1455 cleanup:
1450 return err; 1456 return err;
@@ -1456,21 +1462,13 @@ static int ip_mkroute_input(struct sk_buff *skb,
1456 struct in_device *in_dev, 1462 struct in_device *in_dev,
1457 __be32 daddr, __be32 saddr, u32 tos) 1463 __be32 daddr, __be32 saddr, u32 tos)
1458{ 1464{
1459 struct rtable *rth = NULL;
1460 int err;
1461
1462#ifdef CONFIG_IP_ROUTE_MULTIPATH 1465#ifdef CONFIG_IP_ROUTE_MULTIPATH
1463 if (res->fi && res->fi->fib_nhs > 1) 1466 if (res->fi && res->fi->fib_nhs > 1)
1464 fib_select_multipath(res); 1467 fib_select_multipath(res);
1465#endif 1468#endif
1466 1469
1467 /* create a routing cache entry */ 1470 /* create a routing cache entry */
1468 err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth); 1471 return __mkroute_input(skb, res, in_dev, daddr, saddr, tos);
1469 if (err)
1470 return err;
1471
1472 skb_dst_set(skb, &rth->dst);
1473 return 0;
1474} 1472}
1475 1473
1476/* 1474/*
@@ -1586,8 +1584,9 @@ local_input:
1586 if (!itag) { 1584 if (!itag) {
1587 rth = FIB_RES_NH(res).nh_rth_input; 1585 rth = FIB_RES_NH(res).nh_rth_input;
1588 if (rt_cache_valid(rth)) { 1586 if (rt_cache_valid(rth)) {
1589 dst_hold(&rth->dst); 1587 skb_dst_set_noref(skb, &rth->dst);
1590 goto set_and_out; 1588 err = 0;
1589 goto out;
1591 } 1590 }
1592 do_cache = true; 1591 do_cache = true;
1593 } 1592 }
@@ -1618,7 +1617,6 @@ local_input:
1618 } 1617 }
1619 if (do_cache) 1618 if (do_cache)
1620 rt_cache_route(&FIB_RES_NH(res), rth); 1619 rt_cache_route(&FIB_RES_NH(res), rth);
1621set_and_out:
1622 skb_dst_set(skb, &rth->dst); 1620 skb_dst_set(skb, &rth->dst);
1623 err = 0; 1621 err = 0;
1624 goto out; 1622 goto out;
@@ -1656,8 +1654,8 @@ martian_source_keep_err:
1656 goto out; 1654 goto out;
1657} 1655}
1658 1656
1659int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, 1657int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1660 u8 tos, struct net_device *dev) 1658 u8 tos, struct net_device *dev)
1661{ 1659{
1662 int res; 1660 int res;
1663 1661
@@ -1700,7 +1698,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1700 rcu_read_unlock(); 1698 rcu_read_unlock();
1701 return res; 1699 return res;
1702} 1700}
1703EXPORT_SYMBOL(ip_route_input); 1701EXPORT_SYMBOL(ip_route_input_noref);
1704 1702
1705/* called with rcu_read_lock() */ 1703/* called with rcu_read_lock() */
1706static struct rtable *__mkroute_output(const struct fib_result *res, 1704static struct rtable *__mkroute_output(const struct fib_result *res,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3e30548ac32a..b6b07c93924c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1686,7 +1686,6 @@ void tcp_v4_early_demux(struct sk_buff *skb)
1686 struct net *net = dev_net(skb->dev); 1686 struct net *net = dev_net(skb->dev);
1687 const struct iphdr *iph; 1687 const struct iphdr *iph;
1688 const struct tcphdr *th; 1688 const struct tcphdr *th;
1689 struct net_device *dev;
1690 struct sock *sk; 1689 struct sock *sk;
1691 1690
1692 if (skb->pkt_type != PACKET_HOST) 1691 if (skb->pkt_type != PACKET_HOST)
@@ -1701,14 +1700,10 @@ void tcp_v4_early_demux(struct sk_buff *skb)
1701 if (th->doff < sizeof(struct tcphdr) / 4) 1700 if (th->doff < sizeof(struct tcphdr) / 4)
1702 return; 1701 return;
1703 1702
1704 if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4))
1705 return;
1706
1707 dev = skb->dev;
1708 sk = __inet_lookup_established(net, &tcp_hashinfo, 1703 sk = __inet_lookup_established(net, &tcp_hashinfo,
1709 iph->saddr, th->source, 1704 iph->saddr, th->source,
1710 iph->daddr, ntohs(th->dest), 1705 iph->daddr, ntohs(th->dest),
1711 dev->ifindex); 1706 skb->skb_iif);
1712 if (sk) { 1707 if (sk) {
1713 skb->sk = sk; 1708 skb->sk = sk;
1714 skb->destructor = sock_edemux; 1709 skb->destructor = sock_edemux;
@@ -1718,7 +1713,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
1718 if (dst) 1713 if (dst)
1719 dst = dst_check(dst, 0); 1714 dst = dst_check(dst, 0);
1720 if (dst && 1715 if (dst &&
1721 icsk->rx_dst_ifindex == dev->ifindex) 1716 icsk->rx_dst_ifindex == skb->skb_iif)
1722 skb_dst_set_noref(skb, dst); 1717 skb_dst_set_noref(skb, dst);
1723 } 1718 }
1724 } 1719 }
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 58d23a572509..06814b6216dc 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -27,8 +27,8 @@ static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
27 if (skb_dst(skb) == NULL) { 27 if (skb_dst(skb) == NULL) {
28 const struct iphdr *iph = ip_hdr(skb); 28 const struct iphdr *iph = ip_hdr(skb);
29 29
30 if (ip_route_input(skb, iph->daddr, iph->saddr, 30 if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
31 iph->tos, skb->dev)) 31 iph->tos, skb->dev))
32 goto drop; 32 goto drop;
33 } 33 }
34 return dst_input(skb); 34 return dst_input(skb);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 5ab923e51af3..47975e363fcd 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -47,9 +47,18 @@
47 47
48 48
49 49
50inline int ip6_rcv_finish( struct sk_buff *skb) 50int ip6_rcv_finish(struct sk_buff *skb)
51{ 51{
52 if (skb_dst(skb) == NULL) 52 if (sysctl_ip_early_demux && !skb_dst(skb)) {
53 const struct inet6_protocol *ipprot;
54
55 rcu_read_lock();
56 ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
57 if (ipprot && ipprot->early_demux)
58 ipprot->early_demux(skb);
59 rcu_read_unlock();
60 }
61 if (!skb_dst(skb))
53 ip6_route_input(skb); 62 ip6_route_input(skb);
54 63
55 return dst_input(skb); 64 return dst_input(skb);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f49476e2d884..221224e72507 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1674,6 +1674,43 @@ do_time_wait:
1674 goto discard_it; 1674 goto discard_it;
1675} 1675}
1676 1676
1677static void tcp_v6_early_demux(struct sk_buff *skb)
1678{
1679 const struct ipv6hdr *hdr;
1680 const struct tcphdr *th;
1681 struct sock *sk;
1682
1683 if (skb->pkt_type != PACKET_HOST)
1684 return;
1685
1686 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
1687 return;
1688
1689 hdr = ipv6_hdr(skb);
1690 th = tcp_hdr(skb);
1691
1692 if (th->doff < sizeof(struct tcphdr) / 4)
1693 return;
1694
1695 sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
1696 &hdr->saddr, th->source,
1697 &hdr->daddr, ntohs(th->dest),
1698 inet6_iif(skb));
1699 if (sk) {
1700 skb->sk = sk;
1701 skb->destructor = sock_edemux;
1702 if (sk->sk_state != TCP_TIME_WAIT) {
1703 struct dst_entry *dst = sk->sk_rx_dst;
1704 struct inet_sock *icsk = inet_sk(sk);
1705 if (dst)
1706 dst = dst_check(dst, 0);
1707 if (dst &&
1708 icsk->rx_dst_ifindex == inet6_iif(skb))
1709 skb_dst_set_noref(skb, dst);
1710 }
1711 }
1712}
1713
1677static struct timewait_sock_ops tcp6_timewait_sock_ops = { 1714static struct timewait_sock_ops tcp6_timewait_sock_ops = {
1678 .twsk_obj_size = sizeof(struct tcp6_timewait_sock), 1715 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
1679 .twsk_unique = tcp_twsk_unique, 1716 .twsk_unique = tcp_twsk_unique,
@@ -1984,6 +2021,7 @@ struct proto tcpv6_prot = {
1984}; 2021};
1985 2022
1986static const struct inet6_protocol tcpv6_protocol = { 2023static const struct inet6_protocol tcpv6_protocol = {
2024 .early_demux = tcp_v6_early_demux,
1987 .handler = tcp_v6_rcv, 2025 .handler = tcp_v6_rcv,
1988 .err_handler = tcp_v6_err, 2026 .err_handler = tcp_v6_err,
1989 .gso_send_check = tcp_v6_gso_send_check, 2027 .gso_send_check = tcp_v6_gso_send_check,
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 788a12c1eb5d..2ab785064b7e 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -602,36 +602,31 @@ static int wanrouter_device_new_if(struct wan_device *wandev,
602 * successfully, add it to the interface list. 602 * successfully, add it to the interface list.
603 */ 603 */
604 604
605 if (dev->name == NULL) { 605#ifdef WANDEBUG
606 err = -EINVAL; 606 printk(KERN_INFO "%s: registering interface %s...\n",
607 } else { 607 wanrouter_modname, dev->name);
608#endif
608 609
609 #ifdef WANDEBUG 610 err = register_netdev(dev);
610 printk(KERN_INFO "%s: registering interface %s...\n", 611 if (!err) {
611 wanrouter_modname, dev->name); 612 struct net_device *slave = NULL;
612 #endif 613 unsigned long smp_flags=0;
613 614
614 err = register_netdev(dev); 615 lock_adapter_irq(&wandev->lock, &smp_flags);
615 if (!err) { 616
616 struct net_device *slave = NULL; 617 if (wandev->dev == NULL) {
617 unsigned long smp_flags=0; 618 wandev->dev = dev;
618 619 } else {
619 lock_adapter_irq(&wandev->lock, &smp_flags); 620 for (slave=wandev->dev;
620 621 DEV_TO_SLAVE(slave);
621 if (wandev->dev == NULL) { 622 slave = DEV_TO_SLAVE(slave))
622 wandev->dev = dev; 623 DEV_TO_SLAVE(slave) = dev;
623 } else {
624 for (slave=wandev->dev;
625 DEV_TO_SLAVE(slave);
626 slave = DEV_TO_SLAVE(slave))
627 DEV_TO_SLAVE(slave) = dev;
628 }
629 ++wandev->ndev;
630
631 unlock_adapter_irq(&wandev->lock, &smp_flags);
632 err = 0; /* done !!! */
633 goto out;
634 } 624 }
625 ++wandev->ndev;
626
627 unlock_adapter_irq(&wandev->lock, &smp_flags);
628 err = 0; /* done !!! */
629 goto out;
635 } 630 }
636 if (wandev->del_if) 631 if (wandev->del_if)
637 wandev->del_if(wandev, dev); 632 wandev->del_if(wandev, dev);