Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ec2ee7d authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller
Browse files

mlxsw: Query maximum number of ports from firmware



We currently hard code the maximum number of ports in the driver, but
this may change in future devices, so query it from the firmware
instead.

Fallback to a maximum of 64 ports in case this number can't be queried.
This should only happen in SwitchX-2 for which this number is correct.

Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8494ab06
Loading
Loading
Loading
Loading
+42 −4
Original line number Diff line number Diff line
@@ -110,11 +110,42 @@ struct mlxsw_core {
	struct mlxsw_res res;
	struct mlxsw_hwmon *hwmon;
	struct mlxsw_thermal *thermal;
	struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
	struct mlxsw_core_port *ports;
	unsigned int max_ports;
	unsigned long driver_priv[0];
	/* driver_priv has to be always the last item */
};

#define MLXSW_PORT_MAX_PORTS_DEFAULT	0x40

static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core)
{
	/* Switch ports are numbered from 1 to queried value */
	if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT))
		mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core,
							   MAX_SYSTEM_PORT) + 1;
	else
		mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1;

	mlxsw_core->ports = kcalloc(mlxsw_core->max_ports,
				    sizeof(struct mlxsw_core_port), GFP_KERNEL);
	if (!mlxsw_core->ports)
		return -ENOMEM;

	return 0;
}

static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core)
{
	kfree(mlxsw_core->ports);
}

unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core)
{
	return mlxsw_core->max_ports;
}
EXPORT_SYMBOL(mlxsw_core_max_ports);

void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
{
	return mlxsw_core->driver_priv;
@@ -733,7 +764,7 @@ static int mlxsw_devlink_port_split(struct devlink *devlink,
{
	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);

	if (port_index >= MLXSW_PORT_MAX_PORTS)
	if (port_index >= mlxsw_core->max_ports)
		return -EINVAL;
	if (!mlxsw_core->driver->port_split)
		return -EOPNOTSUPP;
@@ -745,7 +776,7 @@ static int mlxsw_devlink_port_unsplit(struct devlink *devlink,
{
	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);

	if (port_index >= MLXSW_PORT_MAX_PORTS)
	if (port_index >= mlxsw_core->max_ports)
		return -EINVAL;
	if (!mlxsw_core->driver->port_unsplit)
		return -EOPNOTSUPP;
@@ -972,6 +1003,10 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
	if (err)
		goto err_bus_init;

	err = mlxsw_ports_init(mlxsw_core);
	if (err)
		goto err_ports_init;

	if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
	    MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
		alloc_size = sizeof(u8) *
@@ -1019,6 +1054,8 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
err_emad_init:
	kfree(mlxsw_core->lag.mapping);
err_alloc_lag_mapping:
	mlxsw_ports_fini(mlxsw_core);
err_ports_init:
	mlxsw_bus->fini(bus_priv);
err_bus_init:
	devlink_free(devlink);
@@ -1039,6 +1076,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
	devlink_unregister(devlink);
	mlxsw_emad_fini(mlxsw_core);
	kfree(mlxsw_core->lag.mapping);
	mlxsw_ports_fini(mlxsw_core);
	mlxsw_core->bus->fini(mlxsw_core->bus_priv);
	devlink_free(devlink);
	mlxsw_core_driver_put(device_kind);
@@ -1508,7 +1546,7 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
			    __func__, local_port, rx_info->trap_id);

	if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) ||
	    (local_port >= MLXSW_PORT_MAX_PORTS))
	    (local_port >= mlxsw_core->max_ports))
		goto drop;

	rcu_read_lock();
+2 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ struct mlxsw_driver;
struct mlxsw_bus;
struct mlxsw_bus_info;

unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);

void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);

int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver);
+1 −9
Original line number Diff line number Diff line
@@ -49,20 +49,12 @@

#define MLXSW_PORT_MID			0xd000

#define MLXSW_PORT_MAX_PHY_PORTS	0x40
#define MLXSW_PORT_MAX_PORTS		(MLXSW_PORT_MAX_PHY_PORTS + 1)

#define MLXSW_PORT_MAX_IB_PHY_PORTS	36
#define MLXSW_PORT_MAX_IB_PORTS		(MLXSW_PORT_MAX_IB_PHY_PORTS + 1)

#define MLXSW_PORT_DEVID_BITS_OFFSET	10
#define MLXSW_PORT_PHY_BITS_OFFSET	4
#define MLXSW_PORT_PHY_BITS_MASK	(MLXSW_PORT_MAX_PHY_PORTS - 1)

#define MLXSW_PORT_CPU_PORT		0x0
#define MLXSW_PORT_ROUTER_PORT		(MLXSW_PORT_MAX_PHY_PORTS + 2)

#define MLXSW_PORT_DONT_CARE		(MLXSW_PORT_MAX_PORTS)
#define MLXSW_PORT_DONT_CARE		0xFF

#define MLXSW_PORT_MODULE_MAX_WIDTH	4

+13 −3
Original line number Diff line number Diff line
@@ -2595,25 +2595,33 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
{
	int i;

	for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
	for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
		if (mlxsw_sp_port_created(mlxsw_sp, i))
			mlxsw_sp_port_remove(mlxsw_sp, i);
	kfree(mlxsw_sp->port_to_module);
	kfree(mlxsw_sp->ports);
}

static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
{
	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
	u8 module, width, lane;
	size_t alloc_size;
	int i;
	int err;

	alloc_size = sizeof(struct mlxsw_sp_port *) * MLXSW_PORT_MAX_PORTS;
	alloc_size = sizeof(struct mlxsw_sp_port *) * max_ports;
	mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL);
	if (!mlxsw_sp->ports)
		return -ENOMEM;

	for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
	mlxsw_sp->port_to_module = kcalloc(max_ports, sizeof(u8), GFP_KERNEL);
	if (!mlxsw_sp->port_to_module) {
		err = -ENOMEM;
		goto err_port_to_module_alloc;
	}

	for (i = 1; i < max_ports; i++) {
		err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &module,
						    &width, &lane);
		if (err)
@@ -2633,6 +2641,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
	for (i--; i >= 1; i--)
		if (mlxsw_sp_port_created(mlxsw_sp, i))
			mlxsw_sp_port_remove(mlxsw_sp, i);
	kfree(mlxsw_sp->port_to_module);
err_port_to_module_alloc:
	kfree(mlxsw_sp->ports);
	return err;
}
+7 −5
Original line number Diff line number Diff line
@@ -152,12 +152,14 @@ struct mlxsw_sp_sb_pm {
#define MLXSW_SP_SB_POOL_COUNT	4
#define MLXSW_SP_SB_TC_COUNT	8

struct mlxsw_sp_sb {
	struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT];
	struct {
struct mlxsw_sp_sb_port {
	struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT];
	struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT];
	} ports[MLXSW_PORT_MAX_PORTS];
};

struct mlxsw_sp_sb {
	struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT];
	struct mlxsw_sp_sb_port *ports;
};

#define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE)
@@ -273,7 +275,7 @@ struct mlxsw_sp {
	u32 ageing_time;
	struct mlxsw_sp_upper master_bridge;
	struct mlxsw_sp_upper *lags;
	u8 port_to_module[MLXSW_PORT_MAX_PORTS];
	u8 *port_to_module;
	struct mlxsw_sp_sb sb;
	struct mlxsw_sp_router router;
	struct mlxsw_sp_acl *acl;
Loading