summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/etnaviv
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2017-09-24 15:15:20 +0200
committerLucas Stach <l.stach@pengutronix.de>2017-10-10 11:45:40 +0200
commit95a428c17212ddef40909981e118acd6f518dc93 (patch)
tree1b8de3c4610fa253e586e1860f884350826c98ef /drivers/gpu/drm/etnaviv
parent355502e03ad26e3c872a0f5c408a4accca57ba7e (diff)
drm/etnaviv: make it possible to allocate multiple events
This makes it possible to allocate multiple events under the event spinlock. This change is needed to support 'sync'-points. Changes v2 -> v3: - wait for the completion of all events - use 10sec timeout regardless of the number of events - removed validation if there are enough free events - fixed return value evaluation of event_alloc(..) in etnaviv_gpu_submit(..) Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/etnaviv')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 3b02814b9c52..8d961bc238d4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1142,28 +1142,44 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
* event management:
*/
-static unsigned int event_alloc(struct etnaviv_gpu *gpu)
+static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
+ unsigned int *events)
{
- unsigned long ret, flags;
- unsigned int event;
+ unsigned long flags, timeout = msecs_to_jiffies(10 * 10000);
+ unsigned i, acquired = 0;
- ret = wait_for_completion_timeout(&gpu->event_free,
- msecs_to_jiffies(10 * 10000));
- if (!ret)
- dev_err(gpu->dev, "wait_for_completion_timeout failed");
+ for (i = 0; i < nr_events; i++) {
+ unsigned long ret;
+
+ ret = wait_for_completion_timeout(&gpu->event_free, timeout);
+
+ if (!ret) {
+ dev_err(gpu->dev, "wait_for_completion_timeout failed");
+ goto out;
+ }
+
+ acquired++;
+ timeout = ret;
+ }
spin_lock_irqsave(&gpu->event_spinlock, flags);
- /* find first free event */
- event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS);
- if (event < ETNA_NR_EVENTS)
+ for (i = 0; i < nr_events; i++) {
+ int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS);
+
+ events[i] = event;
set_bit(event, gpu->event_bitmap);
- else
- event = ~0U;
+ }
spin_unlock_irqrestore(&gpu->event_spinlock, flags);
- return event;
+ return 0;
+
+out:
+ for (i = 0; i < acquired; i++)
+ complete(&gpu->event_free);
+
+ return -EBUSY;
}
static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
@@ -1332,10 +1348,9 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
*
*/
- event = event_alloc(gpu);
- if (unlikely(event == ~0U)) {
+ ret = event_alloc(gpu, 1, &event);
+ if (ret) {
DRM_ERROR("no free event\n");
- ret = -EBUSY;
goto out_pm_put;
}