blob: 49a436026ab6f74b321456ba6b7b11883d38e462 [file] [log] [blame]
/*
* Copyright (c) 2016-2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*/
#include <stdlib.h>
#include <limits.h>
#include <util/log.h>
#include <ndctl/libndctl.h>
#include "private.h"
static struct ndctl_cmd *alloc_intel_cmd(struct ndctl_dimm *dimm,
unsigned func, size_t in_size, size_t out_size)
{
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
struct ndctl_cmd *cmd;
size_t size;
if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) {
dbg(ctx, "unsupported cmd: %d\n", ND_CMD_CALL);
return NULL;
}
if (test_dimm_dsm(dimm, func) == DIMM_DSM_UNSUPPORTED) {
dbg(ctx, "unsupported function: %d\n", func);
return NULL;
}
size = sizeof(*cmd) + sizeof(struct nd_pkg_intel) + in_size + out_size;
cmd = calloc(1, size);
if (!cmd)
return NULL;
cmd->dimm = dimm;
ndctl_cmd_ref(cmd);
cmd->type = ND_CMD_CALL;
cmd->size = size;
cmd->status = 1;
*(cmd->intel) = (struct nd_pkg_intel) {
.gen = {
.nd_family = NVDIMM_FAMILY_INTEL,
.nd_command = func,
.nd_size_in = in_size,
.nd_size_out = out_size,
},
};
return cmd;
}
static struct ndctl_cmd *intel_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_smart) == 132);
cmd = alloc_intel_cmd(dimm, ND_INTEL_SMART,
0, sizeof(cmd->intel->smart));
if (!cmd)
return NULL;
cmd->firmware_status = &cmd->intel->smart.status;
return cmd;
}
static int intel_smart_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 0
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_SMART)
return cmd->status < 0 ? cmd->status : -EINVAL;
return 0;
}
#define intel_smart_get_field(cmd, field) \
static unsigned int intel_cmd_smart_get_##field(struct ndctl_cmd *cmd) \
{ \
if (intel_smart_valid(cmd) < 0) \
return UINT_MAX; \
return cmd->intel->smart.field; \
}
static unsigned int intel_cmd_smart_get_flags(struct ndctl_cmd *cmd)
{
unsigned int flags = 0;
unsigned int intel_flags;
if (intel_smart_valid(cmd) < 0)
return 0;
/* translate intel specific flags to libndctl api smart flags */
intel_flags = cmd->intel->smart.flags;
if (intel_flags & ND_INTEL_SMART_HEALTH_VALID)
flags |= ND_SMART_HEALTH_VALID;
if (intel_flags & ND_INTEL_SMART_SPARES_VALID)
flags |= ND_SMART_SPARES_VALID;
if (intel_flags & ND_INTEL_SMART_USED_VALID)
flags |= ND_SMART_USED_VALID;
if (intel_flags & ND_INTEL_SMART_MTEMP_VALID)
flags |= ND_SMART_MTEMP_VALID;
if (intel_flags & ND_INTEL_SMART_CTEMP_VALID)
flags |= ND_SMART_CTEMP_VALID;
if (intel_flags & ND_INTEL_SMART_SHUTDOWN_COUNT_VALID)
flags |= ND_SMART_SHUTDOWN_COUNT_VALID;
if (intel_flags & ND_INTEL_SMART_AIT_STATUS_VALID)
flags |= ND_SMART_AIT_STATUS_VALID;
if (intel_flags & ND_INTEL_SMART_PTEMP_VALID)
flags |= ND_SMART_PTEMP_VALID;
if (intel_flags & ND_INTEL_SMART_ALARM_VALID)
flags |= ND_SMART_ALARM_VALID;
if (intel_flags & ND_INTEL_SMART_SHUTDOWN_VALID)
flags |= ND_SMART_SHUTDOWN_VALID;
if (intel_flags & ND_INTEL_SMART_VENDOR_VALID)
flags |= ND_SMART_VENDOR_VALID;
return flags;
}
static unsigned int intel_cmd_smart_get_health(struct ndctl_cmd *cmd)
{
unsigned int health = 0;
unsigned int intel_health;
if (intel_smart_valid(cmd) < 0)
return 0;
intel_health = cmd->intel->smart.health;
if (intel_health & ND_INTEL_SMART_NON_CRITICAL_HEALTH)
health |= ND_SMART_NON_CRITICAL_HEALTH;
if (intel_health & ND_INTEL_SMART_CRITICAL_HEALTH)
health |= ND_SMART_CRITICAL_HEALTH;
if (intel_health & ND_INTEL_SMART_FATAL_HEALTH)
health |= ND_SMART_FATAL_HEALTH;
return health;
}
intel_smart_get_field(cmd, media_temperature)
intel_smart_get_field(cmd, ctrl_temperature)
intel_smart_get_field(cmd, spares)
intel_smart_get_field(cmd, alarm_flags)
intel_smart_get_field(cmd, life_used)
intel_smart_get_field(cmd, shutdown_state)
intel_smart_get_field(cmd, shutdown_count)
intel_smart_get_field(cmd, vendor_size)
static unsigned char *intel_cmd_smart_get_vendor_data(struct ndctl_cmd *cmd)
{
if (intel_smart_valid(cmd) < 0)
return NULL;
return cmd->intel->smart.vendor_data;
}
static int intel_smart_threshold_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 0
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_SMART_THRESHOLD)
return cmd->status < 0 ? cmd->status : -EINVAL;
return 0;
}
#define intel_smart_threshold_get_field(cmd, field) \
static unsigned int intel_cmd_smart_threshold_get_##field( \
struct ndctl_cmd *cmd) \
{ \
if (intel_smart_threshold_valid(cmd) < 0) \
return UINT_MAX; \
return cmd->intel->thresh.field; \
}
static unsigned int intel_cmd_smart_threshold_get_alarm_control(
struct ndctl_cmd *cmd)
{
struct nd_intel_smart_threshold *thresh;
unsigned int flags = 0;
if (intel_smart_threshold_valid(cmd) < 0)
return 0;
thresh = &cmd->intel->thresh;
if (thresh->alarm_control & ND_INTEL_SMART_SPARE_TRIP)
flags |= ND_SMART_SPARE_TRIP;
if (thresh->alarm_control & ND_INTEL_SMART_TEMP_TRIP)
flags |= ND_SMART_TEMP_TRIP;
if (thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
flags |= ND_SMART_CTEMP_TRIP;
return flags;
}
intel_smart_threshold_get_field(cmd, media_temperature)
intel_smart_threshold_get_field(cmd, ctrl_temperature)
intel_smart_threshold_get_field(cmd, spares)
static struct ndctl_cmd *intel_dimm_cmd_new_smart_threshold(
struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_smart_threshold) == 12);
cmd = alloc_intel_cmd(dimm, ND_INTEL_SMART_THRESHOLD,
0, sizeof(cmd->intel->thresh));
if (!cmd)
return NULL;
cmd->firmware_status = &cmd->intel->thresh.status;
return cmd;
}
static struct ndctl_cmd *intel_dimm_cmd_new_smart_set_threshold(
struct ndctl_cmd *cmd_thresh)
{
struct ndctl_cmd *cmd;
struct nd_intel_smart_threshold *thresh;
struct nd_intel_smart_set_threshold *set_thresh;
BUILD_ASSERT(sizeof(struct nd_intel_smart_set_threshold) == 11);
if (intel_smart_threshold_valid(cmd_thresh) < 0)
return NULL;
cmd = alloc_intel_cmd(cmd_thresh->dimm, ND_INTEL_SMART_SET_THRESHOLD,
offsetof(typeof(*set_thresh), status), 4);
if (!cmd)
return NULL;
cmd->source = cmd_thresh;
ndctl_cmd_ref(cmd_thresh);
set_thresh = &cmd->intel->set_thresh;
thresh = &cmd_thresh->intel->thresh;
set_thresh->alarm_control = thresh->alarm_control;
set_thresh->spares = thresh->spares;
set_thresh->media_temperature = thresh->media_temperature;
set_thresh->ctrl_temperature = thresh->ctrl_temperature;
cmd->firmware_status = &set_thresh->status;
return cmd;
}
static int intel_smart_set_threshold_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 1
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_SMART_SET_THRESHOLD)
return -EINVAL;
return 0;
}
#define intel_smart_set_threshold_field(field) \
static int intel_cmd_smart_threshold_set_##field( \
struct ndctl_cmd *cmd, unsigned int val) \
{ \
if (intel_smart_set_threshold_valid(cmd) < 0) \
return -EINVAL; \
cmd->intel->set_thresh.field = val; \
return 0; \
}
static unsigned int intel_cmd_smart_threshold_get_supported_alarms(
struct ndctl_cmd *cmd)
{
if (intel_smart_set_threshold_valid(cmd) < 0)
return 0;
return ND_SMART_SPARE_TRIP | ND_SMART_MTEMP_TRIP
| ND_SMART_CTEMP_TRIP;
}
intel_smart_set_threshold_field(alarm_control)
intel_smart_set_threshold_field(spares)
intel_smart_set_threshold_field(media_temperature)
intel_smart_set_threshold_field(ctrl_temperature)
static int intel_smart_inject_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 1
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_SMART_INJECT)
return cmd->status < 0 ? cmd->status : -EINVAL;
return 0;
}
static struct ndctl_cmd *intel_new_smart_inject(struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_smart_inject) == 19);
cmd = alloc_intel_cmd(dimm, ND_INTEL_SMART_INJECT,
offsetof(struct nd_intel_smart_inject, status), 4);
if (!cmd)
return NULL;
cmd->firmware_status = &cmd->intel->inject.status;
return cmd;
}
static int intel_cmd_smart_inject_media_temperature(struct ndctl_cmd *cmd,
bool enable, unsigned int mtemp)
{
struct nd_intel_smart_inject *inj;
if (intel_smart_inject_valid(cmd) < 0)
return -EINVAL;
inj = &cmd->intel->inject;
inj->flags |= ND_INTEL_SMART_INJECT_MTEMP;
inj->mtemp_enable = enable == true;
inj->media_temperature = mtemp;
return 0;
}
static int intel_cmd_smart_inject_spares(struct ndctl_cmd *cmd,
bool enable, unsigned int spares)
{
struct nd_intel_smart_inject *inj;
if (intel_smart_inject_valid(cmd) < 0)
return -EINVAL;
inj = &cmd->intel->inject;
inj->flags |= ND_INTEL_SMART_INJECT_SPARE;
inj->spare_enable = enable == true;
inj->spares = spares;
return 0;
}
static int intel_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable)
{
struct nd_intel_smart_inject *inj;
if (intel_smart_inject_valid(cmd) < 0)
return -EINVAL;
inj = &cmd->intel->inject;
inj->flags |= ND_INTEL_SMART_INJECT_FATAL;
inj->fatal_enable = enable == true;
return 0;
}
static int intel_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd,
bool enable)
{
struct nd_intel_smart_inject *inj;
if (intel_smart_inject_valid(cmd) < 0)
return -EINVAL;
inj = &cmd->intel->inject;
inj->flags |= ND_INTEL_SMART_INJECT_SHUTDOWN;
inj->unsafe_shutdown_enable = enable == true;
return 0;
}
static const char *intel_cmd_desc(int fn)
{
static const char *descs[] = {
[ND_INTEL_SMART] = "smart",
[ND_INTEL_SMART_INJECT] = "smart_inject",
[ND_INTEL_SMART_THRESHOLD] = "smart_thresh",
[ND_INTEL_FW_GET_INFO] = "firmware_get_info",
[ND_INTEL_FW_START_UPDATE] = "firmware_start_update",
[ND_INTEL_FW_SEND_DATA] = "firmware_send_data",
[ND_INTEL_FW_FINISH_UPDATE] = "firmware_finish_update",
[ND_INTEL_FW_FINISH_STATUS_QUERY] = "firmware_finish_query",
[ND_INTEL_SMART_SET_THRESHOLD] = "smart_set_thresh",
};
const char *desc = descs[fn];
if (fn >= (int) ARRAY_SIZE(descs))
return "unknown";
if (!desc)
return "unknown";
return desc;
}
static struct ndctl_cmd *intel_dimm_cmd_new_fw_get_info(struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_info) == 44);
cmd = alloc_intel_cmd(dimm, ND_INTEL_FW_GET_INFO,
0, sizeof(cmd->intel->info));
if (!cmd)
return NULL;
cmd->firmware_status = &cmd->intel->info.status;
return cmd;
}
static int intel_fw_get_info_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 0
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_FW_GET_INFO)
return -EINVAL;
return 0;
}
#define intel_fw_info_get_field32(cmd, field) \
static unsigned int intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
if (intel_fw_get_info_valid(cmd) < 0) \
return UINT_MAX; \
return cmd->intel->info.field; \
}
#define intel_fw_info_get_field64(cmd, field) \
static unsigned long long intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
if (intel_fw_get_info_valid(cmd) < 0) \
return ULLONG_MAX; \
return cmd->intel->info.field; \
}
intel_fw_info_get_field32(cmd, storage_size)
intel_fw_info_get_field32(cmd, max_send_len)
intel_fw_info_get_field32(cmd, query_interval)
intel_fw_info_get_field32(cmd, max_query_time);
intel_fw_info_get_field64(cmd, run_version);
static unsigned long long intel_cmd_fw_info_get_updated_version(
struct ndctl_cmd *cmd)
{
if (intel_fw_get_info_valid(cmd) < 0)
return ULLONG_MAX;
return cmd->intel->info.updated_version;
}
static struct ndctl_cmd *intel_dimm_cmd_new_fw_start(struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_start) == 8);
cmd = alloc_intel_cmd(dimm, ND_INTEL_FW_START_UPDATE, 0,
sizeof(cmd->intel->start));
if (!cmd)
return NULL;
cmd->firmware_status = &cmd->intel->start.status;
return cmd;
}
static int intel_fw_start_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 0
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_FW_START_UPDATE)
return -EINVAL;
return 0;
}
static unsigned int intel_cmd_fw_start_get_context(struct ndctl_cmd *cmd)
{
if (intel_fw_start_valid(cmd) < 0)
return UINT_MAX;
return cmd->intel->start.context;
}
static struct ndctl_cmd *intel_dimm_cmd_new_fw_send(struct ndctl_cmd *start,
unsigned int offset, unsigned int len, void *data)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_send_data) == 12);
cmd = alloc_intel_cmd(start->dimm, ND_INTEL_FW_SEND_DATA,
sizeof(cmd->intel->send) + len, 4);
if (!cmd)
return NULL;
cmd->intel->send.context = start->intel->start.context;
cmd->intel->send.offset = offset;
cmd->intel->send.length = len;
memcpy(cmd->intel->send.data, data, len);
/* the last dword is reserved for status */
cmd->firmware_status =
(unsigned int *)(&cmd->intel->send.data[0] + len);
return cmd;
}
static struct ndctl_cmd *intel_dimm_cmd_new_fw_finish(struct ndctl_cmd *start)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_finish_update) == 12);
cmd = alloc_intel_cmd(start->dimm, ND_INTEL_FW_FINISH_UPDATE,
offsetof(struct nd_intel_fw_finish_update, status), 4);
if (!cmd)
return NULL;
cmd->intel->finish.context = start->intel->start.context;
cmd->intel->finish.ctrl_flags = 0;
cmd->firmware_status = &cmd->intel->finish.status;
return cmd;
}
static struct ndctl_cmd *intel_dimm_cmd_new_fw_abort(struct ndctl_cmd *start)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_finish_update) == 12);
cmd = alloc_intel_cmd(start->dimm, ND_INTEL_FW_FINISH_UPDATE,
sizeof(cmd->intel->finish) - 4, 4);
if (!cmd)
return NULL;
cmd->intel->finish.context = start->intel->start.context;
cmd->intel->finish.ctrl_flags = 1;
cmd->firmware_status = &cmd->intel->finish.status;
return cmd;
}
static struct ndctl_cmd *
intel_dimm_cmd_new_fw_finish_query(struct ndctl_cmd *start)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_fw_finish_query) == 16);
cmd = alloc_intel_cmd(start->dimm, ND_INTEL_FW_FINISH_STATUS_QUERY,
4, sizeof(cmd->intel->fquery) - 4);
if (!cmd)
return NULL;
cmd->intel->fquery.context = start->intel->start.context;
cmd->firmware_status = &cmd->intel->fquery.status;
return cmd;
}
static int intel_fw_fquery_valid(struct ndctl_cmd *cmd)
{
struct nd_pkg_intel *pkg = cmd->intel;
if (cmd->type != ND_CMD_CALL || cmd->status != 0
|| pkg->gen.nd_family != NVDIMM_FAMILY_INTEL
|| pkg->gen.nd_command != ND_INTEL_FW_FINISH_STATUS_QUERY)
return -EINVAL;
return 0;
}
static unsigned long long
intel_cmd_fw_fquery_get_fw_rev(struct ndctl_cmd *cmd)
{
if (intel_fw_fquery_valid(cmd) < 0)
return ULLONG_MAX;
return cmd->intel->fquery.updated_fw_rev;
}
static enum ND_FW_STATUS
intel_cmd_fw_xlat_extend_firmware_status(struct ndctl_cmd *cmd,
unsigned int status)
{
/*
* Note: the cases commented out are identical to the ones that are
* not. They are there for reference.
*/
switch (status & ND_INTEL_STATUS_EXTEND_MASK) {
case ND_INTEL_STATUS_START_BUSY:
/* case ND_INTEL_STATUS_SEND_CTXINVAL: */
/* case ND_INTEL_STATUS_FIN_CTXINVAL: */
/* case ND_INTEL_STATUS_FQ_CTXINVAL: */
if (cmd->intel->gen.nd_command == ND_INTEL_FW_START_UPDATE)
return FW_EBUSY;
else
return FW_EINVAL_CTX;
case ND_INTEL_STATUS_FIN_DONE:
/* case ND_INTEL_STATUS_FQ_BUSY: */
if (cmd->intel->gen.nd_command == ND_INTEL_FW_FINISH_UPDATE)
return FW_ALREADY_DONE;
else
return FW_EBUSY;
case ND_INTEL_STATUS_FIN_BAD:
/* case ND_INTEL_STATUS_FQ_BAD: */
return FW_EBADFW;
case ND_INTEL_STATUS_FIN_ABORTED:
/* case ND_INTEL_STATUS_FQ_ORDER: */
if (cmd->intel->gen.nd_command == ND_INTEL_FW_FINISH_UPDATE)
return FW_ABORTED;
else
return FW_ESEQUENCE;
}
return FW_EUNKNOWN;
}
static enum ND_FW_STATUS
intel_cmd_fw_xlat_firmware_status(struct ndctl_cmd *cmd)
{
unsigned int status = *cmd->firmware_status;
switch (status & ND_INTEL_STATUS_MASK) {
case ND_INTEL_STATUS_SUCCESS:
return FW_SUCCESS;
case ND_INTEL_STATUS_NOTSUPP:
return FW_ENOTSUPP;
case ND_INTEL_STATUS_NOTEXIST:
return FW_ENOTEXIST;
case ND_INTEL_STATUS_INVALPARM:
return FW_EINVAL;
case ND_INTEL_STATUS_HWERR:
return FW_EHWERR;
case ND_INTEL_STATUS_RETRY:
return FW_ERETRY;
case ND_INTEL_STATUS_EXTEND:
return intel_cmd_fw_xlat_extend_firmware_status(cmd, status);
case ND_INTEL_STATUS_NORES:
return FW_ENORES;
case ND_INTEL_STATUS_NOTREADY:
return FW_ENOTREADY;
}
return FW_EUNKNOWN;
}
static struct ndctl_cmd *
intel_dimm_cmd_new_lss(struct ndctl_dimm *dimm)
{
struct ndctl_cmd *cmd;
BUILD_ASSERT(sizeof(struct nd_intel_lss) == 5);
cmd = alloc_intel_cmd(dimm, ND_INTEL_ENABLE_LSS_STATUS, 1, 4);
if (!cmd)
return NULL;
cmd->intel->lss.enable = 1;
cmd->firmware_status = &cmd->intel->lss.status;
return cmd;
}
static int intel_dimm_fw_update_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_FW_GET_INFO) ==
DIMM_DSM_UNSUPPORTED ||
test_dimm_dsm(dimm, ND_INTEL_FW_START_UPDATE) ==
DIMM_DSM_UNSUPPORTED ||
test_dimm_dsm(dimm, ND_INTEL_FW_SEND_DATA) ==
DIMM_DSM_UNSUPPORTED ||
test_dimm_dsm(dimm, ND_INTEL_FW_FINISH_UPDATE) ==
DIMM_DSM_UNSUPPORTED ||
test_dimm_dsm(dimm, ND_INTEL_FW_FINISH_STATUS_QUERY) ==
DIMM_DSM_UNSUPPORTED) {
dbg(ctx, "unsupported function: %d\n",
ND_INTEL_FW_GET_INFO);
return -EIO;
}
return 0;
}
struct ndctl_dimm_ops * const intel_dimm_ops = &(struct ndctl_dimm_ops) {
.cmd_desc = intel_cmd_desc,
.new_smart = intel_dimm_cmd_new_smart,
.smart_get_flags = intel_cmd_smart_get_flags,
.smart_get_health = intel_cmd_smart_get_health,
.smart_get_media_temperature = intel_cmd_smart_get_media_temperature,
.smart_get_ctrl_temperature = intel_cmd_smart_get_ctrl_temperature,
.smart_get_spares = intel_cmd_smart_get_spares,
.smart_get_alarm_flags = intel_cmd_smart_get_alarm_flags,
.smart_get_life_used = intel_cmd_smart_get_life_used,
.smart_get_shutdown_state = intel_cmd_smart_get_shutdown_state,
.smart_get_shutdown_count = intel_cmd_smart_get_shutdown_count,
.smart_get_vendor_size = intel_cmd_smart_get_vendor_size,
.smart_get_vendor_data = intel_cmd_smart_get_vendor_data,
.new_smart_threshold = intel_dimm_cmd_new_smart_threshold,
.smart_threshold_get_alarm_control
= intel_cmd_smart_threshold_get_alarm_control,
.smart_threshold_get_media_temperature
= intel_cmd_smart_threshold_get_media_temperature,
.smart_threshold_get_ctrl_temperature
= intel_cmd_smart_threshold_get_ctrl_temperature,
.smart_threshold_get_spares = intel_cmd_smart_threshold_get_spares,
.new_smart_set_threshold = intel_dimm_cmd_new_smart_set_threshold,
.smart_threshold_get_supported_alarms
= intel_cmd_smart_threshold_get_supported_alarms,
.smart_threshold_set_alarm_control
= intel_cmd_smart_threshold_set_alarm_control,
.smart_threshold_set_media_temperature
= intel_cmd_smart_threshold_set_media_temperature,
.smart_threshold_set_ctrl_temperature
= intel_cmd_smart_threshold_set_ctrl_temperature,
.smart_threshold_set_spares = intel_cmd_smart_threshold_set_spares,
.new_smart_inject = intel_new_smart_inject,
.smart_inject_media_temperature = intel_cmd_smart_inject_media_temperature,
.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,
.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,
.fw_info_get_query_interval = intel_cmd_fw_info_get_query_interval,
.fw_info_get_max_query_time = intel_cmd_fw_info_get_max_query_time,
.fw_info_get_run_version = intel_cmd_fw_info_get_run_version,
.fw_info_get_updated_version = intel_cmd_fw_info_get_updated_version,
.new_fw_start_update = intel_dimm_cmd_new_fw_start,
.fw_start_get_context = intel_cmd_fw_start_get_context,
.new_fw_send = intel_dimm_cmd_new_fw_send,
.new_fw_finish = intel_dimm_cmd_new_fw_finish,
.new_fw_abort = intel_dimm_cmd_new_fw_abort,
.new_fw_finish_query = intel_dimm_cmd_new_fw_finish_query,
.fw_fquery_get_fw_rev = intel_cmd_fw_fquery_get_fw_rev,
.fw_xlat_firmware_status = intel_cmd_fw_xlat_firmware_status,
.new_ack_shutdown_count = intel_dimm_cmd_new_lss,
.fw_update_supported = intel_dimm_fw_update_supported,
};