mlxsw: spectrum: Extend and export SPAN API
authorArkadi Sharshevsky <arkadis@mellanox.com>
Fri, 19 Jan 2018 08:24:50 +0000 (09:24 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 21 Jan 2018 23:21:30 +0000 (18:21 -0500)
Extend SPAN API for ACL case. In case of ACL triggering the MPAR register
shouldn't be configured. This patch also export those helpers for
ACL usage.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h

index 7e2b552..833cd0a 100644 (file)
@@ -568,7 +568,7 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
        span_entry->used = false;
 }
 
-static struct mlxsw_sp_span_entry *
+struct mlxsw_sp_span_entry *
 mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
        int i;
@@ -669,13 +669,28 @@ mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port,
 static int
 mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
                                  struct mlxsw_sp_span_entry *span_entry,
-                                 enum mlxsw_sp_span_type type)
+                                 enum mlxsw_sp_span_type type,
+                                 bool bind)
 {
-       struct mlxsw_sp_span_inspected_port *inspected_port;
        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
        char mpar_pl[MLXSW_REG_MPAR_LEN];
-       char sbib_pl[MLXSW_REG_SBIB_LEN];
        int pa_id = span_entry->id;
+
+       /* bind the port to the SPAN entry */
+       mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
+                           (enum mlxsw_reg_mpar_i_e) type, bind, pa_id);
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
+}
+
+static int
+mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
+                                struct mlxsw_sp_span_entry *span_entry,
+                                enum mlxsw_sp_span_type type,
+                                bool bind)
+{
+       struct mlxsw_sp_span_inspected_port *inspected_port;
+       struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
+       char sbib_pl[MLXSW_REG_SBIB_LEN];
        int err;
 
        /* if it is an egress SPAN, bind a shared buffer to it */
@@ -691,12 +706,12 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
                }
        }
 
-       /* bind the port to the SPAN entry */
-       mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
-                           (enum mlxsw_reg_mpar_i_e) type, true, pa_id);
-       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
-       if (err)
-               goto err_mpar_reg_write;
+       if (bind) {
+               err = mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
+                                                       true);
+               if (err)
+                       goto err_port_bind;
+       }
 
        inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
        if (!inspected_port) {
@@ -709,8 +724,11 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
 
        return 0;
 
-err_mpar_reg_write:
 err_inspected_port_alloc:
+       if (bind)
+               mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
+                                                 false);
+err_port_bind:
        if (type == MLXSW_SP_SPAN_EGRESS) {
                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
                mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
@@ -719,25 +737,22 @@ err_inspected_port_alloc:
 }
 
 static void
-mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port,
-                                   struct mlxsw_sp_span_entry *span_entry,
-                                   enum mlxsw_sp_span_type type)
+mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
+                                struct mlxsw_sp_span_entry *span_entry,
+                                enum mlxsw_sp_span_type type,
+                                bool bind)
 {
        struct mlxsw_sp_span_inspected_port *inspected_port;
        struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
-       char mpar_pl[MLXSW_REG_MPAR_LEN];
        char sbib_pl[MLXSW_REG_SBIB_LEN];
-       int pa_id = span_entry->id;
 
        inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry);
        if (!inspected_port)
                return;
 
-       /* remove the inspected port */
-       mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
-                           (enum mlxsw_reg_mpar_i_e) type, false, pa_id);
-       mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
-
+       if (bind)
+               mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
+                                                 false);
        /* remove the SBIB buffer if it was egress SPAN */
        if (type == MLXSW_SP_SPAN_EGRESS) {
                mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
@@ -750,9 +765,9 @@ mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port,
        kfree(inspected_port);
 }
 
-static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
-                                   struct mlxsw_sp_port *to,
-                                   enum mlxsw_sp_span_type type)
+int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
+                            struct mlxsw_sp_port *to,
+                            enum mlxsw_sp_span_type type, bool bind)
 {
        struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
        struct mlxsw_sp_span_entry *span_entry;
@@ -765,7 +780,7 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
        netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
                   span_entry->id);
 
-       err = mlxsw_sp_span_inspected_port_bind(from, span_entry, type);
+       err = mlxsw_sp_span_inspected_port_add(from, span_entry, type, bind);
        if (err)
                goto err_port_bind;
 
@@ -776,9 +791,8 @@ err_port_bind:
        return err;
 }
 
-static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from,
-                                       u8 destination_port,
-                                       enum mlxsw_sp_span_type type)
+void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
+                             enum mlxsw_sp_span_type type, bool bind)
 {
        struct mlxsw_sp_span_entry *span_entry;
 
@@ -791,7 +805,7 @@ static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from,
 
        netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
                   span_entry->id);
-       mlxsw_sp_span_inspected_port_unbind(from, span_entry, type);
+       mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
 }
 
 static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -1582,7 +1596,8 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
        mirror->to_local_port = to_port->local_port;
        mirror->ingress = ingress;
        span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
-       return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type);
+       return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type,
+                                       true);
 }
 
 static void
@@ -1593,8 +1608,8 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
 
        span_type = mirror->ingress ?
                        MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
-       mlxsw_sp_span_mirror_remove(mlxsw_sp_port, mirror->to_local_port,
-                                   span_type);
+       mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->to_local_port,
+                                span_type, true);
 }
 
 static int
index 8a30e76..00c14b1 100644 (file)
@@ -396,6 +396,16 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
+int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
+                            struct mlxsw_sp_port *to,
+                            enum mlxsw_sp_span_type type,
+                            bool bind);
+void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from,
+                             u8 destination_port,
+                             enum mlxsw_sp_span_type type,
+                             bool bind);
+struct mlxsw_sp_span_entry *
+mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port);
 
 /* spectrum_dcb.c */
 #ifdef CONFIG_MLXSW_SPECTRUM_DCB