diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core_linecards.c | 63 |
2 files changed, 66 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 44c8a7888985..7d6f8f3bcd93 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -564,7 +564,9 @@ struct mlxsw_linecard { char mbct_pl[MLXSW_REG_MBCT_LEN]; /* Too big for stack */ enum mlxsw_linecard_status_event_type status_event_type_to; struct delayed_work status_event_to_dw; - u8 provisioned:1; + u8 provisioned:1, + ready:1, + active:1; u16 hw_revision; u16 ini_version; }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c index 1401f6d34635..49dfec14da75 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -90,6 +90,8 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard) static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard) { linecard->provisioned = false; + linecard->ready = false; + linecard->active = false; devlink_linecard_provision_fail(linecard->devlink_linecard); } @@ -131,6 +133,46 @@ static void mlxsw_linecard_provision_clear(struct mlxsw_linecard *linecard) devlink_linecard_provision_clear(linecard->devlink_linecard); } +static int mlxsw_linecard_ready_set(struct mlxsw_linecard *linecard) +{ + struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; + char mddc_pl[MLXSW_REG_MDDC_LEN]; + int err; + + mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, true); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); + if (err) + return err; + linecard->ready = true; + return 0; +} + +static int mlxsw_linecard_ready_clear(struct mlxsw_linecard *linecard) +{ + struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; + char mddc_pl[MLXSW_REG_MDDC_LEN]; + int err; + + mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, false); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); + if (err) + return err; + linecard->ready = false; + return 0; +} + +static void mlxsw_linecard_active_set(struct mlxsw_linecard *linecard) +{ + linecard->active = true; + devlink_linecard_activate(linecard->devlink_linecard); +} + +static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard) +{ + linecard->active = false; + devlink_linecard_deactivate(linecard->devlink_linecard); +} + static int mlxsw_linecard_status_process(struct mlxsw_linecards *linecards, struct mlxsw_linecard *linecard, const char *mddq_pl) @@ -164,6 +206,25 @@ static int mlxsw_linecard_status_process(struct mlxsw_linecards *linecards, goto out; } + if (ready == MLXSW_REG_MDDQ_SLOT_INFO_READY_READY && !linecard->ready) { + err = mlxsw_linecard_ready_set(linecard); + if (err) + goto out; + } + + if (active && linecard->active != active) + mlxsw_linecard_active_set(linecard); + + if (!active && linecard->active != active) + mlxsw_linecard_active_clear(linecard); + + if (ready != MLXSW_REG_MDDQ_SLOT_INFO_READY_READY && + linecard->ready) { + err = mlxsw_linecard_ready_clear(linecard); + if (err) + goto out; + } + if (!provisioned && linecard->provisioned != provisioned) mlxsw_linecard_provision_clear(linecard); @@ -676,6 +737,8 @@ static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, cancel_delayed_work_sync(&linecard->status_event_to_dw); /* Make sure all scheduled events are processed */ mlxsw_core_flush_owq(); + if (linecard->active) + mlxsw_linecard_active_clear(linecard); devlink_linecard_destroy(linecard->devlink_linecard); mutex_destroy(&linecard->lock); } |