aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.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/tg3.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/tg3.c')
-rw-r--r--drivers/net/tg3.c61
1 files changed, 28 insertions, 33 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9034a05734ef..ef1e3d1173c4 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -574,7 +574,7 @@ static void tg3_restart_ints(struct tg3 *tp)
574static inline void tg3_netif_stop(struct tg3 *tp) 574static inline void tg3_netif_stop(struct tg3 *tp)
575{ 575{
576 tp->dev->trans_start = jiffies; /* prevent tx timeout */ 576 tp->dev->trans_start = jiffies; /* prevent tx timeout */
577 netif_poll_disable(tp->dev); 577 napi_disable(&tp->napi);
578 netif_tx_disable(tp->dev); 578 netif_tx_disable(tp->dev);
579} 579}
580 580
@@ -585,7 +585,7 @@ static inline void tg3_netif_start(struct tg3 *tp)
585 * so long as all callers are assured to have free tx slots 585 * so long as all callers are assured to have free tx slots
586 * (such as after tg3_init_hw) 586 * (such as after tg3_init_hw)
587 */ 587 */
588 netif_poll_enable(tp->dev); 588 napi_enable(&tp->napi);
589 tp->hw_status->status |= SD_STATUS_UPDATED; 589 tp->hw_status->status |= SD_STATUS_UPDATED;
590 tg3_enable_ints(tp); 590 tg3_enable_ints(tp);
591} 591}
@@ -3471,11 +3471,12 @@ next_pkt_nopost:
3471 return received; 3471 return received;
3472} 3472}
3473 3473
3474static int tg3_poll(struct net_device *netdev, int *budget) 3474static int tg3_poll(struct napi_struct *napi, int budget)
3475{ 3475{
3476 struct tg3 *tp = netdev_priv(netdev); 3476 struct tg3 *tp = container_of(napi, struct tg3, napi);
3477 struct net_device *netdev = tp->dev;
3477 struct tg3_hw_status *sblk = tp->hw_status; 3478 struct tg3_hw_status *sblk = tp->hw_status;
3478 int done; 3479 int work_done = 0;
3479 3480
3480 /* handle link change and other phy events */ 3481 /* handle link change and other phy events */
3481 if (!(tp->tg3_flags & 3482 if (!(tp->tg3_flags &
@@ -3494,7 +3495,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
3494 if (sblk->idx[0].tx_consumer != tp->tx_cons) { 3495 if (sblk->idx[0].tx_consumer != tp->tx_cons) {
3495 tg3_tx(tp); 3496 tg3_tx(tp);
3496 if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) { 3497 if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) {
3497 netif_rx_complete(netdev); 3498 netif_rx_complete(netdev, napi);
3498 schedule_work(&tp->reset_task); 3499 schedule_work(&tp->reset_task);
3499 return 0; 3500 return 0;
3500 } 3501 }
@@ -3502,20 +3503,10 @@ static int tg3_poll(struct net_device *netdev, int *budget)
3502 3503
3503 /* run RX thread, within the bounds set by NAPI. 3504 /* run RX thread, within the bounds set by NAPI.
3504 * All RX "locking" is done by ensuring outside 3505 * All RX "locking" is done by ensuring outside
3505 * code synchronizes with dev->poll() 3506 * code synchronizes with tg3->napi.poll()
3506 */ 3507 */
3507 if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) { 3508 if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
3508 int orig_budget = *budget; 3509 work_done = tg3_rx(tp, budget);
3509 int work_done;
3510
3511 if (orig_budget > netdev->quota)
3512 orig_budget = netdev->quota;
3513
3514 work_done = tg3_rx(tp, orig_budget);
3515
3516 *budget -= work_done;
3517 netdev->quota -= work_done;
3518 }
3519 3510
3520 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { 3511 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
3521 tp->last_tag = sblk->status_tag; 3512 tp->last_tag = sblk->status_tag;
@@ -3524,13 +3515,12 @@ static int tg3_poll(struct net_device *netdev, int *budget)
3524 sblk->status &= ~SD_STATUS_UPDATED; 3515 sblk->status &= ~SD_STATUS_UPDATED;
3525 3516
3526 /* if no more work, tell net stack and NIC we're done */ 3517 /* if no more work, tell net stack and NIC we're done */
3527 done = !tg3_has_work(tp); 3518 if (!tg3_has_work(tp)) {
3528 if (done) { 3519 netif_rx_complete(netdev, napi);
3529 netif_rx_complete(netdev);
3530 tg3_restart_ints(tp); 3520 tg3_restart_ints(tp);
3531 } 3521 }
3532 3522
3533 return (done ? 0 : 1); 3523 return work_done;
3534} 3524}
3535 3525
3536static void tg3_irq_quiesce(struct tg3 *tp) 3526static void tg3_irq_quiesce(struct tg3 *tp)
@@ -3577,7 +3567,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
3577 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); 3567 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
3578 3568
3579 if (likely(!tg3_irq_sync(tp))) 3569 if (likely(!tg3_irq_sync(tp)))
3580 netif_rx_schedule(dev); /* schedule NAPI poll */ 3570 netif_rx_schedule(dev, &tp->napi);
3581 3571
3582 return IRQ_HANDLED; 3572 return IRQ_HANDLED;
3583} 3573}
@@ -3602,7 +3592,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
3602 */ 3592 */
3603 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); 3593 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
3604 if (likely(!tg3_irq_sync(tp))) 3594 if (likely(!tg3_irq_sync(tp)))
3605 netif_rx_schedule(dev); /* schedule NAPI poll */ 3595 netif_rx_schedule(dev, &tp->napi);
3606 3596
3607 return IRQ_RETVAL(1); 3597 return IRQ_RETVAL(1);
3608} 3598}
@@ -3644,7 +3634,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
3644 sblk->status &= ~SD_STATUS_UPDATED; 3634 sblk->status &= ~SD_STATUS_UPDATED;
3645 if (likely(tg3_has_work(tp))) { 3635 if (likely(tg3_has_work(tp))) {
3646 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); 3636 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
3647 netif_rx_schedule(dev); /* schedule NAPI poll */ 3637 netif_rx_schedule(dev, &tp->napi);
3648 } else { 3638 } else {
3649 /* No work, shared interrupt perhaps? re-enable 3639 /* No work, shared interrupt perhaps? re-enable
3650 * interrupts, and flush that PCI write 3640 * interrupts, and flush that PCI write
@@ -3690,7 +3680,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
3690 tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); 3680 tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
3691 if (tg3_irq_sync(tp)) 3681 if (tg3_irq_sync(tp))
3692 goto out; 3682 goto out;
3693 if (netif_rx_schedule_prep(dev)) { 3683 if (netif_rx_schedule_prep(dev, &tp->napi)) {
3694 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); 3684 prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
3695 /* Update last_tag to mark that this status has been 3685 /* Update last_tag to mark that this status has been
3696 * seen. Because interrupt may be shared, we may be 3686 * seen. Because interrupt may be shared, we may be
@@ -3698,7 +3688,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
3698 * if tg3_poll() is not scheduled. 3688 * if tg3_poll() is not scheduled.
3699 */ 3689 */
3700 tp->last_tag = sblk->status_tag; 3690 tp->last_tag = sblk->status_tag;
3701 __netif_rx_schedule(dev); 3691 __netif_rx_schedule(dev, &tp->napi);
3702 } 3692 }
3703out: 3693out:
3704 return IRQ_RETVAL(handled); 3694 return IRQ_RETVAL(handled);
@@ -3737,7 +3727,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
3737 tg3_full_unlock(tp); 3727 tg3_full_unlock(tp);
3738 del_timer_sync(&tp->timer); 3728 del_timer_sync(&tp->timer);
3739 tp->irq_sync = 0; 3729 tp->irq_sync = 0;
3740 netif_poll_enable(tp->dev); 3730 napi_enable(&tp->napi);
3741 dev_close(tp->dev); 3731 dev_close(tp->dev);
3742 tg3_full_lock(tp, 0); 3732 tg3_full_lock(tp, 0);
3743 } 3733 }
@@ -3932,7 +3922,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
3932 len = skb_headlen(skb); 3922 len = skb_headlen(skb);
3933 3923
3934 /* We are running in BH disabled context with netif_tx_lock 3924 /* We are running in BH disabled context with netif_tx_lock
3935 * and TX reclaim runs via tp->poll inside of a software 3925 * and TX reclaim runs via tp->napi.poll inside of a software
3936 * interrupt. Furthermore, IRQ processing runs lockless so we have 3926 * interrupt. Furthermore, IRQ processing runs lockless so we have
3937 * no IRQ context deadlocks to worry about either. Rejoice! 3927 * no IRQ context deadlocks to worry about either. Rejoice!
3938 */ 3928 */
@@ -4087,7 +4077,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
4087 len = skb_headlen(skb); 4077 len = skb_headlen(skb);
4088 4078
4089 /* We are running in BH disabled context with netif_tx_lock 4079 /* We are running in BH disabled context with netif_tx_lock
4090 * and TX reclaim runs via tp->poll inside of a software 4080 * and TX reclaim runs via tp->napi.poll inside of a software
4091 * interrupt. Furthermore, IRQ processing runs lockless so we have 4081 * interrupt. Furthermore, IRQ processing runs lockless so we have
4092 * no IRQ context deadlocks to worry about either. Rejoice! 4082 * no IRQ context deadlocks to worry about either. Rejoice!
4093 */ 4083 */
@@ -7147,6 +7137,8 @@ static int tg3_open(struct net_device *dev)
7147 return err; 7137 return err;
7148 } 7138 }
7149 7139
7140 napi_enable(&tp->napi);
7141
7150 tg3_full_lock(tp, 0); 7142 tg3_full_lock(tp, 0);
7151 7143
7152 err = tg3_init_hw(tp, 1); 7144 err = tg3_init_hw(tp, 1);
@@ -7174,6 +7166,7 @@ static int tg3_open(struct net_device *dev)
7174 tg3_full_unlock(tp); 7166 tg3_full_unlock(tp);
7175 7167
7176 if (err) { 7168 if (err) {
7169 napi_disable(&tp->napi);
7177 free_irq(tp->pdev->irq, dev); 7170 free_irq(tp->pdev->irq, dev);
7178 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { 7171 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
7179 pci_disable_msi(tp->pdev); 7172 pci_disable_msi(tp->pdev);
@@ -7199,6 +7192,8 @@ static int tg3_open(struct net_device *dev)
7199 7192
7200 tg3_full_unlock(tp); 7193 tg3_full_unlock(tp);
7201 7194
7195 napi_disable(&tp->napi);
7196
7202 return err; 7197 return err;
7203 } 7198 }
7204 7199
@@ -7460,6 +7455,7 @@ static int tg3_close(struct net_device *dev)
7460{ 7455{
7461 struct tg3 *tp = netdev_priv(dev); 7456 struct tg3 *tp = netdev_priv(dev);
7462 7457
7458 napi_disable(&tp->napi);
7463 cancel_work_sync(&tp->reset_task); 7459 cancel_work_sync(&tp->reset_task);
7464 7460
7465 netif_stop_queue(dev); 7461 netif_stop_queue(dev);
@@ -11900,9 +11896,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
11900 dev->set_mac_address = tg3_set_mac_addr; 11896 dev->set_mac_address = tg3_set_mac_addr;
11901 dev->do_ioctl = tg3_ioctl; 11897 dev->do_ioctl = tg3_ioctl;
11902 dev->tx_timeout = tg3_tx_timeout; 11898 dev->tx_timeout = tg3_tx_timeout;
11903 dev->poll = tg3_poll; 11899 netif_napi_add(dev, &tp->napi, tg3_poll, 64);
11904 dev->ethtool_ops = &tg3_ethtool_ops; 11900 dev->ethtool_ops = &tg3_ethtool_ops;
11905 dev->weight = 64;
11906 dev->watchdog_timeo = TG3_TX_TIMEOUT; 11901 dev->watchdog_timeo = TG3_TX_TIMEOUT;
11907 dev->change_mtu = tg3_change_mtu; 11902 dev->change_mtu = tg3_change_mtu;
11908 dev->irq = pdev->irq; 11903 dev->irq = pdev->irq;