diff options
| author | Prashant Sreedharan <prashant@broadcom.com> | 2015-01-14 14:34:44 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-01-14 17:05:51 -0500 |
| commit | 932f19de6af9f45784d7fb730dea50525b3b5aac (patch) | |
| tree | d651d9029193efd4278e9eff2cecdc9f4b754389 | |
| parent | db84bf43ef23157cbb40ce8626475187f5ae90c3 (diff) | |
tg3: Release tp->lock before invoking synchronize_irq()
synchronize_irq() can sleep waiting, for pending IRQ handlers so driver
should release the tp->lock spin lock before invoking synchronize_irq()
Reported-by: Peter Hurley <peter@hurleysoftware.com>
Tested-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Prashant Sreedharan <prashant@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 9247ae1412cc..96bf01ba32dd 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
| @@ -7413,6 +7413,8 @@ static inline void tg3_netif_start(struct tg3 *tp) | |||
| 7413 | } | 7413 | } |
| 7414 | 7414 | ||
| 7415 | static void tg3_irq_quiesce(struct tg3 *tp) | 7415 | static void tg3_irq_quiesce(struct tg3 *tp) |
| 7416 | __releases(tp->lock) | ||
| 7417 | __acquires(tp->lock) | ||
| 7416 | { | 7418 | { |
| 7417 | int i; | 7419 | int i; |
| 7418 | 7420 | ||
| @@ -7421,8 +7423,12 @@ static void tg3_irq_quiesce(struct tg3 *tp) | |||
| 7421 | tp->irq_sync = 1; | 7423 | tp->irq_sync = 1; |
| 7422 | smp_mb(); | 7424 | smp_mb(); |
| 7423 | 7425 | ||
| 7426 | spin_unlock_bh(&tp->lock); | ||
| 7427 | |||
| 7424 | for (i = 0; i < tp->irq_cnt; i++) | 7428 | for (i = 0; i < tp->irq_cnt; i++) |
| 7425 | synchronize_irq(tp->napi[i].irq_vec); | 7429 | synchronize_irq(tp->napi[i].irq_vec); |
| 7430 | |||
| 7431 | spin_lock_bh(&tp->lock); | ||
| 7426 | } | 7432 | } |
| 7427 | 7433 | ||
| 7428 | /* Fully shutdown all tg3 driver activity elsewhere in the system. | 7434 | /* Fully shutdown all tg3 driver activity elsewhere in the system. |
| @@ -9018,6 +9024,8 @@ static void tg3_restore_clk(struct tg3 *tp) | |||
| 9018 | 9024 | ||
| 9019 | /* tp->lock is held. */ | 9025 | /* tp->lock is held. */ |
| 9020 | static int tg3_chip_reset(struct tg3 *tp) | 9026 | static int tg3_chip_reset(struct tg3 *tp) |
| 9027 | __releases(tp->lock) | ||
| 9028 | __acquires(tp->lock) | ||
| 9021 | { | 9029 | { |
| 9022 | u32 val; | 9030 | u32 val; |
| 9023 | void (*write_op)(struct tg3 *, u32, u32); | 9031 | void (*write_op)(struct tg3 *, u32, u32); |
| @@ -9073,9 +9081,13 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
| 9073 | } | 9081 | } |
| 9074 | smp_mb(); | 9082 | smp_mb(); |
| 9075 | 9083 | ||
| 9084 | tg3_full_unlock(tp); | ||
| 9085 | |||
| 9076 | for (i = 0; i < tp->irq_cnt; i++) | 9086 | for (i = 0; i < tp->irq_cnt; i++) |
| 9077 | synchronize_irq(tp->napi[i].irq_vec); | 9087 | synchronize_irq(tp->napi[i].irq_vec); |
| 9078 | 9088 | ||
| 9089 | tg3_full_lock(tp, 0); | ||
| 9090 | |||
| 9079 | if (tg3_asic_rev(tp) == ASIC_REV_57780) { | 9091 | if (tg3_asic_rev(tp) == ASIC_REV_57780) { |
| 9080 | val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; | 9092 | val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; |
| 9081 | tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); | 9093 | tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); |
