1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2013-2016 Red Hat |
4 | * Author: Rob Clark <robdclark@gmail.com> |
5 | */ |
6 | |
7 | #ifndef __MSM_FENCE_H__ |
8 | #define __MSM_FENCE_H__ |
9 | |
10 | #include "msm_drv.h" |
11 | |
12 | /** |
13 | * struct msm_fence_context - fence context for gpu |
14 | * |
15 | * Each ringbuffer has a single fence context, with the GPU writing an |
16 | * incrementing fence seqno at the end of each submit |
17 | */ |
18 | struct msm_fence_context { |
19 | struct drm_device *dev; |
20 | /** name: human readable name for fence timeline */ |
21 | char name[32]; |
22 | /** context: see dma_fence_context_alloc() */ |
23 | unsigned context; |
24 | /** index: similar to context, but local to msm_fence_context's */ |
25 | unsigned index; |
26 | |
27 | /** |
28 | * last_fence: |
29 | * |
30 | * Last assigned fence, incremented each time a fence is created |
31 | * on this fence context. If last_fence == completed_fence, |
32 | * there is no remaining pending work |
33 | */ |
34 | uint32_t last_fence; |
35 | |
36 | /** |
37 | * completed_fence: |
38 | * |
39 | * The last completed fence, updated from the CPU after interrupt |
40 | * from GPU |
41 | */ |
42 | uint32_t completed_fence; |
43 | |
44 | /** |
45 | * fenceptr: |
46 | * |
47 | * The address that the GPU directly writes with completed fence |
48 | * seqno. This can be ahead of completed_fence. We can peek at |
49 | * this to see if a fence has already signaled but the CPU hasn't |
50 | * gotten around to handling the irq and updating completed_fence |
51 | */ |
52 | volatile uint32_t *fenceptr; |
53 | |
54 | spinlock_t spinlock; |
55 | |
56 | /* |
57 | * TODO this doesn't really deal with multiple deadlines, like |
58 | * if userspace got multiple frames ahead.. OTOH atomic updates |
59 | * don't queue, so maybe that is ok |
60 | */ |
61 | |
62 | /** next_deadline: Time of next deadline */ |
63 | ktime_t next_deadline; |
64 | |
65 | /** |
66 | * next_deadline_fence: |
67 | * |
68 | * Fence value for next pending deadline. The deadline timer is |
69 | * canceled when this fence is signaled. |
70 | */ |
71 | uint32_t next_deadline_fence; |
72 | |
73 | struct hrtimer deadline_timer; |
74 | struct kthread_work deadline_work; |
75 | }; |
76 | |
77 | struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, |
78 | volatile uint32_t *fenceptr, const char *name); |
79 | void msm_fence_context_free(struct msm_fence_context *fctx); |
80 | |
81 | bool msm_fence_completed(struct msm_fence_context *fctx, uint32_t fence); |
82 | void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); |
83 | |
84 | struct dma_fence * msm_fence_alloc(void); |
85 | void msm_fence_init(struct dma_fence *fence, struct msm_fence_context *fctx); |
86 | |
87 | static inline bool |
88 | fence_before(uint32_t a, uint32_t b) |
89 | { |
90 | return (int32_t)(a - b) < 0; |
91 | } |
92 | |
93 | static inline bool |
94 | fence_after(uint32_t a, uint32_t b) |
95 | { |
96 | return (int32_t)(a - b) > 0; |
97 | } |
98 | |
99 | #endif |
100 | |