Skip to content

Commit

Permalink
bnx2x: protect different statistics flows
Browse files Browse the repository at this point in the history
Add locking to protect different statistics flows from
running simultaneously.
This in order to serialize statistics requests sent to FW,
otherwise two outstanding queries may cause FW assert.

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dmitry Kravkov authored and David S. Miller committed Aug 13, 2013
1 parent 205057a commit 507393e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 12 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,8 @@ struct bnx2x {

int fp_array_size;
u32 dump_preset_idx;
bool stats_started;
struct semaphore stats_sema;
};

/* Tx queues may be less or equal to Rx queues */
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11524,6 +11524,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
spin_lock_init(&bp->stats_lock);
sema_init(&bp->stats_sema, 1);

INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
Expand Down
66 changes: 54 additions & 12 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
* Statistics service functions
*/

static void bnx2x_stats_pmf_update(struct bnx2x *bp)
/* should be called under stats_sema */
static void __bnx2x_stats_pmf_update(struct bnx2x *bp)
{
struct dmae_command *dmae;
u32 opcode;
Expand Down Expand Up @@ -518,7 +519,8 @@ static void bnx2x_func_stats_init(struct bnx2x *bp)
*stats_comp = 0;
}

static void bnx2x_stats_start(struct bnx2x *bp)
/* should be called under stats_sema */
static void __bnx2x_stats_start(struct bnx2x *bp)
{
/* vfs travel through here as part of the statistics FSM, but no action
* is required
Expand All @@ -534,13 +536,34 @@ static void bnx2x_stats_start(struct bnx2x *bp)

bnx2x_hw_stats_post(bp);
bnx2x_storm_stats_post(bp);

bp->stats_started = true;
}

static void bnx2x_stats_start(struct bnx2x *bp)
{
if (down_timeout(&bp->stats_sema, HZ/10))
BNX2X_ERR("Unable to acquire stats lock\n");
__bnx2x_stats_start(bp);
up(&bp->stats_sema);
}

static void bnx2x_stats_pmf_start(struct bnx2x *bp)
{
if (down_timeout(&bp->stats_sema, HZ/10))
BNX2X_ERR("Unable to acquire stats lock\n");
bnx2x_stats_comp(bp);
bnx2x_stats_pmf_update(bp);
bnx2x_stats_start(bp);
__bnx2x_stats_pmf_update(bp);
__bnx2x_stats_start(bp);
up(&bp->stats_sema);
}

static void bnx2x_stats_pmf_update(struct bnx2x *bp)
{
if (down_timeout(&bp->stats_sema, HZ/10))
BNX2X_ERR("Unable to acquire stats lock\n");
__bnx2x_stats_pmf_update(bp);
up(&bp->stats_sema);
}

static void bnx2x_stats_restart(struct bnx2x *bp)
Expand All @@ -550,8 +573,11 @@ static void bnx2x_stats_restart(struct bnx2x *bp)
*/
if (IS_VF(bp))
return;
if (down_timeout(&bp->stats_sema, HZ/10))
BNX2X_ERR("Unable to acquire stats lock\n");
bnx2x_stats_comp(bp);
bnx2x_stats_start(bp);
__bnx2x_stats_start(bp);
up(&bp->stats_sema);
}

static void bnx2x_bmac_stats_update(struct bnx2x *bp)
Expand Down Expand Up @@ -888,9 +914,7 @@ static int bnx2x_storm_stats_validate_counters(struct bnx2x *bp)
/* Make sure we use the value of the counter
* used for sending the last stats ramrod.
*/
spin_lock_bh(&bp->stats_lock);
cur_stats_counter = bp->stats_counter - 1;
spin_unlock_bh(&bp->stats_lock);

/* are storm stats valid? */
if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
Expand Down Expand Up @@ -1227,12 +1251,18 @@ static void bnx2x_stats_update(struct bnx2x *bp)
{
u32 *stats_comp = bnx2x_sp(bp, stats_comp);

if (bnx2x_edebug_stats_stopped(bp))
/* we run update from timer context, so give up
* if somebody is in the middle of transition
*/
if (down_trylock(&bp->stats_sema))
return;

if (bnx2x_edebug_stats_stopped(bp) || !bp->stats_started)
goto out;

if (IS_PF(bp)) {
if (*stats_comp != DMAE_COMP_VAL)
return;
goto out;

if (bp->port.pmf)
bnx2x_hw_stats_update(bp);
Expand All @@ -1242,7 +1272,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
BNX2X_ERR("storm stats were not updated for 3 times\n");
bnx2x_panic();
}
return;
goto out;
}
} else {
/* vf doesn't collect HW statistics, and doesn't get completions
Expand All @@ -1256,7 +1286,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)

/* vf is done */
if (IS_VF(bp))
return;
goto out;

if (netif_msg_timer(bp)) {
struct bnx2x_eth_stats *estats = &bp->eth_stats;
Expand All @@ -1267,6 +1297,9 @@ static void bnx2x_stats_update(struct bnx2x *bp)

bnx2x_hw_stats_post(bp);
bnx2x_storm_stats_post(bp);

out:
up(&bp->stats_sema);
}

static void bnx2x_port_stats_stop(struct bnx2x *bp)
Expand Down Expand Up @@ -1332,6 +1365,11 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
{
int update = 0;

if (down_timeout(&bp->stats_sema, HZ/10))
BNX2X_ERR("Unable to acquire stats lock\n");

bp->stats_started = false;

bnx2x_stats_comp(bp);

if (bp->port.pmf)
Expand All @@ -1348,6 +1386,8 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
bnx2x_hw_stats_post(bp);
bnx2x_stats_comp(bp);
}

up(&bp->stats_sema);
}

static void bnx2x_stats_do_nothing(struct bnx2x *bp)
Expand Down Expand Up @@ -1376,15 +1416,17 @@ static const struct {
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
{
enum bnx2x_stats_state state;
void (*action)(struct bnx2x *bp);
if (unlikely(bp->panic))
return;

spin_lock_bh(&bp->stats_lock);
state = bp->stats_state;
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
action = bnx2x_stats_stm[state][event].action;
spin_unlock_bh(&bp->stats_lock);

bnx2x_stats_stm[state][event].action(bp);
action(bp);

if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
Expand Down

0 comments on commit 507393e

Please sign in to comment.