Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Add an implementation for i915_gem_ww_ctx locking, v2.

i915_gem_ww_ctx is used to lock all gem bo's for pinning and memory
eviction. We don't use it yet, but lets start adding the definition
first.

To use it, we have to pass a non-NULL ww to gem_object_lock, and don't
unlock directly. It is done in i915_gem_ww_ctx_fini.

Changes since v1:
- Change ww_ctx and obj order in locking functions (Jonas Lahtinen)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-6-maarten.lankhorst@linux.intel.com
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

authored by

Maarten Lankhorst and committed by
Joonas Lahtinen
80f0b679 8ae275c2

+171 -40
+2 -2
drivers/gpu/drm/i915/display/intel_display.c
··· 2311 2311 2312 2312 void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) 2313 2313 { 2314 - i915_gem_object_lock(vma->obj); 2314 + i915_gem_object_lock(vma->obj, NULL); 2315 2315 if (flags & PLANE_HAS_FENCE) 2316 2316 i915_vma_unpin_fence(vma); 2317 2317 i915_gem_object_unpin_from_display_plane(vma); ··· 17194 17194 if (!intel_fb->frontbuffer) 17195 17195 return -ENOMEM; 17196 17196 17197 - i915_gem_object_lock(obj); 17197 + i915_gem_object_lock(obj, NULL); 17198 17198 tiling = i915_gem_object_get_tiling(obj); 17199 17199 stride = i915_gem_object_get_stride(obj); 17200 17200 i915_gem_object_unlock(obj);
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
··· 288 288 dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0); 289 289 i915_sw_fence_init(&work->wait, clear_pages_work_notify); 290 290 291 - i915_gem_object_lock(obj); 291 + i915_gem_object_lock(obj, NULL); 292 292 err = i915_sw_fence_await_reservation(&work->wait, 293 293 obj->base.resv, NULL, true, 0, 294 294 I915_FENCE_GFP);
+2 -2
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
··· 128 128 if (err) 129 129 return err; 130 130 131 - err = i915_gem_object_lock_interruptible(obj); 131 + err = i915_gem_object_lock_interruptible(obj, NULL); 132 132 if (err) 133 133 goto out; 134 134 ··· 149 149 if (err) 150 150 return err; 151 151 152 - err = i915_gem_object_lock_interruptible(obj); 152 + err = i915_gem_object_lock_interruptible(obj, NULL); 153 153 if (err) 154 154 goto out; 155 155
+5 -5
drivers/gpu/drm/i915/gem/i915_gem_domain.c
··· 32 32 if (!i915_gem_object_is_framebuffer(obj)) 33 33 return; 34 34 35 - i915_gem_object_lock(obj); 35 + i915_gem_object_lock(obj, NULL); 36 36 __i915_gem_object_flush_for_display(obj); 37 37 i915_gem_object_unlock(obj); 38 38 } ··· 197 197 if (ret) 198 198 return ret; 199 199 200 - ret = i915_gem_object_lock_interruptible(obj); 200 + ret = i915_gem_object_lock_interruptible(obj, NULL); 201 201 if (ret) 202 202 return ret; 203 203 ··· 536 536 if (err) 537 537 goto out; 538 538 539 - err = i915_gem_object_lock_interruptible(obj); 539 + err = i915_gem_object_lock_interruptible(obj, NULL); 540 540 if (err) 541 541 goto out_unpin; 542 542 ··· 576 576 if (!i915_gem_object_has_struct_page(obj)) 577 577 return -ENODEV; 578 578 579 - ret = i915_gem_object_lock_interruptible(obj); 579 + ret = i915_gem_object_lock_interruptible(obj, NULL); 580 580 if (ret) 581 581 return ret; 582 582 ··· 630 630 if (!i915_gem_object_has_struct_page(obj)) 631 631 return -ENODEV; 632 632 633 - ret = i915_gem_object_lock_interruptible(obj); 633 + ret = i915_gem_object_lock_interruptible(obj, NULL); 634 634 if (ret) 635 635 return ret; 636 636
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
··· 1076 1076 if (use_cpu_reloc(cache, obj)) 1077 1077 return NULL; 1078 1078 1079 - i915_gem_object_lock(obj); 1079 + i915_gem_object_lock(obj, NULL); 1080 1080 err = i915_gem_object_set_to_gtt_domain(obj, true); 1081 1081 i915_gem_object_unlock(obj); 1082 1082 if (err)
+32 -8
drivers/gpu/drm/i915/gem/i915_gem_object.h
··· 110 110 111 111 #define assert_object_held(obj) dma_resv_assert_held((obj)->base.resv) 112 112 113 - static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj) 113 + static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, 114 + struct i915_gem_ww_ctx *ww, 115 + bool intr) 114 116 { 115 - dma_resv_lock(obj->base.resv, NULL); 117 + int ret; 118 + 119 + if (intr) 120 + ret = dma_resv_lock_interruptible(obj->base.resv, ww ? &ww->ctx : NULL); 121 + else 122 + ret = dma_resv_lock(obj->base.resv, ww ? &ww->ctx : NULL); 123 + 124 + if (!ret && ww) 125 + list_add_tail(&obj->obj_link, &ww->obj_list); 126 + if (ret == -EALREADY) 127 + ret = 0; 128 + 129 + if (ret == -EDEADLK) 130 + ww->contended = obj; 131 + 132 + return ret; 133 + } 134 + 135 + static inline int i915_gem_object_lock(struct drm_i915_gem_object *obj, 136 + struct i915_gem_ww_ctx *ww) 137 + { 138 + return __i915_gem_object_lock(obj, ww, ww && ww->intr); 139 + } 140 + 141 + static inline int i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj, 142 + struct i915_gem_ww_ctx *ww) 143 + { 144 + WARN_ON(ww && !ww->intr); 145 + return __i915_gem_object_lock(obj, ww, true); 116 146 } 117 147 118 148 static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj) 119 149 { 120 150 return dma_resv_trylock(obj->base.resv); 121 - } 122 - 123 - static inline int 124 - i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj) 125 - { 126 - return dma_resv_lock_interruptible(obj->base.resv, NULL); 127 151 } 128 152 129 153 static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
+9
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
··· 123 123 struct list_head lut_list; 124 124 spinlock_t lut_lock; /* guards lut_list */ 125 125 126 + /** 127 + * @obj_link: Link into @i915_gem_ww_ctx.obj_list 128 + * 129 + * When we lock this object through i915_gem_object_lock() with a 130 + * context, we add it to the list to ensure we can unlock everything 131 + * when i915_gem_ww_ctx_backoff() or i915_gem_ww_ctx_fini() are called. 132 + */ 133 + struct list_head obj_link; 134 + 126 135 /** Stolen memory for this object, instead of being backed by shmem. */ 127 136 struct drm_mm_node *stolen; 128 137 union {
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_pm.c
··· 84 84 85 85 spin_unlock_irqrestore(&i915->mm.obj_lock, flags); 86 86 87 - i915_gem_object_lock(obj); 87 + i915_gem_object_lock(obj, NULL); 88 88 drm_WARN_ON(&i915->drm, 89 89 i915_gem_object_set_to_gtt_domain(obj, false)); 90 90 i915_gem_object_unlock(obj);
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_tiling.c
··· 249 249 * whilst executing a fenced command for an untiled object. 250 250 */ 251 251 252 - i915_gem_object_lock(obj); 252 + i915_gem_object_lock(obj, NULL); 253 253 if (i915_gem_object_is_framebuffer(obj)) { 254 254 i915_gem_object_unlock(obj); 255 255 return -EBUSY;
+1 -1
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
··· 947 947 { 948 948 int err; 949 949 950 - i915_gem_object_lock(vma->obj); 950 + i915_gem_object_lock(vma->obj, NULL); 951 951 err = i915_gem_object_set_to_gtt_domain(vma->obj, true); 952 952 i915_gem_object_unlock(vma->obj); 953 953 if (err)
+1 -1
drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
··· 75 75 if (err) 76 76 goto err_unpin; 77 77 78 - i915_gem_object_lock(obj); 78 + i915_gem_object_lock(obj, NULL); 79 79 err = i915_gem_object_set_to_cpu_domain(obj, false); 80 80 i915_gem_object_unlock(obj); 81 81 if (err)
+5 -5
drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
··· 82 82 u32 __iomem *map; 83 83 int err = 0; 84 84 85 - i915_gem_object_lock(ctx->obj); 85 + i915_gem_object_lock(ctx->obj, NULL); 86 86 err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); 87 87 i915_gem_object_unlock(ctx->obj); 88 88 if (err) ··· 115 115 u32 __iomem *map; 116 116 int err = 0; 117 117 118 - i915_gem_object_lock(ctx->obj); 118 + i915_gem_object_lock(ctx->obj, NULL); 119 119 err = i915_gem_object_set_to_gtt_domain(ctx->obj, false); 120 120 i915_gem_object_unlock(ctx->obj); 121 121 if (err) ··· 147 147 u32 *map; 148 148 int err; 149 149 150 - i915_gem_object_lock(ctx->obj); 150 + i915_gem_object_lock(ctx->obj, NULL); 151 151 err = i915_gem_object_set_to_wc_domain(ctx->obj, true); 152 152 i915_gem_object_unlock(ctx->obj); 153 153 if (err) ··· 170 170 u32 *map; 171 171 int err; 172 172 173 - i915_gem_object_lock(ctx->obj); 173 + i915_gem_object_lock(ctx->obj, NULL); 174 174 err = i915_gem_object_set_to_wc_domain(ctx->obj, false); 175 175 i915_gem_object_unlock(ctx->obj); 176 176 if (err) ··· 193 193 u32 *cs; 194 194 int err; 195 195 196 - i915_gem_object_lock(ctx->obj); 196 + i915_gem_object_lock(ctx->obj, NULL); 197 197 err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); 198 198 i915_gem_object_unlock(ctx->obj); 199 199 if (err)
+2 -2
drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
··· 950 950 if (IS_ERR(vma)) 951 951 return PTR_ERR(vma); 952 952 953 - i915_gem_object_lock(obj); 953 + i915_gem_object_lock(obj, NULL); 954 954 err = i915_gem_object_set_to_gtt_domain(obj, false); 955 955 i915_gem_object_unlock(obj); 956 956 if (err) ··· 1709 1709 1710 1710 i915_request_add(rq); 1711 1711 1712 - i915_gem_object_lock(obj); 1712 + i915_gem_object_lock(obj, NULL); 1713 1713 err = i915_gem_object_set_to_cpu_domain(obj, false); 1714 1714 i915_gem_object_unlock(obj); 1715 1715 if (err)
+2 -2
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
··· 103 103 GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); 104 104 GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); 105 105 106 - i915_gem_object_lock(obj); 106 + i915_gem_object_lock(obj, NULL); 107 107 err = i915_gem_object_set_to_gtt_domain(obj, true); 108 108 i915_gem_object_unlock(obj); 109 109 if (err) { ··· 188 188 GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); 189 189 GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); 190 190 191 - i915_gem_object_lock(obj); 191 + i915_gem_object_lock(obj, NULL); 192 192 err = i915_gem_object_set_to_gtt_domain(obj, true); 193 193 i915_gem_object_unlock(obj); 194 194 if (err) {
+1 -1
drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
··· 44 44 } 45 45 46 46 /* Make the object dirty so that put_pages must do copy back the data */ 47 - i915_gem_object_lock(obj); 47 + i915_gem_object_lock(obj, NULL); 48 48 err = i915_gem_object_set_to_gtt_domain(obj, true); 49 49 i915_gem_object_unlock(obj); 50 50 if (err) {
+1 -1
drivers/gpu/drm/i915/gt/selftest_workarounds.c
··· 214 214 return PTR_ERR(results); 215 215 216 216 err = 0; 217 - i915_gem_object_lock(results); 217 + i915_gem_object_lock(results, NULL); 218 218 intel_wedge_on_timeout(&wedge, engine->gt, HZ / 5) /* safety net! */ 219 219 err = i915_gem_object_set_to_cpu_domain(results, false); 220 220 i915_gem_object_unlock(results);
+1 -1
drivers/gpu/drm/i915/gvt/cmd_parser.c
··· 2982 2982 goto put_obj; 2983 2983 } 2984 2984 2985 - i915_gem_object_lock(obj); 2985 + i915_gem_object_lock(obj, NULL); 2986 2986 ret = i915_gem_object_set_to_cpu_domain(obj, false); 2987 2987 i915_gem_object_unlock(obj); 2988 2988 if (ret) {
+49 -3
drivers/gpu/drm/i915/i915_gem.c
··· 420 420 GEM_BUG_ON(!drm_mm_node_allocated(&node)); 421 421 } 422 422 423 - ret = i915_gem_object_lock_interruptible(obj); 423 + ret = i915_gem_object_lock_interruptible(obj, NULL); 424 424 if (ret) 425 425 goto out_unpin; 426 426 ··· 619 619 GEM_BUG_ON(!drm_mm_node_allocated(&node)); 620 620 } 621 621 622 - ret = i915_gem_object_lock_interruptible(obj); 622 + ret = i915_gem_object_lock_interruptible(obj, NULL); 623 623 if (ret) 624 624 goto out_unpin; 625 625 ··· 1290 1290 i915_gem_drain_freed_objects(i915); 1291 1291 1292 1292 list_for_each_entry(obj, &i915->mm.shrink_list, mm.link) { 1293 - i915_gem_object_lock(obj); 1293 + i915_gem_object_lock(obj, NULL); 1294 1294 drm_WARN_ON(&i915->drm, 1295 1295 i915_gem_object_set_to_cpu_domain(obj, true)); 1296 1296 i915_gem_object_unlock(obj); ··· 1322 1322 ret = i915_gem_context_open(i915, file); 1323 1323 if (ret) 1324 1324 kfree(file_priv); 1325 + 1326 + return ret; 1327 + } 1328 + 1329 + void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr) 1330 + { 1331 + ww_acquire_init(&ww->ctx, &reservation_ww_class); 1332 + INIT_LIST_HEAD(&ww->obj_list); 1333 + ww->intr = intr; 1334 + ww->contended = NULL; 1335 + } 1336 + 1337 + static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) 1338 + { 1339 + struct drm_i915_gem_object *obj; 1340 + 1341 + while ((obj = list_first_entry_or_null(&ww->obj_list, struct drm_i915_gem_object, obj_link))) { 1342 + list_del(&obj->obj_link); 1343 + i915_gem_object_unlock(obj); 1344 + } 1345 + } 1346 + 1347 + void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww) 1348 + { 1349 + i915_gem_ww_ctx_unlock_all(ww); 1350 + WARN_ON(ww->contended); 1351 + ww_acquire_fini(&ww->ctx); 1352 + } 1353 + 1354 + int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww) 1355 + { 1356 + int ret = 0; 1357 + 1358 + if (WARN_ON(!ww->contended)) 1359 + return -EINVAL; 1360 + 1361 + i915_gem_ww_ctx_unlock_all(ww); 1362 + if (ww->intr) 1363 + ret = dma_resv_lock_slow_interruptible(ww->contended->base.resv, &ww->ctx); 1364 + else 1365 + dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx); 1366 + 1367 + if (!ret) 1368 + list_add_tail(&ww->contended->obj_link, &ww->obj_list); 1369 + 1370 + ww->contended = NULL; 1325 1371 1326 1372 return ret; 1327 1373 }
+11
drivers/gpu/drm/i915/i915_gem.h
··· 116 116 return test_bit(TASKLET_STATE_SCHED, &t->state); 117 117 } 118 118 119 + struct i915_gem_ww_ctx { 120 + struct ww_acquire_ctx ctx; 121 + struct list_head obj_list; 122 + bool intr; 123 + struct drm_i915_gem_object *contended; 124 + }; 125 + 126 + void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr); 127 + void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); 128 + int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); 129 + 119 130 #endif /* __I915_GEM_H__ */
+41
drivers/gpu/drm/i915/selftests/i915_gem.c
··· 199 199 return err; 200 200 } 201 201 202 + static int igt_gem_ww_ctx(void *arg) 203 + { 204 + struct drm_i915_private *i915 = arg; 205 + struct drm_i915_gem_object *obj, *obj2; 206 + struct i915_gem_ww_ctx ww; 207 + int err = 0; 208 + 209 + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 210 + if (IS_ERR(obj)) 211 + return PTR_ERR(obj); 212 + 213 + obj2 = i915_gem_object_create_internal(i915, PAGE_SIZE); 214 + if (IS_ERR(obj)) { 215 + err = PTR_ERR(obj); 216 + goto put1; 217 + } 218 + 219 + i915_gem_ww_ctx_init(&ww, true); 220 + retry: 221 + /* Lock the objects, twice for good measure (-EALREADY handling) */ 222 + err = i915_gem_object_lock(obj, &ww); 223 + if (!err) 224 + err = i915_gem_object_lock_interruptible(obj, &ww); 225 + if (!err) 226 + err = i915_gem_object_lock_interruptible(obj2, &ww); 227 + if (!err) 228 + err = i915_gem_object_lock(obj2, &ww); 229 + 230 + if (err == -EDEADLK) { 231 + err = i915_gem_ww_ctx_backoff(&ww); 232 + if (!err) 233 + goto retry; 234 + } 235 + i915_gem_ww_ctx_fini(&ww); 236 + i915_gem_object_put(obj2); 237 + put1: 238 + i915_gem_object_put(obj); 239 + return err; 240 + } 241 + 202 242 int i915_gem_live_selftests(struct drm_i915_private *i915) 203 243 { 204 244 static const struct i915_subtest tests[] = { 205 245 SUBTEST(igt_gem_suspend), 206 246 SUBTEST(igt_gem_hibernate), 247 + SUBTEST(igt_gem_ww_ctx), 207 248 }; 208 249 209 250 if (intel_gt_is_wedged(&i915->gt))
+1 -1
drivers/gpu/drm/i915/selftests/i915_vma.c
··· 892 892 unsigned int x, y; 893 893 int err; 894 894 895 - i915_gem_object_lock(obj); 895 + i915_gem_object_lock(obj, NULL); 896 896 err = i915_gem_object_set_to_gtt_domain(obj, true); 897 897 i915_gem_object_unlock(obj); 898 898 if (err)
+1 -1
drivers/gpu/drm/i915/selftests/intel_memory_region.c
··· 509 509 if (err) 510 510 goto out_unpin; 511 511 512 - i915_gem_object_lock(obj); 512 + i915_gem_object_lock(obj, NULL); 513 513 err = i915_gem_object_set_to_wc_domain(obj, true); 514 514 i915_gem_object_unlock(obj); 515 515 if (err)