bnx2: fix locking when netconsole is used

Functions bnx2_reg_rd_ind(), bnx2_reg_wr_ind() and bnx2_ctx_wr()
can be called with IRQs disabled when netconsole is enabled. So they
should use spin_{,un}lock_irq{save,restore} instead of _bh variants.

Example call flow:
bnx2_poll()
  ->bnx2_poll_link()
    ->bnx2_phy_int()
      ->bnx2_set_remote_link()
        ->bnx2_shmem_rd()
          ->bnx2_reg_rd_ind()
            -> spin_lock_bh(&bp->indirect_lock);
               spin_unlock_bh(&bp->indirect_lock);
               ...
               -> __local_bh_enable_ip

static inline void __local_bh_enable_ip(unsigned long ip)
      WARN_ON_ONCE(in_irq() || irqs_disabled());   <<<<<< WARN

Cc: Sony Chacko <sony.chacko@qlogic.com>
Cc: Dept-HSGLinuxNICDev@qlogic.com
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ivan Vecera 2016-10-18 08:16:03 +02:00 committed by David S. Miller
parent 3dfcb4f56f
commit 6bc80629ee
1 changed files with 11 additions and 6 deletions

View File

@ -271,22 +271,25 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
static u32 static u32
bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
{ {
unsigned long flags;
u32 val; u32 val;
spin_lock_bh(&bp->indirect_lock); spin_lock_irqsave(&bp->indirect_lock, flags);
BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW); val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW);
spin_unlock_bh(&bp->indirect_lock); spin_unlock_irqrestore(&bp->indirect_lock, flags);
return val; return val;
} }
static void static void
bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
{ {
spin_lock_bh(&bp->indirect_lock); unsigned long flags;
spin_lock_irqsave(&bp->indirect_lock, flags);
BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val); BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
spin_unlock_bh(&bp->indirect_lock); spin_unlock_irqrestore(&bp->indirect_lock, flags);
} }
static void static void
@ -304,8 +307,10 @@ bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
static void static void
bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
{ {
unsigned long flags;
offset += cid_addr; offset += cid_addr;
spin_lock_bh(&bp->indirect_lock); spin_lock_irqsave(&bp->indirect_lock, flags);
if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
int i; int i;
@ -322,7 +327,7 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset); BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset);
BNX2_WR(bp, BNX2_CTX_DATA, val); BNX2_WR(bp, BNX2_CTX_DATA, val);
} }
spin_unlock_bh(&bp->indirect_lock); spin_unlock_irqrestore(&bp->indirect_lock, flags);
} }
#ifdef BCM_CNIC #ifdef BCM_CNIC