aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrashant Sreedharan <prashant@broadcom.com>2015-01-14 14:34:44 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-14 17:05:51 -0500
commit932f19de6af9f45784d7fb730dea50525b3b5aac (patch)
treed651d9029193efd4278e9eff2cecdc9f4b754389
parentdb84bf43ef23157cbb40ce8626475187f5ae90c3 (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.c12
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
7415static void tg3_irq_quiesce(struct tg3 *tp) 7415static 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. */
9020static int tg3_chip_reset(struct tg3 *tp) 9026static 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);