From patchwork Fri Aug 14 17:24:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 7017401 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E899D9F39D for ; Fri, 14 Aug 2015 17:24:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id ED15520709 for ; Fri, 14 Aug 2015 17:24:46 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 84727202FF for ; Fri, 14 Aug 2015 17:24:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6D1C489CD3; Fri, 14 Aug 2015 10:24:44 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [87.106.93.118]) by gabe.freedesktop.org (Postfix) with ESMTP id 09A7289CD3 for ; Fri, 14 Aug 2015 10:24:42 -0700 (PDT) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 43675907-1500048 for multiple; Fri, 14 Aug 2015 18:24:55 +0100 Received: by haswell.alporthouse.com (sSMTP sendmail emulation); Fri, 14 Aug 2015 18:24:33 +0100 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Fri, 14 Aug 2015 18:24:32 +0100 Message-Id: <1439573072-8927-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.5.0 X-Originating-IP: 78.156.65.138 X-Country: code=GB country="United Kingdom" ip=78.156.65.138 Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH] drm/i915: Clear PIPE.STAT before IIR on VLV/CHV X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The PIPE.STAT register contains some interrupt status bits per pipe, and if assert cause the corresponding bit in the IIR to be asserted (thus raising an interrupt). When handling an interrupt, we should clear the PIPE.STAT generator first before clearing the IIR so that we do not miss events or cause spurious work. This ordering was broken by commit 27b6c122512ca30399bb1b39cc42eda83901f304 Author: Oscar Mateo Date: Mon Jun 16 16:11:00 2014 +0100 drm/i915/chv: Ack interrupts before handling them (CHV) commit 3ff60f89bc4836583f5bd195062f16c563bd97aa Author: Oscar Mateo Date: Mon Jun 16 16:10:58 2014 +0100 drm/i915/vlv: Ack interrupts before handling them (VLV) in attempting to reduce the amount of work done between receiving an interrupt and acknowledging it. In light of this motivation, split the pipestat interrupt handler into two, one to acknowledge and clear the interrupt and a later pass to process it. Signed-off-by: Chris Wilson Cc: Oscar Mateo Cc: Bob Beckett Cc: Imre Deak Cc: Daniel Vetter Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/i915_irq.c | 55 +++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 66064511cffb..92bdfe6f91d8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1457,24 +1457,21 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) } } -static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe) +static inline bool +intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe) { - if (!drm_handle_vblank(dev, pipe)) - return false; - - return true; + return drm_handle_vblank(dev, pipe); } -static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) +static void valleyview_pipestat_irq_get(struct drm_i915_private *dev_priv, + u32 iir, u32 *pipe_stats) { - struct drm_i915_private *dev_priv = dev->dev_private; - u32 pipe_stats[I915_MAX_PIPES] = { }; int pipe; spin_lock(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { + u32 mask, val, iir_bit = 0; int reg; - u32 mask, iir_bit = 0; /* * PIPESTAT bits get signalled even when the interrupt is @@ -1486,6 +1483,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) /* fifo underruns are filterered in the underrun handler. */ mask = PIPE_FIFO_UNDERRUN_STATUS; + mask |= PIPESTAT_INT_ENABLE_MASK; switch (pipe) { case PIPE_A: @@ -1501,21 +1499,25 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) if (iir & iir_bit) mask |= dev_priv->pipestat_irq_mask[pipe]; - if (!mask) - continue; - reg = PIPESTAT(pipe); - mask |= PIPESTAT_INT_ENABLE_MASK; - pipe_stats[pipe] = I915_READ(reg) & mask; + val = I915_READ(reg); + pipe_stats[pipe] |= val & mask; /* * Clear the PIPE*STAT regs before the IIR */ - if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS | - PIPESTAT_INT_STATUS_MASK)) - I915_WRITE(reg, pipe_stats[pipe]); + if (val & (PIPE_FIFO_UNDERRUN_STATUS | + PIPESTAT_INT_STATUS_MASK)) + I915_WRITE(reg, val); } spin_unlock(&dev_priv->irq_lock); +} + +static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u32 *pipe_stats) +{ + struct drm_device *dev = dev_priv->dev; + int pipe; for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && @@ -1578,6 +1580,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = dev->dev_private; + u32 pipe_stats[I915_MAX_PIPES] = {}; u32 iir, gt_iir, pm_iir; irqreturn_t ret = IRQ_NONE; @@ -1600,6 +1603,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) /* Consume port before clearing IIR or we'll miss events */ if (iir & I915_DISPLAY_PORT_INTERRUPT) i9xx_hpd_irq_handler(dev); + valleyview_pipestat_irq_get(dev_priv, iir, pipe_stats); I915_WRITE(VLV_IIR, iir); } @@ -1612,12 +1616,13 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) snb_gt_irq_handler(dev, dev_priv, gt_iir); if (pm_iir) gen6_rps_irq_handler(dev_priv, pm_iir); - /* Call regardless, as some status bits might not be - * signalled in iir */ - valleyview_pipestat_irq_handler(dev, iir); } out: + + /* Call regardless, as some status bits might not be + * signalled in iir */ + valleyview_pipestat_irq_handler(dev_priv, pipe_stats); return ret; } @@ -1625,6 +1630,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = dev->dev_private; + u32 pipe_stats[I915_MAX_PIPES] = {}; u32 master_ctl, iir; irqreturn_t ret = IRQ_NONE; @@ -1648,18 +1654,19 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) /* Consume port before clearing IIR or we'll miss events */ if (iir & I915_DISPLAY_PORT_INTERRUPT) i9xx_hpd_irq_handler(dev); + valleyview_pipestat_irq_get(dev_priv, iir, pipe_stats); I915_WRITE(VLV_IIR, iir); } gen8_gt_irq_handler(dev_priv, master_ctl); - /* Call regardless, as some status bits might not be - * signalled in iir */ - valleyview_pipestat_irq_handler(dev, iir); - I915_WRITE_FW(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL); } + /* Call regardless, as some status bits might not be + * signalled in iir */ + valleyview_pipestat_irq_handler(dev_priv, pipe_stats); + return ret; }