aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sb1250-mac.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/sb1250-mac.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/sb1250-mac.c')
-rw-r--r--drivers/net/sb1250-mac.c47
1 files changed, 18 insertions, 29 deletions
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index e7fdcf15b5a7..53845ebb649f 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -238,6 +238,7 @@ struct sbmac_softc {
238 */ 238 */
239 239
240 struct net_device *sbm_dev; /* pointer to linux device */ 240 struct net_device *sbm_dev; /* pointer to linux device */
241 struct napi_struct napi;
241 spinlock_t sbm_lock; /* spin lock */ 242 spinlock_t sbm_lock; /* spin lock */
242 struct timer_list sbm_timer; /* for monitoring MII */ 243 struct timer_list sbm_timer; /* for monitoring MII */
243 struct net_device_stats sbm_stats; 244 struct net_device_stats sbm_stats;
@@ -320,7 +321,7 @@ static struct net_device_stats *sbmac_get_stats(struct net_device *dev);
320static void sbmac_set_rx_mode(struct net_device *dev); 321static void sbmac_set_rx_mode(struct net_device *dev);
321static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 322static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
322static int sbmac_close(struct net_device *dev); 323static int sbmac_close(struct net_device *dev);
323static int sbmac_poll(struct net_device *poll_dev, int *budget); 324static int sbmac_poll(struct napi_struct *napi, int budget);
324 325
325static int sbmac_mii_poll(struct sbmac_softc *s,int noisy); 326static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
326static int sbmac_mii_probe(struct net_device *dev); 327static int sbmac_mii_probe(struct net_device *dev);
@@ -2154,20 +2155,13 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance)
2154 * Transmits on channel 0 2155 * Transmits on channel 0
2155 */ 2156 */
2156 2157
2157 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) { 2158 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0))
2158 sbdma_tx_process(sc,&(sc->sbm_txdma), 0); 2159 sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
2159#ifdef CONFIG_NETPOLL_TRAP
2160 if (netpoll_trap()) {
2161 if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
2162 __netif_schedule(dev);
2163 }
2164#endif
2165 }
2166 2160
2167 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { 2161 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
2168 if (netif_rx_schedule_prep(dev)) { 2162 if (netif_rx_schedule_prep(dev, &sc->napi)) {
2169 __raw_writeq(0, sc->sbm_imr); 2163 __raw_writeq(0, sc->sbm_imr);
2170 __netif_rx_schedule(dev); 2164 __netif_rx_schedule(dev, &sc->napi);
2171 /* Depend on the exit from poll to reenable intr */ 2165 /* Depend on the exit from poll to reenable intr */
2172 } 2166 }
2173 else { 2167 else {
@@ -2470,8 +2464,8 @@ static int sbmac_init(struct net_device *dev, int idx)
2470 dev->do_ioctl = sbmac_mii_ioctl; 2464 dev->do_ioctl = sbmac_mii_ioctl;
2471 dev->tx_timeout = sbmac_tx_timeout; 2465 dev->tx_timeout = sbmac_tx_timeout;
2472 dev->watchdog_timeo = TX_TIMEOUT; 2466 dev->watchdog_timeo = TX_TIMEOUT;
2473 dev->poll = sbmac_poll; 2467
2474 dev->weight = 16; 2468 netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
2475 2469
2476 dev->change_mtu = sb1250_change_mtu; 2470 dev->change_mtu = sb1250_change_mtu;
2477#ifdef CONFIG_NET_POLL_CONTROLLER 2471#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2537,6 +2531,8 @@ static int sbmac_open(struct net_device *dev)
2537 return -EINVAL; 2531 return -EINVAL;
2538 } 2532 }
2539 2533
2534 napi_enable(&sc->napi);
2535
2540 /* 2536 /*
2541 * Configure default speed 2537 * Configure default speed
2542 */ 2538 */
@@ -2850,6 +2846,8 @@ static int sbmac_close(struct net_device *dev)
2850 unsigned long flags; 2846 unsigned long flags;
2851 int irq; 2847 int irq;
2852 2848
2849 napi_disable(&sc->napi);
2850
2853 sbmac_set_channel_state(sc,sbmac_state_off); 2851 sbmac_set_channel_state(sc,sbmac_state_off);
2854 2852
2855 del_timer_sync(&sc->sbm_timer); 2853 del_timer_sync(&sc->sbm_timer);
@@ -2874,26 +2872,17 @@ static int sbmac_close(struct net_device *dev)
2874 return 0; 2872 return 0;
2875} 2873}
2876 2874
2877static int sbmac_poll(struct net_device *dev, int *budget) 2875static int sbmac_poll(struct napi_struct *napi, int budget)
2878{ 2876{
2879 int work_to_do; 2877 struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi);
2878 struct net_device *dev = sc->sbm_dev;
2880 int work_done; 2879 int work_done;
2881 struct sbmac_softc *sc = netdev_priv(dev);
2882
2883 work_to_do = min(*budget, dev->quota);
2884 work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), work_to_do, 1);
2885
2886 if (work_done > work_to_do)
2887 printk(KERN_ERR "%s exceeded work_to_do budget=%d quota=%d work-done=%d\n",
2888 sc->sbm_dev->name, *budget, dev->quota, work_done);
2889 2880
2881 work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1);
2890 sbdma_tx_process(sc, &(sc->sbm_txdma), 1); 2882 sbdma_tx_process(sc, &(sc->sbm_txdma), 1);
2891 2883
2892 *budget -= work_done; 2884 if (work_done < budget) {
2893 dev->quota -= work_done; 2885 netif_rx_complete(dev, napi);
2894
2895 if (work_done < work_to_do) {
2896 netif_rx_complete(dev);
2897 2886
2898#ifdef CONFIG_SBMAC_COALESCE 2887#ifdef CONFIG_SBMAC_COALESCE
2899 __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 2888 __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
@@ -2905,7 +2894,7 @@ static int sbmac_poll(struct net_device *dev, int *budget)
2905#endif 2894#endif
2906 } 2895 }
2907 2896
2908 return (work_done >= work_to_do); 2897 return work_done;
2909} 2898}
2910 2899
2911#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR) 2900#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)