aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
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 a0124eb7dbe..77e87aff419 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 e55171f184f..da0cc2e6b25 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 7ad88e5e711..8d07c973409 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 4ebc6feee25..981ff1eef28 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 6bcb8fc71cb..fc1a81ca79a 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 3e30548ac32..b6b07c93924 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 58d23a57250..06814b6216d 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 5ab923e51af..47975e363fc 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 f49476e2d88..221224e7250 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 788a12c1eb5..2ab785064b7 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);