Merge branch 'for-4.7/libnvdimm' into libnvdimm-for-next
This commit is contained in:
Коммит
2159669f58
|
@ -658,6 +658,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
|
|||
if (!nfit_mem)
|
||||
return -ENOMEM;
|
||||
INIT_LIST_HEAD(&nfit_mem->list);
|
||||
nfit_mem->acpi_desc = acpi_desc;
|
||||
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 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,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -850,6 +863,55 @@ static ssize_t format_show(struct device *dev,
|
|||
}
|
||||
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,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -879,6 +941,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = {
|
|||
&dev_attr_vendor.attr,
|
||||
&dev_attr_device.attr,
|
||||
&dev_attr_format.attr,
|
||||
&dev_attr_formats.attr,
|
||||
&dev_attr_format1.attr,
|
||||
&dev_attr_serial.attr,
|
||||
&dev_attr_rev_id.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 device *dev = container_of(kobj, struct device, kobj);
|
||||
struct nvdimm *nvdimm = to_nvdimm(dev);
|
||||
|
||||
if (to_nfit_dcr(dev))
|
||||
return a->mode;
|
||||
else
|
||||
if (!to_nfit_dcr(dev))
|
||||
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 = {
|
||||
|
@ -2309,7 +2375,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
|
|||
acpi_size sz;
|
||||
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)) {
|
||||
/* This is ok, we could have an nvdimm hotplugged later */
|
||||
dev_dbg(dev, "failed to find NFIT at startup\n");
|
||||
|
|
|
@ -109,6 +109,7 @@ struct nfit_mem {
|
|||
struct nfit_flush *nfit_flush;
|
||||
struct list_head list;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
unsigned long dsm_mask;
|
||||
};
|
||||
|
||||
|
|
|
@ -1383,11 +1383,15 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
|
|||
struct btt *btt;
|
||||
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;
|
||||
}
|
||||
|
||||
rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K;
|
||||
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;
|
||||
}
|
||||
nd_region = to_nd_region(nd_btt->dev.parent);
|
||||
|
|
|
@ -787,6 +787,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче