intel_global_state.c (6510B)
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 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 * If the new state wasn't modified (and properly 187 * locked for write access) we throw it away. 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}