aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fec_8xx
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/fec_8xx
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/fec_8xx')
-rw-r--r--drivers/net/fec_8xx/fec_8xx.h2
-rw-r--r--drivers/net/fec_8xx/fec_main.c59
2 files changed, 31 insertions, 30 deletions
diff --git a/drivers/net/fec_8xx/fec_8xx.h b/drivers/net/fec_8xx/fec_8xx.h
index 5af60b0f9208..f3b1c6fbba8b 100644
--- a/drivers/net/fec_8xx/fec_8xx.h
+++ b/drivers/net/fec_8xx/fec_8xx.h
@@ -105,6 +105,8 @@ struct fec;
105struct fec_enet_private { 105struct fec_enet_private {
106 spinlock_t lock; /* during all ops except TX pckt processing */ 106 spinlock_t lock; /* during all ops except TX pckt processing */
107 spinlock_t tx_lock; /* during fec_start_xmit and fec_tx */ 107 spinlock_t tx_lock; /* during fec_start_xmit and fec_tx */
108 struct net_device *dev;
109 struct napi_struct napi;
108 int fecno; 110 int fecno;
109 struct fec *fecp; 111 struct fec *fecp;
110 const struct fec_platform_info *fpi; 112 const struct fec_platform_info *fpi;
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index e5502af5b8e2..6348fb93ca9c 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -465,9 +465,9 @@ void fec_stop(struct net_device *dev)
465} 465}
466 466
467/* common receive function */ 467/* common receive function */
468static int fec_enet_rx_common(struct net_device *dev, int *budget) 468static int fec_enet_rx_common(struct fec_enet_private *ep,
469 struct net_device *dev, int budget)
469{ 470{
470 struct fec_enet_private *fep = netdev_priv(dev);
471 fec_t *fecp = fep->fecp; 471 fec_t *fecp = fep->fecp;
472 const struct fec_platform_info *fpi = fep->fpi; 472 const struct fec_platform_info *fpi = fep->fpi;
473 cbd_t *bdp; 473 cbd_t *bdp;
@@ -475,11 +475,8 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
475 int received = 0; 475 int received = 0;
476 __u16 pkt_len, sc; 476 __u16 pkt_len, sc;
477 int curidx; 477 int curidx;
478 int rx_work_limit;
479 478
480 if (fpi->use_napi) { 479 if (fpi->use_napi) {
481 rx_work_limit = min(dev->quota, *budget);
482
483 if (!netif_running(dev)) 480 if (!netif_running(dev))
484 return 0; 481 return 0;
485 } 482 }
@@ -530,11 +527,6 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
530 BUG_ON(skbn == NULL); 527 BUG_ON(skbn == NULL);
531 528
532 } else { 529 } else {
533
534 /* napi, got packet but no quota */
535 if (fpi->use_napi && --rx_work_limit < 0)
536 break;
537
538 skb = fep->rx_skbuff[curidx]; 530 skb = fep->rx_skbuff[curidx];
539 BUG_ON(skb == NULL); 531 BUG_ON(skb == NULL);
540 532
@@ -599,25 +591,24 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
599 * able to keep up at the expense of system resources. 591 * able to keep up at the expense of system resources.
600 */ 592 */
601 FW(fecp, r_des_active, 0x01000000); 593 FW(fecp, r_des_active, 0x01000000);
594
595 if (received >= budget)
596 break;
597
602 } 598 }
603 599
604 fep->cur_rx = bdp; 600 fep->cur_rx = bdp;
605 601
606 if (fpi->use_napi) { 602 if (fpi->use_napi) {
607 dev->quota -= received; 603 if (received < budget) {
608 *budget -= received; 604 netif_rx_complete(dev, &fep->napi);
609
610 if (rx_work_limit < 0)
611 return 1; /* not done */
612 605
613 /* done */ 606 /* enable RX interrupt bits */
614 netif_rx_complete(dev); 607 FS(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
615 608 }
616 /* enable RX interrupt bits */
617 FS(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
618 } 609 }
619 610
620 return 0; 611 return received;
621} 612}
622 613
623static void fec_enet_tx(struct net_device *dev) 614static void fec_enet_tx(struct net_device *dev)
@@ -743,12 +734,12 @@ fec_enet_interrupt(int irq, void *dev_id)
743 734
744 if ((int_events & FEC_ENET_RXF) != 0) { 735 if ((int_events & FEC_ENET_RXF) != 0) {
745 if (!fpi->use_napi) 736 if (!fpi->use_napi)
746 fec_enet_rx_common(dev, NULL); 737 fec_enet_rx_common(fep, dev, ~0);
747 else { 738 else {
748 if (netif_rx_schedule_prep(dev)) { 739 if (netif_rx_schedule_prep(dev, &fep->napi)) {
749 /* disable rx interrupts */ 740 /* disable rx interrupts */
750 FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB); 741 FC(fecp, imask, FEC_ENET_RXF | FEC_ENET_RXB);
751 __netif_rx_schedule(dev); 742 __netif_rx_schedule(dev, &fep->napi);
752 } else { 743 } else {
753 printk(KERN_ERR DRV_MODULE_NAME 744 printk(KERN_ERR DRV_MODULE_NAME
754 ": %s driver bug! interrupt while in poll!\n", 745 ": %s driver bug! interrupt while in poll!\n",
@@ -893,10 +884,13 @@ static int fec_enet_open(struct net_device *dev)
893 const struct fec_platform_info *fpi = fep->fpi; 884 const struct fec_platform_info *fpi = fep->fpi;
894 unsigned long flags; 885 unsigned long flags;
895 886
887 napi_enable(&fep->napi);
888
896 /* Install our interrupt handler. */ 889 /* Install our interrupt handler. */
897 if (request_irq(fpi->fec_irq, fec_enet_interrupt, 0, "fec", dev) != 0) { 890 if (request_irq(fpi->fec_irq, fec_enet_interrupt, 0, "fec", dev) != 0) {
898 printk(KERN_ERR DRV_MODULE_NAME 891 printk(KERN_ERR DRV_MODULE_NAME
899 ": %s Could not allocate FEC IRQ!", dev->name); 892 ": %s Could not allocate FEC IRQ!", dev->name);
893 napi_disable(&fep->napi);
900 return -EINVAL; 894 return -EINVAL;
901 } 895 }
902 896
@@ -907,6 +901,7 @@ static int fec_enet_open(struct net_device *dev)
907 printk(KERN_ERR DRV_MODULE_NAME 901 printk(KERN_ERR DRV_MODULE_NAME
908 ": %s Could not allocate PHY IRQ!", dev->name); 902 ": %s Could not allocate PHY IRQ!", dev->name);
909 free_irq(fpi->fec_irq, dev); 903 free_irq(fpi->fec_irq, dev);
904 napi_disable(&fep->napi);
910 return -EINVAL; 905 return -EINVAL;
911 } 906 }
912 907
@@ -932,6 +927,7 @@ static int fec_enet_close(struct net_device *dev)
932 unsigned long flags; 927 unsigned long flags;
933 928
934 netif_stop_queue(dev); 929 netif_stop_queue(dev);
930 napi_disable(&fep->napi);
935 netif_carrier_off(dev); 931 netif_carrier_off(dev);
936 932
937 if (fpi->use_mdio) 933 if (fpi->use_mdio)
@@ -955,9 +951,12 @@ static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
955 return &fep->stats; 951 return &fep->stats;
956} 952}
957 953
958static int fec_enet_poll(struct net_device *dev, int *budget) 954static int fec_enet_poll(struct napi_struct *napi, int budget)
959{ 955{
960 return fec_enet_rx_common(dev, budget); 956 struct fec_enet_private *fep = container_of(napi, struct fec_enet_private, napi);
957 struct net_device *dev = fep->dev;
958
959 return fec_enet_rx_common(fep, dev, budget);
961} 960}
962 961
963/*************************************************************************/ 962/*************************************************************************/
@@ -1107,6 +1106,7 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi,
1107 SET_MODULE_OWNER(dev); 1106 SET_MODULE_OWNER(dev);
1108 1107
1109 fep = netdev_priv(dev); 1108 fep = netdev_priv(dev);
1109 fep->dev = dev;
1110 1110
1111 /* partial reset of FEC */ 1111 /* partial reset of FEC */
1112 fec_whack_reset(fecp); 1112 fec_whack_reset(fecp);
@@ -1172,10 +1172,9 @@ int fec_8xx_init_one(const struct fec_platform_info *fpi,
1172 dev->get_stats = fec_enet_get_stats; 1172 dev->get_stats = fec_enet_get_stats;
1173 dev->set_multicast_list = fec_set_multicast_list; 1173 dev->set_multicast_list = fec_set_multicast_list;
1174 dev->set_mac_address = fec_set_mac_address; 1174 dev->set_mac_address = fec_set_mac_address;
1175 if (fpi->use_napi) { 1175 netif_napi_add(dev, &fec->napi,
1176 dev->poll = fec_enet_poll; 1176 fec_enet_poll, fpi->napi_weight);
1177 dev->weight = fpi->napi_weight; 1177
1178 }
1179 dev->ethtool_ops = &fec_ethtool_ops; 1178 dev->ethtool_ops = &fec_ethtool_ops;
1180 dev->do_ioctl = fec_ioctl; 1179 dev->do_ioctl = fec_ioctl;
1181 1180