Merge branch 'for-4.7/libnvdimm' into libnvdimm-for-next
This commit is contained in:
commit
2159669f58
|
@ -658,6 +658,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
|
||||||
if (!nfit_mem)
|
if (!nfit_mem)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
INIT_LIST_HEAD(&nfit_mem->list);
|
INIT_LIST_HEAD(&nfit_mem->list);
|
||||||
|
nfit_mem->acpi_desc = acpi_desc;
|
||||||
list_add(&nfit_mem->list, &acpi_desc->dimms);
|
list_add(&nfit_mem->list, &acpi_desc->dimms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,6 +842,18 @@ static ssize_t device_show(struct device *dev,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(device);
|
static DEVICE_ATTR_RO(device);
|
||||||
|
|
||||||
|
static int num_nvdimm_formats(struct nvdimm *nvdimm)
|
||||||
|
{
|
||||||
|
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
|
||||||
|
int formats = 0;
|
||||||
|
|
||||||
|
if (nfit_mem->memdev_pmem)
|
||||||
|
formats++;
|
||||||
|
if (nfit_mem->memdev_bdw)
|
||||||
|
formats++;
|
||||||
|
return formats;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t format_show(struct device *dev,
|
static ssize_t format_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -850,6 +863,55 @@ static ssize_t format_show(struct device *dev,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(format);
|
static DEVICE_ATTR_RO(format);
|
||||||
|
|
||||||
|
static ssize_t format1_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
u32 handle;
|
||||||
|
ssize_t rc = -ENXIO;
|
||||||
|
struct nfit_mem *nfit_mem;
|
||||||
|
struct nfit_memdev *nfit_memdev;
|
||||||
|
struct acpi_nfit_desc *acpi_desc;
|
||||||
|
struct nvdimm *nvdimm = to_nvdimm(dev);
|
||||||
|
struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
|
||||||
|
|
||||||
|
nfit_mem = nvdimm_provider_data(nvdimm);
|
||||||
|
acpi_desc = nfit_mem->acpi_desc;
|
||||||
|
handle = to_nfit_memdev(dev)->device_handle;
|
||||||
|
|
||||||
|
/* assumes DIMMs have at most 2 published interface codes */
|
||||||
|
mutex_lock(&acpi_desc->init_mutex);
|
||||||
|
list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
|
||||||
|
struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
|
||||||
|
struct nfit_dcr *nfit_dcr;
|
||||||
|
|
||||||
|
if (memdev->device_handle != handle)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
|
||||||
|
if (nfit_dcr->dcr->region_index != memdev->region_index)
|
||||||
|
continue;
|
||||||
|
if (nfit_dcr->dcr->code == dcr->code)
|
||||||
|
continue;
|
||||||
|
rc = sprintf(buf, "%#x\n", nfit_dcr->dcr->code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rc != ENXIO)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mutex_unlock(&acpi_desc->init_mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RO(format1);
|
||||||
|
|
||||||
|
static ssize_t formats_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct nvdimm *nvdimm = to_nvdimm(dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm));
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RO(formats);
|
||||||
|
|
||||||
static ssize_t serial_show(struct device *dev,
|
static ssize_t serial_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -879,6 +941,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = {
|
||||||
&dev_attr_vendor.attr,
|
&dev_attr_vendor.attr,
|
||||||
&dev_attr_device.attr,
|
&dev_attr_device.attr,
|
||||||
&dev_attr_format.attr,
|
&dev_attr_format.attr,
|
||||||
|
&dev_attr_formats.attr,
|
||||||
|
&dev_attr_format1.attr,
|
||||||
&dev_attr_serial.attr,
|
&dev_attr_serial.attr,
|
||||||
&dev_attr_rev_id.attr,
|
&dev_attr_rev_id.attr,
|
||||||
&dev_attr_flags.attr,
|
&dev_attr_flags.attr,
|
||||||
|
@ -889,11 +953,13 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj,
|
||||||
struct attribute *a, int n)
|
struct attribute *a, int n)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
struct device *dev = container_of(kobj, struct device, kobj);
|
||||||
|
struct nvdimm *nvdimm = to_nvdimm(dev);
|
||||||
|
|
||||||
if (to_nfit_dcr(dev))
|
if (!to_nfit_dcr(dev))
|
||||||
return a->mode;
|
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
|
if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1)
|
||||||
|
return 0;
|
||||||
|
return a->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attribute_group acpi_nfit_dimm_attribute_group = {
|
static struct attribute_group acpi_nfit_dimm_attribute_group = {
|
||||||
|
@ -2309,7 +2375,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
|
||||||
acpi_size sz;
|
acpi_size sz;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz);
|
status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
/* This is ok, we could have an nvdimm hotplugged later */
|
/* This is ok, we could have an nvdimm hotplugged later */
|
||||||
dev_dbg(dev, "failed to find NFIT at startup\n");
|
dev_dbg(dev, "failed to find NFIT at startup\n");
|
||||||
|
|
|
@ -109,6 +109,7 @@ struct nfit_mem {
|
||||||
struct nfit_flush *nfit_flush;
|
struct nfit_flush *nfit_flush;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
struct acpi_nfit_desc *acpi_desc;
|
||||||
unsigned long dsm_mask;
|
unsigned long dsm_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1383,11 +1383,15 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
|
||||||
struct btt *btt;
|
struct btt *btt;
|
||||||
size_t rawsize;
|
size_t rawsize;
|
||||||
|
|
||||||
if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize)
|
if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) {
|
||||||
|
dev_dbg(&nd_btt->dev, "incomplete btt configuration\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K;
|
rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K;
|
||||||
if (rawsize < ARENA_MIN_SIZE) {
|
if (rawsize < ARENA_MIN_SIZE) {
|
||||||
|
dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n",
|
||||||
|
dev_name(&ndns->dev), ARENA_MIN_SIZE + SZ_4K);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
nd_region = to_nd_region(nd_btt->dev.parent);
|
nd_region = to_nd_region(nd_btt->dev.parent);
|
||||||
|
|
|
@ -787,6 +787,9 @@ int __init nvdimm_bus_init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
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);
|
rc = bus_register(&nvdimm_bus_type);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -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
|
* 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,
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
@ -20,11 +20,45 @@ struct nd_cmd_smart {
|
||||||
__u8 data[128];
|
__u8 data[128];
|
||||||
} __packed;
|
} __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 {
|
struct nd_cmd_smart_threshold {
|
||||||
__u32 status;
|
__u32 status;
|
||||||
__u8 data[8];
|
__u8 data[8];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct nd_smart_threshold_payload {
|
||||||
|
__u16 alarm_control;
|
||||||
|
__u16 temperature;
|
||||||
|
__u8 spares;
|
||||||
|
__u8 reserved[3];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct nd_cmd_dimm_flags {
|
struct nd_cmd_dimm_flags {
|
||||||
__u32 status;
|
__u32 status;
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
|
|
|
@ -330,6 +330,42 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
|
||||||
return 0;
|
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,
|
static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
||||||
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
|
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
|
||||||
unsigned int buf_len, int *cmd_rc)
|
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,
|
rc = nfit_test_cmd_set_config_data(buf, buf_len,
|
||||||
t->label[i]);
|
t->label[i]);
|
||||||
break;
|
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:
|
default:
|
||||||
return -ENOTTY;
|
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_SIZE, &acpi_desc->dimm_dsm_force_en);
|
||||||
set_bit(ND_CMD_GET_CONFIG_DATA, &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_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_CAP, &acpi_desc->bus_dsm_force_en);
|
||||||
set_bit(ND_CMD_ARS_START, &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_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
|
||||||
set_bit(ND_CMD_CLEAR_ERROR, &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)
|
static void nfit_test1_setup(struct nfit_test *t)
|
||||||
|
|
Loading…
Reference in a new issue