cma: Add support for associating regions by name
Currently, the devicetree lookup code assumes that all
CMA regions are present at a fixed address and uses the
fixed address for associating CMA regions to devices.
This presents a problem for dynamically assigning regions.
Device names get mangled/changed between flattened and
populated devicetree so relying on that is unworkable.
Add a separate name binding to allow lookup later between
devices.
Change-Id: Iaacd9888ea708d7293f1120e2b8c473c5c601f3d
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
index 74e0476..e98ee05 100644
--- a/Documentation/devicetree/bindings/memory.txt
+++ b/Documentation/devicetree/bindings/memory.txt
@@ -36,6 +36,7 @@
reg = <(baseaddr) (size)>;
(linux,contiguous-region);
(linux,default-contiguous-region);
+ label = (unique_name);
};
name: an name given to the defined region.
@@ -47,7 +48,11 @@
linux,default-contiguous-region: property indicating that the region
is the default region for all contiguous memory
allocations, Linux specific (optional)
-
+label: an internal name used for automatically associating the
+ cma region with a given device. The label is optional;
+ if the label is not given the client is responsible for
+ calling the appropriate functions to associate the region
+ with a device.
* Device nodes
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index e879026..3a8bbc5 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -58,6 +58,7 @@
phys_addr_t base;
unsigned long size;
struct cma *cma;
+ const char *name;
} cma_areas[MAX_CMA_AREAS];
static unsigned cma_area_count;
@@ -77,6 +78,20 @@
return NULL;
}
+static struct cma *cma_get_area_by_name(const char *name)
+{
+ int i;
+ if (!name)
+ return NULL;
+
+ for (i = 0; i < cma_area_count; i++)
+ if (cma_areas[i].name && strcmp(cma_areas[i].name, name) == 0)
+ return cma_areas[i].cma;
+ return NULL;
+}
+
+
+
#ifdef CONFIG_CMA_SIZE_MBYTES
#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
#else
@@ -196,6 +211,7 @@
phys_addr_t base, size;
unsigned long len;
__be32 *prop;
+ char *name;
if (strncmp(uname, "region@", 7) != 0 || depth != 2 ||
!of_get_flat_dt_prop(node, "linux,contiguous-region", NULL))
@@ -208,9 +224,11 @@
base = be32_to_cpu(prop[0]);
size = be32_to_cpu(prop[1]);
+ name = of_get_flat_dt_prop(node, "label", NULL);
+
pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
(unsigned long)base, (unsigned long)size / SZ_1M);
- dma_contiguous_reserve_area(size, &base, 0);
+ dma_contiguous_reserve_area(size, &base, 0, name);
return 0;
}
@@ -251,7 +269,8 @@
pr_debug("%s: reserving %ld MiB for global area\n", __func__,
(unsigned long)sel_size / SZ_1M);
- if (dma_contiguous_reserve_area(sel_size, &base, limit) == 0)
+ if (dma_contiguous_reserve_area(sel_size, &base, limit, NULL)
+ == 0)
dma_contiguous_def_base = base;
}
#ifdef CONFIG_OF
@@ -274,7 +293,7 @@
* devices.
*/
int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
- phys_addr_t limit)
+ phys_addr_t limit, const char *name)
{
phys_addr_t base = *res_base;
phys_addr_t alignment;
@@ -326,6 +345,7 @@
*/
cma_areas[cma_area_count].base = base;
cma_areas[cma_area_count].size = size;
+ cma_areas[cma_area_count].name = name;
cma_area_count++;
*res_base = base;
@@ -366,6 +386,7 @@
{
struct device_node *node;
struct cma *cma;
+ const char *name;
u32 value;
node = of_parse_phandle(dev->of_node, "linux,contiguous-region", 0);
@@ -373,7 +394,11 @@
return;
if (of_property_read_u32(node, "reg", &value) && !value)
return;
- cma = cma_get_area(value);
+
+ if (of_property_read_string(node, "label", &name))
+ return;
+
+ cma = cma_get_area_by_name(name);
if (!cma)
return;
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index 285b593..8a1b3a1 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -70,7 +70,7 @@
void dma_contiguous_reserve(phys_addr_t addr_limit);
int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
- phys_addr_t limit);
+ phys_addr_t limit, const char *name);
int dma_contiguous_add_device(struct device *dev, phys_addr_t base);
@@ -91,7 +91,7 @@
phys_addr_t base, phys_addr_t limit)
{
int ret;
- ret = dma_contiguous_reserve_area(size, &base, limit);
+ ret = dma_contiguous_reserve_area(size, &base, limit, NULL);
if (ret == 0)
ret = dma_contiguous_add_device(dev, base);
return ret;