diff options
Diffstat (limited to 'drivers/nvdimm/pfn_devs.c')
| -rw-r--r-- | drivers/nvdimm/pfn_devs.c | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 65cc171c721d..2adada1a5855 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -364,9 +364,9 @@ struct device *nd_pfn_create(struct nd_region *nd_region)  int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)  {  	u64 checksum, offset; -	unsigned long align;  	enum nd_pfn_mode mode;  	struct nd_namespace_io *nsio; +	unsigned long align, start_pad;  	struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;  	struct nd_namespace_common *ndns = nd_pfn->ndns;  	const u8 *parent_uuid = nd_dev_to_uuid(&ndns->dev); @@ -410,6 +410,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)  	align = le32_to_cpu(pfn_sb->align);  	offset = le64_to_cpu(pfn_sb->dataoff); +	start_pad = le32_to_cpu(pfn_sb->start_pad);  	if (align == 0)  		align = 1UL << ilog2(offset);  	mode = le32_to_cpu(pfn_sb->mode); @@ -468,7 +469,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)  		return -EBUSY;  	} -	if ((align && !IS_ALIGNED(offset, align)) +	if ((align && !IS_ALIGNED(nsio->res.start + offset + start_pad, align))  			|| !IS_ALIGNED(offset, PAGE_SIZE)) {  		dev_err(&nd_pfn->dev,  				"bad offset: %#llx dax disabled align: %#lx\n", @@ -582,6 +583,12 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn,  	return altmap;  } +static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys) +{ +	return min_t(u64, PHYS_SECTION_ALIGN_DOWN(phys), +			ALIGN_DOWN(phys, nd_pfn->align)); +} +  static int nd_pfn_init(struct nd_pfn *nd_pfn)  {  	u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0; @@ -637,13 +644,16 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)  	start = nsio->res.start;  	size = PHYS_SECTION_ALIGN_UP(start + size) - start;  	if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM, -				IORES_DESC_NONE) == REGION_MIXED) { +				IORES_DESC_NONE) == REGION_MIXED +			|| !IS_ALIGNED(start + resource_size(&nsio->res), +				nd_pfn->align)) {  		size = resource_size(&nsio->res); -		end_trunc = start + size - PHYS_SECTION_ALIGN_DOWN(start + size); +		end_trunc = start + size - phys_pmem_align_down(nd_pfn, +				start + size);  	}  	if (start_pad + end_trunc) -		dev_info(&nd_pfn->dev, "%s section collision, truncate %d bytes\n", +		dev_info(&nd_pfn->dev, "%s alignment collision, truncate %d bytes\n",  				dev_name(&ndns->dev), start_pad + end_trunc);  	/*  |