diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2019-08-21 20:16:06 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2019-08-22 08:27:44 +0100 |
commit | 8e458fe2ee05cf3fb1fb6bf9857e71e15c4d7441 (patch) | |
tree | e61a227ecb3361f9fd4aea032a9b7836cb4b0e30 /drivers/gpu/drm/i915/i915_sw_fence_work.c | |
parent | 829e8def7bd7b1e58028113ee5c2877da89d8f27 (diff) | |
download | linux-stable-8e458fe2ee05cf3fb1fb6bf9857e71e15c4d7441.tar.gz linux-stable-8e458fe2ee05cf3fb1fb6bf9857e71e15c4d7441.tar.bz2 linux-stable-8e458fe2ee05cf3fb1fb6bf9857e71e15c4d7441.zip |
drm/i915: Generalise the clflush dma-worker
Extract the dma-fence worker used by clflush for wider use, as we
anticipate using workers coupled to dma-fences more frequently.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190821191606.17001-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/i915_sw_fence_work.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_sw_fence_work.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c new file mode 100644 index 000000000000..07552cd544f2 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT + +/* + * Copyright © 2019 Intel Corporation + */ + +#include "i915_sw_fence_work.h" + +static void fence_work(struct work_struct *work) +{ + struct dma_fence_work *f = container_of(work, typeof(*f), work); + int err; + + err = f->ops->work(f); + if (err) + dma_fence_set_error(&f->dma, err); + dma_fence_signal(&f->dma); + dma_fence_put(&f->dma); +} + +static int __i915_sw_fence_call +fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) +{ + struct dma_fence_work *f = container_of(fence, typeof(*f), chain); + + switch (state) { + case FENCE_COMPLETE: + if (fence->error) + dma_fence_set_error(&f->dma, fence->error); + + if (!f->dma.error) { + dma_fence_get(&f->dma); + queue_work(system_unbound_wq, &f->work); + } else { + dma_fence_signal(&f->dma); + } + break; + + case FENCE_FREE: + dma_fence_put(&f->dma); + break; + } + + return NOTIFY_DONE; +} + +static const char *get_driver_name(struct dma_fence *fence) +{ + return "dma-fence"; +} + +static const char *get_timeline_name(struct dma_fence *fence) +{ + struct dma_fence_work *f = container_of(fence, typeof(*f), dma); + + return f->ops->name ?: "work"; +} + +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)); + dma_fence_free(&f->dma); +} + +static const struct dma_fence_ops fence_ops = { + .get_driver_name = get_driver_name, + .get_timeline_name = get_timeline_name, + .release = fence_release, +}; + +void dma_fence_work_init(struct dma_fence_work *f, + const struct dma_fence_work_ops *ops) +{ + spin_lock_init(&f->lock); + dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0); + i915_sw_fence_init(&f->chain, fence_notify); + INIT_WORK(&f->work, fence_work); + + f->ops = ops; +} + +int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal) +{ + if (!signal) + return 0; + + return __i915_sw_fence_await_dma_fence(&f->chain, signal, &f->cb); +} |