All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats
@ 2020-01-29 15:28 Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information Vaibhav Jain
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

The PAPR standard provides suitable mechanisms to query the health and
performance stats of an NVDIMM via various hcalls as described in Ref[2]. Until
now these stats were never fetched in the papr_scm modules nor exposed to the
user-space tools like 'ndctl'. This is partly due to PAPR platform not having
support for ACPI and NFIT. Hence 'ndctl' is unable to query and report the dimm
health status and a user had no way to determine the current health status of
a NDVIMM.

To overcome this limitation this RFC patch-set proposes a new set of
Dimm-Specific-Methods(DSM) for querying and fetching health and stat information
for dimms that support PAPR and provides an implementation in kernel for these
DSM in papr_scm modules. These changes coupled with draft/proposed ndtcl changes
located at Ref[4] should provide a way for user to retributive NVDIMM status
using ndtcl. Below is a sample output using proposed kernel + ndctl for PAPR
NVDIMM in an emulation environment:

 # ndctl list -DH
[
  {
    "dev":"nmem0",
    "health":{
      "health_state":"fatal",
      "life_used_percentage":60,
      "shutdown_state":"dirty"
    }
  }
]

PAPR Dimm-Specific-Methods(DSM)
================================

As the name suggests DSMs are used by vendor specific code in libndctl to
execute certain operations or fetch certain information for NVDIMMS. DSMs
can be sent to papr_scm module via libndctl (userspace) and libnvdimm(kernel)
using the ND_CMD_CALL ioctl which can be handled in the dimm control function
papr_scm_ndctl(). For PAPR this RFC proposes two DSMs that directly map to
hcalls provided by PHYP to query NVDIMM health and stats. These DSMs are:

* DSM_PAPR_SCM_HEALTH: Which map to hcall H_SCM_HEALTH and returns dimm health.

* DSM_PAPR_SCM_STATS: Which map to hcall H_SCM_PERFORMANCE_STATS and returns
  		      dimm performance stats.

The ioctl ND_CMD_CALL can also transfer data between
user-space and kernel via 'envelopes'. The envelop is part of a
'struct nd_cmd_pkg' which in return is wrapped in a user defined struct which
in our case is called 'struct nd_pkg_papr_scm' (packaged). These struct is
defined as:

struct nd_pkg_papr_scm {
	struct nd_cmd_pkg hdr;		/* Package header containing sub-cmd */
	uint32_t cmd_status;		/* Out: Sub-cmd status returned back */
	uint8_t payload[];		/* Out: Sub-cmd data buffer */
};

The 'payload' field of the package holds the libnvdimm defined 'envelope' which
is used to send/receive data from userspace buffer (libndctl). This RFC uses this
field to copy the results of hcalls that are executed in response to the DSM
commands.

Please note that results of hcalls are not interpreted (with few exceptions) in
papr_scm module at all. Instead they are directly copied to the 'payload' field
and sent to userspace(libndctl) for interpretation. This essentially means that
the papr_scm module simply acts as a conduit for libndctl to issue hcalls and
fetch its output. This should make parsing and interpreting with output buffers
of hcalls easier as it can be performed in userspace.

References:
[1]: "Power Architecture Platform Reference"
      https://en.wikipedia.org/wiki/Power_Architecture_Platform_Reference
[2]: "[DOC,v2] powerpc: Provide initial documentation for PAPR hcalls"
     https://patchwork.ozlabs.org/patch/1154292/
[3]: "Linux on Power Architecture Platform Reference"
     https://members.openpowerfoundation.org/document/dl/469
[4]: https://github.com/vaibhav92/ndctl/tree/papr_scm_health

Vaibhav Jain (6):
  powerpc/papr_scm: Provide support for fetching dimm health information
  powerpc/papr_scm: Fetch dimm performance stats from PHYP
  UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family
  powerpc/papr_scm: Add support for handling PAPR DSM commands
  powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
  powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS

 arch/powerpc/platforms/pseries/papr_scm.c | 314 +++++++++++++++++++++-
 include/uapi/linux/ndctl.h                |   1 +
 2 files changed, 306 insertions(+), 9 deletions(-)

-- 
2.24.1


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

* [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 2/6] powerpc/papr_scm: Fetch dimm performance stats from PHYP Vaibhav Jain
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

Implement support for fetching dimm health information via
H_SCM_HEALTH hcall as documented in Ref[1]. The hcall returns a pair of
64-bit big-endian integers which are then stored in 'struct
papr_scm_priv' and subsequently exposed to userspace via dimm
attribute 'papr_health'.

References:
[1]: https://patchwork.ozlabs.org/patch/1154292/

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c | 65 ++++++++++++++++++++++-
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 0b4467e378e5..1a0cc66f3dc9 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -39,6 +39,10 @@ struct papr_scm_priv {
 	struct resource res;
 	struct nd_region *region;
 	struct nd_interleave_set nd_set;
+
+	/* Health information for the dimm */
+	__be64 health_bitmap;
+	__be64 health_bitmap_valid;
 };
 
 static int drc_pmem_bind(struct papr_scm_priv *p)
@@ -144,6 +148,30 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
 	return drc_pmem_bind(p);
 }
 
+static int drc_pmem_query_health(struct papr_scm_priv *p)
+{
+	unsigned long ret[PLPAR_HCALL_BUFSIZE];
+	int64_t rc;
+
+	rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index);
+	if (rc != H_SUCCESS) {
+		dev_err(&p->pdev->dev,
+			 "Failed to query health information, Err:%lld\n", rc);
+		return -ENXIO;
+	}
+
+	/* Store the retrieved health information in dimm platform data */
+
+	p->health_bitmap = ret[0];
+	p->health_bitmap_valid = ret[1];
+
+	dev_dbg(&p->pdev->dev,
+		"Queried dimm health info. Bitmap:0x%016llx Mask:0x%016llx\n",
+		be64_to_cpu(p->health_bitmap),
+		be64_to_cpu(p->health_bitmap_valid));
+
+	return 0;
+}
 
 static int papr_scm_meta_get(struct papr_scm_priv *p,
 			     struct nd_cmd_get_config_data_hdr *hdr)
@@ -304,6 +332,39 @@ static inline int papr_scm_node(int node)
 	return min_node;
 }
 
+static ssize_t papr_health_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct nvdimm *dimm = to_nvdimm(dev);
+	struct papr_scm_priv *p = nvdimm_provider_data(dimm);
+	int rc;
+
+	rc = drc_pmem_query_health(p);
+
+	if (rc)
+		return rc;
+	else
+		return sprintf(buf, "0x%016llX 0x%016llX\n",
+			       be64_to_cpu(p->health_bitmap),
+			       be64_to_cpu(p->health_bitmap_valid));
+}
+DEVICE_ATTR_RO(papr_health);
+
+/* papr_scm specific dimm attributes */
+static struct attribute *papr_scm_nd_attributes[] = {
+	&dev_attr_papr_health.attr,
+	NULL,
+};
+
+static struct attribute_group papr_scm_nd_attribute_group = {
+	.attrs = papr_scm_nd_attributes,
+};
+
+static const struct attribute_group *papr_scm_dimm_attr_groups[] = {
+	&papr_scm_nd_attribute_group,
+	NULL,
+};
+
 static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 {
 	struct device *dev = &p->pdev->dev;
@@ -330,8 +391,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 	dimm_flags = 0;
 	set_bit(NDD_ALIASING, &dimm_flags);
 
-	p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
-				  PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
+	p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_attr_groups,
+				  dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
 	if (!p->nvdimm) {
 		dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
 		goto err;
-- 
2.24.1


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

* [RFC PATCH 2/6] powerpc/papr_scm: Fetch dimm performance stats from PHYP
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 3/6] UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family Vaibhav Jain
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

Implement support for fetching dimm performance metrics via
H_SCM_PERFORMANCE_HEALTH hcall as documented in Ref[1]. The hcall
returns a structure as described in Ref[1] and defined as newly
introduced 'struct papr_scm_perf_stats'. The struct has a header
followed by key-value pairs of performance attributes.

The module 'papr_scm' however doesn't interpret or parses these
performance attributes as it will be returning this buffer as it is to
user-space for further parsing. For now we only implement a dimm
specific sysfs attribute named 'papr_stats_version' that returns the
version of the structure returned from H_SCM_PERFORMANCE_HEALTH hcall.

Hence this patch implements a new function drc_pmem_query_stats() that
issues hcall H_SCM_PERFORMANCE_HEALTH ,requesting PHYP to store
performance stats in pre-allocated 'struct papr_scm_perf_stats' buffer
'stats'.

References:
[1]: https://patchwork.ozlabs.org/patch/1154292/

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c | 56 +++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 1a0cc66f3dc9..deaece6e4d18 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -22,6 +22,16 @@
 	 (1ul << ND_CMD_GET_CONFIG_DATA) | \
 	 (1ul << ND_CMD_SET_CONFIG_DATA))
 
+#define PAPR_SCM_MAX_PERF_STAT 4096
+
+/* Buffer layout returned by phyp when reporting drc perf stats */
+struct papr_scm_perf_stats {
+	uint8_t version;		/* Should be 0x01 */
+	uint8_t reserved1;
+	__be16 size;			/* Size of this struct in bytes */
+	uint8_t buffer[];		/* Performance matrics */
+} __packed;
+
 struct papr_scm_priv {
 	struct platform_device *pdev;
 	struct device_node *dn;
@@ -148,6 +158,25 @@ static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
 	return drc_pmem_bind(p);
 }
 
+static int drc_pmem_query_stats(struct papr_scm_priv *p,
+				struct papr_scm_perf_stats *stats)
+{
+	unsigned long ret[PLPAR_HCALL_BUFSIZE];
+	int64_t rc;
+
+	if (!stats)
+		return -EINVAL;
+
+	rc = plpar_hcall(H_SCM_PERFORMANCE_STATS, ret, p->drc_index,
+			 __pa(stats));
+	if (rc != H_SUCCESS) {
+		dev_err(&p->pdev->dev,
+			 "Failed to query performance stats, Err:%lld\n", rc);
+		return -ENXIO;
+	} else
+		return 0;
+}
+
 static int drc_pmem_query_health(struct papr_scm_priv *p)
 {
 	unsigned long ret[PLPAR_HCALL_BUFSIZE];
@@ -332,6 +361,32 @@ static inline int papr_scm_node(int node)
 	return min_node;
 }
 
+static ssize_t papr_stats_version_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct nvdimm *dimm = to_nvdimm(dev);
+	struct papr_scm_priv *p = nvdimm_provider_data(dimm);
+	struct papr_scm_perf_stats *retbuffer;
+	int rc;
+
+	/* Return buffer for phyp where stats are written */
+	retbuffer = kzalloc(PAPR_SCM_MAX_PERF_STAT, GFP_KERNEL);
+	if (!retbuffer)
+		return -ENOMEM;
+
+	rc = drc_pmem_query_stats(p, retbuffer);
+	if (rc)
+		goto out;
+	else
+		rc = sprintf(buf, "%d\n", retbuffer->version);
+
+out:
+	kfree(retbuffer);
+	return rc;
+
+}
+DEVICE_ATTR_RO(papr_stats_version);
+
 static ssize_t papr_health_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -353,6 +408,7 @@ DEVICE_ATTR_RO(papr_health);
 /* papr_scm specific dimm attributes */
 static struct attribute *papr_scm_nd_attributes[] = {
 	&dev_attr_papr_health.attr,
+	&dev_attr_papr_stats_version.attr,
 	NULL,
 };
 
-- 
2.24.1


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

* [RFC PATCH 3/6] UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 2/6] powerpc/papr_scm: Fetch dimm performance stats from PHYP Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 4/6] powerpc/papr_scm: Add support for handling PAPR DSM commands Vaibhav Jain
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

Add PAPR-scm family of DSM command-set to to the white list of NVDIMM
command sets.

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 include/uapi/linux/ndctl.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index de5d90212409..0e09dc5cec19 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -244,6 +244,7 @@ struct nd_cmd_pkg {
 #define NVDIMM_FAMILY_HPE2 2
 #define NVDIMM_FAMILY_MSFT 3
 #define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR 5
 
 #define ND_IOCTL_CALL			_IOWR(ND_IOCTL, ND_CMD_CALL,\
 					struct nd_cmd_pkg)
-- 
2.24.1


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

* [RFC PATCH 4/6] powerpc/papr_scm: Add support for handling PAPR DSM commands
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
                   ` (2 preceding siblings ...)
  2020-01-29 15:28 ` [RFC PATCH 3/6] UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 5/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS Vaibhav Jain
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

Implement support for handling PAPR DSM commands in papr_scm
module. We advertise support for ND_CMD_CALL for the dimm command mask
and implement necessary scaffolding in the module to handle ND_CMD_CALL
ioctl and DSM commands that we receive.

The layout of the DSM commands as we expect from libnvdimm/libndctl is
defined in 'struct nd_pkg_papr_scm' which contains a 'struct
nd_cmd_pkg' as header. This header is used to communicate the DSM
command via 'nd_pkg_papr_scm->nd_command' and size of payload that
need to be sent/received for servicing the DSM.

The PAPR DSM commands are assigned indexes started from 0x10000 to
prevent them from overlapping ND_CMD_* values and also makes handling
dimm commands in papr_scm_ndctl() easier via a simplified switch-case
block. For this a new function cmd_to_func() is implemented that reads
the args to papr_scm_ndctl() , performs sanity tests on them and
converts them to PAPR DSM commands which can then be handled via the
switch-case block.

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c | 96 +++++++++++++++++++++--
 1 file changed, 89 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index deaece6e4d18..e1a2c0e61077 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -20,10 +20,29 @@
 #define PAPR_SCM_DIMM_CMD_MASK \
 	((1ul << ND_CMD_GET_CONFIG_SIZE) | \
 	 (1ul << ND_CMD_GET_CONFIG_DATA) | \
-	 (1ul << ND_CMD_SET_CONFIG_DATA))
+	 (1ul << ND_CMD_SET_CONFIG_DATA) | \
+	 (1ul << ND_CMD_CALL))
 
 #define PAPR_SCM_MAX_PERF_STAT 4096
 
+/*
+ * Sub commands for ND_CMD_CALL. To prevent overlap from ND_CMD_*, values for
+ * these enums start at 0x10000. These values are then returned from
+ * cmd_to_func() making it easy to implement the switch-case block in
+ * papr_scm_ndctl()
+ */
+enum {
+	DSM_PAPR_MIN =  0x10000,
+	DSM_PAPR_MAX,
+};
+
+/* Payload expected with ND_CMD_CALL ioctl from libnvdimm */
+struct nd_pkg_papr_scm {
+	struct nd_cmd_pkg hdr;		/* Package header containing sub-cmd */
+	uint32_t cmd_status;		/* Out: Sub-cmd status returned back */
+	uint8_t payload[];		/* Out: Sub-cmd data buffer */
+} __packed;
+
 /* Buffer layout returned by phyp when reporting drc perf stats */
 struct papr_scm_perf_stats {
 	uint8_t version;		/* Should be 0x01 */
@@ -303,19 +322,74 @@ static int papr_scm_meta_set(struct papr_scm_priv *p,
 	return 0;
 }
 
+/*
+ * Validate the input to dimm-control function and return papr_scm specific
+ * commands. This does sanity validation to ND_CMD_CALL sub-command packages.
+ */
+static int cmd_to_func(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+		       unsigned int buf_len)
+{
+	unsigned long cmd_mask = PAPR_SCM_DIMM_CMD_MASK;
+	struct nd_pkg_papr_scm *pkg = (struct nd_pkg_papr_scm *)buf;
+
+	/* Only dimm-specific calls are supported atm */
+	if (!nvdimm)
+		return -EINVAL;
+
+	if (!test_bit(cmd, &cmd_mask)) {
+
+		pr_debug("%s: Unsupported cmd=%u\n", __func__, cmd);
+		return -EINVAL;
+
+	} else if (cmd != ND_CMD_CALL) {
+
+		return cmd;
+
+	} else if (buf_len < sizeof(struct nd_pkg_papr_scm)) {
+
+		pr_debug("%s: Invalid pkg size=%u\n", __func__, buf_len);
+		return -EINVAL;
+
+	} else if (pkg->hdr.nd_family != NVDIMM_FAMILY_PAPR) {
+
+		pr_debug("%s: Invalid pkg family=0x%llx\n", __func__,
+			 pkg->hdr.nd_family);
+		return -EINVAL;
+
+	} else if (pkg->hdr.nd_command <= DSM_PAPR_MIN ||
+		   pkg->hdr.nd_command >= DSM_PAPR_MAX) {
+
+		/* for unknown subcommands return ND_CMD_CALL */
+		pr_debug("%s: Unknown sub-command=0x%llx\n", __func__,
+			 pkg->hdr.nd_command);
+		return ND_CMD_CALL;
+	}
+
+	/* Return the DSM_PAPR_SCM_* command */
+	return pkg->hdr.nd_command;
+}
+
 int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
 	struct nd_cmd_get_config_size *get_size_hdr;
 	struct papr_scm_priv *p;
+	struct nd_pkg_papr_scm *call_pkg = NULL;
+	int cmd_in, rc;
 
-	/* Only dimm-specific calls are supported atm */
-	if (!nvdimm)
-		return -EINVAL;
+	/* Use a local variable in case cmd_rc pointer is NULL */
+	if (cmd_rc == NULL)
+		cmd_rc = &rc;
+
+	cmd_in = cmd_to_func(nvdimm, cmd, buf, buf_len);
+	if (cmd_in < 0) {
+		pr_debug("%s: Invalid cmd=%u. Err=%d\n", __func__, cmd, cmd_in);
+		return cmd_in;
+	}
 
 	p = nvdimm_provider_data(nvdimm);
 
-	switch (cmd) {
+	switch (cmd_in) {
 	case ND_CMD_GET_CONFIG_SIZE:
 		get_size_hdr = buf;
 
@@ -333,13 +407,21 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		*cmd_rc = papr_scm_meta_set(p, buf);
 		break;
 
+	case ND_CMD_CALL:
+		/* This happens if subcommand package sanity fails */
+		call_pkg = (struct nd_pkg_papr_scm *) buf;
+		call_pkg->cmd_status = -ENOENT;
+		*cmd_rc = 0;
+		break;
+
 	default:
-		return -EINVAL;
+		dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
+		*cmd_rc = -EINVAL;
 	}
 
 	dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc);
 
-	return 0;
+	return *cmd_rc;
 }
 
 static inline int papr_scm_node(int node)
-- 
2.24.1


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

* [RFC PATCH 5/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
                   ` (3 preceding siblings ...)
  2020-01-29 15:28 ` [RFC PATCH 4/6] powerpc/papr_scm: Add support for handling PAPR DSM commands Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  2020-01-29 15:28 ` [RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS Vaibhav Jain
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

The DSM 'DSM_PAPR_SCM_HEALTH' should return the health-bitmap and
health-valid-bitmap information for a dimm back to userspace in
response to ND_CMD_CALL.

This patch implements this DSM by implementing a new function
papr_scm_get_health() that queries the DIMM health information and
then copies these bitmaps to the package payload whose layout is
defined by 'struct papr_scm_ndctl_health'.

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c | 46 +++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index e1a2c0e61077..6c0bc8f027db 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -33,9 +33,16 @@
  */
 enum {
 	DSM_PAPR_MIN =  0x10000,
+	DSM_PAPR_SCM_HEALTH,
 	DSM_PAPR_MAX,
 };
 
+/* Struct as returned by kernel in response to PAPR_DSM_PAPR_SMART_HEALTH */
+struct papr_scm_ndctl_health {
+	__be64 health_bitmap;
+	__be64 health_bitmap_valid;
+} __packed;
+
 /* Payload expected with ND_CMD_CALL ioctl from libnvdimm */
 struct nd_pkg_papr_scm {
 	struct nd_cmd_pkg hdr;		/* Package header containing sub-cmd */
@@ -369,6 +376,40 @@ static int cmd_to_func(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 	return pkg->hdr.nd_command;
 }
 
+/* Fetch the DIMM health info and populate it in provided papr_scm package */
+static int papr_scm_get_health(struct papr_scm_priv *p,
+			       struct nd_pkg_papr_scm *pkg)
+{
+	int rc;
+	struct papr_scm_ndctl_health *health =
+		(struct papr_scm_ndctl_health *)pkg->payload;
+
+	pkg->hdr.nd_fw_size = sizeof(struct papr_scm_ndctl_health);
+
+	if (pkg->hdr.nd_size_out < sizeof(struct papr_scm_ndctl_health)) {
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	rc = drc_pmem_query_health(p);
+	if (rc)
+		goto out;
+
+	/* Copy the health data to the payload */
+	health->health_bitmap = p->health_bitmap;
+	health->health_bitmap_valid = p->health_bitmap_valid;
+
+out:
+	/*
+	 * Put the error in out package and return success from function
+	 * so that errors if any are propogated back to userspace.
+	 */
+	pkg->cmd_status = rc;
+	dev_dbg(&p->pdev->dev, "%s completion code = %d\n", __func__, rc);
+
+	return 0;
+}
+
 int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
@@ -414,6 +455,11 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		*cmd_rc = 0;
 		break;
 
+	case DSM_PAPR_SCM_HEALTH:
+		call_pkg = (struct nd_pkg_papr_scm *) buf;
+		*cmd_rc = papr_scm_get_health(p, call_pkg);
+		break;
+
 	default:
 		dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
 		*cmd_rc = -EINVAL;
-- 
2.24.1


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

* [RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS
  2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
                   ` (4 preceding siblings ...)
  2020-01-29 15:28 ` [RFC PATCH 5/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH Vaibhav Jain
@ 2020-01-29 15:28 ` Vaibhav Jain
  5 siblings, 0 replies; 7+ messages in thread
From: Vaibhav Jain @ 2020-01-29 15:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Vaibhav Jain, Oliver O'Halloran, Alastair D'Silva,
	Aneesh Kumar K . V

The DSM 'DSM_PAPR_SCM_STATS' should return the PAPR defined buffer
that holds various dimm performance attributes as defined in Ref[1]
back to user-space in response to ND_CMD_CALL.

Presently the module doesn't interpret nor consume these stat as they
are only intended to be consumer and reported by
'libndctl'[2]. PAPR sped [1] states that input buffer to be provided
to H_SCM_PERFORMANCE_HEALTH hcall should be 4KiB in size. However due
to limitations of the libnvdimm envelop (which is 256 bytes in size)
such a large buffer cannot be copied back to user-space.

Hence we do an optimization of querying the size of the output buffer
from H_SCM_PERFORMANCE_HEALTH hcall and copy only the needed portion
of the buffer to the user-space payload package.

This patch implements this DSM by implementing a new function
papr_scm_get_stats that queries the DIMM stat information and then
copies PHYP provided buffer that holds these stat attributes to the
package payload whose layout is defined by 'struct
papr_scm_perf_stats'

References:
[1]: https://patchwork.ozlabs.org/patch/1154292/
[2]: https://github.com/pmem/ndctl

Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c | 51 +++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 6c0bc8f027db..ac50968453b0 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -34,6 +34,7 @@
 enum {
 	DSM_PAPR_MIN =  0x10000,
 	DSM_PAPR_SCM_HEALTH,
+	DSM_PAPR_SCM_STATS,
 	DSM_PAPR_MAX,
 };
 
@@ -410,6 +411,51 @@ static int papr_scm_get_health(struct papr_scm_priv *p,
 	return 0;
 }
 
+/* Fetch the DIMM stats and populate it in provided papr_scm package */
+static int papr_scm_get_stats(struct papr_scm_priv *p,
+			      struct nd_pkg_papr_scm *pkg)
+{
+	struct papr_scm_perf_stats *retbuffer;
+	int rc;
+	size_t copysize;
+
+	/* Return buffer for phyp where stats are written */
+	retbuffer = kzalloc(PAPR_SCM_MAX_PERF_STAT, GFP_KERNEL);
+
+	if (!retbuffer)
+		return -ENOMEM;
+
+	rc = drc_pmem_query_stats(p, retbuffer);
+	if (rc)
+		goto out;
+
+	/*
+	 * Parse the retbuffer, fetch the size returned and return the
+	 * first nd_size_out bytes back to userspce.
+	 */
+	pkg->hdr.nd_fw_size = be16_to_cpu(retbuffer->size);
+	copysize = min_t(__u32, pkg->hdr.nd_fw_size, pkg->hdr.nd_size_out);
+
+	memcpy(pkg->payload, retbuffer, copysize);
+
+	/* Verify if the returned buffer was copied completely */
+	if (pkg->hdr.nd_fw_size > copysize) {
+		rc = -ENOSPC;
+		goto out;
+	}
+
+out:
+	kfree(retbuffer);
+	/*
+	 * Put the error in out package and return success from function
+	 * so that errors if any are propogated back to userspace.
+	 */
+	pkg->cmd_status = rc;
+	dev_dbg(&p->pdev->dev, "%s completion code = %d\n", __func__, rc);
+
+	return 0;
+}
+
 int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
@@ -460,6 +506,11 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		*cmd_rc = papr_scm_get_health(p, call_pkg);
 		break;
 
+	case DSM_PAPR_SCM_STATS:
+		call_pkg = (struct nd_pkg_papr_scm *) buf;
+		*cmd_rc = papr_scm_get_stats(p, call_pkg);
+		break;
+
 	default:
 		dev_dbg(&p->pdev->dev, "Unknown command = %d\n", cmd_in);
 		*cmd_rc = -EINVAL;
-- 
2.24.1


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

end of thread, other threads:[~2020-01-29 15:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-29 15:28 [RFC PATCH 0/6] powerpc/papr_scm: Implement support for reporting DIMM health and stats Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 1/6] powerpc/papr_scm: Provide support for fetching dimm health information Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 2/6] powerpc/papr_scm: Fetch dimm performance stats from PHYP Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 3/6] UAPI: ndctl: Introduce NVDIMM_FAMILY_PAPR as a new NVDIMM DSM family Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 4/6] powerpc/papr_scm: Add support for handling PAPR DSM commands Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 5/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_HEALTH Vaibhav Jain
2020-01-29 15:28 ` [RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS Vaibhav Jain

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.