Commit 889b9af3 authored by Ariel Elior's avatar Ariel Elior Committed by David S. Miller

bnx2x: Track active PFs with bitmap

The recovery register (to which a hardware lock has been added in previous
patch) is used amongst other things to track the active PFs. The old
implementation which used a per path counter is not viable in a virtualized
environment where a pf may increment the counter and then have the kernel
crash around it preventing the counter from ever reaching zero.
In the new implementation the scenario described will result in the PF timing
out against the mcp, which will clear the PF's bit in the bitmask allowing
recovery process to proceed.
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 f16da43b
...@@ -1767,6 +1767,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -1767,6 +1767,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_napi_enable(bp); bnx2x_napi_enable(bp);
/* set pf load just before approaching the MCP */
bnx2x_set_pf_load(bp);
/* Send LOAD_REQUEST command to MCP /* Send LOAD_REQUEST command to MCP
* Returns the type of LOAD command: * Returns the type of LOAD command:
* if it is the first port to be initialized * if it is the first port to be initialized
...@@ -1972,7 +1975,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -1972,7 +1975,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->state == BNX2X_STATE_OPEN) if (bp->state == BNX2X_STATE_OPEN)
bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
#endif #endif
bnx2x_inc_load_cnt(bp);
/* Wait for all pending SP commands to complete */ /* Wait for all pending SP commands to complete */
if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) { if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
...@@ -2012,6 +2014,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -2012,6 +2014,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->port.pmf = 0; bp->port.pmf = 0;
load_error1: load_error1:
bnx2x_napi_disable(bp); bnx2x_napi_disable(bp);
/* clear pf_load status, as it was already set */
bnx2x_clear_pf_load(bp);
load_error0: load_error0:
bnx2x_free_mem(bp); bnx2x_free_mem(bp);
...@@ -2132,7 +2136,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) ...@@ -2132,7 +2136,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
/* The last driver must disable a "close the gate" if there is no /* The last driver must disable a "close the gate" if there is no
* parity attention or "process kill" pending. * parity attention or "process kill" pending.
*/ */
if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp); bnx2x_disable_close_the_gate(bp);
return 0; return 0;
......
...@@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id, ...@@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
unsigned long ramrod_flags); unsigned long ramrod_flags);
/* Parity errors related */ /* Parity errors related */
void bnx2x_inc_load_cnt(struct bnx2x *bp); void bnx2x_set_pf_load(struct bnx2x *bp);
u32 bnx2x_dec_load_cnt(struct bnx2x *bp); bool bnx2x_clear_pf_load(struct bnx2x *bp);
bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print); bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
bool bnx2x_reset_is_done(struct bnx2x *bp, int engine); bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
void bnx2x_set_reset_in_progress(struct bnx2x *bp); void bnx2x_set_reset_in_progress(struct bnx2x *bp);
......
...@@ -3812,11 +3812,11 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine) ...@@ -3812,11 +3812,11 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
} }
/* /*
* Increment the load counter for the current engine. * set pf load for the current pf.
* *
* should be run under rtnl lock * should be run under rtnl lock
*/ */
void bnx2x_inc_load_cnt(struct bnx2x *bp) void bnx2x_set_pf_load(struct bnx2x *bp)
{ {
u32 val1, val; u32 val1, val;
u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
...@@ -3832,8 +3832,8 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp) ...@@ -3832,8 +3832,8 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
/* get the current counter value */ /* get the current counter value */
val1 = (val & mask) >> shift; val1 = (val & mask) >> shift;
/* increment... */ /* set bit of that PF */
val1++; val1 |= (1 << bp->pf_num);
/* clear the old value */ /* clear the old value */
val &= ~mask; val &= ~mask;
...@@ -3846,15 +3846,15 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp) ...@@ -3846,15 +3846,15 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
} }
/** /**
* bnx2x_dec_load_cnt - decrement the load counter * bnx2x_clear_pf_load - clear pf load mark
* *
* @bp: driver handle * @bp: driver handle
* *
* Should be run under rtnl lock. * Should be run under rtnl lock.
* Decrements the load counter for the current engine. Returns * Decrements the load counter for the current engine. Returns
* the new counter value. * whether other functions are still loaded
*/ */
u32 bnx2x_dec_load_cnt(struct bnx2x *bp) bool bnx2x_clear_pf_load(struct bnx2x *bp)
{ {
u32 val1, val; u32 val1, val;
u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
...@@ -3869,8 +3869,8 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp) ...@@ -3869,8 +3869,8 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
/* get the current counter value */ /* get the current counter value */
val1 = (val & mask) >> shift; val1 = (val & mask) >> shift;
/* decrement... */ /* clear bit of that PF */
val1--; val1 &= ~(1 << bp->pf_num);
/* clear the old value */ /* clear the old value */
val &= ~mask; val &= ~mask;
...@@ -3884,11 +3884,11 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp) ...@@ -3884,11 +3884,11 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
} }
/* /*
* Read the load counter for the current engine. * Read the load status for the current engine.
* *
* should be run under rtnl lock * should be run under rtnl lock
*/ */
static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
{ {
u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK : u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
BNX2X_PATH0_LOAD_CNT_MASK); BNX2X_PATH0_LOAD_CNT_MASK);
...@@ -3900,17 +3900,15 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) ...@@ -3900,17 +3900,15 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
val = (val & mask) >> shift; val = (val & mask) >> shift;
DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val); DP(NETIF_MSG_HW, "load mask for engine %d = 0x%x\n", engine, val);
return val; return val != 0;
} }
/* /*
* Reset the load counter for the current engine. * Reset the load status for the current engine.
*
* should be run under rtnl lock
*/ */
static inline void bnx2x_clear_load_cnt(struct bnx2x *bp) static inline void bnx2x_clear_load_status(struct bnx2x *bp)
{ {
u32 val; u32 val;
u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
...@@ -8582,10 +8580,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp) ...@@ -8582,10 +8580,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n"); DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
if (bp->is_leader) { if (bp->is_leader) {
int other_engine = BP_PATH(bp) ? 0 : 1; int other_engine = BP_PATH(bp) ? 0 : 1;
u32 other_load_counter = bool other_load_status =
bnx2x_get_load_cnt(bp, other_engine); bnx2x_get_load_status(bp, other_engine);
u32 load_counter = bool load_status =
bnx2x_get_load_cnt(bp, BP_PATH(bp)); bnx2x_get_load_status(bp, BP_PATH(bp));
global = bnx2x_reset_is_global(bp); global = bnx2x_reset_is_global(bp);
/* /*
...@@ -8596,8 +8594,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp) ...@@ -8596,8 +8594,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
* the the gates will remain closed for that * the the gates will remain closed for that
* engine. * engine.
*/ */
if (load_counter || if (load_status ||
(global && other_load_counter)) { (global && other_load_status)) {
/* Wait until all other functions get /* Wait until all other functions get
* down. * down.
*/ */
...@@ -10206,14 +10204,14 @@ static int bnx2x_open(struct net_device *dev) ...@@ -10206,14 +10204,14 @@ static int bnx2x_open(struct net_device *dev)
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);
bool global = false; bool global = false;
int other_engine = BP_PATH(bp) ? 0 : 1; int other_engine = BP_PATH(bp) ? 0 : 1;
u32 other_load_counter, load_counter; bool other_load_status, load_status;
netif_carrier_off(dev); netif_carrier_off(dev);
bnx2x_set_power_state(bp, PCI_D0); bnx2x_set_power_state(bp, PCI_D0);
other_load_counter = bnx2x_get_load_cnt(bp, other_engine); other_load_status = bnx2x_get_load_status(bp, other_engine);
load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp)); load_status = bnx2x_get_load_status(bp, BP_PATH(bp));
/* /*
* If parity had happen during the unload, then attentions * If parity had happen during the unload, then attentions
...@@ -10239,8 +10237,8 @@ static int bnx2x_open(struct net_device *dev) ...@@ -10239,8 +10237,8 @@ static int bnx2x_open(struct net_device *dev)
* global blocks only the first in the chip should try * global blocks only the first in the chip should try
* to recover. * to recover.
*/ */
if ((!load_counter && if ((!load_status &&
(!global || !other_load_counter)) && (!global || !other_load_status)) &&
bnx2x_trylock_leader_lock(bp) && bnx2x_trylock_leader_lock(bp) &&
!bnx2x_leader_reset(bp)) { !bnx2x_leader_reset(bp)) {
netdev_info(bp->dev, "Recovered in open\n"); netdev_info(bp->dev, "Recovered in open\n");
...@@ -10680,7 +10678,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, ...@@ -10680,7 +10678,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
/* Reset the load counter */ /* Reset the load counter */
bnx2x_clear_load_cnt(bp); bnx2x_clear_load_status(bp);
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
......
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