mlxsw: Track per-module port status
In the common port module core, track the number of logical ports that are mapped to the port module and the number of logical ports using it that are administratively up. This will be used by later patches to potentially veto and control certain operations on the module, such as reset and setting its power mode. Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
196bff2927
commit
896f399be0
@ -15,6 +15,8 @@
|
|||||||
struct mlxsw_env_module_info {
|
struct mlxsw_env_module_info {
|
||||||
u64 module_overheat_counter;
|
u64 module_overheat_counter;
|
||||||
bool is_overheat;
|
bool is_overheat;
|
||||||
|
int num_ports_mapped;
|
||||||
|
int num_ports_up;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlxsw_env {
|
struct mlxsw_env {
|
||||||
@ -708,6 +710,60 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get);
|
EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module)
|
||||||
|
{
|
||||||
|
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&mlxsw_env->module_info_lock);
|
||||||
|
mlxsw_env->module_info[module].num_ports_mapped++;
|
||||||
|
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_env_module_port_map);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module)
|
||||||
|
{
|
||||||
|
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&mlxsw_env->module_info_lock);
|
||||||
|
mlxsw_env->module_info[module].num_ports_mapped--;
|
||||||
|
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_env_module_port_unmap);
|
||||||
|
|
||||||
|
int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module)
|
||||||
|
{
|
||||||
|
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&mlxsw_env->module_info_lock);
|
||||||
|
mlxsw_env->module_info[module].num_ports_up++;
|
||||||
|
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_env_module_port_up);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module)
|
||||||
|
{
|
||||||
|
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&mlxsw_env->module_info_lock);
|
||||||
|
mlxsw_env->module_info[module].num_ports_up--;
|
||||||
|
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mlxsw_env_module_port_down);
|
||||||
|
|
||||||
int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
||||||
{
|
{
|
||||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||||
|
@ -27,6 +27,15 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module,
|
|||||||
int
|
int
|
||||||
mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
|
mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
|
||||||
u64 *p_counter);
|
u64 *p_counter);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module);
|
||||||
|
|
||||||
|
int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module);
|
||||||
|
|
||||||
|
void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module);
|
||||||
|
|
||||||
int mlxsw_env_init(struct mlxsw_core *core, struct mlxsw_env **p_env);
|
int mlxsw_env_init(struct mlxsw_core *core, struct mlxsw_env **p_env);
|
||||||
void mlxsw_env_fini(struct mlxsw_env *env);
|
void mlxsw_env_fini(struct mlxsw_env *env);
|
||||||
|
|
||||||
|
@ -54,8 +54,20 @@ static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_m_port_dummy_open_stop(struct net_device *dev)
|
static int mlxsw_m_port_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
|
||||||
|
struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
|
||||||
|
|
||||||
|
return mlxsw_env_module_port_up(mlxsw_m->core, mlxsw_m_port->module);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlxsw_m_port_stop(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
|
||||||
|
struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
|
||||||
|
|
||||||
|
mlxsw_env_module_port_down(mlxsw_m->core, mlxsw_m_port->module);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +82,8 @@ mlxsw_m_port_get_devlink_port(struct net_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct net_device_ops mlxsw_m_port_netdev_ops = {
|
static const struct net_device_ops mlxsw_m_port_netdev_ops = {
|
||||||
.ndo_open = mlxsw_m_port_dummy_open_stop,
|
.ndo_open = mlxsw_m_port_open,
|
||||||
.ndo_stop = mlxsw_m_port_dummy_open_stop,
|
.ndo_stop = mlxsw_m_port_stop,
|
||||||
.ndo_get_devlink_port = mlxsw_m_port_get_devlink_port,
|
.ndo_get_devlink_port = mlxsw_m_port_get_devlink_port,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -266,6 +278,7 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
|
|||||||
|
|
||||||
if (WARN_ON_ONCE(module >= max_ports))
|
if (WARN_ON_ONCE(module >= max_ports))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
mlxsw_env_module_port_map(mlxsw_m->core, module);
|
||||||
mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
|
mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -274,6 +287,7 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
|
|||||||
static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module)
|
static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module)
|
||||||
{
|
{
|
||||||
mlxsw_m->module_to_port[module] = -1;
|
mlxsw_m->module_to_port[module] = -1;
|
||||||
|
mlxsw_env_module_port_unmap(mlxsw_m->core, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
|
static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
|
||||||
|
@ -539,7 +539,9 @@ mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
|||||||
const struct mlxsw_sp_port_mapping *port_mapping)
|
const struct mlxsw_sp_port_mapping *port_mapping)
|
||||||
{
|
{
|
||||||
char pmlp_pl[MLXSW_REG_PMLP_LEN];
|
char pmlp_pl[MLXSW_REG_PMLP_LEN];
|
||||||
int i;
|
int i, err;
|
||||||
|
|
||||||
|
mlxsw_env_module_port_map(mlxsw_sp->core, port_mapping->module);
|
||||||
|
|
||||||
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
|
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
|
||||||
mlxsw_reg_pmlp_width_set(pmlp_pl, port_mapping->width);
|
mlxsw_reg_pmlp_width_set(pmlp_pl, port_mapping->width);
|
||||||
@ -548,36 +550,58 @@ mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
|||||||
mlxsw_reg_pmlp_tx_lane_set(pmlp_pl, i, port_mapping->lane + i); /* Rx & Tx */
|
mlxsw_reg_pmlp_tx_lane_set(pmlp_pl, i, port_mapping->lane + i); /* Rx & Tx */
|
||||||
}
|
}
|
||||||
|
|
||||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
|
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
|
||||||
|
if (err)
|
||||||
|
goto err_pmlp_write;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_pmlp_write:
|
||||||
|
mlxsw_env_module_port_unmap(mlxsw_sp->core, port_mapping->module);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_port_module_unmap(struct mlxsw_sp *mlxsw_sp, u8 local_port)
|
static void mlxsw_sp_port_module_unmap(struct mlxsw_sp *mlxsw_sp, u8 local_port,
|
||||||
|
u8 module)
|
||||||
{
|
{
|
||||||
char pmlp_pl[MLXSW_REG_PMLP_LEN];
|
char pmlp_pl[MLXSW_REG_PMLP_LEN];
|
||||||
|
|
||||||
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
|
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
|
||||||
mlxsw_reg_pmlp_width_set(pmlp_pl, 0);
|
mlxsw_reg_pmlp_width_set(pmlp_pl, 0);
|
||||||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
|
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
|
||||||
|
mlxsw_env_module_port_unmap(mlxsw_sp->core, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_port_open(struct net_device *dev)
|
static int mlxsw_sp_port_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
||||||
|
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
|
err = mlxsw_env_module_port_up(mlxsw_sp->core,
|
||||||
|
mlxsw_sp_port->mapping.module);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
|
||||||
|
if (err)
|
||||||
|
goto err_port_admin_status_set;
|
||||||
netif_start_queue(dev);
|
netif_start_queue(dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_port_admin_status_set:
|
||||||
|
mlxsw_env_module_port_down(mlxsw_sp->core,
|
||||||
|
mlxsw_sp_port->mapping.module);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_port_stop(struct net_device *dev)
|
static int mlxsw_sp_port_stop(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
||||||
|
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||||
|
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
|
mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
|
||||||
|
mlxsw_env_module_port_down(mlxsw_sp->core,
|
||||||
|
mlxsw_sp_port->mapping.module);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1747,13 +1771,14 @@ err_port_label_info_get:
|
|||||||
mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
|
mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
|
||||||
MLXSW_PORT_SWID_DISABLED_PORT);
|
MLXSW_PORT_SWID_DISABLED_PORT);
|
||||||
err_port_swid_set:
|
err_port_swid_set:
|
||||||
mlxsw_sp_port_module_unmap(mlxsw_sp, local_port);
|
mlxsw_sp_port_module_unmap(mlxsw_sp, local_port, port_mapping->module);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
|
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];
|
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
|
||||||
|
u8 module = mlxsw_sp_port->mapping.module;
|
||||||
|
|
||||||
cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
|
cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw);
|
||||||
cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
|
cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw);
|
||||||
@ -1775,7 +1800,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
|
|||||||
mlxsw_core_port_fini(mlxsw_sp->core, local_port);
|
mlxsw_core_port_fini(mlxsw_sp->core, local_port);
|
||||||
mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
|
mlxsw_sp_port_swid_set(mlxsw_sp, local_port,
|
||||||
MLXSW_PORT_SWID_DISABLED_PORT);
|
MLXSW_PORT_SWID_DISABLED_PORT);
|
||||||
mlxsw_sp_port_module_unmap(mlxsw_sp, local_port);
|
mlxsw_sp_port_module_unmap(mlxsw_sp, local_port, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp)
|
static int mlxsw_sp_cpu_port_create(struct mlxsw_sp *mlxsw_sp)
|
||||||
|
Loading…
Reference in New Issue
Block a user