From ee4a60d898826d34b804a357847c7910aba80b96 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:29 +0100 Subject: mlxsw: spectrum: Remove unused traps Since commit 99724c18fc66 ("mlxsw: spectrum: Introduce support for router interfaces") we no longer rely on flooding traffic to the CPU in order to trap packets intended for the host itself. Therefore, the FDB MC trap can be removed. Remove traps for protocols that are not supported yet. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index e0d7d5adbaee..2f06de336b38 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2785,15 +2785,10 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, } static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = { - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, FDB_MC, TRAP_TO_CPU), - /* Traps for specific L2 packet types, not trapped as FDB MC */ + /* L2 traps */ MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, STP, TRAP_TO_CPU), MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LACP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, EAPOL, TRAP_TO_CPU), MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LLDP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MMRP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MVRP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RPVST, TRAP_TO_CPU), MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, DHCP, MIRROR_TO_CPU), MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, IGMP_QUERY, MIRROR_TO_CPU), MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V1_REPORT, TRAP_TO_CPU), -- cgit v1.2.3 From 0791051c43ef994149c6d8b3ee7dc8d7e81a16a6 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:30 +0100 Subject: mlxsw: core: Create a generic function to register / unregister traps We have 2 types of HW traps to handle, rx traps and events. The registration workflow for both is very similar. So it only make sense to create one function to handle both. This patch creates a struct to hold the data for both cases. It also creates a registration and an un-registration functions that get this generic struct as input. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 67 ++++++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 18 ++++++++ 2 files changed, 85 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index bcd7251385e3..a8cff78c7029 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1392,6 +1392,73 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_event_listener_unregister); +static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + void *priv) +{ + if (listener->is_event) + return mlxsw_core_event_listener_register(mlxsw_core, + &listener->u.event_listener, + priv); + else + return mlxsw_core_rx_listener_register(mlxsw_core, + &listener->u.rx_listener, + priv); +} + +static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + void *priv) +{ + if (listener->is_event) + mlxsw_core_event_listener_unregister(mlxsw_core, + &listener->u.event_listener, + priv); + else + mlxsw_core_rx_listener_unregister(mlxsw_core, + &listener->u.rx_listener, + priv); +} + +int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, void *priv) +{ + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int err; + + err = mlxsw_core_listener_register(mlxsw_core, listener, priv); + if (err) + return err; + + mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); + if (err) + goto err_trap_set; + + return 0; + +err_trap_set: + mlxsw_core_listener_unregister(mlxsw_core, listener, priv); + return err; +} +EXPORT_SYMBOL(mlxsw_core_trap_register); + +void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + void *priv) +{ + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + + if (!listener->is_event) { + mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action, + listener->trap_id); + mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); + } + + mlxsw_core_listener_unregister(mlxsw_core, listener, priv); +} +EXPORT_SYMBOL(mlxsw_core_trap_unregister); + static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core) { return atomic64_inc_return(&mlxsw_core->emad.tid); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 3de8955a26fd..66d97c495309 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -90,6 +90,17 @@ struct mlxsw_event_listener { enum mlxsw_event_trap_id trap_id; }; +struct mlxsw_listener { + u16 trap_id; + union { + struct mlxsw_rx_listener rx_listener; + struct mlxsw_event_listener event_listener; + } u; + enum mlxsw_reg_hpkt_action action; + enum mlxsw_reg_hpkt_action unreg_action; + bool is_event; +}; + int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, const struct mlxsw_rx_listener *rxl, void *priv); @@ -104,6 +115,13 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core, const struct mlxsw_event_listener *el, void *priv); +int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + void *priv); +void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, + const struct mlxsw_listener *listener, + void *priv); + typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload, size_t payload_len, unsigned long cb_priv); -- cgit v1.2.3 From b63da93de89bcb009de89d15d4d01e75a2fc37f9 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:31 +0100 Subject: mlxsw: core: Expose generic macros for rx trap In Spectrum, there is a macro to arrange the traps list. This macro is useful for everyone who is using rx traps. Create a similar macro in core.h for creating the generic listener struct for rx traps. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 66d97c495309..5f6fed12ba27 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -101,6 +101,20 @@ struct mlxsw_listener { bool is_event; }; +#define MLXSW_RXL(_func, _trap_id, _action, _unreg_action) \ + { \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + .u.rx_listener = \ + { \ + .func = _func, \ + .local_port = MLXSW_PORT_DONT_CARE, \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + }, \ + .action = MLXSW_REG_HPKT_ACTION_##_action, \ + .unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action, \ + .is_event = false, \ + } + int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, const struct mlxsw_rx_listener *rxl, void *priv); -- cgit v1.2.3 From 14eeda99c4a6b6bf92261f980bcd95f345c76b64 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:32 +0100 Subject: mlxsw: spectrum: Use generic listener struct for rx traps Replace the old rx listener struct definitions by the generic ones. Use the new generic registering / unregistering functions for them. Add some macros to organize the trap list. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 95 +++++++++++--------------- 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 2f06de336b38..efa99af15406 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2744,8 +2744,8 @@ static void mlxsw_sp_event_unregister(struct mlxsw_sp *mlxsw_sp, mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp); } -static void mlxsw_sp_rx_listener_func(struct sk_buff *skb, u8 local_port, - void *priv) +static void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb, + u8 local_port, void *priv) { struct mlxsw_sp *mlxsw_sp = priv; struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; @@ -2773,44 +2773,43 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, void *priv) { skb->offload_fwd_mark = 1; - return mlxsw_sp_rx_listener_func(skb, local_port, priv); + return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv); } -#define MLXSW_SP_RXL(_func, _trap_id, _action) \ - { \ - .func = _func, \ - .local_port = MLXSW_PORT_DONT_CARE, \ - .trap_id = MLXSW_TRAP_ID_##_trap_id, \ - .action = MLXSW_REG_HPKT_ACTION_##_action, \ - } +#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action) \ + MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ + DISCARD) + +#define MLXSW_SP_RXL_MARK(_trap_id, _action) \ + MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \ + DISCARD) -static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = { +static const struct mlxsw_listener mlxsw_sp_rx_listener[] = { /* L2 traps */ - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, STP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LACP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LLDP, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, DHCP, MIRROR_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, IGMP_QUERY, MIRROR_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V1_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_LEAVE, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V3_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPBC, MIRROR_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPUC, MIRROR_TO_CPU), + MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU), + MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU), + MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU), + MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU), + MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU), + MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU), /* L3 traps */ - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MTUERROR, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, TTLERROR, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LBERROR, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, OSPF, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IP2ME, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RTR_INGRESS0, TRAP_TO_CPU), - MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, HOST_MISS_IPV4, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU), + MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU), }; static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) { char htgt_pl[MLXSW_REG_HTGT_LEN]; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; int i; int err; @@ -2825,50 +2824,32 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) return err; for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { - err = mlxsw_core_rx_listener_register(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], - mlxsw_sp); + err = mlxsw_core_trap_register(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); if (err) goto err_rx_listener_register; - mlxsw_reg_hpkt_pack(hpkt_pl, mlxsw_sp_rx_listener[i].action, - mlxsw_sp_rx_listener[i].trap_id); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); - if (err) - goto err_rx_trap_set; } return 0; -err_rx_trap_set: - mlxsw_core_rx_listener_unregister(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], - mlxsw_sp); err_rx_listener_register: for (i--; i >= 0; i--) { - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, - mlxsw_sp_rx_listener[i].trap_id); - mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); - - mlxsw_core_rx_listener_unregister(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], - mlxsw_sp); + mlxsw_core_trap_unregister(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); } return err; } static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) { - char hpkt_pl[MLXSW_REG_HPKT_LEN]; int i; for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, - mlxsw_sp_rx_listener[i].trap_id); - mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); - - mlxsw_core_rx_listener_unregister(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], - mlxsw_sp); + mlxsw_core_trap_unregister(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); } } -- cgit v1.2.3 From 2332d8c7df9531a0b73ff3a7d2d65b0c99122c21 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:33 +0100 Subject: mlxsw: switchx2: Use generic listener struct for rx traps Reorganize the traps to use the new generic listener struct and functions. Use macros to shorten the traps list. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 127 ++++++------------------- 1 file changed, 27 insertions(+), 100 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 60f19fb68e5f..df6afdd573f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1494,84 +1494,29 @@ err_port_module_info_get: return err; } -static const struct mlxsw_rx_listener mlxsw_sx_rx_listener[] = { - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_FDB_MC, - }, - /* Traps for specific L2 packet types, not trapped as FDB MC */ - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_STP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_LACP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_EAPOL, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_LLDP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_MMRP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_MVRP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_RPVST, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_DHCP, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_IGMP_QUERY, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE, - }, - { - .func = mlxsw_sx_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT, - }, +#define MLXSW_SX_RXL(_trap_id) \ + MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, FORWARD) + +static const struct mlxsw_listener mlxsw_sx_rx_listener[] = { + MLXSW_SX_RXL(FDB_MC), + MLXSW_SX_RXL(STP), + MLXSW_SX_RXL(LACP), + MLXSW_SX_RXL(EAPOL), + MLXSW_SX_RXL(LLDP), + MLXSW_SX_RXL(MMRP), + MLXSW_SX_RXL(MVRP), + MLXSW_SX_RXL(RPVST), + MLXSW_SX_RXL(DHCP), + MLXSW_SX_RXL(IGMP_QUERY), + MLXSW_SX_RXL(IGMP_V1_REPORT), + MLXSW_SX_RXL(IGMP_V2_REPORT), + MLXSW_SX_RXL(IGMP_V2_LEAVE), + MLXSW_SX_RXL(IGMP_V3_REPORT), }; static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) { char htgt_pl[MLXSW_REG_HTGT_LEN]; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; int i; int err; @@ -1586,50 +1531,32 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) return err; for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { - err = mlxsw_core_rx_listener_register(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], - mlxsw_sx); + err = mlxsw_core_trap_register(mlxsw_sx->core, + &mlxsw_sx_rx_listener[i], + mlxsw_sx); if (err) goto err_rx_listener_register; - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, - mlxsw_sx_rx_listener[i].trap_id); - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); - if (err) - goto err_rx_trap_set; } return 0; -err_rx_trap_set: - mlxsw_core_rx_listener_unregister(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], - mlxsw_sx); err_rx_listener_register: for (i--; i >= 0; i--) { - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, - mlxsw_sx_rx_listener[i].trap_id); - mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); - - mlxsw_core_rx_listener_unregister(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], - mlxsw_sx); + mlxsw_core_trap_unregister(mlxsw_sx->core, + &mlxsw_sx_rx_listener[i], + mlxsw_sx); } return err; } static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx) { - char hpkt_pl[MLXSW_REG_HPKT_LEN]; int i; for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, - mlxsw_sx_rx_listener[i].trap_id); - mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); - - mlxsw_core_rx_listener_unregister(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], - mlxsw_sx); + mlxsw_core_trap_unregister(mlxsw_sx->core, + &mlxsw_sx_rx_listener[i], + mlxsw_sx); } } -- cgit v1.2.3 From fb9012d93f3d8abc316ec06105a7e781c37e2696 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:34 +0100 Subject: mlxsw: core: Introduce generic macro for event Create a macro for creating the generic listener struct for events, similar to the one for rx traps. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 5f6fed12ba27..852218e44b23 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -115,6 +115,18 @@ struct mlxsw_listener { .is_event = false, \ } +#define MLXSW_EVENTL(_func, _trap_id) \ + { \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + .u.event_listener = \ + { \ + .func = _func, \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + }, \ + .action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \ + .is_event = true, \ + } + int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, const struct mlxsw_rx_listener *rxl, void *priv); -- cgit v1.2.3 From 4544913ed79275ce6a1cd98baa7edbf018c5242a Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:35 +0100 Subject: mlxsw: spectrum: Use generic listener struct for events Change the events to use the generic listener struct. Merge the event list into the trap list, so the same functions will handle both. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 77 ++++---------------------- 1 file changed, 12 insertions(+), 65 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index efa99af15406..d758ce6228f4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2698,52 +2698,6 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, } } -static struct mlxsw_event_listener mlxsw_sp_pude_event = { - .func = mlxsw_sp_pude_event_func, - .trap_id = MLXSW_TRAP_ID_PUDE, -}; - -static int mlxsw_sp_event_register(struct mlxsw_sp *mlxsw_sp, - enum mlxsw_event_trap_id trap_id) -{ - struct mlxsw_event_listener *el; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; - int err; - - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sp_pude_event; - break; - } - err = mlxsw_core_event_listener_register(mlxsw_sp->core, el, mlxsw_sp); - if (err) - return err; - - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); - if (err) - goto err_event_trap_set; - - return 0; - -err_event_trap_set: - mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp); - return err; -} - -static void mlxsw_sp_event_unregister(struct mlxsw_sp *mlxsw_sp, - enum mlxsw_event_trap_id trap_id) -{ - struct mlxsw_event_listener *el; - - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sp_pude_event; - break; - } - mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp); -} - static void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb, u8 local_port, void *priv) { @@ -2784,7 +2738,9 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \ DISCARD) -static const struct mlxsw_listener mlxsw_sp_rx_listener[] = { +static const struct mlxsw_listener mlxsw_sp_listener[] = { + /* Events */ + MLXSW_EVENTL(mlxsw_sp_pude_event_func, PUDE), /* L2 traps */ MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU), MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU), @@ -2823,20 +2779,20 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) if (err) return err; - for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) { err = mlxsw_core_trap_register(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], + &mlxsw_sp_listener[i], mlxsw_sp); if (err) - goto err_rx_listener_register; + goto err_listener_register; } return 0; -err_rx_listener_register: +err_listener_register: for (i--; i >= 0; i--) { mlxsw_core_trap_unregister(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], + &mlxsw_sp_listener[i], mlxsw_sp); } return err; @@ -2846,9 +2802,9 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) { int i; - for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) { mlxsw_core_trap_unregister(mlxsw_sp->core, - &mlxsw_sp_rx_listener[i], + &mlxsw_sp_listener[i], mlxsw_sp); } } @@ -2952,16 +2908,10 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, return err; } - err = mlxsw_sp_event_register(mlxsw_sp, MLXSW_TRAP_ID_PUDE); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to register for PUDE events\n"); - return err; - } - err = mlxsw_sp_traps_init(mlxsw_sp); if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps for RX\n"); - goto err_rx_listener_register; + dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n"); + return err; } err = mlxsw_sp_flood_init(mlxsw_sp); @@ -3021,8 +2971,6 @@ err_lag_init: err_buffers_init: err_flood_init: mlxsw_sp_traps_fini(mlxsw_sp); -err_rx_listener_register: - mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE); return err; } @@ -3037,7 +2985,6 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) mlxsw_sp_lag_fini(mlxsw_sp); mlxsw_sp_buffers_fini(mlxsw_sp); mlxsw_sp_traps_fini(mlxsw_sp); - mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE); WARN_ON(!list_empty(&mlxsw_sp->vfids.list)); WARN_ON(!list_empty(&mlxsw_sp->fids)); } -- cgit v1.2.3 From 6bf08b53ed84a256f5e789d278e4852006f8e387 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:36 +0100 Subject: mlxsw: switchx2: Use generic listener struct for events Change the events to use the generic listener struct. Merge the event list into the trap list, so the same functions will handle both. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 78 ++++---------------------- 1 file changed, 12 insertions(+), 66 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index df6afdd573f1..675ce122768b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1396,52 +1396,6 @@ static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg, mlxsw_sx_pude_ib_event_func(mlxsw_sx_port, status); } -static struct mlxsw_event_listener mlxsw_sx_pude_event = { - .func = mlxsw_sx_pude_event_func, - .trap_id = MLXSW_TRAP_ID_PUDE, -}; - -static int mlxsw_sx_event_register(struct mlxsw_sx *mlxsw_sx, - enum mlxsw_event_trap_id trap_id) -{ - struct mlxsw_event_listener *el; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; - int err; - - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sx_pude_event; - break; - } - err = mlxsw_core_event_listener_register(mlxsw_sx->core, el, mlxsw_sx); - if (err) - return err; - - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); - if (err) - goto err_event_trap_set; - - return 0; - -err_event_trap_set: - mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx); - return err; -} - -static void mlxsw_sx_event_unregister(struct mlxsw_sx *mlxsw_sx, - enum mlxsw_event_trap_id trap_id) -{ - struct mlxsw_event_listener *el; - - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sx_pude_event; - break; - } - mlxsw_core_event_listener_unregister(mlxsw_sx->core, el, mlxsw_sx); -} - static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port, void *priv) { @@ -1497,7 +1451,8 @@ err_port_module_info_get: #define MLXSW_SX_RXL(_trap_id) \ MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, FORWARD) -static const struct mlxsw_listener mlxsw_sx_rx_listener[] = { +static const struct mlxsw_listener mlxsw_sx_listener[] = { + MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE), MLXSW_SX_RXL(FDB_MC), MLXSW_SX_RXL(STP), MLXSW_SX_RXL(LACP), @@ -1530,20 +1485,20 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) if (err) return err; - for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { + for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) { err = mlxsw_core_trap_register(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], + &mlxsw_sx_listener[i], mlxsw_sx); if (err) - goto err_rx_listener_register; + goto err_listener_register; } return 0; -err_rx_listener_register: +err_listener_register: for (i--; i >= 0; i--) { mlxsw_core_trap_unregister(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], + &mlxsw_sx_listener[i], mlxsw_sx); } return err; @@ -1553,9 +1508,9 @@ static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx) { int i; - for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { + for (i = 0; i < ARRAY_SIZE(mlxsw_sx_listener); i++) { mlxsw_core_trap_unregister(mlxsw_sx->core, - &mlxsw_sx_rx_listener[i], + &mlxsw_sx_listener[i], mlxsw_sx); } } @@ -1649,16 +1604,10 @@ static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, return err; } - err = mlxsw_sx_event_register(mlxsw_sx, MLXSW_TRAP_ID_PUDE); - if (err) { - dev_err(mlxsw_sx->bus_info->dev, "Failed to register for PUDE events\n"); - goto err_event_register; - } - err = mlxsw_sx_traps_init(mlxsw_sx); if (err) { - dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps for RX\n"); - goto err_rx_listener_register; + dev_err(mlxsw_sx->bus_info->dev, "Failed to set traps\n"); + goto err_listener_register; } err = mlxsw_sx_flood_init(mlxsw_sx); @@ -1671,9 +1620,7 @@ static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, err_flood_init: mlxsw_sx_traps_fini(mlxsw_sx); -err_rx_listener_register: - mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE); -err_event_register: +err_listener_register: mlxsw_sx_ports_remove(mlxsw_sx); return err; } @@ -1683,7 +1630,6 @@ static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core) struct mlxsw_sx *mlxsw_sx = mlxsw_core_driver_priv(mlxsw_core); mlxsw_sx_traps_fini(mlxsw_sx); - mlxsw_sx_event_unregister(mlxsw_sx, MLXSW_TRAP_ID_PUDE); mlxsw_sx_ports_remove(mlxsw_sx); } -- cgit v1.2.3 From 85d5c9cd90d2b271d8498ee6362ad57e00a2af16 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:37 +0100 Subject: mlxsw: switchib: Use generic listener struct for events Change the event handling in Switchib to be comptible with Spectrum and Switchx2. Use the generic listener struct for the events. Init and fini them by loop (and not by calling each event by its name). Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchib.c | 62 +++++++++++--------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c index 1552594b2d1f..847cbbfe854c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -408,51 +408,43 @@ static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg, mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status); } -static struct mlxsw_event_listener mlxsw_sib_pude_event = { - .func = mlxsw_sib_pude_event_func, - .trap_id = MLXSW_TRAP_ID_PUDE, +static const struct mlxsw_listener mlxsw_sib_listener[] = { + MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE), }; -static int mlxsw_sib_event_register(struct mlxsw_sib *mlxsw_sib, - enum mlxsw_event_trap_id trap_id) +static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib) { - struct mlxsw_event_listener *el; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int i; int err; - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sib_pude_event; - break; + for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) { + err = mlxsw_core_trap_register(mlxsw_sib->core, + &mlxsw_sib_listener[i], + mlxsw_sib); + if (err) + goto err_rx_listener_register; } - err = mlxsw_core_event_listener_register(mlxsw_sib->core, el, - mlxsw_sib); - if (err) - return err; - - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); - err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(hpkt), hpkt_pl); - if (err) - goto err_event_trap_set; return 0; -err_event_trap_set: - mlxsw_core_event_listener_unregister(mlxsw_sib->core, el, mlxsw_sib); +err_rx_listener_register: + for (i--; i >= 0; i--) { + mlxsw_core_trap_unregister(mlxsw_sib->core, + &mlxsw_sib_listener[i], + mlxsw_sib); + } + return err; } -static void mlxsw_sib_event_unregister(struct mlxsw_sib *mlxsw_sib, - enum mlxsw_event_trap_id trap_id) +static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib) { - struct mlxsw_event_listener *el; + int i; - switch (trap_id) { - case MLXSW_TRAP_ID_PUDE: - el = &mlxsw_sib_pude_event; - break; + for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) { + mlxsw_core_trap_unregister(mlxsw_sib->core, + &mlxsw_sib_listener[i], mlxsw_sib); } - mlxsw_core_event_listener_unregister(mlxsw_sib->core, el, mlxsw_sib); } static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core, @@ -470,15 +462,15 @@ static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core, return err; } - err = mlxsw_sib_event_register(mlxsw_sib, MLXSW_TRAP_ID_PUDE); + err = mlxsw_sib_taps_init(mlxsw_sib); if (err) { - dev_err(mlxsw_sib->bus_info->dev, "Failed to register for PUDE events\n"); - goto err_event_register; + dev_err(mlxsw_sib->bus_info->dev, "Failed to set traps\n"); + goto err_traps_init_err; } return 0; -err_event_register: +err_traps_init_err: mlxsw_sib_ports_remove(mlxsw_sib); return err; } @@ -487,7 +479,7 @@ static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core) { struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core); - mlxsw_sib_event_unregister(mlxsw_sib, MLXSW_TRAP_ID_PUDE); + mlxsw_sib_traps_fini(mlxsw_sib); mlxsw_sib_ports_remove(mlxsw_sib); } -- cgit v1.2.3 From d570b7ee4e47721099fc6309fd3ff9b637261357 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:38 +0100 Subject: mlxsw: Change trap set function Change trap setting function so instead of determining the trap group by trap id, it gets it as a parameter (so later we can have different trap groups for Spectrum and Switchx2). Add "is_ctrl" parameter to the trap setting function. It control whether the trapped packets wait in a designated control buffer or in their default one. This parameter is ignored by Switchx2 and Switchib. Add these parameters to the traps array in Spectrum, Switchx2 and Switchib. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 14 +++++--- drivers/net/ethernet/mellanox/mlxsw/core.h | 8 ++++- drivers/net/ethernet/mellanox/mlxsw/reg.h | 20 ++++------- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 46 +++++++++++++------------- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 5 +-- 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index a8cff78c7029..d3b82d6e35d1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -590,7 +590,8 @@ static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core) return err; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, - MLXSW_TRAP_ID_ETHEMAD); + MLXSW_TRAP_ID_ETHEMAD, + MLXSW_REG_HTGT_TRAP_GROUP_EMAD, false); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); } @@ -643,7 +644,8 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) mlxsw_core->emad.use_emad = false; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, - MLXSW_TRAP_ID_ETHEMAD); + MLXSW_TRAP_ID_ETHEMAD, + MLXSW_REG_HTGT_TRAP_GROUP_EMAD, false); mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); mlxsw_core_rx_listener_unregister(mlxsw_core, @@ -1430,8 +1432,9 @@ int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core, if (err) return err; - mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id); - err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); + mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id, + listener->trap_group, listener->is_ctrl); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); if (err) goto err_trap_set; @@ -1451,7 +1454,8 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core, if (!listener->is_event) { mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action, - listener->trap_id); + listener->trap_id, listener->trap_group, + listener->is_ctrl); mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 852218e44b23..b5b5b367d25c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -98,10 +98,12 @@ struct mlxsw_listener { } u; enum mlxsw_reg_hpkt_action action; enum mlxsw_reg_hpkt_action unreg_action; + u8 trap_group; + bool is_ctrl; /* should go via control buffer or not */ bool is_event; }; -#define MLXSW_RXL(_func, _trap_id, _action, _unreg_action) \ +#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _unreg_action) \ { \ .trap_id = MLXSW_TRAP_ID_##_trap_id, \ .u.rx_listener = \ @@ -112,6 +114,8 @@ struct mlxsw_listener { }, \ .action = MLXSW_REG_HPKT_ACTION_##_action, \ .unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action, \ + .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX, \ + .is_ctrl = _is_ctrl, \ .is_event = false, \ } @@ -124,6 +128,8 @@ struct mlxsw_listener { .trap_id = MLXSW_TRAP_ID_##_trap_id, \ }, \ .action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \ + .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD, \ + .is_ctrl = false, \ .is_event = true, \ } diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2618e9cf3aab..68a0e63954b6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3214,6 +3214,7 @@ enum { /* reg_hpkt_ctrl * Configure dedicated buffer resources for control packets. + * Ignored by SwitchX-2. * 0 - Keep factory defaults. * 1 - Do not use control buffer for this trap ID. * 2 - Use control buffer for this trap ID. @@ -3221,25 +3222,18 @@ enum { */ MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2); -static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id) +static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id, + enum mlxsw_reg_htgt_trap_group trap_group, + bool is_ctrl) { - enum mlxsw_reg_htgt_trap_group trap_group; - MLXSW_REG_ZERO(hpkt, payload); mlxsw_reg_hpkt_ack_set(payload, MLXSW_REG_HPKT_ACK_NOT_REQUIRED); mlxsw_reg_hpkt_action_set(payload, action); - switch (trap_id) { - case MLXSW_TRAP_ID_ETHEMAD: - case MLXSW_TRAP_ID_PUDE: - trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD; - break; - default: - trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX; - break; - } mlxsw_reg_hpkt_trap_group_set(payload, trap_group); mlxsw_reg_hpkt_trap_id_set(payload, trap_id); - mlxsw_reg_hpkt_ctrl_set(payload, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT); + mlxsw_reg_hpkt_ctrl_set(payload, is_ctrl ? + MLXSW_REG_HPKT_CTRL_PACKET_USE_BUFFER : + MLXSW_REG_HPKT_CTRL_PACKET_NO_BUFFER); } /* RGCR - Router General Configuration Register diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index d758ce6228f4..3582e3f2901b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2730,37 +2730,37 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv); } -#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action) \ - MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ - DISCARD) +#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _is_ctrl) \ + MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ + _is_ctrl, DISCARD) -#define MLXSW_SP_RXL_MARK(_trap_id, _action) \ +#define MLXSW_SP_RXL_MARK(_trap_id, _action, _is_ctrl) \ MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \ - DISCARD) + _is_ctrl, DISCARD) static const struct mlxsw_listener mlxsw_sp_listener[] = { /* Events */ MLXSW_EVENTL(mlxsw_sp_pude_event_func, PUDE), /* L2 traps */ - MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU), - MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU), - MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU), - MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU), - MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU), - MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU), + MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, true), + MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, true), + MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, true), + MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, false), + MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, false), + MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, false), + MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, false), /* L3 traps */ - MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU), - MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU), - MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU), + MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, false), + MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, false), }; static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 675ce122768b..a15875675c48 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1448,8 +1448,9 @@ err_port_module_info_get: return err; } -#define MLXSW_SX_RXL(_trap_id) \ - MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, FORWARD) +#define MLXSW_SX_RXL(_trap_id) \ + MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \ + false, FORWARD) static const struct mlxsw_listener mlxsw_sx_listener[] = { MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE), -- cgit v1.2.3 From 0fb78a4e9c8563e1f95358794bd168c5c1e72009 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:39 +0100 Subject: mlxsw: Add option to choose trap group Currently, we set the trap group to pre-determined option, based on whether it is an rx or event trap. This commit adds a possibility to chose the trap group, so it can be set to different values in the following patches. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 29 +++++++++++++------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 8 +++---- drivers/net/ethernet/mellanox/mlxsw/switchib.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 4 ++-- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index b5b5b367d25c..d663b8e98c91 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -103,7 +103,8 @@ struct mlxsw_listener { bool is_event; }; -#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _unreg_action) \ +#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _trap_group, \ + _unreg_action) \ { \ .trap_id = MLXSW_TRAP_ID_##_trap_id, \ .u.rx_listener = \ @@ -114,23 +115,23 @@ struct mlxsw_listener { }, \ .action = MLXSW_REG_HPKT_ACTION_##_action, \ .unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action, \ - .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX, \ + .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \ .is_ctrl = _is_ctrl, \ .is_event = false, \ } -#define MLXSW_EVENTL(_func, _trap_id) \ - { \ - .trap_id = MLXSW_TRAP_ID_##_trap_id, \ - .u.event_listener = \ - { \ - .func = _func, \ - .trap_id = MLXSW_TRAP_ID_##_trap_id, \ - }, \ - .action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \ - .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD, \ - .is_ctrl = false, \ - .is_event = true, \ +#define MLXSW_EVENTL(_func, _trap_id, _trap_group) \ + { \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + .u.event_listener = \ + { \ + .func = _func, \ + .trap_id = MLXSW_TRAP_ID_##_trap_id, \ + }, \ + .action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \ + .trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \ + .is_ctrl = false, \ + .is_event = true, \ } int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 3582e3f2901b..44243a4294c9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2731,16 +2731,16 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, } #define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _is_ctrl) \ - MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ - _is_ctrl, DISCARD) + MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ + _is_ctrl, RX, DISCARD) #define MLXSW_SP_RXL_MARK(_trap_id, _action, _is_ctrl) \ MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \ - _is_ctrl, DISCARD) + _is_ctrl, RX, DISCARD) static const struct mlxsw_listener mlxsw_sp_listener[] = { /* Events */ - MLXSW_EVENTL(mlxsw_sp_pude_event_func, PUDE), + MLXSW_EVENTL(mlxsw_sp_pude_event_func, PUDE, EMAD), /* L2 traps */ MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, true), MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, true), diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c index 847cbbfe854c..b798711a9c78 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -409,7 +409,7 @@ static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg, } static const struct mlxsw_listener mlxsw_sib_listener[] = { - MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE), + MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE, EMAD), }; static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib) diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index a15875675c48..1bcb391a35f8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1450,10 +1450,10 @@ err_port_module_info_get: #define MLXSW_SX_RXL(_trap_id) \ MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \ - false, FORWARD) + false, RX, FORWARD) static const struct mlxsw_listener mlxsw_sx_listener[] = { - MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE), + MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE, EMAD), MLXSW_SX_RXL(FDB_MC), MLXSW_SX_RXL(STP), MLXSW_SX_RXL(LACP), -- cgit v1.2.3 From 9d87fceac6e1a7885e3f7766de3ec2ab7d152aa2 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:40 +0100 Subject: mlxsw: core: Change emad trap group settings Currently, the emad trap init was done in the core. In the future we will want to add some changes to the traps groups, according to device type. This commit create a driver function to create the trap group for the emad, so later it can be changed by devices. It also changes the emad registration to use the new generic functions. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 49 ++++++-------------------- drivers/net/ethernet/mellanox/mlxsw/core.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 9 +++++ drivers/net/ethernet/mellanox/mlxsw/switchib.c | 10 ++++++ drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 9 +++++ 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index d3b82d6e35d1..b21f88c66d1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -572,28 +572,9 @@ free_skb: dev_kfree_skb(skb); } -static const struct mlxsw_rx_listener mlxsw_emad_rx_listener = { - .func = mlxsw_emad_rx_listener_func, - .local_port = MLXSW_PORT_DONT_CARE, - .trap_id = MLXSW_TRAP_ID_ETHEMAD, -}; - -static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core) -{ - char htgt_pl[MLXSW_REG_HTGT_LEN]; - char hpkt_pl[MLXSW_REG_HPKT_LEN]; - int err; - - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); - err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); - if (err) - return err; - - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, - MLXSW_TRAP_ID_ETHEMAD, - MLXSW_REG_HTGT_TRAP_GROUP_EMAD, false); - return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); -} +static const struct mlxsw_listener mlxsw_emad_rx_listener = + MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false, + EMAD, DISCARD); static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) { @@ -614,43 +595,33 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) INIT_LIST_HEAD(&mlxsw_core->emad.trans_list); spin_lock_init(&mlxsw_core->emad.trans_list_lock); - err = mlxsw_core_rx_listener_register(mlxsw_core, - &mlxsw_emad_rx_listener, - mlxsw_core); + err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener, + mlxsw_core); if (err) return err; - err = mlxsw_emad_traps_set(mlxsw_core); + err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core); if (err) goto err_emad_trap_set; - mlxsw_core->emad.use_emad = true; return 0; err_emad_trap_set: - mlxsw_core_rx_listener_unregister(mlxsw_core, - &mlxsw_emad_rx_listener, - mlxsw_core); + mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, + mlxsw_core); return err; } static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) { - char hpkt_pl[MLXSW_REG_HPKT_LEN]; if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) return; mlxsw_core->emad.use_emad = false; - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, - MLXSW_TRAP_ID_ETHEMAD, - MLXSW_REG_HTGT_TRAP_GROUP_EMAD, false); - mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); - - mlxsw_core_rx_listener_unregister(mlxsw_core, - &mlxsw_emad_rx_listener, - mlxsw_core); + mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, + mlxsw_core); } static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index d663b8e98c91..e856b49b83de 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -265,6 +265,7 @@ struct mlxsw_driver { int (*init)(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info); void (*fini)(struct mlxsw_core *mlxsw_core); + int (*basic_trap_groups_set)(struct mlxsw_core *mlxsw_core); int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port, enum devlink_port_type new_type); int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 44243a4294c9..79c0a01721a7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2890,6 +2890,14 @@ static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->lags); } +static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) +{ + char htgt_pl[MLXSW_REG_HTGT_LEN]; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); +} + static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info) { @@ -3026,6 +3034,7 @@ static struct mlxsw_driver mlxsw_sp_driver = { .priv_size = sizeof(struct mlxsw_sp), .init = mlxsw_sp_init, .fini = mlxsw_sp_fini, + .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, .port_split = mlxsw_sp_port_split, .port_unsplit = mlxsw_sp_port_unsplit, .sb_pool_get = mlxsw_sp_sb_pool_get, diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c index b798711a9c78..9a5f829239cb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -447,6 +447,14 @@ static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib) } } +static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) +{ + char htgt_pl[MLXSW_REG_HTGT_LEN]; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); +} + static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info) { @@ -504,6 +512,7 @@ static struct mlxsw_driver mlxsw_sib_driver = { .priv_size = sizeof(struct mlxsw_sib), .init = mlxsw_sib_init, .fini = mlxsw_sib_fini, + .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set, .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sib_config_profile, @@ -514,6 +523,7 @@ static struct mlxsw_driver mlxsw_sib2_driver = { .priv_size = sizeof(struct mlxsw_sib), .init = mlxsw_sib_init, .fini = mlxsw_sib_fini, + .basic_trap_groups_set = mlxsw_sib_basic_trap_groups_set, .txhdr_construct = mlxsw_sib_tx_v1_hdr_construct, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sib_config_profile, diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 1bcb391a35f8..8caa9625ca75 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1584,6 +1584,14 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx) return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sgcr), sgcr_pl); } +static int mlxsw_sx_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) +{ + char htgt_pl[MLXSW_REG_HTGT_LEN]; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); +} + static int mlxsw_sx_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info) { @@ -1674,6 +1682,7 @@ static struct mlxsw_driver mlxsw_sx_driver = { .priv_size = sizeof(struct mlxsw_sx), .init = mlxsw_sx_init, .fini = mlxsw_sx_fini, + .basic_trap_groups_set = mlxsw_sx_basic_trap_groups_set, .txhdr_construct = mlxsw_sx_txhdr_construct, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sx_config_profile, -- cgit v1.2.3 From 23432cb86a53b03da6dc827ee373d113ee1cc2f8 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:41 +0100 Subject: mlxsw: resources: Add max trap groups resource Add the max number of trap groups to resource query. Signed-off-by: Nogah Frankel Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index a031e45c8b06..07b09f8caabd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -42,6 +42,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_KVD_SIZE, MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE, MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE, + MLXSW_RES_ID_MAX_TRAP_GROUPS, MLXSW_RES_ID_MAX_SPAN, MLXSW_RES_ID_MAX_SYSTEM_PORT, MLXSW_RES_ID_MAX_LAG, @@ -63,6 +64,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_KVD_SIZE] = 0x1001, [MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002, [MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003, + [MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201, [MLXSW_RES_ID_MAX_SPAN] = 0x2420, [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502, [MLXSW_RES_ID_MAX_LAG] = 0x2520, -- cgit v1.2.3 From 579c82e4c5a8d6653533b2ffd8a2b519928050cb Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:42 +0100 Subject: mlxsw: Change trap groups setting Trap groups have many options which we currently set to default values. In the next patches we will use many of them with non-default values. Some of these options have no default value, so this patch sets them as params for the trap group set function. Others almost always use the same values, so the set function will use this default values. In the rare cases when they will need to be with other values, these values can be set directly (using the macros for fields in registers). Parameters without default value: TC - the traffic class for packets that hit this trap group. (old default is the max tc) priority - if one packet hits multiple trap groups, the group with the higher priority will "catch" it. (old default is 0) policer - limit rate policer (old default is disabled) Default parameters: swid - switch id, relevant for the emad trap only, ignored on Spectrum. (new default is 0) rdq - CPU receive descriptor queue (new default is identical to trap group id) Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 53 +++++++++++++------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 47 ++++++++++++++++++----- drivers/net/ethernet/mellanox/mlxsw/switchib.c | 8 +++- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 24 ++++++++++-- 4 files changed, 92 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 68a0e63954b6..2116f8f0802f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3057,6 +3057,8 @@ enum { */ MLXSW_ITEM32(reg, htgt, pide, 0x04, 15, 1); +#define MLXSW_REG_HTGT_INVALID_POLICER 0xff + /* reg_htgt_pid * Policer ID for the trap group. * Access: RW @@ -3082,6 +3084,8 @@ MLXSW_ITEM32(reg, htgt, mirror_action, 0x08, 8, 2); */ MLXSW_ITEM32(reg, htgt, mirroring_agent, 0x08, 0, 3); +#define MLXSW_REG_HTGT_DEFAULT_PRIORITY 0 + /* reg_htgt_priority * Trap group priority. * In case a packet matches multiple classification rules, the packet will @@ -3095,52 +3099,47 @@ MLXSW_ITEM32(reg, htgt, mirroring_agent, 0x08, 0, 3); */ MLXSW_ITEM32(reg, htgt, priority, 0x0C, 0, 4); +#define MLXSW_REG_HTGT_DEFAULT_TC 7 + /* reg_htgt_local_path_cpu_tclass * CPU ingress traffic class for the trap group. * Access: RW */ MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6); -#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD 0x15 -#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX 0x14 -#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL 0x13 - +enum mlxsw_reg_htgt_local_path_rdq { + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL = 0x13, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX = 0x14, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD = 0x15, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD = 0x15, +}; /* reg_htgt_local_path_rdq * Receive descriptor queue (RDQ) to use for the trap group. * Access: RW */ MLXSW_ITEM32(reg, htgt, local_path_rdq, 0x10, 0, 6); -static inline void mlxsw_reg_htgt_pack(char *payload, - enum mlxsw_reg_htgt_trap_group group) +static inline void mlxsw_reg_htgt_pack(char *payload, u8 group, u8 policer_id, + u8 priority, u8 tc) { - u8 swid, rdq; - MLXSW_REG_ZERO(htgt, payload); - switch (group) { - case MLXSW_REG_HTGT_TRAP_GROUP_EMAD: - swid = MLXSW_PORT_SWID_ALL_SWIDS; - rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD; - break; - case MLXSW_REG_HTGT_TRAP_GROUP_RX: - swid = 0; - rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX; - break; - case MLXSW_REG_HTGT_TRAP_GROUP_CTRL: - swid = 0; - rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL; - break; + + if (policer_id == MLXSW_REG_HTGT_INVALID_POLICER) { + mlxsw_reg_htgt_pide_set(payload, + MLXSW_REG_HTGT_POLICER_DISABLE); + } else { + mlxsw_reg_htgt_pide_set(payload, + MLXSW_REG_HTGT_POLICER_ENABLE); + mlxsw_reg_htgt_pid_set(payload, policer_id); } - mlxsw_reg_htgt_swid_set(payload, swid); + mlxsw_reg_htgt_type_set(payload, MLXSW_REG_HTGT_PATH_TYPE_LOCAL); mlxsw_reg_htgt_trap_group_set(payload, group); - mlxsw_reg_htgt_pide_set(payload, MLXSW_REG_HTGT_POLICER_DISABLE); - mlxsw_reg_htgt_pid_set(payload, 0); mlxsw_reg_htgt_mirror_action_set(payload, MLXSW_REG_HTGT_TRAP_TO_CPU); mlxsw_reg_htgt_mirroring_agent_set(payload, 0); - mlxsw_reg_htgt_priority_set(payload, 0); - mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, 7); - mlxsw_reg_htgt_local_path_rdq_set(payload, rdq); + mlxsw_reg_htgt_priority_set(payload, priority); + mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, tc); + mlxsw_reg_htgt_local_path_rdq_set(payload, group); } /* HPKT - Host Packet Trap diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 79c0a01721a7..75ba22ab7c16 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2763,19 +2763,45 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, false), }; -static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) +static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; + int max_trap_groups; + u8 priority, tc; + int i, err; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS)) + return -EIO; + + max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS); + + for (i = 0; i < max_trap_groups; i++) { + switch (i) { + case MLXSW_REG_HTGT_TRAP_GROUP_EMAD: + case MLXSW_REG_HTGT_TRAP_GROUP_RX: + case MLXSW_REG_HTGT_TRAP_GROUP_CTRL: + priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY; + tc = MLXSW_REG_HTGT_DEFAULT_TC; + break; + default: + continue; + } + mlxsw_reg_htgt_pack(htgt_pl, i, MLXSW_REG_HTGT_INVALID_POLICER, + priority, tc); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + } + + return 0; +} + +static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) +{ int i; int err; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl); - if (err) - return err; - - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl); + err = mlxsw_sp_trap_groups_set(mlxsw_sp->core); if (err) return err; @@ -2894,7 +2920,10 @@ static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchib.c b/drivers/net/ethernet/mellanox/mlxsw/switchib.c index 9a5f829239cb..74341fe0eb25 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchib.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchib.c @@ -451,7 +451,13 @@ static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS); + mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 8caa9625ca75..4cdc02cf152e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1476,12 +1476,24 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) int i; int err; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX); + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX); + err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl); if (err) return err; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL); + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL); + err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl); if (err) return err; @@ -1588,7 +1600,13 @@ static int mlxsw_sx_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD); + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS); + mlxsw_reg_htgt_local_path_rdq_set(htgt_pl, + MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); } -- cgit v1.2.3 From 616d8040e56fa5cd276c988e351cc928002c3502 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:43 +0100 Subject: mlxsw: spectrum: Add BGP trap Add a trap for BGP protocol that was previously trapped by the generic trap for IP2ME. This trap will allow us to have better control (over priority and rate) of the traffic. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 + drivers/net/ethernet/mellanox/mlxsw/trap.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 75ba22ab7c16..42ac968e49a2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2761,6 +2761,7 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, false), MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, false), MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, false), + MLXSW_SP_RXL_MARK(BGP_IPV4, TRAP_TO_CPU, false), }; static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index ed8e30186400..7ab275deacac 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -62,6 +62,7 @@ enum { MLXSW_TRAP_ID_OSPF = 0x55, MLXSW_TRAP_ID_IP2ME = 0x5F, MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70, + MLXSW_TRAP_ID_BGP_IPV4 = 0x88, MLXSW_TRAP_ID_HOST_MISS_IPV4 = 0x90, MLXSW_TRAP_ID_MAX = 0x1FF -- cgit v1.2.3 From 117b0dad2d54a4265f24eff1328ba594d9153f2a Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:44 +0100 Subject: mlxsw: Create a different trap group list for each device Trap groups can be used to control traps priority, both in terms of which trap "wins" if a packet matches two traps (priority) and in terms of packets from which trap group will be scheduled to the cpu first (tc). They can also be used to set rate limiters (policers) on them (will be added in the next patches). Currently, we support two trap groups. In Spectrum we want a better resolution, so every protocol / flow will have a different trap group, so we can control its parameters separately. Once the policers will be implemented, it will also allow us limit the rate of each protocol by itself. This patch change the trap group list to include: * the emad trap group, which is shared for all the devices. * Switchx2's trap groups, which are a copy of the current trap groups. * Spectrum's new trap groups, in order to match the above guidelines. (Switchib is using only the emad trap group, so it require no changes). This patch also includes new configuration for Spectrum's trap groups, with primary priority order within them. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 17 ++++- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 86 +++++++++++++++++--------- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 8 +-- 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2116f8f0802f..2d92e41379b2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3034,8 +3034,21 @@ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4); enum mlxsw_reg_htgt_trap_group { MLXSW_REG_HTGT_TRAP_GROUP_EMAD, - MLXSW_REG_HTGT_TRAP_GROUP_RX, - MLXSW_REG_HTGT_TRAP_GROUP_CTRL, + MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX, + MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL, + MLXSW_REG_HTGT_TRAP_GROUP_SP_STP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4, + MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF, + MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS, + MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE, + MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME, + MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP, + MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT, }; /* reg_htgt_trap_group diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 42ac968e49a2..2207001846dc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2730,46 +2730,50 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port, return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv); } -#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _is_ctrl) \ +#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl) \ MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action, \ - _is_ctrl, RX, DISCARD) + _is_ctrl, SP_##_trap_group, DISCARD) -#define MLXSW_SP_RXL_MARK(_trap_id, _action, _is_ctrl) \ +#define MLXSW_SP_RXL_MARK(_trap_id, _action, _trap_group, _is_ctrl) \ MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action, \ - _is_ctrl, RX, DISCARD) + _is_ctrl, SP_##_trap_group, DISCARD) + +#define MLXSW_SP_EVENTL(_func, _trap_id) \ + MLXSW_EVENTL(_func, _trap_id, SP_EVENT) static const struct mlxsw_listener mlxsw_sp_listener[] = { /* Events */ - MLXSW_EVENTL(mlxsw_sp_pude_event_func, PUDE, EMAD), + MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE), /* L2 traps */ - MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, true), - MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, true), - MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, true), - MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, false), - MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, false), - MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, false), - MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true), + MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true), + MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, LLDP, true), + MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false), + MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, IGMP, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, IGMP, false), + MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, IGMP, false), + MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false), + MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false), /* L3 traps */ - MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, false), - MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, false), - MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, false), - MLXSW_SP_RXL_MARK(BGP_IPV4, TRAP_TO_CPU, false), + MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, ROUTER_EXP, false), + MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, OSPF, false), + MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false), + MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false), + MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false), + MLXSW_SP_RXL_NO_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false), }; static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; + enum mlxsw_reg_htgt_trap_group i; int max_trap_groups; u8 priority, tc; - int i, err; + int err; if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS)) return -EIO; @@ -2778,15 +2782,41 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) for (i = 0; i < max_trap_groups; i++) { switch (i) { - case MLXSW_REG_HTGT_TRAP_GROUP_EMAD: - case MLXSW_REG_HTGT_TRAP_GROUP_RX: - case MLXSW_REG_HTGT_TRAP_GROUP_CTRL: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF: + priority = 5; + tc = 5; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP: + priority = 4; + tc = 4; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME: + priority = 3; + tc = 3; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP: + priority = 2; + tc = 2; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE: + priority = 1; + tc = 1; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT: priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY; tc = MLXSW_REG_HTGT_DEFAULT_TC; break; default: continue; } + mlxsw_reg_htgt_pack(htgt_pl, i, MLXSW_REG_HTGT_INVALID_POLICER, priority, tc); err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 4cdc02cf152e..150ccf5192a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1448,9 +1448,9 @@ err_port_module_info_get: return err; } -#define MLXSW_SX_RXL(_trap_id) \ +#define MLXSW_SX_RXL(_trap_id) \ MLXSW_RXL(mlxsw_sx_rx_listener_func, _trap_id, TRAP_TO_CPU, \ - false, RX, FORWARD) + false, SX2_RX, FORWARD) static const struct mlxsw_listener mlxsw_sx_listener[] = { MLXSW_EVENTL(mlxsw_sx_pude_event_func, PUDE, EMAD), @@ -1476,7 +1476,7 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) int i; int err; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX, + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX, MLXSW_REG_HTGT_INVALID_POLICER, MLXSW_REG_HTGT_DEFAULT_PRIORITY, MLXSW_REG_HTGT_DEFAULT_TC); @@ -1487,7 +1487,7 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) if (err) return err; - mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL, + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL, MLXSW_REG_HTGT_INVALID_POLICER, MLXSW_REG_HTGT_DEFAULT_PRIORITY, MLXSW_REG_HTGT_DEFAULT_TC); -- cgit v1.2.3 From 2b77958bf4c80cf40fe669c7cf6b65861f9c2e09 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:45 +0100 Subject: mlxsw: resources: Add max cpu policers resource Add a new resource to resources query: max cpu policers which tells us how many policers can be used to limit the data rate to the cpu port. Signed-off-by: Nogah Frankel Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index 07b09f8caabd..1c2119b63258 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -47,6 +47,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_MAX_SYSTEM_PORT, MLXSW_RES_ID_MAX_LAG, MLXSW_RES_ID_MAX_LAG_MEMBERS, + MLXSW_RES_ID_MAX_CPU_POLICERS, MLXSW_RES_ID_MAX_VRS, MLXSW_RES_ID_MAX_RIFS, @@ -69,6 +70,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502, [MLXSW_RES_ID_MAX_LAG] = 0x2520, [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, + [MLXSW_RES_ID_MAX_CPU_POLICERS] = 0x2A13, [MLXSW_RES_ID_MAX_VRS] = 0x2C01, [MLXSW_RES_ID_MAX_RIFS] = 0x2C02, }; -- cgit v1.2.3 From 76a4c7d32a0b0a5a4a072a56a3dc4a2850afd8d8 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:46 +0100 Subject: mlxsw: reg: Add QoS Policer Configuration Register The QPCR register is used to create and control policers. A policer can discard or change the color of packets that are trapped by a specific trap. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 141 ++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2d92e41379b2..1357fe04391b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1757,6 +1757,146 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, } } +/* QPCR - QoS Policer Configuration Register + * ----------------------------------------- + * The QPCR register is used to create policers - that limit + * the rate of bytes or packets via some trap group. + */ +#define MLXSW_REG_QPCR_ID 0x4004 +#define MLXSW_REG_QPCR_LEN 0x28 + +MLXSW_REG_DEFINE(qpcr, MLXSW_REG_QPCR_ID, MLXSW_REG_QPCR_LEN); + +enum mlxsw_reg_qpcr_g { + MLXSW_REG_QPCR_G_GLOBAL = 2, + MLXSW_REG_QPCR_G_STORM_CONTROL = 3, +}; + +/* reg_qpcr_g + * The policer type. + * Access: Index + */ +MLXSW_ITEM32(reg, qpcr, g, 0x00, 14, 2); + +/* reg_qpcr_pid + * Policer ID. + * Access: Index + */ +MLXSW_ITEM32(reg, qpcr, pid, 0x00, 0, 14); + +/* reg_qpcr_color_aware + * Is the policer aware of colors. + * Must be 0 (unaware) for cpu port. + * Access: RW for unbounded policer. RO for bounded policer. + */ +MLXSW_ITEM32(reg, qpcr, color_aware, 0x04, 15, 1); + +/* reg_qpcr_bytes + * Is policer limit is for bytes per sec or packets per sec. + * 0 - packets + * 1 - bytes + * Access: RW for unbounded policer. RO for bounded policer. + */ +MLXSW_ITEM32(reg, qpcr, bytes, 0x04, 14, 1); + +enum mlxsw_reg_qpcr_ir_units { + MLXSW_REG_QPCR_IR_UNITS_M, + MLXSW_REG_QPCR_IR_UNITS_K, +}; + +/* reg_qpcr_ir_units + * Policer's units for cir and eir fields (for bytes limits only) + * 1 - 10^3 + * 0 - 10^6 + * Access: OP + */ +MLXSW_ITEM32(reg, qpcr, ir_units, 0x04, 12, 1); + +enum mlxsw_reg_qpcr_rate_type { + MLXSW_REG_QPCR_RATE_TYPE_SINGLE = 1, + MLXSW_REG_QPCR_RATE_TYPE_DOUBLE = 2, +}; + +/* reg_qpcr_rate_type + * Policer can have one limit (single rate) or 2 limits with specific operation + * for packets that exceed the lower rate but not the upper one. + * (For cpu port must be single rate) + * Access: RW for unbounded policer. RO for bounded policer. + */ +MLXSW_ITEM32(reg, qpcr, rate_type, 0x04, 8, 2); + +/* reg_qpc_cbs + * Policer's committed burst size. + * The policer is working with time slices of 50 nano sec. By default every + * slice is granted the proportionate share of the committed rate. If we want to + * allow a slice to exceed that share (while still keeping the rate per sec) we + * can allow burst. The burst size is between the default proportionate share + * (and no lower than 8) to 32Gb. (Even though giving a number higher than the + * committed rate will result in exceeding the rate). The burst size must be a + * log of 2 and will be determined by 2^cbs. + * Access: RW + */ +MLXSW_ITEM32(reg, qpcr, cbs, 0x08, 24, 6); + +/* reg_qpcr_cir + * Policer's committed rate. + * The rate used for sungle rate, the lower rate for double rate. + * For bytes limits, the rate will be this value * the unit from ir_units. + * (Resolution error is up to 1%). + * Access: RW + */ +MLXSW_ITEM32(reg, qpcr, cir, 0x0C, 0, 32); + +/* reg_qpcr_eir + * Policer's exceed rate. + * The higher rate for double rate, reserved for single rate. + * Lower rate for double rate policer. + * For bytes limits, the rate will be this value * the unit from ir_units. + * (Resolution error is up to 1%). + * Access: RW + */ +MLXSW_ITEM32(reg, qpcr, eir, 0x10, 0, 32); + +#define MLXSW_REG_QPCR_DOUBLE_RATE_ACTION 2 + +/* reg_qpcr_exceed_action. + * What to do with packets between the 2 limits for double rate. + * Access: RW for unbounded policer. RO for bounded policer. + */ +MLXSW_ITEM32(reg, qpcr, exceed_action, 0x14, 0, 4); + +enum mlxsw_reg_qpcr_action { + /* Discard */ + MLXSW_REG_QPCR_ACTION_DISCARD = 1, + /* Forward and set color to red. + * If the packet is intended to cpu port, it will be dropped. + */ + MLXSW_REG_QPCR_ACTION_FORWARD = 2, +}; + +/* reg_qpcr_violate_action + * What to do with packets that cross the cir limit (for single rate) or the eir + * limit (for double rate). + * Access: RW for unbounded policer. RO for bounded policer. + */ +MLXSW_ITEM32(reg, qpcr, violate_action, 0x18, 0, 4); + +static inline void mlxsw_reg_qpcr_pack(char *payload, u16 pid, + enum mlxsw_reg_qpcr_ir_units ir_units, + bool bytes, u32 cir, u16 cbs) +{ + MLXSW_REG_ZERO(qpcr, payload); + mlxsw_reg_qpcr_pid_set(payload, pid); + mlxsw_reg_qpcr_g_set(payload, MLXSW_REG_QPCR_G_GLOBAL); + mlxsw_reg_qpcr_rate_type_set(payload, MLXSW_REG_QPCR_RATE_TYPE_SINGLE); + mlxsw_reg_qpcr_violate_action_set(payload, + MLXSW_REG_QPCR_ACTION_DISCARD); + mlxsw_reg_qpcr_cir_set(payload, cir); + mlxsw_reg_qpcr_ir_units_set(payload, ir_units); + mlxsw_reg_qpcr_bytes_set(payload, bytes); + mlxsw_reg_qpcr_cbs_set(payload, cbs); +} + /* QTCT - QoS Switch Traffic Class Table * ------------------------------------- * Configures the mapping between the packet switch priority and the @@ -5254,6 +5394,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(svpe), MLXSW_REG(sfmr), MLXSW_REG(spvmlr), + MLXSW_REG(qpcr), MLXSW_REG(qtct), MLXSW_REG(qeec), MLXSW_REG(pmlp), -- cgit v1.2.3 From 9148e7cf73ced9bf9d2a1104f6ab3b69303662a2 Mon Sep 17 00:00:00 2001 From: Nogah Frankel Date: Fri, 25 Nov 2016 10:33:47 +0100 Subject: mlxsw: spectrum: Add policers for trap groups Configure policers and connect them to trap groups. While many trap groups share policer's configuration they don't share the actual policer because each trap group represents a different flow / protocol and we don't want one of them to be able to exceed its rate on behalf of another. For example, if STP and LLDP gets to send 128 packets/sec each, if we put them in one 256 packets/sec policer, one can send 200 packets while the other only 50. Note that IP2ME covers lots of flows, so it's limit is set to match the cpu ability to handle data. Signed-off-by: Nogah Frankel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 74 +++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 2207001846dc..fece974b4edd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2767,20 +2767,82 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = { MLXSW_SP_RXL_NO_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false), }; +static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core) +{ + char qpcr_pl[MLXSW_REG_QPCR_LEN]; + enum mlxsw_reg_qpcr_ir_units ir_units; + int max_cpu_policers; + bool is_bytes; + u8 burst_size; + u32 rate; + int i, err; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS)) + return -EIO; + + max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS); + + ir_units = MLXSW_REG_QPCR_IR_UNITS_M; + for (i = 0; i < max_cpu_policers; i++) { + is_bytes = false; + switch (i) { + case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF: + rate = 128; + burst_size = 7; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP: + rate = 16 * 1024; + burst_size = 10; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP: + case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE: + rate = 1024; + burst_size = 7; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME: + is_bytes = true; + rate = 4 * 1024; + burst_size = 4; + break; + default: + continue; + } + + mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate, + burst_size); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl); + if (err) + return err; + } + + return 0; +} + static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; enum mlxsw_reg_htgt_trap_group i; + int max_cpu_policers; int max_trap_groups; u8 priority, tc; + u16 policer_id; int err; if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS)) return -EIO; max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS); + max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS); for (i = 0; i < max_trap_groups; i++) { + policer_id = i; switch (i) { case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP: case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP: @@ -2812,13 +2874,17 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core) case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT: priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY; tc = MLXSW_REG_HTGT_DEFAULT_TC; + policer_id = MLXSW_REG_HTGT_INVALID_POLICER; break; default: continue; } - mlxsw_reg_htgt_pack(htgt_pl, i, MLXSW_REG_HTGT_INVALID_POLICER, - priority, tc); + if (max_cpu_policers <= policer_id && + policer_id != MLXSW_REG_HTGT_INVALID_POLICER) + return -EIO; + + mlxsw_reg_htgt_pack(htgt_pl, i, policer_id, priority, tc); err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); if (err) return err; @@ -2832,6 +2898,10 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) int i; int err; + err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core); + if (err) + return err; + err = mlxsw_sp_trap_groups_set(mlxsw_sp->core); if (err) return err; -- cgit v1.2.3