All of lore.kernel.org
 help / color / mirror / Atom feed
* [ndctl v2 1/4] libndctl: Rename dimm property nfit_dsm_mask for generic use
@ 2021-05-17  8:42 Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 2/4] papr: ndtest: Enable smart test cases Santosh Sivaraj
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Santosh Sivaraj @ 2021-05-17  8:42 UTC (permalink / raw)
  To: Linux NVDIMM
  Cc: Shivaprasad G Bhat, Harish Sriram, Aneesh Kumar K.V, Shivaprasad G Bhat

From: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>

The dimm specific dsm masks can be used by different platforms.
Rename it to dsm_mask to avoid confusion.

Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
---
 ndctl/lib/libndctl.c | 4 ++--
 ndctl/lib/private.h  | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

Resending both the SMART test and error injection patches as one series. Will be
easier for review and testing.

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index bf0968c..a148438 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1728,7 +1728,7 @@ static int populate_dimm_attributes(struct ndctl_dimm *dimm,
 
 	sprintf(path, "%s/%s/dsm_mask", dimm_base, bus_prefix);
 	if (sysfs_read_attr(ctx, path, buf) == 0)
-		dimm->nfit_dsm_mask = strtoul(buf, NULL, 0);
+		dimm->dsm_mask = strtoul(buf, NULL, 0);
 
 	sprintf(path, "%s/%s/format", dimm_base, bus_prefix);
 	if (sysfs_read_attr(ctx, path, buf) == 0)
@@ -1821,7 +1821,7 @@ static void *add_dimm(void *parent, int id, const char *dimm_base)
 	dimm->manufacturing_date = -1;
 	dimm->manufacturing_location = -1;
 	dimm->cmd_family = -1;
-	dimm->nfit_dsm_mask = ULONG_MAX;
+	dimm->dsm_mask = ULONG_MAX;
 	for (i = 0; i < formats; i++)
 		dimm->format[i] = -1;
 
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 8f4510e..53fae0f 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -68,7 +68,7 @@ struct ndctl_dimm {
 	unsigned char manufacturing_location;
 	unsigned long cmd_family;
 	unsigned long cmd_mask;
-	unsigned long nfit_dsm_mask;
+	unsigned long dsm_mask;
 	long long dirty_shutdown;
 	enum ndctl_fwa_state fwa_state;
 	enum ndctl_fwa_result fwa_result;
@@ -105,9 +105,9 @@ enum dsm_support {
 
 static inline enum dsm_support test_dimm_dsm(struct ndctl_dimm *dimm, int fn)
 {
-	if (dimm->nfit_dsm_mask == ULONG_MAX) {
+	if (dimm->dsm_mask == ULONG_MAX) {
 		return DIMM_DSM_UNKNOWN;
-	} else if (dimm->nfit_dsm_mask & (1 << fn))
+	} else if (dimm->dsm_mask & (1 << fn))
 		return DIMM_DSM_SUPPORTED;
 	return DIMM_DSM_UNSUPPORTED;
 }
-- 
2.31.1
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [ndctl v2 2/4] papr: ndtest: Enable smart test cases
  2021-05-17  8:42 [ndctl v2 1/4] libndctl: Rename dimm property nfit_dsm_mask for generic use Santosh Sivaraj
@ 2021-05-17  8:42 ` Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 3/4] inject-error: Remove assumptions on error injection support Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 4/4] Error injection support for PAPR Santosh Sivaraj
  2 siblings, 0 replies; 4+ messages in thread
From: Santosh Sivaraj @ 2021-05-17  8:42 UTC (permalink / raw)
  To: Linux NVDIMM
  Cc: Shivaprasad G Bhat, Harish Sriram, Aneesh Kumar K.V, Shivaprasad G Bhat

From: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>

The patch implements all necessary smart APIs for the
ndtest kernel driver.

Both inject-smart.sh and monitor.sh tests pass with the patch.

Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
---
 ndctl/lib/papr.c      | 313 ++++++++++++++++++++++++++++++++++++++++++
 ndctl/lib/papr.h      |   9 ++
 ndctl/lib/papr_pdsm.h |  50 ++++++-
 3 files changed, 371 insertions(+), 1 deletion(-)

diff --git a/ndctl/lib/papr.c b/ndctl/lib/papr.c
index 9c6f2f0..f94f8aa 100644
--- a/ndctl/lib/papr.c
+++ b/ndctl/lib/papr.c
@@ -165,6 +165,18 @@ static unsigned int papr_smart_get_flags(struct ndctl_cmd *cmd)
 		if (health.extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID)
 			flags |= ND_SMART_USED_VALID;
 
+		if (health.extension_flags & PDSM_DIMM_HEALTH_MEDIA_TEMPERATURE_VALID)
+			flags |= ND_SMART_MTEMP_VALID;
+
+		if (health.extension_flags & PDSM_DIMM_HEALTH_CTRL_TEMPERATURE_VALID)
+			flags |= ND_SMART_CTEMP_VALID;
+
+		if (health.extension_flags & PDSM_DIMM_HEALTH_SPARES_VALID)
+			flags |= ND_SMART_SPARES_VALID;
+
+		if (health.extension_flags & PDSM_DIMM_HEALTH_ALARM_VALID)
+			flags |= ND_SMART_ALARM_VALID;
+
 		return flags;
 	}
 
@@ -201,6 +213,26 @@ static unsigned int papr_smart_get_health(struct ndctl_cmd *cmd)
 	return  !health.dimm_health ? 0 : 1 << (health.dimm_health - 1);
 }
 
+static int papr_pdsm_health_set_threshold_valid(struct ndctl_cmd *cmd)
+{
+       if (!cmd_is_valid(cmd) ||
+           to_pdsm(cmd)->cmd_status != 0 ||
+           to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH_THRESHOLD_SET) {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned int papr_cmd_smart_threshold_get_supported_alarms(
+               struct ndctl_cmd *cmd)
+{
+       if (papr_pdsm_health_set_threshold_valid(cmd) < 0)
+               return 0;
+       return ND_SMART_SPARE_TRIP | ND_SMART_MTEMP_TRIP
+               | ND_SMART_CTEMP_TRIP;
+}
+
 static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd)
 {
 	struct nd_papr_pdsm_health health;
@@ -218,6 +250,126 @@ static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd)
 	return health.dimm_bad_shutdown;
 }
 
+static int papr_smart_inject_supported(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+
+	if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) {
+		dbg(ctx, "unsupported cmd: %d\n", ND_CMD_CALL);
+		return -EOPNOTSUPP;
+	}
+
+	if (!test_dimm_dsm(dimm, PAPR_PDSM_HEALTH_INJECT)) {
+		dbg(ctx, "smart injection functions unsupported\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int papr_smart_inject_valid(struct ndctl_cmd *cmd)
+{
+	if (cmd->type != ND_CMD_CALL ||
+			to_pdsm(cmd)->cmd_status != 0 ||
+			to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH_INJECT)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int papr_cmd_smart_inject_media_temperature(struct ndctl_cmd *cmd,
+		bool enable, unsigned int mtemp)
+{
+	if (papr_smart_inject_valid(cmd) < 0)
+		return -EINVAL;
+
+	to_payload(cmd)->inject.flags |= ND_PAPR_SMART_INJECT_MTEMP;
+	to_payload(cmd)->inject.mtemp_enable = enable == true;
+	to_payload(cmd)->inject.media_temperature = mtemp;
+
+	return 0;
+}
+
+static int papr_cmd_smart_inject_ctrl_temperature(struct ndctl_cmd *cmd,
+		bool enable, unsigned int mtemp)
+{
+	if (papr_smart_inject_valid(cmd) < 0)
+		return -EINVAL;
+
+	to_payload(cmd)->inject.flags |= ND_PAPR_SMART_INJECT_MTEMP;
+	to_payload(cmd)->inject.ctemp_enable = enable == true;
+	to_payload(cmd)->inject.ctrl_temperature = mtemp;
+
+	return 0;
+}
+
+static int papr_cmd_smart_inject_spares(struct ndctl_cmd *cmd,
+		bool enable, unsigned int spares)
+{
+	if (papr_smart_inject_valid(cmd) < 0)
+		return -EINVAL;
+
+	to_payload(cmd)->inject.flags |= ND_PAPR_SMART_INJECT_SPARES;
+	to_payload(cmd)->inject.spares_enable = enable == true;
+	to_payload(cmd)->inject.spares = spares;
+
+	return 0;
+}
+
+static struct ndctl_cmd *papr_new_smart_inject(struct ndctl_dimm *dimm)
+{
+	struct ndctl_cmd *cmd;
+
+	cmd = allocate_cmd(dimm, PAPR_PDSM_HEALTH_INJECT,
+			sizeof(struct nd_papr_pdsm_health_inject));
+	if (!cmd)
+		return NULL;
+
+	return cmd;
+}
+
+static struct ndctl_cmd *papr_dimm_cmd_new_smart_set_threshold(
+		struct ndctl_cmd *threshold_cmd)
+{
+	struct ndctl_cmd *set_cmd;
+	struct nd_papr_pdsm_health_threshold thresh;
+
+	if (!cmd_is_valid(threshold_cmd) ||
+	    to_pdsm(threshold_cmd)->cmd_status != 0 ||
+	    to_pdsm_cmd(threshold_cmd) != PAPR_PDSM_HEALTH_THRESHOLD) {
+		return NULL;
+	}
+
+	thresh = to_payload(threshold_cmd)->threshold;
+
+	set_cmd = allocate_cmd(threshold_cmd->dimm, PAPR_PDSM_HEALTH_THRESHOLD_SET,
+			sizeof(struct nd_papr_pdsm_health_threshold));
+	if (!set_cmd)
+		return NULL;
+
+	set_cmd->source = threshold_cmd;
+	ndctl_cmd_ref(threshold_cmd);
+
+	to_payload(set_cmd)->threshold.alarm_control = thresh.alarm_control;
+	to_payload(set_cmd)->threshold.spares = thresh.spares;
+	to_payload(set_cmd)->threshold.media_temperature = thresh.media_temperature;
+	to_payload(set_cmd)->threshold.ctrl_temperature = thresh.ctrl_temperature;
+
+	return set_cmd;
+}
+
+static struct ndctl_cmd *papr_cmd_new_smart_threshold(struct ndctl_dimm *dimm)
+{
+	struct ndctl_cmd *cmd;
+
+	cmd = allocate_cmd(dimm, PAPR_PDSM_HEALTH_THRESHOLD,
+			sizeof(struct nd_papr_pdsm_health_threshold));
+	if (!cmd)
+		return NULL;
+
+	return cmd;
+}
+
 static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd)
 {
 	struct nd_papr_pdsm_health health;
@@ -236,13 +388,174 @@ static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd)
 		(100 - health.dimm_fuel_gauge) : 0;
 }
 
+static int papr_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable)
+{
+	if (papr_smart_inject_valid(cmd) < 0)
+		return -EINVAL;
+
+	to_payload(cmd)->inject.flags |= ND_PAPR_SMART_INJECT_FATAL;
+	to_payload(cmd)->inject.fatal_enable = enable == true;
+
+	return 0;
+}
+
+static int papr_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd,
+							bool enable)
+{
+	if (papr_smart_inject_valid(cmd) < 0)
+		return -EINVAL;
+
+	to_payload(cmd)->inject.flags |= ND_PAPR_SMART_INJECT_SHUTDOWN;
+	to_payload(cmd)->inject.unsafe_shutdown_enable = enable == true;
+
+	return 0;
+}
+
+static unsigned int papr_cmd_smart_threshold_get_alarm_control(struct ndctl_cmd *cmd)
+{
+	int rc = 0;
+	unsigned int flags = 0;
+	struct nd_pkg_pdsm *pcmd = to_pdsm(cmd);
+	struct nd_papr_pdsm_health_threshold threshold;
+
+	if (!cmd_is_valid(cmd) ||
+	    to_pdsm(cmd)->cmd_status != 0 ||
+	    to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH_THRESHOLD) {
+		rc = -EINVAL;
+	}
+
+        if (rc < 0) {
+		errno = -rc;
+		return UINT_MAX;
+	}
+
+	threshold = pcmd->payload.threshold;
+	if (threshold.alarm_control & ND_PAPR_HEALTH_SPARE_TRIP)
+		flags |= ND_SMART_SPARE_TRIP;
+	if (threshold.alarm_control & ND_PAPR_HEALTH_TEMP_TRIP)
+		flags |= ND_SMART_TEMP_TRIP;
+	if (threshold.alarm_control & ND_PAPR_HEALTH_CTEMP_TRIP)
+		flags |= ND_SMART_CTEMP_TRIP;
+
+	return flags;
+}
+
+static int papr_smart_threshold_valid(struct ndctl_cmd *cmd)
+{
+	int rc = 0;
+
+	if (!cmd_is_valid(cmd) ||
+		to_pdsm(cmd)->cmd_status != 0 ||
+		to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH_THRESHOLD) {
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+#define papr_smart_threshold_get_field(cmd, field) \
+static unsigned int papr_cmd_smart_threshold_get_##field( \
+		struct ndctl_cmd *cmd) \
+{ \
+	int rc; \
+	struct nd_pkg_pdsm *pcmd = to_pdsm(cmd); \
+	rc = papr_smart_threshold_valid(cmd); \
+	if (rc < 0) { \
+		errno = -rc; \
+		return UINT_MAX; \
+	} \
+	return pcmd->payload.threshold.field; \
+}
+
+papr_smart_threshold_get_field(cmd, media_temperature)
+papr_smart_threshold_get_field(cmd, ctrl_temperature)
+papr_smart_threshold_get_field(cmd, spares)
+
+static int papr_smart_valid(struct ndctl_cmd *cmd)
+{
+	int rc = 0;
+
+	if (!cmd_is_valid(cmd) ||
+		to_pdsm(cmd)->cmd_status != 0 ||
+		to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH) {
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+
+#define papr_smart_get_field(cmd, field) \
+static unsigned int papr_cmd_smart_get_##field(struct ndctl_cmd *cmd) \
+{ \
+	int rc; \
+	struct nd_pkg_pdsm *pcmd = to_pdsm(cmd); \
+	rc = papr_smart_valid(cmd); \
+	if (rc < 0) { \
+		errno = -rc; \
+		return UINT_MAX; \
+	} \
+	return pcmd->payload.health.field; \
+}
+
+papr_smart_get_field(cmd, ctrl_temperature)
+papr_smart_get_field(cmd, media_temperature)
+papr_smart_get_field(cmd, alarm_flags)
+papr_smart_get_field(cmd, spares)
+
+#define papr_cmd_smart_threshold_set_field(field) \
+static int papr_cmd_smart_threshold_set_##field( \
+				struct ndctl_cmd *cmd, unsigned int val) \
+{ \
+	struct nd_pkg_pdsm *pcmd = to_pdsm(cmd); \
+	if (papr_pdsm_health_set_threshold_valid(cmd) < 0) \
+		return -EINVAL; \
+	pcmd->payload.threshold.field = val; \
+	return 0; \
+}
+
+papr_cmd_smart_threshold_set_field(alarm_control)
+papr_cmd_smart_threshold_set_field(media_temperature)
+papr_cmd_smart_threshold_set_field(ctrl_temperature)
+papr_cmd_smart_threshold_set_field(spares)
+
+
 struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) {
 	.cmd_is_supported = papr_cmd_is_supported,
+	.new_smart_inject = papr_new_smart_inject,
 	.smart_get_flags = papr_smart_get_flags,
+	.smart_inject_supported = papr_smart_inject_supported,
+	.smart_inject_media_temperature = papr_cmd_smart_inject_media_temperature,
+	.smart_inject_ctrl_temperature = papr_cmd_smart_inject_ctrl_temperature,
+	.smart_inject_spares = papr_cmd_smart_inject_spares,
+	.smart_inject_fatal = papr_cmd_smart_inject_fatal,
+	.smart_inject_unsafe_shutdown = papr_cmd_smart_inject_unsafe_shutdown,
+	.smart_get_ctrl_temperature = papr_cmd_smart_get_ctrl_temperature,
+	.smart_get_media_temperature = papr_cmd_smart_get_media_temperature,
+	.smart_get_alarm_flags = papr_cmd_smart_get_alarm_flags,
+	.smart_get_spares = papr_cmd_smart_get_spares,
 	.get_firmware_status =  papr_get_firmware_status,
 	.xlat_firmware_status = papr_xlat_firmware_status,
 	.new_smart = papr_new_smart_health,
 	.smart_get_health = papr_smart_get_health,
 	.smart_get_shutdown_state = papr_smart_get_shutdown_state,
 	.smart_get_life_used = papr_smart_get_life_used,
+	.new_smart_threshold = papr_cmd_new_smart_threshold,
+	.smart_threshold_get_alarm_control
+		= papr_cmd_smart_threshold_get_alarm_control,
+	.smart_threshold_get_media_temperature
+		= papr_cmd_smart_threshold_get_media_temperature,
+	.smart_threshold_get_ctrl_temperature
+		= papr_cmd_smart_threshold_get_ctrl_temperature,
+	.smart_threshold_get_spares = papr_cmd_smart_threshold_get_spares,
+	.new_smart_set_threshold = papr_dimm_cmd_new_smart_set_threshold,
+	.smart_threshold_get_supported_alarms
+		= papr_cmd_smart_threshold_get_supported_alarms,
+	.smart_threshold_set_alarm_control
+		= papr_cmd_smart_threshold_set_alarm_control,
+	.smart_threshold_set_media_temperature
+		= papr_cmd_smart_threshold_set_media_temperature,
+	.smart_threshold_set_ctrl_temperature
+		= papr_cmd_smart_threshold_set_ctrl_temperature,
+	.smart_threshold_set_spares = papr_cmd_smart_threshold_set_spares,
 };
diff --git a/ndctl/lib/papr.h b/ndctl/lib/papr.h
index 7757939..58ba81c 100644
--- a/ndctl/lib/papr.h
+++ b/ndctl/lib/papr.h
@@ -12,4 +12,13 @@ struct nd_pkg_papr {
 	struct nd_pkg_pdsm pdsm;
 };
 
+#define ND_PAPR_SMART_INJECT_MTEMP             (1 << 0)
+#define ND_PAPR_SMART_INJECT_SPARES            (1 << 1)
+#define ND_PAPR_SMART_INJECT_FATAL             (1 << 2)
+#define ND_PAPR_SMART_INJECT_SHUTDOWN          (1 << 3)
+
+#define ND_PAPR_HEALTH_SPARE_TRIP               (1 << 0)
+#define ND_PAPR_HEALTH_TEMP_TRIP                (1 << 1)
+#define ND_PAPR_HEALTH_CTEMP_TRIP               (1 << 2)
+
 #endif /* __PAPR_H__ */
diff --git a/ndctl/lib/papr_pdsm.h b/ndctl/lib/papr_pdsm.h
index 1bac8a7..19586dc 100644
--- a/ndctl/lib/papr_pdsm.h
+++ b/ndctl/lib/papr_pdsm.h
@@ -73,7 +73,12 @@
 #define PAPR_PDSM_DIMM_FATAL         3
 
 /* Indicate that the 'dimm_fuel_gauge' field is valid */
-#define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID 1
+#define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID		(1 << 0)
+#define PDSM_DIMM_HEALTH_MEDIA_TEMPERATURE_VALID 	(1 << 1)
+#define PDSM_DIMM_HEALTH_CTRL_TEMPERATURE_VALID		(1 << 2)
+#define PDSM_DIMM_HEALTH_SHUTDOWN_COUNT_VALID		(1 << 3)
+#define PDSM_DIMM_HEALTH_SPARES_VALID			(1 << 4)
+#define PDSM_DIMM_HEALTH_ALARM_VALID			(1 << 5)
 
 /*
  * Struct exchanged between kernel & ndctl in for PAPR_PDSM_HEALTH
@@ -103,6 +108,10 @@ struct nd_papr_pdsm_health {
 
 			/* Extension flag PDSM_DIMM_HEALTH_RUN_GAUGE_VALID */
 			__u16 dimm_fuel_gauge;
+			__u16 media_temperature;
+			__u16 ctrl_temperature;
+			__u8 spares;
+			__u16 alarm_flags;
 		};
 		__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
 	};
@@ -115,12 +124,51 @@ struct nd_papr_pdsm_health {
 enum papr_pdsm {
 	PAPR_PDSM_MIN = 0x0,
 	PAPR_PDSM_HEALTH,
+	PAPR_PDSM_INJECT_SET = 11,
+	PAPR_PDSM_INJECT_CLEAR = 12,
+	PAPR_PDSM_INJECT_GET = 13,
+	PAPR_PDSM_HEALTH_INJECT = 14,
+	PAPR_PDSM_HEALTH_THRESHOLD = 15,
+	PAPR_PDSM_HEALTH_THRESHOLD_SET = 16,
 	PAPR_PDSM_MAX,
 };
 
+struct nd_papr_pdsm_health_inject {
+	union {
+		struct {
+			__u64 flags;
+			__u8 mtemp_enable;
+			__u16 media_temperature;
+			__u8 ctemp_enable;
+			__u16 ctrl_temperature;
+			__u8 spares_enable;
+			__u8 spares;
+			__u8 fatal_enable;
+			__u8 unsafe_shutdown_enable;
+			__u32 status;
+		};
+		__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+	};
+};
+
+struct nd_papr_pdsm_health_threshold {
+	union {
+		struct {
+			__u16 alarm_control;
+			__u8 spares;
+			__u16 media_temperature;
+			__u16 ctrl_temperature;
+			__u32 status;
+		};
+		__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+	};
+};
+
 /* Maximal union that can hold all possible payload types */
 union nd_pdsm_payload {
 	struct nd_papr_pdsm_health health;
+	struct nd_papr_pdsm_health_inject inject;
+	struct nd_papr_pdsm_health_threshold threshold;
 	__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
 } __attribute__((packed));
 
-- 
2.31.1
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [ndctl v2 3/4] inject-error: Remove assumptions on error injection support
  2021-05-17  8:42 [ndctl v2 1/4] libndctl: Rename dimm property nfit_dsm_mask for generic use Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 2/4] papr: ndtest: Enable smart test cases Santosh Sivaraj
@ 2021-05-17  8:42 ` Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 4/4] Error injection support for PAPR Santosh Sivaraj
  2 siblings, 0 replies; 4+ messages in thread
From: Santosh Sivaraj @ 2021-05-17  8:42 UTC (permalink / raw)
  To: Linux NVDIMM; +Cc: Shivaprasad G Bhat, Harish Sriram, Aneesh Kumar K.V

Currently the code assumes that only nfit supports error injection,
remove those assumptions before error injection support for PAPR is
added. Add bus operations similar to that of DIMM operations with
injection operations in it.

Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
---
 ndctl/lib/inject.c   | 96 ++++++++++++++++++++------------------------
 ndctl/lib/libndctl.c | 11 +++--
 ndctl/lib/nfit.c     | 20 +++++++++
 ndctl/lib/private.h  | 14 +++++++
 4 files changed, 85 insertions(+), 56 deletions(-)

diff --git a/ndctl/lib/inject.c b/ndctl/lib/inject.c
index d61c02c..35fd11e 100644
--- a/ndctl/lib/inject.c
+++ b/ndctl/lib/inject.c
@@ -6,19 +6,15 @@
 #include <util/size.h>
 #include <ndctl/libndctl.h>
 #include <ccan/list/list.h>
-#include <ndctl/libndctl-nfit.h>
 #include <ccan/short_types/short_types.h>
 #include "private.h"
 
 NDCTL_EXPORT int ndctl_bus_has_error_injection(struct ndctl_bus *bus)
 {
-	/* Currently, only nfit buses have error injection */
-	if (!bus || !ndctl_bus_has_nfit(bus))
+	if (!bus)
 		return 0;
 
-	if (ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_SET) &&
-		ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_GET) &&
-		ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_CLEAR))
+	if (bus->ops->err_inj_supported(bus))
 		return 1;
 
 	return 0;
@@ -151,7 +147,7 @@ static int ndctl_namespace_inject_one_error(struct ndctl_namespace *ndns,
 			length = clear_unit;
 	}
 
-	cmd = ndctl_bus_cmd_new_err_inj(bus);
+	cmd = bus->ops->new_err_inj(bus);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -185,8 +181,6 @@ NDCTL_EXPORT int ndctl_namespace_inject_error2(struct ndctl_namespace *ndns,
 
 	if (!ndctl_bus_has_error_injection(bus))
 		return -EOPNOTSUPP;
-	if (!ndctl_bus_has_nfit(bus))
-		return -EOPNOTSUPP;
 
 	for (i = 0; i < count; i++) {
 		rc = ndctl_namespace_inject_one_error(ndns, block + i, flags);
@@ -231,7 +225,7 @@ static int ndctl_namespace_uninject_one_error(struct ndctl_namespace *ndns,
 			length = clear_unit;
 	}
 
-	cmd = ndctl_bus_cmd_new_err_inj_clr(bus);
+	cmd = bus->ops->new_err_inj_clr(bus);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -263,8 +257,6 @@ NDCTL_EXPORT int ndctl_namespace_uninject_error2(struct ndctl_namespace *ndns,
 
 	if (!ndctl_bus_has_error_injection(bus))
 		return -EOPNOTSUPP;
-	if (!ndctl_bus_has_nfit(bus))
-		return -EOPNOTSUPP;
 
 	for (i = 0; i < count; i++) {
 		rc = ndctl_namespace_uninject_one_error(ndns, block + i,
@@ -445,51 +437,49 @@ NDCTL_EXPORT int ndctl_namespace_injection_status(struct ndctl_namespace *ndns)
 	if (!ndctl_bus_has_error_injection(bus))
 		return -EOPNOTSUPP;
 
-	if (ndctl_bus_has_nfit(bus)) {
-		rc = ndctl_namespace_get_injection_bounds(ndns, &ns_offset,
-			&ns_size);
-		if (rc)
-			return rc;
+	rc = ndctl_namespace_get_injection_bounds(ndns, &ns_offset,
+						  &ns_size);
+	if (rc)
+		return rc;
 
-		cmd = ndctl_bus_cmd_new_ars_cap(bus, ns_offset, ns_size);
-		if (!cmd) {
-			err(ctx, "%s: failed to create cmd\n",
-				ndctl_namespace_get_devname(ndns));
-			return -ENOTTY;
-		}
-		rc = ndctl_cmd_submit(cmd);
-		if (rc < 0) {
-			dbg(ctx, "Error submitting ars_cap: %d\n", rc);
-			goto out;
-		}
-		buf_size = ndctl_cmd_ars_cap_get_size(cmd);
-		if (buf_size == 0) {
-			dbg(ctx, "Got an invalid max_ars_out from ars_cap\n");
-			rc = -EINVAL;
-			goto out;
-		}
-		ndctl_cmd_unref(cmd);
+	cmd = ndctl_bus_cmd_new_ars_cap(bus, ns_offset, ns_size);
+	if (!cmd) {
+		err(ctx, "%s: failed to create cmd\n",
+		    ndctl_namespace_get_devname(ndns));
+		return -ENOTTY;
+	}
+	rc = ndctl_cmd_submit(cmd);
+	if (rc < 0) {
+		dbg(ctx, "Error submitting ars_cap: %d\n", rc);
+		goto out;
+	}
+	buf_size = ndctl_cmd_ars_cap_get_size(cmd);
+	if (buf_size == 0) {
+		dbg(ctx, "Got an invalid max_ars_out from ars_cap\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	ndctl_cmd_unref(cmd);
 
-		cmd = ndctl_bus_cmd_new_err_inj_stat(bus, buf_size);
-		if (!cmd)
-			return -ENOMEM;
+	cmd = bus->ops->new_err_inj_stat(bus, buf_size);
+	if (!cmd)
+		return -ENOMEM;
 
-		pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
-		err_inj_stat =
-			(struct nd_cmd_ars_err_inj_stat *)&pkg->nd_payload[0];
+	pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
+	err_inj_stat =
+		(struct nd_cmd_ars_err_inj_stat *)&pkg->nd_payload[0];
 
-		rc = ndctl_cmd_submit(cmd);
-		if (rc < 0) {
-			dbg(ctx, "Error submitting command: %d\n", rc);
-			goto out;
-		}
-		rc = injection_status_to_bb(ndns, err_inj_stat,
-			ns_offset, ns_size);
-		if (rc) {
-			dbg(ctx, "Error converting status to badblocks: %d\n",
-				rc);
-			goto out;
-		}
+	rc = ndctl_cmd_submit(cmd);
+	if (rc < 0) {
+		dbg(ctx, "Error submitting command: %d\n", rc);
+		goto out;
+	}
+	rc = injection_status_to_bb(ndns, err_inj_stat,
+				    ns_offset, ns_size);
+	if (rc) {
+		dbg(ctx, "Error converting status to badblocks: %d\n",
+		    rc);
+		goto out;
 	}
 
  out:
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index a148438..232c531 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -864,6 +864,7 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 	struct ndctl_ctx *ctx = parent;
 	struct ndctl_bus *bus, *bus_dup;
 	char *path = calloc(1, strlen(ctl_base) + 100);
+	char *bus_name;
 
 	if (!path)
 		return NULL;
@@ -893,15 +894,19 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 	} else {
 		bus->has_nfit = 1;
 		bus->revision = strtoul(buf, NULL, 0);
+		bus_name = "nfit";
+		bus->ops = nfit_bus_ops;
 	}
 
 	sprintf(path, "%s/device/of_node/compatible", ctl_base);
 	if (sysfs_read_attr(ctx, path, buf) < 0)
 		bus->has_of_node = 0;
-	else
+	else {
 		bus->has_of_node = 1;
+		bus_name = "papr";
+	}
 
-	sprintf(path, "%s/device/nfit/dsm_mask", ctl_base);
+	sprintf(path, "%s/device/%s/dsm_mask", ctl_base, bus_name);
 	if (sysfs_read_attr(ctx, path, buf) < 0)
 		bus->nfit_dsm_mask = 0;
 	else
@@ -920,7 +925,7 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 	if (!bus->wait_probe_path)
 		goto err_read;
 
-	sprintf(path, "%s/device/nfit/scrub", ctl_base);
+	sprintf(path, "%s/device/%s/scrub", ctl_base, bus_name);
 	bus->scrub_path = strdup(path);
 	if (!bus->scrub_path)
 		goto err_read;
diff --git a/ndctl/lib/nfit.c b/ndctl/lib/nfit.c
index d85682f..a37e50e 100644
--- a/ndctl/lib/nfit.c
+++ b/ndctl/lib/nfit.c
@@ -5,6 +5,19 @@
 #include "private.h"
 #include <ndctl/libndctl-nfit.h>
 
+static int nfit_is_errinj_supported(struct ndctl_bus *bus)
+{
+	if (!ndctl_bus_has_nfit(bus))
+		return 0;
+
+	if (ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_SET) &&
+	    ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_GET) &&
+	    ndctl_bus_is_nfit_cmd_supported(bus, NFIT_CMD_ARS_INJECT_CLEAR))
+		return 1;
+
+	return 0;
+}
+
 static u32 bus_get_firmware_status(struct ndctl_cmd *cmd)
 {
 	struct nd_cmd_bus *cmd_bus = cmd->cmd_bus;
@@ -234,3 +247,10 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus,
 
 	return cmd;
 }
+
+struct ndctl_bus_ops *const nfit_bus_ops = &(struct ndctl_bus_ops) {
+	.new_err_inj = ndctl_bus_cmd_new_err_inj,
+	.new_err_inj_clr = ndctl_bus_cmd_new_err_inj_clr,
+	.new_err_inj_stat = ndctl_bus_cmd_new_err_inj_stat,
+	.err_inj_supported = nfit_is_errinj_supported,
+};
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 53fae0f..0f36c67 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -157,6 +157,7 @@ struct ndctl_bus {
 	struct list_head dimms;
 	struct list_head regions;
 	struct list_node list;
+	struct ndctl_bus_ops *ops;
 	int dimms_init;
 	int regions_init;
 	int has_nfit;
@@ -370,6 +371,19 @@ static inline int check_kmod(struct kmod_ctx *kmod_ctx)
 	return kmod_ctx ? 0 : -ENXIO;
 }
 
+int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, unsigned long long addr,
+		unsigned int *handle, unsigned long long *dpa);
+
+struct ndctl_bus_ops {
+	int (*err_inj_supported)(struct ndctl_bus *bus);
+	struct ndctl_cmd *(*new_err_inj)(struct ndctl_bus *bus);
+	struct ndctl_cmd *(*new_err_inj_clr)(struct ndctl_bus *bus);
+	struct ndctl_cmd *(*new_err_inj_stat)(struct ndctl_bus *bus,
+					      u32 buf_len);
+};
+
+extern struct ndctl_bus_ops * const nfit_bus_ops;
+
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct ndctl_bus *bus);
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus);
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus,
-- 
2.31.1
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [ndctl v2 4/4] Error injection support for PAPR
  2021-05-17  8:42 [ndctl v2 1/4] libndctl: Rename dimm property nfit_dsm_mask for generic use Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 2/4] papr: ndtest: Enable smart test cases Santosh Sivaraj
  2021-05-17  8:42 ` [ndctl v2 3/4] inject-error: Remove assumptions on error injection support Santosh Sivaraj
@ 2021-05-17  8:42 ` Santosh Sivaraj
  2 siblings, 0 replies; 4+ messages in thread
From: Santosh Sivaraj @ 2021-05-17  8:42 UTC (permalink / raw)
  To: Linux NVDIMM; +Cc: Shivaprasad G Bhat, Harish Sriram, Aneesh Kumar K.V

Add support for error injection on PAPR family of devices. This is
particularly useful in running 'make check' on non-nfit platforms.

Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
---
 ndctl/lib/libndctl.c  |   1 +
 ndctl/lib/papr.c      | 134 ++++++++++++++++++++++++++++++++++++++++++
 ndctl/lib/private.h   |   1 +
 ndctl/libndctl-papr.h |   7 +++
 4 files changed, 143 insertions(+)
 create mode 100644 ndctl/libndctl-papr.h

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 232c531..95cdc14 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -904,6 +904,7 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 	else {
 		bus->has_of_node = 1;
 		bus_name = "papr";
+		bus->ops = papr_bus_ops;
 	}
 
 	sprintf(path, "%s/device/%s/dsm_mask", ctl_base, bus_name);
diff --git a/ndctl/lib/papr.c b/ndctl/lib/papr.c
index f94f8aa..6ac3d3e 100644
--- a/ndctl/lib/papr.c
+++ b/ndctl/lib/papr.c
@@ -12,6 +12,7 @@
 #include <util/log.h>
 #include <ndctl.h>
 #include <ndctl/libndctl.h>
+#include <ndctl/libndctl-papr.h>
 #include <lib/private.h>
 #include "papr.h"
 
@@ -38,6 +39,33 @@
 /* return the pdsm command */
 #define to_pdsm_cmd(C) ((enum papr_pdsm)to_ndcmd(C)->nd_command)
 
+/**
+ * ndctl_bus_is_papr_cmd_supported - check if command is supported on @bus.
+ * @bus: ndctl_bus instance
+ * @cmd: papr command number (defined as PAPR_PDSM_XXX in papr-pdsm.h)
+ *
+ * Return 1: command is supported. Return 0: command is not supported.
+ *
+ */
+NDCTL_EXPORT int ndctl_bus_is_papr_cmd_supported(struct ndctl_bus *bus,
+						 int cmd)
+{
+	return !!(bus->nfit_dsm_mask & (1ULL << cmd));
+}
+
+static int papr_is_errinj_supported(struct ndctl_bus *bus)
+{
+	if (!ndctl_bus_is_papr_scm(bus))
+		return 0;
+
+	if (ndctl_bus_is_papr_cmd_supported(bus, PAPR_PDSM_INJECT_SET) &&
+	    ndctl_bus_is_papr_cmd_supported(bus, PAPR_PDSM_INJECT_CLEAR) &&
+	    ndctl_bus_is_papr_cmd_supported(bus, PAPR_PDSM_INJECT_GET))
+		return 1;
+
+	return 0;
+}
+
 static bool papr_cmd_is_supported(struct ndctl_dimm *dimm, int cmd)
 {
 	/* Handle this separately to support monitor mode */
@@ -559,3 +587,109 @@ struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) {
 		= papr_cmd_smart_threshold_set_ctrl_temperature,
 	.smart_threshold_set_spares = papr_cmd_smart_threshold_set_spares,
 };
+
+static u32 bus_get_firmware_status(struct ndctl_cmd *cmd)
+{
+	struct nd_cmd_bus *cmd_bus = cmd->cmd_bus;
+
+	switch (cmd_bus->gen.nd_command) {
+	case PAPR_PDSM_INJECT_SET:
+		return cmd_bus->err_inj.status;
+	case PAPR_PDSM_INJECT_CLEAR:
+		return cmd_bus->err_inj_clr.status;
+	case PAPR_PDSM_INJECT_GET:
+		return cmd_bus->err_inj_stat.status;
+	}
+
+	return -1U;
+}
+
+static struct ndctl_cmd *papr_bus_cmd_new_err_inj(struct ndctl_bus *bus)
+{
+	size_t size, cmd_length;
+	struct nd_cmd_pkg *pkg;
+	struct ndctl_cmd *cmd;
+
+	cmd_length = sizeof(struct nd_cmd_ars_err_inj);
+	size = sizeof(*cmd) + sizeof(*pkg) + cmd_length;
+	cmd = calloc(1, size);
+	if (!cmd)
+		return NULL;
+
+	cmd->bus = bus;
+	ndctl_cmd_ref(cmd);
+	cmd->type = ND_CMD_CALL;
+	cmd->get_firmware_status = bus_get_firmware_status;
+	cmd->size = size;
+	cmd->status = 1;
+	pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
+	pkg->nd_command = PAPR_PDSM_INJECT_SET;
+	pkg->nd_size_in = offsetof(struct nd_cmd_ars_err_inj, status);
+	pkg->nd_size_out = cmd_length - pkg->nd_size_in;
+	pkg->nd_fw_size = pkg->nd_size_out;
+
+	return cmd;
+}
+
+static struct ndctl_cmd *papr_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus)
+{
+	size_t size, cmd_length;
+	struct nd_cmd_pkg *pkg;
+	struct ndctl_cmd *cmd;
+
+	cmd_length = sizeof(struct nd_cmd_ars_err_inj_clr);
+	size = sizeof(*cmd) + sizeof(*pkg) + cmd_length;
+	cmd = calloc(1, size);
+	if (!cmd)
+		return NULL;
+
+	cmd->bus = bus;
+	ndctl_cmd_ref(cmd);
+	cmd->type = ND_CMD_CALL;
+	cmd->get_firmware_status = bus_get_firmware_status;
+	cmd->size = size;
+	cmd->status = 1;
+	pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
+	pkg->nd_command = PAPR_PDSM_INJECT_CLEAR;
+	pkg->nd_size_in = offsetof(struct nd_cmd_ars_err_inj_clr, status);
+	pkg->nd_size_out = cmd_length - pkg->nd_size_in;
+	pkg->nd_fw_size = pkg->nd_size_out;
+
+	return cmd;
+}
+
+static struct ndctl_cmd *papr_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus,
+						u32 buf_size)
+{
+	size_t size, cmd_length;
+	struct nd_cmd_pkg *pkg;
+	struct ndctl_cmd *cmd;
+
+
+	cmd_length = sizeof(struct nd_cmd_ars_err_inj_stat);
+	size = sizeof(*cmd) + sizeof(*pkg) + cmd_length + buf_size;
+	cmd = calloc(1, size);
+	if (!cmd)
+		return NULL;
+
+	cmd->bus = bus;
+	ndctl_cmd_ref(cmd);
+	cmd->type = ND_CMD_CALL;
+	cmd->get_firmware_status = bus_get_firmware_status;
+	cmd->size = size;
+	cmd->status = 1;
+	pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
+	pkg->nd_command = PAPR_PDSM_INJECT_GET;
+	pkg->nd_size_in = 0;
+	pkg->nd_size_out = cmd_length + buf_size;
+	pkg->nd_fw_size = pkg->nd_size_out;
+
+	return cmd;
+}
+
+struct ndctl_bus_ops *const papr_bus_ops = &(struct ndctl_bus_ops) {
+	.new_err_inj = papr_bus_cmd_new_err_inj,
+	.new_err_inj_clr = papr_bus_cmd_new_err_inj_clr,
+	.new_err_inj_stat = papr_bus_cmd_new_err_inj_stat,
+	.err_inj_supported = papr_is_errinj_supported,
+};
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 0f36c67..96d890b 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -383,6 +383,7 @@ struct ndctl_bus_ops {
 };
 
 extern struct ndctl_bus_ops * const nfit_bus_ops;
+extern struct ndctl_bus_ops * const papr_bus_ops;
 
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct ndctl_bus *bus);
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus);
diff --git a/ndctl/libndctl-papr.h b/ndctl/libndctl-papr.h
new file mode 100644
index 0000000..1658d8e
--- /dev/null
+++ b/ndctl/libndctl-papr.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+
+#ifndef __LIBNDCTL_PAPR_H__
+#define __LIBNDCTL_PAPR_H__
+
+int ndctl_bus_is_papr_cmd_supported(struct ndctl_bus *bus, int cmd);
+#endif
-- 
2.31.1
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-05-17  8:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-17  8:42 [ndctl v2 1/4] libndctl: Rename dimm property nfit_dsm_mask for generic use Santosh Sivaraj
2021-05-17  8:42 ` [ndctl v2 2/4] papr: ndtest: Enable smart test cases Santosh Sivaraj
2021-05-17  8:42 ` [ndctl v2 3/4] inject-error: Remove assumptions on error injection support Santosh Sivaraj
2021-05-17  8:42 ` [ndctl v2 4/4] Error injection support for PAPR Santosh Sivaraj

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.