aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/gianfar.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/gianfar.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/gianfar.c')
-rw-r--r--drivers/net/gianfar.c47
1 files changed, 23 insertions, 24 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index f92690555dd9..bd2de325bbdd 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -134,7 +134,7 @@ static void gfar_configure_serdes(struct net_device *dev);
134extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); 134extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
135extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); 135extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
136#ifdef CONFIG_GFAR_NAPI 136#ifdef CONFIG_GFAR_NAPI
137static int gfar_poll(struct net_device *dev, int *budget); 137static int gfar_poll(struct napi_struct *napi, int budget);
138#endif 138#endif
139#ifdef CONFIG_NET_POLL_CONTROLLER 139#ifdef CONFIG_NET_POLL_CONTROLLER
140static void gfar_netpoll(struct net_device *dev); 140static void gfar_netpoll(struct net_device *dev);
@@ -188,6 +188,7 @@ static int gfar_probe(struct platform_device *pdev)
188 return -ENOMEM; 188 return -ENOMEM;
189 189
190 priv = netdev_priv(dev); 190 priv = netdev_priv(dev);
191 priv->dev = dev;
191 192
192 /* Set the info in the priv to the current info */ 193 /* Set the info in the priv to the current info */
193 priv->einfo = einfo; 194 priv->einfo = einfo;
@@ -261,10 +262,7 @@ static int gfar_probe(struct platform_device *pdev)
261 dev->hard_start_xmit = gfar_start_xmit; 262 dev->hard_start_xmit = gfar_start_xmit;
262 dev->tx_timeout = gfar_timeout; 263 dev->tx_timeout = gfar_timeout;
263 dev->watchdog_timeo = TX_TIMEOUT; 264 dev->watchdog_timeo = TX_TIMEOUT;
264#ifdef CONFIG_GFAR_NAPI 265 netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT);
265 dev->poll = gfar_poll;
266 dev->weight = GFAR_DEV_WEIGHT;
267#endif
268#ifdef CONFIG_NET_POLL_CONTROLLER 266#ifdef CONFIG_NET_POLL_CONTROLLER
269 dev->poll_controller = gfar_netpoll; 267 dev->poll_controller = gfar_netpoll;
270#endif 268#endif
@@ -939,6 +937,8 @@ static int gfar_enet_open(struct net_device *dev)
939{ 937{
940 int err; 938 int err;
941 939
940 napi_enable(&priv->napi);
941
942 /* Initialize a bunch of registers */ 942 /* Initialize a bunch of registers */
943 init_registers(dev); 943 init_registers(dev);
944 944
@@ -946,10 +946,14 @@ static int gfar_enet_open(struct net_device *dev)
946 946
947 err = init_phy(dev); 947 err = init_phy(dev);
948 948
949 if(err) 949 if(err) {
950 napi_disable(&priv->napi);
950 return err; 951 return err;
952 }
951 953
952 err = startup_gfar(dev); 954 err = startup_gfar(dev);
955 if (err)
956 napi_disable(&priv->napi);
953 957
954 netif_start_queue(dev); 958 netif_start_queue(dev);
955 959
@@ -1102,6 +1106,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1102static int gfar_close(struct net_device *dev) 1106static int gfar_close(struct net_device *dev)
1103{ 1107{
1104 struct gfar_private *priv = netdev_priv(dev); 1108 struct gfar_private *priv = netdev_priv(dev);
1109
1110 napi_disable(&priv->napi);
1111
1105 stop_gfar(dev); 1112 stop_gfar(dev);
1106 1113
1107 /* Disconnect from the PHY */ 1114 /* Disconnect from the PHY */
@@ -1318,7 +1325,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
1318 return NULL; 1325 return NULL;
1319 1326
1320 alignamount = RXBUF_ALIGNMENT - 1327 alignamount = RXBUF_ALIGNMENT -
1321 (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)); 1328 (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1));
1322 1329
1323 /* We need the data buffer to be aligned properly. We will reserve 1330 /* We need the data buffer to be aligned properly. We will reserve
1324 * as many bytes as needed to align the data properly 1331 * as many bytes as needed to align the data properly
@@ -1390,12 +1397,12 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
1390 1397
1391 /* support NAPI */ 1398 /* support NAPI */
1392#ifdef CONFIG_GFAR_NAPI 1399#ifdef CONFIG_GFAR_NAPI
1393 if (netif_rx_schedule_prep(dev)) { 1400 if (netif_rx_schedule_prep(dev, &priv->napi)) {
1394 tempval = gfar_read(&priv->regs->imask); 1401 tempval = gfar_read(&priv->regs->imask);
1395 tempval &= IMASK_RX_DISABLED; 1402 tempval &= IMASK_RX_DISABLED;
1396 gfar_write(&priv->regs->imask, tempval); 1403 gfar_write(&priv->regs->imask, tempval);
1397 1404
1398 __netif_rx_schedule(dev); 1405 __netif_rx_schedule(dev, &priv->napi);
1399 } else { 1406 } else {
1400 if (netif_msg_rx_err(priv)) 1407 if (netif_msg_rx_err(priv))
1401 printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", 1408 printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
@@ -1569,23 +1576,16 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
1569} 1576}
1570 1577
1571#ifdef CONFIG_GFAR_NAPI 1578#ifdef CONFIG_GFAR_NAPI
1572static int gfar_poll(struct net_device *dev, int *budget) 1579static int gfar_poll(struct napi_struct *napi, int budget)
1573{ 1580{
1581 struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
1582 struct net_device *dev = priv->dev;
1574 int howmany; 1583 int howmany;
1575 struct gfar_private *priv = netdev_priv(dev);
1576 int rx_work_limit = *budget;
1577
1578 if (rx_work_limit > dev->quota)
1579 rx_work_limit = dev->quota;
1580 1584
1581 howmany = gfar_clean_rx_ring(dev, rx_work_limit); 1585 howmany = gfar_clean_rx_ring(dev, budget);
1582 1586
1583 dev->quota -= howmany; 1587 if (howmany < budget) {
1584 rx_work_limit -= howmany; 1588 netif_rx_complete(dev, napi);
1585 *budget -= howmany;
1586
1587 if (rx_work_limit > 0) {
1588 netif_rx_complete(dev);
1589 1589
1590 /* Clear the halt bit in RSTAT */ 1590 /* Clear the halt bit in RSTAT */
1591 gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); 1591 gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
@@ -1601,8 +1601,7 @@ static int gfar_poll(struct net_device *dev, int *budget)
1601 gfar_write(&priv->regs->rxic, 0); 1601 gfar_write(&priv->regs->rxic, 0);
1602 } 1602 }
1603 1603
1604 /* Return 1 if there's more work to do */ 1604 return howmany;
1605 return (rx_work_limit > 0) ? 0 : 1;
1606} 1605}
1607#endif 1606#endif
1608 1607