Skip to content

Commit

Permalink
drm/i915/fence: Separate timeout mechanism for awaiting on dma-fences
Browse files Browse the repository at this point in the history
As the timeout mechanism has grown more and more complicated, using
multiple deferred tasks and more than doubling the size of our struct,
split the two implementations to streamline the simpler no-timeout
callback variant.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180115090643.26696-2-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed Jan 15, 2018
1 parent c32164b commit f255c1e
Showing 1 changed file with 40 additions and 21 deletions.
61 changes: 40 additions & 21 deletions drivers/gpu/drm/i915/i915_sw_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,18 +365,31 @@ int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
struct i915_sw_dma_fence_cb {
struct dma_fence_cb base;
struct i915_sw_fence *fence;
};

struct i915_sw_dma_fence_cb_timer {
struct i915_sw_dma_fence_cb base;
struct dma_fence *dma;
struct timer_list timer;
struct irq_work work;
struct rcu_head rcu;
};

static void dma_i915_sw_fence_wake(struct dma_fence *dma,
struct dma_fence_cb *data)
{
struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);

i915_sw_fence_complete(cb->fence);
kfree(cb);
}

static void timer_i915_sw_fence_wake(struct timer_list *t)
{
struct i915_sw_dma_fence_cb *cb = from_timer(cb, t, timer);
struct i915_sw_dma_fence_cb_timer *cb = from_timer(cb, t, timer);
struct i915_sw_fence *fence;

fence = xchg(&cb->fence, NULL);
fence = xchg(&cb->base.fence, NULL);
if (!fence)
return;

Expand All @@ -388,27 +401,24 @@ static void timer_i915_sw_fence_wake(struct timer_list *t)
i915_sw_fence_complete(fence);
}

static void dma_i915_sw_fence_wake(struct dma_fence *dma,
struct dma_fence_cb *data)
static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma,
struct dma_fence_cb *data)
{
struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
struct i915_sw_dma_fence_cb_timer *cb =
container_of(data, typeof(*cb), base.base);
struct i915_sw_fence *fence;

fence = xchg(&cb->fence, NULL);
fence = xchg(&cb->base.fence, NULL);
if (fence)
i915_sw_fence_complete(fence);

if (cb->dma) {
irq_work_queue(&cb->work);
return;
}

kfree(cb);
irq_work_queue(&cb->work);
}

static void irq_i915_sw_fence_work(struct irq_work *wrk)
{
struct i915_sw_dma_fence_cb *cb = container_of(wrk, typeof(*cb), work);
struct i915_sw_dma_fence_cb_timer *cb =
container_of(wrk, typeof(*cb), work);

del_timer_sync(&cb->timer);
dma_fence_put(cb->dma);
Expand All @@ -422,6 +432,7 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
gfp_t gfp)
{
struct i915_sw_dma_fence_cb *cb;
dma_fence_func_t func;
int ret;

debug_fence_assert(fence);
Expand All @@ -430,7 +441,10 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
if (dma_fence_is_signaled(dma))
return 0;

cb = kmalloc(sizeof(*cb), gfp);
cb = kmalloc(timeout ?
sizeof(struct i915_sw_dma_fence_cb_timer) :
sizeof(struct i915_sw_dma_fence_cb),
gfp);
if (!cb) {
if (!gfpflags_allow_blocking(gfp))
return -ENOMEM;
Expand All @@ -441,21 +455,26 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
cb->fence = fence;
i915_sw_fence_await(fence);

cb->dma = NULL;
func = dma_i915_sw_fence_wake;
if (timeout) {
cb->dma = dma_fence_get(dma);
init_irq_work(&cb->work, irq_i915_sw_fence_work);
struct i915_sw_dma_fence_cb_timer *timer =
container_of(cb, typeof(*timer), base);

timer_setup(&cb->timer,
timer->dma = dma_fence_get(dma);
init_irq_work(&timer->work, irq_i915_sw_fence_work);

timer_setup(&timer->timer,
timer_i915_sw_fence_wake, TIMER_IRQSAFE);
mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout));
mod_timer(&timer->timer, round_jiffies_up(jiffies + timeout));

func = dma_i915_sw_fence_wake_timer;
}

ret = dma_fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake);
ret = dma_fence_add_callback(dma, &cb->base, func);
if (ret == 0) {
ret = 1;
} else {
dma_i915_sw_fence_wake(dma, &cb->base);
func(dma, &cb->base);
if (ret == -ENOENT) /* fence already signaled */
ret = 0;
}
Expand Down

0 comments on commit f255c1e

Please sign in to comment.