aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tc35815.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/tc35815.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/tc35815.c')
-rw-r--r--drivers/net/tc35815.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index ec41469eee82..b5e0dff67230 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -414,6 +414,9 @@ enum tc35815_timer_state {
414struct tc35815_local { 414struct tc35815_local {
415 struct pci_dev *pci_dev; 415 struct pci_dev *pci_dev;
416 416
417 struct net_device *dev;
418 struct napi_struct napi;
419
417 /* statistics */ 420 /* statistics */
418 struct net_device_stats stats; 421 struct net_device_stats stats;
419 struct { 422 struct {
@@ -566,7 +569,7 @@ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);
566static irqreturn_t tc35815_interrupt(int irq, void *dev_id); 569static irqreturn_t tc35815_interrupt(int irq, void *dev_id);
567#ifdef TC35815_NAPI 570#ifdef TC35815_NAPI
568static int tc35815_rx(struct net_device *dev, int limit); 571static int tc35815_rx(struct net_device *dev, int limit);
569static int tc35815_poll(struct net_device *dev, int *budget); 572static int tc35815_poll(struct napi_struct *napi, int budget);
570#else 573#else
571static void tc35815_rx(struct net_device *dev); 574static void tc35815_rx(struct net_device *dev);
572#endif 575#endif
@@ -685,6 +688,7 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
685 SET_MODULE_OWNER(dev); 688 SET_MODULE_OWNER(dev);
686 SET_NETDEV_DEV(dev, &pdev->dev); 689 SET_NETDEV_DEV(dev, &pdev->dev);
687 lp = dev->priv; 690 lp = dev->priv;
691 lp->dev = dev;
688 692
689 /* enable device (incl. PCI PM wakeup), and bus-mastering */ 693 /* enable device (incl. PCI PM wakeup), and bus-mastering */
690 rc = pci_enable_device (pdev); 694 rc = pci_enable_device (pdev);
@@ -738,8 +742,7 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
738 dev->tx_timeout = tc35815_tx_timeout; 742 dev->tx_timeout = tc35815_tx_timeout;
739 dev->watchdog_timeo = TC35815_TX_TIMEOUT; 743 dev->watchdog_timeo = TC35815_TX_TIMEOUT;
740#ifdef TC35815_NAPI 744#ifdef TC35815_NAPI
741 dev->poll = tc35815_poll; 745 netif_napi_add(dev, &lp->napi, tc35815_poll, NAPI_WEIGHT);
742 dev->weight = NAPI_WEIGHT;
743#endif 746#endif
744#ifdef CONFIG_NET_POLL_CONTROLLER 747#ifdef CONFIG_NET_POLL_CONTROLLER
745 dev->poll_controller = tc35815_poll_controller; 748 dev->poll_controller = tc35815_poll_controller;
@@ -748,8 +751,6 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
748 dev->irq = pdev->irq; 751 dev->irq = pdev->irq;
749 dev->base_addr = (unsigned long) ioaddr; 752 dev->base_addr = (unsigned long) ioaddr;
750 753
751 /* dev->priv/lp zeroed and aligned in alloc_etherdev */
752 lp = dev->priv;
753 spin_lock_init(&lp->lock); 754 spin_lock_init(&lp->lock);
754 lp->pci_dev = pdev; 755 lp->pci_dev = pdev;
755 lp->boardtype = ent->driver_data; 756 lp->boardtype = ent->driver_data;
@@ -1237,6 +1238,10 @@ tc35815_open(struct net_device *dev)
1237 return -EAGAIN; 1238 return -EAGAIN;
1238 } 1239 }
1239 1240
1241#ifdef TC35815_NAPI
1242 napi_enable(&lp->napi);
1243#endif
1244
1240 /* Reset the hardware here. Don't forget to set the station address. */ 1245 /* Reset the hardware here. Don't forget to set the station address. */
1241 spin_lock_irq(&lp->lock); 1246 spin_lock_irq(&lp->lock);
1242 tc35815_chip_init(dev); 1247 tc35815_chip_init(dev);
@@ -1436,6 +1441,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
1436static irqreturn_t tc35815_interrupt(int irq, void *dev_id) 1441static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
1437{ 1442{
1438 struct net_device *dev = dev_id; 1443 struct net_device *dev = dev_id;
1444 struct tc35815_local *lp = netdev_priv(dev);
1439 struct tc35815_regs __iomem *tr = 1445 struct tc35815_regs __iomem *tr =
1440 (struct tc35815_regs __iomem *)dev->base_addr; 1446 (struct tc35815_regs __iomem *)dev->base_addr;
1441#ifdef TC35815_NAPI 1447#ifdef TC35815_NAPI
@@ -1444,8 +1450,8 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
1444 if (!(dmactl & DMA_IntMask)) { 1450 if (!(dmactl & DMA_IntMask)) {
1445 /* disable interrupts */ 1451 /* disable interrupts */
1446 tc_writel(dmactl | DMA_IntMask, &tr->DMA_Ctl); 1452 tc_writel(dmactl | DMA_IntMask, &tr->DMA_Ctl);
1447 if (netif_rx_schedule_prep(dev)) 1453 if (netif_rx_schedule_prep(dev, &lp->napi))
1448 __netif_rx_schedule(dev); 1454 __netif_rx_schedule(dev, &lp->napi);
1449 else { 1455 else {
1450 printk(KERN_ERR "%s: interrupt taken in poll\n", 1456 printk(KERN_ERR "%s: interrupt taken in poll\n",
1451 dev->name); 1457 dev->name);
@@ -1726,13 +1732,12 @@ tc35815_rx(struct net_device *dev)
1726} 1732}
1727 1733
1728#ifdef TC35815_NAPI 1734#ifdef TC35815_NAPI
1729static int 1735static int tc35815_poll(struct napi_struct *napi, int budget)
1730tc35815_poll(struct net_device *dev, int *budget)
1731{ 1736{
1732 struct tc35815_local *lp = dev->priv; 1737 struct tc35815_local *lp = container_of(napi, struct tc35815_local, napi);
1738 struct net_device *dev = lp->dev;
1733 struct tc35815_regs __iomem *tr = 1739 struct tc35815_regs __iomem *tr =
1734 (struct tc35815_regs __iomem *)dev->base_addr; 1740 (struct tc35815_regs __iomem *)dev->base_addr;
1735 int limit = min(*budget, dev->quota);
1736 int received = 0, handled; 1741 int received = 0, handled;
1737 u32 status; 1742 u32 status;
1738 1743
@@ -1744,23 +1749,19 @@ tc35815_poll(struct net_device *dev, int *budget)
1744 handled = tc35815_do_interrupt(dev, status, limit); 1749 handled = tc35815_do_interrupt(dev, status, limit);
1745 if (handled >= 0) { 1750 if (handled >= 0) {
1746 received += handled; 1751 received += handled;
1747 limit -= handled; 1752 if (received >= budget)
1748 if (limit <= 0)
1749 break; 1753 break;
1750 } 1754 }
1751 status = tc_readl(&tr->Int_Src); 1755 status = tc_readl(&tr->Int_Src);
1752 } while (status); 1756 } while (status);
1753 spin_unlock(&lp->lock); 1757 spin_unlock(&lp->lock);
1754 1758
1755 dev->quota -= received; 1759 if (received < budget) {
1756 *budget -= received; 1760 netif_rx_complete(dev, napi);
1757 if (limit <= 0) 1761 /* enable interrupts */
1758 return 1; 1762 tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
1759 1763 }
1760 netif_rx_complete(dev); 1764 return received;
1761 /* enable interrupts */
1762 tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
1763 return 0;
1764} 1765}
1765#endif 1766#endif
1766 1767
@@ -1949,7 +1950,11 @@ static int
1949tc35815_close(struct net_device *dev) 1950tc35815_close(struct net_device *dev)
1950{ 1951{
1951 struct tc35815_local *lp = dev->priv; 1952 struct tc35815_local *lp = dev->priv;
1953
1952 netif_stop_queue(dev); 1954 netif_stop_queue(dev);
1955#ifdef TC35815_NAPI
1956 napi_disable(&lp->napi);
1957#endif
1953 1958
1954 /* Flush the Tx and disable Rx here. */ 1959 /* Flush the Tx and disable Rx here. */
1955 1960