diff mbox series

[net-next,14/17] mlxsw: core_linecards: Implement line card activation process

Message ID 20220418064241.2925668-15-idosch@nvidia.com (mailing list archive)
State Accepted
Commit ee7a70fa671b274aa7e34c66a6e9ab55acadc59a
Delegated to: Netdev Maintainers
Headers show
Series Introduce line card support for modular switch | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count fail Series longer than 15 patches (and no cover letter)
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 97 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Ido Schimmel April 18, 2022, 6:42 a.m. UTC
From: Jiri Pirko <jiri@nvidia.com>

Allow to process events generated upon line card getting "ready" and
"active".

When DSDSC event with "ready" bit set is delivered, that means the
line card is powered up. Use MDDC register to push the line card to
active state. Once FW is done with that, the DSDSC event with "active"
bit set is delivered.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.h    |  4 +-
 .../ethernet/mellanox/mlxsw/core_linecards.c  | 63 +++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)
diff mbox series

Patch

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);
 }