aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2017-12-04 17:07:43 -0500
committerDan Williams <dan.j.williams@intel.com>2017-12-19 18:37:34 -0500
commit41fce90f26333c4fa82e8e43b9ace86c4e8a0120 (patch)
tree3d7083541ddb4e75d8224d4616177895dc9f2c9f
parent19deaa217bc04e83b59b5e8c8229eb0e53ad9efc (diff)
libnvdimm, dax: fix 1GB-aligned namespaces vs physical misalignment
The following namespace configuration attempt: # ndctl create-namespace -e namespace0.0 -m devdax -a 1G -f libndctl: ndctl_dax_enable: dax0.1: failed to enable Error: namespace0.0: failed to enable failed to reconfigure namespace: No such device or address ...fails when the backing memory range is not physically aligned to 1G: # cat /proc/iomem | grep Persistent 210000000-30fffffff : Persistent Memory (legacy) In the above example the 4G persistent memory range starts and ends on a 256MB boundary. We handle this case correctly when needing to handle cases that violate section alignment (128MB) collisions against "System RAM", and we simply need to extend that padding/truncation for the 1GB alignment use case. Cc: <stable@vger.kernel.org> Fixes: 315c562536c4 ("libnvdimm, pfn: add 'align' attribute...") Reported-and-tested-by: Jane Chu <jane.chu@oracle.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/nvdimm/pfn_devs.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index db2fc7c02e01..2adada1a5855 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -583,6 +583,12 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
583 return altmap; 583 return altmap;
584} 584}
585 585
586static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys)
587{
588 return min_t(u64, PHYS_SECTION_ALIGN_DOWN(phys),
589 ALIGN_DOWN(phys, nd_pfn->align));
590}
591
586static int nd_pfn_init(struct nd_pfn *nd_pfn) 592static int nd_pfn_init(struct nd_pfn *nd_pfn)
587{ 593{
588 u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0; 594 u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0;
@@ -638,13 +644,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
638 start = nsio->res.start; 644 start = nsio->res.start;
639 size = PHYS_SECTION_ALIGN_UP(start + size) - start; 645 size = PHYS_SECTION_ALIGN_UP(start + size) - start;
640 if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, 646 if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
641 IORES_DESC_NONE) == REGION_MIXED) { 647 IORES_DESC_NONE) == REGION_MIXED
648 || !IS_ALIGNED(start + resource_size(&nsio->res),
649 nd_pfn->align)) {
642 size = resource_size(&nsio->res); 650 size = resource_size(&nsio->res);
643 end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size); 651 end_trunc = start + size - phys_pmem_align_down(nd_pfn,
652 start + size);
644 } 653 }
645 654
646 if (start_pad + end_trunc) 655 if (start_pad + end_trunc)
647 dev_info(&nd_pfn->dev, "%s section collision, truncate %d bytes\n", 656 dev_info(&nd_pfn->dev, "%s alignment collision, truncate %d bytes\n",
648 dev_name(&ndns->dev), start_pad + end_trunc); 657 dev_name(&ndns->dev), start_pad + end_trunc);
649 658
650 /* 659 /*