aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_breadcrumbs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_breadcrumbs.c')
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 5f8b9f1f40f1..5ae2d276f7f3 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -123,7 +123,7 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t)
123 */ 123 */
124 124
125 spin_lock_irq(&b->irq_lock); 125 spin_lock_irq(&b->irq_lock);
126 if (!__intel_breadcrumbs_wakeup(b)) 126 if (b->irq_armed && !__intel_breadcrumbs_wakeup(b))
127 __intel_engine_disarm_breadcrumbs(engine); 127 __intel_engine_disarm_breadcrumbs(engine);
128 spin_unlock_irq(&b->irq_lock); 128 spin_unlock_irq(&b->irq_lock);
129 if (!b->irq_armed) 129 if (!b->irq_armed)
@@ -145,6 +145,14 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t)
145 145
146static void irq_enable(struct intel_engine_cs *engine) 146static void irq_enable(struct intel_engine_cs *engine)
147{ 147{
148 /*
149 * FIXME: Ideally we want this on the API boundary, but for the
150 * sake of testing with mock breadcrumbs (no HW so unable to
151 * enable irqs) we place it deep within the bowels, at the point
152 * of no return.
153 */
154 GEM_BUG_ON(!intel_irqs_enabled(engine->i915));
155
148 /* Enabling the IRQ may miss the generation of the interrupt, but 156 /* Enabling the IRQ may miss the generation of the interrupt, but
149 * we still need to force the barrier before reading the seqno, 157 * we still need to force the barrier before reading the seqno,
150 * just in case. 158 * just in case.
@@ -171,15 +179,37 @@ void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
171 179
172 lockdep_assert_held(&b->irq_lock); 180 lockdep_assert_held(&b->irq_lock);
173 GEM_BUG_ON(b->irq_wait); 181 GEM_BUG_ON(b->irq_wait);
182 GEM_BUG_ON(!b->irq_armed);
174 183
175 if (b->irq_enabled) { 184 GEM_BUG_ON(!b->irq_enabled);
185 if (!--b->irq_enabled)
176 irq_disable(engine); 186 irq_disable(engine);
177 b->irq_enabled = false;
178 }
179 187
180 b->irq_armed = false; 188 b->irq_armed = false;
181} 189}
182 190
191void intel_engine_pin_breadcrumbs_irq(struct intel_engine_cs *engine)
192{
193 struct intel_breadcrumbs *b = &engine->breadcrumbs;
194
195 spin_lock_irq(&b->irq_lock);
196 if (!b->irq_enabled++)
197 irq_enable(engine);
198 GEM_BUG_ON(!b->irq_enabled); /* no overflow! */
199 spin_unlock_irq(&b->irq_lock);
200}
201
202void intel_engine_unpin_breadcrumbs_irq(struct intel_engine_cs *engine)
203{
204 struct intel_breadcrumbs *b = &engine->breadcrumbs;
205
206 spin_lock_irq(&b->irq_lock);
207 GEM_BUG_ON(!b->irq_enabled); /* no underflow! */
208 if (!--b->irq_enabled)
209 irq_disable(engine);
210 spin_unlock_irq(&b->irq_lock);
211}
212
183void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) 213void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
184{ 214{
185 struct intel_breadcrumbs *b = &engine->breadcrumbs; 215 struct intel_breadcrumbs *b = &engine->breadcrumbs;
@@ -197,7 +227,8 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
197 227
198 spin_lock(&b->irq_lock); 228 spin_lock(&b->irq_lock);
199 first = fetch_and_zero(&b->irq_wait); 229 first = fetch_and_zero(&b->irq_wait);
200 __intel_engine_disarm_breadcrumbs(engine); 230 if (b->irq_armed)
231 __intel_engine_disarm_breadcrumbs(engine);
201 spin_unlock(&b->irq_lock); 232 spin_unlock(&b->irq_lock);
202 233
203 rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) { 234 rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) {
@@ -241,6 +272,7 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
241 struct intel_engine_cs *engine = 272 struct intel_engine_cs *engine =
242 container_of(b, struct intel_engine_cs, breadcrumbs); 273 container_of(b, struct intel_engine_cs, breadcrumbs);
243 struct drm_i915_private *i915 = engine->i915; 274 struct drm_i915_private *i915 = engine->i915;
275 bool enabled;
244 276
245 lockdep_assert_held(&b->irq_lock); 277 lockdep_assert_held(&b->irq_lock);
246 if (b->irq_armed) 278 if (b->irq_armed)
@@ -252,7 +284,6 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
252 * the irq. 284 * the irq.
253 */ 285 */
254 b->irq_armed = true; 286 b->irq_armed = true;
255 GEM_BUG_ON(b->irq_enabled);
256 287
257 if (I915_SELFTEST_ONLY(b->mock)) { 288 if (I915_SELFTEST_ONLY(b->mock)) {
258 /* For our mock objects we want to avoid interaction 289 /* For our mock objects we want to avoid interaction
@@ -273,14 +304,15 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
273 */ 304 */
274 305
275 /* No interrupts? Kick the waiter every jiffie! */ 306 /* No interrupts? Kick the waiter every jiffie! */
276 if (intel_irqs_enabled(i915)) { 307 enabled = false;
277 if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings)) 308 if (!b->irq_enabled++ &&
278 irq_enable(engine); 309 !test_bit(engine->id, &i915->gpu_error.test_irq_rings)) {
279 b->irq_enabled = true; 310 irq_enable(engine);
311 enabled = true;
280 } 312 }
281 313
282 enable_fake_irq(b); 314 enable_fake_irq(b);
283 return true; 315 return enabled;
284} 316}
285 317
286static inline struct intel_wait *to_wait(struct rb_node *node) 318static inline struct intel_wait *to_wait(struct rb_node *node)