aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ucc_geth.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/ucc_geth.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/ucc_geth.c')
-rw-r--r--drivers/net/ucc_geth.c64
1 files changed, 33 insertions, 31 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 9a38dfe45f8f..72f617bf2520 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3582,41 +3582,31 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
3582} 3582}
3583 3583
3584#ifdef CONFIG_UGETH_NAPI 3584#ifdef CONFIG_UGETH_NAPI
3585static int ucc_geth_poll(struct net_device *dev, int *budget) 3585static int ucc_geth_poll(struct napi_struct *napi, int budget)
3586{ 3586{
3587 struct ucc_geth_private *ugeth = netdev_priv(dev); 3587 struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
3588 struct net_device *dev = ugeth->dev;
3588 struct ucc_geth_info *ug_info; 3589 struct ucc_geth_info *ug_info;
3589 struct ucc_fast_private *uccf; 3590 int howmany, i;
3590 int howmany;
3591 u8 i;
3592 int rx_work_limit;
3593 register u32 uccm;
3594 3591
3595 ug_info = ugeth->ug_info; 3592 ug_info = ugeth->ug_info;
3596 3593
3597 rx_work_limit = *budget;
3598 if (rx_work_limit > dev->quota)
3599 rx_work_limit = dev->quota;
3600
3601 howmany = 0; 3594 howmany = 0;
3595 for (i = 0; i < ug_info->numQueuesRx; i++)
3596 howmany += ucc_geth_rx(ugeth, i, budget - howmany);
3602 3597
3603 for (i = 0; i < ug_info->numQueuesRx; i++) { 3598 if (howmany < budget) {
3604 howmany += ucc_geth_rx(ugeth, i, rx_work_limit); 3599 struct ucc_fast_private *uccf;
3605 } 3600 u32 uccm;
3606
3607 dev->quota -= howmany;
3608 rx_work_limit -= howmany;
3609 *budget -= howmany;
3610 3601
3611 if (rx_work_limit > 0) { 3602 netif_rx_complete(dev, napi);
3612 netif_rx_complete(dev);
3613 uccf = ugeth->uccf; 3603 uccf = ugeth->uccf;
3614 uccm = in_be32(uccf->p_uccm); 3604 uccm = in_be32(uccf->p_uccm);
3615 uccm |= UCCE_RX_EVENTS; 3605 uccm |= UCCE_RX_EVENTS;
3616 out_be32(uccf->p_uccm, uccm); 3606 out_be32(uccf->p_uccm, uccm);
3617 } 3607 }
3618 3608
3619 return (rx_work_limit > 0) ? 0 : 1; 3609 return howmany;
3620} 3610}
3621#endif /* CONFIG_UGETH_NAPI */ 3611#endif /* CONFIG_UGETH_NAPI */
3622 3612
@@ -3651,10 +3641,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
3651 /* check for receive events that require processing */ 3641 /* check for receive events that require processing */
3652 if (ucce & UCCE_RX_EVENTS) { 3642 if (ucce & UCCE_RX_EVENTS) {
3653#ifdef CONFIG_UGETH_NAPI 3643#ifdef CONFIG_UGETH_NAPI
3654 if (netif_rx_schedule_prep(dev)) { 3644 if (netif_rx_schedule_prep(dev, &ugeth->napi)) {
3655 uccm &= ~UCCE_RX_EVENTS; 3645 uccm &= ~UCCE_RX_EVENTS;
3656 out_be32(uccf->p_uccm, uccm); 3646 out_be32(uccf->p_uccm, uccm);
3657 __netif_rx_schedule(dev); 3647 __netif_rx_schedule(dev, &ugeth->napi);
3658 } 3648 }
3659#else 3649#else
3660 rx_mask = UCCE_RXBF_SINGLE_MASK; 3650 rx_mask = UCCE_RXBF_SINGLE_MASK;
@@ -3717,12 +3707,15 @@ static int ucc_geth_open(struct net_device *dev)
3717 return err; 3707 return err;
3718 } 3708 }
3719 3709
3710#ifdef CONFIG_UGETH_NAPI
3711 napi_enable(&ugeth->napi);
3712#endif
3720 err = ucc_geth_startup(ugeth); 3713 err = ucc_geth_startup(ugeth);
3721 if (err) { 3714 if (err) {
3722 if (netif_msg_ifup(ugeth)) 3715 if (netif_msg_ifup(ugeth))
3723 ugeth_err("%s: Cannot configure net device, aborting.", 3716 ugeth_err("%s: Cannot configure net device, aborting.",
3724 dev->name); 3717 dev->name);
3725 return err; 3718 goto out_err;
3726 } 3719 }
3727 3720
3728 err = adjust_enet_interface(ugeth); 3721 err = adjust_enet_interface(ugeth);
@@ -3730,7 +3723,7 @@ static int ucc_geth_open(struct net_device *dev)
3730 if (netif_msg_ifup(ugeth)) 3723 if (netif_msg_ifup(ugeth))
3731 ugeth_err("%s: Cannot configure net device, aborting.", 3724 ugeth_err("%s: Cannot configure net device, aborting.",
3732 dev->name); 3725 dev->name);
3733 return err; 3726 goto out_err;
3734 } 3727 }
3735 3728
3736 /* Set MACSTNADDR1, MACSTNADDR2 */ 3729 /* Set MACSTNADDR1, MACSTNADDR2 */
@@ -3748,7 +3741,7 @@ static int ucc_geth_open(struct net_device *dev)
3748 if (err) { 3741 if (err) {
3749 if (netif_msg_ifup(ugeth)) 3742 if (netif_msg_ifup(ugeth))
3750 ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); 3743 ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name);
3751 return err; 3744 goto out_err;
3752 } 3745 }
3753 3746
3754 phy_start(ugeth->phydev); 3747 phy_start(ugeth->phydev);
@@ -3761,7 +3754,7 @@ static int ucc_geth_open(struct net_device *dev)
3761 ugeth_err("%s: Cannot get IRQ for net device, aborting.", 3754 ugeth_err("%s: Cannot get IRQ for net device, aborting.",
3762 dev->name); 3755 dev->name);
3763 ucc_geth_stop(ugeth); 3756 ucc_geth_stop(ugeth);
3764 return err; 3757 goto out_err;
3765 } 3758 }
3766 3759
3767 err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); 3760 err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
@@ -3769,12 +3762,18 @@ static int ucc_geth_open(struct net_device *dev)
3769 if (netif_msg_ifup(ugeth)) 3762 if (netif_msg_ifup(ugeth))
3770 ugeth_err("%s: Cannot enable net device, aborting.", dev->name); 3763 ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
3771 ucc_geth_stop(ugeth); 3764 ucc_geth_stop(ugeth);
3772 return err; 3765 goto out_err;
3773 } 3766 }
3774 3767
3775 netif_start_queue(dev); 3768 netif_start_queue(dev);
3776 3769
3777 return err; 3770 return err;
3771
3772out_err:
3773#ifdef CONFIG_UGETH_NAPI
3774 napi_disable(&ugeth->napi);
3775#endif
3776 return err;
3778} 3777}
3779 3778
3780/* Stops the kernel queue, and halts the controller */ 3779/* Stops the kernel queue, and halts the controller */
@@ -3784,6 +3783,10 @@ static int ucc_geth_close(struct net_device *dev)
3784 3783
3785 ugeth_vdbg("%s: IN", __FUNCTION__); 3784 ugeth_vdbg("%s: IN", __FUNCTION__);
3786 3785
3786#ifdef CONFIG_UGETH_NAPI
3787 napi_disable(&ugeth->napi);
3788#endif
3789
3787 ucc_geth_stop(ugeth); 3790 ucc_geth_stop(ugeth);
3788 3791
3789 phy_disconnect(ugeth->phydev); 3792 phy_disconnect(ugeth->phydev);
@@ -3964,8 +3967,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3964 dev->tx_timeout = ucc_geth_timeout; 3967 dev->tx_timeout = ucc_geth_timeout;
3965 dev->watchdog_timeo = TX_TIMEOUT; 3968 dev->watchdog_timeo = TX_TIMEOUT;
3966#ifdef CONFIG_UGETH_NAPI 3969#ifdef CONFIG_UGETH_NAPI
3967 dev->poll = ucc_geth_poll; 3970 netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
3968 dev->weight = UCC_GETH_DEV_WEIGHT;
3969#endif /* CONFIG_UGETH_NAPI */ 3971#endif /* CONFIG_UGETH_NAPI */
3970 dev->stop = ucc_geth_close; 3972 dev->stop = ucc_geth_close;
3971 dev->get_stats = ucc_geth_get_stats; 3973 dev->get_stats = ucc_geth_get_stats;