0001
0002
0003
0004
0005
0006
0007 #include "i915_sw_fence_work.h"
0008
0009 static void fence_complete(struct dma_fence_work *f)
0010 {
0011 if (f->ops->release)
0012 f->ops->release(f);
0013 dma_fence_signal(&f->dma);
0014 }
0015
0016 static void fence_work(struct work_struct *work)
0017 {
0018 struct dma_fence_work *f = container_of(work, typeof(*f), work);
0019
0020 f->ops->work(f);
0021
0022 fence_complete(f);
0023 dma_fence_put(&f->dma);
0024 }
0025
0026 static int
0027 fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
0028 {
0029 struct dma_fence_work *f = container_of(fence, typeof(*f), chain);
0030
0031 switch (state) {
0032 case FENCE_COMPLETE:
0033 if (fence->error)
0034 dma_fence_set_error(&f->dma, fence->error);
0035
0036 if (!f->dma.error) {
0037 dma_fence_get(&f->dma);
0038 if (test_bit(DMA_FENCE_WORK_IMM, &f->dma.flags))
0039 fence_work(&f->work);
0040 else
0041 queue_work(system_unbound_wq, &f->work);
0042 } else {
0043 fence_complete(f);
0044 }
0045 break;
0046
0047 case FENCE_FREE:
0048 dma_fence_put(&f->dma);
0049 break;
0050 }
0051
0052 return NOTIFY_DONE;
0053 }
0054
0055 static const char *get_driver_name(struct dma_fence *fence)
0056 {
0057 return "dma-fence";
0058 }
0059
0060 static const char *get_timeline_name(struct dma_fence *fence)
0061 {
0062 struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
0063
0064 return f->ops->name ?: "work";
0065 }
0066
0067 static void fence_release(struct dma_fence *fence)
0068 {
0069 struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
0070
0071 i915_sw_fence_fini(&f->chain);
0072
0073 BUILD_BUG_ON(offsetof(typeof(*f), dma));
0074 dma_fence_free(&f->dma);
0075 }
0076
0077 static const struct dma_fence_ops fence_ops = {
0078 .get_driver_name = get_driver_name,
0079 .get_timeline_name = get_timeline_name,
0080 .release = fence_release,
0081 };
0082
0083 void dma_fence_work_init(struct dma_fence_work *f,
0084 const struct dma_fence_work_ops *ops)
0085 {
0086 f->ops = ops;
0087 spin_lock_init(&f->lock);
0088 dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0);
0089 i915_sw_fence_init(&f->chain, fence_notify);
0090 INIT_WORK(&f->work, fence_work);
0091 }
0092
0093 int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal)
0094 {
0095 if (!signal)
0096 return 0;
0097
0098 return __i915_sw_fence_await_dma_fence(&f->chain, signal, &f->cb);
0099 }