mlxsw: spectrum: split base on local_ports_in_{1x, 2x} resources
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>
This commit is contained in:

committed by
David S. Miller

parent
4fa050d29c
commit
fd321c6c23
@@ -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,
|
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;
|
u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
|
err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * offset,
|
||||||
module, width, i * width);
|
true, module, width, i * width);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_port_create;
|
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:
|
err_port_create:
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
if (mlxsw_sp_port_created(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);
|
mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
|
||||||
return err;
|
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 netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
|
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;
|
struct mlxsw_sp_port *mlxsw_sp_port;
|
||||||
u8 module, cur_width, base_port;
|
u8 module, cur_width, base_port;
|
||||||
int i;
|
int i;
|
||||||
int err;
|
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];
|
mlxsw_sp_port = mlxsw_sp->ports[local_port];
|
||||||
if (!mlxsw_sp_port) {
|
if (!mlxsw_sp_port) {
|
||||||
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
|
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. */
|
/* Make sure we have enough slave (even) ports for the split. */
|
||||||
if (count == 2) {
|
if (count == 2) {
|
||||||
|
offset = local_ports_in_2x;
|
||||||
base_port = local_port;
|
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");
|
netdev_err(mlxsw_sp_port->dev, "Invalid split configuration\n");
|
||||||
NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
|
NL_SET_ERR_MSG_MOD(extack, "Invalid split configuration");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
offset = local_ports_in_1x;
|
||||||
base_port = mlxsw_sp_cluster_base_port_get(local_port);
|
base_port = mlxsw_sp_cluster_base_port_get(local_port);
|
||||||
if (mlxsw_sp->ports[base_port + 1] ||
|
if (mlxsw_sp->ports[base_port + 1] ||
|
||||||
mlxsw_sp->ports[base_port + 3]) {
|
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++)
|
for (i = 0; i < count; i++)
|
||||||
if (mlxsw_sp_port_created(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);
|
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) {
|
if (err) {
|
||||||
dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
|
dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
|
||||||
goto err_port_split_create;
|
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 netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
|
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;
|
struct mlxsw_sp_port *mlxsw_sp_port;
|
||||||
u8 cur_width, base_port;
|
u8 cur_width, base_port;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
int i;
|
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];
|
mlxsw_sp_port = mlxsw_sp->ports[local_port];
|
||||||
if (!mlxsw_sp_port) {
|
if (!mlxsw_sp_port) {
|
||||||
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
|
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;
|
cur_width = mlxsw_sp_port->mapping.width;
|
||||||
count = cur_width == 1 ? 4 : 2;
|
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);
|
base_port = mlxsw_sp_cluster_base_port_get(local_port);
|
||||||
|
|
||||||
/* Determine which ports to remove. */
|
/* 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;
|
base_port = base_port + 2;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
if (mlxsw_sp_port_created(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);
|
mlxsw_sp_port_remove(mlxsw_sp, base_port + i * offset);
|
||||||
|
|
||||||
mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
|
mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user