aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.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/sky2.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/sky2.c')
-rw-r--r--drivers/net/sky2.c94
1 files changed, 41 insertions, 53 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index ea117fc3d5e3..a0d75b0f3798 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1130,7 +1130,7 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
1130 u16 port = sky2->port; 1130 u16 port = sky2->port;
1131 1131
1132 netif_tx_lock_bh(dev); 1132 netif_tx_lock_bh(dev);
1133 netif_poll_disable(sky2->hw->dev[0]); 1133 napi_disable(&hw->napi);
1134 1134
1135 sky2->vlgrp = grp; 1135 sky2->vlgrp = grp;
1136 if (grp) { 1136 if (grp) {
@@ -1145,7 +1145,7 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
1145 TX_VLAN_TAG_OFF); 1145 TX_VLAN_TAG_OFF);
1146 } 1146 }
1147 1147
1148 netif_poll_enable(sky2->hw->dev[0]); 1148 napi_enable(&hw->napi);
1149 netif_tx_unlock_bh(dev); 1149 netif_tx_unlock_bh(dev);
1150} 1150}
1151#endif 1151#endif
@@ -1385,9 +1385,13 @@ static int sky2_up(struct net_device *dev)
1385 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, 1385 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
1386 TX_RING_SIZE - 1); 1386 TX_RING_SIZE - 1);
1387 1387
1388 napi_enable(&hw->napi);
1389
1388 err = sky2_rx_start(sky2); 1390 err = sky2_rx_start(sky2);
1389 if (err) 1391 if (err) {
1392 napi_disable(&hw->napi);
1390 goto err_out; 1393 goto err_out;
1394 }
1391 1395
1392 /* Enable interrupts from phy/mac for port */ 1396 /* Enable interrupts from phy/mac for port */
1393 imask = sky2_read32(hw, B0_IMSK); 1397 imask = sky2_read32(hw, B0_IMSK);
@@ -1676,6 +1680,8 @@ static int sky2_down(struct net_device *dev)
1676 /* Stop more packets from being queued */ 1680 /* Stop more packets from being queued */
1677 netif_stop_queue(dev); 1681 netif_stop_queue(dev);
1678 1682
1683 napi_disable(&hw->napi);
1684
1679 /* Disable port IRQ */ 1685 /* Disable port IRQ */
1680 imask = sky2_read32(hw, B0_IMSK); 1686 imask = sky2_read32(hw, B0_IMSK);
1681 imask &= ~portirq_msk[port]; 1687 imask &= ~portirq_msk[port];
@@ -2016,7 +2022,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
2016 2022
2017 dev->trans_start = jiffies; /* prevent tx timeout */ 2023 dev->trans_start = jiffies; /* prevent tx timeout */
2018 netif_stop_queue(dev); 2024 netif_stop_queue(dev);
2019 netif_poll_disable(hw->dev[0]); 2025 napi_disable(&hw->napi);
2020 2026
2021 synchronize_irq(hw->pdev->irq); 2027 synchronize_irq(hw->pdev->irq);
2022 2028
@@ -2043,12 +2049,16 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
2043 err = sky2_rx_start(sky2); 2049 err = sky2_rx_start(sky2);
2044 sky2_write32(hw, B0_IMSK, imask); 2050 sky2_write32(hw, B0_IMSK, imask);
2045 2051
2052 /* Unconditionally re-enable NAPI because even if we
2053 * call dev_close() that will do a napi_disable().
2054 */
2055 napi_enable(&hw->napi);
2056
2046 if (err) 2057 if (err)
2047 dev_close(dev); 2058 dev_close(dev);
2048 else { 2059 else {
2049 gma_write16(hw, port, GM_GP_CTRL, ctl); 2060 gma_write16(hw, port, GM_GP_CTRL, ctl);
2050 2061
2051 netif_poll_enable(hw->dev[0]);
2052 netif_wake_queue(dev); 2062 netif_wake_queue(dev);
2053 } 2063 }
2054 2064
@@ -2544,18 +2554,15 @@ static int sky2_rx_hung(struct net_device *dev)
2544static void sky2_watchdog(unsigned long arg) 2554static void sky2_watchdog(unsigned long arg)
2545{ 2555{
2546 struct sky2_hw *hw = (struct sky2_hw *) arg; 2556 struct sky2_hw *hw = (struct sky2_hw *) arg;
2547 struct net_device *dev;
2548 2557
2549 /* Check for lost IRQ once a second */ 2558 /* Check for lost IRQ once a second */
2550 if (sky2_read32(hw, B0_ISRC)) { 2559 if (sky2_read32(hw, B0_ISRC)) {
2551 dev = hw->dev[0]; 2560 napi_schedule(&hw->napi);
2552 if (__netif_rx_schedule_prep(dev))
2553 __netif_rx_schedule(dev);
2554 } else { 2561 } else {
2555 int i, active = 0; 2562 int i, active = 0;
2556 2563
2557 for (i = 0; i < hw->ports; i++) { 2564 for (i = 0; i < hw->ports; i++) {
2558 dev = hw->dev[i]; 2565 struct net_device *dev = hw->dev[i];
2559 if (!netif_running(dev)) 2566 if (!netif_running(dev))
2560 continue; 2567 continue;
2561 ++active; 2568 ++active;
@@ -2605,11 +2612,11 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
2605 sky2_le_error(hw, 1, Q_XA2, TX_RING_SIZE); 2612 sky2_le_error(hw, 1, Q_XA2, TX_RING_SIZE);
2606} 2613}
2607 2614
2608static int sky2_poll(struct net_device *dev0, int *budget) 2615static int sky2_poll(struct napi_struct *napi, int work_limit)
2609{ 2616{
2610 struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; 2617 struct sky2_hw *hw = container_of(napi, struct sky2_hw, napi);
2611 int work_done;
2612 u32 status = sky2_read32(hw, B0_Y2_SP_EISR); 2618 u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
2619 int work_done;
2613 2620
2614 if (unlikely(status & Y2_IS_ERROR)) 2621 if (unlikely(status & Y2_IS_ERROR))
2615 sky2_err_intr(hw, status); 2622 sky2_err_intr(hw, status);
@@ -2620,31 +2627,27 @@ static int sky2_poll(struct net_device *dev0, int *budget)
2620 if (status & Y2_IS_IRQ_PHY2) 2627 if (status & Y2_IS_IRQ_PHY2)
2621 sky2_phy_intr(hw, 1); 2628 sky2_phy_intr(hw, 1);
2622 2629
2623 work_done = sky2_status_intr(hw, min(dev0->quota, *budget)); 2630 work_done = sky2_status_intr(hw, work_limit);
2624 *budget -= work_done;
2625 dev0->quota -= work_done;
2626 2631
2627 /* More work? */ 2632 /* More work? */
2628 if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)) 2633 if (hw->st_idx == sky2_read16(hw, STAT_PUT_IDX)) {
2629 return 1; 2634 /* Bug/Errata workaround?
2635 * Need to kick the TX irq moderation timer.
2636 */
2637 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2638 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2639 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2640 }
2630 2641
2631 /* Bug/Errata workaround? 2642 napi_complete(napi);
2632 * Need to kick the TX irq moderation timer. 2643 sky2_read32(hw, B0_Y2_SP_LISR);
2633 */
2634 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2635 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2636 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2637 } 2644 }
2638 netif_rx_complete(dev0); 2645 return work_done;
2639
2640 sky2_read32(hw, B0_Y2_SP_LISR);
2641 return 0;
2642} 2646}
2643 2647
2644static irqreturn_t sky2_intr(int irq, void *dev_id) 2648static irqreturn_t sky2_intr(int irq, void *dev_id)
2645{ 2649{
2646 struct sky2_hw *hw = dev_id; 2650 struct sky2_hw *hw = dev_id;
2647 struct net_device *dev0 = hw->dev[0];
2648 u32 status; 2651 u32 status;
2649 2652
2650 /* Reading this mask interrupts as side effect */ 2653 /* Reading this mask interrupts as side effect */
@@ -2653,8 +2656,8 @@ static irqreturn_t sky2_intr(int irq, void *dev_id)
2653 return IRQ_NONE; 2656 return IRQ_NONE;
2654 2657
2655 prefetch(&hw->st_le[hw->st_idx]); 2658 prefetch(&hw->st_le[hw->st_idx]);
2656 if (likely(__netif_rx_schedule_prep(dev0))) 2659
2657 __netif_rx_schedule(dev0); 2660 napi_schedule(&hw->napi);
2658 2661
2659 return IRQ_HANDLED; 2662 return IRQ_HANDLED;
2660} 2663}
@@ -2663,10 +2666,8 @@ static irqreturn_t sky2_intr(int irq, void *dev_id)
2663static void sky2_netpoll(struct net_device *dev) 2666static void sky2_netpoll(struct net_device *dev)
2664{ 2667{
2665 struct sky2_port *sky2 = netdev_priv(dev); 2668 struct sky2_port *sky2 = netdev_priv(dev);
2666 struct net_device *dev0 = sky2->hw->dev[0];
2667 2669
2668 if (netif_running(dev) && __netif_rx_schedule_prep(dev0)) 2670 napi_schedule(&sky2->hw->napi);
2669 __netif_rx_schedule(dev0);
2670} 2671}
2671#endif 2672#endif
2672 2673
@@ -2914,8 +2915,6 @@ static void sky2_restart(struct work_struct *work)
2914 sky2_write32(hw, B0_IMSK, 0); 2915 sky2_write32(hw, B0_IMSK, 0);
2915 sky2_read32(hw, B0_IMSK); 2916 sky2_read32(hw, B0_IMSK);
2916 2917
2917 netif_poll_disable(hw->dev[0]);
2918
2919 for (i = 0; i < hw->ports; i++) { 2918 for (i = 0; i < hw->ports; i++) {
2920 dev = hw->dev[i]; 2919 dev = hw->dev[i];
2921 if (netif_running(dev)) 2920 if (netif_running(dev))
@@ -2924,7 +2923,6 @@ static void sky2_restart(struct work_struct *work)
2924 2923
2925 sky2_reset(hw); 2924 sky2_reset(hw);
2926 sky2_write32(hw, B0_IMSK, Y2_IS_BASE); 2925 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
2927 netif_poll_enable(hw->dev[0]);
2928 2926
2929 for (i = 0; i < hw->ports; i++) { 2927 for (i = 0; i < hw->ports; i++) {
2930 dev = hw->dev[i]; 2928 dev = hw->dev[i];
@@ -3735,7 +3733,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
3735{ 3733{
3736 struct net_device *dev = seq->private; 3734 struct net_device *dev = seq->private;
3737 const struct sky2_port *sky2 = netdev_priv(dev); 3735 const struct sky2_port *sky2 = netdev_priv(dev);
3738 const struct sky2_hw *hw = sky2->hw; 3736 struct sky2_hw *hw = sky2->hw;
3739 unsigned port = sky2->port; 3737 unsigned port = sky2->port;
3740 unsigned idx, last; 3738 unsigned idx, last;
3741 int sop; 3739 int sop;
@@ -3748,7 +3746,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
3748 sky2_read32(hw, B0_IMSK), 3746 sky2_read32(hw, B0_IMSK),
3749 sky2_read32(hw, B0_Y2_SP_ICR)); 3747 sky2_read32(hw, B0_Y2_SP_ICR));
3750 3748
3751 netif_poll_disable(hw->dev[0]); 3749 napi_disable(&hw->napi);
3752 last = sky2_read16(hw, STAT_PUT_IDX); 3750 last = sky2_read16(hw, STAT_PUT_IDX);
3753 3751
3754 if (hw->st_idx == last) 3752 if (hw->st_idx == last)
@@ -3818,7 +3816,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
3818 last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), 3816 last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
3819 sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); 3817 sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
3820 3818
3821 netif_poll_enable(hw->dev[0]); 3819 napi_enable(&hw->napi);
3822 return 0; 3820 return 0;
3823} 3821}
3824 3822
@@ -3943,15 +3941,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
3943 SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops); 3941 SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
3944 dev->tx_timeout = sky2_tx_timeout; 3942 dev->tx_timeout = sky2_tx_timeout;
3945 dev->watchdog_timeo = TX_WATCHDOG; 3943 dev->watchdog_timeo = TX_WATCHDOG;
3946 if (port == 0)
3947 dev->poll = sky2_poll;
3948 dev->weight = NAPI_WEIGHT;
3949#ifdef CONFIG_NET_POLL_CONTROLLER 3944#ifdef CONFIG_NET_POLL_CONTROLLER
3950 /* Network console (only works on port 0) 3945 dev->poll_controller = sky2_netpoll;
3951 * because netpoll makes assumptions about NAPI
3952 */
3953 if (port == 0)
3954 dev->poll_controller = sky2_netpoll;
3955#endif 3946#endif
3956 3947
3957 sky2 = netdev_priv(dev); 3948 sky2 = netdev_priv(dev);
@@ -4166,6 +4157,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
4166 err = -ENOMEM; 4157 err = -ENOMEM;
4167 goto err_out_free_pci; 4158 goto err_out_free_pci;
4168 } 4159 }
4160 netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
4169 4161
4170 if (!disable_msi && pci_enable_msi(pdev) == 0) { 4162 if (!disable_msi && pci_enable_msi(pdev) == 0) {
4171 err = sky2_test_msi(hw); 4163 err = sky2_test_msi(hw);
@@ -4288,8 +4280,6 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
4288 if (!hw) 4280 if (!hw)
4289 return 0; 4281 return 0;
4290 4282
4291 netif_poll_disable(hw->dev[0]);
4292
4293 for (i = 0; i < hw->ports; i++) { 4283 for (i = 0; i < hw->ports; i++) {
4294 struct net_device *dev = hw->dev[i]; 4284 struct net_device *dev = hw->dev[i];
4295 struct sky2_port *sky2 = netdev_priv(dev); 4285 struct sky2_port *sky2 = netdev_priv(dev);
@@ -4356,8 +4346,6 @@ static int sky2_resume(struct pci_dev *pdev)
4356 } 4346 }
4357 } 4347 }
4358 4348
4359 netif_poll_enable(hw->dev[0]);
4360
4361 return 0; 4349 return 0;
4362out: 4350out:
4363 dev_err(&pdev->dev, "resume failed (%d)\n", err); 4351 dev_err(&pdev->dev, "resume failed (%d)\n", err);
@@ -4374,7 +4362,7 @@ static void sky2_shutdown(struct pci_dev *pdev)
4374 if (!hw) 4362 if (!hw)
4375 return; 4363 return;
4376 4364
4377 netif_poll_disable(hw->dev[0]); 4365 napi_disable(&hw->napi);
4378 4366
4379 for (i = 0; i < hw->ports; i++) { 4367 for (i = 0; i < hw->ports; i++) {
4380 struct net_device *dev = hw->dev[i]; 4368 struct net_device *dev = hw->dev[i];