1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2020 Intel Corporation
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
__intel_atomic_global_state_free(struct kref * kref)13 static 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
intel_atomic_global_state_put(struct intel_global_state * obj_state)22 static 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
27 static struct intel_global_state *
intel_atomic_global_state_get(struct intel_global_state * obj_state)28 intel_atomic_global_state_get(struct intel_global_state *obj_state)
29 {
30 kref_get(&obj_state->ref);
31
32 return obj_state;
33 }
34
intel_atomic_global_obj_init(struct drm_i915_private * dev_priv,struct intel_global_obj * obj,struct intel_global_state * state,const struct intel_global_state_funcs * funcs)35 void 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->display.global.obj_list);
49 }
50
intel_atomic_global_obj_cleanup(struct drm_i915_private * dev_priv)51 void 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->display.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
assert_global_state_write_locked(struct drm_i915_private * dev_priv)63 static 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
modeset_lock_is_held(struct drm_modeset_acquire_ctx * ctx,struct drm_modeset_lock * lock)71 static 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
assert_global_state_read_locked(struct intel_atomic_state * state)84 static 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
98 struct intel_global_state *
intel_atomic_get_global_obj_state(struct intel_atomic_state * state,struct intel_global_obj * obj)99 intel_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 #ifdef __linux__
117 arr = krealloc(state->global_objs, size, GFP_KERNEL);
118 if (!arr)
119 return ERR_PTR(-ENOMEM);
120 #else
121 arr = kmalloc(size, GFP_KERNEL);
122 if (!arr)
123 return ERR_PTR(-ENOMEM);
124 memcpy(arr, state->global_objs,
125 sizeof(*state->global_objs) * state->num_global_objs);
126 kfree(state->global_objs);
127 #endif
128
129 state->global_objs = arr;
130 index = state->num_global_objs;
131 memset(&state->global_objs[index], 0, sizeof(*state->global_objs));
132
133 obj_state = obj->funcs->atomic_duplicate_state(obj);
134 if (!obj_state)
135 return ERR_PTR(-ENOMEM);
136
137 obj_state->obj = obj;
138 obj_state->changed = false;
139
140 kref_init(&obj_state->ref);
141
142 state->global_objs[index].state = obj_state;
143 state->global_objs[index].old_state =
144 intel_atomic_global_state_get(obj->state);
145 state->global_objs[index].new_state = obj_state;
146 state->global_objs[index].ptr = obj;
147 obj_state->state = state;
148
149 state->num_global_objs = num_objs;
150
151 drm_dbg_atomic(&i915->drm, "Added new global object %p state %p to %p\n",
152 obj, obj_state, state);
153
154 return obj_state;
155 }
156
157 struct intel_global_state *
intel_atomic_get_old_global_obj_state(struct intel_atomic_state * state,struct intel_global_obj * obj)158 intel_atomic_get_old_global_obj_state(struct intel_atomic_state *state,
159 struct intel_global_obj *obj)
160 {
161 int i;
162
163 for (i = 0; i < state->num_global_objs; i++)
164 if (obj == state->global_objs[i].ptr)
165 return state->global_objs[i].old_state;
166
167 return NULL;
168 }
169
170 struct intel_global_state *
intel_atomic_get_new_global_obj_state(struct intel_atomic_state * state,struct intel_global_obj * obj)171 intel_atomic_get_new_global_obj_state(struct intel_atomic_state *state,
172 struct intel_global_obj *obj)
173 {
174 int i;
175
176 for (i = 0; i < state->num_global_objs; i++)
177 if (obj == state->global_objs[i].ptr)
178 return state->global_objs[i].new_state;
179
180 return NULL;
181 }
182
intel_atomic_swap_global_state(struct intel_atomic_state * state)183 void intel_atomic_swap_global_state(struct intel_atomic_state *state)
184 {
185 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
186 struct intel_global_state *old_obj_state, *new_obj_state;
187 struct intel_global_obj *obj;
188 int i;
189
190 for_each_oldnew_global_obj_in_state(state, obj, old_obj_state,
191 new_obj_state, i) {
192 drm_WARN_ON(&dev_priv->drm, obj->state != old_obj_state);
193
194 /*
195 * If the new state wasn't modified (and properly
196 * locked for write access) we throw it away.
197 */
198 if (!new_obj_state->changed)
199 continue;
200
201 assert_global_state_write_locked(dev_priv);
202
203 old_obj_state->state = state;
204 new_obj_state->state = NULL;
205
206 state->global_objs[i].state = old_obj_state;
207
208 intel_atomic_global_state_put(obj->state);
209 obj->state = intel_atomic_global_state_get(new_obj_state);
210 }
211 }
212
intel_atomic_clear_global_state(struct intel_atomic_state * state)213 void intel_atomic_clear_global_state(struct intel_atomic_state *state)
214 {
215 int i;
216
217 for (i = 0; i < state->num_global_objs; i++) {
218 intel_atomic_global_state_put(state->global_objs[i].old_state);
219 intel_atomic_global_state_put(state->global_objs[i].new_state);
220
221 state->global_objs[i].ptr = NULL;
222 state->global_objs[i].state = NULL;
223 state->global_objs[i].old_state = NULL;
224 state->global_objs[i].new_state = NULL;
225 }
226 state->num_global_objs = 0;
227 }
228
intel_atomic_lock_global_state(struct intel_global_state * obj_state)229 int intel_atomic_lock_global_state(struct intel_global_state *obj_state)
230 {
231 struct intel_atomic_state *state = obj_state->state;
232 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
233 struct intel_crtc *crtc;
234
235 for_each_intel_crtc(&dev_priv->drm, crtc) {
236 int ret;
237
238 ret = drm_modeset_lock(&crtc->base.mutex,
239 state->base.acquire_ctx);
240 if (ret)
241 return ret;
242 }
243
244 obj_state->changed = true;
245
246 return 0;
247 }
248
intel_atomic_serialize_global_state(struct intel_global_state * obj_state)249 int intel_atomic_serialize_global_state(struct intel_global_state *obj_state)
250 {
251 struct intel_atomic_state *state = obj_state->state;
252 struct drm_i915_private *dev_priv = to_i915(state->base.dev);
253 struct intel_crtc *crtc;
254
255 for_each_intel_crtc(&dev_priv->drm, crtc) {
256 struct intel_crtc_state *crtc_state;
257
258 crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
259 if (IS_ERR(crtc_state))
260 return PTR_ERR(crtc_state);
261 }
262
263 obj_state->changed = true;
264
265 return 0;
266 }
267
268 bool
intel_atomic_global_state_is_serialized(struct intel_atomic_state * state)269 intel_atomic_global_state_is_serialized(struct intel_atomic_state *state)
270 {
271 struct drm_i915_private *i915 = to_i915(state->base.dev);
272 struct intel_crtc *crtc;
273
274 for_each_intel_crtc(&i915->drm, crtc)
275 if (!intel_atomic_get_new_crtc_state(state, crtc))
276 return false;
277 return true;
278 }
279