hc
2024-08-12 233ab1bd4c5697f5cdec94e60206e8c6ac609b4c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// SPDX-License-Identifier: MIT
 
/*
 * Copyright © 2019 Intel Corporation
 */
 
#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);
   int err;
 
   err = f->ops->work(f);
   if (err)
       dma_fence_set_error(&f->dma, err);
 
   fence_complete(f);
   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);
           if (test_bit(DMA_FENCE_WORK_IMM, &f->dma.flags))
               fence_work(&f->work);
           else
               queue_work(system_unbound_wq, &f->work);
       } else {
           fence_complete(f);
       }
       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);
 
   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)
{
   f->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);
}
 
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);
}