diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_breadcrumbs.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_breadcrumbs.c | 54 |
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 | ||
| 146 | static void irq_enable(struct intel_engine_cs *engine) | 146 | static 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 | ||
| 191 | void 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 | |||
| 202 | void 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 | |||
| 183 | void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) | 213 | void 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 | ||
| 286 | static inline struct intel_wait *to_wait(struct rb_node *node) | 318 | static inline struct intel_wait *to_wait(struct rb_node *node) |
