aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/epic100.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/epic100.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/epic100.c')
-rw-r--r--drivers/net/epic100.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 119778401e48..f8446e373bdd 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -262,6 +262,7 @@ struct epic_private {
262 /* Ring pointers. */ 262 /* Ring pointers. */
263 spinlock_t lock; /* Group with Tx control cache line. */ 263 spinlock_t lock; /* Group with Tx control cache line. */
264 spinlock_t napi_lock; 264 spinlock_t napi_lock;
265 struct napi_struct napi;
265 unsigned int reschedule_in_poll; 266 unsigned int reschedule_in_poll;
266 unsigned int cur_tx, dirty_tx; 267 unsigned int cur_tx, dirty_tx;
267 268
@@ -294,7 +295,7 @@ static void epic_tx_timeout(struct net_device *dev);
294static void epic_init_ring(struct net_device *dev); 295static void epic_init_ring(struct net_device *dev);
295static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); 296static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
296static int epic_rx(struct net_device *dev, int budget); 297static int epic_rx(struct net_device *dev, int budget);
297static int epic_poll(struct net_device *dev, int *budget); 298static int epic_poll(struct napi_struct *napi, int budget);
298static irqreturn_t epic_interrupt(int irq, void *dev_instance); 299static irqreturn_t epic_interrupt(int irq, void *dev_instance);
299static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 300static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
300static const struct ethtool_ops netdev_ethtool_ops; 301static const struct ethtool_ops netdev_ethtool_ops;
@@ -487,8 +488,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
487 dev->ethtool_ops = &netdev_ethtool_ops; 488 dev->ethtool_ops = &netdev_ethtool_ops;
488 dev->watchdog_timeo = TX_TIMEOUT; 489 dev->watchdog_timeo = TX_TIMEOUT;
489 dev->tx_timeout = &epic_tx_timeout; 490 dev->tx_timeout = &epic_tx_timeout;
490 dev->poll = epic_poll; 491 netif_napi_add(dev, &ep->napi, epic_poll, 64);
491 dev->weight = 64;
492 492
493 ret = register_netdev(dev); 493 ret = register_netdev(dev);
494 if (ret < 0) 494 if (ret < 0)
@@ -660,8 +660,11 @@ static int epic_open(struct net_device *dev)
660 /* Soft reset the chip. */ 660 /* Soft reset the chip. */
661 outl(0x4001, ioaddr + GENCTL); 661 outl(0x4001, ioaddr + GENCTL);
662 662
663 if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev))) 663 napi_enable(&ep->napi);
664 if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev))) {
665 napi_disable(&ep->napi);
664 return retval; 666 return retval;
667 }
665 668
666 epic_init_ring(dev); 669 epic_init_ring(dev);
667 670
@@ -1103,9 +1106,9 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
1103 1106
1104 if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { 1107 if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
1105 spin_lock(&ep->napi_lock); 1108 spin_lock(&ep->napi_lock);
1106 if (netif_rx_schedule_prep(dev)) { 1109 if (netif_rx_schedule_prep(dev, &ep->napi)) {
1107 epic_napi_irq_off(dev, ep); 1110 epic_napi_irq_off(dev, ep);
1108 __netif_rx_schedule(dev); 1111 __netif_rx_schedule(dev, &ep->napi);
1109 } else 1112 } else
1110 ep->reschedule_in_poll++; 1113 ep->reschedule_in_poll++;
1111 spin_unlock(&ep->napi_lock); 1114 spin_unlock(&ep->napi_lock);
@@ -1257,26 +1260,22 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
1257 outw(RxQueued, ioaddr + COMMAND); 1260 outw(RxQueued, ioaddr + COMMAND);
1258} 1261}
1259 1262
1260static int epic_poll(struct net_device *dev, int *budget) 1263static int epic_poll(struct napi_struct *napi, int budget)
1261{ 1264{
1262 struct epic_private *ep = dev->priv; 1265 struct epic_private *ep = container_of(napi, struct epic_private, napi);
1263 int work_done = 0, orig_budget; 1266 struct net_device *dev = ep->mii.dev;
1267 int work_done = 0;
1264 long ioaddr = dev->base_addr; 1268 long ioaddr = dev->base_addr;
1265 1269
1266 orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
1267
1268rx_action: 1270rx_action:
1269 1271
1270 epic_tx(dev, ep); 1272 epic_tx(dev, ep);
1271 1273
1272 work_done += epic_rx(dev, *budget); 1274 work_done += epic_rx(dev, budget);
1273 1275
1274 epic_rx_err(dev, ep); 1276 epic_rx_err(dev, ep);
1275 1277
1276 *budget -= work_done; 1278 if (netif_running(dev) && (work_done < budget)) {
1277 dev->quota -= work_done;
1278
1279 if (netif_running(dev) && (work_done < orig_budget)) {
1280 unsigned long flags; 1279 unsigned long flags;
1281 int more; 1280 int more;
1282 1281
@@ -1286,7 +1285,7 @@ rx_action:
1286 1285
1287 more = ep->reschedule_in_poll; 1286 more = ep->reschedule_in_poll;
1288 if (!more) { 1287 if (!more) {
1289 __netif_rx_complete(dev); 1288 __netif_rx_complete(dev, napi);
1290 outl(EpicNapiEvent, ioaddr + INTSTAT); 1289 outl(EpicNapiEvent, ioaddr + INTSTAT);
1291 epic_napi_irq_on(dev, ep); 1290 epic_napi_irq_on(dev, ep);
1292 } else 1291 } else
@@ -1298,7 +1297,7 @@ rx_action:
1298 goto rx_action; 1297 goto rx_action;
1299 } 1298 }
1300 1299
1301 return (work_done >= orig_budget); 1300 return work_done;
1302} 1301}
1303 1302
1304static int epic_close(struct net_device *dev) 1303static int epic_close(struct net_device *dev)
@@ -1309,6 +1308,7 @@ static int epic_close(struct net_device *dev)
1309 int i; 1308 int i;
1310 1309
1311 netif_stop_queue(dev); 1310 netif_stop_queue(dev);
1311 napi_disable(&ep->napi);
1312 1312
1313 if (debug > 1) 1313 if (debug > 1)
1314 printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", 1314 printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",