anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone

Blame 9ef460e-libndctl-papr-Add-limited-support-for-inject-smart.patch

Bryan Gurney bc084d
libndctl/papr: Add limited support for inject-smart
Bryan Gurney bc084d
Bryan Gurney bc084d
BZ: 
Bryan Gurney bc084d
Brew: 
Bryan Gurney bc084d
Bryan Gurney bc084d
commit 9ef460eb7fd1b1f286955b18db8c18cd1a640e77
Bryan Gurney bc084d
Author: Vaibhav Jain <vaibhav@linux.ibm.com>
Bryan Gurney bc084d
Date:   Tue Jan 25 02:08:04 2022 +0530
Bryan Gurney bc084d
Bryan Gurney bc084d
    libndctl/papr: Add limited support for inject-smart
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    Implements support for ndctl inject-smart command by providing an
Bryan Gurney bc084d
    implementation of 'smart_inject*' dimm-ops callbacks. Presently only
Bryan Gurney bc084d
    support for injecting unsafe-shutdown and fatal-health states is
Bryan Gurney bc084d
    available.
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    The patch also introduce various PAPR PDSM structures that are used to
Bryan Gurney bc084d
    communicate the inject-smart errors to the papr_scm kernel
Bryan Gurney bc084d
    module. This is done via SMART_INJECT PDSM which sends a payload of
Bryan Gurney bc084d
    type 'struct nd_papr_pdsm_smart_inject'.
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    With the patch following output from ndctl inject-smart command is
Bryan Gurney bc084d
    expected for PAPR NVDIMMs:
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    $ sudo ndctl inject-smart -fU nmem0
Bryan Gurney bc084d
    [
Bryan Gurney bc084d
      {
Bryan Gurney bc084d
        "dev":"nmem0",
Bryan Gurney bc084d
        "flag_failed_flush":true,
Bryan Gurney bc084d
        "flag_smart_event":true,
Bryan Gurney bc084d
        "health":{
Bryan Gurney bc084d
          "health_state":"fatal",
Bryan Gurney bc084d
          "shutdown_state":"dirty",
Bryan Gurney bc084d
          "shutdown_count":0
Bryan Gurney bc084d
        }
Bryan Gurney bc084d
      }
Bryan Gurney bc084d
    ]
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    $ sudo ndctl inject-smart -N nmem0
Bryan Gurney bc084d
    [
Bryan Gurney bc084d
      {
Bryan Gurney bc084d
        "dev":"nmem0",
Bryan Gurney bc084d
        "health":{
Bryan Gurney bc084d
          "health_state":"ok",
Bryan Gurney bc084d
          "shutdown_state":"clean",
Bryan Gurney bc084d
          "shutdown_count":0
Bryan Gurney bc084d
        }
Bryan Gurney bc084d
      }
Bryan Gurney bc084d
    ]
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    The patch depends on the kernel PAPR PDSM implementation for
Bryan Gurney bc084d
    PDSM_SMART_INJECT posted at [1].
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    [1] : https://lore.kernel.org/nvdimm/20220124202204.1488346-1-vaibhav@linux.ibm.com/
Bryan Gurney bc084d
    
Bryan Gurney bc084d
    Link: https://lore.kernel.org/r/20220124203804.1490254-1-vaibhav@linux.ibm.com
Bryan Gurney bc084d
    Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Bryan Gurney bc084d
    Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
Bryan Gurney bc084d
    Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Bryan Gurney bc084d
    Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Bryan Gurney bc084d
Bryan Gurney bc084d
diff --git a/ndctl/lib/papr.c b/ndctl/lib/papr.c
Bryan Gurney bc084d
index 46cf9c1..7a1d559 100644
Bryan Gurney bc084d
--- a/ndctl/lib/papr.c
Bryan Gurney bc084d
+++ b/ndctl/lib/papr.c
Bryan Gurney bc084d
@@ -221,6 +221,41 @@ static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd)
Bryan Gurney bc084d
 	return health.dimm_bad_shutdown;
Bryan Gurney bc084d
 }
Bryan Gurney bc084d
 
Bryan Gurney bc084d
+static int papr_smart_inject_supported(struct ndctl_dimm *dimm)
Bryan Gurney bc084d
+{
Bryan Gurney bc084d
+	if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL))
Bryan Gurney bc084d
+		return -EOPNOTSUPP;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	if (!test_dimm_dsm(dimm, PAPR_PDSM_SMART_INJECT))
Bryan Gurney bc084d
+		return -EIO;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	return ND_SMART_INJECT_HEALTH_STATE | ND_SMART_INJECT_UNCLEAN_SHUTDOWN;
Bryan Gurney bc084d
+}
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+static int papr_smart_inject_valid(struct ndctl_cmd *cmd)
Bryan Gurney bc084d
+{
Bryan Gurney bc084d
+	if (cmd->type != ND_CMD_CALL ||
Bryan Gurney bc084d
+	    to_pdsm(cmd)->cmd_status != 0 ||
Bryan Gurney bc084d
+	    to_pdsm_cmd(cmd) != PAPR_PDSM_SMART_INJECT)
Bryan Gurney bc084d
+		return -EINVAL;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	return 0;
Bryan Gurney bc084d
+}
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+static struct ndctl_cmd *papr_new_smart_inject(struct ndctl_dimm *dimm)
Bryan Gurney bc084d
+{
Bryan Gurney bc084d
+	struct ndctl_cmd *cmd;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	cmd = allocate_cmd(dimm, PAPR_PDSM_SMART_INJECT,
Bryan Gurney bc084d
+			sizeof(struct nd_papr_pdsm_smart_inject));
Bryan Gurney bc084d
+	if (!cmd)
Bryan Gurney bc084d
+		return NULL;
Bryan Gurney bc084d
+	/* Set the input payload size */
Bryan Gurney bc084d
+	to_ndcmd(cmd)->nd_size_in = ND_PDSM_HDR_SIZE +
Bryan Gurney bc084d
+		sizeof(struct nd_papr_pdsm_smart_inject);
Bryan Gurney bc084d
+	return cmd;
Bryan Gurney bc084d
+}
Bryan Gurney bc084d
+
Bryan Gurney bc084d
 static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd)
Bryan Gurney bc084d
 {
Bryan Gurney bc084d
 	struct nd_papr_pdsm_health health;
Bryan Gurney bc084d
@@ -255,11 +290,37 @@ static unsigned int papr_smart_get_shutdown_count(struct ndctl_cmd *cmd)
Bryan Gurney bc084d
 
Bryan Gurney bc084d
 	return (health.extension_flags & PDSM_DIMM_DSC_VALID) ?
Bryan Gurney bc084d
 		(health.dimm_dsc) : 0;
Bryan Gurney bc084d
+}
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+static int papr_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable)
Bryan Gurney bc084d
+{
Bryan Gurney bc084d
+	if (papr_smart_inject_valid(cmd) < 0)
Bryan Gurney bc084d
+		return -EINVAL;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	to_payload(cmd)->inject.flags |= PDSM_SMART_INJECT_HEALTH_FATAL;
Bryan Gurney bc084d
+	to_payload(cmd)->inject.fatal_enable = enable;
Bryan Gurney bc084d
 
Bryan Gurney bc084d
+	return 0;
Bryan Gurney bc084d
+}
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+static int papr_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd,
Bryan Gurney bc084d
+						 bool enable)
Bryan Gurney bc084d
+{
Bryan Gurney bc084d
+	if (papr_smart_inject_valid(cmd) < 0)
Bryan Gurney bc084d
+		return -EINVAL;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	to_payload(cmd)->inject.flags |= PDSM_SMART_INJECT_BAD_SHUTDOWN;
Bryan Gurney bc084d
+	to_payload(cmd)->inject.unsafe_shutdown_enable = enable;
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+	return 0;
Bryan Gurney bc084d
 }
Bryan Gurney bc084d
 
Bryan Gurney bc084d
 struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) {
Bryan Gurney bc084d
 	.cmd_is_supported = papr_cmd_is_supported,
Bryan Gurney bc084d
+	.new_smart_inject = papr_new_smart_inject,
Bryan Gurney bc084d
+	.smart_inject_supported = papr_smart_inject_supported,
Bryan Gurney bc084d
+	.smart_inject_fatal = papr_cmd_smart_inject_fatal,
Bryan Gurney bc084d
+	.smart_inject_unsafe_shutdown = papr_cmd_smart_inject_unsafe_shutdown,
Bryan Gurney bc084d
 	.smart_get_flags = papr_smart_get_flags,
Bryan Gurney bc084d
 	.get_firmware_status =  papr_get_firmware_status,
Bryan Gurney bc084d
 	.xlat_firmware_status = papr_xlat_firmware_status,
Bryan Gurney bc084d
diff --git a/ndctl/lib/papr_pdsm.h b/ndctl/lib/papr_pdsm.h
Bryan Gurney bc084d
index f45b1e4..20ac20f 100644
Bryan Gurney bc084d
--- a/ndctl/lib/papr_pdsm.h
Bryan Gurney bc084d
+++ b/ndctl/lib/papr_pdsm.h
Bryan Gurney bc084d
@@ -121,12 +121,29 @@ struct nd_papr_pdsm_health {
Bryan Gurney bc084d
 enum papr_pdsm {
Bryan Gurney bc084d
 	PAPR_PDSM_MIN = 0x0,
Bryan Gurney bc084d
 	PAPR_PDSM_HEALTH,
Bryan Gurney bc084d
+	PAPR_PDSM_SMART_INJECT,
Bryan Gurney bc084d
 	PAPR_PDSM_MAX,
Bryan Gurney bc084d
 };
Bryan Gurney bc084d
+/* Flags for injecting specific smart errors */
Bryan Gurney bc084d
+#define PDSM_SMART_INJECT_HEALTH_FATAL		(1 << 0)
Bryan Gurney bc084d
+#define PDSM_SMART_INJECT_BAD_SHUTDOWN		(1 << 1)
Bryan Gurney bc084d
+
Bryan Gurney bc084d
+struct nd_papr_pdsm_smart_inject {
Bryan Gurney bc084d
+	union {
Bryan Gurney bc084d
+		struct {
Bryan Gurney bc084d
+			/* One or more of PDSM_SMART_INJECT_ */
Bryan Gurney bc084d
+			__u32 flags;
Bryan Gurney bc084d
+			__u8 fatal_enable;
Bryan Gurney bc084d
+			__u8 unsafe_shutdown_enable;
Bryan Gurney bc084d
+		};
Bryan Gurney bc084d
+		__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
Bryan Gurney bc084d
+	};
Bryan Gurney bc084d
+};
Bryan Gurney bc084d
 
Bryan Gurney bc084d
 /* Maximal union that can hold all possible payload types */
Bryan Gurney bc084d
 union nd_pdsm_payload {
Bryan Gurney bc084d
 	struct nd_papr_pdsm_health health;
Bryan Gurney bc084d
+	struct nd_papr_pdsm_smart_inject inject;
Bryan Gurney bc084d
 	__u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
Bryan Gurney bc084d
 } __attribute__((packed));
Bryan Gurney bc084d