Skip to content

Commit

Permalink
libnvdimm, pmem: fix 'pfn' support for section-misaligned namespaces
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dan Williams committed Mar 5, 2016
1 parent bc94b99 commit d9cbe09
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
13 changes: 13 additions & 0 deletions drivers/nvdimm/pfn.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define __NVDIMM_PFN_H

#include <linux/types.h>
#include <linux/mmzone.h>

#define PFN_SIG_LEN 16
#define PFN_SIG "NVDIMM_PFN_INFO\0"
Expand All @@ -32,4 +33,16 @@ struct nd_pfn_sb {
u8 padding[4012];
__le64 checksum;
};

#ifdef CONFIG_SPARSEMEM
#define PFN_SECTION_ALIGN_DOWN(x) SECTION_ALIGN_DOWN(x)
#define PFN_SECTION_ALIGN_UP(x) SECTION_ALIGN_UP(x)
#else
/*
* In this case ZONE_DEVICE=n and we will disable 'pfn' device support,
* but we still want pmem to compile.
*/
#define PFN_SECTION_ALIGN_DOWN(x) (x)
#define PFN_SECTION_ALIGN_UP(x) (x)
#endif
#endif /* __NVDIMM_PFN_H */
24 changes: 22 additions & 2 deletions drivers/nvdimm/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,26 @@ static int nvdimm_namespace_detach_pfn(struct nd_namespace_common *ndns)
return 0;
}

/*
* We hotplug memory at section granularity, pad the reserved area from
* the previous section base to the namespace base address.
*/
static unsigned long init_altmap_base(resource_size_t base)
{
unsigned long base_pfn = __phys_to_pfn(base);

return PFN_SECTION_ALIGN_DOWN(base_pfn);
}

static unsigned long init_altmap_reserve(resource_size_t base)
{
unsigned long reserve = __phys_to_pfn(SZ_8K);
unsigned long base_pfn = __phys_to_pfn(base);

reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn);
return reserve;
}

static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
{
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
Expand All @@ -369,8 +389,8 @@ static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
phys_addr_t offset;
int rc;
struct vmem_altmap __altmap = {
.base_pfn = __phys_to_pfn(nsio->res.start),
.reserve = __phys_to_pfn(SZ_8K),
.base_pfn = init_altmap_base(nsio->res.start),
.reserve = init_altmap_reserve(nsio->res.start),
};

if (!nd_pfn->uuid || !nd_pfn->ndns)
Expand Down

0 comments on commit d9cbe09

Please sign in to comment.