Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 
0003 /*
0004  * Copyright © 2019 Intel Corporation
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 }