diff options
author | Ido Schimmel <idosch@mellanox.com> | 2016-08-24 06:00:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-24 12:41:12 -0400 |
commit | 584d73df06253f206e31ff897a475283167bf0f0 (patch) | |
tree | 61f599c699ee06dc38671ab391c7f68d279a5e31 | |
parent | 640be7b7177dbe026cf7ae387b21f6917f0fc44f (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.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 35 |
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 | ||
558 | static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, | 558 | int __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 | ||
576 | static 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 | |||
575 | static int | 583 | static int |
576 | mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port) | 584 | mlxsw_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, | |||
558 | int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port, | 558 | int 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); |
561 | int __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 | ||
638 | static 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 | |||
638 | static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, | 659 | static 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, | |||
697 | err_port_stp_state_set: | 726 | err_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); | ||
731 | err_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); |
702 | err_port_pvid_set: | 734 | err_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); |