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