aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVladislav Zolotarov <vladz@broadcom.com>2010-07-21 01:59:01 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-21 14:11:54 -0400
commita13773a53faa28cf79982601b6fc9ddb0ca45f36 (patch)
tree1eb2a88545d8ffe742648886b9da48446b6f0eb0 /drivers
parent573201f36fd9c7c6d5218cdcd9948cee700b277d (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/bnx2x.h4
-rw-r--r--drivers/net/bnx2x_main.c11
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
4850static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) 4850static 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