aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
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];