mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
dma-heaps: Define qcom tui carveout heap
Move behavior specific to the tui carveout heap usecase out of the mem-buf driver, and existing dma-heap carveout driver into a new file. This is done to reduce code complexity in the dma-heap carveout driver, as well as to prepare for adding new mem-buf clients. Change-Id: I1241e009e63b8e21c55920d3561c5a1777cbf83c Signed-off-by: Patrick Daly <quic_pdaly@quicinc.com>
This commit is contained in:
parent
9cac3c58a2
commit
aa9a1b50ef
|
|
@ -84,3 +84,12 @@ config QCOM_DMABUF_HEAPS_UBWCP
|
|||
The heap itself is backed by system heap memory and works
|
||||
in tandem with the UBWC-P driver.
|
||||
If in doubt, say Y here.
|
||||
|
||||
config QCOM_DMABUF_HEAPS_TUI_CARVEOUT
|
||||
bool "QCOM DMA-BUF TUI Carveout Heap"
|
||||
depends on QCOM_DMABUF_HEAPS
|
||||
help
|
||||
Choose this option to build the QCOM Trusted UI carvout heap.
|
||||
This heap is controlled from an ioctl, and memory is transferred
|
||||
to it from the Primary VM. Not GKI-Compatible as it cannot
|
||||
be built as a module.
|
||||
|
|
|
|||
|
|
@ -13,3 +13,4 @@ qcom_dma_heaps-$(CONFIG_QCOM_DMABUF_HEAPS_CARVEOUT) += qcom_carveout_heap.o \
|
|||
qcom_dma_heap_secure_utils.o
|
||||
qcom_dma_heaps-$(CONFIG_QCOM_DMABUF_HEAPS_BITSTREAM_CONTIG) += qcom_bitstream_contig_heap.o
|
||||
qcom_dma_heaps-$(CONFIG_QCOM_DMABUF_HEAPS_UBWCP) += qcom_ubwcp_heap.o
|
||||
qcom_dma_heaps-$(CONFIG_QCOM_DMABUF_HEAPS_TUI_CARVEOUT) += qcom_tui_carveout_heap.o
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
|
|
@ -50,10 +51,6 @@ struct carveout_heap {
|
|||
bool is_secure;
|
||||
bool is_nomap;
|
||||
phys_addr_t base;
|
||||
|
||||
void *pool_refcount_priv;
|
||||
int (*pool_refcount_get)(void *priv);
|
||||
void (*pool_refcount_put)(void *priv);
|
||||
};
|
||||
|
||||
struct secure_carveout_heap {
|
||||
|
|
@ -79,22 +76,6 @@ void pages_sync_for_device(struct device *dev, struct page *page,
|
|||
dma_sync_sg_for_device(dev, &sg, 1, dir);
|
||||
}
|
||||
|
||||
static int carveout_pool_refcount_get(struct carveout_heap *carveout_heap)
|
||||
{
|
||||
if (!carveout_heap->pool_refcount_get)
|
||||
return 0;
|
||||
|
||||
return carveout_heap->pool_refcount_get(carveout_heap->pool_refcount_priv);
|
||||
}
|
||||
|
||||
static void carveout_pool_refcount_put(struct carveout_heap *carveout_heap)
|
||||
{
|
||||
if (!carveout_heap->pool_refcount_put)
|
||||
return;
|
||||
|
||||
carveout_heap->pool_refcount_put(carveout_heap->pool_refcount_priv);
|
||||
}
|
||||
|
||||
static phys_addr_t carveout_allocate(struct carveout_heap *carveout_heap,
|
||||
unsigned long size)
|
||||
{
|
||||
|
|
@ -102,13 +83,9 @@ static phys_addr_t carveout_allocate(struct carveout_heap *carveout_heap,
|
|||
|
||||
down_read(&carveout_heap->mem_sem);
|
||||
if (carveout_heap->pool) {
|
||||
if (carveout_pool_refcount_get(carveout_heap))
|
||||
goto unlock;
|
||||
|
||||
offset = gen_pool_alloc(carveout_heap->pool, size);
|
||||
if (!offset) {
|
||||
offset = CARVEOUT_ALLOCATE_FAIL;
|
||||
carveout_pool_refcount_put(carveout_heap);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
|
@ -127,7 +104,6 @@ static void carveout_free(struct carveout_heap *carveout_heap,
|
|||
down_read(&carveout_heap->mem_sem);
|
||||
if (carveout_heap->pool)
|
||||
gen_pool_free(carveout_heap->pool, addr, size);
|
||||
carveout_pool_refcount_put(carveout_heap);
|
||||
up_read(&carveout_heap->mem_sem);
|
||||
}
|
||||
|
||||
|
|
@ -344,111 +320,17 @@ static int carveout_init_heap_memory(struct carveout_heap *co_heap,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int carveout_heap_add_memory(char *heap_name, struct sg_table *sgt, void *cookie,
|
||||
int (*get)(void *), void (*put)(void *))
|
||||
{
|
||||
struct dma_heap *heap;
|
||||
struct carveout_heap *carveout_heap;
|
||||
int ret;
|
||||
|
||||
if (!sgt || sgt->nents != 1)
|
||||
return -EINVAL;
|
||||
|
||||
heap = dma_heap_find(heap_name);
|
||||
if (!heap) {
|
||||
pr_err_ratelimited("%s: No heap named %s\n", __func__, heap_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!get || !put || !cookie) {
|
||||
pr_err_ratelimited("%s: Missing refcount callbacks\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
carveout_heap = dma_heap_get_drvdata(heap);
|
||||
|
||||
down_write(&carveout_heap->mem_sem);
|
||||
if (carveout_heap->pool) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = carveout_init_heap_memory(carveout_heap,
|
||||
page_to_phys(sg_page(sgt->sgl)),
|
||||
sgt->sgl->length, true);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
carveout_heap->pool_refcount_priv = cookie;
|
||||
carveout_heap->pool_refcount_get = get;
|
||||
carveout_heap->pool_refcount_put = put;
|
||||
|
||||
unlock:
|
||||
up_write(&carveout_heap->mem_sem);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(carveout_heap_add_memory);
|
||||
|
||||
int carveout_heap_remove_memory(char *heap_name,
|
||||
struct sg_table *sgt)
|
||||
{
|
||||
struct dma_heap *heap;
|
||||
struct carveout_heap *carveout_heap;
|
||||
phys_addr_t base;
|
||||
int ret = 0;
|
||||
|
||||
if (!sgt || sgt->nents != 1)
|
||||
return -EINVAL;
|
||||
|
||||
heap = dma_heap_find(heap_name);
|
||||
if (!heap)
|
||||
return -EINVAL;
|
||||
|
||||
carveout_heap = dma_heap_get_drvdata(heap);
|
||||
|
||||
down_write(&carveout_heap->mem_sem);
|
||||
if (!carveout_heap->pool) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
base = page_to_phys(sg_page(sgt->sgl));
|
||||
if (carveout_heap->base != base) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (gen_pool_size(carveout_heap->pool) !=
|
||||
gen_pool_avail(carveout_heap->pool)) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
gen_pool_destroy(carveout_heap->pool);
|
||||
carveout_heap->pool = NULL;
|
||||
carveout_heap->base = 0;
|
||||
carveout_heap->pool_refcount_priv = NULL;
|
||||
carveout_heap->pool_refcount_get = NULL;
|
||||
carveout_heap->pool_refcount_put = NULL;
|
||||
unlock:
|
||||
up_write(&carveout_heap->mem_sem);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(carveout_heap_remove_memory);
|
||||
|
||||
static int __carveout_heap_init(struct platform_heap *heap_data,
|
||||
struct carveout_heap *carveout_heap,
|
||||
bool sync)
|
||||
{
|
||||
struct device *dev = heap_data->dev;
|
||||
bool dynamic_heap = heap_data->is_dynamic;
|
||||
int ret = 0;
|
||||
|
||||
carveout_heap->dev = dev;
|
||||
if (!dynamic_heap)
|
||||
ret = carveout_init_heap_memory(carveout_heap,
|
||||
heap_data->base,
|
||||
heap_data->size, sync);
|
||||
ret = carveout_init_heap_memory(carveout_heap,
|
||||
heap_data->base,
|
||||
heap_data->size, sync);
|
||||
|
||||
init_rwsem(&carveout_heap->mem_sem);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -9,6 +10,7 @@
|
|||
#include <linux/err.h>
|
||||
|
||||
#include <linux/qcom_dma_heap.h>
|
||||
#include <linux/qcom_tui_heap.h>
|
||||
#include "qcom_cma_heap.h"
|
||||
#include "qcom_dt_parser.h"
|
||||
#include "qcom_system_heap.h"
|
||||
|
|
@ -65,6 +67,16 @@ static int qcom_dma_heap_probe(struct platform_device *pdev)
|
|||
pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
|
||||
heap_data->name);
|
||||
break;
|
||||
case HEAP_TYPE_TUI_CARVEOUT:
|
||||
ret = qcom_tui_carveout_heap_create(heap_data);
|
||||
if (ret)
|
||||
pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
|
||||
__func__, heap_data->name, ret);
|
||||
else
|
||||
pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
|
||||
heap_data->name);
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("%s: Unknown heap type %u\n", __func__, heap_data->type);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
|
|
@ -37,8 +38,6 @@ static int populate_heap(struct device_node *node,
|
|||
}
|
||||
|
||||
/* Optional properties */
|
||||
heap->is_dynamic = of_property_read_bool(node, "qcom,dynamic-heap");
|
||||
|
||||
heap->is_uncached = of_property_read_bool(node, "qcom,uncached-heap");
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,token", &heap->token);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _QCOM_DT_PARSER_H
|
||||
|
|
@ -33,7 +34,6 @@ struct platform_heap {
|
|||
size_t size;
|
||||
struct device *dev;
|
||||
bool is_uncached;
|
||||
bool is_dynamic;
|
||||
bool is_nomap;
|
||||
u32 token;
|
||||
u32 max_align;
|
||||
|
|
|
|||
334
drivers/dma-buf/heaps/qcom_tui_carveout_heap.c
Normal file
334
drivers/dma-buf/heaps/qcom_tui_carveout_heap.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "tui_heap: %s" fmt, __func__
|
||||
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mem-buf.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/qcom_tui_heap.h>
|
||||
#include "qcom_dt_parser.h"
|
||||
#include "qcom_sg_ops.h"
|
||||
|
||||
struct tui_heap;
|
||||
struct tui_pool {
|
||||
struct tui_heap *heap;
|
||||
void *membuf;
|
||||
struct kref kref;
|
||||
struct gen_pool *pool;
|
||||
struct file *filp;
|
||||
};
|
||||
|
||||
struct tui_heap_obj {
|
||||
struct qcom_sg_buffer buffer;
|
||||
struct tui_pool *pool;
|
||||
};
|
||||
|
||||
struct tui_heap {
|
||||
struct dma_heap *heap;
|
||||
/* Protects the pool pointer, not the pool itself */
|
||||
struct rw_semaphore pool_sem;
|
||||
struct tui_pool *pool;
|
||||
};
|
||||
#define CARVEOUT_ALLOCATE_FAIL -1
|
||||
|
||||
static struct tui_pool *tui_pool_create(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
struct tui_pool *pool;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
phys_addr_t base;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
|
||||
if (!pool)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pool->membuf = mem_buf_alloc(alloc_data);
|
||||
if (IS_ERR(pool->membuf)) {
|
||||
ret = PTR_ERR(pool->membuf);
|
||||
goto err_mem_buf_alloc;
|
||||
}
|
||||
sgl_desc = mem_buf_get_sgl(pool->membuf);
|
||||
|
||||
ret = mem_buf_map_mem_s1(sgl_desc);
|
||||
if (ret)
|
||||
goto err_mem_buf_map_mem_s1;
|
||||
|
||||
kref_init(&pool->kref);
|
||||
pool->pool = gen_pool_create(PAGE_SHIFT, -1);
|
||||
if (!pool->pool) {
|
||||
ret = -ENOMEM;
|
||||
goto err_gen_pool_create;
|
||||
}
|
||||
|
||||
base = sgl_desc->sgl_entries[0].ipa_base;
|
||||
size = sgl_desc->sgl_entries[0].size;
|
||||
ret = gen_pool_add(pool->pool, base, size, -1);
|
||||
if (ret)
|
||||
goto err_gen_pool_add;
|
||||
|
||||
return pool;
|
||||
|
||||
err_gen_pool_add:
|
||||
gen_pool_destroy(pool->pool);
|
||||
err_gen_pool_create:
|
||||
if (WARN_ON(mem_buf_unmap_mem_s1(sgl_desc)))
|
||||
return ERR_PTR(ret);
|
||||
err_mem_buf_map_mem_s1:
|
||||
mem_buf_free(pool->membuf);
|
||||
err_mem_buf_alloc:
|
||||
kfree(pool);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void tui_pool_release(struct kref *kref)
|
||||
{
|
||||
struct tui_pool *pool;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
|
||||
pool = container_of(kref, struct tui_pool, kref);
|
||||
|
||||
gen_pool_destroy(pool->pool);
|
||||
sgl_desc = mem_buf_get_sgl(pool->membuf);
|
||||
if (WARN_ON(mem_buf_unmap_mem_s1(sgl_desc)))
|
||||
return;
|
||||
mem_buf_free(pool->membuf);
|
||||
kfree(pool);
|
||||
}
|
||||
|
||||
/* Prevent new allocations from this pool, and drop our refcount */
|
||||
static void qcom_tui_heap_remove_pool(void *handle)
|
||||
{
|
||||
struct tui_pool *pool = handle;
|
||||
struct tui_heap *heap = pool->heap;
|
||||
|
||||
down_write(&heap->pool_sem);
|
||||
heap->pool = NULL;
|
||||
pool->heap = NULL;
|
||||
kref_put(&pool->kref, tui_pool_release);
|
||||
up_write(&heap->pool_sem);
|
||||
}
|
||||
|
||||
static void *qcom_tui_heap_add_pool(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
struct dma_heap *dma_heap;
|
||||
struct tui_heap *heap;
|
||||
struct tui_pool *pool;
|
||||
char *heap_name;
|
||||
|
||||
if (alloc_data->dst_mem_type != MEM_BUF_DMAHEAP_MEM_TYPE)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
heap_name = alloc_data->dst_data;
|
||||
dma_heap = dma_heap_find(heap_name);
|
||||
if (!dma_heap) {
|
||||
pr_err_ratelimited("No heap named %s\n", heap_name);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
heap = dma_heap_get_drvdata(dma_heap);
|
||||
|
||||
/*
|
||||
* Subsection alignment is a requirement of SPARSEMEM_VMEMMAP.
|
||||
* refer to check_pfn_span(). This is the minimum granularity
|
||||
* pfn_valid() and pfn_to_online_page() operate at.
|
||||
*/
|
||||
alloc_data->size = ALIGN(alloc_data->size, 1UL << SUBSECTION_SHIFT);
|
||||
alloc_data->trans_type = GH_RM_TRANS_TYPE_DONATE;
|
||||
alloc_data->sgl_desc = NULL;
|
||||
pool = tui_pool_create(alloc_data);
|
||||
if (IS_ERR(pool))
|
||||
return ERR_CAST(pool);
|
||||
|
||||
down_write(&heap->pool_sem);
|
||||
if (heap->pool) {
|
||||
pr_err_ratelimited("%s already has a pool\n", heap_name);
|
||||
kref_put(&pool->kref, tui_pool_release);
|
||||
pool = ERR_PTR(-EBUSY);
|
||||
} else {
|
||||
pool->heap = heap;
|
||||
heap->pool = pool;
|
||||
}
|
||||
up_write(&heap->pool_sem);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static int tui_heap_file_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
qcom_tui_heap_remove_pool(filp->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations tui_heap_fops = {
|
||||
.release = tui_heap_file_release,
|
||||
};
|
||||
|
||||
int qcom_tui_heap_add_pool_fd(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
struct tui_pool *pool;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Tui heap specific ioctl parsing should move here eventually.
|
||||
*/
|
||||
|
||||
pool = qcom_tui_heap_add_pool(alloc_data);
|
||||
if (IS_ERR(pool))
|
||||
return PTR_ERR(pool);
|
||||
|
||||
pool->filp = anon_inode_getfile("tui_heap", &tui_heap_fops, pool, O_RDWR);
|
||||
if (IS_ERR(pool->filp)) {
|
||||
int ret = PTR_ERR(pool->filp);
|
||||
|
||||
qcom_tui_heap_remove_pool(pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
fput(pool->filp);
|
||||
return fd;
|
||||
}
|
||||
|
||||
fd_install(fd, pool->filp);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void tui_heap_obj_release(struct qcom_sg_buffer *buffer)
|
||||
{
|
||||
struct tui_heap_obj *obj = container_of(buffer, struct tui_heap_obj, buffer);
|
||||
struct sg_table *table = &buffer->sg_table;
|
||||
|
||||
/* Prevent data from previous user from leaking to next user */
|
||||
memset(sg_virt(table->sgl), 0, buffer->len);
|
||||
gen_pool_free(obj->pool->pool, sg_phys(table->sgl), buffer->len);
|
||||
kref_put(&obj->pool->kref, tui_pool_release);
|
||||
sg_free_table(table);
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
static struct dma_buf *tui_heap_allocate(struct dma_heap *dma_heap,
|
||||
unsigned long len,
|
||||
unsigned long fd_flags,
|
||||
unsigned long heap_flags)
|
||||
{
|
||||
struct tui_heap *heap = dma_heap_get_drvdata(dma_heap);
|
||||
struct tui_pool *pool;
|
||||
struct sg_table *table;
|
||||
struct tui_heap_obj *obj;
|
||||
struct qcom_sg_buffer *buffer;
|
||||
u64 paddr;
|
||||
int ret;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *dmabuf;
|
||||
|
||||
len = PAGE_ALIGN(len);
|
||||
|
||||
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
|
||||
if (!obj)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
buffer = &obj->buffer;
|
||||
|
||||
down_read(&heap->pool_sem);
|
||||
pool = heap->pool;
|
||||
if (!pool) {
|
||||
pr_err_ratelimited("%s does not have a pool\n",
|
||||
dma_heap_get_name(heap->heap));
|
||||
ret = -ENODEV;
|
||||
goto err_no_pool;
|
||||
}
|
||||
|
||||
obj->pool = pool;
|
||||
kref_get(&pool->kref);
|
||||
|
||||
/* Returns 0 on failure */
|
||||
paddr = gen_pool_alloc(pool->pool, len);
|
||||
if (!paddr) {
|
||||
ret = -ENOMEM;
|
||||
goto err_tui_pool_alloc;
|
||||
}
|
||||
|
||||
/* Initialize the buffer */
|
||||
INIT_LIST_HEAD(&buffer->attachments);
|
||||
mutex_init(&buffer->lock);
|
||||
buffer->heap = heap->heap;
|
||||
buffer->len = len;
|
||||
buffer->free = tui_heap_obj_release;
|
||||
buffer->uncached = false;
|
||||
|
||||
table = &buffer->sg_table;
|
||||
ret = sg_alloc_table(table, 1, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto err_sg_alloc_table;
|
||||
sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), len, 0);
|
||||
|
||||
buffer->vmperm = mem_buf_vmperm_alloc(table);
|
||||
if (IS_ERR(buffer->vmperm)) {
|
||||
ret = PTR_ERR(buffer->vmperm);
|
||||
goto err_vmperm_alloc;
|
||||
}
|
||||
|
||||
/* Instantiate our dma_buf */
|
||||
exp_info.exp_name = dma_heap_get_name(heap->heap);
|
||||
exp_info.size = buffer->len;
|
||||
exp_info.flags = fd_flags;
|
||||
exp_info.priv = buffer;
|
||||
dmabuf = mem_buf_dma_buf_export(&exp_info, &qcom_sg_buf_ops);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
ret = PTR_ERR(dmabuf);
|
||||
goto err_export;
|
||||
}
|
||||
|
||||
up_read(&heap->pool_sem);
|
||||
return dmabuf;
|
||||
|
||||
err_export:
|
||||
mem_buf_vmperm_release(buffer->vmperm);
|
||||
err_vmperm_alloc:
|
||||
sg_free_table(table);
|
||||
err_sg_alloc_table:
|
||||
gen_pool_free(pool->pool, paddr, len);
|
||||
err_tui_pool_alloc:
|
||||
kref_put(&pool->kref, tui_pool_release);
|
||||
err_no_pool:
|
||||
up_read(&heap->pool_sem);
|
||||
kfree(obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static const struct dma_heap_ops tui_heap_ops = {
|
||||
.allocate = tui_heap_allocate,
|
||||
};
|
||||
|
||||
int qcom_tui_carveout_heap_create(struct platform_heap *heap_data)
|
||||
{
|
||||
struct dma_heap_export_info exp_info;
|
||||
struct tui_heap *heap;
|
||||
int ret;
|
||||
|
||||
heap = kzalloc(sizeof(*heap), GFP_KERNEL);
|
||||
if (!heap)
|
||||
return -ENOMEM;
|
||||
|
||||
exp_info.name = heap_data->name;
|
||||
exp_info.ops = &tui_heap_ops;
|
||||
exp_info.priv = heap;
|
||||
|
||||
heap->heap = dma_heap_add(&exp_info);
|
||||
if (IS_ERR(heap->heap)) {
|
||||
ret = PTR_ERR(heap->heap);
|
||||
goto err_dma_heap_add;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_dma_heap_add:
|
||||
kfree(heap);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -31,10 +31,6 @@ int mem_buf_hyp_assign_table(struct sg_table *sgt, u32 *src_vmid, int source_nel
|
|||
int *dest_vmids, int *dest_perms, int dest_nelems);
|
||||
|
||||
#ifdef CONFIG_QCOM_MEM_BUF_DEV_GH
|
||||
|
||||
int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
|
||||
struct gh_acl_desc *mem_buf_vmid_perm_list_to_gh_acl(int *vmids, int *perms,
|
||||
unsigned int nr_acl_entries);
|
||||
struct gh_sgl_desc *mem_buf_sgt_to_gh_sgl_desc(struct sg_table *sgt);
|
||||
|
|
@ -51,16 +47,6 @@ int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
|||
struct mem_buf_lend_kernel_arg *arg);
|
||||
int mem_buf_unassign_mem_gunyah(gh_memparcel_handle_t memparcel_hdl);
|
||||
#else
|
||||
static inline int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline struct gh_acl_desc *mem_buf_vmid_perm_list_to_gh_acl(int *vmids, int *perms,
|
||||
unsigned int nr_acl_entries)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/memory_hotplug.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/qcom_dma_heap.h>
|
||||
#include <linux/qcom_tui_heap.h>
|
||||
|
||||
#include "../../../../drivers/dma-buf/heaps/qcom_sg_ops.h"
|
||||
#include "mem-buf-gh.h"
|
||||
|
|
@ -750,103 +751,6 @@ static void mem_buf_relinquish_memparcel_hdl(void *hdlr_data, u32 obj_id, gh_mem
|
|||
__mem_buf_relinquish_mem(obj_id, hdl);
|
||||
}
|
||||
|
||||
static int get_mem_buf(void *membuf_desc);
|
||||
static int mem_buf_add_dmaheap_mem(struct mem_buf_desc *membuf, struct sg_table *sgt,
|
||||
void *dst_data)
|
||||
{
|
||||
char *heap_name = dst_data;
|
||||
|
||||
return carveout_heap_add_memory(heap_name, sgt, (void *)membuf,
|
||||
get_mem_buf, mem_buf_put);
|
||||
}
|
||||
|
||||
static int mem_buf_add_mem_type(struct mem_buf_desc *membuf, enum mem_buf_mem_type type,
|
||||
void *dst_data, struct sg_table *sgt)
|
||||
{
|
||||
if (type == MEM_BUF_DMAHEAP_MEM_TYPE)
|
||||
return mem_buf_add_dmaheap_mem(membuf, sgt, dst_data);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mem_buf_add_mem(struct mem_buf_desc *membuf)
|
||||
{
|
||||
int i, ret, nr_sgl_entries;
|
||||
struct sg_table sgt;
|
||||
struct scatterlist *sgl;
|
||||
u64 base, size;
|
||||
|
||||
pr_debug("%s: adding memory to destination\n", __func__);
|
||||
nr_sgl_entries = membuf->sgl_desc->n_sgl_entries;
|
||||
ret = sg_alloc_table(&sgt, nr_sgl_entries, GFP_KERNEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_sg(sgt.sgl, sgl, nr_sgl_entries, i) {
|
||||
base = membuf->sgl_desc->sgl_entries[i].ipa_base;
|
||||
size = membuf->sgl_desc->sgl_entries[i].size;
|
||||
sg_set_page(sgl, phys_to_page(base), size, 0);
|
||||
}
|
||||
|
||||
ret = mem_buf_add_mem_type(membuf, membuf->dst_mem_type, membuf->dst_data,
|
||||
&sgt);
|
||||
if (ret)
|
||||
pr_err("%s failed to add memory to destination rc: %d\n",
|
||||
__func__, ret);
|
||||
else
|
||||
pr_debug("%s: memory added to destination\n", __func__);
|
||||
|
||||
sg_free_table(&sgt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_buf_remove_dmaheap_mem(struct sg_table *sgt, void *dst_data)
|
||||
{
|
||||
char *heap_name = dst_data;
|
||||
|
||||
return carveout_heap_remove_memory(heap_name, sgt);
|
||||
}
|
||||
|
||||
static int mem_buf_remove_mem_type(enum mem_buf_mem_type type, void *dst_data,
|
||||
struct sg_table *sgt)
|
||||
{
|
||||
if (type == MEM_BUF_DMAHEAP_MEM_TYPE)
|
||||
return mem_buf_remove_dmaheap_mem(sgt, dst_data);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mem_buf_remove_mem(struct mem_buf_desc *membuf)
|
||||
{
|
||||
int i, ret, nr_sgl_entries;
|
||||
struct sg_table sgt;
|
||||
struct scatterlist *sgl;
|
||||
u64 base, size;
|
||||
|
||||
pr_debug("%s: removing memory from destination\n", __func__);
|
||||
nr_sgl_entries = membuf->sgl_desc->n_sgl_entries;
|
||||
ret = sg_alloc_table(&sgt, nr_sgl_entries, GFP_KERNEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_sg(sgt.sgl, sgl, nr_sgl_entries, i) {
|
||||
base = membuf->sgl_desc->sgl_entries[i].ipa_base;
|
||||
size = membuf->sgl_desc->sgl_entries[i].size;
|
||||
sg_set_page(sgl, phys_to_page(base), size, 0);
|
||||
}
|
||||
|
||||
ret = mem_buf_remove_mem_type(membuf->dst_mem_type, membuf->dst_data,
|
||||
&sgt);
|
||||
if (ret)
|
||||
pr_err("%s failed to remove memory from destination rc: %d\n",
|
||||
__func__, ret);
|
||||
else
|
||||
pr_debug("%s: memory removed from destination\n", __func__);
|
||||
|
||||
sg_free_table(&sgt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *mem_buf_retrieve_dmaheap_mem_type_data_user(
|
||||
struct mem_buf_dmaheap_data __user *udata)
|
||||
{
|
||||
|
|
@ -912,48 +816,14 @@ static void mem_buf_free_mem_type_data(enum mem_buf_mem_type mem_type,
|
|||
mem_buf_free_dmaheap_mem_type_data(mem_type_data);
|
||||
}
|
||||
|
||||
static int mem_buf_buffer_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct mem_buf_desc *membuf = filp->private_data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mem_buf_list_lock);
|
||||
list_del(&membuf->entry);
|
||||
mutex_unlock(&mem_buf_list_lock);
|
||||
|
||||
pr_debug("%s: Destroyng carveout memory\n", __func__);
|
||||
ret = mem_buf_remove_mem(membuf);
|
||||
if (ret < 0)
|
||||
goto out_free_mem;
|
||||
|
||||
ret = mem_buf_unmap_mem_s1(membuf->sgl_desc);
|
||||
if (ret < 0)
|
||||
goto out_free_mem;
|
||||
|
||||
mem_buf_relinquish_mem(membuf);
|
||||
|
||||
out_free_mem:
|
||||
mem_buf_free_mem_type_data(membuf->dst_mem_type, membuf->dst_data);
|
||||
mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
|
||||
kvfree(membuf->sgl_desc);
|
||||
kfree(membuf->acl_desc);
|
||||
kfree(membuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations mem_buf_fops = {
|
||||
.release = mem_buf_buffer_release,
|
||||
};
|
||||
|
||||
static bool is_valid_mem_type(enum mem_buf_mem_type mem_type)
|
||||
{
|
||||
return mem_type == MEM_BUF_DMAHEAP_MEM_TYPE;
|
||||
}
|
||||
|
||||
static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
||||
void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
int ret;
|
||||
struct file *filp;
|
||||
struct mem_buf_desc *membuf;
|
||||
int perms = PERM_READ | PERM_WRITE | PERM_EXEC;
|
||||
|
||||
|
|
@ -971,7 +841,7 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pr_debug("%s: mem buf alloc begin\n", __func__);
|
||||
membuf->size = ALIGN(alloc_data->size, MEM_BUF_MHP_ALIGNMENT);
|
||||
membuf->size = alloc_data->size;
|
||||
|
||||
/* Create copies of data structures from alloc_data as they may be on-stack */
|
||||
membuf->acl_desc = mem_buf_vmid_perm_list_to_gh_acl(
|
||||
|
|
@ -1021,37 +891,13 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
if (ret)
|
||||
goto err_map_mem_s2;
|
||||
|
||||
ret = mem_buf_map_mem_s1(membuf->sgl_desc);
|
||||
if (ret)
|
||||
goto err_map_mem_s1;
|
||||
|
||||
filp = anon_inode_getfile("membuf", &mem_buf_fops, membuf, O_RDWR);
|
||||
if (IS_ERR(filp)) {
|
||||
ret = PTR_ERR(filp);
|
||||
goto err_get_file;
|
||||
}
|
||||
membuf->filp = filp;
|
||||
|
||||
mutex_lock(&mem_buf_list_lock);
|
||||
list_add_tail(&membuf->entry, &mem_buf_list);
|
||||
mutex_unlock(&mem_buf_list_lock);
|
||||
|
||||
ret = mem_buf_add_mem(membuf);
|
||||
if (ret)
|
||||
goto err_add_mem;
|
||||
|
||||
pr_debug("%s: mem buf alloc success\n", __func__);
|
||||
return membuf;
|
||||
|
||||
err_add_mem:
|
||||
fput(filp);
|
||||
return ERR_PTR(ret);
|
||||
err_get_file:
|
||||
if (mem_buf_unmap_mem_s1(membuf->sgl_desc) < 0) {
|
||||
kvfree(membuf->sgl_desc);
|
||||
goto err_mem_req;
|
||||
}
|
||||
err_map_mem_s1:
|
||||
err_map_mem_s2:
|
||||
mem_buf_relinquish_mem(membuf);
|
||||
err_mem_req:
|
||||
|
|
@ -1068,82 +914,22 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int _mem_buf_get_fd(struct file *filp)
|
||||
void mem_buf_free(void *__membuf)
|
||||
{
|
||||
int fd;
|
||||
struct mem_buf_desc *membuf = __membuf;
|
||||
|
||||
if (!filp)
|
||||
return -EINVAL;
|
||||
mutex_lock(&mem_buf_list_lock);
|
||||
list_del(&membuf->entry);
|
||||
mutex_unlock(&mem_buf_list_lock);
|
||||
|
||||
fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
fd_install(fd, filp);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int mem_buf_get_fd(void *membuf_desc)
|
||||
{
|
||||
struct mem_buf_desc *membuf = membuf_desc;
|
||||
|
||||
if (!membuf_desc)
|
||||
return -EINVAL;
|
||||
|
||||
return _mem_buf_get_fd(membuf->filp);
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_get_fd);
|
||||
|
||||
static void _mem_buf_put(struct file *filp)
|
||||
{
|
||||
fput(filp);
|
||||
}
|
||||
|
||||
void mem_buf_put(void *membuf_desc)
|
||||
{
|
||||
struct mem_buf_desc *membuf = membuf_desc;
|
||||
|
||||
if (membuf && membuf->filp)
|
||||
_mem_buf_put(membuf->filp);
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_put);
|
||||
|
||||
static bool is_mem_buf_file(struct file *filp)
|
||||
{
|
||||
return filp->f_op == &mem_buf_fops;
|
||||
}
|
||||
|
||||
void *mem_buf_get(int fd)
|
||||
{
|
||||
struct file *filp;
|
||||
|
||||
filp = fget(fd);
|
||||
|
||||
if (!filp)
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
if (!is_mem_buf_file(filp)) {
|
||||
fput(filp);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return filp->private_data;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_get);
|
||||
|
||||
static int get_mem_buf(void *membuf_desc)
|
||||
{
|
||||
struct mem_buf_desc *membuf = membuf_desc;
|
||||
|
||||
/*
|
||||
* get_file_rcu used for atomic_long_inc_unless_zero.
|
||||
* It returns 0 if file count is already zero.
|
||||
*/
|
||||
if (!get_file_rcu(membuf->filp))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
mem_buf_relinquish_mem(membuf);
|
||||
kvfree(membuf->sgl_desc);
|
||||
mem_buf_free_mem_type_data(membuf->dst_mem_type, membuf->dst_data);
|
||||
mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
|
||||
kfree(membuf->acl_desc);
|
||||
kfree(membuf);
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_free);
|
||||
|
||||
struct gh_sgl_desc *mem_buf_get_sgl(void *__membuf)
|
||||
{
|
||||
|
|
@ -1306,7 +1092,6 @@ static void mem_buf_free_alloc_data(struct mem_buf_allocation_data *alloc_data)
|
|||
|
||||
int mem_buf_alloc_fd(struct mem_buf_alloc_ioctl_arg *allocation_args)
|
||||
{
|
||||
struct mem_buf_desc *membuf;
|
||||
struct mem_buf_allocation_data alloc_data;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1323,19 +1108,11 @@ int mem_buf_alloc_fd(struct mem_buf_alloc_ioctl_arg *allocation_args)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Only donate is supported currently */
|
||||
alloc_data.trans_type = GH_RM_TRANS_TYPE_DONATE;
|
||||
membuf = mem_buf_alloc(&alloc_data);
|
||||
if (IS_ERR(membuf)) {
|
||||
ret = PTR_ERR(membuf);
|
||||
goto out;
|
||||
}
|
||||
if (alloc_data.dst_mem_type == MEM_BUF_DMAHEAP_MEM_TYPE)
|
||||
ret = qcom_tui_heap_add_pool_fd(&alloc_data);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
ret = mem_buf_get_fd(membuf);
|
||||
if (ret < 0)
|
||||
mem_buf_put(membuf);
|
||||
|
||||
out:
|
||||
mem_buf_free_alloc_data(&alloc_data);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,32 +98,37 @@ int mem_buf_reclaim(struct dma_buf *dmabuf);
|
|||
|
||||
#if IS_ENABLED(CONFIG_QCOM_MEM_BUF)
|
||||
|
||||
int mem_buf_get_fd(void *membuf_desc);
|
||||
|
||||
void mem_buf_put(void *membuf_desc);
|
||||
|
||||
void *mem_buf_get(int fd);
|
||||
|
||||
void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data);
|
||||
void mem_buf_free(void *membuf);
|
||||
struct gh_sgl_desc *mem_buf_get_sgl(void *membuf);
|
||||
#else
|
||||
|
||||
static inline int mem_buf_get_fd(void *membuf_desc)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void mem_buf_put(void *membuf_desc)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void *mem_buf_get(int fd)
|
||||
static inline void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline void mem_buf_free(void *membuf) {}
|
||||
|
||||
static inline struct gh_sgl_desc *mem_buf_get_sgl(void *membuf)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
#endif /* CONFIG_QCOM_MEM_BUF */
|
||||
|
||||
|
||||
#ifdef CONFIG_QCOM_MEM_BUF_DEV_GH
|
||||
int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
#else
|
||||
static inline int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_QCOM_MEM_BUF_DEV_GH */
|
||||
#endif /* _MEM_BUF_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _QCOM_DMA_HEAP_H
|
||||
#define _QCOM_DMA_HEAP_H
|
||||
|
|
@ -36,29 +37,6 @@
|
|||
|
||||
#define QCOM_DMA_HEAP_FLAG_SECURE BIT(31)
|
||||
|
||||
/**
|
||||
* carveout_heap_add_memory - Dynamically add reserved heap memory
|
||||
* @heap_name: The name of the DMA-BUF Heap we're giving memory to
|
||||
* @sgt: An SGT corresponding to the memory adding to the heap
|
||||
* @cookie: Cookie for managing refcount.
|
||||
* @get: Function callback for increasing refcount.
|
||||
* @put: Function callback for decreasing refcount.
|
||||
*
|
||||
* Return: 0 on success, a negative error value otherwise.
|
||||
*/
|
||||
int carveout_heap_add_memory(char *heap_name, struct sg_table *sgt, void *cookie,
|
||||
int (*get)(void *), void (*put)(void *));
|
||||
|
||||
|
||||
/**
|
||||
* carveout_heap_remove_memory - Dynamically remove reserved heap memory
|
||||
* @heap_name: The name of the DMA-BUF Heap we're taking memory away from
|
||||
* @sgt: An SGT corresponding to the memory we're removing from the heap
|
||||
*
|
||||
* Return: 0 on success, a negative error value otherwise.
|
||||
*/
|
||||
int carveout_heap_remove_memory(char *heap_name, struct sg_table *sgt);
|
||||
|
||||
struct dma_buf_heap_prefetch_region {
|
||||
u64 size;
|
||||
struct dma_heap *heap;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _QCOM_DMA_HEAP_DT_CONSTATS_H
|
||||
#define _QCOM_DMA_HEAP_DT_CONSTATS_H
|
||||
|
|
@ -8,5 +9,6 @@
|
|||
#define HEAP_TYPE_SECURE_CARVEOUT 0
|
||||
#define HEAP_TYPE_CARVEOUT 1
|
||||
#define HEAP_TYPE_CMA 2
|
||||
#define HEAP_TYPE_TUI_CARVEOUT 3
|
||||
|
||||
#endif /* _QCOM_DMA_HEAP_DT_CONSTATS_H */
|
||||
|
|
|
|||
28
include/linux/qcom_tui_heap.h
Normal file
28
include/linux/qcom_tui_heap.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _QCOM_TUI_HEAP_H
|
||||
#define _QCOM_TUI_HEAP_H
|
||||
|
||||
#include <linux/mem-buf.h>
|
||||
|
||||
struct platform_heap;
|
||||
|
||||
#ifdef CONFIG_QCOM_DMABUF_HEAPS_TUI_CARVEOUT
|
||||
int qcom_tui_carveout_heap_create(struct platform_heap *heap_data);
|
||||
int qcom_tui_heap_add_pool_fd(struct mem_buf_allocation_data *alloc_data);
|
||||
#else
|
||||
static inline int qcom_tui_carveout_heap_create(struct platform_heap *heap_data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int qcom_tui_heap_add_pool_fd(struct mem_buf_allocation_data *alloc_data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _QCOM_TUI_HEAP_H */
|
||||
Loading…
Reference in New Issue
Block a user