aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/starfire.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/starfire.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/starfire.c')
-rw-r--r--drivers/net/starfire.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 8b6478663a56..3b9336c34206 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -178,16 +178,13 @@ static int full_duplex[MAX_UNITS] = {0, };
178#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1) 178#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
179 179
180#ifdef HAVE_NETDEV_POLL 180#ifdef HAVE_NETDEV_POLL
181#define init_poll(dev) \ 181#define init_poll(dev, np) \
182do { \ 182 netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work)
183 dev->poll = &netdev_poll; \ 183#define netdev_rx(dev, np, ioaddr) \
184 dev->weight = max_interrupt_work; \
185} while (0)
186#define netdev_rx(dev, ioaddr) \
187do { \ 184do { \
188 u32 intr_enable; \ 185 u32 intr_enable; \
189 if (netif_rx_schedule_prep(dev)) { \ 186 if (netif_rx_schedule_prep(dev, &np->napi)) { \
190 __netif_rx_schedule(dev); \ 187 __netif_rx_schedule(dev, &np->napi); \
191 intr_enable = readl(ioaddr + IntrEnable); \ 188 intr_enable = readl(ioaddr + IntrEnable); \
192 intr_enable &= ~(IntrRxDone | IntrRxEmpty); \ 189 intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
193 writel(intr_enable, ioaddr + IntrEnable); \ 190 writel(intr_enable, ioaddr + IntrEnable); \
@@ -204,12 +201,12 @@ do { \
204} while (0) 201} while (0)
205#define netdev_receive_skb(skb) netif_receive_skb(skb) 202#define netdev_receive_skb(skb) netif_receive_skb(skb)
206#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_receive_skb(skb, vlgrp, vlid) 203#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_receive_skb(skb, vlgrp, vlid)
207static int netdev_poll(struct net_device *dev, int *budget); 204static int netdev_poll(struct napi_struct *napi, int budget);
208#else /* not HAVE_NETDEV_POLL */ 205#else /* not HAVE_NETDEV_POLL */
209#define init_poll(dev) 206#define init_poll(dev, np)
210#define netdev_receive_skb(skb) netif_rx(skb) 207#define netdev_receive_skb(skb) netif_rx(skb)
211#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_rx(skb, vlgrp, vlid) 208#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_rx(skb, vlgrp, vlid)
212#define netdev_rx(dev, ioaddr) \ 209#define netdev_rx(dev, np, ioaddr) \
213do { \ 210do { \
214 int quota = np->dirty_rx + RX_RING_SIZE - np->cur_rx; \ 211 int quota = np->dirty_rx + RX_RING_SIZE - np->cur_rx; \
215 __netdev_rx(dev, &quota);\ 212 __netdev_rx(dev, &quota);\
@@ -599,6 +596,8 @@ struct netdev_private {
599 struct tx_done_desc *tx_done_q; 596 struct tx_done_desc *tx_done_q;
600 dma_addr_t tx_done_q_dma; 597 dma_addr_t tx_done_q_dma;
601 unsigned int tx_done; 598 unsigned int tx_done;
599 struct napi_struct napi;
600 struct net_device *dev;
602 struct net_device_stats stats; 601 struct net_device_stats stats;
603 struct pci_dev *pci_dev; 602 struct pci_dev *pci_dev;
604#ifdef VLAN_SUPPORT 603#ifdef VLAN_SUPPORT
@@ -791,6 +790,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
791 dev->irq = irq; 790 dev->irq = irq;
792 791
793 np = netdev_priv(dev); 792 np = netdev_priv(dev);
793 np->dev = dev;
794 np->base = base; 794 np->base = base;
795 spin_lock_init(&np->lock); 795 spin_lock_init(&np->lock);
796 pci_set_drvdata(pdev, dev); 796 pci_set_drvdata(pdev, dev);
@@ -851,7 +851,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
851 dev->hard_start_xmit = &start_tx; 851 dev->hard_start_xmit = &start_tx;
852 dev->tx_timeout = tx_timeout; 852 dev->tx_timeout = tx_timeout;
853 dev->watchdog_timeo = TX_TIMEOUT; 853 dev->watchdog_timeo = TX_TIMEOUT;
854 init_poll(dev); 854 init_poll(dev, np);
855 dev->stop = &netdev_close; 855 dev->stop = &netdev_close;
856 dev->get_stats = &get_stats; 856 dev->get_stats = &get_stats;
857 dev->set_multicast_list = &set_rx_mode; 857 dev->set_multicast_list = &set_rx_mode;
@@ -1056,6 +1056,9 @@ static int netdev_open(struct net_device *dev)
1056 1056
1057 writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl); 1057 writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
1058 1058
1059#ifdef HAVE_NETDEV_POLL
1060 napi_enable(&np->napi);
1061#endif
1059 netif_start_queue(dev); 1062 netif_start_queue(dev);
1060 1063
1061 if (debug > 1) 1064 if (debug > 1)
@@ -1330,7 +1333,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
1330 handled = 1; 1333 handled = 1;
1331 1334
1332 if (intr_status & (IntrRxDone | IntrRxEmpty)) 1335 if (intr_status & (IntrRxDone | IntrRxEmpty))
1333 netdev_rx(dev, ioaddr); 1336 netdev_rx(dev, np, ioaddr);
1334 1337
1335 /* Scavenge the skbuff list based on the Tx-done queue. 1338 /* Scavenge the skbuff list based on the Tx-done queue.
1336 There are redundant checks here that may be cleaned up 1339 There are redundant checks here that may be cleaned up
@@ -1531,36 +1534,35 @@ static int __netdev_rx(struct net_device *dev, int *quota)
1531 1534
1532 1535
1533#ifdef HAVE_NETDEV_POLL 1536#ifdef HAVE_NETDEV_POLL
1534static int netdev_poll(struct net_device *dev, int *budget) 1537static int netdev_poll(struct napi_struct *napi, int budget)
1535{ 1538{
1539 struct netdev_private *np = container_of(napi, struct netdev_private, napi);
1540 struct net_device *dev = np->dev;
1536 u32 intr_status; 1541 u32 intr_status;
1537 struct netdev_private *np = netdev_priv(dev);
1538 void __iomem *ioaddr = np->base; 1542 void __iomem *ioaddr = np->base;
1539 int retcode = 0, quota = dev->quota; 1543 int quota = budget;
1540 1544
1541 do { 1545 do {
1542 writel(IntrRxDone | IntrRxEmpty, ioaddr + IntrClear); 1546 writel(IntrRxDone | IntrRxEmpty, ioaddr + IntrClear);
1543 1547
1544 retcode = __netdev_rx(dev, &quota); 1548 if (__netdev_rx(dev, &quota))
1545 *budget -= (dev->quota - quota);
1546 dev->quota = quota;
1547 if (retcode)
1548 goto out; 1549 goto out;
1549 1550
1550 intr_status = readl(ioaddr + IntrStatus); 1551 intr_status = readl(ioaddr + IntrStatus);
1551 } while (intr_status & (IntrRxDone | IntrRxEmpty)); 1552 } while (intr_status & (IntrRxDone | IntrRxEmpty));
1552 1553
1553 netif_rx_complete(dev); 1554 netif_rx_complete(dev, napi);
1554 intr_status = readl(ioaddr + IntrEnable); 1555 intr_status = readl(ioaddr + IntrEnable);
1555 intr_status |= IntrRxDone | IntrRxEmpty; 1556 intr_status |= IntrRxDone | IntrRxEmpty;
1556 writel(intr_status, ioaddr + IntrEnable); 1557 writel(intr_status, ioaddr + IntrEnable);
1557 1558
1558 out: 1559 out:
1559 if (debug > 5) 1560 if (debug > 5)
1560 printk(KERN_DEBUG " exiting netdev_poll(): %d.\n", retcode); 1561 printk(KERN_DEBUG " exiting netdev_poll(): %d.\n",
1562 budget - quota);
1561 1563
1562 /* Restart Rx engine if stopped. */ 1564 /* Restart Rx engine if stopped. */
1563 return retcode; 1565 return budget - quota;
1564} 1566}
1565#endif /* HAVE_NETDEV_POLL */ 1567#endif /* HAVE_NETDEV_POLL */
1566 1568
@@ -1904,6 +1906,9 @@ static int netdev_close(struct net_device *dev)
1904 int i; 1906 int i;
1905 1907
1906 netif_stop_queue(dev); 1908 netif_stop_queue(dev);
1909#ifdef HAVE_NETDEV_POLL
1910 napi_disable(&np->napi);
1911#endif
1907 1912
1908 if (debug > 1) { 1913 if (debug > 1) {
1909 printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n", 1914 printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",