video: rockchip: rga3: Remove useless memory maps

Update driver version to 1.2.16

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I655c4cbc7dcf91769a978ad61700c43fb0e97d90
This commit is contained in:
Yu Qiaowei
2022-07-07 14:33:26 +08:00
parent 88d6006732
commit 759eaa8274
4 changed files with 333 additions and 346 deletions

View File

@@ -86,7 +86,7 @@
#define DRIVER_MAJOR_VERISON 1
#define DRIVER_MINOR_VERSION 2
#define DRIVER_REVISION_VERSION 15
#define DRIVER_REVISION_VERSION 16
#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \
"." STR(DRIVER_REVISION_VERSION))
@@ -185,7 +185,6 @@ struct rga_virt_addr {
struct rga_internal_buffer {
/* DMA buffer */
struct rga_dma_buffer *dma_buffer;
uint32_t dma_buffer_size;
/* virtual address */
struct rga_virt_addr *virt_addr;

View File

@@ -37,13 +37,16 @@ struct rga_mm {
static inline bool rga_mm_is_invalid_dma_buffer(struct rga_dma_buffer *buffer)
{
if (buffer == NULL)
return true;
return buffer->scheduler == NULL ? true : false;
}
struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle);
int rga_mm_lookup_flag(struct rga_mm *mm_session, uint64_t handle);
dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core);
struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core);
dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer);
struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer);
void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer);
void rga_mm_dump_info(struct rga_mm *session);

View File

@@ -235,7 +235,7 @@ static int rga_scheduler_show(struct seq_file *m, void *data)
static int rga_mm_session_show(struct seq_file *m, void *data)
{
int id, i;
int id;
struct rga_mm *mm_session = NULL;
struct rga_internal_buffer *dump_buffer;
@@ -255,36 +255,45 @@ static int rga_mm_session_show(struct seq_file *m, void *data)
switch (dump_buffer->type) {
case RGA_DMA_BUFFER:
case RGA_DMA_BUFFER_PTR:
seq_puts(m, "dma_buffer:\n");
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer))
break;
seq_puts(m, "dma_buffer:\n");
seq_printf(m, "\t dma_buf = %p, iova = 0x%lxsgt = 0x%p, size = %ld, map_core = 0x%x\n",
dump_buffer->dma_buffer->dma_buf,
(unsigned long)dump_buffer->dma_buffer->iova,
dump_buffer->dma_buffer->sgt,
dump_buffer->dma_buffer->size,
dump_buffer->dma_buffer->scheduler->core);
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
seq_printf(m, "\t is contiguous, pa = 0x%lx\n",
(unsigned long)dump_buffer->phys_addr);
seq_printf(m, "\t core %d:\n",
dump_buffer->dma_buffer[i].scheduler->core);
seq_printf(m, "\t\t dma_buf = %p, iova = 0x%lx\n",
dump_buffer->dma_buffer[i].dma_buf,
(unsigned long)dump_buffer->dma_buffer[i].iova);
}
break;
case RGA_VIRTUAL_ADDRESS:
if (dump_buffer->virt_addr == NULL)
break;
seq_puts(m, "virtual address:\n");
seq_printf(m, "\t va = 0x%lx, pages = %p, size = %ld\n",
seq_printf(m, "\t va = 0x%lx, pages = 0x%p, size = %ld\n",
(unsigned long)dump_buffer->virt_addr->addr,
dump_buffer->virt_addr->pages,
dump_buffer->virt_addr->size);
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer))
break;
seq_printf(m, "\t iova = 0x%lx, offset = 0x%lx, sgt = 0x%p, size = %ld, map_core = 0x%x\n",
(unsigned long)dump_buffer->dma_buffer->iova,
(unsigned long)dump_buffer->dma_buffer->offset,
dump_buffer->dma_buffer->sgt,
dump_buffer->dma_buffer->size,
dump_buffer->dma_buffer->scheduler->core);
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
seq_printf(m, "\t is contiguous, pa = 0x%lx\n",
(unsigned long)dump_buffer->phys_addr);
seq_printf(m, "\t core %d:\n",
dump_buffer->dma_buffer[i].scheduler->core);
seq_printf(m, "\t\t iova = 0x%lx, sgt = %p, size = %ld\n",
(unsigned long)dump_buffer->dma_buffer[i].iova,
dump_buffer->dma_buffer[i].sgt,
dump_buffer->dma_buffer[i].size);
}
break;
case RGA_PHYSICAL_ADDRESS:
seq_puts(m, "physical address:\n");

View File

@@ -155,47 +155,43 @@ static int rga_get_user_pages(struct page **pages, unsigned long Memory,
return ret;
}
static void rga_free_sgt(struct rga_dma_buffer *virt_dma_buf)
static void rga_free_sgt(struct sg_table **sgt_ptr)
{
if (virt_dma_buf->sgt == NULL)
if (sgt_ptr == NULL || *sgt_ptr == NULL)
return;
sg_free_table(virt_dma_buf->sgt);
kfree(virt_dma_buf->sgt);
virt_dma_buf->sgt = NULL;
sg_free_table(*sgt_ptr);
kfree(*sgt_ptr);
*sgt_ptr = NULL;
}
static int rga_alloc_sgt(struct rga_virt_addr *virt_addr,
struct rga_dma_buffer *virt_dma_buf)
static struct sg_table *rga_alloc_sgt(struct rga_virt_addr *virt_addr)
{
int ret;
struct sg_table *sgt = NULL;
sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (sgt == NULL) {
pr_err("%s alloc sgt error!\n", __func__);
return -ENOMEM;
return ERR_PTR(-ENOMEM);
}
/* get sg form pages. */
if (sg_alloc_table_from_pages(sgt, virt_addr->pages,
virt_addr->page_count, 0,
virt_addr->size, GFP_KERNEL)) {
ret = sg_alloc_table_from_pages(sgt, virt_addr->pages,
virt_addr->page_count,
0, virt_addr->size,
GFP_KERNEL);
if (ret) {
pr_err("sg_alloc_table_from_pages failed");
ret = -ENOMEM;
goto out_free_sgt;
}
virt_dma_buf->sgt = sgt;
virt_dma_buf->size = virt_addr->size;
virt_dma_buf->offset = virt_addr->offset;
return 0;
return sgt;
out_free_sgt:
kfree(sgt);
return ret;
return ERR_PTR(ret);
}
static void rga_free_virt_addr(struct rga_virt_addr **virt_addr_p)
@@ -341,20 +337,14 @@ static inline bool rga_mm_check_contiguous_sgt(struct sg_table *sgt)
static void rga_mm_unmap_dma_buffer(struct rga_internal_buffer *internal_buffer)
{
int i;
if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer))
return;
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i]))
continue;
rga_dma_unmap_buf(internal_buffer->dma_buffer);
rga_dma_unmap_buf(&internal_buffer->dma_buffer[i]);
if (i == 0 &&
internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
internal_buffer->phys_addr > 0) {
internal_buffer->phys_addr = 0;
}
}
if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
internal_buffer->phys_addr > 0)
internal_buffer->phys_addr = 0;
kfree(internal_buffer->dma_buffer);
internal_buffer->dma_buffer = NULL;
@@ -364,110 +354,112 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer,
struct rga_internal_buffer *internal_buffer,
struct rga_job *job)
{
int ret, i;
struct rga_scheduler_t *scheduler = NULL;
int ret;
struct rga_dma_buffer *buffer;
struct device *map_dev;
struct rga_scheduler_t *scheduler;
internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler;
internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size,
sizeof(struct rga_dma_buffer), GFP_KERNEL);
if (internal_buffer->dma_buffer == NULL) {
scheduler = job ? job->scheduler :
rga_drvdata->scheduler[rga_drvdata->map_scheduler_index];
if (scheduler == NULL) {
pr_err("Invalid scheduler device!\n");
return -EINVAL;
}
/*
* dma-buf api needs to use default_domain of main dev,
* and not IOMMU for devices without iommu_info ptr.
*/
map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev;
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
pr_err("%s alloc internal_buffer error!\n", __func__);
return -ENOMEM;
}
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
scheduler = job ? job->scheduler : rga_drvdata->scheduler[i];
/* If the physical address is greater than 4G, there is no need to map RAG_MMU. */
if (i != 0)
if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag))
continue;
if (scheduler->data->mmu == RGA_MMU &&
~internal_buffer->mm_flag & RGA_MEM_UNDER_4G &&
i != 0)
continue;
if (external_buffer->type == RGA_DMA_BUFFER)
ret = rga_dma_map_fd((int)external_buffer->memory,
&internal_buffer->dma_buffer[i],
DMA_BIDIRECTIONAL,
scheduler->dev);
else if (external_buffer->type == RGA_DMA_BUFFER_PTR)
ret = rga_dma_map_buf((struct dma_buf *)
u64_to_user_ptr(external_buffer->memory),
&internal_buffer->dma_buffer[i],
DMA_BIDIRECTIONAL,
scheduler->dev);
else
ret = -EFAULT;
if (ret < 0) {
pr_err("%s core[%d] map dma buffer error!\n",
__func__, scheduler->core);
goto FREE_RGA_DMA_BUF;
}
internal_buffer->dma_buffer[i].scheduler = scheduler;
/* At first, check whether the physical address. */
if (i == 0) {
if (rga_mm_check_range_sgt(internal_buffer->dma_buffer[0].sgt))
internal_buffer->mm_flag |= RGA_MEM_UNDER_4G;
/*
* If it's physically contiguous, then the RGA_MMU can
* directly use the physical address.
*/
if (rga_mm_check_contiguous_sgt(internal_buffer->dma_buffer[0].sgt)) {
internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
internal_buffer->phys_addr =
sg_phys(internal_buffer->dma_buffer[0].sgt->sgl);
if (internal_buffer->phys_addr == 0) {
pr_err("%s get physical address error!", __func__);
goto FREE_RGA_DMA_BUF;
}
}
}
switch (external_buffer->type) {
case RGA_DMA_BUFFER:
ret = rga_dma_map_fd((int)external_buffer->memory,
buffer, DMA_BIDIRECTIONAL,
map_dev);
break;
case RGA_DMA_BUFFER_PTR:
ret = rga_dma_map_buf((struct dma_buf *)u64_to_user_ptr(external_buffer->memory),
buffer, DMA_BIDIRECTIONAL,
map_dev);
break;
default:
ret = -EFAULT;
break;
}
if (ret < 0) {
pr_err("%s core[%d] map dma buffer error!\n",
__func__, scheduler->core);
goto free_buffer;
}
buffer->scheduler = scheduler;
if (rga_mm_check_range_sgt(buffer->sgt))
internal_buffer->mm_flag |= RGA_MEM_UNDER_4G;
/*
* If it's physically contiguous, then the RGA_MMU can
* directly use the physical address.
*/
if (rga_mm_check_contiguous_sgt(buffer->sgt)) {
internal_buffer->phys_addr = sg_phys(buffer->sgt->sgl);
if (internal_buffer->phys_addr == 0) {
pr_err("%s get physical address error!", __func__);
goto unmap_buffer;
}
internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
}
internal_buffer->dma_buffer = buffer;
return 0;
FREE_RGA_DMA_BUF:
rga_mm_unmap_dma_buffer(internal_buffer);
unmap_buffer:
rga_dma_unmap_buf(buffer);
free_buffer:
kfree(buffer);
return ret;
}
static void rga_mm_unmap_virt_addr(struct rga_internal_buffer *internal_buffer)
{
int i;
WARN_ON(internal_buffer->dma_buffer == NULL || internal_buffer->virt_addr == NULL);
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer))
return;
switch (internal_buffer->dma_buffer[i].scheduler->data->mmu) {
case RGA_IOMMU:
rga_iommu_unmap(&internal_buffer->dma_buffer[i]);
break;
case RGA_MMU:
dma_unmap_sg(internal_buffer->dma_buffer[i].scheduler->dev,
internal_buffer->dma_buffer[i].sgt->sgl,
internal_buffer->dma_buffer[i].sgt->orig_nents,
DMA_BIDIRECTIONAL);
break;
default:
break;
}
switch (internal_buffer->dma_buffer->scheduler->data->mmu) {
case RGA_IOMMU:
rga_iommu_unmap(internal_buffer->dma_buffer);
break;
case RGA_MMU:
dma_unmap_sg(internal_buffer->dma_buffer->scheduler->dev,
internal_buffer->dma_buffer->sgt->sgl,
internal_buffer->dma_buffer->sgt->orig_nents,
DMA_BIDIRECTIONAL);
break;
default:
break;
}
for (i = 0; i < internal_buffer->dma_buffer_size; i++)
rga_free_sgt(&internal_buffer->dma_buffer[i]);
if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
internal_buffer->phys_addr > 0)
internal_buffer->phys_addr = 0;
rga_free_sgt(&internal_buffer->dma_buffer->sgt);
kfree(internal_buffer->dma_buffer);
internal_buffer->dma_buffer = NULL;
internal_buffer->dma_buffer_size = 0;
rga_free_virt_addr(&internal_buffer->virt_addr);
@@ -480,9 +472,20 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
struct rga_internal_buffer *internal_buffer,
struct rga_job *job, int write_flag)
{
int i;
int ret;
struct rga_scheduler_t *scheduler = NULL;
uint32_t mm_flag = 0;
phys_addr_t phys_addr = 0;
struct sg_table *sgt;
struct rga_virt_addr *virt_addr;
struct rga_dma_buffer *buffer;
struct rga_scheduler_t *scheduler;
scheduler = job ? job->scheduler :
rga_drvdata->scheduler[rga_drvdata->map_scheduler_index];
if (scheduler == NULL) {
pr_err("Invalid scheduler device!\n");
return -EINVAL;
}
internal_buffer->current_mm = current->mm;
if (internal_buffer->current_mm == NULL) {
@@ -492,7 +495,7 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
mmgrab(internal_buffer->current_mm);
mmget(internal_buffer->current_mm);
ret = rga_alloc_virt_addr(&internal_buffer->virt_addr,
ret = rga_alloc_virt_addr(&virt_addr,
external_buffer->memory,
&internal_buffer->memory_parm,
write_flag, internal_buffer->current_mm);
@@ -502,105 +505,86 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
goto put_current_mm;
}
internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler;
internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size,
sizeof(struct rga_dma_buffer), GFP_KERNEL);
if (internal_buffer->dma_buffer == NULL) {
pr_err("%s alloc internal_buffer->dma_buffer error!\n", __func__);
ret = -ENOMEM;
sgt = rga_alloc_sgt(virt_addr);
if (IS_ERR(sgt)) {
pr_err("alloc sgt error!\n");
ret = PTR_ERR(sgt);
goto free_virt_addr;
}
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
scheduler = job ? job->scheduler : rga_drvdata->scheduler[i];
if (rga_mm_check_range_sgt(sgt))
mm_flag |= RGA_MEM_UNDER_4G;
/* If the physical address is greater than 4G, there is no need to map RGA_MMU. */
if (scheduler->data->mmu == RGA_MMU &&
~internal_buffer->mm_flag & RGA_MEM_UNDER_4G &&
i != 0)
continue;
if (rga_mm_check_contiguous_sgt(sgt)) {
phys_addr = sg_phys(sgt->sgl);
if (phys_addr == 0) {
pr_err("%s get physical address error!", __func__);
goto free_sgt;
}
ret = rga_alloc_sgt(internal_buffer->virt_addr,
&internal_buffer->dma_buffer[i]);
mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
}
if (!rga_mm_check_memory_limit(scheduler, mm_flag)) {
pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n",
scheduler->core, mm_flag);
ret = -EINVAL;
goto free_sgt;
}
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
pr_err("%s alloc internal dma_buffer error!\n", __func__);
ret = -ENOMEM;
goto free_sgt;
}
switch (scheduler->data->mmu) {
case RGA_IOMMU:
ret = rga_iommu_map_sgt(sgt, virt_addr->size, buffer, scheduler->dev);
if (ret < 0) {
pr_err("%s core[%d] alloc sgt error!\n", __func__,
scheduler->core);
goto free_sgt_and_dma_buffer;
pr_err("%s core[%d] iommu_map virtual address error!\n",
__func__, scheduler->core);
goto free_dma_buffer;
}
break;
case RGA_MMU:
ret = dma_map_sg(scheduler->dev, sgt->sgl, sgt->orig_nents, DMA_BIDIRECTIONAL);
if (ret == 0) {
pr_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n",
__func__, scheduler->core,
(unsigned long)virt_addr->addr, sgt->orig_nents);
ret = -EINVAL;
goto free_dma_buffer;
}
break;
default:
if (mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
break;
if (i == 0)
if (rga_mm_check_range_sgt(internal_buffer->dma_buffer[0].sgt))
internal_buffer->mm_flag |= RGA_MEM_UNDER_4G;
pr_err("Current RGA mmu[%d] cannot support virtual address!\n",
scheduler->data->mmu);
goto free_dma_buffer;
}
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
scheduler = job ? job->scheduler : rga_drvdata->scheduler[i];
buffer->sgt = sgt;
buffer->offset = virt_addr->offset;
buffer->size = virt_addr->size;
buffer->scheduler = scheduler;
if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag))
continue;
switch (scheduler->data->mmu) {
case RGA_IOMMU:
ret = rga_iommu_map_sgt(internal_buffer->dma_buffer[i].sgt,
internal_buffer->dma_buffer[i].size,
&internal_buffer->dma_buffer[i],
scheduler->dev);
if (ret < 0) {
pr_err("%s core[%d] iommu_map virtual address error!\n",
__func__, scheduler->core);
goto unmap_virt_addr;
}
break;
case RGA_MMU:
ret = dma_map_sg(scheduler->dev,
internal_buffer->dma_buffer[i].sgt->sgl,
internal_buffer->dma_buffer[i].sgt->orig_nents,
DMA_BIDIRECTIONAL);
if (ret == 0) {
pr_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n",
__func__, scheduler->core,
(unsigned long)internal_buffer->virt_addr->addr,
internal_buffer->dma_buffer[i].sgt->orig_nents);
ret = -EINVAL;
goto unmap_virt_addr;
}
break;
default:
pr_err("Current RGA mmu[%d] cannot support virtual address!\n",
scheduler->data->mmu);
goto free_sgt_and_dma_buffer;
}
internal_buffer->dma_buffer[i].scheduler = scheduler;
}
internal_buffer->virt_addr = virt_addr;
internal_buffer->dma_buffer = buffer;
internal_buffer->mm_flag = mm_flag;
internal_buffer->phys_addr = phys_addr ? phys_addr : 0;
return 0;
unmap_virt_addr:
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i]))
continue;
switch (internal_buffer->dma_buffer[i].scheduler->data->mmu) {
case RGA_IOMMU:
rga_iommu_unmap(&internal_buffer->dma_buffer[i]);
break;
case RGA_MMU:
dma_unmap_sg(internal_buffer->dma_buffer[i].scheduler->dev,
internal_buffer->dma_buffer[i].sgt->sgl,
internal_buffer->dma_buffer[i].sgt->orig_nents,
DMA_BIDIRECTIONAL);
break;
default:
break;
}
}
free_sgt_and_dma_buffer:
for (i = 0; i < internal_buffer->dma_buffer_size; i++)
rga_free_sgt(&internal_buffer->dma_buffer[i]);
kfree(internal_buffer->dma_buffer);
free_dma_buffer:
kfree(buffer);
free_sgt:
rga_free_sgt(&sgt);
free_virt_addr:
rga_free_virt_addr(&internal_buffer->virt_addr);
rga_free_virt_addr(&virt_addr);
put_current_mm:
mmput(internal_buffer->current_mm);
mmdrop(internal_buffer->current_mm);
@@ -611,82 +595,83 @@ put_current_mm:
static void rga_mm_unmap_phys_addr(struct rga_internal_buffer *internal_buffer)
{
int i;
WARN_ON(internal_buffer->dma_buffer == NULL);
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer))
return;
if (internal_buffer->dma_buffer[i].scheduler->data->mmu == RGA_IOMMU)
rga_iommu_unmap(&internal_buffer->dma_buffer[i]);
}
internal_buffer->phys_addr = 0;
if (internal_buffer->dma_buffer->scheduler->data->mmu == RGA_IOMMU)
rga_iommu_unmap(internal_buffer->dma_buffer);
kfree(internal_buffer->dma_buffer);
internal_buffer->dma_buffer = NULL;
internal_buffer->dma_buffer_size = 0;
internal_buffer->phys_addr = 0;
internal_buffer->size = 0;
}
static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
struct rga_internal_buffer *internal_buffer,
struct rga_job *job)
{
int ret, i;
struct rga_scheduler_t *scheduler = NULL;
int ret;
phys_addr_t phys_addr;
int buffer_size;
uint32_t mm_flag = 0;
struct rga_dma_buffer *buffer;
struct rga_scheduler_t *scheduler;
internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler;
internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size,
sizeof(struct rga_dma_buffer), GFP_KERNEL);
if (internal_buffer->dma_buffer == NULL) {
pr_err("%s alloc internal_buffer error!\n", __func__);
scheduler = job ? job->scheduler :
rga_drvdata->scheduler[rga_drvdata->map_scheduler_index];
if (scheduler == NULL) {
pr_err("Invalid scheduler device!\n");
return -EINVAL;
}
if (internal_buffer->memory_parm.size)
buffer_size = internal_buffer->memory_parm.size;
else
buffer_size = rga_image_size_cal(internal_buffer->memory_parm.width,
internal_buffer->memory_parm.height,
internal_buffer->memory_parm.format,
NULL, NULL, NULL);
if (buffer_size <= 0) {
pr_err("Fault to get phys addr size!\n");
return buffer_size == 0 ? -EINVAL : buffer_size;
}
phys_addr = external_buffer->memory;
mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
if (rga_mm_check_range_phys_addr(phys_addr, buffer_size))
mm_flag |= RGA_MEM_UNDER_4G;
if (!rga_mm_check_memory_limit(scheduler, mm_flag)) {
pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n",
scheduler->core, mm_flag);
return -EINVAL;
}
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
pr_err("%s alloc internal dma buffer error!\n", __func__);
return -ENOMEM;
}
internal_buffer->phys_addr = external_buffer->memory;
if (internal_buffer->memory_parm.size)
internal_buffer->size = internal_buffer->memory_parm.size;
else
internal_buffer->size =
rga_image_size_cal(internal_buffer->memory_parm.width,
internal_buffer->memory_parm.height,
internal_buffer->memory_parm.format,
NULL, NULL, NULL);
internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
if (rga_mm_check_range_phys_addr(internal_buffer->phys_addr, internal_buffer->size))
internal_buffer->mm_flag |= RGA_MEM_UNDER_4G;
for (i = 0; i < internal_buffer->dma_buffer_size; i++) {
scheduler = job ? job->scheduler : rga_drvdata->scheduler[i];
if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag))
continue;
if (scheduler->data->mmu == RGA_IOMMU) {
ret = rga_iommu_map(internal_buffer->phys_addr,
internal_buffer->size,
&internal_buffer->dma_buffer[i],
scheduler->dev);
if (ret < 0) {
pr_err("%s core[%d] map phys_addr error!\n",
__func__, scheduler->core);
goto UNMAP_PHYS_ADDR;
}
if (scheduler->data->mmu == RGA_IOMMU) {
ret = rga_iommu_map(phys_addr, buffer_size, buffer, scheduler->dev);
if (ret < 0) {
pr_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core);
return ret;
}
internal_buffer->dma_buffer[i].scheduler = scheduler;
}
buffer->scheduler = scheduler;
internal_buffer->phys_addr = phys_addr;
internal_buffer->size = buffer_size;
internal_buffer->mm_flag = mm_flag;
internal_buffer->dma_buffer = buffer;
return 0;
UNMAP_PHYS_ADDR:
rga_mm_unmap_phys_addr(internal_buffer);
return ret;
}
static int rga_mm_unmap_buffer(struct rga_internal_buffer *internal_buffer)
@@ -886,40 +871,24 @@ int rga_mm_lookup_flag(struct rga_mm *mm_session, uint64_t handle)
return output_buffer->mm_flag;
}
dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core)
dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer)
{
int i;
if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer))
return 0;
for (i = 0; i < buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&buffer->dma_buffer[i]))
continue;
if (buffer->dma_buffer[i].scheduler->core == core)
return buffer->dma_buffer[i].iova + buffer->dma_buffer[i].offset;
}
return 0;
return buffer->dma_buffer->iova + buffer->dma_buffer->offset;
}
struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core)
struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer)
{
int i;
if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer))
return NULL;
for (i = 0; i < buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&buffer->dma_buffer[i]))
continue;
if (buffer->dma_buffer[i].scheduler->core == core)
return buffer->dma_buffer[i].sgt;
}
return NULL;
return buffer->dma_buffer->sgt;
}
void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer)
{
int i;
pr_info("handle = %d refcount = %d mm_flag = 0x%x\n",
dump_buffer->handle, kref_read(&dump_buffer->refcount),
dump_buffer->mm_flag);
@@ -927,37 +896,44 @@ void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer)
switch (dump_buffer->type) {
case RGA_DMA_BUFFER:
case RGA_DMA_BUFFER_PTR:
pr_info("dma_buffer:\n");
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer))
break;
pr_info("core %d: dma_buf = %p, iova = 0x%lx\n",
dump_buffer->dma_buffer[i].scheduler->core,
dump_buffer->dma_buffer[i].dma_buf,
(unsigned long)dump_buffer->dma_buffer[i].iova);
}
pr_info("dma_buffer:\n");
pr_info("dma_buf = %p, iova = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n",
dump_buffer->dma_buffer->dma_buf,
(unsigned long)dump_buffer->dma_buffer->iova,
dump_buffer->dma_buffer->sgt,
dump_buffer->dma_buffer->size,
dump_buffer->dma_buffer->scheduler->core);
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
pr_info("is contiguous, pa = 0x%lx\n",
(unsigned long)dump_buffer->phys_addr);
break;
case RGA_VIRTUAL_ADDRESS:
pr_info("virtual address: va = 0x%lx, pages = %p, size = %ld\n",
if (dump_buffer->virt_addr == NULL)
break;
pr_info("virtual address:\n");
pr_info("va = 0x%lx, pages = %p, size = %ld\n",
(unsigned long)dump_buffer->virt_addr->addr,
dump_buffer->virt_addr->pages,
dump_buffer->virt_addr->size);
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i]))
continue;
if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer))
break;
pr_info("core %d: iova = 0x%lx, sgt = %p, size = %ld\n",
dump_buffer->dma_buffer[i].scheduler->core,
(unsigned long)dump_buffer->dma_buffer[i].iova,
dump_buffer->dma_buffer[i].sgt,
dump_buffer->dma_buffer[i].size);
}
pr_info("iova = 0x%lx, offset = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n",
(unsigned long)dump_buffer->dma_buffer->iova,
(unsigned long)dump_buffer->dma_buffer->offset,
dump_buffer->dma_buffer->sgt,
dump_buffer->dma_buffer->size,
dump_buffer->dma_buffer->scheduler->core);
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
pr_info("is contiguous, pa = 0x%lx\n",
(unsigned long)dump_buffer->phys_addr);
break;
case RGA_PHYSICAL_ADDRESS:
pr_info("physical address: pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr);
@@ -1152,7 +1128,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
mutex_unlock(&rga_drvdata->lock);
}
sgt = rga_mm_lookup_sgt(job_buf->y_addr, job->core);
sgt = rga_mm_lookup_sgt(job_buf->y_addr);
if (sgt == NULL) {
pr_err("rga2 cannot get sgt from internal buffer!\n");
ret = -EINVAL;
@@ -1160,7 +1136,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
}
rga_mm_sgt_to_page_table(sgt, page_table, yrgb_count, false);
sgt = rga_mm_lookup_sgt(job_buf->uv_addr, job->core);
sgt = rga_mm_lookup_sgt(job_buf->uv_addr);
if (sgt == NULL) {
pr_err("rga2 cannot get sgt from internal buffer!\n");
ret = -EINVAL;
@@ -1168,7 +1144,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
}
rga_mm_sgt_to_page_table(sgt, page_table + yrgb_count, uv_count, false);
sgt = rga_mm_lookup_sgt(job_buf->v_addr, job->core);
sgt = rga_mm_lookup_sgt(job_buf->v_addr);
if (sgt == NULL) {
pr_err("rga2 cannot get sgt from internal buffer!\n");
ret = -EINVAL;
@@ -1211,7 +1187,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
mutex_unlock(&rga_drvdata->lock);
}
sgt = rga_mm_lookup_sgt(job_buf->addr, job->core);
sgt = rga_mm_lookup_sgt(job_buf->addr);
if (sgt == NULL) {
pr_err("rga2 cannot get sgt from internal buffer!\n");
ret = -EINVAL;
@@ -1242,20 +1218,20 @@ static int rga_mm_sync_dma_sg_for_device(struct rga_internal_buffer *buffer,
struct sg_table *sgt;
struct rga_scheduler_t *scheduler;
scheduler = rga_job_get_scheduler(job);
if (scheduler == NULL) {
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EFAULT;
}
sgt = rga_mm_lookup_sgt(buffer, job->core);
sgt = rga_mm_lookup_sgt(buffer);
if (sgt == NULL) {
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EINVAL;
}
scheduler = buffer->dma_buffer->scheduler;
if (scheduler == NULL) {
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EFAULT;
}
dma_sync_sg_for_device(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
return 0;
@@ -1268,20 +1244,20 @@ static int rga_mm_sync_dma_sg_for_cpu(struct rga_internal_buffer *buffer,
struct sg_table *sgt;
struct rga_scheduler_t *scheduler;
scheduler = rga_job_get_scheduler(job);
if (scheduler == NULL) {
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EFAULT;
}
sgt = rga_mm_lookup_sgt(buffer, job->core);
sgt = rga_mm_lookup_sgt(buffer);
if (sgt == NULL) {
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EINVAL;
}
scheduler = buffer->dma_buffer->scheduler;
if (scheduler == NULL) {
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
__func__, __LINE__, job->core);
return -EFAULT;
}
dma_sync_sg_for_cpu(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
return 0;
@@ -1295,7 +1271,7 @@ static int rga_mm_get_buffer_info(struct rga_job *job,
switch (job->scheduler->data->mmu) {
case RGA_IOMMU:
addr = rga_mm_lookup_iova(internal_buffer, job->core);
addr = rga_mm_lookup_iova(internal_buffer);
if (addr == 0) {
pr_err("core[%d] lookup buffer_type[0x%x] iova error!\n",
job->core, internal_buffer->type);