From c3adebffcca4e05e7f20942acb71422a9dd0eae2 Mon Sep 17 00:00:00 2001 From: "hyesoo.yu" Date: Thu, 11 May 2017 16:12:19 +0900 Subject: [PATCH] [COMMON] g2d: add the hwfc Support hw flow control between MFC and G2D. The hw flow control is that g2d H/W writes destination, and inform MFC of written line count of destination, so MFC could read from destination of G2D even if the operation is not completed yet. To support hwfc, driver performs following process. First, driver get the shared buffer from repeater driver that has role of shared buffer management and set the destination before H/W run. Second, set the reserved job id from 0 to MAX_SHARED_BUF_NUM that is the same of buffer index received from repeater driver. Finally, driver set register related HWFC. Change-Id: If4c646928017db9198448b68745e4e818eb5de6c Signed-off-by: hyesoo.yu --- drivers/gpu/exynos/g2d/g2d.h | 9 +-- drivers/gpu/exynos/g2d/g2d_command.c | 52 ++++++++++--- drivers/gpu/exynos/g2d/g2d_command.h | 1 + drivers/gpu/exynos/g2d/g2d_debug.h | 1 + drivers/gpu/exynos/g2d/g2d_drv.c | 45 ++++++++++- drivers/gpu/exynos/g2d/g2d_regs.h | 3 + drivers/gpu/exynos/g2d/g2d_task.c | 27 +++++-- drivers/gpu/exynos/g2d/g2d_task.h | 5 +- drivers/gpu/exynos/g2d/g2d_uapi_process.c | 95 ++++++++++++++++++----- drivers/gpu/exynos/g2d/g2d_uapi_process.h | 2 +- 10 files changed, 193 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/exynos/g2d/g2d.h b/drivers/gpu/exynos/g2d/g2d.h index b2856fbff56c..b6b86f793e47 100644 --- a/drivers/gpu/exynos/g2d/g2d.h +++ b/drivers/gpu/exynos/g2d/g2d.h @@ -17,6 +17,7 @@ #include #include #include +#include struct g2d_task; /* defined in g2d_task.h */ @@ -44,6 +45,7 @@ struct g2d_device { spinlock_t lock_task; struct g2d_task *tasks; struct list_head tasks_free; + struct list_head tasks_free_hwfc; struct list_head tasks_prepared; struct list_head tasks_active; struct workqueue_struct *schedule_workq; @@ -58,14 +60,9 @@ struct g2d_device { struct g2d_context { struct g2d_device *g2d_dev; + struct shared_buffer_info *hwfc_info; }; -/* job mask (hwfc or not) */ -#define G2D_JOBMASK_HWFC 0x7 -#define G2D_JOBMASK_DEFAULT 0xFFF8 -#define g2d_job_full(id, job_mask) ((id & job_mask) == job_mask) -#define g2d_job_empty(id, job_mask) ((id & job_mask) == 0) - int g2d_device_run(struct g2d_device *g2d_dev, struct g2d_task *task); void g2d_hw_timeout_handler(unsigned long arg); diff --git a/drivers/gpu/exynos/g2d/g2d_command.c b/drivers/gpu/exynos/g2d/g2d_command.c index 7019f35aa07f..47733c564859 100644 --- a/drivers/gpu/exynos/g2d/g2d_command.c +++ b/drivers/gpu/exynos/g2d/g2d_command.c @@ -113,21 +113,35 @@ static void g2d_set_taskctl_commands(struct g2d_task *task) task->cmd_count++; } +static void g2d_set_hwfc_commands(struct g2d_task *task) +{ + struct g2d_reg *regs = (struct g2d_reg *)page_address(task->cmd_page); + + regs[task->cmd_count].offset = G2D_HWFC_CAPTURE_IDX_REG; + regs[task->cmd_count].value = + G2D_HWFC_CAPTURE_HWFC_JOB | task->job_id; + task->cmd_count++; +} + void g2d_complete_commands(struct g2d_task *task) { struct g2d_reg *regs = page_address(task->cmd_page); - unsigned int n = 8 - ((task->cmd_count + 1) % 8); - + unsigned int n; /* 832 is the total number of the G2D registers */ BUG_ON(task->cmd_count > 830); g2d_set_taskctl_commands(task); + if (IS_HWFC(task->flags)) + g2d_set_hwfc_commands(task); + /* * Number of commands should be multiple of 8. * If it is not, then pad dummy commands with no side effect. */ + n = (8 - ((task->cmd_count + 1) & 7)) & 7; + while (n-- > 0) { regs[task->cmd_count].offset = G2D_LAYER_UPDATE_REG; regs[task->cmd_count].value = regs[TASK_REG_LAYER_UPDATE].value; @@ -534,13 +548,17 @@ static bool g2d_validate_image_dimension(struct g2d_device *g2d_dev, #define IS_EVEN(value) (((value) & 1) == 0) static bool g2d_validate_image_format(struct g2d_device *g2d_dev, - struct g2d_reg commands[], bool dst) + struct g2d_task *task, struct g2d_reg commands[], bool dst) { struct device *dev = g2d_dev->dev; u32 stride = commands[G2DSFR_IMG_STRIDE].value; u32 mode = commands[G2DSFR_IMG_COLORMODE].value; u32 width = commands[G2DSFR_IMG_WIDTH].value; u32 height = commands[G2DSFR_IMG_HEIGHT].value; + u32 left = commands[G2DSFR_IMG_LEFT].value; + u32 right = commands[G2DSFR_IMG_RIGHT].value; + u32 top = commands[G2DSFR_IMG_TOP].value; + u32 bottom = commands[G2DSFR_IMG_BOTTOM].value; u32 Bpp = 0; const struct g2d_fmt *fmt; @@ -550,10 +568,7 @@ static bool g2d_validate_image_format(struct g2d_device *g2d_dev, } if (!g2d_validate_image_dimension(g2d_dev, width, height, - commands[G2DSFR_IMG_LEFT].value, - commands[G2DSFR_IMG_TOP].value, - commands[G2DSFR_IMG_RIGHT].value, - commands[G2DSFR_IMG_BOTTOM].value)) + left, top, right, bottom)) return false; fmt = g2d_find_format(mode); @@ -593,6 +608,17 @@ static bool g2d_validate_image_format(struct g2d_device *g2d_dev, return false; } + if (IS_HWFC(task->flags)) { + if (IS_AFBC(mode) || IS_UORDER(mode)) { + dev_err(dev, "%s: Invalid HWFC format with %s\n", + __func__, IS_AFBC(mode) ? "AFBC" : "UORDER"); + return false; + } + if (dst && + ((width != right - left) || (height != bottom - top))) + goto err_align; + } + if (!dst) { if (IS_AFBC(mode) && (!IS_AFBC_WIDTH_ALIGNED(width) || !IS_AFBC_HEIGHT_ALIGNED(height))) @@ -624,7 +650,7 @@ static bool g2d_validate_image_format(struct g2d_device *g2d_dev, return true; err_align: dev_err(dev, - "%s: Unaligned size %ux%u or crop [%ux%u, %ux%u) for %s %s\n", + "%s: Unaligned size %ux%u or crop [%ux%u, %ux%u) for %s %s %s\n", __func__, commands[G2DSFR_IMG_WIDTH].value, commands[G2DSFR_IMG_HEIGHT].value, @@ -634,19 +660,22 @@ err_align: commands[G2DSFR_IMG_BOTTOM].value, IS_AFBC(mode) ? "AFBC" : IS_YUV422(mode) ? "YUV422" : "YUV20", - IS_YUV420_82(mode) ? "8+2" : ""); + IS_YUV420_82(mode) ? "8+2" : "", + IS_HWFC(task->flags) ? "HWFC" : ""); return false; } bool g2d_validate_source_commands(struct g2d_device *g2d_dev, + struct g2d_task *task, unsigned int i, struct g2d_layer *source, struct g2d_layer *target) { u32 colormode = source->commands[G2DSFR_IMG_COLORMODE].value; u32 width, height; - if (!g2d_validate_image_format(g2d_dev, source->commands, false)) { + if (!g2d_validate_image_format( + g2d_dev, task, source->commands, false)) { dev_err(g2d_dev->dev, "%s: Failed to validate source[%d] commands\n", __func__, i); @@ -689,7 +718,8 @@ bool g2d_validate_source_commands(struct g2d_device *g2d_dev, bool g2d_validate_target_commands(struct g2d_device *g2d_dev, struct g2d_task *task) { - if (!g2d_validate_image_format(g2d_dev, task->target.commands, true)) { + if (!g2d_validate_image_format(g2d_dev, task, + task->target.commands, true)) { dev_err(g2d_dev->dev, "%s: Failed to validate target commands\n", __func__); return false; diff --git a/drivers/gpu/exynos/g2d/g2d_command.h b/drivers/gpu/exynos/g2d/g2d_command.h index 61735d25f669..e2f4aa85784d 100644 --- a/drivers/gpu/exynos/g2d/g2d_command.h +++ b/drivers/gpu/exynos/g2d/g2d_command.h @@ -36,6 +36,7 @@ const struct g2d_fmt *g2d_find_format(u32 fmtval); int g2d_import_commands(struct g2d_device *g2d_dev, struct g2d_task *task, struct g2d_task_data *data, unsigned int num_sources); bool g2d_validate_source_commands(struct g2d_device *g2d_dev, + struct g2d_task *task, unsigned int i, struct g2d_layer *source, struct g2d_layer *target); bool g2d_validate_target_commands(struct g2d_device *g2d_dev, diff --git a/drivers/gpu/exynos/g2d/g2d_debug.h b/drivers/gpu/exynos/g2d/g2d_debug.h index 17a768087521..8daccd0970c2 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.h +++ b/drivers/gpu/exynos/g2d/g2d_debug.h @@ -42,6 +42,7 @@ enum g2d_stamp_id { G2D_STAMP_STATE_SUSPEND_E, G2D_STAMP_STATE_RESUME_S, G2D_STAMP_STATE_RESUME_E, + G2D_STAMP_STATE_HWFCBUF, }; void g2d_init_debug(struct g2d_device *dev); diff --git a/drivers/gpu/exynos/g2d/g2d_drv.c b/drivers/gpu/exynos/g2d/g2d_drv.c index 4b5ad3333559..8c7a98491c17 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -98,6 +98,9 @@ int g2d_device_run(struct g2d_device *g2d_dev, struct g2d_task *task) g2d_stamp_task(task, G2D_STAMP_STATE_PUSH); + if (IS_HWFC(task->flags)) + hwfc_set_valid_buffer(task->job_id, task->job_id); + return 0; } @@ -219,6 +222,14 @@ static int g2d_release(struct inode *inode, struct file *filp) { struct g2d_context *g2d_ctx = filp->private_data; + if (g2d_ctx->hwfc_info) { + int i; + + for (i = 0; i < g2d_ctx->hwfc_info->buffer_count; i++) + dma_buf_put(g2d_ctx->hwfc_info->bufs[i]); + kfree(g2d_ctx->hwfc_info); + } + kfree(g2d_ctx); return 0; @@ -245,7 +256,36 @@ static long g2d_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } - task = g2d_get_free_task(g2d_dev); + /* + * If the task should be run by hardware flow control with MFC, + * driver must request shared buffer to repeater driver if it + * has not been previously requested at current context. + * hwfc_request_buffer has increased the reference count inside + * function, so driver must reduce the reference + * when context releases. + */ + if (IS_HWFC(data.flags) && !ctx->hwfc_info) { + ctx->hwfc_info = kzalloc( + sizeof(*ctx->hwfc_info), GFP_KERNEL); + if (!ctx->hwfc_info) { + ret = -ENOMEM; + break; + } + + ret = hwfc_request_buffer(ctx->hwfc_info, 0); + if (ret || + (ctx->hwfc_info->buffer_count > + MAX_SHARED_BUF_NUM)) { + kfree(ctx->hwfc_info); + ctx->hwfc_info = NULL; + dev_err(g2d_dev->dev, + "%s: Failed to read hwfc info\n", + __func__); + break; + } + } + + task = g2d_get_free_task(g2d_dev, IS_HWFC(data.flags)); if (task == NULL) { ret = -EBUSY; break; @@ -253,7 +293,7 @@ static long g2d_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) kref_init(&task->starter); - ret = g2d_get_userdata(g2d_dev, task, &data); + ret = g2d_get_userdata(g2d_dev, ctx, task, &data); if (ret < 0) { g2d_put_free_task(g2d_dev, task); break; @@ -376,6 +416,7 @@ static int g2d_probe(struct platform_device *pdev) spin_lock_init(&g2d_dev->lock_task); INIT_LIST_HEAD(&g2d_dev->tasks_free); + INIT_LIST_HEAD(&g2d_dev->tasks_free_hwfc); INIT_LIST_HEAD(&g2d_dev->tasks_prepared); INIT_LIST_HEAD(&g2d_dev->tasks_active); diff --git a/drivers/gpu/exynos/g2d/g2d_regs.h b/drivers/gpu/exynos/g2d/g2d_regs.h index bbb4852965b3..523c193f20fe 100644 --- a/drivers/gpu/exynos/g2d/g2d_regs.h +++ b/drivers/gpu/exynos/g2d/g2d_regs.h @@ -88,6 +88,9 @@ #define G2D_DST_SPLIT_TILE_IDX_VFLAG (1 << 16) #define G2D_DST_SPLIT_TILE_IDX_HFLAG (0 << 16) +/* Fields of G2D_HWFC_CAPTURE_IDX_REG */ +#define G2D_HWFC_CAPTURE_HWFC_JOB (1 << 8) + void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task); int g2d_hw_get_current_task(struct g2d_device *g2d_dev); void g2d_hw_kill_task(struct g2d_device *g2d_dev, unsigned int job_id); diff --git a/drivers/gpu/exynos/g2d/g2d_task.c b/drivers/gpu/exynos/g2d/g2d_task.c index f26852328bf0..fd10e4b61915 100644 --- a/drivers/gpu/exynos/g2d/g2d_task.c +++ b/drivers/gpu/exynos/g2d/g2d_task.c @@ -346,19 +346,25 @@ void g2d_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb) spin_unlock_irqrestore(&layer->task->fence_timeout_lock, flags); } -struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev) +struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev, bool hwfc) { struct g2d_task *task; + struct list_head *taskfree; unsigned long flags; + if (hwfc) + taskfree = &g2d_dev->tasks_free_hwfc; + else + taskfree = &g2d_dev->tasks_free; + spin_lock_irqsave(&g2d_dev->lock_task, flags); - if (list_empty(&g2d_dev->tasks_free)) { + if (list_empty(taskfree)) { spin_unlock_irqrestore(&g2d_dev->lock_task, flags); return NULL; } - task = list_first_entry(&g2d_dev->tasks_free, struct g2d_task, node); + task = list_first_entry(taskfree, struct g2d_task, node); list_del_init(&task->node); INIT_WORK(&task->work, g2d_task_schedule_work); @@ -381,7 +387,13 @@ void g2d_put_free_task(struct g2d_device *g2d_dev, struct g2d_task *task) clear_task_state(task); - list_add(&task->node, &g2d_dev->tasks_free); + if (IS_HWFC(task->flags)) { + /* hwfc job id will be set from repeater driver info */ + task->job_id = G2D_MAX_JOBS; + list_add(&task->node, &g2d_dev->tasks_free_hwfc); + } else { + list_add(&task->node, &g2d_dev->tasks_free); + } g2d_stamp_task(task, G2D_STAMP_STATE_FREE); @@ -475,7 +487,12 @@ int g2d_create_tasks(struct g2d_device *g2d_dev) task->next = g2d_dev->tasks; g2d_dev->tasks = task; - list_add(&task->node, &g2d_dev->tasks_free); + + /* MAX_SHARED_BUF_NUM is defined in media/exynos_repeater.h */ + if (i < MAX_SHARED_BUF_NUM) + list_add(&task->node, &g2d_dev->tasks_free_hwfc); + else + list_add(&task->node, &g2d_dev->tasks_free); } return 0; diff --git a/drivers/gpu/exynos/g2d/g2d_task.h b/drivers/gpu/exynos/g2d/g2d_task.h index 18d28cd28440..4386b6614d27 100644 --- a/drivers/gpu/exynos/g2d/g2d_task.h +++ b/drivers/gpu/exynos/g2d/g2d_task.h @@ -79,6 +79,8 @@ struct g2d_layer { struct g2d_context; struct g2d_device; +#define IS_HWFC(flags) (!!((flags) & G2D_FLAG_HWFC)) + struct g2d_task { struct list_head node; struct g2d_task *next; @@ -153,6 +155,7 @@ static inline void clear_task_state(struct g2d_task *task) task->state = 0; } +#define is_task_state_idle(task) ((task)->state == 0) #define is_task_state_active(task) (((task)->state & G2D_TASKSTATE_ACTIVE) != 0) #define is_task_state_killed(task) (((task)->state & G2D_TASKSTATE_KILLED) != 0) #define is_task_state_error(task) (((task)->state & G2D_TASKSTATE_ERROR) != 0) @@ -171,7 +174,7 @@ struct g2d_task *g2d_get_active_task_from_id(struct g2d_device *g2d_dev, void g2d_destroy_tasks(struct g2d_device *g2d_dev); int g2d_create_tasks(struct g2d_device *g2d_dev); -struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev); +struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev, bool hwfc); void g2d_put_free_task(struct g2d_device *g2d_dev, struct g2d_task *task); void g2d_start_task(struct g2d_task *task); diff --git a/drivers/gpu/exynos/g2d/g2d_uapi_process.c b/drivers/gpu/exynos/g2d/g2d_uapi_process.c index 43104077f990..6b180cbdf6bd 100644 --- a/drivers/gpu/exynos/g2d/g2d_uapi_process.c +++ b/drivers/gpu/exynos/g2d/g2d_uapi_process.c @@ -31,6 +31,8 @@ #include "g2d_uapi_process.h" #include "g2d_command.h" #include "g2d_fence.h" +#include "g2d_regs.h" +#include "g2d_debug.h" unsigned int get_layer_payload(struct g2d_layer *layer) { @@ -186,6 +188,7 @@ static int g2d_prepare_buffer(struct g2d_device *g2d_dev, } static int g2d_get_dmabuf(struct g2d_task *task, + struct g2d_context *ctx, struct g2d_buffer *buffer, struct g2d_buffer_data *data, enum dma_data_direction dir) @@ -198,11 +201,58 @@ static int g2d_get_dmabuf(struct g2d_task *task, int ret = -EINVAL; int prot = IOMMU_READ | IOMMU_CACHE; - dmabuf = dma_buf_get(data->dmabuf.fd); - if (IS_ERR(dmabuf)) { - dev_err(dev, "%s: Failed to get dmabuf from fd %d\n", - __func__, data->dmabuf.fd); - return PTR_ERR(dmabuf); + if (!IS_HWFC(task->flags) || (dir == DMA_TO_DEVICE)) { + dmabuf = dma_buf_get(data->dmabuf.fd); + if (IS_ERR(dmabuf)) { + dev_err(dev, "%s: Failed to get dmabuf from fd %d\n", + __func__, data->dmabuf.fd); + return PTR_ERR(dmabuf); + } + } else { + struct g2d_task *ptask; + unsigned long flags; + u32 idx; + + /* + * The index from repeater driver used on both buffer index and + * job id, and this index is managed by repeater driver to + * avoid overwriting the buffer index and job id while MFC is + * running. + */ + hwfc_get_valid_buffer(&idx); + BUG_ON(idx >= ctx->hwfc_info->buffer_count); + + spin_lock_irqsave(&task->g2d_dev->lock_task, flags); + + ptask = task->g2d_dev->tasks; + + while (ptask != NULL) { + if (ptask == task) { + ptask = ptask->next; + continue; + } + if ((ptask->job_id == idx) && + !is_task_state_idle(ptask)) { + dev_err(dev, "%s: The task using that job #%d is not idle\n", + __func__, idx); + + spin_unlock_irqrestore( + &task->g2d_dev->lock_task, flags); + return ret; + } + ptask = ptask->next; + } + task->job_id = idx; + + spin_unlock_irqrestore(&task->g2d_dev->lock_task, flags); + + dmabuf = ctx->hwfc_info->bufs[idx]; + get_dma_buf(dmabuf); + + data->dmabuf.offset = 0; + data->length = dmabuf->size; + + g2d_stamp_task(task, G2D_STAMP_STATE_HWFCBUF); } if (dmabuf->size < data->dmabuf.offset) { @@ -288,6 +338,7 @@ static int g2d_put_dmabuf(struct g2d_device *g2d_dev, struct g2d_buffer *buffer, pgprot_val((vma)->vm_page_prot))) static int g2d_get_userptr(struct g2d_task *task, + struct g2d_context *ctx, struct g2d_buffer *buffer, struct g2d_buffer_data *data, enum dma_data_direction dir) @@ -444,14 +495,16 @@ static int g2d_put_userptr(struct g2d_device *g2d_dev, } static int g2d_get_buffer(struct g2d_device *g2d_dev, + struct g2d_context *ctx, struct g2d_layer *layer, struct g2d_layer_data *data, enum dma_data_direction dir) { int ret = 0; unsigned int i; - int (*get_func)(struct g2d_task *, struct g2d_buffer *, - struct g2d_buffer_data *, enum dma_data_direction); + int (*get_func)(struct g2d_task *, struct g2d_context *, + struct g2d_buffer *, struct g2d_buffer_data *, + enum dma_data_direction); int (*put_func)(struct g2d_device *, struct g2d_buffer *, enum dma_data_direction); @@ -466,7 +519,7 @@ static int g2d_get_buffer(struct g2d_device *g2d_dev, } for (i = 0; i < layer->num_buffers; i++) { - ret = get_func(layer->task, &layer->buffer[i], + ret = get_func(layer->task, ctx, &layer->buffer[i], &data->buffer[i], dir); if (ret) { while (i-- > 0) @@ -547,7 +600,8 @@ static int g2d_get_source(struct g2d_device *g2d_dev, struct g2d_task *task, return -EINVAL; } - if (!g2d_validate_source_commands(g2d_dev, index, layer, &task->target)) + if (!g2d_validate_source_commands( + g2d_dev, task, index, layer, &task->target)) return -EINVAL; ret = g2d_prepare_buffer(g2d_dev, layer, data); @@ -561,7 +615,7 @@ static int g2d_get_source(struct g2d_device *g2d_dev, struct g2d_task *task, return ret; } - ret = g2d_get_buffer(g2d_dev, layer, data, DMA_TO_DEVICE); + ret = g2d_get_buffer(g2d_dev, NULL, layer, data, DMA_TO_DEVICE); if (ret) goto err_buffer; @@ -614,7 +668,7 @@ static int g2d_get_sources(struct g2d_device *g2d_dev, struct g2d_task *task, return ret; } -static int g2d_get_target(struct g2d_device *g2d_dev, +static int g2d_get_target(struct g2d_device *g2d_dev, struct g2d_context *ctx, struct g2d_task *task, struct g2d_layer_data *data) { struct device *dev = g2d_dev->dev; @@ -633,14 +687,13 @@ static int g2d_get_target(struct g2d_device *g2d_dev, return -EINVAL; } + if (IS_HWFC(task->flags)) + target->buffer_type = G2D_BUFTYPE_DMABUF; + if (target->buffer_type == G2D_BUFTYPE_EMPTY) { - if (!!(task->flags & G2D_FLAG_HWFC)) { - /* TODO: set the hwfc buffers from g2d_dev*/ - } else { - dev_err(dev, "%s: target has no buffer - flags: %#x\n", - __func__, task->flags); - return -EINVAL; - } + dev_err(dev, "%s: target has no buffer - flags: %#x\n", + __func__, task->flags); + return -EINVAL; } if (!g2d_validate_target_commands(g2d_dev, task)) @@ -657,7 +710,7 @@ static int g2d_get_target(struct g2d_device *g2d_dev, return ret; } - ret = g2d_get_buffer(g2d_dev, target, data, DMA_FROM_DEVICE); + ret = g2d_get_buffer(g2d_dev, ctx, target, data, DMA_FROM_DEVICE); if (ret) goto err_buffer; @@ -677,7 +730,7 @@ err_buffer: return ret; } -int g2d_get_userdata(struct g2d_device *g2d_dev, +int g2d_get_userdata(struct g2d_device *g2d_dev, struct g2d_context *ctx, struct g2d_task *task, struct g2d_task_data *data) { struct device *dev = g2d_dev->dev; @@ -705,7 +758,7 @@ int g2d_get_userdata(struct g2d_device *g2d_dev, if (ret < 0) return ret; - ret = g2d_get_target(g2d_dev, task, &data->target); + ret = g2d_get_target(g2d_dev, ctx, task, &data->target); if (ret) return ret; diff --git a/drivers/gpu/exynos/g2d/g2d_uapi_process.h b/drivers/gpu/exynos/g2d/g2d_uapi_process.h index d917891aae06..61cb32f3d4d1 100644 --- a/drivers/gpu/exynos/g2d/g2d_uapi_process.h +++ b/drivers/gpu/exynos/g2d/g2d_uapi_process.h @@ -21,7 +21,7 @@ struct g2d_device; struct g2d_task; -int g2d_get_userdata(struct g2d_device *g2d_dev, +int g2d_get_userdata(struct g2d_device *g2d_dev, struct g2d_context *ctx, struct g2d_task *task, struct g2d_task_data *data); void g2d_put_images(struct g2d_device *g2d_dev, struct g2d_task *task); int g2d_wait_put_user(struct g2d_device *g2d_dev, struct g2d_task *task, -- 2.20.1