ge2d: add ioctl to attach/detach [1/1]

PD#SWPL-33277

Problem:
reduce cache invalidate actions
while doing bulk actions to improve the performance

Solution:
add ioctl to attach/detach dma fd

Verify:
on sm1/w400

Change-Id: Iea8fae9e483ff70044da748c78d8641c52a0c65d
Signed-off-by: Cao Jian <jian.cao@amlogic.com>
Signed-off-by: chunlong.cao <chunlong.cao@amlogic.com>
This commit is contained in:
Cao Jian
2020-10-16 20:34:27 +08:00
committed by Chris
parent 690e290f04
commit 87ea2f5e78
5 changed files with 181 additions and 64 deletions

View File

@@ -626,32 +626,11 @@ int ge2d_dma_buffer_get_phys(struct aml_dma_buffer *buffer,
dma_sync_sg_for_cpu(cfg->dev, sg_table->sgl,
sg_table->nents, cfg->dir);
}
ge2d_dma_buffer_unmap(cfg);
}
return ret;
}
int ge2d_dma_buffer_unmap_info(struct aml_dma_buffer *buffer,
struct aml_dma_cfg *cfg)
{
int i, found = 0;
if (cfg == NULL || (cfg->fd < 0)) {
pr_err("%s: error input param\n", __func__);
return -EINVAL;
}
for (i = 0; i < AML_MAX_DMABUF; i++) {
if (buffer->gd_buffer[i].alloc) {
if (cfg->dbuf == buffer->gd_buffer[i].dbuf) {
found = 1;
break;
}
}
}
if (!found)
ge2d_dma_buffer_unmap(cfg);
return 0;
}
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg)
{
int fd = -1;

View File

@@ -78,8 +78,10 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg);
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg);
int ge2d_dma_buffer_get_phys(struct aml_dma_buffer *buffer,
struct aml_dma_cfg *cfg, unsigned long *addr);
int ge2d_dma_buffer_unmap_info(struct aml_dma_buffer *buffer,
struct aml_dma_cfg *cfg);
void ge2d_dma_buffer_dma_flush(struct device *dev, int fd);
void ge2d_dma_buffer_cache_flush(struct device *dev, int fd);
int ge2d_ioctl_attach_dma_fd(struct ge2d_context_s *wq,
struct ge2d_dmabuf_attach_s *dma_attach);
void ge2d_ioctl_detach_dma_fd(struct ge2d_context_s *wq,
enum ge2d_data_type_e data_type);
#endif

View File

@@ -219,6 +219,7 @@ static ssize_t log_level_store(struct class *cla,
static int ge2d_open(struct inode *inode, struct file *file)
{
struct ge2d_context_s *context = NULL;
int i;
/* we create one ge2d workqueue for this file handler. */
context = create_ge2d_work_queue();
@@ -226,6 +227,14 @@ static int ge2d_open(struct inode *inode, struct file *file)
ge2d_log_err("can't create work queue\n");
return -1;
}
/* reset dms_used flag */
for (i = 0; i < MAX_PLANE; i++) {
context->config.src_dma_cfg[i].dma_used[i] = 0;
context->config.src2_dma_cfg[i].dma_used[i] = 0;
context->config.dst_dma_cfg[i].dma_used[i] = 0;
}
file->private_data = context;
atomic_inc(&ge2d_device.open_count);
@@ -447,6 +456,8 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
#endif
int cap_mask = 0;
int index = 0, dma_fd;
enum ge2d_data_type_e data_type;
struct ge2d_dmabuf_attach_s attatch;
void __user *argp = (void __user *)args;
context = (struct ge2d_context_s *)filp->private_data;
@@ -794,6 +805,22 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
return -EINVAL;
}
break;
case GE2D_ATTACH_DMA_FD:
ret = copy_from_user(&attatch, argp,
sizeof(struct ge2d_dmabuf_attach_s));
if (ret < 0) {
pr_err("Error user param\n");
return -EINVAL;
}
break;
case GE2D_DETACH_DMA_FD:
ret = copy_from_user(&data_type, argp,
sizeof(enum ge2d_data_type_e));
if (ret < 0) {
pr_err("Error user param\n");
return -EINVAL;
}
break;
case GE2D_CONFIG_OLD:
case GE2D_CONFIG_EX_OLD:
case GE2D_SRCCOLORKEY_OLD:
@@ -1027,6 +1054,12 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
case GE2D_SYNC_CPU:
ge2d_buffer_cache_flush(dma_fd);
break;
case GE2D_ATTACH_DMA_FD:
ge2d_ioctl_attach_dma_fd(context, &attatch);
break;
case GE2D_DETACH_DMA_FD:
ge2d_ioctl_detach_dma_fd(context, data_type);
break;
}
return ret;
}

View File

@@ -124,7 +124,6 @@ static const int default_ge2d_color_lut[] = {
static int ge2d_buffer_get_phys(struct aml_dma_cfg *cfg,
unsigned long *addr);
static int ge2d_buffer_unmap(struct aml_dma_cfg *cfg);
static void ge2d_pre_init(void)
{
@@ -386,7 +385,7 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
struct ge2d_queue_item_s *pitem;
unsigned int mask = 0x1;
struct list_head *head = &wq->work_queue, *pos;
int ret = 0, i = 0;
int ret = 0;
unsigned int block_mode;
int timeout = 0;
@@ -418,6 +417,10 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
goto exit;
}
/* do power on/off every process, all setting should be updated */
if (ge2d_meson_dev.has_self_pwr)
pitem->config.update_flag = UPDATE_ALL;
do {
cfg = &pitem->config;
ge2d_log_dbg("secure mode:%d\n", cfg->mem_sec);
@@ -479,27 +482,6 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
pos = pos->next;
list_move_tail(&pitem->list, &wq->free_queue);
spin_unlock(&wq->lock);
/* if dma buf detach it */
for (i = 0; i < MAX_PLANE; i++) {
if (pitem->config.src_dma_cfg[i].dma_used) {
ge2d_buffer_unmap((struct aml_dma_cfg *
)pitem->config.src_dma_cfg[i].dma_cfg);
pitem->config.src_dma_cfg[i].dma_used = 0;
kfree(pitem->config.src_dma_cfg[i].dma_cfg);
}
if (pitem->config.src2_dma_cfg[i].dma_used) {
ge2d_buffer_unmap((struct aml_dma_cfg *
)pitem->config.src2_dma_cfg[i].dma_cfg);
pitem->config.src2_dma_cfg[i].dma_used = 0;
kfree(pitem->config.src2_dma_cfg[i].dma_cfg);
}
if (pitem->config.dst_dma_cfg[i].dma_used) {
ge2d_buffer_unmap((struct aml_dma_cfg *
)pitem->config.dst_dma_cfg[i].dma_cfg);
pitem->config.dst_dma_cfg[i].dma_used = 0;
kfree(pitem->config.dst_dma_cfg[i].dma_cfg);
}
}
/* if block mode (cmd) */
if (block_mode) {
pitem->cmd.wait_done_flag = 0;
@@ -552,7 +534,7 @@ struct ge2d_canvas_cfg_s *ge2d_wq_get_canvas_cfg(struct ge2d_context_s *wq,
canvas_cfg = &wq->config.dst_canvas_cfg[plane_id];
break;
default:
ge2d_log_err("wrong data_type\n");
ge2d_log_err("%s, wrong data_type\n", __func__);
break;
}
return canvas_cfg;
@@ -575,7 +557,7 @@ struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq,
dma_cfg = &wq->config.dst_dma_cfg[plane_id];
break;
default:
ge2d_log_err("wrong data_type\n");
ge2d_log_err("%s, wrong data_type\n", __func__);
break;
}
@@ -1105,14 +1087,13 @@ static int build_ge2d_addr_config_dma(
ge2d_log_dbg("build_ge2d_addr_config_dma bpp_value=%d\n",
bpp_value);
if (plane) {
if (plane[0].shared_fd) {
if (plane[0].shared_fd > 0) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
cfg = ge2d_wq_get_dma_cfg(context, data_type, 0);
if (!cfg)
return -1;
cfg->dma_used = 1;
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
dma_cfg->fd = plane[0].shared_fd;
dma_cfg->dev = &(ge2d_manager.pdev->dev);
@@ -1121,8 +1102,25 @@ static int build_ge2d_addr_config_dma(
ret = ge2d_buffer_get_phys(dma_cfg, &addr_temp);
if (ret != 0)
return ret;
kfree(dma_cfg);
plane[0].addr += addr_temp;
} else if (plane[0].shared_fd == DMA_FD_ATTACHED) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
cfg = ge2d_wq_get_dma_cfg(context, data_type, 0);
if (!cfg)
return -1;
if (!cfg->dma_cfg) {
ge2d_log_err("%s, dma_cfg is null\n",
__func__);
return -1;
}
dma_cfg = (struct aml_dma_cfg *)cfg->dma_cfg;
plane[0].addr += sg_phys(dma_cfg->sg->sgl);
}
plane[0].addr += addr_temp;
if (plane[0].addr) {
*addr = plane[0].addr;
*stride = plane[0].w * bpp_value;
@@ -1234,7 +1232,7 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
for (i = 0; i < MAX_PLANE; i++) {
/* multi-src_planes */
canvas_set = 0;
if (plane[i].shared_fd) {
if (plane[i].shared_fd > 0) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
@@ -1242,7 +1240,6 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
data_type, i);
if (!cfg)
return -1;
cfg->dma_used = 1;
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
if (!dma_cfg)
return ret;
@@ -1253,8 +1250,27 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
ret = ge2d_buffer_get_phys(dma_cfg, &addr);
if (ret != 0)
return ret;
kfree(dma_cfg);
plane[i].addr = addr;
canvas_set = 1;
} else if (plane[i].shared_fd == DMA_FD_ATTACHED) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
cfg = ge2d_wq_get_dma_cfg(context,
data_type, i);
if (!cfg)
return -1;
if (!cfg->dma_cfg) {
ge2d_log_err("%s, dma_cfg is null\n",
__func__);
return -1;
}
dma_cfg = (struct aml_dma_cfg *)cfg->dma_cfg;
plane[i].addr = sg_phys(dma_cfg->sg->sgl);
canvas_set = 1;
ret = 0;
} else if (plane[i].addr) {
plane[i].addr += plane[0].addr;
canvas_set = 1;
@@ -2028,15 +2044,9 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context,
unsigned int src_addr = 0, src2_addr = 0, dst_addr = 0;
unsigned int src_stride = 0, src2_stride = 0, dst_stride = 0;
struct config_para_ex_ion_s *ge2d_config;
int i;
unsigned int *stride_custom;
ge2d_config = &(ge2d_config_mem->_ge2d_config_ex);
/* reset dms_used flag */
for (i = 0; i < MAX_PLANE; i++) {
context->config.src_dma_cfg[i].dma_used = 0;
context->config.src2_dma_cfg[i].dma_used = 0;
context->config.dst_dma_cfg[i].dma_used = 0;
}
/* setup src and dst */
switch (ge2d_config->src_para.mem_type) {
case CANVAS_OSD0:
@@ -2444,9 +2454,89 @@ static int ge2d_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr)
return ge2d_dma_buffer_get_phys(ge2d_manager.buffer, cfg, addr);
}
static int ge2d_buffer_unmap(struct aml_dma_cfg *cfg)
int ge2d_ioctl_attach_dma_fd(struct ge2d_context_s *wq,
struct ge2d_dmabuf_attach_s *dma_attach)
{
return ge2d_dma_buffer_unmap_info(ge2d_manager.buffer, cfg);
int ret = -1;
enum dma_data_direction dir;
int dma_fd, i;
if (!dma_attach) {
ge2d_log_err("dma_attach is null\n");
return -EINVAL;
}
for (i = 0; i < MAX_PLANE; i++) {
dma_fd = dma_attach->dma_fd[i];
if (dma_fd > 0) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
cfg = ge2d_wq_get_dma_cfg(wq,
dma_attach->data_type, i);
if (!cfg)
return -1;
cfg->dma_used[i] = 1;
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
if (!dma_cfg) {
ge2d_log_err("%s, kzalloc error\n", __func__);
return ret;
}
cfg->dma_cfg = dma_cfg;
switch (dma_attach->data_type) {
case AML_GE2D_SRC:
dir = DMA_TO_DEVICE;
break;
case AML_GE2D_SRC2:
dir = DMA_TO_DEVICE;
break;
case AML_GE2D_DST:
dir = DMA_FROM_DEVICE;
break;
default:
ge2d_log_err("%s, data_type %d error\n",
__func__, dma_attach->data_type);
dir = DMA_BIDIRECTIONAL;
break;
}
dma_cfg->fd = dma_fd;
dma_cfg->dev = &ge2d_manager.pdev->dev;
dma_cfg->dir = dir;
ret = ge2d_dma_buffer_map(dma_cfg);
if (ret < 0) {
kfree(dma_cfg);
pr_err("gdc_dma_buffer_map failed i=%d\n", i);
return ret;
}
}
}
return ret;
}
void ge2d_ioctl_detach_dma_fd(struct ge2d_context_s *wq,
enum ge2d_data_type_e data_type)
{
int i;
for (i = 0; i < MAX_PLANE; i++) {
struct ge2d_dma_cfg_s *cfg = NULL;
struct aml_dma_cfg *dma_cfg = NULL;
cfg = ge2d_wq_get_dma_cfg(wq, data_type, i);
if (!cfg)
return;
dma_cfg = cfg->dma_cfg;
if (dma_cfg && cfg->dma_used[i]) {
ge2d_dma_buffer_unmap(dma_cfg);
cfg->dma_used[i] = 0;
kfree(dma_cfg);
}
}
}
struct ge2d_context_s *create_ge2d_work_queue(void)

View File

@@ -369,6 +369,9 @@ enum ge2d_memtype_s {
#define UPDATE_SCALE_COEF 0x20
#define UPDATE_ALL 0x3f
/* Indicates that dma fd has been attatched using ioctl GE2D_ATTACH_DMA_FD */
#define DMA_FD_ATTACHED (-2)
struct rectangle_s {
int x; /* X coordinate of its top-left point */
int y; /* Y coordinate of its top-left point */
@@ -638,7 +641,7 @@ struct ge2d_canvas_cfg_s {
};
struct ge2d_dma_cfg_s {
int dma_used;
int dma_used[MAX_PLANE];
void *dma_cfg;
};
@@ -1095,6 +1098,12 @@ struct ge2d_dmabuf_exp_s {
unsigned int flags;
int fd;
};
struct ge2d_dmabuf_attach_s {
int dma_fd[MAX_PLANE];
enum ge2d_data_type_e data_type;
};
/* end of ge2d dma buffer define */
enum {
@@ -1181,6 +1190,10 @@ extern struct ge2d_device_data_s ge2d_meson_dev;
#define GE2D_SYNC_DEVICE _IOW(GE2D_IOC_MAGIC, 0x08, int)
#define GE2D_SYNC_CPU _IOW(GE2D_IOC_MAGIC, 0x09, int)
#define GE2D_ATTACH_DMA_FD \
_IOW(GE2D_IOC_MAGIC, 0x0a, struct ge2d_dmabuf_attach_s)
#define GE2D_DETACH_DMA_FD _IOW(GE2D_IOC_MAGIC, 0x0b, enum ge2d_data_type_e)
extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg);
extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg);
extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg);