1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2018 Intel Corporation 5 */ 6 7 #include <linux/kref.h> 8 9 #include "gem/i915_gem_pm.h" 10 #include "gt/intel_gt.h" 11 12 #include "i915_selftest.h" 13 14 #include "igt_flush_test.h" 15 #include "lib_sw_fence.h" 16 17 struct live_active { 18 struct i915_active base; 19 struct kref ref; 20 bool retired; 21 }; 22 23 static void __live_get(struct live_active *active) 24 { 25 kref_get(&active->ref); 26 } 27 28 static void __live_free(struct live_active *active) 29 { 30 i915_active_fini(&active->base); 31 kfree(active); 32 } 33 34 static void __live_release(struct kref *ref) 35 { 36 struct live_active *active = container_of(ref, typeof(*active), ref); 37 38 __live_free(active); 39 } 40 41 static void __live_put(struct live_active *active) 42 { 43 kref_put(&active->ref, __live_release); 44 } 45 46 static int __live_active(struct i915_active *base) 47 { 48 struct live_active *active = container_of(base, typeof(*active), base); 49 50 __live_get(active); 51 return 0; 52 } 53 54 static void __live_retire(struct i915_active *base) 55 { 56 struct live_active *active = container_of(base, typeof(*active), base); 57 58 active->retired = true; 59 __live_put(active); 60 } 61 62 static struct live_active *__live_alloc(struct drm_i915_private *i915) 63 { 64 struct live_active *active; 65 66 active = kzalloc(sizeof(*active), GFP_KERNEL); 67 if (!active) 68 return NULL; 69 70 kref_init(&active->ref); 71 i915_active_init(&active->base, __live_active, __live_retire); 72 73 return active; 74 } 75 76 static struct live_active * 77 __live_active_setup(struct drm_i915_private *i915) 78 { 79 struct intel_engine_cs *engine; 80 struct i915_sw_fence *submit; 81 struct live_active *active; 82 unsigned int count = 0; 83 int err = 0; 84 85 active = __live_alloc(i915); 86 if (!active) 87 return ERR_PTR(-ENOMEM); 88 89 submit = heap_fence_create(GFP_KERNEL); 90 if (!submit) { 91 kfree(active); 92 return ERR_PTR(-ENOMEM); 93 } 94 95 err = i915_active_acquire(&active->base); 96 if (err) 97 goto out; 98 99 for_each_uabi_engine(engine, i915) { 100 struct i915_request *rq; 101 102 rq = i915_request_create(engine->kernel_context); 103 if (IS_ERR(rq)) { 104 err = PTR_ERR(rq); 105 break; 106 } 107 108 err = i915_sw_fence_await_sw_fence_gfp(&rq->submit, 109 submit, 110 GFP_KERNEL); 111 if (err >= 0) 112 err = i915_active_add_request(&active->base, rq); 113 i915_request_add(rq); 114 if (err) { 115 pr_err("Failed to track active ref!\n"); 116 break; 117 } 118 119 count++; 120 } 121 122 i915_active_release(&active->base); 123 if (READ_ONCE(active->retired) && count) { 124 pr_err("i915_active retired before submission!\n"); 125 err = -EINVAL; 126 } 127 if (atomic_read(&active->base.count) != count) { 128 pr_err("i915_active not tracking all requests, found %d, expected %d\n", 129 atomic_read(&active->base.count), count); 130 err = -EINVAL; 131 } 132 133 out: 134 i915_sw_fence_commit(submit); 135 heap_fence_put(submit); 136 if (err) { 137 __live_put(active); 138 active = ERR_PTR(err); 139 } 140 141 return active; 142 } 143 144 static int live_active_wait(void *arg) 145 { 146 struct drm_i915_private *i915 = arg; 147 struct live_active *active; 148 int err = 0; 149 150 /* Check that we get a callback when requests retire upon waiting */ 151 152 active = __live_active_setup(i915); 153 if (IS_ERR(active)) 154 return PTR_ERR(active); 155 156 i915_active_wait(&active->base); 157 if (!READ_ONCE(active->retired)) { 158 pr_err("i915_active not retired after waiting!\n"); 159 err = -EINVAL; 160 } 161 162 __live_put(active); 163 164 if (igt_flush_test(i915)) 165 err = -EIO; 166 167 return err; 168 } 169 170 static int live_active_retire(void *arg) 171 { 172 struct drm_i915_private *i915 = arg; 173 struct live_active *active; 174 int err = 0; 175 176 /* Check that we get a callback when requests are indirectly retired */ 177 178 active = __live_active_setup(i915); 179 if (IS_ERR(active)) 180 return PTR_ERR(active); 181 182 /* waits for & retires all requests */ 183 if (igt_flush_test(i915)) 184 err = -EIO; 185 186 if (!READ_ONCE(active->retired)) { 187 pr_err("i915_active not retired after flushing!\n"); 188 err = -EINVAL; 189 } 190 191 __live_put(active); 192 193 return err; 194 } 195 196 int i915_active_live_selftests(struct drm_i915_private *i915) 197 { 198 static const struct i915_subtest tests[] = { 199 SUBTEST(live_active_wait), 200 SUBTEST(live_active_retire), 201 }; 202 203 if (intel_gt_is_wedged(&i915->gt)) 204 return 0; 205 206 return i915_subtests(tests, i915); 207 } 208 209 static struct intel_engine_cs *node_to_barrier(struct active_node *it) 210 { 211 struct intel_engine_cs *engine; 212 213 if (!is_barrier(&it->base)) 214 return NULL; 215 216 engine = __barrier_to_engine(it); 217 smp_rmb(); /* serialise with add_active_barriers */ 218 if (!is_barrier(&it->base)) 219 return NULL; 220 221 return engine; 222 } 223 224 void i915_active_print(struct i915_active *ref, struct drm_printer *m) 225 { 226 drm_printf(m, "active %pS:%pS\n", ref->active, ref->retire); 227 drm_printf(m, "\tcount: %d\n", atomic_read(&ref->count)); 228 drm_printf(m, "\tpreallocated barriers? %s\n", 229 yesno(!llist_empty(&ref->preallocated_barriers))); 230 231 if (i915_active_acquire_if_busy(ref)) { 232 struct active_node *it, *n; 233 234 rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) { 235 struct intel_engine_cs *engine; 236 237 engine = node_to_barrier(it); 238 if (engine) { 239 drm_printf(m, "\tbarrier: %s\n", engine->name); 240 continue; 241 } 242 243 if (i915_active_fence_isset(&it->base)) { 244 drm_printf(m, 245 "\ttimeline: %llx\n", it->timeline); 246 continue; 247 } 248 } 249 250 i915_active_release(ref); 251 } 252 } 253