@@ -352,6 +352,22 @@ static int dimm_inject_smart(struct ndctl_dimm *dimm)
struct json_object *jdimm;
int rc;
+ rc = ndctl_dimm_smart_inject_supported(dimm);
+ switch (rc) {
+ case -ENOTTY:
+ error("%s: smart injection not supported by ndctl.",
+ ndctl_dimm_get_devname(dimm));
+ return rc;
+ case -EOPNOTSUPP:
+ error("%s: smart injection not supported by the kernel",
+ ndctl_dimm_get_devname(dimm));
+ return rc;
+ case -EIO:
+ error("%s: smart injection not supported by either platform firmware or the kernel.",
+ ndctl_dimm_get_devname(dimm));
+ return rc;
+ }
+
if (sctx.op_mask & (1 << OP_SET)) {
rc = smart_set_thresh(dimm);
if (rc)
@@ -362,6 +362,23 @@ static int intel_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd,
return 0;
}
+static int intel_dimm_smart_inject_supported(struct ndctl_dimm *dimm)
+{
+ struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) {
+ dbg(ctx, "unsupported cmd: %d\n", ND_CMD_CALL);
+ return -EOPNOTSUPP;
+ }
+
+ if (!test_dimm_dsm(dimm, ND_INTEL_SMART_INJECT)) {
+ dbg(ctx, "smart injection functions unsupported\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static const char *intel_cmd_desc(int fn)
{
static const char *descs[] = {
@@ -714,6 +731,7 @@ struct ndctl_dimm_ops * const intel_dimm_ops = &(struct ndctl_dimm_ops) {
.smart_inject_spares = intel_cmd_smart_inject_spares,
.smart_inject_fatal = intel_cmd_smart_inject_fatal,
.smart_inject_unsafe_shutdown = intel_cmd_smart_inject_unsafe_shutdown,
+ .smart_inject_supported = intel_dimm_smart_inject_supported,
.new_fw_get_info = intel_dimm_cmd_new_fw_get_info,
.fw_info_get_storage_size = intel_cmd_fw_info_get_storage_size,
.fw_info_get_max_send_len = intel_cmd_fw_info_get_max_send_len,
@@ -367,3 +367,8 @@ global:
ndctl_namespace_uninject_error2;
ndctl_cmd_ars_stat_get_flag_overflow;
} LIBNDCTL_15;
+
+LIBNDCTL_17 {
+global:
+ ndctl_dimm_smart_inject_supported;
+} LIBNDCTL_16;
@@ -311,6 +311,7 @@ struct ndctl_dimm_ops {
int (*smart_inject_spares)(struct ndctl_cmd *, bool, unsigned int);
int (*smart_inject_fatal)(struct ndctl_cmd *, bool);
int (*smart_inject_unsafe_shutdown)(struct ndctl_cmd *, bool);
+ int (*smart_inject_supported)(struct ndctl_dimm *);
struct ndctl_cmd *(*new_fw_get_info)(struct ndctl_dimm *);
unsigned int (*fw_info_get_storage_size)(struct ndctl_cmd *);
unsigned int (*fw_info_get_max_send_len)(struct ndctl_cmd *);
@@ -172,3 +172,13 @@ ndctl_dimm_cmd_new_ack_shutdown_count(struct ndctl_dimm *dimm)
else
return NULL;
}
+
+NDCTL_EXPORT int ndctl_dimm_smart_inject_supported(struct ndctl_dimm *dimm)
+{
+ struct ndctl_dimm_ops *ops = dimm->ops;
+
+ if (ops && ops->smart_inject_supported)
+ return ops->smart_inject_supported(dimm);
+ else
+ return -ENOTTY;
+}
@@ -279,6 +279,7 @@ int ndctl_cmd_smart_inject_spares(struct ndctl_cmd *cmd, bool enable,
unsigned int spares);
int ndctl_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable);
int ndctl_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd, bool enable);
+int ndctl_dimm_smart_inject_supported(struct ndctl_dimm *dimm);
struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(struct ndctl_dimm *dimm,
unsigned int opcode, size_t input_size, size_t output_size);
Add an API to check whether smart injection is supported, and add an intel-dsm implementation for it. Use this check in the ndctl inject-smart command. Reported-by: Leszek Lugin <leszek.lugin@intel.com> Cc: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com> --- ndctl/inject-smart.c | 16 ++++++++++++++++ ndctl/lib/intel.c | 18 ++++++++++++++++++ ndctl/lib/libndctl.sym | 5 +++++ ndctl/lib/private.h | 1 + ndctl/lib/smart.c | 10 ++++++++++ ndctl/libndctl.h | 1 + 6 files changed, 51 insertions(+) v2: - Fix the supported check to only use the command DSM instead of all its internal flags (which are not commands by themselves). - Improve readability of the DSM test (Dan)