aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-17 16:26:42 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-17 20:17:34 -0400
commit6de16237c78a9df6c7cb2d1b3bbd788322ecb344 (patch)
tree8315150fd91c39a6f7763ab87150e963d4039a5f
parentc264c3dee9f20bad1f42ef5821300791291d0f77 (diff)
sky2: shutdown cleanup
Solve issues with dual port devices due to shared NAPI. * shutting down one device shouldn't kill other one. * suspend shouldn't hang. Also fix potential race between restart and shutdown. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/sky2.c46
1 files changed, 20 insertions, 26 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 7967240534d5..6b2fc508fe00 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1384,13 +1384,9 @@ static int sky2_up(struct net_device *dev)
1384 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, 1384 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
1385 TX_RING_SIZE - 1); 1385 TX_RING_SIZE - 1);
1386 1386
1387 napi_enable(&hw->napi);
1388
1389 err = sky2_rx_start(sky2); 1387 err = sky2_rx_start(sky2);
1390 if (err) { 1388 if (err)
1391 napi_disable(&hw->napi);
1392 goto err_out; 1389 goto err_out;
1393 }
1394 1390
1395 /* Enable interrupts from phy/mac for port */ 1391 /* Enable interrupts from phy/mac for port */
1396 imask = sky2_read32(hw, B0_IMSK); 1392 imask = sky2_read32(hw, B0_IMSK);
@@ -1679,13 +1675,13 @@ static int sky2_down(struct net_device *dev)
1679 /* Stop more packets from being queued */ 1675 /* Stop more packets from being queued */
1680 netif_stop_queue(dev); 1676 netif_stop_queue(dev);
1681 1677
1682 napi_disable(&hw->napi);
1683
1684 /* Disable port IRQ */ 1678 /* Disable port IRQ */
1685 imask = sky2_read32(hw, B0_IMSK); 1679 imask = sky2_read32(hw, B0_IMSK);
1686 imask &= ~portirq_msk[port]; 1680 imask &= ~portirq_msk[port];
1687 sky2_write32(hw, B0_IMSK, imask); 1681 sky2_write32(hw, B0_IMSK, imask);
1688 1682
1683 synchronize_irq(hw->pdev->irq);
1684
1689 sky2_gmac_reset(hw, port); 1685 sky2_gmac_reset(hw, port);
1690 1686
1691 /* Stop transmitter */ 1687 /* Stop transmitter */
@@ -1699,6 +1695,9 @@ static int sky2_down(struct net_device *dev)
1699 ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); 1695 ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
1700 gma_write16(hw, port, GM_GP_CTRL, ctrl); 1696 gma_write16(hw, port, GM_GP_CTRL, ctrl);
1701 1697
1698 /* Make sure no packets are pending */
1699 napi_synchronize(&hw->napi);
1700
1702 sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); 1701 sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
1703 1702
1704 /* Workaround shared GMAC reset */ 1703 /* Workaround shared GMAC reset */
@@ -1736,8 +1735,6 @@ static int sky2_down(struct net_device *dev)
1736 /* turn off LED's */ 1735 /* turn off LED's */
1737 sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); 1736 sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
1738 1737
1739 synchronize_irq(hw->pdev->irq);
1740
1741 sky2_tx_clean(dev); 1738 sky2_tx_clean(dev);
1742 sky2_rx_clean(sky2); 1739 sky2_rx_clean(sky2);
1743 1740
@@ -2048,9 +2045,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
2048 err = sky2_rx_start(sky2); 2045 err = sky2_rx_start(sky2);
2049 sky2_write32(hw, B0_IMSK, imask); 2046 sky2_write32(hw, B0_IMSK, imask);
2050 2047
2051 /* Unconditionally re-enable NAPI because even if we
2052 * call dev_close() that will do a napi_disable().
2053 */
2054 napi_enable(&hw->napi); 2048 napi_enable(&hw->napi);
2055 2049
2056 if (err) 2050 if (err)
@@ -2915,6 +2909,7 @@ static void sky2_restart(struct work_struct *work)
2915 rtnl_lock(); 2909 rtnl_lock();
2916 sky2_write32(hw, B0_IMSK, 0); 2910 sky2_write32(hw, B0_IMSK, 0);
2917 sky2_read32(hw, B0_IMSK); 2911 sky2_read32(hw, B0_IMSK);
2912 napi_disable(&hw->napi);
2918 2913
2919 for (i = 0; i < hw->ports; i++) { 2914 for (i = 0; i < hw->ports; i++) {
2920 dev = hw->dev[i]; 2915 dev = hw->dev[i];
@@ -2924,6 +2919,7 @@ static void sky2_restart(struct work_struct *work)
2924 2919
2925 sky2_reset(hw); 2920 sky2_reset(hw);
2926 sky2_write32(hw, B0_IMSK, Y2_IS_BASE); 2921 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
2922 napi_enable(&hw->napi);
2927 2923
2928 for (i = 0; i < hw->ports; i++) { 2924 for (i = 0; i < hw->ports; i++) {
2929 dev = hw->dev[i]; 2925 dev = hw->dev[i];
@@ -4191,7 +4187,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
4191 err = -ENOMEM; 4187 err = -ENOMEM;
4192 goto err_out_free_pci; 4188 goto err_out_free_pci;
4193 } 4189 }
4194 netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
4195 4190
4196 if (!disable_msi && pci_enable_msi(pdev) == 0) { 4191 if (!disable_msi && pci_enable_msi(pdev) == 0) {
4197 err = sky2_test_msi(hw); 4192 err = sky2_test_msi(hw);
@@ -4207,6 +4202,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
4207 goto err_out_free_netdev; 4202 goto err_out_free_netdev;
4208 } 4203 }
4209 4204
4205 netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
4206
4210 err = request_irq(pdev->irq, sky2_intr, 4207 err = request_irq(pdev->irq, sky2_intr,
4211 (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, 4208 (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
4212 dev->name, hw); 4209 dev->name, hw);
@@ -4215,6 +4212,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
4215 goto err_out_unregister; 4212 goto err_out_unregister;
4216 } 4213 }
4217 sky2_write32(hw, B0_IMSK, Y2_IS_BASE); 4214 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
4215 napi_enable(&hw->napi);
4218 4216
4219 sky2_show_addr(dev); 4217 sky2_show_addr(dev);
4220 4218
@@ -4265,23 +4263,18 @@ err_out:
4265static void __devexit sky2_remove(struct pci_dev *pdev) 4263static void __devexit sky2_remove(struct pci_dev *pdev)
4266{ 4264{
4267 struct sky2_hw *hw = pci_get_drvdata(pdev); 4265 struct sky2_hw *hw = pci_get_drvdata(pdev);
4268 struct net_device *dev0, *dev1; 4266 int i;
4269 4267
4270 if (!hw) 4268 if (!hw)
4271 return; 4269 return;
4272 4270
4273 del_timer_sync(&hw->watchdog_timer); 4271 del_timer_sync(&hw->watchdog_timer);
4272 cancel_work_sync(&hw->restart_work);
4274 4273
4275 flush_scheduled_work(); 4274 for (i = hw->ports; i >= 0; --i)
4275 unregister_netdev(hw->dev[i]);
4276 4276
4277 sky2_write32(hw, B0_IMSK, 0); 4277 sky2_write32(hw, B0_IMSK, 0);
4278 synchronize_irq(hw->pdev->irq);
4279
4280 dev0 = hw->dev[0];
4281 dev1 = hw->dev[1];
4282 if (dev1)
4283 unregister_netdev(dev1);
4284 unregister_netdev(dev0);
4285 4278
4286 sky2_power_aux(hw); 4279 sky2_power_aux(hw);
4287 4280
@@ -4296,9 +4289,9 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
4296 pci_release_regions(pdev); 4289 pci_release_regions(pdev);
4297 pci_disable_device(pdev); 4290 pci_disable_device(pdev);
4298 4291
4299 if (dev1) 4292 for (i = hw->ports; i >= 0; --i)
4300 free_netdev(dev1); 4293 free_netdev(hw->dev[i]);
4301 free_netdev(dev0); 4294
4302 iounmap(hw->regs); 4295 iounmap(hw->regs);
4303 kfree(hw); 4296 kfree(hw);
4304 4297
@@ -4328,6 +4321,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
4328 } 4321 }
4329 4322
4330 sky2_write32(hw, B0_IMSK, 0); 4323 sky2_write32(hw, B0_IMSK, 0);
4324 napi_disable(&hw->napi);
4331 sky2_power_aux(hw); 4325 sky2_power_aux(hw);
4332 4326
4333 pci_save_state(pdev); 4327 pci_save_state(pdev);
@@ -4362,8 +4356,8 @@ static int sky2_resume(struct pci_dev *pdev)
4362 pci_write_config_dword(pdev, PCI_DEV_REG3, 0); 4356 pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
4363 4357
4364 sky2_reset(hw); 4358 sky2_reset(hw);
4365
4366 sky2_write32(hw, B0_IMSK, Y2_IS_BASE); 4359 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
4360 napi_enable(&hw->napi);
4367 4361
4368 for (i = 0; i < hw->ports; i++) { 4362 for (i = 0; i < hw->ports; i++) {
4369 struct net_device *dev = hw->dev[i]; 4363 struct net_device *dev = hw->dev[i];