static int __nvdimm_setup_pfn()

in pfn_devs.c [673:716]


static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap)
{
	struct range *range = &pgmap->range;
	struct vmem_altmap *altmap = &pgmap->altmap;
	struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
	u64 offset = le64_to_cpu(pfn_sb->dataoff);
	u32 start_pad = __le32_to_cpu(pfn_sb->start_pad);
	u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc);
	u32 reserve = nd_info_block_reserve();
	struct nd_namespace_common *ndns = nd_pfn->ndns;
	struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
	resource_size_t base = nsio->res.start + start_pad;
	resource_size_t end = nsio->res.end - end_trunc;
	struct vmem_altmap __altmap = {
		.base_pfn = init_altmap_base(base),
		.reserve = init_altmap_reserve(base),
		.end_pfn = PHYS_PFN(end),
	};

	*range = (struct range) {
		.start = nsio->res.start + start_pad,
		.end = nsio->res.end - end_trunc,
	};
	pgmap->nr_range = 1;
	if (nd_pfn->mode == PFN_MODE_RAM) {
		if (offset < reserve)
			return -EINVAL;
		nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns);
	} else if (nd_pfn->mode == PFN_MODE_PMEM) {
		nd_pfn->npfns = PHYS_PFN((range_len(range) - offset));
		if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns)
			dev_info(&nd_pfn->dev,
					"number of pfns truncated from %lld to %ld\n",
					le64_to_cpu(nd_pfn->pfn_sb->npfns),
					nd_pfn->npfns);
		memcpy(altmap, &__altmap, sizeof(*altmap));
		altmap->free = PHYS_PFN(offset - reserve);
		altmap->alloc = 0;
		pgmap->flags |= PGMAP_ALTMAP_VALID;
	} else
		return -ENXIO;

	return 0;
}