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 13 struct intel_global_commit { 14 struct kref ref; 15 struct completion done; 16 }; 17 18 static struct intel_global_commit *commit_new(void) 19 { 20 struct intel_global_commit *commit; 21 22 commit = kzalloc(sizeof(*commit), GFP_KERNEL); 23 if (!commit) 24 return NULL; 25 26 init_completion(&commit->done); 27 kref_init(&commit->ref); 28 29 return commit; 30 } 31 32 static void __commit_free(struct kref *kref) 33 { 34 struct intel_global_commit *commit = 35 container_of(kref, typeof(*commit), ref); 36 37 kfree(commit); 38 } 39 40 static struct intel_global_commit *commit_get(struct intel_global_commit *commit) 41 { 42 if (commit) 43 kref_get(&commit->ref); 44 45 return commit; 46 } 47 48 static void commit_put(struct intel_global_commit *commit) 49 { 50 if (commit) 51 kref_put(&commit->ref, __commit_free); 52 } 53 54 static void __intel_atomic_global_state_free(struct kref *kref) 55 { 56 struct intel_global_state *obj_state = 57 container_of(kref, struct intel_global_state, ref); 58 struct intel_global_obj *obj = obj_state->obj; 59 60 commit_put(obj_state->commit); 61 62 obj->funcs->atomic_destroy_state(obj, obj_state); 63 } 64 65 static void intel_atomic_global_state_put(struct intel_global_state *obj_state) 66 { 67 kref_put(&obj_state->ref, __intel_atomic_global_state_free); 68 } 69 70 static struct intel_global_state * 71 intel_atomic_global_state_get(struct intel_global_state *obj_state) 72 { 73 kref_get(&obj_state->ref); 74 75 return obj_state; 76 } 77 78 void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv, 79 struct intel_global_obj *obj, 80 struct intel_global_state *state, 81 const struct intel_global_state_funcs *funcs) 82 { 83 memset(obj, 0, sizeof(*obj)); 84 85 state->obj = obj; 86 87 kref_init(&state->ref); 88 89 obj->state = state; 90 obj->funcs = funcs; 91 list_add_tail(&obj->head, &dev_priv->display.global.obj_list); 92 } 93 94 void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv) 95 { 96 struct intel_global_obj *obj, *next; 97 98 list_for_each_entry_safe(obj, next, &dev_priv->display.global.obj_list, head) { 99 list_del(&obj->head); 100 101 drm_WARN_ON(&dev_priv->drm, kref_read(&obj->state->ref) != 1); 102 intel_atomic_global_state_put(obj->state); 103 } 104 } 105 106 static void assert_global_state_write_locked(struct drm_i915_private *dev_priv) 107 { 108 struct intel_crtc *crtc; 109 110 for_each_intel_crtc(&dev_priv->drm, crtc) 111 drm_modeset_lock_assert_held(&crtc->base.mutex); 112 } 113 114 static bool modeset_lock_is_held(struct drm_modeset_acquire_ctx *ctx, 115 struct drm_modeset_lock *lock) 116 { 117 struct drm_modeset_lock *l; 118 119 list_for_each_entry(l, &ctx->locked, head) { 120 if (lock == l) 121 return true; 122 } 123 124 return false; 125 } 126 127 static void assert_global_state_read_locked(struct intel_atomic_state *state) 128 { 129 struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx; 130 struct drm_i915_private *dev_priv = to_i915(state->base.dev); 131 struct intel_crtc *crtc; 132 133 for_each_intel_crtc(&dev_priv->drm, crtc) { 134 if (modeset_lock_is_held(ctx, &crtc->base.mutex)) 135 return; 136 } 137 138 drm_WARN(&dev_priv->drm, 1, "Global state not read locked\n"); 139 } 140 141 struct intel_global_state * 142 intel_atomic_get_global_obj_state(struct intel_atomic_state *state, 143 struct intel_global_obj *obj) 144 { 145 struct drm_i915_private *i915 = to_i915(state->base.dev); 146 int index, num_objs, i; 147 size_t size; 148 struct __intel_global_objs_state *arr; 149 struct intel_global_state *obj_state; 150 151 for (i = 0; i < state->num_global_objs; i++) 152 if (obj == state->global_objs[i].ptr) 153 return state->global_objs[i].state; 154 155 assert_global_state_read_locked(state); 156 157 num_objs = state->num_global_objs + 1; 158 size = sizeof(*state->global_objs) * num_objs; 159 arr = krealloc(state->global_objs, size, GFP_KERNEL); 160 if (!arr) 161 return ERR_PTR(-ENOMEM); 162 163 state->global_objs = arr; 164 index = state->num_global_objs; 165 memset(&state->global_objs[index], 0, sizeof(*state->global_objs)); 166 167 obj_state = obj->funcs->atomic_duplicate_state(obj); 168 if (!obj_state) 169 return ERR_PTR(-ENOMEM); 170 171 obj_state->obj = obj; 172 obj_state->changed = false; 173 obj_state->serialized = false; 174 obj_state->commit = NULL; 175 176 kref_init(&obj_state->ref); 177 178 state->global_objs[index].state = obj_state; 179 state->global_objs[index].old_state = 180 intel_atomic_global_state_get(obj->state); 181 state->global_objs[index].new_state = obj_state; 182 state->global_objs[index].ptr = obj; 183 obj_state->state = state; 184 185 state->num_global_objs = num_objs; 186 187 drm_dbg_atomic(&i915->drm, "Added new global object %p state %p to %p\n", 188 obj, obj_state, state); 189 190 return obj_state; 191 } 192 193 struct intel_global_state * 194 intel_atomic_get_old_global_obj_state(struct intel_atomic_state *state, 195 struct intel_global_obj *obj) 196 { 197 int i; 198 199 for (i = 0; i < state->num_global_objs; i++) 200 if (obj == state->global_objs[i].ptr) 201 return state->global_objs[i].old_state; 202 203 return NULL; 204 } 205 206 struct intel_global_state * 207 intel_atomic_get_new_global_obj_state(struct intel_atomic_state *state, 208 struct intel_global_obj *obj) 209 { 210 int i; 211 212 for (i = 0; i < state->num_global_objs; i++) 213 if (obj == state->global_objs[i].ptr) 214 return state->global_objs[i].new_state; 215 216 return NULL; 217 } 218 219 void intel_atomic_swap_global_state(struct intel_atomic_state *state) 220 { 221 struct drm_i915_private *dev_priv = to_i915(state->base.dev); 222 struct intel_global_state *old_obj_state, *new_obj_state; 223 struct intel_global_obj *obj; 224 int i; 225 226 for_each_oldnew_global_obj_in_state(state, obj, old_obj_state, 227 new_obj_state, i) { 228 drm_WARN_ON(&dev_priv->drm, obj->state != old_obj_state); 229 230 /* 231 * If the new state wasn't modified (and properly 232 * locked for write access) we throw it away. 233 */ 234 if (!new_obj_state->changed) 235 continue; 236 237 assert_global_state_write_locked(dev_priv); 238 239 old_obj_state->state = state; 240 new_obj_state->state = NULL; 241 242 state->global_objs[i].state = old_obj_state; 243 244 intel_atomic_global_state_put(obj->state); 245 obj->state = intel_atomic_global_state_get(new_obj_state); 246 } 247 } 248 249 void intel_atomic_clear_global_state(struct intel_atomic_state *state) 250 { 251 int i; 252 253 for (i = 0; i < state->num_global_objs; i++) { 254 intel_atomic_global_state_put(state->global_objs[i].old_state); 255 intel_atomic_global_state_put(state->global_objs[i].new_state); 256 257 state->global_objs[i].ptr = NULL; 258 state->global_objs[i].state = NULL; 259 state->global_objs[i].old_state = NULL; 260 state->global_objs[i].new_state = NULL; 261 } 262 state->num_global_objs = 0; 263 } 264 265 int intel_atomic_lock_global_state(struct intel_global_state *obj_state) 266 { 267 struct intel_atomic_state *state = obj_state->state; 268 struct drm_i915_private *dev_priv = to_i915(state->base.dev); 269 struct intel_crtc *crtc; 270 271 for_each_intel_crtc(&dev_priv->drm, crtc) { 272 int ret; 273 274 ret = drm_modeset_lock(&crtc->base.mutex, 275 state->base.acquire_ctx); 276 if (ret) 277 return ret; 278 } 279 280 obj_state->changed = true; 281 282 return 0; 283 } 284 285 int intel_atomic_serialize_global_state(struct intel_global_state *obj_state) 286 { 287 int ret; 288 289 ret = intel_atomic_lock_global_state(obj_state); 290 if (ret) 291 return ret; 292 293 obj_state->serialized = true; 294 295 return 0; 296 } 297 298 bool 299 intel_atomic_global_state_is_serialized(struct intel_atomic_state *state) 300 { 301 struct drm_i915_private *i915 = to_i915(state->base.dev); 302 struct intel_crtc *crtc; 303 304 for_each_intel_crtc(&i915->drm, crtc) 305 if (!intel_atomic_get_new_crtc_state(state, crtc)) 306 return false; 307 return true; 308 } 309 310 int 311 intel_atomic_global_state_setup_commit(struct intel_atomic_state *state) 312 { 313 const struct intel_global_state *old_obj_state; 314 struct intel_global_state *new_obj_state; 315 struct intel_global_obj *obj; 316 int i; 317 318 for_each_oldnew_global_obj_in_state(state, obj, old_obj_state, 319 new_obj_state, i) { 320 struct intel_global_commit *commit = NULL; 321 322 if (new_obj_state->serialized) { 323 /* 324 * New commit which is going to be completed 325 * after the hardware reprogramming is done. 326 */ 327 commit = commit_new(); 328 if (!commit) 329 return -ENOMEM; 330 } else if (new_obj_state->changed) { 331 /* 332 * We're going to swap to this state, so carry the 333 * previous commit along, in case it's not yet done. 334 */ 335 commit = commit_get(old_obj_state->commit); 336 } 337 338 new_obj_state->commit = commit; 339 } 340 341 return 0; 342 } 343 344 int 345 intel_atomic_global_state_wait_for_dependencies(struct intel_atomic_state *state) 346 { 347 struct drm_i915_private *i915 = to_i915(state->base.dev); 348 const struct intel_global_state *old_obj_state; 349 struct intel_global_obj *obj; 350 int i; 351 352 for_each_old_global_obj_in_state(state, obj, old_obj_state, i) { 353 struct intel_global_commit *commit = old_obj_state->commit; 354 long ret; 355 356 if (!commit) 357 continue; 358 359 ret = wait_for_completion_timeout(&commit->done, 10 * HZ); 360 if (ret == 0) { 361 drm_err(&i915->drm, "global state timed out\n"); 362 return -ETIMEDOUT; 363 } 364 } 365 366 return 0; 367 } 368 369 void 370 intel_atomic_global_state_commit_done(struct intel_atomic_state *state) 371 { 372 const struct intel_global_state *new_obj_state; 373 struct intel_global_obj *obj; 374 int i; 375 376 for_each_new_global_obj_in_state(state, obj, new_obj_state, i) { 377 struct intel_global_commit *commit = new_obj_state->commit; 378 379 if (!new_obj_state->serialized) 380 continue; 381 382 complete_all(&commit->done); 383 } 384 } 385