diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-05-18 13:06:48 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-05-18 13:06:48 -0400 |
commit | 2159669f581917c4d197d3ea183d3d85b47faf66 (patch) | |
tree | 9faa8bbf19fa1ea33e371b02cfa5a5b4507583de | |
parent | 594d6d96ea042366878aa7dc7f5711b8c245db5a (diff) | |
parent | 9dec4892ca9afd6aad3c9c9e6c17480ecbd04440 (diff) |
Merge branch 'for-4.7/libnvdimm' into libnvdimm-for-next
-rw-r--r-- | drivers/acpi/nfit.c | 74 | ||||
-rw-r--r-- | drivers/acpi/nfit.h | 1 | ||||
-rw-r--r-- | drivers/nvdimm/btt.c | 6 | ||||
-rw-r--r-- | drivers/nvdimm/bus.c | 3 | ||||
-rw-r--r-- | include/uapi/linux/ndctl.h | 36 | ||||
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 44 |
6 files changed, 158 insertions, 6 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 63cc9dbe4f3b..d60f73a63c3c 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c | |||
@@ -658,6 +658,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
658 | if (!nfit_mem) | 658 | if (!nfit_mem) |
659 | return -ENOMEM; | 659 | return -ENOMEM; |
660 | INIT_LIST_HEAD(&nfit_mem->list); | 660 | INIT_LIST_HEAD(&nfit_mem->list); |
661 | nfit_mem->acpi_desc = acpi_desc; | ||
661 | list_add(&nfit_mem->list, &acpi_desc->dimms); | 662 | list_add(&nfit_mem->list, &acpi_desc->dimms); |
662 | } | 663 | } |
663 | 664 | ||
@@ -841,6 +842,18 @@ static ssize_t device_show(struct device *dev, | |||
841 | } | 842 | } |
842 | static DEVICE_ATTR_RO(device); | 843 | static DEVICE_ATTR_RO(device); |
843 | 844 | ||
845 | static int num_nvdimm_formats(struct nvdimm *nvdimm) | ||
846 | { | ||
847 | struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); | ||
848 | int formats = 0; | ||
849 | |||
850 | if (nfit_mem->memdev_pmem) | ||
851 | formats++; | ||
852 | if (nfit_mem->memdev_bdw) | ||
853 | formats++; | ||
854 | return formats; | ||
855 | } | ||
856 | |||
844 | static ssize_t format_show(struct device *dev, | 857 | static ssize_t format_show(struct device *dev, |
845 | struct device_attribute *attr, char *buf) | 858 | struct device_attribute *attr, char *buf) |
846 | { | 859 | { |
@@ -850,6 +863,55 @@ static ssize_t format_show(struct device *dev, | |||
850 | } | 863 | } |
851 | static DEVICE_ATTR_RO(format); | 864 | static DEVICE_ATTR_RO(format); |
852 | 865 | ||
866 | static ssize_t format1_show(struct device *dev, | ||
867 | struct device_attribute *attr, char *buf) | ||
868 | { | ||
869 | u32 handle; | ||
870 | ssize_t rc = -ENXIO; | ||
871 | struct nfit_mem *nfit_mem; | ||
872 | struct nfit_memdev *nfit_memdev; | ||
873 | struct acpi_nfit_desc *acpi_desc; | ||
874 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
875 | struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); | ||
876 | |||
877 | nfit_mem = nvdimm_provider_data(nvdimm); | ||
878 | acpi_desc = nfit_mem->acpi_desc; | ||
879 | handle = to_nfit_memdev(dev)->device_handle; | ||
880 | |||
881 | /* assumes DIMMs have at most 2 published interface codes */ | ||
882 | mutex_lock(&acpi_desc->init_mutex); | ||
883 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { | ||
884 | struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev; | ||
885 | struct nfit_dcr *nfit_dcr; | ||
886 | |||
887 | if (memdev->device_handle != handle) | ||
888 | continue; | ||
889 | |||
890 | list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { | ||
891 | if (nfit_dcr->dcr->region_index != memdev->region_index) | ||
892 | continue; | ||
893 | if (nfit_dcr->dcr->code == dcr->code) | ||
894 | continue; | ||
895 | rc = sprintf(buf, "%#x\n", nfit_dcr->dcr->code); | ||
896 | break; | ||
897 | } | ||
898 | if (rc != ENXIO) | ||
899 | break; | ||
900 | } | ||
901 | mutex_unlock(&acpi_desc->init_mutex); | ||
902 | return rc; | ||
903 | } | ||
904 | static DEVICE_ATTR_RO(format1); | ||
905 | |||
906 | static ssize_t formats_show(struct device *dev, | ||
907 | struct device_attribute *attr, char *buf) | ||
908 | { | ||
909 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
910 | |||
911 | return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm)); | ||
912 | } | ||
913 | static DEVICE_ATTR_RO(formats); | ||
914 | |||
853 | static ssize_t serial_show(struct device *dev, | 915 | static ssize_t serial_show(struct device *dev, |
854 | struct device_attribute *attr, char *buf) | 916 | struct device_attribute *attr, char *buf) |
855 | { | 917 | { |
@@ -879,6 +941,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = { | |||
879 | &dev_attr_vendor.attr, | 941 | &dev_attr_vendor.attr, |
880 | &dev_attr_device.attr, | 942 | &dev_attr_device.attr, |
881 | &dev_attr_format.attr, | 943 | &dev_attr_format.attr, |
944 | &dev_attr_formats.attr, | ||
945 | &dev_attr_format1.attr, | ||
882 | &dev_attr_serial.attr, | 946 | &dev_attr_serial.attr, |
883 | &dev_attr_rev_id.attr, | 947 | &dev_attr_rev_id.attr, |
884 | &dev_attr_flags.attr, | 948 | &dev_attr_flags.attr, |
@@ -889,11 +953,13 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj, | |||
889 | struct attribute *a, int n) | 953 | struct attribute *a, int n) |
890 | { | 954 | { |
891 | struct device *dev = container_of(kobj, struct device, kobj); | 955 | struct device *dev = container_of(kobj, struct device, kobj); |
956 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
892 | 957 | ||
893 | if (to_nfit_dcr(dev)) | 958 | if (!to_nfit_dcr(dev)) |
894 | return a->mode; | 959 | return 0; |
895 | else | 960 | if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1) |
896 | return 0; | 961 | return 0; |
962 | return a->mode; | ||
897 | } | 963 | } |
898 | 964 | ||
899 | static struct attribute_group acpi_nfit_dimm_attribute_group = { | 965 | static struct attribute_group acpi_nfit_dimm_attribute_group = { |
@@ -2309,7 +2375,7 @@ static int acpi_nfit_add(struct acpi_device *adev) | |||
2309 | acpi_size sz; | 2375 | acpi_size sz; |
2310 | int rc; | 2376 | int rc; |
2311 | 2377 | ||
2312 | status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz); | 2378 | status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz); |
2313 | if (ACPI_FAILURE(status)) { | 2379 | if (ACPI_FAILURE(status)) { |
2314 | /* This is ok, we could have an nvdimm hotplugged later */ | 2380 | /* This is ok, we could have an nvdimm hotplugged later */ |
2315 | dev_dbg(dev, "failed to find NFIT at startup\n"); | 2381 | dev_dbg(dev, "failed to find NFIT at startup\n"); |
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index c75576b2d50e..5201840c1147 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h | |||
@@ -109,6 +109,7 @@ struct nfit_mem { | |||
109 | struct nfit_flush *nfit_flush; | 109 | struct nfit_flush *nfit_flush; |
110 | struct list_head list; | 110 | struct list_head list; |
111 | struct acpi_device *adev; | 111 | struct acpi_device *adev; |
112 | struct acpi_nfit_desc *acpi_desc; | ||
112 | unsigned long dsm_mask; | 113 | unsigned long dsm_mask; |
113 | }; | 114 | }; |
114 | 115 | ||
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index cc9fafed9362..68a7c3c1eed9 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c | |||
@@ -1383,11 +1383,15 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns) | |||
1383 | struct btt *btt; | 1383 | struct btt *btt; |
1384 | size_t rawsize; | 1384 | size_t rawsize; |
1385 | 1385 | ||
1386 | if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) | 1386 | if (!nd_btt->uuid || !nd_btt->ndns || !nd_btt->lbasize) { |
1387 | dev_dbg(&nd_btt->dev, "incomplete btt configuration\n"); | ||
1387 | return -ENODEV; | 1388 | return -ENODEV; |
1389 | } | ||
1388 | 1390 | ||
1389 | rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K; | 1391 | rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K; |
1390 | if (rawsize < ARENA_MIN_SIZE) { | 1392 | if (rawsize < ARENA_MIN_SIZE) { |
1393 | dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n", | ||
1394 | dev_name(&ndns->dev), ARENA_MIN_SIZE + SZ_4K); | ||
1391 | return -ENXIO; | 1395 | return -ENXIO; |
1392 | } | 1396 | } |
1393 | nd_region = to_nd_region(nd_btt->dev.parent); | 1397 | nd_region = to_nd_region(nd_btt->dev.parent); |
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 97589e3cb852..dcaefe229887 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c | |||
@@ -787,6 +787,9 @@ int __init nvdimm_bus_init(void) | |||
787 | { | 787 | { |
788 | int rc; | 788 | int rc; |
789 | 789 | ||
790 | BUILD_BUG_ON(sizeof(struct nd_smart_payload) != 128); | ||
791 | BUILD_BUG_ON(sizeof(struct nd_smart_threshold_payload) != 8); | ||
792 | |||
790 | rc = bus_register(&nvdimm_bus_type); | 793 | rc = bus_register(&nvdimm_bus_type); |
791 | if (rc) | 794 | if (rc) |
792 | return rc; | 795 | return rc; |
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h index 4f29d247f709..1eac426aead5 100644 --- a/include/uapi/linux/ndctl.h +++ b/include/uapi/linux/ndctl.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014-2015, Intel Corporation. | 2 | * Copyright (c) 2014-2016, Intel Corporation. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU Lesser General Public License, | 5 | * under the terms and conditions of the GNU Lesser General Public License, |
@@ -20,11 +20,45 @@ struct nd_cmd_smart { | |||
20 | __u8 data[128]; | 20 | __u8 data[128]; |
21 | } __packed; | 21 | } __packed; |
22 | 22 | ||
23 | #define ND_SMART_HEALTH_VALID (1 << 0) | ||
24 | #define ND_SMART_TEMP_VALID (1 << 1) | ||
25 | #define ND_SMART_SPARES_VALID (1 << 2) | ||
26 | #define ND_SMART_ALARM_VALID (1 << 3) | ||
27 | #define ND_SMART_USED_VALID (1 << 4) | ||
28 | #define ND_SMART_SHUTDOWN_VALID (1 << 5) | ||
29 | #define ND_SMART_VENDOR_VALID (1 << 6) | ||
30 | #define ND_SMART_TEMP_TRIP (1 << 0) | ||
31 | #define ND_SMART_SPARE_TRIP (1 << 1) | ||
32 | #define ND_SMART_NON_CRITICAL_HEALTH (1 << 0) | ||
33 | #define ND_SMART_CRITICAL_HEALTH (1 << 1) | ||
34 | #define ND_SMART_FATAL_HEALTH (1 << 2) | ||
35 | |||
36 | struct nd_smart_payload { | ||
37 | __u32 flags; | ||
38 | __u8 reserved0[4]; | ||
39 | __u8 health; | ||
40 | __u16 temperature; | ||
41 | __u8 spares; | ||
42 | __u8 alarm_flags; | ||
43 | __u8 life_used; | ||
44 | __u8 shutdown_state; | ||
45 | __u8 reserved1; | ||
46 | __u32 vendor_size; | ||
47 | __u8 vendor_data[108]; | ||
48 | } __packed; | ||
49 | |||
23 | struct nd_cmd_smart_threshold { | 50 | struct nd_cmd_smart_threshold { |
24 | __u32 status; | 51 | __u32 status; |
25 | __u8 data[8]; | 52 | __u8 data[8]; |
26 | } __packed; | 53 | } __packed; |
27 | 54 | ||
55 | struct nd_smart_threshold_payload { | ||
56 | __u16 alarm_control; | ||
57 | __u16 temperature; | ||
58 | __u8 spares; | ||
59 | __u8 reserved[3]; | ||
60 | } __packed; | ||
61 | |||
28 | struct nd_cmd_dimm_flags { | 62 | struct nd_cmd_dimm_flags { |
29 | __u32 status; | 63 | __u32 status; |
30 | __u32 flags; | 64 | __u32 flags; |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 3187322eeed7..d1c98d4386d4 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -330,6 +330,42 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, | |||
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len) | ||
334 | { | ||
335 | static const struct nd_smart_payload smart_data = { | ||
336 | .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID | ||
337 | | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID | ||
338 | | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID, | ||
339 | .health = ND_SMART_NON_CRITICAL_HEALTH, | ||
340 | .temperature = 23 * 16, | ||
341 | .spares = 75, | ||
342 | .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP, | ||
343 | .life_used = 5, | ||
344 | .shutdown_state = 0, | ||
345 | .vendor_size = 0, | ||
346 | }; | ||
347 | |||
348 | if (buf_len < sizeof(*smart)) | ||
349 | return -EINVAL; | ||
350 | memcpy(smart->data, &smart_data, sizeof(smart_data)); | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t, | ||
355 | unsigned int buf_len) | ||
356 | { | ||
357 | static const struct nd_smart_threshold_payload smart_t_data = { | ||
358 | .alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP, | ||
359 | .temperature = 40 * 16, | ||
360 | .spares = 5, | ||
361 | }; | ||
362 | |||
363 | if (buf_len < sizeof(*smart_t)) | ||
364 | return -EINVAL; | ||
365 | memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data)); | ||
366 | return 0; | ||
367 | } | ||
368 | |||
333 | static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | 369 | static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, |
334 | struct nvdimm *nvdimm, unsigned int cmd, void *buf, | 370 | struct nvdimm *nvdimm, unsigned int cmd, void *buf, |
335 | unsigned int buf_len, int *cmd_rc) | 371 | unsigned int buf_len, int *cmd_rc) |
@@ -368,6 +404,12 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
368 | rc = nfit_test_cmd_set_config_data(buf, buf_len, | 404 | rc = nfit_test_cmd_set_config_data(buf, buf_len, |
369 | t->label[i]); | 405 | t->label[i]); |
370 | break; | 406 | break; |
407 | case ND_CMD_SMART: | ||
408 | rc = nfit_test_cmd_smart(buf, buf_len); | ||
409 | break; | ||
410 | case ND_CMD_SMART_THRESHOLD: | ||
411 | rc = nfit_test_cmd_smart_threshold(buf, buf_len); | ||
412 | break; | ||
371 | default: | 413 | default: |
372 | return -ENOTTY; | 414 | return -ENOTTY; |
373 | } | 415 | } |
@@ -1254,10 +1296,12 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1254 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); | 1296 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); |
1255 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); | 1297 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); |
1256 | set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); | 1298 | set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); |
1299 | set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en); | ||
1257 | set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); | 1300 | set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); |
1258 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); | 1301 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); |
1259 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); | 1302 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); |
1260 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); | 1303 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); |
1304 | set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_dsm_force_en); | ||
1261 | } | 1305 | } |
1262 | 1306 | ||
1263 | static void nfit_test1_setup(struct nfit_test *t) | 1307 | static void nfit_test1_setup(struct nfit_test *t) |