diff options
author | stephen hemminger <shemminger@vyatta.com> | 2011-11-17 09:37:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-17 21:43:57 -0500 |
commit | 282edcece39e08d02c22492d593e4b9b94a65dff (patch) | |
tree | a0d0c9816a5ef76bc637a573e382379600016e09 | |
parent | 738a849c8eef4787a526d95763f985b8c1cb68e4 (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>
-rw-r--r-- | drivers/net/ethernet/marvell/sky2.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/marvell/sky2.h | 1 |
2 files changed, 11 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 | ||
3446 | static void sky2_all_up(struct sky2_hw *hw) | 3450 | static 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); |
diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h index 0af31b8b5f10..ff6f58bf822a 100644 --- a/drivers/net/ethernet/marvell/sky2.h +++ b/drivers/net/ethernet/marvell/sky2.h | |||
@@ -2287,6 +2287,7 @@ struct sky2_hw { | |||
2287 | #define SKY2_HW_RSS_BROKEN 0x00000100 | 2287 | #define SKY2_HW_RSS_BROKEN 0x00000100 |
2288 | #define SKY2_HW_VLAN_BROKEN 0x00000200 | 2288 | #define SKY2_HW_VLAN_BROKEN 0x00000200 |
2289 | #define SKY2_HW_RSS_CHKSUM 0x00000400 /* RSS requires chksum */ | 2289 | #define SKY2_HW_RSS_CHKSUM 0x00000400 /* RSS requires chksum */ |
2290 | #define SKY2_HW_IRQ_SETUP 0x00000800 | ||
2290 | 2291 | ||
2291 | u8 chip_id; | 2292 | u8 chip_id; |
2292 | u8 chip_rev; | 2293 | u8 chip_rev; |