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 90 list_add(&dax_id->list, &dax_drv->ids); 91 91 } else 92 92 rc = -ENOMEM; 93 - } else 94 - /* nothing to remove */; 93 + } 95 94 } else if (action == ID_REMOVE) { 96 95 list_del(&dax_id->list); 97 96 kfree(dax_id); 98 - } else 99 - /* dax_id already added */; 97 + } 100 98 mutex_unlock(&dax_bus_lock); 101 99 102 100 if (rc < 0)
+6 -8
drivers/nvdimm/bus.c
··· 631 631 struct nd_region *nd_region = to_nd_region(dev->parent); 632 632 int disk_ro = get_disk_ro(disk); 633 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) 634 + /* catch the disk up with the region ro state */ 635 + if (disk_ro == nd_region->ro) 639 636 return; 640 637 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); 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); 644 642 } 645 643 EXPORT_SYMBOL(nvdimm_check_and_set_ro); 646 644
+33 -4
drivers/nvdimm/pmem.c
··· 26 26 #include <linux/mm.h> 27 27 #include <asm/cacheflush.h> 28 28 #include "pmem.h" 29 + #include "btt.h" 29 30 #include "pfn.h" 30 31 #include "nd.h" 31 32 ··· 586 585 nvdimm_flush(to_nd_region(dev->parent), NULL); 587 586 } 588 587 589 - static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) 588 + static void pmem_revalidate_poison(struct device *dev) 590 589 { 591 590 struct nd_region *nd_region; 592 591 resource_size_t offset = 0, end_trunc = 0; ··· 595 594 struct badblocks *bb; 596 595 struct range range; 597 596 struct kernfs_node *bb_state; 598 - 599 - if (event != NVDIMM_REVALIDATE_POISON) 600 - return; 601 597 602 598 if (is_nd_btt(dev)) { 603 599 struct nd_btt *nd_btt = to_nd_btt(dev); ··· 631 633 nvdimm_badblocks_populate(nd_region, bb, &range); 632 634 if (bb_state) 633 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 + } 634 667 } 635 668 636 669 MODULE_ALIAS("pmem");
+14 -2
drivers/nvdimm/region_devs.c
··· 518 518 return sprintf(buf, "%d\n", nd_region->ro); 519 519 } 520 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 + 521 527 static ssize_t read_only_store(struct device *dev, 522 528 struct device_attribute *attr, const char *buf, size_t len) 523 529 { ··· 535 529 return rc; 536 530 537 531 nd_region->ro = ro; 532 + device_for_each_child(dev, NULL, revalidate_read_only); 538 533 return len; 539 534 } 540 535 static DEVICE_ATTR_RW(read_only); ··· 1246 1239 || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) 1247 1240 return -ENXIO; 1248 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 */ 1249 1247 for (i = 0; i < nd_region->ndr_mappings; i++) { 1250 1248 struct nd_mapping *nd_mapping = &nd_region->mapping[i]; 1251 1249 struct nvdimm *nvdimm = nd_mapping->nvdimm; ··· 1261 1249 } 1262 1250 1263 1251 /* 1264 - * The platform defines dimm devices without hints, assume 1265 - * platform persistence mechanism like ADR 1252 + * The platform defines dimm devices without hints nor explicit flush, 1253 + * assume platform persistence mechanism like ADR 1266 1254 */ 1267 1255 return 0; 1268 1256 }
+1
include/linux/nd.h
··· 11 11 12 12 enum nvdimm_event { 13 13 NVDIMM_REVALIDATE_POISON, 14 + NVDIMM_REVALIDATE_REGION, 14 15 }; 15 16 16 17 enum nvdimm_claim_class {