Commit 72f8c0bf authored by Wolfram Sang's avatar Wolfram Sang Committed by Greg Kroah-Hartman
Browse files

lib: devres: add convenience function to remap a resource



Almost every platform_driver does the three steps get_resource,
request_mem_region, ioremap. This does not only lead to a lot of code
duplication, but also a huge number of similar error strings and
inconsistent error codes on failure. So, introduce a helper function
which simplifies remapping a resource and make it hard to do something
wrong and add documentation for it.

Signed-off-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Acked-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 571806a9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -262,6 +262,7 @@ IOMAP
  devm_ioremap()
  devm_ioremap_nocache()
  devm_iounmap()
  devm_request_and_ioremap() : checks resource, requests region, ioremaps
  pcim_iomap()
  pcim_iounmap()
  pcim_iomap_table()	: array of mapped addresses indexed by BAR
+3 −0
Original line number Diff line number Diff line
@@ -490,6 +490,9 @@ extern int devres_release_group(struct device *dev, void *id);
extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
extern void devm_kfree(struct device *dev, void *p);

void __iomem *devm_request_and_ioremap(struct device *dev,
			struct resource *res);

struct device_dma_parameters {
	/*
	 * a low level driver may set these to teach IOMMU code about
+51 −0
Original line number Diff line number Diff line
@@ -85,6 +85,57 @@ void devm_iounmap(struct device *dev, void __iomem *addr)
}
EXPORT_SYMBOL(devm_iounmap);

/**
 * devm_request_and_ioremap() - Check, request region, and ioremap resource
 * @dev: Generic device to handle the resource for
 * @res: resource to be handled
 *
 * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
 * everything is undone on driver detach. Checks arguments, so you can feed
 * it the result from e.g. platform_get_resource() directly. Returns the
 * remapped pointer or NULL on error. Usage example:
 *
 *	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 *	base = devm_request_and_ioremap(&pdev->dev, res);
 *	if (!base)
 *		return -EADDRNOTAVAIL;
 */
void __iomem *devm_request_and_ioremap(struct device *dev,
			struct resource *res)
{
	resource_size_t size;
	const char *name;
	void __iomem *dest_ptr;

	BUG_ON(!dev);

	if (!res || resource_type(res) != IORESOURCE_MEM) {
		dev_err(dev, "invalid resource\n");
		return NULL;
	}

	size = resource_size(res);
	name = res->name ?: dev_name(dev);

	if (!devm_request_mem_region(dev, res->start, size, name)) {
		dev_err(dev, "can't request region for resource %pR\n", res);
		return NULL;
	}

	if (res->flags & IORESOURCE_CACHEABLE)
		dest_ptr = devm_ioremap(dev, res->start, size);
	else
		dest_ptr = devm_ioremap_nocache(dev, res->start, size);

	if (!dest_ptr) {
		dev_err(dev, "ioremap failed for resource %pR\n", res);
		devm_release_mem_region(dev, res->start, size);
	}

	return dest_ptr;
}
EXPORT_SYMBOL(devm_request_and_ioremap);

#ifdef CONFIG_HAS_IOPORT
/*
 * Generic iomap devres