* [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