libnvdimm, test: add mock SMART data payload

Provide simulated SMART data to enable the ndctl implementation of SMART
data retrieval and parsing.

The payload is defined here, "Section 4.1 SMART and Health Info
(Function Index 1)":

    http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2016-04-05 17:40:52 -07:00
parent 8cc6ddfcaf
commit baa51277cf
3 changed files with 82 additions and 1 deletions

View File

@ -783,6 +783,9 @@ int __init nvdimm_bus_init(void)
{
int rc;
BUILD_BUG_ON(sizeof(struct nd_smart_payload) != 128);
BUILD_BUG_ON(sizeof(struct nd_smart_threshold_payload) != 8);
rc = bus_register(&nvdimm_bus_type);
if (rc)
return rc;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2015, Intel Corporation.
* Copyright (c) 2014-2016, 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,
@ -20,11 +20,45 @@ struct nd_cmd_smart {
__u8 data[128];
} __packed;
#define ND_SMART_HEALTH_VALID (1 << 0)
#define ND_SMART_TEMP_VALID (1 << 1)
#define ND_SMART_SPARES_VALID (1 << 2)
#define ND_SMART_ALARM_VALID (1 << 3)
#define ND_SMART_USED_VALID (1 << 4)
#define ND_SMART_SHUTDOWN_VALID (1 << 5)
#define ND_SMART_VENDOR_VALID (1 << 6)
#define ND_SMART_TEMP_TRIP (1 << 0)
#define ND_SMART_SPARE_TRIP (1 << 1)
#define ND_SMART_NON_CRITICAL_HEALTH (1 << 0)
#define ND_SMART_CRITICAL_HEALTH (1 << 1)
#define ND_SMART_FATAL_HEALTH (1 << 2)
struct nd_smart_payload {
__u32 flags;
__u8 reserved0[4];
__u8 health;
__u16 temperature;
__u8 spares;
__u8 alarm_flags;
__u8 life_used;
__u8 shutdown_state;
__u8 reserved1;
__u32 vendor_size;
__u8 vendor_data[108];
} __packed;
struct nd_cmd_smart_threshold {
__u32 status;
__u8 data[8];
} __packed;
struct nd_smart_threshold_payload {
__u16 alarm_control;
__u16 temperature;
__u8 spares;
__u8 reserved[3];
} __packed;
struct nd_cmd_dimm_flags {
__u32 status;
__u32 flags;

View File

@ -330,6 +330,42 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
return 0;
}
static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
{
static const struct nd_smart_payload smart_data = {
.flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
| ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
| ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
.health = ND_SMART_NON_CRITICAL_HEALTH,
.temperature = 23 * 16,
.spares = 75,
.alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
.life_used = 5,
.shutdown_state = 0,
.vendor_size = 0,
};
if (buf_len < sizeof(*smart))
return -EINVAL;
memcpy(smart->data, &smart_data, sizeof(smart_data));
return 0;
}
static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
unsigned int buf_len)
{
static const struct nd_smart_threshold_payload smart_t_data = {
.alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
.temperature = 40 * 16,
.spares = 5,
};
if (buf_len < sizeof(*smart_t))
return -EINVAL;
memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
return 0;
}
static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc)
@ -368,6 +404,12 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
rc = nfit_test_cmd_set_config_data(buf, buf_len,
t->label[i]);
break;
case ND_CMD_SMART:
rc = nfit_test_cmd_smart(buf, buf_len);
break;
case ND_CMD_SMART_THRESHOLD:
rc = nfit_test_cmd_smart_threshold(buf, buf_len);
break;
default:
return -ENOTTY;
}
@ -1254,10 +1296,12 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_dsm_force_en);
}
static void nfit_test1_setup(struct nfit_test *t)