aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2016-08-24 06:00:23 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-24 12:41:11 -0400
commit1803e0fb7ef9534154e6a1abf77bc2ca352f72e1 (patch)
treed7b73756b7170c50379e40f2a7e9d7f1c57d3fa1
parentfff84d2a39603336ccb7140e282c4011315e29c4 (diff)
mlxsw: spectrum: Limit number of FDB records per learning session
Up until now a learning session ended whenever the number of queried records was zero. This turned out to be problematic in situations where a large number of MACs (48K) had to be processed by the switch driver, as RTNL mutex is held during the learning session. Instead, limit the number of FDB records that can be processed in a session to 64. This means that every time the device is queried for learning notifications (currently, every 100ms), up to 64 records will be processed by the switch driver. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c22
2 files changed, 17 insertions, 12 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 1721098eef13..b83d0a7a0b49 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -591,6 +591,12 @@ static const struct mlxsw_reg_info mlxsw_reg_sfn = {
591 */ 591 */
592MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8); 592MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8);
593 593
594/* reg_sfn_end
595 * Forces the current session to end.
596 * Access: OP
597 */
598MLXSW_ITEM32(reg, sfn, end, 0x04, 20, 1);
599
594/* reg_sfn_num_rec 600/* reg_sfn_num_rec
595 * Request: Number of learned notifications and aged-out notification 601 * Request: Number of learned notifications and aged-out notification
596 * records requested. 602 * records requested.
@@ -605,6 +611,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload)
605{ 611{
606 MLXSW_REG_ZERO(sfn, payload); 612 MLXSW_REG_ZERO(sfn, payload);
607 mlxsw_reg_sfn_swid_set(payload, 0); 613 mlxsw_reg_sfn_swid_set(payload, 0);
614 mlxsw_reg_sfn_end_set(payload, 1);
608 mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT); 615 mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
609} 616}
610 617
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index d1b59cdfacc1..02de24080e79 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1496,20 +1496,18 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
1496 mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work); 1496 mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
1497 1497
1498 rtnl_lock(); 1498 rtnl_lock();
1499 do { 1499 mlxsw_reg_sfn_pack(sfn_pl);
1500 mlxsw_reg_sfn_pack(sfn_pl); 1500 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
1501 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl); 1501 if (err) {
1502 if (err) { 1502 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
1503 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n"); 1503 goto out;
1504 break; 1504 }
1505 } 1505 num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
1506 num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl); 1506 for (i = 0; i < num_rec; i++)
1507 for (i = 0; i < num_rec; i++) 1507 mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
1508 mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
1509 1508
1510 } while (num_rec); 1509out:
1511 rtnl_unlock(); 1510 rtnl_unlock();
1512
1513 kfree(sfn_pl); 1511 kfree(sfn_pl);
1514 mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); 1512 mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
1515} 1513}