diff options
author | Vladislav Zolotarov <vladz@broadcom.com> | 2010-07-21 01:59:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-21 14:11:54 -0400 |
commit | a13773a53faa28cf79982601b6fc9ddb0ca45f36 (patch) | |
tree | 1eb2a88545d8ffe742648886b9da48446b6f0eb0 | |
parent | 573201f36fd9c7c6d5218cdcd9948cee700b277d (diff) |
bnx2x: Protect a SM state change
Bug fix: Protect the statistics state machine state update with a
spinlock. Otherwise there was a race condition that would cause the
statistics to stay enabled despite the fact that they were disabled in
the LINK_DOWN event handler.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bnx2x.h | 4 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 11 |
2 files changed, 11 insertions, 4 deletions
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 8bd23687c530..bb0872a63315 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h | |||
@@ -1062,6 +1062,10 @@ struct bnx2x { | |||
1062 | 1062 | ||
1063 | /* used to synchronize stats collecting */ | 1063 | /* used to synchronize stats collecting */ |
1064 | int stats_state; | 1064 | int stats_state; |
1065 | |||
1066 | /* used for synchronization of concurrent threads statistics handling */ | ||
1067 | spinlock_t stats_lock; | ||
1068 | |||
1065 | /* used by dmae command loader */ | 1069 | /* used by dmae command loader */ |
1066 | struct dmae_command stats_dmae; | 1070 | struct dmae_command stats_dmae; |
1067 | int executer_idx; | 1071 | int executer_idx; |
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 57ff5b3bcce6..3dc876ce6e1f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -4849,16 +4849,18 @@ static const struct { | |||
4849 | 4849 | ||
4850 | static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) | 4850 | static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) |
4851 | { | 4851 | { |
4852 | enum bnx2x_stats_state state = bp->stats_state; | 4852 | enum bnx2x_stats_state state; |
4853 | 4853 | ||
4854 | if (unlikely(bp->panic)) | 4854 | if (unlikely(bp->panic)) |
4855 | return; | 4855 | return; |
4856 | 4856 | ||
4857 | bnx2x_stats_stm[state][event].action(bp); | 4857 | /* Protect a state change flow */ |
4858 | spin_lock_bh(&bp->stats_lock); | ||
4859 | state = bp->stats_state; | ||
4858 | bp->stats_state = bnx2x_stats_stm[state][event].next_state; | 4860 | bp->stats_state = bnx2x_stats_stm[state][event].next_state; |
4861 | spin_unlock_bh(&bp->stats_lock); | ||
4859 | 4862 | ||
4860 | /* Make sure the state has been "changed" */ | 4863 | bnx2x_stats_stm[state][event].action(bp); |
4861 | smp_wmb(); | ||
4862 | 4864 | ||
4863 | if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) | 4865 | if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) |
4864 | DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", | 4866 | DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", |
@@ -9908,6 +9910,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) | |||
9908 | 9910 | ||
9909 | mutex_init(&bp->port.phy_mutex); | 9911 | mutex_init(&bp->port.phy_mutex); |
9910 | mutex_init(&bp->fw_mb_mutex); | 9912 | mutex_init(&bp->fw_mb_mutex); |
9913 | spin_lock_init(&bp->stats_lock); | ||
9911 | #ifdef BCM_CNIC | 9914 | #ifdef BCM_CNIC |
9912 | mutex_init(&bp->cnic_mutex); | 9915 | mutex_init(&bp->cnic_mutex); |
9913 | #endif | 9916 | #endif |