Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum.c
index d48873b..a7efd2a 100644 (file)
@@ -556,8 +556,9 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
 }
 
-static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
-                                         u16 vid, bool learn_enable)
+int __mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                    u16 vid_begin, u16 vid_end,
+                                    bool learn_enable)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char *spvmlr_pl;
@@ -566,13 +567,20 @@ static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
        spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL);
        if (!spvmlr_pl)
                return -ENOMEM;
-       mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid,
-                             learn_enable);
+       mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid_begin,
+                             vid_end, learn_enable);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl);
        kfree(spvmlr_pl);
        return err;
 }
 
+static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                         u16 vid, bool learn_enable)
+{
+       return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
+                                               learn_enable);
+}
+
 static int
 mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
 {
@@ -974,10 +982,6 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
                        goto err_port_vp_mode_trans;
        }
 
-       err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
-       if (err)
-               goto err_port_vid_learning_set;
-
        err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged);
        if (err)
                goto err_port_add_vid;
@@ -985,8 +989,6 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
        return 0;
 
 err_port_add_vid:
-       mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
-err_port_vid_learning_set:
        if (list_is_singular(&mlxsw_sp_port->vports_list))
                mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 err_port_vp_mode_trans:
@@ -1013,8 +1015,6 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
 
        mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, false, false);
 
-       mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
-
        /* Drop FID reference. If this was the last reference the
         * resources will be freed.
         */
@@ -2571,123 +2571,47 @@ static void mlxsw_sp_rx_listener_func(struct sk_buff *skb, u8 local_port,
        netif_receive_skb(skb);
 }
 
+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);
+}
+
+#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,      \
+       }
+
 static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = {
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_FDB_MC,
-       },
+       MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, FDB_MC, TRAP_TO_CPU),
        /* Traps for specific L2 packet types, not trapped as FDB MC */
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_STP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_LACP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_EAPOL,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_LLDP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_MMRP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_MVRP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_RPVST,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_DHCP,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IGMP_QUERY,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_ARPBC,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_ARPUC,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_MTUERROR,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_TTLERROR,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_LBERROR,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_OSPF,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_IP2ME,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_RTR_INGRESS0,
-       },
-       {
-               .func = mlxsw_sp_rx_listener_func,
-               .local_port = MLXSW_PORT_DONT_CARE,
-               .trap_id = MLXSW_TRAP_ID_HOST_MISS_IPV4,
-       },
+       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),
+       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),
+       /* 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),
 };
 
 static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
@@ -2714,7 +2638,7 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
                if (err)
                        goto err_rx_listener_register;
 
-               mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
+               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)