aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOscar Mateo <oscar.mateo@intel.com>2014-06-16 11:10:59 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-17 18:49:18 -0400
commit38cc46d73ed99dd7002f1406002e52d7975d16cc (patch)
tree239c48502a2a3bf054caddee3bb27b23d4777ec3
parent3ff60f89bc4836583f5bd195062f16c563bd97aa (diff)
drm/i915/bdw: Ack interrupts before handling them (GEN8)
Otherwise, we might receive a new interrupt before we have time to ack the first one, eventually missing it. The right order should be: 1 - Disable Master Interrupt Control. 2 - Find the category of interrupt that is pending. 3 - Find the source(s) of the interrupt and clear the Interrupt Identity bits (IIR) 4 - Process the interrupt(s) that had bits set in the IIRs. 5 - Re-enable Master Interrupt Control. Without an atomic XCHG operation with mmio space, the above merely reduces the window in which we can miss an interrupt (especially when you consider how heavyweight the I915_READ/I915_WRITE operations are). Spotted by Bob Beckett <robert.beckett@intel.com>. v2: Add warning to commit message and comments to the code as per Chris Wilson's request. v3: Improve the source code comment. Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c91
1 files changed, 45 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c434a6848c0f..b6debdc869c8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1465,6 +1465,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1465 if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { 1465 if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
1466 tmp = I915_READ(GEN8_GT_IIR(0)); 1466 tmp = I915_READ(GEN8_GT_IIR(0));
1467 if (tmp) { 1467 if (tmp) {
1468 I915_WRITE(GEN8_GT_IIR(0), tmp);
1468 ret = IRQ_HANDLED; 1469 ret = IRQ_HANDLED;
1469 rcs = tmp >> GEN8_RCS_IRQ_SHIFT; 1470 rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
1470 bcs = tmp >> GEN8_BCS_IRQ_SHIFT; 1471 bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
@@ -1472,7 +1473,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1472 notify_ring(dev, &dev_priv->ring[RCS]); 1473 notify_ring(dev, &dev_priv->ring[RCS]);
1473 if (bcs & GT_RENDER_USER_INTERRUPT) 1474 if (bcs & GT_RENDER_USER_INTERRUPT)
1474 notify_ring(dev, &dev_priv->ring[BCS]); 1475 notify_ring(dev, &dev_priv->ring[BCS]);
1475 I915_WRITE(GEN8_GT_IIR(0), tmp);
1476 } else 1476 } else
1477 DRM_ERROR("The master control interrupt lied (GT0)!\n"); 1477 DRM_ERROR("The master control interrupt lied (GT0)!\n");
1478 } 1478 }
@@ -1480,6 +1480,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1480 if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { 1480 if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
1481 tmp = I915_READ(GEN8_GT_IIR(1)); 1481 tmp = I915_READ(GEN8_GT_IIR(1));
1482 if (tmp) { 1482 if (tmp) {
1483 I915_WRITE(GEN8_GT_IIR(1), tmp);
1483 ret = IRQ_HANDLED; 1484 ret = IRQ_HANDLED;
1484 vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; 1485 vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
1485 if (vcs & GT_RENDER_USER_INTERRUPT) 1486 if (vcs & GT_RENDER_USER_INTERRUPT)
@@ -1487,7 +1488,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1487 vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; 1488 vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
1488 if (vcs & GT_RENDER_USER_INTERRUPT) 1489 if (vcs & GT_RENDER_USER_INTERRUPT)
1489 notify_ring(dev, &dev_priv->ring[VCS2]); 1490 notify_ring(dev, &dev_priv->ring[VCS2]);
1490 I915_WRITE(GEN8_GT_IIR(1), tmp);
1491 } else 1491 } else
1492 DRM_ERROR("The master control interrupt lied (GT1)!\n"); 1492 DRM_ERROR("The master control interrupt lied (GT1)!\n");
1493 } 1493 }
@@ -1495,10 +1495,10 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1495 if (master_ctl & GEN8_GT_PM_IRQ) { 1495 if (master_ctl & GEN8_GT_PM_IRQ) {
1496 tmp = I915_READ(GEN8_GT_IIR(2)); 1496 tmp = I915_READ(GEN8_GT_IIR(2));
1497 if (tmp & dev_priv->pm_rps_events) { 1497 if (tmp & dev_priv->pm_rps_events) {
1498 ret = IRQ_HANDLED;
1499 gen8_rps_irq_handler(dev_priv, tmp);
1500 I915_WRITE(GEN8_GT_IIR(2), 1498 I915_WRITE(GEN8_GT_IIR(2),
1501 tmp & dev_priv->pm_rps_events); 1499 tmp & dev_priv->pm_rps_events);
1500 ret = IRQ_HANDLED;
1501 gen8_rps_irq_handler(dev_priv, tmp);
1502 } else 1502 } else
1503 DRM_ERROR("The master control interrupt lied (PM)!\n"); 1503 DRM_ERROR("The master control interrupt lied (PM)!\n");
1504 } 1504 }
@@ -1506,11 +1506,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
1506 if (master_ctl & GEN8_GT_VECS_IRQ) { 1506 if (master_ctl & GEN8_GT_VECS_IRQ) {
1507 tmp = I915_READ(GEN8_GT_IIR(3)); 1507 tmp = I915_READ(GEN8_GT_IIR(3));
1508 if (tmp) { 1508 if (tmp) {
1509 I915_WRITE(GEN8_GT_IIR(3), tmp);
1509 ret = IRQ_HANDLED; 1510 ret = IRQ_HANDLED;
1510 vcs = tmp >> GEN8_VECS_IRQ_SHIFT; 1511 vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
1511 if (vcs & GT_RENDER_USER_INTERRUPT) 1512 if (vcs & GT_RENDER_USER_INTERRUPT)
1512 notify_ring(dev, &dev_priv->ring[VECS]); 1513 notify_ring(dev, &dev_priv->ring[VECS]);
1513 I915_WRITE(GEN8_GT_IIR(3), tmp);
1514 } else 1514 } else
1515 DRM_ERROR("The master control interrupt lied (GT3)!\n"); 1515 DRM_ERROR("The master control interrupt lied (GT3)!\n");
1516 } 1516 }
@@ -2241,36 +2241,36 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
2241 I915_WRITE(GEN8_MASTER_IRQ, 0); 2241 I915_WRITE(GEN8_MASTER_IRQ, 0);
2242 POSTING_READ(GEN8_MASTER_IRQ); 2242 POSTING_READ(GEN8_MASTER_IRQ);
2243 2243
2244 /* Find, clear, then process each source of interrupt */
2245
2244 ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl); 2246 ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl);
2245 2247
2246 if (master_ctl & GEN8_DE_MISC_IRQ) { 2248 if (master_ctl & GEN8_DE_MISC_IRQ) {
2247 tmp = I915_READ(GEN8_DE_MISC_IIR); 2249 tmp = I915_READ(GEN8_DE_MISC_IIR);
2248 if (tmp & GEN8_DE_MISC_GSE)
2249 intel_opregion_asle_intr(dev);
2250 else if (tmp)
2251 DRM_ERROR("Unexpected DE Misc interrupt\n");
2252 else
2253 DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
2254
2255 if (tmp) { 2250 if (tmp) {
2256 I915_WRITE(GEN8_DE_MISC_IIR, tmp); 2251 I915_WRITE(GEN8_DE_MISC_IIR, tmp);
2257 ret = IRQ_HANDLED; 2252 ret = IRQ_HANDLED;
2253 if (tmp & GEN8_DE_MISC_GSE)
2254 intel_opregion_asle_intr(dev);
2255 else
2256 DRM_ERROR("Unexpected DE Misc interrupt\n");
2258 } 2257 }
2258 else
2259 DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
2259 } 2260 }
2260 2261
2261 if (master_ctl & GEN8_DE_PORT_IRQ) { 2262 if (master_ctl & GEN8_DE_PORT_IRQ) {
2262 tmp = I915_READ(GEN8_DE_PORT_IIR); 2263 tmp = I915_READ(GEN8_DE_PORT_IIR);
2263 if (tmp & GEN8_AUX_CHANNEL_A)
2264 dp_aux_irq_handler(dev);
2265 else if (tmp)
2266 DRM_ERROR("Unexpected DE Port interrupt\n");
2267 else
2268 DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
2269
2270 if (tmp) { 2264 if (tmp) {
2271 I915_WRITE(GEN8_DE_PORT_IIR, tmp); 2265 I915_WRITE(GEN8_DE_PORT_IIR, tmp);
2272 ret = IRQ_HANDLED; 2266 ret = IRQ_HANDLED;
2267 if (tmp & GEN8_AUX_CHANNEL_A)
2268 dp_aux_irq_handler(dev);
2269 else
2270 DRM_ERROR("Unexpected DE Port interrupt\n");
2273 } 2271 }
2272 else
2273 DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
2274 } 2274 }
2275 2275
2276 for_each_pipe(pipe) { 2276 for_each_pipe(pipe) {
@@ -2280,33 +2280,32 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
2280 continue; 2280 continue;
2281 2281
2282 pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); 2282 pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
2283 if (pipe_iir & GEN8_PIPE_VBLANK) 2283 if (pipe_iir) {
2284 intel_pipe_handle_vblank(dev, pipe); 2284 ret = IRQ_HANDLED;
2285 2285 I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
2286 if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) { 2286 if (pipe_iir & GEN8_PIPE_VBLANK)
2287 intel_prepare_page_flip(dev, pipe); 2287 intel_pipe_handle_vblank(dev, pipe);
2288 intel_finish_page_flip_plane(dev, pipe);
2289 }
2290 2288
2291 if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE) 2289 if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
2292 hsw_pipe_crc_irq_handler(dev, pipe); 2290 intel_prepare_page_flip(dev, pipe);
2291 intel_finish_page_flip_plane(dev, pipe);
2292 }
2293 2293
2294 if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) { 2294 if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
2295 if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, 2295 hsw_pipe_crc_irq_handler(dev, pipe);
2296 false))
2297 DRM_ERROR("Pipe %c FIFO underrun\n",
2298 pipe_name(pipe));
2299 }
2300 2296
2301 if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) { 2297 if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
2302 DRM_ERROR("Fault errors on pipe %c\n: 0x%08x", 2298 if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
2303 pipe_name(pipe), 2299 false))
2304 pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS); 2300 DRM_ERROR("Pipe %c FIFO underrun\n",
2305 } 2301 pipe_name(pipe));
2302 }
2306 2303
2307 if (pipe_iir) { 2304 if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
2308 ret = IRQ_HANDLED; 2305 DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
2309 I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir); 2306 pipe_name(pipe),
2307 pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
2308 }
2310 } else 2309 } else
2311 DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); 2310 DRM_ERROR("The master control interrupt lied (DE PIPE)!\n");
2312 } 2311 }
@@ -2318,13 +2317,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
2318 * on older pch-split platforms. But this needs testing. 2317 * on older pch-split platforms. But this needs testing.
2319 */ 2318 */
2320 u32 pch_iir = I915_READ(SDEIIR); 2319 u32 pch_iir = I915_READ(SDEIIR);
2321
2322 cpt_irq_handler(dev, pch_iir);
2323
2324 if (pch_iir) { 2320 if (pch_iir) {
2325 I915_WRITE(SDEIIR, pch_iir); 2321 I915_WRITE(SDEIIR, pch_iir);
2326 ret = IRQ_HANDLED; 2322 ret = IRQ_HANDLED;
2327 } 2323 cpt_irq_handler(dev, pch_iir);
2324 } else
2325 DRM_ERROR("The master control interrupt lied (SDE)!\n");
2326
2328 } 2327 }
2329 2328
2330 I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 2329 I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);