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

Commit 67963a33 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

mlxsw: Make devlink port instances independent of spectrum/switchx2 port instances



Currently, devlink register/unregister is done directly from
spectrum/switchx2 port create/remove functions. With a need to
introduce a port type change, the devlink port instances have to be
persistent across type changes, therefore across port create/remove
function calls. So do a bit of reshuffling to achieve that.

Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarElad Raz <eladr@mellanox.com>
Reviewed-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 7136793e
Loading
Loading
Loading
Loading
+68 −14
Original line number Diff line number Diff line
@@ -90,6 +90,22 @@ struct mlxsw_core_pcpu_stats {
	u32			port_rx_invalid;
};

struct mlxsw_core_port {
	struct devlink_port devlink_port;
	void *port_driver_priv;
};

void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
{
	return mlxsw_core_port->port_driver_priv;
}
EXPORT_SYMBOL(mlxsw_core_port_driver_priv);

static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port)
{
	return mlxsw_core_port->port_driver_priv != NULL;
}

struct mlxsw_core {
	struct mlxsw_driver *driver;
	const struct mlxsw_bus *bus;
@@ -114,6 +130,7 @@ struct mlxsw_core {
	} lag;
	struct mlxsw_res res;
	struct mlxsw_hwmon *hwmon;
	struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
	unsigned long driver_priv[0];
	/* driver_priv has to be always the last item */
};
@@ -928,7 +945,8 @@ static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_port_pool_get)
	if (!mlxsw_driver->sb_port_pool_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
					      pool_index, p_threshold);
@@ -942,7 +960,8 @@ static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_port_pool_set)
	if (!mlxsw_driver->sb_port_pool_set ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
					      pool_index, threshold);
@@ -958,7 +977,8 @@ mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_tc_pool_bind_get)
	if (!mlxsw_driver->sb_tc_pool_bind_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
						 tc_index, pool_type,
@@ -975,7 +995,8 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_tc_pool_bind_set)
	if (!mlxsw_driver->sb_tc_pool_bind_set ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
						 tc_index, pool_type,
@@ -1013,7 +1034,8 @@ mlxsw_devlink_sb_occ_port_pool_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_occ_port_pool_get)
	if (!mlxsw_driver->sb_occ_port_pool_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index,
						  pool_index, p_cur, p_max);
@@ -1029,7 +1051,8 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);

	if (!mlxsw_driver->sb_occ_tc_port_bind_get)
	if (!mlxsw_driver->sb_occ_tc_port_bind_get ||
	    !mlxsw_core_port_check(mlxsw_core_port))
		return -EOPNOTSUPP;
	return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port,
						     sb_index, tc_index,
@@ -1656,28 +1679,59 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_res_get);

int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
			 struct net_device *dev, bool split, u32 split_group)
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port)
{
	struct devlink *devlink = priv_to_devlink(mlxsw_core);
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
	int err;

	if (split)
		devlink_port_split_set(devlink_port, split_group);
	devlink_port_type_eth_set(devlink_port, dev);
	return devlink_port_register(devlink, devlink_port, local_port);
	err = devlink_port_register(devlink, devlink_port, local_port);
	if (err)
		memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
	return err;
}
EXPORT_SYMBOL(mlxsw_core_port_init);

void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port)
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	devlink_port_unregister(devlink_port);
	memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
}
EXPORT_SYMBOL(mlxsw_core_port_fini);

void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			 void *port_driver_priv, struct net_device *dev,
			 bool split, u32 split_group)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	mlxsw_core_port->port_driver_priv = port_driver_priv;
	if (split)
		devlink_port_split_set(devlink_port, split_group);
	devlink_port_type_eth_set(devlink_port, dev);
}
EXPORT_SYMBOL(mlxsw_core_port_set);

void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
			   void *port_driver_priv)
{
	struct mlxsw_core_port *mlxsw_core_port =
					&mlxsw_core->ports[local_port];
	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;

	mlxsw_core_port->port_driver_priv = port_driver_priv;
	devlink_port_type_clear(devlink_port);
}
EXPORT_SYMBOL(mlxsw_core_port_clear);

static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
				    const char *buf, size_t size)
{
+9 −17
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#include "resources.h"

struct mlxsw_core;
struct mlxsw_core_port;
struct mlxsw_driver;
struct mlxsw_bus;
struct mlxsw_bus_info;
@@ -141,23 +142,14 @@ u8 mlxsw_core_lag_mapping_get(struct mlxsw_core *mlxsw_core,
void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
				  u16 lag_id, u8 local_port);

struct mlxsw_core_port {
	struct devlink_port devlink_port;
};

static inline void *
mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
{
	/* mlxsw_core_port is ensured to always be the first field in driver
	 * port structure.
	 */
	return mlxsw_core_port;
}

int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
			 struct net_device *dev, bool split, u32 split_group);
void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port);
void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_set(struct mlxsw_core *mlxsw_core, u8 local_port,
			 void *port_driver_priv, struct net_device *dev,
			 bool split, u32 split_group);
void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
			   void *port_driver_priv);

int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);

+36 −17
Original line number Diff line number Diff line
@@ -2212,7 +2212,7 @@ static int mlxsw_sp_port_pvid_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_port)
	return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
}

static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
				  bool split, u8 module, u8 width, u8 lane)
{
	struct mlxsw_sp_port *mlxsw_sp_port;
@@ -2358,20 +2358,11 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
		goto err_register_netdev;
	}

	err = mlxsw_core_port_init(mlxsw_sp->core, &mlxsw_sp_port->core_port,
				   mlxsw_sp_port->local_port, dev,
				   mlxsw_sp_port->split, module);
	if (err) {
		dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
			mlxsw_sp_port->local_port);
		goto err_core_port_init;
	}

	mlxsw_core_port_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
			    mlxsw_sp_port, dev, mlxsw_sp_port->split, module);
	mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0);
	return 0;

err_core_port_init:
	unregister_netdev(dev);
err_register_netdev:
	mlxsw_sp->ports[local_port] = NULL;
	mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2400,12 +2391,34 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
	return err;
}

static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
				bool split, u8 module, u8 width, u8 lane)
{
	int err;

	err = mlxsw_core_port_init(mlxsw_sp->core, local_port);
	if (err) {
		dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
			local_port);
		return err;
	}
	err = __mlxsw_sp_port_create(mlxsw_sp, local_port, false,
				     module, width, lane);
	if (err)
		goto err_port_create;
	return 0;

err_port_create:
	mlxsw_core_port_fini(mlxsw_sp->core, local_port);
	return err;
}

static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{
	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];

	cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw);
	mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
	mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
	unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
	mlxsw_sp->ports[local_port] = NULL;
	mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2421,6 +2434,12 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
	free_netdev(mlxsw_sp_port->dev);
}

static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{
	__mlxsw_sp_port_remove(mlxsw_sp, local_port);
	mlxsw_core_port_fini(mlxsw_sp->core, local_port);
}

static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{
	return mlxsw_sp->ports[local_port] != NULL;
@@ -2456,8 +2475,8 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
		if (!width)
			continue;
		mlxsw_sp->port_to_module[i] = module;
		err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width,
					   lane);
		err = mlxsw_sp_port_create(mlxsw_sp, i, false,
					   module, width, lane);
		if (err)
			goto err_port_create;
	}
+0 −1
Original line number Diff line number Diff line
@@ -316,7 +316,6 @@ struct mlxsw_sp_port_pcpu_stats {
};

struct mlxsw_sp_port {
	struct mlxsw_core_port core_port; /* must be first */
	struct net_device *dev;
	struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
	struct mlxsw_sp *mlxsw_sp;
+34 −15
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ struct mlxsw_sx_port_pcpu_stats {
};

struct mlxsw_sx_port {
	struct mlxsw_core_port core_port; /* must be first */
	struct net_device *dev;
	struct mlxsw_sx_port_pcpu_stats __percpu *pcpu_stats;
	struct mlxsw_sx *mlxsw_sx;
@@ -995,7 +994,7 @@ mlxsw_sx_port_mac_learning_mode_set(struct mlxsw_sx_port *mlxsw_sx_port,
	return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spmlr), spmlr_pl);
}

static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
static int __mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
				  u8 module, u8 width)
{
	struct mlxsw_sx_port *mlxsw_sx_port;
@@ -1099,19 +1098,11 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
		goto err_register_netdev;
	}

	err = mlxsw_core_port_init(mlxsw_sx->core, &mlxsw_sx_port->core_port,
				   mlxsw_sx_port->local_port, dev, false, 0);
	if (err) {
		dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
			mlxsw_sx_port->local_port);
		goto err_core_port_init;
	}

	mlxsw_core_port_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
			    mlxsw_sx_port, dev, false, 0);
	mlxsw_sx->ports[local_port] = mlxsw_sx_port;
	return 0;

err_core_port_init:
	unregister_netdev(dev);
err_register_netdev:
err_port_mac_learning_mode_set:
err_port_stp_state_set:
@@ -1128,11 +1119,33 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
	return err;
}

static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
				u8 module, u8 width)
{
	int err;

	err = mlxsw_core_port_init(mlxsw_sx->core, local_port);
	if (err) {
		dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
			local_port);
		return err;
	}
	err = __mlxsw_sx_port_create(mlxsw_sx, local_port, module, width);
	if (err)
		goto err_port_create;

	return 0;

err_port_create:
	mlxsw_core_port_fini(mlxsw_sx->core, local_port);
	return err;
}

static void __mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
{
	struct mlxsw_sx_port *mlxsw_sx_port = mlxsw_sx->ports[local_port];

	mlxsw_core_port_fini(&mlxsw_sx_port->core_port);
	mlxsw_core_port_clear(mlxsw_sx->core, local_port, mlxsw_sx);
	unregister_netdev(mlxsw_sx_port->dev); /* This calls ndo_stop */
	mlxsw_sx->ports[local_port] = NULL;
	mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
@@ -1140,6 +1153,12 @@ static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
	free_netdev(mlxsw_sx_port->dev);
}

static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
{
	__mlxsw_sx_port_remove(mlxsw_sx, local_port);
	mlxsw_core_port_fini(mlxsw_sx->core, local_port);
}

static bool mlxsw_sx_port_created(struct mlxsw_sx *mlxsw_sx, u8 local_port)
{
	return mlxsw_sx->ports[local_port] != NULL;