aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/netpoll.c')
-rw-r--r--net/core/netpoll.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a119696d5521..c327c9edadc5 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,22 @@ 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;
352 unsigned long flags;
348 struct sk_buff *send_skb; 353 struct sk_buff *send_skb;
349 struct netpoll *np = skb->dev->np; 354 struct netpoll *np = NULL;
355
356 spin_lock_irqsave(&npinfo->rx_lock, flags);
357 if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
358 np = npinfo->rx_np;
359 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
350 360
351 if (!np) return; 361 if (!np)
362 return;
352 363
353 /* No arp on this interface */ 364 /* No arp on this interface */
354 if (skb->dev->flags & IFF_NOARP) 365 if (skb->dev->flags & IFF_NOARP)
@@ -429,9 +440,9 @@ int __netpoll_rx(struct sk_buff *skb)
429 int proto, len, ulen; 440 int proto, len, ulen;
430 struct iphdr *iph; 441 struct iphdr *iph;
431 struct udphdr *uh; 442 struct udphdr *uh;
432 struct netpoll *np = skb->dev->np; 443 struct netpoll *np = skb->dev->npinfo->rx_np;
433 444
434 if (!np->rx_hook) 445 if (!np)
435 goto out; 446 goto out;
436 if (skb->dev->type != ARPHRD_ETHER) 447 if (skb->dev->type != ARPHRD_ETHER)
437 goto out; 448 goto out;
@@ -611,9 +622,8 @@ int netpoll_setup(struct netpoll *np)
611{ 622{
612 struct net_device *ndev = NULL; 623 struct net_device *ndev = NULL;
613 struct in_device *in_dev; 624 struct in_device *in_dev;
614 625 struct netpoll_info *npinfo;
615 np->poll_lock = SPIN_LOCK_UNLOCKED; 626 unsigned long flags;
616 np->poll_owner = -1;
617 627
618 if (np->dev_name) 628 if (np->dev_name)
619 ndev = dev_get_by_name(np->dev_name); 629 ndev = dev_get_by_name(np->dev_name);
@@ -624,7 +634,17 @@ int netpoll_setup(struct netpoll *np)
624 } 634 }
625 635
626 np->dev = ndev; 636 np->dev = ndev;
627 ndev->np = np; 637 if (!ndev->npinfo) {
638 npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
639 if (!npinfo)
640 goto release;
641
642 npinfo->rx_np = NULL;
643 npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
644 npinfo->poll_owner = -1;
645 npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
646 } else
647 npinfo = ndev->npinfo;
628 648
629 if (!ndev->poll_controller) { 649 if (!ndev->poll_controller) {
630 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", 650 printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
@@ -692,13 +712,20 @@ int netpoll_setup(struct netpoll *np)
692 np->name, HIPQUAD(np->local_ip)); 712 np->name, HIPQUAD(np->local_ip));
693 } 713 }
694 714
695 if(np->rx_hook) 715 if (np->rx_hook) {
696 np->rx_flags = NETPOLL_RX_ENABLED; 716 spin_lock_irqsave(&npinfo->rx_lock, flags);
717 npinfo->rx_flags |= NETPOLL_RX_ENABLED;
718 npinfo->rx_np = np;
719 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
720 }
721 /* last thing to do is link it to the net device structure */
722 ndev->npinfo = npinfo;
697 723
698 return 0; 724 return 0;
699 725
700 release: 726 release:
701 ndev->np = NULL; 727 if (!ndev->npinfo)
728 kfree(npinfo);
702 np->dev = NULL; 729 np->dev = NULL;
703 dev_put(ndev); 730 dev_put(ndev);
704 return -1; 731 return -1;
@@ -706,9 +733,20 @@ int netpoll_setup(struct netpoll *np)
706 733
707void netpoll_cleanup(struct netpoll *np) 734void netpoll_cleanup(struct netpoll *np)
708{ 735{
709 if (np->dev) 736 struct netpoll_info *npinfo;
710 np->dev->np = NULL; 737 unsigned long flags;
711 dev_put(np->dev); 738
739 if (np->dev) {
740 npinfo = np->dev->npinfo;
741 if (npinfo && npinfo->rx_np == np) {
742 spin_lock_irqsave(&npinfo->rx_lock, flags);
743 npinfo->rx_np = NULL;
744 npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
745 spin_unlock_irqrestore(&npinfo->rx_lock, flags);
746 }
747 dev_put(np->dev);
748 }
749
712 np->dev = NULL; 750 np->dev = NULL;
713} 751}
714 752