aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/sky2.c
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-11-17 09:37:35 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-17 21:43:57 -0500
commit282edcece39e08d02c22492d593e4b9b94a65dff (patch)
treea0d0c9816a5ef76bc637a573e382379600016e09 /drivers/net/ethernet/marvell/sky2.c
parent738a849c8eef4787a526d95763f985b8c1cb68e4 (diff)
sky2: fix hang in napi_disable
If IRQ was never initialized, then calling napi_disable() would hang. Add more bookkeeping to track whether IRQ was ever initialized. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/marvell/sky2.c')
-rw-r--r--drivers/net/ethernet/marvell/sky2.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index d99687177704..7803efa46eb2 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1723,6 +1723,8 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
1723 if (err) 1723 if (err)
1724 dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); 1724 dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
1725 else { 1725 else {
1726 hw->flags |= SKY2_HW_IRQ_SETUP;
1727
1726 napi_enable(&hw->napi); 1728 napi_enable(&hw->napi);
1727 sky2_write32(hw, B0_IMSK, Y2_IS_BASE); 1729 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
1728 sky2_read32(hw, B0_IMSK); 1730 sky2_read32(hw, B0_IMSK);
@@ -2120,6 +2122,7 @@ static int sky2_close(struct net_device *dev)
2120 2122
2121 napi_disable(&hw->napi); 2123 napi_disable(&hw->napi);
2122 free_irq(hw->pdev->irq, hw); 2124 free_irq(hw->pdev->irq, hw);
2125 hw->flags &= ~SKY2_HW_IRQ_SETUP;
2123 } else { 2126 } else {
2124 u32 imask; 2127 u32 imask;
2125 2128
@@ -3423,12 +3426,13 @@ static void sky2_all_down(struct sky2_hw *hw)
3423{ 3426{
3424 int i; 3427 int i;
3425 3428
3426 sky2_read32(hw, B0_IMSK); 3429 if (hw->flags & SKY2_HW_IRQ_SETUP) {
3427 sky2_write32(hw, B0_IMSK, 0); 3430 sky2_read32(hw, B0_IMSK);
3431 sky2_write32(hw, B0_IMSK, 0);
3428 3432
3429 if (hw->ports > 1 || netif_running(hw->dev[0]))
3430 synchronize_irq(hw->pdev->irq); 3433 synchronize_irq(hw->pdev->irq);
3431 napi_disable(&hw->napi); 3434 napi_disable(&hw->napi);
3435 }
3432 3436
3433 for (i = 0; i < hw->ports; i++) { 3437 for (i = 0; i < hw->ports; i++) {
3434 struct net_device *dev = hw->dev[i]; 3438 struct net_device *dev = hw->dev[i];
@@ -3445,7 +3449,7 @@ static void sky2_all_down(struct sky2_hw *hw)
3445 3449
3446static void sky2_all_up(struct sky2_hw *hw) 3450static void sky2_all_up(struct sky2_hw *hw)
3447{ 3451{
3448 u32 imask = 0; 3452 u32 imask = Y2_IS_BASE;
3449 int i; 3453 int i;
3450 3454
3451 for (i = 0; i < hw->ports; i++) { 3455 for (i = 0; i < hw->ports; i++) {
@@ -3461,8 +3465,7 @@ static void sky2_all_up(struct sky2_hw *hw)
3461 netif_wake_queue(dev); 3465 netif_wake_queue(dev);
3462 } 3466 }
3463 3467
3464 if (imask || hw->ports > 1) { 3468 if (hw->flags & SKY2_HW_IRQ_SETUP) {
3465 imask |= Y2_IS_BASE;
3466 sky2_write32(hw, B0_IMSK, imask); 3469 sky2_write32(hw, B0_IMSK, imask);
3467 sky2_read32(hw, B0_IMSK); 3470 sky2_read32(hw, B0_IMSK);
3468 sky2_read32(hw, B0_Y2_SP_LISR); 3471 sky2_read32(hw, B0_Y2_SP_LISR);