Skip to content

Commit

Permalink
bnx2x: Track active PFs with bitmap
Browse files Browse the repository at this point in the history
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: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ariel Elior authored and David S. Miller committed Jan 26, 2012
1 parent f16da43 commit 889b9af
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 33 deletions.
8 changes: 6 additions & 2 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)

bnx2x_napi_enable(bp);

/* set pf load just before approaching the MCP */
bnx2x_set_pf_load(bp);

/* Send LOAD_REQUEST command to MCP
* Returns the type of LOAD command:
* if it is the first port to be initialized
Expand Down Expand Up @@ -1972,7 +1975,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
#endif
bnx2x_inc_load_cnt(bp);

/* Wait for all pending SP commands to complete */
if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
Expand Down Expand Up @@ -2012,6 +2014,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->port.pmf = 0;
load_error1:
bnx2x_napi_disable(bp);
/* clear pf_load status, as it was already set */
bnx2x_clear_pf_load(bp);
load_error0:
bnx2x_free_mem(bp);

Expand Down Expand Up @@ -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
* 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);

return 0;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
unsigned long ramrod_flags);

/* Parity errors related */
void bnx2x_inc_load_cnt(struct bnx2x *bp);
u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
void bnx2x_set_pf_load(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_reset_is_done(struct bnx2x *bp, int engine);
void bnx2x_set_reset_in_progress(struct bnx2x *bp);
Expand Down
56 changes: 27 additions & 29 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
void bnx2x_inc_load_cnt(struct bnx2x *bp)
void bnx2x_set_pf_load(struct bnx2x *bp)
{
u32 val1, val;
u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
Expand All @@ -3832,8 +3832,8 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
/* get the current counter value */
val1 = (val & mask) >> shift;

/* increment... */
val1++;
/* set bit of that PF */
val1 |= (1 << bp->pf_num);

/* clear the old value */
val &= ~mask;
Expand All @@ -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
*
* Should be run under rtnl lock.
* 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 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
Expand All @@ -3869,8 +3869,8 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
/* get the current counter value */
val1 = (val & mask) >> shift;

/* decrement... */
val1--;
/* clear bit of that PF */
val1 &= ~(1 << bp->pf_num);

/* clear the old value */
val &= ~mask;
Expand All @@ -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
*/
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 :
BNX2X_PATH0_LOAD_CNT_MASK);
Expand All @@ -3900,17 +3900,15 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)

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.
*
* should be run under rtnl lock
* Reset the load status for the current engine.
*/
static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
static inline void bnx2x_clear_load_status(struct bnx2x *bp)
{
u32 val;
u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
Expand Down Expand Up @@ -8582,10 +8580,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
if (bp->is_leader) {
int other_engine = BP_PATH(bp) ? 0 : 1;
u32 other_load_counter =
bnx2x_get_load_cnt(bp, other_engine);
u32 load_counter =
bnx2x_get_load_cnt(bp, BP_PATH(bp));
bool other_load_status =
bnx2x_get_load_status(bp, other_engine);
bool load_status =
bnx2x_get_load_status(bp, BP_PATH(bp));
global = bnx2x_reset_is_global(bp);

/*
Expand All @@ -8596,8 +8594,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
* the the gates will remain closed for that
* engine.
*/
if (load_counter ||
(global && other_load_counter)) {
if (load_status ||
(global && other_load_status)) {
/* Wait until all other functions get
* down.
*/
Expand Down Expand Up @@ -10206,14 +10204,14 @@ static int bnx2x_open(struct net_device *dev)
struct bnx2x *bp = netdev_priv(dev);
bool global = false;
int other_engine = BP_PATH(bp) ? 0 : 1;
u32 other_load_counter, load_counter;
bool other_load_status, load_status;

netif_carrier_off(dev);

bnx2x_set_power_state(bp, PCI_D0);

other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
other_load_status = bnx2x_get_load_status(bp, other_engine);
load_status = bnx2x_get_load_status(bp, BP_PATH(bp));

/*
* If parity had happen during the unload, then attentions
Expand All @@ -10239,8 +10237,8 @@ static int bnx2x_open(struct net_device *dev)
* global blocks only the first in the chip should try
* to recover.
*/
if ((!load_counter &&
(!global || !other_load_counter)) &&
if ((!load_status &&
(!global || !other_load_status)) &&
bnx2x_trylock_leader_lock(bp) &&
!bnx2x_leader_reset(bp)) {
netdev_info(bp->dev, "Recovered in open\n");
Expand Down Expand Up @@ -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);

/* Reset the load counter */
bnx2x_clear_load_cnt(bp);
bnx2x_clear_load_status(bp);

dev->watchdog_timeo = TX_TIMEOUT;

Expand Down

0 comments on commit 889b9af

Please sign in to comment.