video: rockchip: rga3: use dma_map_sg instead of dma_map_resouce

Change-Id: Ic41f6eb94d2dd749f71bfa02ba718e6bb4dcd263
Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
This commit is contained in:
Yu Qiaowei
2025-08-18 17:59:22 +08:00
committed by Tao Huang
parent ae35fd7eec
commit 6e89da27be
3 changed files with 75 additions and 52 deletions

View File

@@ -44,10 +44,6 @@ int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd);
int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_info_t *img);
int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer,
enum dma_data_direction dir, struct device *map_dev);
void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer);
int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer,
enum dma_data_direction dir, struct device *map_dev);
void rga_dma_unmap_sgt(struct rga_dma_buffer *buffer);

View File

@@ -251,32 +251,6 @@ int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_i
return ret;
}
int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer,
enum dma_data_direction dir, struct device *map_dev)
{
int ret;
dma_addr_t addr;
addr = dma_map_resource(map_dev, phys_addr, size, dir, 0);
ret = dma_mapping_error(map_dev, addr);
if (ret < 0) {
rga_err("dma_map_resouce failed!, ret = %d\n", ret);
return ret;
}
buffer->dma_addr = addr;
buffer->dir = dir;
buffer->size = size;
buffer->map_dev = map_dev;
return 0;
}
void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer)
{
dma_unmap_resource(buffer->map_dev, buffer->dma_addr, buffer->size, buffer->dir, 0);
}
int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer,
enum dma_data_direction dir, struct device *map_dev)
{

View File

@@ -160,6 +160,23 @@ static int rga_get_user_pages(struct page **pages, unsigned long Memory,
return ret;
}
static int rga_get_phys_addr_pages(struct page **pages, phys_addr_t phys_addr, uint32_t page_count)
{
int i;
phys_addr_t addr;
if (WARN_ON_ONCE(!pfn_valid(PHYS_PFN(phys_addr))))
return -EINVAL;
addr = phys_addr;
for (i = 0; i < page_count; i++) {
pages[i] = phys_to_page(addr);
addr += PAGE_SIZE;
}
return 0;
}
static void rga_free_sgt(struct sg_table **sgt_ptr)
{
if (sgt_ptr == NULL || *sgt_ptr == NULL)
@@ -170,24 +187,21 @@ static void rga_free_sgt(struct sg_table **sgt_ptr)
*sgt_ptr = NULL;
}
static struct sg_table *rga_alloc_sgt(struct rga_virt_addr *virt_addr)
static struct sg_table *rga_alloc_sgt(struct page **pages,
int page_count, size_t offset,
size_t size, gfp_t gfp_mask)
{
int ret;
struct sg_table *sgt = NULL;
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
sgt = kzalloc(sizeof(*sgt), gfp_mask);
if (sgt == NULL) {
rga_err("%s alloc sgt error!\n", __func__);
return ERR_PTR(-ENOMEM);
}
/* get sg form pages. */
ret = sg_alloc_table_from_pages(sgt,
virt_addr->pages,
virt_addr->page_count,
virt_addr->offset,
virt_addr->size,
GFP_KERNEL);
ret = sg_alloc_table_from_pages(sgt, pages, page_count, offset, size, gfp_mask);
if (ret) {
rga_err("sg_alloc_table_from_pages failed");
goto out_free_sgt;
@@ -541,7 +555,10 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
goto put_current_mm;
}
sgt = rga_alloc_sgt(virt_addr);
sgt = rga_alloc_sgt(virt_addr->pages,
virt_addr->page_count,
virt_addr->offset,
virt_addr->size, GFP_KERNEL);
if (IS_ERR(sgt)) {
rga_err("alloc sgt error!\n");
ret = PTR_ERR(sgt);
@@ -630,7 +647,8 @@ put_current_mm:
static void rga_mm_unmap_phys_addr(struct rga_internal_buffer *internal_buffer)
{
if (internal_buffer->dma_buffer != NULL) {
rga_dma_unmap_phys_addr(internal_buffer->dma_buffer);
rga_dma_unmap_sgt(internal_buffer->dma_buffer);
rga_free_sgt(&internal_buffer->dma_buffer->sgt);
kfree(internal_buffer->dma_buffer);
internal_buffer->dma_buffer = NULL;
}
@@ -644,9 +662,13 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
struct rga_job *job)
{
int ret;
phys_addr_t phys_addr;
int buffer_size;
size_t offset;
uint32_t mm_flag = 0;
uint32_t page_count;
phys_addr_t phys_addr, phys_addr_aligned;
struct page **pages = NULL;
struct sg_table *sgt = NULL;
struct rga_dma_buffer *buffer = NULL;
struct device *map_dev;
struct rga_scheduler_t *scheduler;
@@ -658,16 +680,16 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
return -EINVAL;
}
if (internal_buffer->memory_parm.size)
buffer_size = internal_buffer->memory_parm.size;
if (external_buffer->memory_parm.size)
buffer_size = external_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,
buffer_size = rga_image_size_cal(external_buffer->memory_parm.width,
external_buffer->memory_parm.height,
external_buffer->memory_parm.format,
NULL, NULL, NULL);
if (buffer_size <= 0) {
rga_err("Failed to get phys addr size!\n");
rga_dump_memory_parm(&internal_buffer->memory_parm);
rga_err("failed to calculating buffer size!\n");
rga_dump_memory_parm(&external_buffer->memory_parm);
return buffer_size == 0 ? -EINVAL : buffer_size;
}
@@ -683,10 +705,35 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
}
if (scheduler->data->mmu == RGA_IOMMU) {
phys_addr_aligned = phys_addr & PAGE_MASK;
offset = phys_addr & (~PAGE_MASK);
page_count = RGA_GET_PAGE_COUNT(buffer_size + offset);
pages = vzalloc(sizeof(struct page *) * page_count);
if (pages == NULL) {
rga_err("%s can not alloc pages for phys_addr pages\n", __func__);
return -ENOMEM;
}
ret = rga_get_phys_addr_pages(pages, phys_addr_aligned, page_count);
if (ret < 0) {
rga_err("failed to get pages from physical address: 0x%llx\n",
(unsigned long long)phys_addr);
goto free_pages;
}
sgt = rga_alloc_sgt(pages, page_count, offset, buffer_size, GFP_KERNEL);
if (IS_ERR(sgt)) {
rga_err("failed to alloc sgt\n");
ret = PTR_ERR(sgt);
goto free_pages;
}
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
rga_err("%s alloc internal dma buffer error!\n", __func__);
return -ENOMEM;
ret = -ENOMEM;
goto free_sgt;
}
/*
@@ -695,14 +742,16 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
*/
map_dev = scheduler->iommu_info ?
scheduler->iommu_info->default_dev : scheduler->dev;
ret = rga_dma_map_phys_addr(phys_addr, buffer_size, buffer,
DMA_BIDIRECTIONAL, map_dev);
ret = rga_dma_map_sgt(sgt, buffer, DMA_BIDIRECTIONAL, map_dev);
if (ret < 0) {
rga_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core);
rga_err("%s core[%d] map phys_addr error!, phys_addr = 0x%llx\n",
__func__, scheduler->core,
(unsigned long long)phys_addr);
goto free_dma_buffer;
}
buffer->iova = buffer->dma_addr;
vfree(pages);
}
internal_buffer->dma_buffer = buffer;
@@ -715,6 +764,10 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
free_dma_buffer:
kfree(buffer);
free_sgt:
rga_free_sgt(&sgt);
free_pages:
vfree(pages);
return ret;
}