static int alloc_dev_dax_range()

in bus.c [782:841]


static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
		resource_size_t size)
{
	struct dax_region *dax_region = dev_dax->region;
	struct resource *res = &dax_region->res;
	struct device *dev = &dev_dax->dev;
	struct dev_dax_range *ranges;
	unsigned long pgoff = 0;
	struct resource *alloc;
	int i, rc;

	device_lock_assert(dax_region->dev);

	/* handle the seed alloc special case */
	if (!size) {
		if (dev_WARN_ONCE(dev, dev_dax->nr_range,
					"0-size allocation must be first\n"))
			return -EBUSY;
		/* nr_range == 0 is elsewhere special cased as 0-size device */
		return 0;
	}

	alloc = __request_region(res, start, size, dev_name(dev), 0);
	if (!alloc)
		return -ENOMEM;

	ranges = krealloc(dev_dax->ranges, sizeof(*ranges)
			* (dev_dax->nr_range + 1), GFP_KERNEL);
	if (!ranges) {
		__release_region(res, alloc->start, resource_size(alloc));
		return -ENOMEM;
	}

	for (i = 0; i < dev_dax->nr_range; i++)
		pgoff += PHYS_PFN(range_len(&ranges[i].range));
	dev_dax->ranges = ranges;
	ranges[dev_dax->nr_range++] = (struct dev_dax_range) {
		.pgoff = pgoff,
		.range = {
			.start = alloc->start,
			.end = alloc->end,
		},
	};

	dev_dbg(dev, "alloc range[%d]: %pa:%pa\n", dev_dax->nr_range - 1,
			&alloc->start, &alloc->end);
	/*
	 * A dev_dax instance must be registered before mapping device
	 * children can be added. Defer to devm_create_dev_dax() to add
	 * the initial mapping device.
	 */
	if (!device_is_registered(&dev_dax->dev))
		return 0;

	rc = devm_register_dax_mapping(dev_dax, dev_dax->nr_range - 1);
	if (rc)
		trim_dev_dax_range(dev_dax);

	return rc;
}