OSDN Git Service

mlxsw: spectrum: split base on local_ports_in_{1x, 2x} resources
authorShalom Toledo <shalomt@mellanox.com>
Thu, 2 May 2019 11:13:09 +0000 (14:13 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 4 May 2019 05:21:36 +0000 (01:21 -0400)
When splitting a port, different local ports need to be mapped on different
systems. For example:

SN3700 (local_ports_in_2x=2):
  * Without split:
      front panel 1   --> local port 1
      front panel 2   --> local port 5
  * Split to 2:
      front panel 1s0 --> local port 1
      front panel 1s1 --> local port 3
      front panel 2   --> local port 5

SN3800 (local_ports_in_2x=1):
  * Without split:
      front panel 1 --> local port 1
      front panel 2 --> local port 3
  * Split to 2:
      front panel 1s0 --> local port 1
      front panel 1s1 --> local port 2
      front panel 2   --> local port 3

The local_ports_in_{1x, 2x} resources provide the offsets from the base
local ports according to which the new local ports can be calculated.

Signed-off-by: Shalom Toledo <shalomt@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c

index d3c9f8c..a6c6d5e 100644 (file)
@@ -3699,14 +3699,14 @@ static u8 mlxsw_sp_cluster_base_port_get(u8 local_port)
 }
 
 static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
-                                     u8 module, unsigned int count)
+                                     u8 module, unsigned int count, u8 offset)
 {
        u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
        int err, i;
 
        for (i = 0; i < count; i++) {
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
-                                          module, width, i * width);
+               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset,
+                                          true, module, width, i * width);
                if (err)
                        goto err_port_create;
        }
@@ -3715,8 +3715,8 @@ static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
 
 err_port_create:
        for (i--; i >= 0; i--)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
+                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
        return err;
 }
 
@@ -3747,11 +3747,19 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
                               struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+       u8 local_ports_in_1x, local_ports_in_2x, offset;
        struct mlxsw_sp_port *mlxsw_sp_port;
        u8 module, cur_width, base_port;
        int i;
        int err;
 
+       if (!MLXSW_CORE_RES_VALID(mlxsw_core, LOCAL_PORTS_IN_1X) ||
+           !MLXSW_CORE_RES_VALID(mlxsw_core, LOCAL_PORTS_IN_2X))
+               return -EIO;
+
+       local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
+       local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
+
        mlxsw_sp_port = mlxsw_sp->ports[local_port];
        if (!mlxsw_sp_port) {
                dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
@@ -3777,13 +3785,15 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
 
        /* Make sure we have enough slave (even) ports for the split. */
        if (count == 2) {
+               offset = local_ports_in_2x;
                base_port = local_port;
-               if (mlxsw_sp->ports[base_port + 1]) {
+               if (mlxsw_sp->ports[base_port + local_ports_in_2x]) {
                        netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n");
                        NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
                        return -EINVAL;
                }
        } else {
+               offset = local_ports_in_1x;
                base_port = mlxsw_sp_cluster_base_port_get(local_port);
                if (mlxsw_sp->ports[base_port + 1] ||
                    mlxsw_sp->ports[base_port + 3]) {
@@ -3794,10 +3804,11 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
        }
 
        for (i = 0; i < count; i++)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
+                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
 
-       err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count);
+       err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count,
+                                        offset);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
                goto err_port_split_create;
@@ -3814,11 +3825,19 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
                                 struct netlink_ext_ack *extack)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+       u8 local_ports_in_1x, local_ports_in_2x, offset;
        struct mlxsw_sp_port *mlxsw_sp_port;
        u8 cur_width, base_port;
        unsigned int count;
        int i;
 
+       if (!MLXSW_CORE_RES_VALID(mlxsw_core, LOCAL_PORTS_IN_1X) ||
+           !MLXSW_CORE_RES_VALID(mlxsw_core, LOCAL_PORTS_IN_2X))
+               return -EIO;
+
+       local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
+       local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
+
        mlxsw_sp_port = mlxsw_sp->ports[local_port];
        if (!mlxsw_sp_port) {
                dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
@@ -3836,6 +3855,11 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
        cur_width = mlxsw_sp_port->mapping.width;
        count = cur_width == 1 ? 4 : 2;
 
+       if (count == 2)
+               offset = local_ports_in_2x;
+       else
+               offset = local_ports_in_1x;
+
        base_port = mlxsw_sp_cluster_base_port_get(local_port);
 
        /* Determine which ports to remove. */
@@ -3843,8 +3867,8 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
                base_port = base_port + 2;
 
        for (i = 0; i < count; i++)
-               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
-                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+               if (mlxsw_sp_port_created(mlxsw_sp, base_port + i * offset))
+                       mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
 
        mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);