Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95a428c1 authored by Christian Gmeiner's avatar Christian Gmeiner Committed by Lucas Stach
Browse files

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: default avatarChristian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
parent 355502e0
Loading
Loading
Loading
Loading
+31 −16
Original line number Diff line number Diff line
@@ -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)
	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;
	}