diff options
-rw-r--r-- | include/linux/netdevice.h | 4 | ||||
-rw-r--r-- | include/linux/netpoll.h | 25 | ||||
-rw-r--r-- | net/core/netpoll.c | 57 |
3 files changed, 57 insertions, 29 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ba5d1236aa17..d6afd440cf7b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -41,7 +41,7 @@ | |||
41 | struct divert_blk; | 41 | struct divert_blk; |
42 | struct vlan_group; | 42 | struct vlan_group; |
43 | struct ethtool_ops; | 43 | struct ethtool_ops; |
44 | struct netpoll; | 44 | struct netpoll_info; |
45 | /* source back-compat hooks */ | 45 | /* source back-compat hooks */ |
46 | #define SET_ETHTOOL_OPS(netdev,ops) \ | 46 | #define SET_ETHTOOL_OPS(netdev,ops) \ |
47 | ( (netdev)->ethtool_ops = (ops) ) | 47 | ( (netdev)->ethtool_ops = (ops) ) |
@@ -468,7 +468,7 @@ struct net_device | |||
468 | unsigned char *haddr); | 468 | unsigned char *haddr); |
469 | int (*neigh_setup)(struct net_device *dev, struct neigh_parms *); | 469 | int (*neigh_setup)(struct net_device *dev, struct neigh_parms *); |
470 | #ifdef CONFIG_NETPOLL | 470 | #ifdef CONFIG_NETPOLL |
471 | struct netpoll *np; | 471 | struct netpoll_info *npinfo; |
472 | #endif | 472 | #endif |
473 | #ifdef CONFIG_NET_POLL_CONTROLLER | 473 | #ifdef CONFIG_NET_POLL_CONTROLLER |
474 | void (*poll_controller)(struct net_device *dev); | 474 | void (*poll_controller)(struct net_device *dev); |
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 449a4fde6587..388cd91bc7a6 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h | |||
@@ -16,14 +16,18 @@ struct netpoll; | |||
16 | struct netpoll { | 16 | struct netpoll { |
17 | struct net_device *dev; | 17 | struct net_device *dev; |
18 | char dev_name[16], *name; | 18 | char dev_name[16], *name; |
19 | int rx_flags; | ||
20 | void (*rx_hook)(struct netpoll *, int, char *, int); | 19 | void (*rx_hook)(struct netpoll *, int, char *, int); |
21 | void (*drop)(struct sk_buff *skb); | 20 | void (*drop)(struct sk_buff *skb); |
22 | u32 local_ip, remote_ip; | 21 | u32 local_ip, remote_ip; |
23 | u16 local_port, remote_port; | 22 | u16 local_port, remote_port; |
24 | unsigned char local_mac[6], remote_mac[6]; | 23 | unsigned char local_mac[6], remote_mac[6]; |
24 | }; | ||
25 | |||
26 | struct netpoll_info { | ||
25 | spinlock_t poll_lock; | 27 | spinlock_t poll_lock; |
26 | int poll_owner; | 28 | int poll_owner; |
29 | int rx_flags; | ||
30 | struct netpoll *np; | ||
27 | }; | 31 | }; |
28 | 32 | ||
29 | void netpoll_poll(struct netpoll *np); | 33 | void netpoll_poll(struct netpoll *np); |
@@ -39,22 +43,27 @@ void netpoll_queue(struct sk_buff *skb); | |||
39 | #ifdef CONFIG_NETPOLL | 43 | #ifdef CONFIG_NETPOLL |
40 | static inline int netpoll_rx(struct sk_buff *skb) | 44 | static inline int netpoll_rx(struct sk_buff *skb) |
41 | { | 45 | { |
42 | return skb->dev->np && skb->dev->np->rx_flags && __netpoll_rx(skb); | 46 | struct netpoll_info *npinfo = skb->dev->npinfo; |
47 | |||
48 | if (!npinfo || !npinfo->rx_flags) | ||
49 | return 0; | ||
50 | |||
51 | return npinfo->np && __netpoll_rx(skb); | ||
43 | } | 52 | } |
44 | 53 | ||
45 | static inline void netpoll_poll_lock(struct net_device *dev) | 54 | static inline void netpoll_poll_lock(struct net_device *dev) |
46 | { | 55 | { |
47 | if (dev->np) { | 56 | if (dev->npinfo) { |
48 | spin_lock(&dev->np->poll_lock); | 57 | spin_lock(&dev->npinfo->poll_lock); |
49 | dev->np->poll_owner = smp_processor_id(); | 58 | dev->npinfo->poll_owner = smp_processor_id(); |
50 | } | 59 | } |
51 | } | 60 | } |
52 | 61 | ||
53 | static inline void netpoll_poll_unlock(struct net_device *dev) | 62 | static inline void netpoll_poll_unlock(struct net_device *dev) |
54 | { | 63 | { |
55 | if (dev->np) { | 64 | if (dev->npinfo) { |
56 | dev->np->poll_owner = -1; | 65 | dev->npinfo->poll_owner = -1; |
57 | spin_unlock(&dev->np->poll_lock); | 66 | spin_unlock(&dev->npinfo->poll_lock); |
58 | } | 67 | } |
59 | } | 68 | } |
60 | 69 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a119696d5521..ab3c0c9713b0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -130,19 +130,20 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, | |||
130 | */ | 130 | */ |
131 | static void poll_napi(struct netpoll *np) | 131 | static void poll_napi(struct netpoll *np) |
132 | { | 132 | { |
133 | struct netpoll_info *npinfo = np->dev->npinfo; | ||
133 | int budget = 16; | 134 | int budget = 16; |
134 | 135 | ||
135 | if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) && | 136 | if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) && |
136 | np->poll_owner != smp_processor_id() && | 137 | npinfo->poll_owner != smp_processor_id() && |
137 | spin_trylock(&np->poll_lock)) { | 138 | spin_trylock(&npinfo->poll_lock)) { |
138 | np->rx_flags |= NETPOLL_RX_DROP; | 139 | npinfo->rx_flags |= NETPOLL_RX_DROP; |
139 | atomic_inc(&trapped); | 140 | atomic_inc(&trapped); |
140 | 141 | ||
141 | np->dev->poll(np->dev, &budget); | 142 | np->dev->poll(np->dev, &budget); |
142 | 143 | ||
143 | atomic_dec(&trapped); | 144 | atomic_dec(&trapped); |
144 | np->rx_flags &= ~NETPOLL_RX_DROP; | 145 | npinfo->rx_flags &= ~NETPOLL_RX_DROP; |
145 | spin_unlock(&np->poll_lock); | 146 | spin_unlock(&npinfo->poll_lock); |
146 | } | 147 | } |
147 | } | 148 | } |
148 | 149 | ||
@@ -245,6 +246,7 @@ repeat: | |||
245 | static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | 246 | static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) |
246 | { | 247 | { |
247 | int status; | 248 | int status; |
249 | struct netpoll_info *npinfo; | ||
248 | 250 | ||
249 | repeat: | 251 | repeat: |
250 | if(!np || !np->dev || !netif_running(np->dev)) { | 252 | if(!np || !np->dev || !netif_running(np->dev)) { |
@@ -253,8 +255,9 @@ repeat: | |||
253 | } | 255 | } |
254 | 256 | ||
255 | /* avoid recursion */ | 257 | /* avoid recursion */ |
256 | if(np->poll_owner == smp_processor_id() || | 258 | npinfo = np->dev->npinfo; |
257 | np->dev->xmit_lock_owner == smp_processor_id()) { | 259 | if (npinfo->poll_owner == smp_processor_id() || |
260 | np->dev->xmit_lock_owner == smp_processor_id()) { | ||
258 | if (np->drop) | 261 | if (np->drop) |
259 | np->drop(skb); | 262 | np->drop(skb); |
260 | else | 263 | else |
@@ -341,14 +344,18 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
341 | 344 | ||
342 | static void arp_reply(struct sk_buff *skb) | 345 | static void arp_reply(struct sk_buff *skb) |
343 | { | 346 | { |
347 | struct netpoll_info *npinfo = skb->dev->npinfo; | ||
344 | struct arphdr *arp; | 348 | struct arphdr *arp; |
345 | unsigned char *arp_ptr; | 349 | unsigned char *arp_ptr; |
346 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; | 350 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; |
347 | u32 sip, tip; | 351 | u32 sip, tip; |
348 | struct sk_buff *send_skb; | 352 | struct sk_buff *send_skb; |
349 | struct netpoll *np = skb->dev->np; | 353 | struct netpoll *np = NULL; |
350 | 354 | ||
351 | if (!np) return; | 355 | if (npinfo) |
356 | np = npinfo->np; | ||
357 | if (!np) | ||
358 | return; | ||
352 | 359 | ||
353 | /* No arp on this interface */ | 360 | /* No arp on this interface */ |
354 | if (skb->dev->flags & IFF_NOARP) | 361 | if (skb->dev->flags & IFF_NOARP) |
@@ -429,7 +436,7 @@ int __netpoll_rx(struct sk_buff *skb) | |||
429 | int proto, len, ulen; | 436 | int proto, len, ulen; |
430 | struct iphdr *iph; | 437 | struct iphdr *iph; |
431 | struct udphdr *uh; | 438 | struct udphdr *uh; |
432 | struct netpoll *np = skb->dev->np; | 439 | struct netpoll *np = skb->dev->npinfo->np; |
433 | 440 | ||
434 | if (!np->rx_hook) | 441 | if (!np->rx_hook) |
435 | goto out; | 442 | goto out; |
@@ -611,9 +618,7 @@ int netpoll_setup(struct netpoll *np) | |||
611 | { | 618 | { |
612 | struct net_device *ndev = NULL; | 619 | struct net_device *ndev = NULL; |
613 | struct in_device *in_dev; | 620 | struct in_device *in_dev; |
614 | 621 | struct netpoll_info *npinfo; | |
615 | np->poll_lock = SPIN_LOCK_UNLOCKED; | ||
616 | np->poll_owner = -1; | ||
617 | 622 | ||
618 | if (np->dev_name) | 623 | if (np->dev_name) |
619 | ndev = dev_get_by_name(np->dev_name); | 624 | ndev = dev_get_by_name(np->dev_name); |
@@ -624,7 +629,16 @@ int netpoll_setup(struct netpoll *np) | |||
624 | } | 629 | } |
625 | 630 | ||
626 | np->dev = ndev; | 631 | np->dev = ndev; |
627 | ndev->np = np; | 632 | if (!ndev->npinfo) { |
633 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); | ||
634 | if (!npinfo) | ||
635 | goto release; | ||
636 | |||
637 | npinfo->np = NULL; | ||
638 | npinfo->poll_lock = SPIN_LOCK_UNLOCKED; | ||
639 | npinfo->poll_owner = -1; | ||
640 | } else | ||
641 | npinfo = ndev->npinfo; | ||
628 | 642 | ||
629 | if (!ndev->poll_controller) { | 643 | if (!ndev->poll_controller) { |
630 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", | 644 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", |
@@ -693,12 +707,15 @@ int netpoll_setup(struct netpoll *np) | |||
693 | } | 707 | } |
694 | 708 | ||
695 | if(np->rx_hook) | 709 | if(np->rx_hook) |
696 | np->rx_flags = NETPOLL_RX_ENABLED; | 710 | npinfo->rx_flags = NETPOLL_RX_ENABLED; |
711 | npinfo->np = np; | ||
712 | ndev->npinfo = npinfo; | ||
697 | 713 | ||
698 | return 0; | 714 | return 0; |
699 | 715 | ||
700 | release: | 716 | release: |
701 | ndev->np = NULL; | 717 | if (!ndev->npinfo) |
718 | kfree(npinfo); | ||
702 | np->dev = NULL; | 719 | np->dev = NULL; |
703 | dev_put(ndev); | 720 | dev_put(ndev); |
704 | return -1; | 721 | return -1; |
@@ -706,9 +723,11 @@ int netpoll_setup(struct netpoll *np) | |||
706 | 723 | ||
707 | void netpoll_cleanup(struct netpoll *np) | 724 | void netpoll_cleanup(struct netpoll *np) |
708 | { | 725 | { |
709 | if (np->dev) | 726 | if (np->dev) { |
710 | np->dev->np = NULL; | 727 | if (np->dev->npinfo) |
711 | dev_put(np->dev); | 728 | np->dev->npinfo->np = NULL; |
729 | dev_put(np->dev); | ||
730 | } | ||
712 | np->dev = NULL; | 731 | np->dev = NULL; |
713 | } | 732 | } |
714 | 733 | ||