From: hyesoo.yu Date: Mon, 24 Dec 2018 06:32:06 +0000 (+0900) Subject: [RAMEN9610-10376] g2d: add blocking interface by module param X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=5a0518b676d834bbad2360e2c64163375ca5a635;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [RAMEN9610-10376] g2d: add blocking interface by module param If the jobs are queued larger than max_queued set by module param or there is not free task on list, the user request of task could be returned with -EBUSY immediately, or wait until the number of queued job is less than max_queued and free list is not empty. Change-Id: I71dde2620830ea7e4426c86d70b7cd8eba9af952 Signed-off-by: hyesoo.yu --- diff --git a/drivers/gpu/exynos/g2d/g2d.h b/drivers/gpu/exynos/g2d/g2d.h index 81aae54c984d..d76f21979118 100644 --- a/drivers/gpu/exynos/g2d/g2d.h +++ b/drivers/gpu/exynos/g2d/g2d.h @@ -104,6 +104,7 @@ struct g2d_device { struct notifier_block pm_notifier; wait_queue_head_t freeze_wait; + wait_queue_head_t queued_wait; struct dentry *debug_root; struct dentry *debug; diff --git a/drivers/gpu/exynos/g2d/g2d_debug.c b/drivers/gpu/exynos/g2d/g2d_debug.c index 9e931ff2420b..87106d5112eb 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.c +++ b/drivers/gpu/exynos/g2d/g2d_debug.c @@ -69,6 +69,7 @@ static struct g2d_stamp_type { {"suspend", G2D_STAMPTYPE_INOUT, false}, {"resume", G2D_STAMPTYPE_INOUT, false}, {"hwfc_job", G2D_STAMPTYPE_NUM, true}, + {"pending", G2D_STAMPTYPE_NUM, false}, }; static bool g2d_stamp_show_single(struct seq_file *s, struct g2d_stamp *stamp) diff --git a/drivers/gpu/exynos/g2d/g2d_debug.h b/drivers/gpu/exynos/g2d/g2d_debug.h index ae511d0006d5..cd1a9ab491d9 100644 --- a/drivers/gpu/exynos/g2d/g2d_debug.h +++ b/drivers/gpu/exynos/g2d/g2d_debug.h @@ -39,6 +39,7 @@ enum g2d_stamp_id { G2D_STAMP_STATE_SUSPEND, G2D_STAMP_STATE_RESUME, G2D_STAMP_STATE_HWFCBUF, + G2D_STAMP_STATE_PENDING, G2D_STAMP_STATE_NUM, }; diff --git a/drivers/gpu/exynos/g2d/g2d_drv.c b/drivers/gpu/exynos/g2d/g2d_drv.c index d5ec2a07b928..5ce4388280ba 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -920,6 +920,7 @@ static int g2d_probe(struct platform_device *pdev) } init_waitqueue_head(&g2d_dev->freeze_wait); + init_waitqueue_head(&g2d_dev->queued_wait); g2d_dev->pm_notifier.notifier_call = &g2d_notifier_event; ret = register_pm_notifier(&g2d_dev->pm_notifier); diff --git a/drivers/gpu/exynos/g2d/g2d_task.c b/drivers/gpu/exynos/g2d/g2d_task.c index 80d6bf3d38f7..83dfe6cd9d7e 100644 --- a/drivers/gpu/exynos/g2d/g2d_task.c +++ b/drivers/gpu/exynos/g2d/g2d_task.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "g2d.h" #include "g2d_task.h" @@ -320,12 +321,34 @@ void g2d_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb) spin_unlock_irqrestore(&layer->task->fence_timeout_lock, flags); } +static bool block_on_contension; +module_param(block_on_contension, bool, 0644); + +static int max_queued; +module_param(max_queued, int, 0644); + +static int g2d_queued_task_count(struct g2d_device *g2d_dev) +{ + struct g2d_task *task; + int num_queued = 0; + + list_for_each_entry(task, &g2d_dev->tasks_active, node) + num_queued++; + + list_for_each_entry(task, &g2d_dev->tasks_prepared, node) + num_queued++; + + return num_queued; +} + struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev, struct g2d_context *g2d_ctx, bool hwfc) { struct g2d_task *task; struct list_head *taskfree; unsigned long flags; + int num_queued = 0; + ktime_t ktime_pending; if (hwfc) taskfree = &g2d_dev->tasks_free_hwfc; @@ -334,11 +357,34 @@ struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev, spin_lock_irqsave(&g2d_dev->lock_task, flags); - if (list_empty(taskfree)) { - dev_err(g2d_dev->dev, "%s: no free task slot found(hwfc? %d)\n", - __func__, hwfc); + while (list_empty(taskfree) || + ((num_queued = g2d_queued_task_count(g2d_dev)) >= max_queued)) { + spin_unlock_irqrestore(&g2d_dev->lock_task, flags); - return NULL; + + if (list_empty(taskfree)) + dev_err(g2d_dev->dev, + "%s : no free task slot found (hwfc %d)", + __func__, hwfc); + else + dev_err(g2d_dev->dev, "%s : queued %d >= max %d", + __func__, num_queued, max_queued); + + if (!block_on_contension) + return NULL; + + ktime_pending = ktime_get(); + + g2d_stamp_task(NULL, G2D_STAMP_STATE_PENDING, num_queued); + wait_event(g2d_dev->queued_wait, + !list_empty(taskfree) && + (g2d_queued_task_count(g2d_dev) < max_queued)); + + dev_err(g2d_dev->dev, + "%s : wait to resolve contension for %d us", __func__, + (int)ktime_us_delta(ktime_get(), ktime_pending)); + + spin_lock_irqsave(&g2d_dev->lock_task, flags); } task = list_first_entry(taskfree, struct g2d_task, node); @@ -378,6 +424,8 @@ void g2d_put_free_task(struct g2d_device *g2d_dev, struct g2d_task *task) g2d_stamp_task(task, G2D_STAMP_STATE_TASK_RESOURCE, 1); spin_unlock_irqrestore(&g2d_dev->lock_task, flags); + + wake_up(&g2d_dev->queued_wait); } void g2d_destroy_tasks(struct g2d_device *g2d_dev) @@ -491,5 +539,7 @@ int g2d_create_tasks(struct g2d_device *g2d_dev) list_add(&task->node, &g2d_dev->tasks_free); } + max_queued = G2D_MAX_JOBS; + return 0; }