diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-03-03 12:14:36 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-03-05 15:25:44 -0500 |
commit | d9cbe09d39aa13f6924dc5fb88325de7ef01a72e (patch) | |
tree | 8d2e60e548272353fbfa8bd9ac705cdfac918efc | |
parent | bc94b99636dc7bcccce439a9fb9c00065e2e2627 (diff) |
libnvdimm, pmem: fix 'pfn' support for section-misaligned namespaces
The altmap for a section-misaligned namespace needs to arrange for the
base_pfn to be section-aligned. As a result the 'reserve' region (pfns
from base that do not have a struct page) must be increased. Otherwise
we trip the altmap validation check in __add_pages:
if (altmap->base_pfn != phys_start_pfn
|| vmem_altmap_offset(altmap) > nr_pages) {
pr_warn_once("memory add fail, invalid altmap\n");
return -EINVAL;
}
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/nvdimm/pfn.h | 13 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 24 |
2 files changed, 35 insertions, 2 deletions
diff --git a/drivers/nvdimm/pfn.h b/drivers/nvdimm/pfn.h index cc243754acef..6ee707e5b279 100644 --- a/drivers/nvdimm/pfn.h +++ b/drivers/nvdimm/pfn.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define __NVDIMM_PFN_H | 15 | #define __NVDIMM_PFN_H |
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/mmzone.h> | ||
18 | 19 | ||
19 | #define PFN_SIG_LEN 16 | 20 | #define PFN_SIG_LEN 16 |
20 | #define PFN_SIG "NVDIMM_PFN_INFO\0" | 21 | #define PFN_SIG "NVDIMM_PFN_INFO\0" |
@@ -32,4 +33,16 @@ struct nd_pfn_sb { | |||
32 | u8 padding[4012]; | 33 | u8 padding[4012]; |
33 | __le64 checksum; | 34 | __le64 checksum; |
34 | }; | 35 | }; |
36 | |||
37 | #ifdef CONFIG_SPARSEMEM | ||
38 | #define PFN_SECTION_ALIGN_DOWN(x) SECTION_ALIGN_DOWN(x) | ||
39 | #define PFN_SECTION_ALIGN_UP(x) SECTION_ALIGN_UP(x) | ||
40 | #else | ||
41 | /* | ||
42 | * In this case ZONE_DEVICE=n and we will disable 'pfn' device support, | ||
43 | * but we still want pmem to compile. | ||
44 | */ | ||
45 | #define PFN_SECTION_ALIGN_DOWN(x) (x) | ||
46 | #define PFN_SECTION_ALIGN_UP(x) (x) | ||
47 | #endif | ||
35 | #endif /* __NVDIMM_PFN_H */ | 48 | #endif /* __NVDIMM_PFN_H */ |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 8d0b54670184..59d568ab7556 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -356,6 +356,26 @@ static int nvdimm_namespace_detach_pfn(struct nd_namespace_common *ndns) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | /* | ||
360 | * We hotplug memory at section granularity, pad the reserved area from | ||
361 | * the previous section base to the namespace base address. | ||
362 | */ | ||
363 | static unsigned long init_altmap_base(resource_size_t base) | ||
364 | { | ||
365 | unsigned long base_pfn = __phys_to_pfn(base); | ||
366 | |||
367 | return PFN_SECTION_ALIGN_DOWN(base_pfn); | ||
368 | } | ||
369 | |||
370 | static unsigned long init_altmap_reserve(resource_size_t base) | ||
371 | { | ||
372 | unsigned long reserve = __phys_to_pfn(SZ_8K); | ||
373 | unsigned long base_pfn = __phys_to_pfn(base); | ||
374 | |||
375 | reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn); | ||
376 | return reserve; | ||
377 | } | ||
378 | |||
359 | static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns) | 379 | static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns) |
360 | { | 380 | { |
361 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); | 381 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); |
@@ -369,8 +389,8 @@ static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns) | |||
369 | phys_addr_t offset; | 389 | phys_addr_t offset; |
370 | int rc; | 390 | int rc; |
371 | struct vmem_altmap __altmap = { | 391 | struct vmem_altmap __altmap = { |
372 | .base_pfn = __phys_to_pfn(nsio->res.start), | 392 | .base_pfn = init_altmap_base(nsio->res.start), |
373 | .reserve = __phys_to_pfn(SZ_8K), | 393 | .reserve = init_altmap_reserve(nsio->res.start), |
374 | }; | 394 | }; |
375 | 395 | ||
376 | if (!nd_pfn->uuid || !nd_pfn->ndns) | 396 | if (!nd_pfn->uuid || !nd_pfn->ndns) |