aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2016-08-24 06:00:26 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-24 12:41:12 -0400
commit584d73df06253f206e31ff897a475283167bf0f0 (patch)
tree61f599c699ee06dc38671ab391c7f68d279a5e31
parent640be7b7177dbe026cf7ae387b21f6917f0fc44f (diff)
mlxsw: spectrum: Configure learning for VLAN-aware bridge port
We are going to prevent the device from generating learning notifications for a port that was configured with learning disabled. Since learning configuration is done per {Port, VID} we need to apply the port's learning configuration for any VID that is added to the bridge port's VLAN filter list. When a VID is added to the VLAN filter list of a VLAN-aware bridge port, configure the {Port, VID} learning status according to the port's configuration. When the VID is removed, disable learning for the {Port, VID}. 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/spectrum.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c35
3 files changed, 50 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 1f8168906811..3820317d9a42 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -555,8 +555,9 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
555 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); 555 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
556} 556}
557 557
558static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, 558int __mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
559 u16 vid, bool learn_enable) 559 u16 vid_begin, u16 vid_end,
560 bool learn_enable)
560{ 561{
561 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 562 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
562 char *spvmlr_pl; 563 char *spvmlr_pl;
@@ -565,13 +566,20 @@ static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
565 spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL); 566 spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL);
566 if (!spvmlr_pl) 567 if (!spvmlr_pl)
567 return -ENOMEM; 568 return -ENOMEM;
568 mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid, 569 mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid_begin,
569 learn_enable); 570 vid_end, learn_enable);
570 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl); 571 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl);
571 kfree(spvmlr_pl); 572 kfree(spvmlr_pl);
572 return err; 573 return err;
573} 574}
574 575
576static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
577 u16 vid, bool learn_enable)
578{
579 return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
580 learn_enable);
581}
582
575static int 583static int
576mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port) 584mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
577{ 585{
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index ab3feb81bd43..01537d3a1c48 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -558,6 +558,9 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
558int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, 558int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
559 enum mlxsw_reg_qeec_hr hr, u8 index, 559 enum mlxsw_reg_qeec_hr hr, u8 index,
560 u8 next_index, u32 maxrate); 560 u8 next_index, u32 maxrate);
561int __mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
562 u16 vid_begin, u16 vid_end,
563 bool learn_enable);
561 564
562#ifdef CONFIG_MLXSW_SPECTRUM_DCB 565#ifdef CONFIG_MLXSW_SPECTRUM_DCB
563 566
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index e5cf8a5da5d0..d1b2b11a3936 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -635,6 +635,27 @@ static int __mlxsw_sp_port_vlans_set(struct mlxsw_sp_port *mlxsw_sp_port,
635 return 0; 635 return 0;
636} 636}
637 637
638static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
639 u16 vid_begin, u16 vid_end,
640 bool learn_enable)
641{
642 u16 vid, vid_e;
643 int err;
644
645 for (vid = vid_begin; vid <= vid_end;
646 vid += MLXSW_REG_SPVMLR_REC_MAX_COUNT) {
647 vid_e = min((u16) (vid + MLXSW_REG_SPVMLR_REC_MAX_COUNT - 1),
648 vid_end);
649
650 err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid,
651 vid_e, learn_enable);
652 if (err)
653 return err;
654 }
655
656 return 0;
657}
658
638static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, 659static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
639 u16 vid_begin, u16 vid_end, 660 u16 vid_begin, u16 vid_end,
640 bool flag_untagged, bool flag_pvid) 661 bool flag_untagged, bool flag_pvid)
@@ -675,6 +696,14 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
675 } 696 }
676 } 697 }
677 698
699 err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
700 mlxsw_sp_port->learning);
701 if (err) {
702 netdev_err(dev, "Failed to set learning for VIDs %d-%d\n",
703 vid_begin, vid_end);
704 goto err_port_vid_learning_set;
705 }
706
678 /* Changing activity bits only if HW operation succeded */ 707 /* Changing activity bits only if HW operation succeded */
679 for (vid = vid_begin; vid <= vid_end; vid++) { 708 for (vid = vid_begin; vid <= vid_end; vid++) {
680 set_bit(vid, mlxsw_sp_port->active_vlans); 709 set_bit(vid, mlxsw_sp_port->active_vlans);
@@ -697,6 +726,9 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
697err_port_stp_state_set: 726err_port_stp_state_set:
698 for (vid = vid_begin; vid <= vid_end; vid++) 727 for (vid = vid_begin; vid <= vid_end; vid++)
699 clear_bit(vid, mlxsw_sp_port->active_vlans); 728 clear_bit(vid, mlxsw_sp_port->active_vlans);
729 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
730 false);
731err_port_vid_learning_set:
700 if (old_pvid != mlxsw_sp_port->pvid) 732 if (old_pvid != mlxsw_sp_port->pvid)
701 mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid); 733 mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid);
702err_port_pvid_set: 734err_port_pvid_set:
@@ -1006,6 +1038,9 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
1006 if (!mlxsw_sp_port->bridged) 1038 if (!mlxsw_sp_port->bridged)
1007 return -EINVAL; 1039 return -EINVAL;
1008 1040
1041 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
1042 false);
1043
1009 pvid = mlxsw_sp_port->pvid; 1044 pvid = mlxsw_sp_port->pvid;
1010 if (pvid >= vid_begin && pvid <= vid_end) 1045 if (pvid >= vid_begin && pvid <= vid_end)
1011 mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0); 1046 mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);