summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/nfit.c31
-rw-r--r--drivers/acpi/nfit.h3
-rw-r--r--drivers/nvdimm/blk.c2
-rw-r--r--drivers/nvdimm/btt.c10
-rw-r--r--drivers/nvdimm/bus.c18
-rw-r--r--drivers/nvdimm/nd.h3
-rw-r--r--drivers/nvdimm/pmem.c2
-rw-r--r--drivers/nvdimm/region_devs.c29
-rw-r--r--include/linux/libnvdimm.h2
-rw-r--r--tools/testing/nvdimm/test/nfit.c3
10 files changed, 100 insertions, 3 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 07d630e9f4ae..1f6f1b1a54f4 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -668,6 +668,20 @@ static ssize_t serial_show(struct device *dev,
668} 668}
669static DEVICE_ATTR_RO(serial); 669static DEVICE_ATTR_RO(serial);
670 670
671static ssize_t flags_show(struct device *dev,
672 struct device_attribute *attr, char *buf)
673{
674 u16 flags = to_nfit_memdev(dev)->flags;
675
676 return sprintf(buf, "%s%s%s%s%s\n",
677 flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
678 flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
679 flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
680 flags & ACPI_NFIT_MEM_ARMED ? "arm " : "",
681 flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart " : "");
682}
683static DEVICE_ATTR_RO(flags);
684
671static struct attribute *acpi_nfit_dimm_attributes[] = { 685static struct attribute *acpi_nfit_dimm_attributes[] = {
672 &dev_attr_handle.attr, 686 &dev_attr_handle.attr,
673 &dev_attr_phys_id.attr, 687 &dev_attr_phys_id.attr,
@@ -676,6 +690,7 @@ static struct attribute *acpi_nfit_dimm_attributes[] = {
676 &dev_attr_format.attr, 690 &dev_attr_format.attr,
677 &dev_attr_serial.attr, 691 &dev_attr_serial.attr,
678 &dev_attr_rev_id.attr, 692 &dev_attr_rev_id.attr,
693 &dev_attr_flags.attr,
679 NULL, 694 NULL,
680}; 695};
681 696
@@ -768,6 +783,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
768 struct nvdimm *nvdimm; 783 struct nvdimm *nvdimm;
769 unsigned long flags = 0; 784 unsigned long flags = 0;
770 u32 device_handle; 785 u32 device_handle;
786 u16 mem_flags;
771 int rc; 787 int rc;
772 788
773 device_handle = __to_nfit_memdev(nfit_mem)->device_handle; 789 device_handle = __to_nfit_memdev(nfit_mem)->device_handle;
@@ -785,6 +801,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
785 if (nfit_mem->bdw && nfit_mem->memdev_pmem) 801 if (nfit_mem->bdw && nfit_mem->memdev_pmem)
786 flags |= NDD_ALIASING; 802 flags |= NDD_ALIASING;
787 803
804 mem_flags = __to_nfit_memdev(nfit_mem)->flags;
805 if (mem_flags & ACPI_NFIT_MEM_ARMED)
806 flags |= NDD_UNARMED;
807
788 rc = acpi_nfit_add_dimm(acpi_desc, nfit_mem, device_handle); 808 rc = acpi_nfit_add_dimm(acpi_desc, nfit_mem, device_handle);
789 if (rc) 809 if (rc)
790 continue; 810 continue;
@@ -797,6 +817,17 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
797 817
798 nfit_mem->nvdimm = nvdimm; 818 nfit_mem->nvdimm = nvdimm;
799 dimm_count++; 819 dimm_count++;
820
821 if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
822 continue;
823
824 dev_info(acpi_desc->dev, "%s: failed: %s%s%s%s\n",
825 nvdimm_name(nvdimm),
826 mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
827 mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
828 mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
829 mem_flags & ACPI_NFIT_MEM_ARMED ? "arm " : "");
830
800 } 831 }
801 832
802 return nvdimm_bus_check_dimm_count(acpi_desc->nvdimm_bus, dimm_count); 833 return nvdimm_bus_check_dimm_count(acpi_desc->nvdimm_bus, dimm_count);
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index c62fffea8423..81f2e8c5a79c 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -22,6 +22,9 @@
22 22
23#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba" 23#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
24#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66" 24#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
25#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
26 | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
27 | ACPI_NFIT_MEM_ARMED)
25 28
26enum nfit_uuids { 29enum nfit_uuids {
27 NFIT_SPA_VOLATILE, 30 NFIT_SPA_VOLATILE,
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 96ef38ceeceb..4f97b248c236 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -232,6 +232,7 @@ static int nd_blk_rw_bytes(struct nd_namespace_common *ndns,
232 232
233static const struct block_device_operations nd_blk_fops = { 233static const struct block_device_operations nd_blk_fops = {
234 .owner = THIS_MODULE, 234 .owner = THIS_MODULE,
235 .revalidate_disk = nvdimm_revalidate_disk,
235}; 236};
236 237
237static int nd_blk_attach_disk(struct nd_namespace_common *ndns, 238static int nd_blk_attach_disk(struct nd_namespace_common *ndns,
@@ -283,6 +284,7 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns,
283 } 284 }
284 285
285 set_capacity(disk, available_disk_size >> SECTOR_SHIFT); 286 set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
287 revalidate_disk(disk);
286 return 0; 288 return 0;
287} 289}
288 290
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index c02065aed03d..411c7b2bb37a 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1245,6 +1245,7 @@ static const struct block_device_operations btt_fops = {
1245 .owner = THIS_MODULE, 1245 .owner = THIS_MODULE,
1246 .rw_page = btt_rw_page, 1246 .rw_page = btt_rw_page,
1247 .getgeo = btt_getgeo, 1247 .getgeo = btt_getgeo,
1248 .revalidate_disk = nvdimm_revalidate_disk,
1248}; 1249};
1249 1250
1250static int btt_blk_init(struct btt *btt) 1251static int btt_blk_init(struct btt *btt)
@@ -1292,6 +1293,7 @@ static int btt_blk_init(struct btt *btt)
1292 } 1293 }
1293 } 1294 }
1294 set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9); 1295 set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
1296 revalidate_disk(btt->btt_disk);
1295 1297
1296 return 0; 1298 return 0;
1297} 1299}
@@ -1346,7 +1348,11 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize,
1346 goto out_free; 1348 goto out_free;
1347 } 1349 }
1348 1350
1349 if (btt->init_state != INIT_READY) { 1351 if (btt->init_state != INIT_READY && nd_region->ro) {
1352 dev_info(dev, "%s is read-only, unable to init btt metadata\n",
1353 dev_name(&nd_region->dev));
1354 goto out_free;
1355 } else if (btt->init_state != INIT_READY) {
1350 btt->num_arenas = (rawsize / ARENA_MAX_SIZE) + 1356 btt->num_arenas = (rawsize / ARENA_MAX_SIZE) +
1351 ((rawsize % ARENA_MAX_SIZE) ? 1 : 0); 1357 ((rawsize % ARENA_MAX_SIZE) ? 1 : 0);
1352 dev_dbg(dev, "init: %d arenas for %llu rawsize\n", 1358 dev_dbg(dev, "init: %d arenas for %llu rawsize\n",
@@ -1361,7 +1367,7 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize,
1361 ret = btt_meta_init(btt); 1367 ret = btt_meta_init(btt);
1362 if (ret) { 1368 if (ret) {
1363 dev_err(dev, "init: error in meta_init: %d\n", ret); 1369 dev_err(dev, "init: error in meta_init: %d\n", ret);
1364 return NULL; 1370 goto out_free;
1365 } 1371 }
1366 } 1372 }
1367 1373
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index dd12f38397db..ec59f1f26d95 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -227,6 +227,24 @@ int __nd_driver_register(struct nd_device_driver *nd_drv, struct module *owner,
227} 227}
228EXPORT_SYMBOL(__nd_driver_register); 228EXPORT_SYMBOL(__nd_driver_register);
229 229
230int nvdimm_revalidate_disk(struct gendisk *disk)
231{
232 struct device *dev = disk->driverfs_dev;
233 struct nd_region *nd_region = to_nd_region(dev->parent);
234 const char *pol = nd_region->ro ? "only" : "write";
235
236 if (nd_region->ro == get_disk_ro(disk))
237 return 0;
238
239 dev_info(dev, "%s read-%s, marking %s read-%s\n",
240 dev_name(&nd_region->dev), pol, disk->disk_name, pol);
241 set_disk_ro(disk, nd_region->ro);
242
243 return 0;
244
245}
246EXPORT_SYMBOL(nvdimm_revalidate_disk);
247
230static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, 248static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
231 char *buf) 249 char *buf)
232{ 250{
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 4614b00542d1..48b09a210689 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -97,7 +97,7 @@ struct nd_region {
97 u16 ndr_mappings; 97 u16 ndr_mappings;
98 u64 ndr_size; 98 u64 ndr_size;
99 u64 ndr_start; 99 u64 ndr_start;
100 int id, num_lanes; 100 int id, num_lanes, ro;
101 void *provider_data; 101 void *provider_data;
102 struct nd_interleave_set *nd_set; 102 struct nd_interleave_set *nd_set;
103 struct nd_percpu_lane __percpu *lane; 103 struct nd_percpu_lane __percpu *lane;
@@ -189,6 +189,7 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
189void nvdimm_bus_lock(struct device *dev); 189void nvdimm_bus_lock(struct device *dev);
190void nvdimm_bus_unlock(struct device *dev); 190void nvdimm_bus_unlock(struct device *dev);
191bool is_nvdimm_bus_locked(struct device *dev); 191bool is_nvdimm_bus_locked(struct device *dev);
192int nvdimm_revalidate_disk(struct gendisk *disk);
192void nvdimm_drvdata_release(struct kref *kref); 193void nvdimm_drvdata_release(struct kref *kref);
193void put_ndd(struct nvdimm_drvdata *ndd); 194void put_ndd(struct nvdimm_drvdata *ndd);
194int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd); 195int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd);
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index a9709db0704c..42b766f33e59 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -104,6 +104,7 @@ static const struct block_device_operations pmem_fops = {
104 .owner = THIS_MODULE, 104 .owner = THIS_MODULE,
105 .rw_page = pmem_rw_page, 105 .rw_page = pmem_rw_page,
106 .direct_access = pmem_direct_access, 106 .direct_access = pmem_direct_access,
107 .revalidate_disk = nvdimm_revalidate_disk,
107}; 108};
108 109
109static struct pmem_device *pmem_alloc(struct device *dev, 110static struct pmem_device *pmem_alloc(struct device *dev,
@@ -178,6 +179,7 @@ static int pmem_attach_disk(struct nd_namespace_common *ndns,
178 pmem->pmem_disk = disk; 179 pmem->pmem_disk = disk;
179 180
180 add_disk(disk); 181 add_disk(disk);
182 revalidate_disk(disk);
181 183
182 return 0; 184 return 0;
183} 185}
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 2cfb3f74bcbf..482ee3e4e04a 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -345,11 +345,35 @@ static ssize_t btt_seed_show(struct device *dev,
345} 345}
346static DEVICE_ATTR_RO(btt_seed); 346static DEVICE_ATTR_RO(btt_seed);
347 347
348static ssize_t read_only_show(struct device *dev,
349 struct device_attribute *attr, char *buf)
350{
351 struct nd_region *nd_region = to_nd_region(dev);
352
353 return sprintf(buf, "%d\n", nd_region->ro);
354}
355
356static ssize_t read_only_store(struct device *dev,
357 struct device_attribute *attr, const char *buf, size_t len)
358{
359 bool ro;
360 int rc = strtobool(buf, &ro);
361 struct nd_region *nd_region = to_nd_region(dev);
362
363 if (rc)
364 return rc;
365
366 nd_region->ro = ro;
367 return len;
368}
369static DEVICE_ATTR_RW(read_only);
370
348static struct attribute *nd_region_attributes[] = { 371static struct attribute *nd_region_attributes[] = {
349 &dev_attr_size.attr, 372 &dev_attr_size.attr,
350 &dev_attr_nstype.attr, 373 &dev_attr_nstype.attr,
351 &dev_attr_mappings.attr, 374 &dev_attr_mappings.attr,
352 &dev_attr_btt_seed.attr, 375 &dev_attr_btt_seed.attr,
376 &dev_attr_read_only.attr,
353 &dev_attr_set_cookie.attr, 377 &dev_attr_set_cookie.attr,
354 &dev_attr_available_size.attr, 378 &dev_attr_available_size.attr,
355 &dev_attr_namespace_seed.attr, 379 &dev_attr_namespace_seed.attr,
@@ -641,6 +665,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
641 struct device *dev; 665 struct device *dev;
642 void *region_buf; 666 void *region_buf;
643 unsigned int i; 667 unsigned int i;
668 int ro = 0;
644 669
645 for (i = 0; i < ndr_desc->num_mappings; i++) { 670 for (i = 0; i < ndr_desc->num_mappings; i++) {
646 struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; 671 struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i];
@@ -652,6 +677,9 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
652 677
653 return NULL; 678 return NULL;
654 } 679 }
680
681 if (nvdimm->flags & NDD_UNARMED)
682 ro = 1;
655 } 683 }
656 684
657 if (dev_type == &nd_blk_device_type) { 685 if (dev_type == &nd_blk_device_type) {
@@ -707,6 +735,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
707 nd_region->provider_data = ndr_desc->provider_data; 735 nd_region->provider_data = ndr_desc->provider_data;
708 nd_region->nd_set = ndr_desc->nd_set; 736 nd_region->nd_set = ndr_desc->nd_set;
709 nd_region->num_lanes = ndr_desc->num_lanes; 737 nd_region->num_lanes = ndr_desc->num_lanes;
738 nd_region->ro = ro;
710 ida_init(&nd_region->ns_ida); 739 ida_init(&nd_region->ns_ida);
711 ida_init(&nd_region->btt_ida); 740 ida_init(&nd_region->btt_ida);
712 dev = &nd_region->dev; 741 dev = &nd_region->dev;
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 7fc1b25bdb5d..dc799a29ed1a 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -21,6 +21,8 @@
21enum { 21enum {
22 /* when a dimm supports both PMEM and BLK access a label is required */ 22 /* when a dimm supports both PMEM and BLK access a label is required */
23 NDD_ALIASING = 1 << 0, 23 NDD_ALIASING = 1 << 0,
24 /* unarmed memory devices may not persist writes */
25 NDD_UNARMED = 1 << 1,
24 26
25 /* need to set a limit somewhere, but yes, this is likely overkill */ 27 /* need to set a limit somewhere, but yes, this is likely overkill */
26 ND_IOCTL_MAX_BUFLEN = SZ_4M, 28 ND_IOCTL_MAX_BUFLEN = SZ_4M,
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 7a4a5a5edbe4..4b69b8368de0 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -874,6 +874,9 @@ static void nfit_test1_setup(struct nfit_test *t)
874 memdev->address = 0; 874 memdev->address = 0;
875 memdev->interleave_index = 0; 875 memdev->interleave_index = 0;
876 memdev->interleave_ways = 1; 876 memdev->interleave_ways = 1;
877 memdev->flags = ACPI_NFIT_MEM_SAVE_FAILED | ACPI_NFIT_MEM_RESTORE_FAILED
878 | ACPI_NFIT_MEM_FLUSH_FAILED | ACPI_NFIT_MEM_HEALTH_OBSERVED
879 | ACPI_NFIT_MEM_ARMED;
877 880
878 offset += sizeof(*memdev); 881 offset += sizeof(*memdev);
879 /* dcr-descriptor0 */ 882 /* dcr-descriptor0 */