aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/8139cp.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-03 19:41:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:45 -0400
commitbea3348eef27e6044b6161fd04c3152215f96411 (patch)
treef0990b263e5ce42505d290a4c346fe990bcd4c33 /drivers/net/8139cp.c
parentdde4e47e8fe333a5649a3fa0e7db1fa7c08d6158 (diff)
[NET]: Make NAPI polling independent of struct net_device objects.
Several devices have multiple independant RX queues per net device, and some have a single interrupt doorbell for several queues. In either case, it's easier to support layouts like that if the structure representing the poll is independant from the net device itself. The signature of the ->poll() call back goes from: int foo_poll(struct net_device *dev, int *budget) to int foo_poll(struct napi_struct *napi, int budget) The caller is returned the number of RX packets processed (or the number of "NAPI credits" consumed if you want to get abstract). The callee no longer messes around bumping dev->quota, *budget, etc. because that is all handled in the caller upon return. The napi_struct is to be embedded in the device driver private data structures. Furthermore, it is the driver's responsibility to disable all NAPI instances in it's ->stop() device close handler. Since the napi_struct is privatized into the driver's private data structures, only the driver knows how to get at all of the napi_struct instances it may have per-device. With lots of help and suggestions from Rusty Russell, Roland Dreier, Michael Chan, Jeff Garzik, and Jamal Hadi Salim. Bug fixes from Thomas Graf, Roland Dreier, Peter Zijlstra, Joseph Fannin, Scott Wood, Hans J. Koch, and Michael Chan. [ Ported to current tree and all drivers converted. Integrated Stephen's follow-on kerneldoc additions, and restored poll_list handling to the old style to fix mutual exclusion issues. -DaveM ] Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/8139cp.c')
-rw-r--r--drivers/net/8139cp.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a79f28c7a100..7f18ca23d9f8 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -334,6 +334,8 @@ struct cp_private {
334 spinlock_t lock; 334 spinlock_t lock;
335 u32 msg_enable; 335 u32 msg_enable;
336 336
337 struct napi_struct napi;
338
337 struct pci_dev *pdev; 339 struct pci_dev *pdev;
338 u32 rx_config; 340 u32 rx_config;
339 u16 cpcmd; 341 u16 cpcmd;
@@ -501,12 +503,12 @@ static inline unsigned int cp_rx_csum_ok (u32 status)
501 return 0; 503 return 0;
502} 504}
503 505
504static int cp_rx_poll (struct net_device *dev, int *budget) 506static int cp_rx_poll(struct napi_struct *napi, int budget)
505{ 507{
506 struct cp_private *cp = netdev_priv(dev); 508 struct cp_private *cp = container_of(napi, struct cp_private, napi);
507 unsigned rx_tail = cp->rx_tail; 509 struct net_device *dev = cp->dev;
508 unsigned rx_work = dev->quota; 510 unsigned int rx_tail = cp->rx_tail;
509 unsigned rx; 511 int rx;
510 512
511rx_status_loop: 513rx_status_loop:
512 rx = 0; 514 rx = 0;
@@ -588,33 +590,28 @@ rx_next:
588 desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); 590 desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
589 rx_tail = NEXT_RX(rx_tail); 591 rx_tail = NEXT_RX(rx_tail);
590 592
591 if (!rx_work--) 593 if (rx >= budget)
592 break; 594 break;
593 } 595 }
594 596
595 cp->rx_tail = rx_tail; 597 cp->rx_tail = rx_tail;
596 598
597 dev->quota -= rx;
598 *budget -= rx;
599
600 /* if we did not reach work limit, then we're done with 599 /* if we did not reach work limit, then we're done with
601 * this round of polling 600 * this round of polling
602 */ 601 */
603 if (rx_work) { 602 if (rx < budget) {
604 unsigned long flags; 603 unsigned long flags;
605 604
606 if (cpr16(IntrStatus) & cp_rx_intr_mask) 605 if (cpr16(IntrStatus) & cp_rx_intr_mask)
607 goto rx_status_loop; 606 goto rx_status_loop;
608 607
609 local_irq_save(flags); 608 spin_lock_irqsave(&cp->lock, flags);
610 cpw16_f(IntrMask, cp_intr_mask); 609 cpw16_f(IntrMask, cp_intr_mask);
611 __netif_rx_complete(dev); 610 __netif_rx_complete(dev, napi);
612 local_irq_restore(flags); 611 spin_unlock_irqrestore(&cp->lock, flags);
613
614 return 0; /* done */
615 } 612 }
616 613
617 return 1; /* not done */ 614 return rx;
618} 615}
619 616
620static irqreturn_t cp_interrupt (int irq, void *dev_instance) 617static irqreturn_t cp_interrupt (int irq, void *dev_instance)
@@ -647,9 +644,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
647 } 644 }
648 645
649 if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) 646 if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
650 if (netif_rx_schedule_prep(dev)) { 647 if (netif_rx_schedule_prep(dev, &cp->napi)) {
651 cpw16_f(IntrMask, cp_norx_intr_mask); 648 cpw16_f(IntrMask, cp_norx_intr_mask);
652 __netif_rx_schedule(dev); 649 __netif_rx_schedule(dev, &cp->napi);
653 } 650 }
654 651
655 if (status & (TxOK | TxErr | TxEmpty | SWInt)) 652 if (status & (TxOK | TxErr | TxEmpty | SWInt))
@@ -1175,6 +1172,8 @@ static int cp_open (struct net_device *dev)
1175 if (rc) 1172 if (rc)
1176 return rc; 1173 return rc;
1177 1174
1175 napi_enable(&cp->napi);
1176
1178 cp_init_hw(cp); 1177 cp_init_hw(cp);
1179 1178
1180 rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev); 1179 rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
@@ -1188,6 +1187,7 @@ static int cp_open (struct net_device *dev)
1188 return 0; 1187 return 0;
1189 1188
1190err_out_hw: 1189err_out_hw:
1190 napi_disable(&cp->napi);
1191 cp_stop_hw(cp); 1191 cp_stop_hw(cp);
1192 cp_free_rings(cp); 1192 cp_free_rings(cp);
1193 return rc; 1193 return rc;
@@ -1198,6 +1198,8 @@ static int cp_close (struct net_device *dev)
1198 struct cp_private *cp = netdev_priv(dev); 1198 struct cp_private *cp = netdev_priv(dev);
1199 unsigned long flags; 1199 unsigned long flags;
1200 1200
1201 napi_disable(&cp->napi);
1202
1201 if (netif_msg_ifdown(cp)) 1203 if (netif_msg_ifdown(cp))
1202 printk(KERN_DEBUG "%s: disabling interface\n", dev->name); 1204 printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
1203 1205
@@ -1933,11 +1935,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
1933 dev->hard_start_xmit = cp_start_xmit; 1935 dev->hard_start_xmit = cp_start_xmit;
1934 dev->get_stats = cp_get_stats; 1936 dev->get_stats = cp_get_stats;
1935 dev->do_ioctl = cp_ioctl; 1937 dev->do_ioctl = cp_ioctl;
1936 dev->poll = cp_rx_poll;
1937#ifdef CONFIG_NET_POLL_CONTROLLER 1938#ifdef CONFIG_NET_POLL_CONTROLLER
1938 dev->poll_controller = cp_poll_controller; 1939 dev->poll_controller = cp_poll_controller;
1939#endif 1940#endif
1940 dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */ 1941 netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
1941#ifdef BROKEN 1942#ifdef BROKEN
1942 dev->change_mtu = cp_change_mtu; 1943 dev->change_mtu = cp_change_mtu;
1943#endif 1944#endif