mlxsw: core: Extend port module data structures for line cards
The port module core is tasked with module operations such as setting power mode policy and reset. The per-module information is currently stored in one large array suited for non-modular systems where only the main board is present (i.e., slot index 0). As a preparation for line cards support, allocate a per line card array according to the queried number of slots in the system. For each line card, allocate a module array according to the queried maximum number of modules per-slot. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
349454526f
commit
e5b6a5bac8
@ -21,20 +21,36 @@ struct mlxsw_env_module_info {
|
||||
enum mlxsw_reg_pmtm_module_type type;
|
||||
};
|
||||
|
||||
struct mlxsw_env {
|
||||
struct mlxsw_core *core;
|
||||
struct mlxsw_env_line_card {
|
||||
u8 module_count;
|
||||
struct mutex module_info_lock; /* Protects 'module_info'. */
|
||||
struct mlxsw_env_module_info module_info[];
|
||||
};
|
||||
|
||||
struct mlxsw_env {
|
||||
struct mlxsw_core *core;
|
||||
u8 max_module_count; /* Maximum number of modules per-slot. */
|
||||
u8 num_of_slots; /* Including the main board. */
|
||||
struct mutex line_cards_lock; /* Protects line cards. */
|
||||
struct mlxsw_env_line_card *line_cards[];
|
||||
};
|
||||
|
||||
static struct
|
||||
mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core,
|
||||
u8 slot_index, u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
|
||||
return &mlxsw_env->line_cards[slot_index]->module_info[module];
|
||||
}
|
||||
|
||||
static int __mlxsw_env_validate_module_type(struct mlxsw_core *core,
|
||||
u8 slot_index, u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
int err;
|
||||
|
||||
switch (mlxsw_env->module_info[module].type) {
|
||||
module_info = mlxsw_env_module_info_get(core, slot_index, module);
|
||||
switch (module_info->type) {
|
||||
case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
@ -51,9 +67,9 @@ static int mlxsw_env_validate_module_type(struct mlxsw_core *core,
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(core);
|
||||
int err;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
err = __mlxsw_env_validate_module_type(core, slot_index, module);
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -472,6 +488,7 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
u8 module, u32 *flags)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
u32 req = *flags;
|
||||
int err;
|
||||
|
||||
@ -479,7 +496,7 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
!(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
err = __mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
|
||||
if (err) {
|
||||
@ -487,13 +504,14 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_up) {
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
if (module_info->num_ports_up) {
|
||||
netdev_err(netdev, "Cannot reset module when ports using it are administratively up\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_mapped > 1 &&
|
||||
if (module_info->num_ports_mapped > 1 &&
|
||||
!(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) {
|
||||
netdev_err(netdev, "Cannot reset module without \"phy-shared\" flag when shared by multiple ports\n");
|
||||
err = -EINVAL;
|
||||
@ -509,7 +527,7 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
*flags &= ~(ETH_RESET_PHY | (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT));
|
||||
|
||||
out:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_reset_module);
|
||||
@ -521,11 +539,12 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
char mcion_pl[MLXSW_REG_MCION_LEN];
|
||||
u32 status_bits;
|
||||
int err;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
err = __mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
|
||||
if (err) {
|
||||
@ -533,7 +552,8 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
goto out;
|
||||
}
|
||||
|
||||
params->policy = mlxsw_env->module_info[module].power_mode_policy;
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
params->policy = module_info->power_mode_policy;
|
||||
|
||||
mlxsw_reg_mcion_pack(mcion_pl, slot_index, module);
|
||||
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl);
|
||||
@ -552,7 +572,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH;
|
||||
|
||||
out:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_get_module_power_mode);
|
||||
@ -634,6 +654,7 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
bool low_power;
|
||||
int err = 0;
|
||||
|
||||
@ -643,7 +664,7 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
err = __mlxsw_env_validate_module_type(mlxsw_core, slot_index, module);
|
||||
if (err) {
|
||||
@ -652,11 +673,12 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mlxsw_env->module_info[module].power_mode_policy == policy)
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
if (module_info->power_mode_policy == policy)
|
||||
goto out;
|
||||
|
||||
/* If any ports are up, we are already in high power mode. */
|
||||
if (mlxsw_env->module_info[module].num_ports_up)
|
||||
if (module_info->num_ports_up)
|
||||
goto out_set_policy;
|
||||
|
||||
low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO;
|
||||
@ -666,9 +688,9 @@ mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
goto out;
|
||||
|
||||
out_set_policy:
|
||||
mlxsw_env->module_info[module].power_mode_policy = policy;
|
||||
module_info->power_mode_policy = policy;
|
||||
out:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_set_module_power_mode);
|
||||
@ -748,10 +770,11 @@ mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core,
|
||||
u8 slot_index)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
int i, err, sensor_index;
|
||||
bool has_temp_sensor;
|
||||
|
||||
for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) {
|
||||
for (i = 0; i < mlxsw_env->line_cards[slot_index]->module_count; i++) {
|
||||
err = mlxsw_env_module_has_temp_sensor(mlxsw_core, slot_index,
|
||||
i, &has_temp_sensor);
|
||||
if (err)
|
||||
@ -779,6 +802,7 @@ struct mlxsw_env_module_temp_warn_event {
|
||||
static void mlxsw_env_mtwe_event_work(struct work_struct *work)
|
||||
{
|
||||
struct mlxsw_env_module_temp_warn_event *event;
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
struct mlxsw_env *mlxsw_env;
|
||||
int i, sensor_warning;
|
||||
bool is_overheat;
|
||||
@ -787,7 +811,7 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work)
|
||||
work);
|
||||
mlxsw_env = event->mlxsw_env;
|
||||
|
||||
for (i = 0; i < mlxsw_env->module_count; i++) {
|
||||
for (i = 0; i < mlxsw_env->max_module_count; i++) {
|
||||
/* 64-127 of sensor_index are mapped to the port modules
|
||||
* sequentially (module 0 is mapped to sensor_index 64,
|
||||
* module 1 to sensor_index 65 and so on)
|
||||
@ -795,9 +819,10 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work)
|
||||
sensor_warning =
|
||||
mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl,
|
||||
i + MLXSW_REG_MTMP_MODULE_INDEX_MIN);
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
is_overheat =
|
||||
mlxsw_env->module_info[i].is_overheat;
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
/* MTWE only supports main board. */
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_env->core, 0, i);
|
||||
is_overheat = module_info->is_overheat;
|
||||
|
||||
if ((is_overheat && sensor_warning) ||
|
||||
(!is_overheat && !sensor_warning)) {
|
||||
@ -805,21 +830,21 @@ static void mlxsw_env_mtwe_event_work(struct work_struct *work)
|
||||
* warning OR current state in "no warning" and MTWE
|
||||
* does not report warning.
|
||||
*/
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
continue;
|
||||
} else if (is_overheat && !sensor_warning) {
|
||||
/* MTWE reports "no warning", turn is_overheat off.
|
||||
*/
|
||||
mlxsw_env->module_info[i].is_overheat = false;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
module_info->is_overheat = false;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
} else {
|
||||
/* Current state is "no warning" and MTWE reports
|
||||
* "warning", increase the counter and turn is_overheat
|
||||
* on.
|
||||
*/
|
||||
mlxsw_env->module_info[i].is_overheat = true;
|
||||
mlxsw_env->module_info[i].module_overheat_counter++;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
module_info->is_overheat = true;
|
||||
module_info->module_overheat_counter++;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -871,6 +896,7 @@ struct mlxsw_env_module_plug_unplug_event {
|
||||
static void mlxsw_env_pmpe_event_work(struct work_struct *work)
|
||||
{
|
||||
struct mlxsw_env_module_plug_unplug_event *event;
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
struct mlxsw_env *mlxsw_env;
|
||||
bool has_temp_sensor;
|
||||
u16 sensor_index;
|
||||
@ -880,9 +906,12 @@ static void mlxsw_env_pmpe_event_work(struct work_struct *work)
|
||||
work);
|
||||
mlxsw_env = event->mlxsw_env;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mlxsw_env->module_info[event->module].is_overheat = false;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_env->core,
|
||||
event->slot_index,
|
||||
event->module);
|
||||
module_info->is_overheat = false;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core,
|
||||
event->slot_index,
|
||||
@ -909,12 +938,14 @@ static void
|
||||
mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl,
|
||||
void *priv)
|
||||
{
|
||||
u8 slot_index = mlxsw_reg_pmpe_slot_index_get(pmpe_pl);
|
||||
struct mlxsw_env_module_plug_unplug_event *event;
|
||||
enum mlxsw_reg_pmpe_module_status module_status;
|
||||
u8 module = mlxsw_reg_pmpe_module_get(pmpe_pl);
|
||||
struct mlxsw_env *mlxsw_env = priv;
|
||||
|
||||
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||
if (WARN_ON_ONCE(module >= mlxsw_env->max_module_count ||
|
||||
slot_index >= mlxsw_env->num_of_slots))
|
||||
return;
|
||||
|
||||
module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl);
|
||||
@ -926,7 +957,7 @@ mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl,
|
||||
return;
|
||||
|
||||
event->mlxsw_env = mlxsw_env;
|
||||
event->slot_index = 0;
|
||||
event->slot_index = slot_index;
|
||||
event->module = module;
|
||||
INIT_WORK(&event->work, mlxsw_env_pmpe_event_work);
|
||||
mlxsw_core_schedule_work(&event->work);
|
||||
@ -957,9 +988,10 @@ static int
|
||||
mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core,
|
||||
u8 slot_index)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) {
|
||||
for (i = 0; i < mlxsw_env->line_cards[slot_index]->module_count; i++) {
|
||||
char pmaos_pl[MLXSW_REG_PMAOS_LEN];
|
||||
|
||||
mlxsw_reg_pmaos_pack(pmaos_pl, slot_index, i);
|
||||
@ -978,10 +1010,12 @@ mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 slot_ind
|
||||
u8 module, u64 *p_counter)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
*p_counter = mlxsw_env->module_info[module].module_overheat_counter;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
*p_counter = module_info->module_overheat_counter;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -991,10 +1025,12 @@ void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mlxsw_env->module_info[module].num_ports_mapped++;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
module_info->num_ports_mapped++;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_map);
|
||||
|
||||
@ -1002,10 +1038,12 @@ void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mlxsw_env->module_info[module].num_ports_mapped--;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
module_info->num_ports_mapped--;
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_unmap);
|
||||
|
||||
@ -1013,15 +1051,17 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
if (mlxsw_env->module_info[module].power_mode_policy !=
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
if (module_info->power_mode_policy !=
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
|
||||
goto out_inc;
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_up != 0)
|
||||
if (module_info->num_ports_up != 0)
|
||||
goto out_inc;
|
||||
|
||||
/* Transition to high power mode following first port using the module
|
||||
@ -1033,9 +1073,9 @@ int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
goto out_unlock;
|
||||
|
||||
out_inc:
|
||||
mlxsw_env->module_info[module].num_ports_up++;
|
||||
module_info->num_ports_up++;
|
||||
out_unlock:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_up);
|
||||
@ -1044,16 +1084,18 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mutex_lock(&mlxsw_env->line_cards_lock);
|
||||
|
||||
mlxsw_env->module_info[module].num_ports_up--;
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index, module);
|
||||
module_info->num_ports_up--;
|
||||
|
||||
if (mlxsw_env->module_info[module].power_mode_policy !=
|
||||
if (module_info->power_mode_policy !=
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
|
||||
goto out_unlock;
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_up != 0)
|
||||
if (module_info->num_ports_up != 0)
|
||||
goto out_unlock;
|
||||
|
||||
/* Transition to low power mode following last port using the module
|
||||
@ -1063,17 +1105,57 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 slot_index,
|
||||
NULL);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
mutex_unlock(&mlxsw_env->line_cards_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_down);
|
||||
|
||||
static int mlxsw_env_line_cards_alloc(struct mlxsw_env *env)
|
||||
{
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < env->num_of_slots; i++) {
|
||||
env->line_cards[i] = kzalloc(struct_size(env->line_cards[i],
|
||||
module_info,
|
||||
env->max_module_count),
|
||||
GFP_KERNEL);
|
||||
if (!env->line_cards[i])
|
||||
goto kzalloc_err;
|
||||
|
||||
/* Firmware defaults to high power mode policy where modules
|
||||
* are transitioned to high power mode following plug-in.
|
||||
*/
|
||||
for (j = 0; j < env->max_module_count; j++) {
|
||||
module_info = &env->line_cards[i]->module_info[j];
|
||||
module_info->power_mode_policy =
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
kzalloc_err:
|
||||
for (i--; i >= 0; i--)
|
||||
kfree(env->line_cards[i]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void mlxsw_env_line_cards_free(struct mlxsw_env *env)
|
||||
{
|
||||
int i = env->num_of_slots;
|
||||
|
||||
for (i--; i >= 0; i--)
|
||||
kfree(env->line_cards[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mlxsw_env->module_count; i++) {
|
||||
for (i = 0; i < mlxsw_env->line_cards[slot_index]->module_count; i++) {
|
||||
struct mlxsw_env_module_info *module_info;
|
||||
char pmtm_pl[MLXSW_REG_PMTM_LEN];
|
||||
int err;
|
||||
|
||||
@ -1082,8 +1164,9 @@ mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlxsw_env->module_info[i].type =
|
||||
mlxsw_reg_pmtm_module_type_get(pmtm_pl);
|
||||
module_info = mlxsw_env_module_info_get(mlxsw_core, slot_index,
|
||||
i);
|
||||
module_info->type = mlxsw_reg_pmtm_module_type_get(pmtm_pl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1091,32 +1174,38 @@ mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
|
||||
|
||||
int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
||||
{
|
||||
u8 module_count, num_of_slots, max_module_count;
|
||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
struct mlxsw_env *env;
|
||||
u8 module_count;
|
||||
int i, err;
|
||||
int err;
|
||||
|
||||
mlxsw_reg_mgpir_pack(mgpir_pl, 0);
|
||||
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count, NULL);
|
||||
mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count,
|
||||
&num_of_slots);
|
||||
/* If the system is modular, get the maximum number of modules per-slot.
|
||||
* Otherwise, get the maximum number of modules on the main board.
|
||||
*/
|
||||
max_module_count = num_of_slots ?
|
||||
mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl) :
|
||||
module_count;
|
||||
|
||||
env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL);
|
||||
env = kzalloc(struct_size(env, line_cards, num_of_slots + 1),
|
||||
GFP_KERNEL);
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Firmware defaults to high power mode policy where modules are
|
||||
* transitioned to high power mode following plug-in.
|
||||
*/
|
||||
for (i = 0; i < module_count; i++)
|
||||
env->module_info[i].power_mode_policy =
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH;
|
||||
|
||||
mutex_init(&env->module_info_lock);
|
||||
env->core = mlxsw_core;
|
||||
env->module_count = module_count;
|
||||
env->num_of_slots = num_of_slots + 1;
|
||||
env->max_module_count = max_module_count;
|
||||
err = mlxsw_env_line_cards_alloc(env);
|
||||
if (err)
|
||||
goto err_mlxsw_env_line_cards_alloc;
|
||||
|
||||
mutex_init(&env->line_cards_lock);
|
||||
*p_env = env;
|
||||
|
||||
err = mlxsw_env_temp_warn_event_register(mlxsw_core);
|
||||
@ -1127,6 +1216,10 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
||||
if (err)
|
||||
goto err_module_plug_event_register;
|
||||
|
||||
/* Set 'module_count' only for main board. Actual count for line card
|
||||
* is to be set after line card is activated.
|
||||
*/
|
||||
env->line_cards[0]->module_count = num_of_slots ? 0 : module_count;
|
||||
err = mlxsw_env_module_oper_state_event_enable(mlxsw_core, 0);
|
||||
if (err)
|
||||
goto err_oper_state_event_enable;
|
||||
@ -1148,7 +1241,9 @@ err_oper_state_event_enable:
|
||||
err_module_plug_event_register:
|
||||
mlxsw_env_temp_warn_event_unregister(env);
|
||||
err_temp_warn_event_register:
|
||||
mutex_destroy(&env->module_info_lock);
|
||||
mutex_destroy(&env->line_cards_lock);
|
||||
mlxsw_env_line_cards_free(env);
|
||||
err_mlxsw_env_line_cards_alloc:
|
||||
kfree(env);
|
||||
return err;
|
||||
}
|
||||
@ -1159,6 +1254,7 @@ void mlxsw_env_fini(struct mlxsw_env *env)
|
||||
/* Make sure there is no more event work scheduled. */
|
||||
mlxsw_core_flush_owq();
|
||||
mlxsw_env_temp_warn_event_unregister(env);
|
||||
mutex_destroy(&env->module_info_lock);
|
||||
mutex_destroy(&env->line_cards_lock);
|
||||
mlxsw_env_line_cards_free(env);
|
||||
kfree(env);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user