1
2
3
4
5
6#include <linux/string.h>
7
8#include "i915_drv.h"
9#include "intel_atomic.h"
10#include "intel_display_types.h"
11#include "intel_global_state.h"
12
13static void __intel_atomic_global_state_free(struct kref *kref)
14{
15 struct intel_global_state *obj_state =
16 container_of(kref, struct intel_global_state, ref);
17 struct intel_global_obj *obj = obj_state->obj;
18
19 obj->funcs->atomic_destroy_state(obj, obj_state);
20}
21
22static void intel_atomic_global_state_put(struct intel_global_state *obj_state)
23{
24 kref_put(&obj_state->ref, __intel_atomic_global_state_free);
25}
26
27static struct intel_global_state *
28intel_atomic_global_state_get(struct intel_global_state *obj_state)
29{
30 kref_get(&obj_state->ref);
31
32 return obj_state;
33}
34
35void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv,
36 struct intel_global_obj *obj,
37 struct intel_global_state *state,
38 const struct intel_global_state_funcs *funcs)
39{
40 memset(obj, 0, sizeof(*obj));
41
42 state->obj = obj;
43
44 kref_init(&state->ref);
45
46 obj->state = state;
47 obj->funcs = funcs;
48 list_add_tail(&obj->head, &dev_priv->global_obj_list);
49}
50
51void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv)
52{
53 struct intel_global_obj *obj, *next;
54
55 list_for_each_entry_safe(obj, next, &dev_priv->global_obj_list, head) {
56 list_del(&obj->head);
57
58 drm_WARN_ON(&dev_priv->drm, kref_read(&obj->state->ref) != 1);
59 intel_atomic_global_state_put(obj->state);
60 }
61}
62
63static void assert_global_state_write_locked(struct drm_i915_private *dev_priv)
64{
65 struct intel_crtc *crtc;
66
67 for_each_intel_crtc(&dev_priv->drm, crtc)
68 drm_modeset_lock_assert_held(&crtc->base.mutex);
69}
70
71static bool modeset_lock_is_held(struct drm_modeset_acquire_ctx *ctx,
72 struct drm_modeset_lock *lock)
73{
74 struct drm_modeset_lock *l;
75
76 list_for_each_entry(l, &ctx->locked, head) {
77 if (lock == l)
78 return true;
79 }
80
81 return false;
82}
83
84static void assert_global_state_read_locked(struct intel_atomic_state *state)
85{
86 struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx;
87 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
88 struct intel_crtc *crtc;
89
90 for_each_intel_crtc(&dev_priv->drm, crtc) {
91 if (modeset_lock_is_held(ctx, &crtc->base.mutex))
92 return;
93 }
94
95 drm_WARN(&dev_priv->drm, 1, "Global state not read locked\n");
96}
97
98struct intel_global_state *
99intel_atomic_get_global_obj_state(struct intel_atomic_state *state,
100 struct intel_global_obj *obj)
101{
102 struct drm_i915_private *i915 = to_i915(state->base.dev);
103 int index, num_objs, i;
104 size_t size;
105 struct __intel_global_objs_state *arr;
106 struct intel_global_state *obj_state;
107
108 for (i = 0; i < state->num_global_objs; i++)
109 if (obj == state->global_objs[i].ptr)
110 return state->global_objs[i].state;
111
112 assert_global_state_read_locked(state);
113
114 num_objs = state->num_global_objs + 1;
115 size = sizeof(*state->global_objs) * num_objs;
116 arr = krealloc(state->global_objs, size, GFP_KERNEL);
117 if (!arr)
118 return ERR_PTR(-ENOMEM);
119
120 state->global_objs = arr;
121 index = state->num_global_objs;
122 memset(&state->global_objs[index], 0, sizeof(*state->global_objs));
123
124 obj_state = obj->funcs->atomic_duplicate_state(obj);
125 if (!obj_state)
126 return ERR_PTR(-ENOMEM);
127
128 obj_state->obj = obj;
129 obj_state->changed = false;
130
131 kref_init(&obj_state->ref);
132
133 state->global_objs[index].state = obj_state;
134 state->global_objs[index].old_state =
135 intel_atomic_global_state_get(obj->state);
136 state->global_objs[index].new_state = obj_state;
137 state->global_objs[index].ptr = obj;
138 obj_state->state = state;
139
140 state->num_global_objs = num_objs;
141
142 drm_dbg_atomic(&i915->drm, "Added new global object %p state %p to %p\n",
143 obj, obj_state, state);
144
145 return obj_state;
146}
147
148struct intel_global_state *
149intel_atomic_get_old_global_obj_state(struct intel_atomic_state *state,
150 struct intel_global_obj *obj)
151{
152 int i;
153
154 for (i = 0; i < state->num_global_objs; i++)
155 if (obj == state->global_objs[i].ptr)
156 return state->global_objs[i].old_state;
157
158 return NULL;
159}
160
161struct intel_global_state *
162intel_atomic_get_new_global_obj_state(struct intel_atomic_state *state,
163 struct intel_global_obj *obj)
164{
165 int i;
166
167 for (i = 0; i < state->num_global_objs; i++)
168 if (obj == state->global_objs[i].ptr)
169 return state->global_objs[i].new_state;
170
171 return NULL;
172}
173
174void intel_atomic_swap_global_state(struct intel_atomic_state *state)
175{
176 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
177 struct intel_global_state *old_obj_state, *new_obj_state;
178 struct intel_global_obj *obj;
179 int i;
180
181 for_each_oldnew_global_obj_in_state(state, obj, old_obj_state,
182 new_obj_state, i) {
183 drm_WARN_ON(&dev_priv->drm, obj->state != old_obj_state);
184
185
186
187
188
189 if (!new_obj_state->changed)
190 continue;
191
192 assert_global_state_write_locked(dev_priv);
193
194 old_obj_state->state = state;
195 new_obj_state->state = NULL;
196
197 state->global_objs[i].state = old_obj_state;
198
199 intel_atomic_global_state_put(obj->state);
200 obj->state = intel_atomic_global_state_get(new_obj_state);
201 }
202}
203
204void intel_atomic_clear_global_state(struct intel_atomic_state *state)
205{
206 int i;
207
208 for (i = 0; i < state->num_global_objs; i++) {
209 intel_atomic_global_state_put(state->global_objs[i].old_state);
210 intel_atomic_global_state_put(state->global_objs[i].new_state);
211
212 state->global_objs[i].ptr = NULL;
213 state->global_objs[i].state = NULL;
214 state->global_objs[i].old_state = NULL;
215 state->global_objs[i].new_state = NULL;
216 }
217 state->num_global_objs = 0;
218}
219
220int intel_atomic_lock_global_state(struct intel_global_state *obj_state)
221{
222 struct intel_atomic_state *state = obj_state->state;
223 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
224 struct intel_crtc *crtc;
225
226 for_each_intel_crtc(&dev_priv->drm, crtc) {
227 int ret;
228
229 ret = drm_modeset_lock(&crtc->base.mutex,
230 state->base.acquire_ctx);
231 if (ret)
232 return ret;
233 }
234
235 obj_state->changed = true;
236
237 return 0;
238}
239
240int intel_atomic_serialize_global_state(struct intel_global_state *obj_state)
241{
242 struct intel_atomic_state *state = obj_state->state;
243 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
244 struct intel_crtc *crtc;
245
246 for_each_intel_crtc(&dev_priv->drm, crtc) {
247 struct intel_crtc_state *crtc_state;
248
249 crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
250 if (IS_ERR(crtc_state))
251 return PTR_ERR(crtc_state);
252 }
253
254 obj_state->changed = true;
255
256 return 0;
257}
258