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>
This commit is contained in:
parent
355502e03a
commit
95a428c172
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue