aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/natsemi.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/natsemi.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/natsemi.c')
-rw-r--r--drivers/net/natsemi.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index b47a12d684f..43cfa4b3e29 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -560,6 +560,8 @@ struct netdev_private {
560 /* address of a sent-in-place packet/buffer, for later free() */ 560 /* address of a sent-in-place packet/buffer, for later free() */
561 struct sk_buff *tx_skbuff[TX_RING_SIZE]; 561 struct sk_buff *tx_skbuff[TX_RING_SIZE];
562 dma_addr_t tx_dma[TX_RING_SIZE]; 562 dma_addr_t tx_dma[TX_RING_SIZE];
563 struct net_device *dev;
564 struct napi_struct napi;
563 struct net_device_stats stats; 565 struct net_device_stats stats;
564 /* Media monitoring timer */ 566 /* Media monitoring timer */
565 struct timer_list timer; 567 struct timer_list timer;
@@ -636,7 +638,7 @@ static void init_registers(struct net_device *dev);
636static int start_tx(struct sk_buff *skb, struct net_device *dev); 638static int start_tx(struct sk_buff *skb, struct net_device *dev);
637static irqreturn_t intr_handler(int irq, void *dev_instance); 639static irqreturn_t intr_handler(int irq, void *dev_instance);
638static void netdev_error(struct net_device *dev, int intr_status); 640static void netdev_error(struct net_device *dev, int intr_status);
639static int natsemi_poll(struct net_device *dev, int *budget); 641static int natsemi_poll(struct napi_struct *napi, int budget);
640static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do); 642static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
641static void netdev_tx_done(struct net_device *dev); 643static void netdev_tx_done(struct net_device *dev);
642static int natsemi_change_mtu(struct net_device *dev, int new_mtu); 644static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
@@ -861,6 +863,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
861 dev->irq = irq; 863 dev->irq = irq;
862 864
863 np = netdev_priv(dev); 865 np = netdev_priv(dev);
866 netif_napi_add(dev, &np->napi, natsemi_poll, 64);
864 867
865 np->pci_dev = pdev; 868 np->pci_dev = pdev;
866 pci_set_drvdata(pdev, dev); 869 pci_set_drvdata(pdev, dev);
@@ -931,8 +934,6 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
931 dev->do_ioctl = &netdev_ioctl; 934 dev->do_ioctl = &netdev_ioctl;
932 dev->tx_timeout = &tx_timeout; 935 dev->tx_timeout = &tx_timeout;
933 dev->watchdog_timeo = TX_TIMEOUT; 936 dev->watchdog_timeo = TX_TIMEOUT;
934 dev->poll = natsemi_poll;
935 dev->weight = 64;
936 937
937#ifdef CONFIG_NET_POLL_CONTROLLER 938#ifdef CONFIG_NET_POLL_CONTROLLER
938 dev->poll_controller = &natsemi_poll_controller; 939 dev->poll_controller = &natsemi_poll_controller;
@@ -1554,6 +1555,8 @@ static int netdev_open(struct net_device *dev)
1554 free_irq(dev->irq, dev); 1555 free_irq(dev->irq, dev);
1555 return i; 1556 return i;
1556 } 1557 }
1558 napi_enable(&np->napi);
1559
1557 init_ring(dev); 1560 init_ring(dev);
1558 spin_lock_irq(&np->lock); 1561 spin_lock_irq(&np->lock);
1559 init_registers(dev); 1562 init_registers(dev);
@@ -2200,10 +2203,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
2200 2203
2201 prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); 2204 prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]);
2202 2205
2203 if (netif_rx_schedule_prep(dev)) { 2206 if (netif_rx_schedule_prep(dev, &np->napi)) {
2204 /* Disable interrupts and register for poll */ 2207 /* Disable interrupts and register for poll */
2205 natsemi_irq_disable(dev); 2208 natsemi_irq_disable(dev);
2206 __netif_rx_schedule(dev); 2209 __netif_rx_schedule(dev, &np->napi);
2207 } else 2210 } else
2208 printk(KERN_WARNING 2211 printk(KERN_WARNING
2209 "%s: Ignoring interrupt, status %#08x, mask %#08x.\n", 2212 "%s: Ignoring interrupt, status %#08x, mask %#08x.\n",
@@ -2216,12 +2219,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
2216/* This is the NAPI poll routine. As well as the standard RX handling 2219/* This is the NAPI poll routine. As well as the standard RX handling
2217 * it also handles all other interrupts that the chip might raise. 2220 * it also handles all other interrupts that the chip might raise.
2218 */ 2221 */
2219static int natsemi_poll(struct net_device *dev, int *budget) 2222static int natsemi_poll(struct napi_struct *napi, int budget)
2220{ 2223{
2221 struct netdev_private *np = netdev_priv(dev); 2224 struct netdev_private *np = container_of(napi, struct netdev_private, napi);
2225 struct net_device *dev = np->dev;
2222 void __iomem * ioaddr = ns_ioaddr(dev); 2226 void __iomem * ioaddr = ns_ioaddr(dev);
2223
2224 int work_to_do = min(*budget, dev->quota);
2225 int work_done = 0; 2227 int work_done = 0;
2226 2228
2227 do { 2229 do {
@@ -2236,7 +2238,7 @@ static int natsemi_poll(struct net_device *dev, int *budget)
2236 if (np->intr_status & 2238 if (np->intr_status &
2237 (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | 2239 (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
2238 IntrRxErr | IntrRxOverrun)) { 2240 IntrRxErr | IntrRxOverrun)) {
2239 netdev_rx(dev, &work_done, work_to_do); 2241 netdev_rx(dev, &work_done, budget);
2240 } 2242 }
2241 2243
2242 if (np->intr_status & 2244 if (np->intr_status &
@@ -2250,16 +2252,13 @@ static int natsemi_poll(struct net_device *dev, int *budget)
2250 if (np->intr_status & IntrAbnormalSummary) 2252 if (np->intr_status & IntrAbnormalSummary)
2251 netdev_error(dev, np->intr_status); 2253 netdev_error(dev, np->intr_status);
2252 2254
2253 *budget -= work_done; 2255 if (work_done >= budget)
2254 dev->quota -= work_done; 2256 return work_done;
2255
2256 if (work_done >= work_to_do)
2257 return 1;
2258 2257
2259 np->intr_status = readl(ioaddr + IntrStatus); 2258 np->intr_status = readl(ioaddr + IntrStatus);
2260 } while (np->intr_status); 2259 } while (np->intr_status);
2261 2260
2262 netif_rx_complete(dev); 2261 netif_rx_complete(dev, napi);
2263 2262
2264 /* Reenable interrupts providing nothing is trying to shut 2263 /* Reenable interrupts providing nothing is trying to shut
2265 * the chip down. */ 2264 * the chip down. */
@@ -2268,7 +2267,7 @@ static int natsemi_poll(struct net_device *dev, int *budget)
2268 natsemi_irq_enable(dev); 2267 natsemi_irq_enable(dev);
2269 spin_unlock(&np->lock); 2268 spin_unlock(&np->lock);
2270 2269
2271 return 0; 2270 return work_done;
2272} 2271}
2273 2272
2274/* This routine is logically part of the interrupt handler, but separated 2273/* This routine is logically part of the interrupt handler, but separated
@@ -3158,6 +3157,8 @@ static int netdev_close(struct net_device *dev)
3158 dev->name, np->cur_tx, np->dirty_tx, 3157 dev->name, np->cur_tx, np->dirty_tx,
3159 np->cur_rx, np->dirty_rx); 3158 np->cur_rx, np->dirty_rx);
3160 3159
3160 napi_disable(&np->napi);
3161
3161 /* 3162 /*
3162 * FIXME: what if someone tries to close a device 3163 * FIXME: what if someone tries to close a device
3163 * that is suspended? 3164 * that is suspended?
@@ -3253,7 +3254,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
3253 * disable_irq() to enforce synchronization. 3254 * disable_irq() to enforce synchronization.
3254 * * natsemi_poll: checks before reenabling interrupts. suspend 3255 * * natsemi_poll: checks before reenabling interrupts. suspend
3255 * sets hands_off, disables interrupts and then waits with 3256 * sets hands_off, disables interrupts and then waits with
3256 * netif_poll_disable(). 3257 * napi_disable().
3257 * 3258 *
3258 * Interrupts must be disabled, otherwise hands_off can cause irq storms. 3259 * Interrupts must be disabled, otherwise hands_off can cause irq storms.
3259 */ 3260 */
@@ -3279,7 +3280,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
3279 spin_unlock_irq(&np->lock); 3280 spin_unlock_irq(&np->lock);
3280 enable_irq(dev->irq); 3281 enable_irq(dev->irq);
3281 3282
3282 netif_poll_disable(dev); 3283 napi_disable(&np->napi);
3283 3284
3284 /* Update the error counts. */ 3285 /* Update the error counts. */
3285 __get_stats(dev); 3286 __get_stats(dev);
@@ -3320,6 +3321,8 @@ static int natsemi_resume (struct pci_dev *pdev)
3320 pci_enable_device(pdev); 3321 pci_enable_device(pdev);
3321 /* pci_power_on(pdev); */ 3322 /* pci_power_on(pdev); */
3322 3323
3324 napi_enable(&np->napi);
3325
3323 natsemi_reset(dev); 3326 natsemi_reset(dev);
3324 init_ring(dev); 3327 init_ring(dev);
3325 disable_irq(dev->irq); 3328 disable_irq(dev->irq);
@@ -3333,7 +3336,6 @@ static int natsemi_resume (struct pci_dev *pdev)
3333 mod_timer(&np->timer, jiffies + 1*HZ); 3336 mod_timer(&np->timer, jiffies + 1*HZ);
3334 } 3337 }
3335 netif_device_attach(dev); 3338 netif_device_attach(dev);
3336 netif_poll_enable(dev);
3337out: 3339out:
3338 rtnl_unlock(); 3340 rtnl_unlock();
3339 return 0; 3341 return 0;