@@ -36,6 +36,12 @@ static struct ndctl_cmd *hpe1_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
return NULL;
}
+ if (test_dimm_dsm(dimm, NDN_HPE1_CMD_SMART)
+ == DIMM_DSM_UNSUPPORTED) {
+ dbg(ctx, "unsupported function\n");
+ return NULL;
+ }
+
size = sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1);
cmd = calloc(1, size);
if (!cmd)
@@ -214,6 +220,12 @@ static struct ndctl_cmd *hpe1_dimm_cmd_new_smart_threshold(struct ndctl_dimm *di
return NULL;
}
+ if (test_dimm_dsm(dimm, NDN_HPE1_CMD_SMART_THRESHOLD)
+ == DIMM_DSM_UNSUPPORTED) {
+ dbg(ctx, "unsupported function\n");
+ return NULL;
+ }
+
size = sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1);
cmd = calloc(1, size);
if (!cmd)
@@ -1232,6 +1232,7 @@ static void *add_dimm(void *parent, int id, const char *dimm_base)
dimm->manufacturing_date = -1;
dimm->manufacturing_location = -1;
dimm->cmd_family = -1;
+ dimm->nfit_dsm_mask = ULONG_MAX;
for (i = 0; i < formats; i++)
dimm->format[i] = -1;
@@ -1310,6 +1311,10 @@ static void *add_dimm(void *parent, int id, const char *dimm_base)
if (dimm->cmd_family == NVDIMM_FAMILY_MSFT)
dimm->smart_ops = msft_smart_ops;
+ sprintf(path, "%s/nfit/dsm_mask", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
+ dimm->nfit_dsm_mask = strtoul(buf, NULL, 0);
+
dimm->formats = formats;
sprintf(path, "%s/nfit/format", dimm_base);
if (sysfs_read_attr(ctx, path, buf) == 0)
@@ -35,6 +35,11 @@ static struct ndctl_cmd *msft_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
return NULL;
}
+ if (test_dimm_dsm(dimm, NDN_MSFT_CMD_SMART) == DIMM_DSM_UNSUPPORTED) {
+ dbg(ctx, "unsupported function\n");
+ return NULL;
+ }
+
size = sizeof(*cmd) + sizeof(struct ndn_pkg_msft);
cmd = calloc(1, size);
if (!cmd)
@@ -77,6 +77,7 @@ struct ndctl_dimm {
unsigned char manufacturing_location;
unsigned long cmd_family;
unsigned long cmd_mask;
+ unsigned long nfit_dsm_mask;
char *unique_id;
char *dimm_path;
char *dimm_buf;
@@ -102,6 +103,21 @@ struct ndctl_dimm {
int format[0];
};
+enum dsm_support {
+ DIMM_DSM_UNSUPPORTED, /* don't attempt command */
+ DIMM_DSM_SUPPORTED, /* good to go */
+ DIMM_DSM_UNKNOWN, /* try ND_CMD_CALL on older kernels */
+};
+
+static inline enum dsm_support test_dimm_dsm(struct ndctl_dimm *dimm, int fn)
+{
+ if (dimm->nfit_dsm_mask == ULONG_MAX) {
+ return DIMM_DSM_UNKNOWN;
+ } else if (dimm->nfit_dsm_mask & (1 << fn))
+ return DIMM_DSM_SUPPORTED;
+ return DIMM_DSM_UNSUPPORTED;
+}
+
void region_flag_refresh(struct ndctl_region *region);
/**
Validate vendor specific ACPI-defined command implementations against the published dsm_mask. Cc: Lijun Pan <Lijun.Pan@dell.com> Cc: Jerry Hoemann <jerry.hoemann@hpe.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- ndctl/lib/hpe1.c | 12 ++++++++++++ ndctl/lib/libndctl.c | 5 +++++ ndctl/lib/msft.c | 5 +++++ ndctl/lib/private.h | 16 ++++++++++++++++ 4 files changed, 38 insertions(+)