Loading drivers/acpi/nfit.c +70 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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, Loading @@ -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 = { Loading Loading @@ -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"); Loading drivers/acpi/nfit.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; }; Loading drivers/nvdimm/btt.c +5 −1 Original line number Diff line number Diff line Loading @@ -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); Loading drivers/nvdimm/bus.c +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading include/uapi/linux/ndctl.h +35 −1 Original line number Diff line number Diff line /* * 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, Loading @@ -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; Loading Loading
drivers/acpi/nfit.c +70 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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, Loading @@ -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 = { Loading Loading @@ -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"); Loading
drivers/acpi/nfit.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; }; Loading
drivers/nvdimm/btt.c +5 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
drivers/nvdimm/bus.c +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
include/uapi/linux/ndctl.h +35 −1 Original line number Diff line number Diff line /* * 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, Loading @@ -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; Loading