Commit ad9b4359 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

cnic, bnx2x: Add CNIC_DRV_STATE_HANDLES_IRQ to ethdev->drv_state

In INTA mode, cnic and bnx2x share the same IRQ.  During chip reset,
for example, cnic will stop servicing IRQs after it has shutdown the
cnic hardware resources.  However, the shared IRQ is still active as
bnx2x needs to finish the reset.  There is a window when bnx2x does
not know that cnic is no longer handling IRQ and things don't always
work properly.

Add a flag to tell bnx2x that cnic is handling IRQ.  The flag is set
before the first cnic IRQ is expected and cleared when no more cnic
IRQs are expected, so there should be no race conditions.
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarAriel Elior <ariele@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 580d9d08
...@@ -1875,14 +1875,12 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) ...@@ -1875,14 +1875,12 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
if (status & (mask | 0x1)) { if (status & (mask | 0x1)) {
struct cnic_ops *c_ops = NULL; struct cnic_ops *c_ops = NULL;
if (likely(bp->state == BNX2X_STATE_OPEN)) { rcu_read_lock();
rcu_read_lock(); c_ops = rcu_dereference(bp->cnic_ops);
c_ops = rcu_dereference(bp->cnic_ops); if (c_ops && (bp->cnic_eth_dev.drv_state &
if (c_ops) CNIC_DRV_STATE_HANDLES_IRQ))
c_ops->cnic_handler(bp->cnic_data, c_ops->cnic_handler(bp->cnic_data, NULL);
NULL); rcu_read_unlock();
rcu_read_unlock();
}
status &= ~mask; status &= ~mask;
} }
......
...@@ -4816,6 +4816,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) ...@@ -4816,6 +4816,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
return err; return err;
} }
ethdev->drv_state |= CNIC_DRV_STATE_HANDLES_IRQ;
return 0; return 0;
} }
...@@ -5136,6 +5138,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) ...@@ -5136,6 +5138,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
if (ret) if (ret)
return ret; return ret;
ethdev->drv_state |= CNIC_DRV_STATE_HANDLES_IRQ;
return 0; return 0;
} }
...@@ -5387,6 +5390,7 @@ static void cnic_stop_hw(struct cnic_dev *dev) ...@@ -5387,6 +5390,7 @@ static void cnic_stop_hw(struct cnic_dev *dev)
} }
cnic_shutdown_rings(dev); cnic_shutdown_rings(dev);
cp->stop_cm(dev); cp->stop_cm(dev);
cp->ethdev->drv_state &= ~CNIC_DRV_STATE_HANDLES_IRQ;
clear_bit(CNIC_F_CNIC_UP, &dev->flags); clear_bit(CNIC_F_CNIC_UP, &dev->flags);
RCU_INIT_POINTER(cp->ulp_ops[CNIC_ULP_L4], NULL); RCU_INIT_POINTER(cp->ulp_ops[CNIC_ULP_L4], NULL);
synchronize_rcu(); synchronize_rcu();
......
...@@ -179,6 +179,7 @@ struct cnic_eth_dev { ...@@ -179,6 +179,7 @@ struct cnic_eth_dev {
#define CNIC_DRV_STATE_NO_ISCSI_OOO 0x00000004 #define CNIC_DRV_STATE_NO_ISCSI_OOO 0x00000004
#define CNIC_DRV_STATE_NO_ISCSI 0x00000008 #define CNIC_DRV_STATE_NO_ISCSI 0x00000008
#define CNIC_DRV_STATE_NO_FCOE 0x00000010 #define CNIC_DRV_STATE_NO_FCOE 0x00000010
#define CNIC_DRV_STATE_HANDLES_IRQ 0x00000020
u32 chip_id; u32 chip_id;
u32 max_kwqe_pending; u32 max_kwqe_pending;
struct pci_dev *pdev; struct pci_dev *pdev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment