Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/arm64/configs/qcom.config
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ CONFIG_CPU_IDLE_THERMAL=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_DEBUG_INFO_BTF_MODULES=y
# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set
CONFIG_DMA_CMA=y
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_HEAPS_CMA=y
CONFIG_DMABUF_HEAPS_SYSTEM=y
Expand Down
46 changes: 29 additions & 17 deletions drivers/dma-buf/heaps/cma_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,33 +395,45 @@ static int __init __add_cma_heap(struct cma *cma, const char *name)
return 0;
}

static int __init add_default_cma_heap(void)
static int __init add_cma_heaps(void)
{
struct cma *default_cma = dev_get_cma_area(NULL);
const char *legacy_cma_name;
struct cma *cma;
unsigned int i;
int ret;

if (!default_cma)
return 0;

ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME);
if (ret)
return ret;

if (IS_ENABLED(CONFIG_DMABUF_HEAPS_CMA_LEGACY)) {
legacy_cma_name = cma_get_name(default_cma);
if (!strcmp(legacy_cma_name, DEFAULT_CMA_NAME)) {
pr_warn("legacy name and default name are the same, skipping legacy heap\n");
return 0;
if (default_cma) {
ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME);
if (ret)
return ret;

if (IS_ENABLED(CONFIG_DMABUF_HEAPS_CMA_LEGACY)) {
legacy_cma_name = cma_get_name(default_cma);
if (!strcmp(legacy_cma_name, DEFAULT_CMA_NAME)) {
pr_warn("legacy name and default name are the same, skipping legacy heap\n");
goto add_additional_heaps;
}

ret = __add_cma_heap(default_cma, legacy_cma_name);
if (ret)
pr_warn("failed to add legacy heap: %pe\n",
ERR_PTR(ret));
}
}

add_additional_heaps:
for (i = 0; (cma = dma_contiguous_get_area_by_idx(i)) != NULL; i++) {
if (cma == default_cma)
continue;

ret = __add_cma_heap(default_cma, legacy_cma_name);
ret = __add_cma_heap(cma, cma_get_name(cma));
if (ret)
pr_warn("failed to add legacy heap: %pe\n",
ERR_PTR(ret));
pr_warn("failed to add CMA heap %s: %pe\n",
cma_get_name(cma), ERR_PTR(ret));
}

return 0;
}
module_init(add_default_cma_heap);
module_init(add_cma_heaps);
MODULE_DESCRIPTION("DMA-BUF CMA Heap");
6 changes: 6 additions & 0 deletions include/linux/dma-map-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static inline void set_dma_ops(struct device *dev,

#ifdef CONFIG_DMA_CMA
extern struct cma *dma_contiguous_default_area;
struct cma *dma_contiguous_get_area_by_idx(unsigned int idx);

static inline struct cma *dev_get_cma_area(struct device *dev)
{
Expand Down Expand Up @@ -156,6 +157,11 @@ static inline void dma_free_contiguous(struct device *dev, struct page *page,
static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
{
}

static inline struct cma *dma_contiguous_get_area_by_idx(unsigned int idx)
{
return NULL;
}
#endif /* CONFIG_DMA_CMA*/

#ifdef CONFIG_DMA_DECLARE_COHERENT
Expand Down
41 changes: 37 additions & 4 deletions kernel/dma/contiguous.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@
#endif

struct cma *dma_contiguous_default_area;
static struct cma *dma_contiguous_areas[MAX_CMA_AREAS];
static unsigned int dma_contiguous_areas_num;

static int dma_contiguous_insert_area(struct cma *cma)
{
if (dma_contiguous_areas_num >= ARRAY_SIZE(dma_contiguous_areas))
return -EINVAL;

dma_contiguous_areas[dma_contiguous_areas_num++] = cma;

return 0;
}

struct cma *dma_contiguous_get_area_by_idx(unsigned int idx)
{
if (idx >= dma_contiguous_areas_num)
return NULL;

return dma_contiguous_areas[idx];
}
EXPORT_SYMBOL_GPL(dma_contiguous_get_area_by_idx);

/*
* Default global CMA area size can be defined in kernel's .config.
Expand Down Expand Up @@ -251,13 +272,21 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
}

if (selected_size && !dma_contiguous_default_area) {
int ret;

pr_debug("%s: reserving %ld MiB for global area\n", __func__,
(unsigned long)selected_size / SZ_1M);

dma_contiguous_reserve_area(selected_size, selected_base,
selected_limit,
&dma_contiguous_default_area,
fixed);
ret = dma_contiguous_reserve_area(selected_size, selected_base,
selected_limit,
&dma_contiguous_default_area,
fixed);
if (ret)
return;

ret = dma_contiguous_insert_area(dma_contiguous_default_area);
if (ret)
pr_warn("Couldn't queue default CMA region for heap creation.\n");
}
}

Expand Down Expand Up @@ -497,6 +526,10 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",
&rmem->base, (unsigned long)rmem->size / SZ_1M);

err = dma_contiguous_insert_area(cma);
if (err)
pr_warn("Couldn't store CMA reserved area.\n");

return 0;
}
RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);
Expand Down