aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cassini.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/cassini.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/cassini.c')
-rw-r--r--drivers/net/cassini.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index f6e4030c73d1..13f14df21e6e 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2485,7 +2485,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id)
2485 if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ 2485 if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
2486#ifdef USE_NAPI 2486#ifdef USE_NAPI
2487 cas_mask_intr(cp); 2487 cas_mask_intr(cp);
2488 netif_rx_schedule(dev); 2488 netif_rx_schedule(dev, &cp->napi);
2489#else 2489#else
2490 cas_rx_ringN(cp, ring, 0); 2490 cas_rx_ringN(cp, ring, 0);
2491#endif 2491#endif
@@ -2536,7 +2536,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id)
2536 if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ 2536 if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
2537#ifdef USE_NAPI 2537#ifdef USE_NAPI
2538 cas_mask_intr(cp); 2538 cas_mask_intr(cp);
2539 netif_rx_schedule(dev); 2539 netif_rx_schedule(dev, &cp->napi);
2540#else 2540#else
2541 cas_rx_ringN(cp, 1, 0); 2541 cas_rx_ringN(cp, 1, 0);
2542#endif 2542#endif
@@ -2592,7 +2592,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
2592 if (status & INTR_RX_DONE) { 2592 if (status & INTR_RX_DONE) {
2593#ifdef USE_NAPI 2593#ifdef USE_NAPI
2594 cas_mask_intr(cp); 2594 cas_mask_intr(cp);
2595 netif_rx_schedule(dev); 2595 netif_rx_schedule(dev, &cp->napi);
2596#else 2596#else
2597 cas_rx_ringN(cp, 0, 0); 2597 cas_rx_ringN(cp, 0, 0);
2598#endif 2598#endif
@@ -2607,9 +2607,10 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
2607 2607
2608 2608
2609#ifdef USE_NAPI 2609#ifdef USE_NAPI
2610static int cas_poll(struct net_device *dev, int *budget) 2610static int cas_poll(struct napi_struct *napi, int budget)
2611{ 2611{
2612 struct cas *cp = netdev_priv(dev); 2612 struct cas *cp = container_of(napi, struct cas, napi);
2613 struct net_device *dev = cp->dev;
2613 int i, enable_intr, todo, credits; 2614 int i, enable_intr, todo, credits;
2614 u32 status = readl(cp->regs + REG_INTR_STATUS); 2615 u32 status = readl(cp->regs + REG_INTR_STATUS);
2615 unsigned long flags; 2616 unsigned long flags;
@@ -2620,20 +2621,18 @@ static int cas_poll(struct net_device *dev, int *budget)
2620 2621
2621 /* NAPI rx packets. we spread the credits across all of the 2622 /* NAPI rx packets. we spread the credits across all of the
2622 * rxc rings 2623 * rxc rings
2623 */ 2624 *
2624 todo = min(*budget, dev->quota); 2625 * to make sure we're fair with the work we loop through each
2625
2626 /* to make sure we're fair with the work we loop through each
2627 * ring N_RX_COMP_RING times with a request of 2626 * ring N_RX_COMP_RING times with a request of
2628 * todo / N_RX_COMP_RINGS 2627 * budget / N_RX_COMP_RINGS
2629 */ 2628 */
2630 enable_intr = 1; 2629 enable_intr = 1;
2631 credits = 0; 2630 credits = 0;
2632 for (i = 0; i < N_RX_COMP_RINGS; i++) { 2631 for (i = 0; i < N_RX_COMP_RINGS; i++) {
2633 int j; 2632 int j;
2634 for (j = 0; j < N_RX_COMP_RINGS; j++) { 2633 for (j = 0; j < N_RX_COMP_RINGS; j++) {
2635 credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS); 2634 credits += cas_rx_ringN(cp, j, budget / N_RX_COMP_RINGS);
2636 if (credits >= todo) { 2635 if (credits >= budget) {
2637 enable_intr = 0; 2636 enable_intr = 0;
2638 goto rx_comp; 2637 goto rx_comp;
2639 } 2638 }
@@ -2641,9 +2640,6 @@ static int cas_poll(struct net_device *dev, int *budget)
2641 } 2640 }
2642 2641
2643rx_comp: 2642rx_comp:
2644 *budget -= credits;
2645 dev->quota -= credits;
2646
2647 /* final rx completion */ 2643 /* final rx completion */
2648 spin_lock_irqsave(&cp->lock, flags); 2644 spin_lock_irqsave(&cp->lock, flags);
2649 if (status) 2645 if (status)
@@ -2674,11 +2670,10 @@ rx_comp:
2674#endif 2670#endif
2675 spin_unlock_irqrestore(&cp->lock, flags); 2671 spin_unlock_irqrestore(&cp->lock, flags);
2676 if (enable_intr) { 2672 if (enable_intr) {
2677 netif_rx_complete(dev); 2673 netif_rx_complete(dev, napi);
2678 cas_unmask_intr(cp); 2674 cas_unmask_intr(cp);
2679 return 0;
2680 } 2675 }
2681 return 1; 2676 return credits;
2682} 2677}
2683#endif 2678#endif
2684 2679
@@ -4351,6 +4346,9 @@ static int cas_open(struct net_device *dev)
4351 goto err_spare; 4346 goto err_spare;
4352 } 4347 }
4353 4348
4349#ifdef USE_NAPI
4350 napi_enable(&cp->napi);
4351#endif
4354 /* init hw */ 4352 /* init hw */
4355 cas_lock_all_save(cp, flags); 4353 cas_lock_all_save(cp, flags);
4356 cas_clean_rings(cp); 4354 cas_clean_rings(cp);
@@ -4376,6 +4374,9 @@ static int cas_close(struct net_device *dev)
4376 unsigned long flags; 4374 unsigned long flags;
4377 struct cas *cp = netdev_priv(dev); 4375 struct cas *cp = netdev_priv(dev);
4378 4376
4377#ifdef USE_NAPI
4378 napi_enable(&cp->napi);
4379#endif
4379 /* Make sure we don't get distracted by suspend/resume */ 4380 /* Make sure we don't get distracted by suspend/resume */
4380 mutex_lock(&cp->pm_mutex); 4381 mutex_lock(&cp->pm_mutex);
4381 4382
@@ -5062,8 +5063,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
5062 dev->watchdog_timeo = CAS_TX_TIMEOUT; 5063 dev->watchdog_timeo = CAS_TX_TIMEOUT;
5063 dev->change_mtu = cas_change_mtu; 5064 dev->change_mtu = cas_change_mtu;
5064#ifdef USE_NAPI 5065#ifdef USE_NAPI
5065 dev->poll = cas_poll; 5066 netif_napi_add(dev, &cp->napi, cas_poll, 64);
5066 dev->weight = 64;
5067#endif 5067#endif
5068#ifdef CONFIG_NET_POLL_CONTROLLER 5068#ifdef CONFIG_NET_POLL_CONTROLLER
5069 dev->poll_controller = cas_netpoll; 5069 dev->poll_controller = cas_netpoll;