Merge tag 'libnvdimm-fixes-for-5.12-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm fixes from Dan Williams:
"The largest change is for a regression that landed during -rc1 for
block-device read-only handling. Vaibhav found a new use for the
ability (originally introduced by virtio_pmem) to call back to the
platform to flush data, but also found an original bug in that
implementation. Lastly, Arnd cleans up some compile warnings in dax.

This has all appeared in -next with no reported issues.

Summary:

- Fix a regression of read-only handling in the pmem driver

- Fix a compile warning

- Fix support for platform cache flush commands on powerpc/papr"

* tag 'libnvdimm-fixes-for-5.12-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC
libnvdimm: Notify disk drivers to revalidate region read-only
dax: avoid -Wempty-body warnings

Changed files
+56 -18
drivers
include
linux
+2 -4
drivers/dax/bus.c
··· 90 list_add(&dax_id->list, &dax_drv->ids); 91 } else 92 rc = -ENOMEM; 93 - } else 94 - /* nothing to remove */; 95 } else if (action == ID_REMOVE) { 96 list_del(&dax_id->list); 97 kfree(dax_id); 98 - } else 99 - /* dax_id already added */; 100 mutex_unlock(&dax_bus_lock); 101 102 if (rc < 0)
··· 90 list_add(&dax_id->list, &dax_drv->ids); 91 } else 92 rc = -ENOMEM; 93 + } 94 } else if (action == ID_REMOVE) { 95 list_del(&dax_id->list); 96 kfree(dax_id); 97 + } 98 mutex_unlock(&dax_bus_lock); 99 100 if (rc < 0)
+6 -8
drivers/nvdimm/bus.c
··· 631 struct nd_region *nd_region = to_nd_region(dev->parent); 632 int disk_ro = get_disk_ro(disk); 633 634 - /* 635 - * Upgrade to read-only if the region is read-only preserve as 636 - * read-only if the disk is already read-only. 637 - */ 638 - if (disk_ro || nd_region->ro == disk_ro) 639 return; 640 641 - dev_info(dev, "%s read-only, marking %s read-only\n", 642 - dev_name(&nd_region->dev), disk->disk_name); 643 - set_disk_ro(disk, 1); 644 } 645 EXPORT_SYMBOL(nvdimm_check_and_set_ro); 646
··· 631 struct nd_region *nd_region = to_nd_region(dev->parent); 632 int disk_ro = get_disk_ro(disk); 633 634 + /* catch the disk up with the region ro state */ 635 + if (disk_ro == nd_region->ro) 636 return; 637 638 + dev_info(dev, "%s read-%s, marking %s read-%s\n", 639 + dev_name(&nd_region->dev), nd_region->ro ? "only" : "write", 640 + disk->disk_name, nd_region->ro ? "only" : "write"); 641 + set_disk_ro(disk, nd_region->ro); 642 } 643 EXPORT_SYMBOL(nvdimm_check_and_set_ro); 644
+33 -4
drivers/nvdimm/pmem.c
··· 26 #include <linux/mm.h> 27 #include <asm/cacheflush.h> 28 #include "pmem.h" 29 #include "pfn.h" 30 #include "nd.h" 31 ··· 586 nvdimm_flush(to_nd_region(dev->parent), NULL); 587 } 588 589 - static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) 590 { 591 struct nd_region *nd_region; 592 resource_size_t offset = 0, end_trunc = 0; ··· 595 struct badblocks *bb; 596 struct range range; 597 struct kernfs_node *bb_state; 598 - 599 - if (event != NVDIMM_REVALIDATE_POISON) 600 - return; 601 602 if (is_nd_btt(dev)) { 603 struct nd_btt *nd_btt = to_nd_btt(dev); ··· 631 nvdimm_badblocks_populate(nd_region, bb, &range); 632 if (bb_state) 633 sysfs_notify_dirent(bb_state); 634 } 635 636 MODULE_ALIAS("pmem");
··· 26 #include <linux/mm.h> 27 #include <asm/cacheflush.h> 28 #include "pmem.h" 29 + #include "btt.h" 30 #include "pfn.h" 31 #include "nd.h" 32 ··· 585 nvdimm_flush(to_nd_region(dev->parent), NULL); 586 } 587 588 + static void pmem_revalidate_poison(struct device *dev) 589 { 590 struct nd_region *nd_region; 591 resource_size_t offset = 0, end_trunc = 0; ··· 594 struct badblocks *bb; 595 struct range range; 596 struct kernfs_node *bb_state; 597 598 if (is_nd_btt(dev)) { 599 struct nd_btt *nd_btt = to_nd_btt(dev); ··· 633 nvdimm_badblocks_populate(nd_region, bb, &range); 634 if (bb_state) 635 sysfs_notify_dirent(bb_state); 636 + } 637 + 638 + static void pmem_revalidate_region(struct device *dev) 639 + { 640 + struct pmem_device *pmem; 641 + 642 + if (is_nd_btt(dev)) { 643 + struct nd_btt *nd_btt = to_nd_btt(dev); 644 + struct btt *btt = nd_btt->btt; 645 + 646 + nvdimm_check_and_set_ro(btt->btt_disk); 647 + return; 648 + } 649 + 650 + pmem = dev_get_drvdata(dev); 651 + nvdimm_check_and_set_ro(pmem->disk); 652 + } 653 + 654 + static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) 655 + { 656 + switch (event) { 657 + case NVDIMM_REVALIDATE_POISON: 658 + pmem_revalidate_poison(dev); 659 + break; 660 + case NVDIMM_REVALIDATE_REGION: 661 + pmem_revalidate_region(dev); 662 + break; 663 + default: 664 + dev_WARN_ONCE(dev, 1, "notify: unknown event: %d\n", event); 665 + break; 666 + } 667 } 668 669 MODULE_ALIAS("pmem");
+14 -2
drivers/nvdimm/region_devs.c
··· 518 return sprintf(buf, "%d\n", nd_region->ro); 519 } 520 521 static ssize_t read_only_store(struct device *dev, 522 struct device_attribute *attr, const char *buf, size_t len) 523 { ··· 535 return rc; 536 537 nd_region->ro = ro; 538 return len; 539 } 540 static DEVICE_ATTR_RW(read_only); ··· 1246 || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) 1247 return -ENXIO; 1248 1249 for (i = 0; i < nd_region->ndr_mappings; i++) { 1250 struct nd_mapping *nd_mapping = &nd_region->mapping[i]; 1251 struct nvdimm *nvdimm = nd_mapping->nvdimm; ··· 1261 } 1262 1263 /* 1264 - * The platform defines dimm devices without hints, assume 1265 - * platform persistence mechanism like ADR 1266 */ 1267 return 0; 1268 }
··· 518 return sprintf(buf, "%d\n", nd_region->ro); 519 } 520 521 + static int revalidate_read_only(struct device *dev, void *data) 522 + { 523 + nd_device_notify(dev, NVDIMM_REVALIDATE_REGION); 524 + return 0; 525 + } 526 + 527 static ssize_t read_only_store(struct device *dev, 528 struct device_attribute *attr, const char *buf, size_t len) 529 { ··· 529 return rc; 530 531 nd_region->ro = ro; 532 + device_for_each_child(dev, NULL, revalidate_read_only); 533 return len; 534 } 535 static DEVICE_ATTR_RW(read_only); ··· 1239 || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) 1240 return -ENXIO; 1241 1242 + /* Test if an explicit flush function is defined */ 1243 + if (test_bit(ND_REGION_ASYNC, &nd_region->flags) && nd_region->flush) 1244 + return 1; 1245 + 1246 + /* Test if any flush hints for the region are available */ 1247 for (i = 0; i < nd_region->ndr_mappings; i++) { 1248 struct nd_mapping *nd_mapping = &nd_region->mapping[i]; 1249 struct nvdimm *nvdimm = nd_mapping->nvdimm; ··· 1249 } 1250 1251 /* 1252 + * The platform defines dimm devices without hints nor explicit flush, 1253 + * assume platform persistence mechanism like ADR 1254 */ 1255 return 0; 1256 }
+1
include/linux/nd.h
··· 11 12 enum nvdimm_event { 13 NVDIMM_REVALIDATE_POISON, 14 }; 15 16 enum nvdimm_claim_class {
··· 11 12 enum nvdimm_event { 13 NVDIMM_REVALIDATE_POISON, 14 + NVDIMM_REVALIDATE_REGION, 15 }; 16 17 enum nvdimm_claim_class {