[RFC PATCH 6/6] powerpc/papr_scm: Implement support for DSM_PAPR_SCM_STATS
From: Vaibhav Jain <hidden>
Date: 2020-01-29 15:42:55
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Linus Torvalds
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 <redacted> --- 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