aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorDmitry Kravkov <dmitry@broadcom.com>2013-08-12 19:24:59 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-13 19:04:28 -0400
commit507393eb2909ddf39edf3f8f4cd0fd914b720006 (patch)
treeb6698cefef1be7ac49d3c1db4ec5a6dd56a90a6b /drivers/net/ethernet
parent205057aeb3c488fbd4a9c3a0542e05dcf4fda149 (diff)
bnx2x: protect different statistics flows
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>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c66
3 files changed, 57 insertions, 12 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index d80e34b8285f..98be67f660f2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1830,6 +1830,8 @@ struct bnx2x {
1830 1830
1831 int fp_array_size; 1831 int fp_array_size;
1832 u32 dump_preset_idx; 1832 u32 dump_preset_idx;
1833 bool stats_started;
1834 struct semaphore stats_sema;
1833}; 1835};
1834 1836
1835/* Tx queues may be less or equal to Rx queues */ 1837/* Tx queues may be less or equal to Rx queues */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e06186c305d8..6e1e9e7d8201 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -11524,6 +11524,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
11524 mutex_init(&bp->port.phy_mutex); 11524 mutex_init(&bp->port.phy_mutex);
11525 mutex_init(&bp->fw_mb_mutex); 11525 mutex_init(&bp->fw_mb_mutex);
11526 spin_lock_init(&bp->stats_lock); 11526 spin_lock_init(&bp->stats_lock);
11527 sema_init(&bp->stats_sema, 1);
11527 11528
11528 INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); 11529 INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
11529 INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); 11530 INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 98366abd02bd..d63d1327b051 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -221,7 +221,8 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
221 * Statistics service functions 221 * Statistics service functions
222 */ 222 */
223 223
224static void bnx2x_stats_pmf_update(struct bnx2x *bp) 224/* should be called under stats_sema */
225static void __bnx2x_stats_pmf_update(struct bnx2x *bp)
225{ 226{
226 struct dmae_command *dmae; 227 struct dmae_command *dmae;
227 u32 opcode; 228 u32 opcode;
@@ -518,7 +519,8 @@ static void bnx2x_func_stats_init(struct bnx2x *bp)
518 *stats_comp = 0; 519 *stats_comp = 0;
519} 520}
520 521
521static void bnx2x_stats_start(struct bnx2x *bp) 522/* should be called under stats_sema */
523static void __bnx2x_stats_start(struct bnx2x *bp)
522{ 524{
523 /* vfs travel through here as part of the statistics FSM, but no action 525 /* vfs travel through here as part of the statistics FSM, but no action
524 * is required 526 * is required
@@ -534,13 +536,34 @@ static void bnx2x_stats_start(struct bnx2x *bp)
534 536
535 bnx2x_hw_stats_post(bp); 537 bnx2x_hw_stats_post(bp);
536 bnx2x_storm_stats_post(bp); 538 bnx2x_storm_stats_post(bp);
539
540 bp->stats_started = true;
541}
542
543static void bnx2x_stats_start(struct bnx2x *bp)
544{
545 if (down_timeout(&bp->stats_sema, HZ/10))
546 BNX2X_ERR("Unable to acquire stats lock\n");
547 __bnx2x_stats_start(bp);
548 up(&bp->stats_sema);
537} 549}
538 550
539static void bnx2x_stats_pmf_start(struct bnx2x *bp) 551static void bnx2x_stats_pmf_start(struct bnx2x *bp)
540{ 552{
553 if (down_timeout(&bp->stats_sema, HZ/10))
554 BNX2X_ERR("Unable to acquire stats lock\n");
541 bnx2x_stats_comp(bp); 555 bnx2x_stats_comp(bp);
542 bnx2x_stats_pmf_update(bp); 556 __bnx2x_stats_pmf_update(bp);
543 bnx2x_stats_start(bp); 557 __bnx2x_stats_start(bp);
558 up(&bp->stats_sema);
559}
560
561static void bnx2x_stats_pmf_update(struct bnx2x *bp)
562{
563 if (down_timeout(&bp->stats_sema, HZ/10))
564 BNX2X_ERR("Unable to acquire stats lock\n");
565 __bnx2x_stats_pmf_update(bp);
566 up(&bp->stats_sema);
544} 567}
545 568
546static void bnx2x_stats_restart(struct bnx2x *bp) 569static void bnx2x_stats_restart(struct bnx2x *bp)
@@ -550,8 +573,11 @@ static void bnx2x_stats_restart(struct bnx2x *bp)
550 */ 573 */
551 if (IS_VF(bp)) 574 if (IS_VF(bp))
552 return; 575 return;
576 if (down_timeout(&bp->stats_sema, HZ/10))
577 BNX2X_ERR("Unable to acquire stats lock\n");
553 bnx2x_stats_comp(bp); 578 bnx2x_stats_comp(bp);
554 bnx2x_stats_start(bp); 579 __bnx2x_stats_start(bp);
580 up(&bp->stats_sema);
555} 581}
556 582
557static void bnx2x_bmac_stats_update(struct bnx2x *bp) 583static void bnx2x_bmac_stats_update(struct bnx2x *bp)
@@ -888,9 +914,7 @@ static int bnx2x_storm_stats_validate_counters(struct bnx2x *bp)
888 /* Make sure we use the value of the counter 914 /* Make sure we use the value of the counter
889 * used for sending the last stats ramrod. 915 * used for sending the last stats ramrod.
890 */ 916 */
891 spin_lock_bh(&bp->stats_lock);
892 cur_stats_counter = bp->stats_counter - 1; 917 cur_stats_counter = bp->stats_counter - 1;
893 spin_unlock_bh(&bp->stats_lock);
894 918
895 /* are storm stats valid? */ 919 /* are storm stats valid? */
896 if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) { 920 if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
@@ -1227,12 +1251,18 @@ static void bnx2x_stats_update(struct bnx2x *bp)
1227{ 1251{
1228 u32 *stats_comp = bnx2x_sp(bp, stats_comp); 1252 u32 *stats_comp = bnx2x_sp(bp, stats_comp);
1229 1253
1230 if (bnx2x_edebug_stats_stopped(bp)) 1254 /* we run update from timer context, so give up
1255 * if somebody is in the middle of transition
1256 */
1257 if (down_trylock(&bp->stats_sema))
1231 return; 1258 return;
1232 1259
1260 if (bnx2x_edebug_stats_stopped(bp) || !bp->stats_started)
1261 goto out;
1262
1233 if (IS_PF(bp)) { 1263 if (IS_PF(bp)) {
1234 if (*stats_comp != DMAE_COMP_VAL) 1264 if (*stats_comp != DMAE_COMP_VAL)
1235 return; 1265 goto out;
1236 1266
1237 if (bp->port.pmf) 1267 if (bp->port.pmf)
1238 bnx2x_hw_stats_update(bp); 1268 bnx2x_hw_stats_update(bp);
@@ -1242,7 +1272,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
1242 BNX2X_ERR("storm stats were not updated for 3 times\n"); 1272 BNX2X_ERR("storm stats were not updated for 3 times\n");
1243 bnx2x_panic(); 1273 bnx2x_panic();
1244 } 1274 }
1245 return; 1275 goto out;
1246 } 1276 }
1247 } else { 1277 } else {
1248 /* vf doesn't collect HW statistics, and doesn't get completions 1278 /* vf doesn't collect HW statistics, and doesn't get completions
@@ -1256,7 +1286,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
1256 1286
1257 /* vf is done */ 1287 /* vf is done */
1258 if (IS_VF(bp)) 1288 if (IS_VF(bp))
1259 return; 1289 goto out;
1260 1290
1261 if (netif_msg_timer(bp)) { 1291 if (netif_msg_timer(bp)) {
1262 struct bnx2x_eth_stats *estats = &bp->eth_stats; 1292 struct bnx2x_eth_stats *estats = &bp->eth_stats;
@@ -1267,6 +1297,9 @@ static void bnx2x_stats_update(struct bnx2x *bp)
1267 1297
1268 bnx2x_hw_stats_post(bp); 1298 bnx2x_hw_stats_post(bp);
1269 bnx2x_storm_stats_post(bp); 1299 bnx2x_storm_stats_post(bp);
1300
1301out:
1302 up(&bp->stats_sema);
1270} 1303}
1271 1304
1272static void bnx2x_port_stats_stop(struct bnx2x *bp) 1305static void bnx2x_port_stats_stop(struct bnx2x *bp)
@@ -1332,6 +1365,11 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
1332{ 1365{
1333 int update = 0; 1366 int update = 0;
1334 1367
1368 if (down_timeout(&bp->stats_sema, HZ/10))
1369 BNX2X_ERR("Unable to acquire stats lock\n");
1370
1371 bp->stats_started = false;
1372
1335 bnx2x_stats_comp(bp); 1373 bnx2x_stats_comp(bp);
1336 1374
1337 if (bp->port.pmf) 1375 if (bp->port.pmf)
@@ -1348,6 +1386,8 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
1348 bnx2x_hw_stats_post(bp); 1386 bnx2x_hw_stats_post(bp);
1349 bnx2x_stats_comp(bp); 1387 bnx2x_stats_comp(bp);
1350 } 1388 }
1389
1390 up(&bp->stats_sema);
1351} 1391}
1352 1392
1353static void bnx2x_stats_do_nothing(struct bnx2x *bp) 1393static void bnx2x_stats_do_nothing(struct bnx2x *bp)
@@ -1376,15 +1416,17 @@ static const struct {
1376void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) 1416void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
1377{ 1417{
1378 enum bnx2x_stats_state state; 1418 enum bnx2x_stats_state state;
1419 void (*action)(struct bnx2x *bp);
1379 if (unlikely(bp->panic)) 1420 if (unlikely(bp->panic))
1380 return; 1421 return;
1381 1422
1382 spin_lock_bh(&bp->stats_lock); 1423 spin_lock_bh(&bp->stats_lock);
1383 state = bp->stats_state; 1424 state = bp->stats_state;
1384 bp->stats_state = bnx2x_stats_stm[state][event].next_state; 1425 bp->stats_state = bnx2x_stats_stm[state][event].next_state;
1426 action = bnx2x_stats_stm[state][event].action;
1385 spin_unlock_bh(&bp->stats_lock); 1427 spin_unlock_bh(&bp->stats_lock);
1386 1428
1387 bnx2x_stats_stm[state][event].action(bp); 1429 action(bp);
1388 1430
1389 if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) 1431 if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
1390 DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", 1432 DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",