Message ID | 20200220095805.197229-9-vaibhav@linux.ibm.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | powerpc/papr_scm: Add support for reporting nvdimm health | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (65b2623f395a4e25ab3ff4cff1c9c7623619a22d) |
snowpatch_ozlabs/build-ppc64le | success | Build succeeded |
snowpatch_ozlabs/build-ppc64be | success | Build succeeded |
snowpatch_ozlabs/build-ppc64e | success | Build succeeded |
snowpatch_ozlabs/build-pmac32 | success | Build succeeded |
snowpatch_ozlabs/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 85 lines checked |
snowpatch_ozlabs/needsstable | success | Patch has no Fixes tags |
Vaibhav Jain <vaibhav@linux.ibm.com> writes: > The DSM 'DSM_PAPR_SCM_HEALTH' should return a 'struct > nd_papr_scm_dimm_health_stat' containing information in dimm health back > to user space in response to ND_CMD_CALL. We implement 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'. > > The patch also handle cases where in future versions of 'struct > papr_scm_ndctl_health' may want to return more health > information. Such payload envelops will contain appropriate version > information in 'struct nd_papr_scm_cmd_pkg.payload_version'. The patch > takes care of only returning the sub-data corresponding to the payload > version requested. Please see the comments in papr_scm_get_health() > for how this is done. > > Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com> > --- > arch/powerpc/platforms/pseries/papr_scm.c | 73 +++++++++++++++++++++++ > 1 file changed, 73 insertions(+) > > diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c > index 29f38246c59f..bf81acb0bf3f 100644 > --- a/arch/powerpc/platforms/pseries/papr_scm.c > +++ b/arch/powerpc/platforms/pseries/papr_scm.c > @@ -415,6 +415,74 @@ 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. > + * Since the caller can request a different version of payload and each new > + * version of struct nd_papr_scm_dimm_health_stat is a proper-subset of > + * previous version hence we return a subset of the cached 'struct > + * nd_papr_scm_dimm_health_stat' depending on the payload version requested. > + */ > +static int papr_scm_get_health(struct papr_scm_priv *p, > + struct nd_papr_scm_cmd_pkg *pkg) > +{ > + int rc; > + size_t copysize; > + /* Map version to number of bytes to be copied to payload */ > + const size_t copysizes[] = { > + [1] = > + sizeof(struct nd_papr_scm_dimm_health_stat_v1), > + > + /* This should always be preset */ > + [ND_PAPR_SCM_DIMM_HEALTH_VERSION] = > + sizeof(struct nd_papr_scm_dimm_health_stat), > + }; We will not be able to determine that during build. For performance hcall to run LPAR should be privileged. ie, even if the kernel supports v2 version of the health information, it may only be able to return v1 version of the health because LPAR performance stat hcall failed. -aneesh
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 29f38246c59f..bf81acb0bf3f 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -415,6 +415,74 @@ 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. + * Since the caller can request a different version of payload and each new + * version of struct nd_papr_scm_dimm_health_stat is a proper-subset of + * previous version hence we return a subset of the cached 'struct + * nd_papr_scm_dimm_health_stat' depending on the payload version requested. + */ +static int papr_scm_get_health(struct papr_scm_priv *p, + struct nd_papr_scm_cmd_pkg *pkg) +{ + int rc; + size_t copysize; + /* Map version to number of bytes to be copied to payload */ + const size_t copysizes[] = { + [1] = + sizeof(struct nd_papr_scm_dimm_health_stat_v1), + + /* This should always be preset */ + [ND_PAPR_SCM_DIMM_HEALTH_VERSION] = + sizeof(struct nd_papr_scm_dimm_health_stat), + }; + + rc = drc_pmem_query_health(p); + if (rc) + goto out; + /* + * If the requested payload version is greater than one we know + * aboute, return the payload version we know about and let + * caller/userspace handle the mess. + */ + if (pkg->payload_version > ND_PAPR_SCM_DIMM_HEALTH_VERSION) + pkg->payload_version = ND_PAPR_SCM_DIMM_HEALTH_VERSION; + + copysize = copysizes[pkg->payload_version]; + if (!copysize) { + dev_dbg(&p->pdev->dev, "%s Unsupported payload version=0x%x\n", + __func__, pkg->payload_version); + rc = -ENOSPC; + goto out; + } + + if (pkg->hdr.nd_size_out < copysize) { + dev_dbg(&p->pdev->dev, "%s Payload not large enough\n", + __func__); + dev_dbg(&p->pdev->dev, "%s Expected %lu, available %u\n", + __func__, copysize, pkg->hdr.nd_size_out); + rc = -ENOSPC; + goto out; + } + + dev_dbg(&p->pdev->dev, "%s Copying payload size=%lu version=0x%x\n", + __func__, copysize, pkg->payload_version); + + /* Copy a subset of health struct based on copysize */ + memcpy(papr_scm_pcmd_to_payload(pkg), &p->health, copysize); + pkg->hdr.nd_fw_size = copysize; + +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) { @@ -460,6 +528,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 = nd_to_papr_cmd_pkg(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;
The DSM 'DSM_PAPR_SCM_HEALTH' should return a 'struct nd_papr_scm_dimm_health_stat' containing information in dimm health back to user space in response to ND_CMD_CALL. We implement 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'. The patch also handle cases where in future versions of 'struct papr_scm_ndctl_health' may want to return more health information. Such payload envelops will contain appropriate version information in 'struct nd_papr_scm_cmd_pkg.payload_version'. The patch takes care of only returning the sub-data corresponding to the payload version requested. Please see the comments in papr_scm_get_health() for how this is done. Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com> --- arch/powerpc/platforms/pseries/papr_scm.c | 73 +++++++++++++++++++++++ 1 file changed, 73 insertions(+)