aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--include/linux/netpoll.h25
-rw-r--r--net/core/netpoll.c57
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 @@
41struct divert_blk; 41struct divert_blk;
42struct vlan_group; 42struct vlan_group;
43struct ethtool_ops; 43struct ethtool_ops;
44struct netpoll; 44struct 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;
16struct netpoll { 16struct 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
26struct 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
29void netpoll_poll(struct netpoll *np); 33void netpoll_poll(struct netpoll *np);
@@ -39,22 +43,27 @@ void netpoll_queue(struct sk_buff *skb);
39#ifdef CONFIG_NETPOLL 43#ifdef CONFIG_NETPOLL
40static inline int netpoll_rx(struct sk_buff *skb) 44static 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
45static inline void netpoll_poll_lock(struct net_device *dev) 54static 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
53static inline void netpoll_poll_unlock(struct net_device *dev) 62static 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 */
131static void poll_napi(struct netpoll *np) 131static 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:
245static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) 246static 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
249repeat: 251repeat:
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
342static void arp_reply(struct sk_buff *skb) 345static 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
707void netpoll_cleanup(struct netpoll *np) 724void 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