diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index b9f504ba3b32056e97fca71b652d34780f2d6593..5448efa77710eae3010c75e62a78b148b485bf3e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -26,27 +26,24 @@ static void __do_clflush(struct drm_i915_gem_object *obj) static int clflush_work(struct dma_fence_work *base) { struct clflush *clflush = container_of(base, typeof(*clflush), base); - struct drm_i915_gem_object *obj = fetch_and_zero(&clflush->obj); + struct drm_i915_gem_object *obj = clflush->obj; int err; err = i915_gem_object_pin_pages(obj); if (err) - goto put; + return err; __do_clflush(obj); i915_gem_object_unpin_pages(obj); -put: - i915_gem_object_put(obj); - return err; + return 0; } static void clflush_release(struct dma_fence_work *base) { struct clflush *clflush = container_of(base, typeof(*clflush), base); - if (clflush->obj) - i915_gem_object_put(clflush->obj); + i915_gem_object_put(clflush->obj); } static const struct dma_fence_work_ops clflush_ops = { diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c index 8538ee7a521de21b6006304e8577865a58498efc..997b2998f1f2158ea53e4b202f55154ecce5cbb4 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence_work.c +++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c @@ -6,6 +6,13 @@ #include "i915_sw_fence_work.h" +static void fence_complete(struct dma_fence_work *f) +{ + if (f->ops->release) + f->ops->release(f); + dma_fence_signal(&f->dma); +} + static void fence_work(struct work_struct *work) { struct dma_fence_work *f = container_of(work, typeof(*f), work); @@ -14,7 +21,8 @@ static void fence_work(struct work_struct *work) err = f->ops->work(f); if (err) dma_fence_set_error(&f->dma, err); - dma_fence_signal(&f->dma); + + fence_complete(f); dma_fence_put(&f->dma); } @@ -32,7 +40,7 @@ fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) dma_fence_get(&f->dma); queue_work(system_unbound_wq, &f->work); } else { - dma_fence_signal(&f->dma); + fence_complete(f); } break; @@ -60,9 +68,6 @@ static void fence_release(struct dma_fence *fence) { struct dma_fence_work *f = container_of(fence, typeof(*f), dma); - if (f->ops->release) - f->ops->release(f); - i915_sw_fence_fini(&f->chain); BUILD_BUG_ON(offsetof(typeof(*f), dma)); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 6794c742fbbf7eff6ceef4694dd730c4d6fadd73..62670459ee8e8049c5d17d03cd44af335ae0a1fb 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -292,6 +292,7 @@ i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_vma_work { struct dma_fence_work base; struct i915_vma *vma; + struct drm_i915_gem_object *pinned; enum i915_cache_level cache_level; unsigned int flags; }; @@ -306,15 +307,21 @@ static int __vma_bind(struct dma_fence_work *work) if (err) atomic_or(I915_VMA_ERROR, &vma->flags); - if (vma->obj) - __i915_gem_object_unpin_pages(vma->obj); - return err; } +static void __vma_release(struct dma_fence_work *work) +{ + struct i915_vma_work *vw = container_of(work, typeof(*vw), base); + + if (vw->pinned) + __i915_gem_object_unpin_pages(vw->pinned); +} + static const struct dma_fence_work_ops bind_ops = { .name = "bind", .work = __vma_bind, + .release = __vma_release, }; struct i915_vma_work *i915_vma_work(void) @@ -395,8 +402,10 @@ int i915_vma_bind(struct i915_vma *vma, i915_active_set_exclusive(&vma->active, &work->base.dma); work->base.dma.error = 0; /* enable the queue_work() */ - if (vma->obj) + if (vma->obj) { __i915_gem_object_pin_pages(vma->obj); + work->pinned = vma->obj; + } } else { GEM_BUG_ON((bind_flags & ~vma_flags) & vma->vm->bind_async_flags); ret = vma->ops->bind_vma(vma, cache_level, bind_flags);