Skip to content

Commit d9cbe09

Browse files
committed
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>
1 parent bc94b99 commit d9cbe09

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

drivers/nvdimm/pfn.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define __NVDIMM_PFN_H
1616

1717
#include <linux/types.h>
18+
#include <linux/mmzone.h>
1819

1920
#define PFN_SIG_LEN 16
2021
#define PFN_SIG "NVDIMM_PFN_INFO\0"
@@ -32,4 +33,16 @@ struct nd_pfn_sb {
3233
u8 padding[4012];
3334
__le64 checksum;
3435
};
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
3548
#endif /* __NVDIMM_PFN_H */

drivers/nvdimm/pmem.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,26 @@ static int nvdimm_namespace_detach_pfn(struct nd_namespace_common *ndns)
356356
return 0;
357357
}
358358

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+
359379
static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
360380
{
361381
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)
369389
phys_addr_t offset;
370390
int rc;
371391
struct vmem_altmap __altmap = {
372-
.base_pfn = __phys_to_pfn(nsio->res.start),
373-
.reserve = __phys_to_pfn(SZ_8K),
392+
.base_pfn = init_altmap_base(nsio->res.start),
393+
.reserve = init_altmap_reserve(nsio->res.start),
374394
};
375395

376396
if (!nd_pfn->uuid || !nd_pfn->ndns)

0 commit comments

Comments
 (0)