Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT 2 : : 3 : : /* 4 : : * Copyright © 2019 Intel Corporation 5 : : */ 6 : : 7 : : #include "i915_sw_fence_work.h" 8 : : 9 : 0 : static void fence_complete(struct dma_fence_work *f) 10 : : { 11 [ # # ]: 0 : if (f->ops->release) 12 : 0 : f->ops->release(f); 13 : 0 : dma_fence_signal(&f->dma); 14 : 0 : } 15 : : 16 : 0 : static void fence_work(struct work_struct *work) 17 : : { 18 : 0 : struct dma_fence_work *f = container_of(work, typeof(*f), work); 19 : 0 : int err; 20 : : 21 : 0 : err = f->ops->work(f); 22 [ # # ]: 0 : if (err) 23 : 0 : dma_fence_set_error(&f->dma, err); 24 : : 25 : 0 : fence_complete(f); 26 : 0 : dma_fence_put(&f->dma); 27 : 0 : } 28 : : 29 : : static int __i915_sw_fence_call 30 : 0 : fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) 31 : : { 32 : 0 : struct dma_fence_work *f = container_of(fence, typeof(*f), chain); 33 : : 34 [ # # # ]: 0 : switch (state) { 35 : 0 : case FENCE_COMPLETE: 36 [ # # ]: 0 : if (fence->error) 37 : 0 : dma_fence_set_error(&f->dma, fence->error); 38 : : 39 [ # # ]: 0 : if (!f->dma.error) { 40 [ # # ]: 0 : dma_fence_get(&f->dma); 41 : 0 : queue_work(system_unbound_wq, &f->work); 42 : : } else { 43 : 0 : fence_complete(f); 44 : : } 45 : : break; 46 : : 47 : 0 : case FENCE_FREE: 48 : 0 : dma_fence_put(&f->dma); 49 : 0 : break; 50 : : } 51 : : 52 : 0 : return NOTIFY_DONE; 53 : : } 54 : : 55 : 0 : static const char *get_driver_name(struct dma_fence *fence) 56 : : { 57 : 0 : return "dma-fence"; 58 : : } 59 : : 60 : 0 : static const char *get_timeline_name(struct dma_fence *fence) 61 : : { 62 : 0 : struct dma_fence_work *f = container_of(fence, typeof(*f), dma); 63 : : 64 [ # # ]: 0 : return f->ops->name ?: "work"; 65 : : } 66 : : 67 : 0 : static void fence_release(struct dma_fence *fence) 68 : : { 69 : 0 : struct dma_fence_work *f = container_of(fence, typeof(*f), dma); 70 : : 71 : 0 : i915_sw_fence_fini(&f->chain); 72 : : 73 : 0 : BUILD_BUG_ON(offsetof(typeof(*f), dma)); 74 : 0 : dma_fence_free(&f->dma); 75 : 0 : } 76 : : 77 : : static const struct dma_fence_ops fence_ops = { 78 : : .get_driver_name = get_driver_name, 79 : : .get_timeline_name = get_timeline_name, 80 : : .release = fence_release, 81 : : }; 82 : : 83 : 0 : void dma_fence_work_init(struct dma_fence_work *f, 84 : : const struct dma_fence_work_ops *ops) 85 : : { 86 : 0 : f->ops = ops; 87 : 0 : spin_lock_init(&f->lock); 88 : 0 : dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0); 89 : 0 : i915_sw_fence_init(&f->chain, fence_notify); 90 : 0 : INIT_WORK(&f->work, fence_work); 91 : 0 : } 92 : : 93 : 0 : int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal) 94 : : { 95 [ # # ]: 0 : if (!signal) 96 : : return 0; 97 : : 98 : 0 : return __i915_sw_fence_await_dma_fence(&f->chain, signal, &f->cb); 99 : : }