From patchwork Mon Apr 15 15:49:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 10901069 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0B1201669 for ; Mon, 15 Apr 2019 15:49:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3D6F28867 for ; Mon, 15 Apr 2019 15:49:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D85B7288D9; Mon, 15 Apr 2019 15:49:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3B0F028867 for ; Mon, 15 Apr 2019 15:49:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B987F89856; Mon, 15 Apr 2019 15:49:17 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 52F2B89856 for ; Mon, 15 Apr 2019 15:49:17 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Apr 2019 08:49:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,354,1549958400"; d="scan'208";a="134516739" Received: from stinkbox.fi.intel.com (HELO stinkbox) ([10.237.72.174]) by orsmga008.jf.intel.com with SMTP; 15 Apr 2019 08:49:14 -0700 Received: by stinkbox (sSMTP sendmail emulation); Mon, 15 Apr 2019 18:49:13 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Date: Mon, 15 Apr 2019 18:49:03 +0300 Message-Id: <20190415154904.31055-4-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415154904.31055-1-ville.syrjala@linux.intel.com> References: <20190415154904.31055-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 3/4] drm/i915: Split pch irq handling to ack+handler X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Ville Syrjälä The proper way to process interrupts is to first acknowledge them all, and later process them. Start down that path for pch interrupts by collecting the relevant register values into a struct so that we can carry them from the ack part to the handler part. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_irq.c | 198 +++++++++++++++++++++----------- 1 file changed, 131 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b6f7b98b9ddb..14e0e9fe1853 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2276,6 +2276,19 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) return ret; } +struct pch_irq_regs { + u32 iir; + u32 serr_int; /* cpt/lpt */ + union { + struct hpd_irq_regs hpd; /* ibx+ */ + struct hpd_irq_regs ddi; /* icp+ */ + }; + union { + struct hpd_irq_regs hpd2; /* spt+ */ + struct hpd_irq_regs tc; /* icp+ */ + }; +}; + static void ibx_hpd_irq_ack(struct drm_i915_private *dev_priv, struct hpd_irq_regs *hpd) { @@ -2312,15 +2325,21 @@ static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); } -static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) +static void ibx_irq_ack(struct drm_i915_private *dev_priv, + struct pch_irq_regs *pch) { - struct hpd_irq_regs hpd = {}; - int pipe; + pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK; - hpd.hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; + ibx_hpd_irq_ack(dev_priv, &pch->hpd); +} - ibx_hpd_irq_ack(dev_priv, &hpd); - ibx_hpd_irq_handler(dev_priv, &hpd, hpd_ibx); +static void ibx_irq_handler(struct drm_i915_private *dev_priv, + const struct pch_irq_regs *pch) +{ + u32 pch_iir = pch->iir; + enum pipe pipe; + + ibx_hpd_irq_handler(dev_priv, &pch->hpd, hpd_ibx); if (pch_iir & SDE_AUDIO_POWER_MASK) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> @@ -2386,9 +2405,17 @@ static void ivb_err_int_handler(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_ERR_INT, err_int); } -static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) +static void cpt_serr_int_ack(struct drm_i915_private *dev_priv, + struct pch_irq_regs *pch) { - u32 serr_int = I915_READ(SERR_INT); + pch->serr_int = I915_READ(SERR_INT); + I915_WRITE(SERR_INT, pch->serr_int); +} + +static void cpt_serr_int_handler(struct drm_i915_private *dev_priv, + const struct pch_irq_regs *pch) +{ + u32 serr_int = pch->serr_int; enum pipe pipe; if (serr_int & SERR_INT_POISON) @@ -2397,19 +2424,26 @@ static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) for_each_pipe(dev_priv, pipe) if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); - - I915_WRITE(SERR_INT, serr_int); } -static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) +static void cpt_irq_ack(struct drm_i915_private *dev_priv, + struct pch_irq_regs *pch) { - struct hpd_irq_regs hpd = {}; - int pipe; + pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK_CPT; + + ibx_hpd_irq_ack(dev_priv, &pch->hpd); - hpd.hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; + if (pch->iir & SDE_ERROR_CPT) + cpt_serr_int_ack(dev_priv, pch); +} + +static void cpt_irq_handler(struct drm_i915_private *dev_priv, + const struct pch_irq_regs *pch) +{ + u32 pch_iir = pch->iir; + enum pipe pipe; - ibx_hpd_irq_ack(dev_priv, &hpd); - ibx_hpd_irq_handler(dev_priv, &hpd, hpd_cpt); + ibx_hpd_irq_handler(dev_priv, &pch->hpd, hpd_cpt); if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> @@ -2437,33 +2471,41 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) I915_READ(FDI_RX_IIR(pipe))); if (pch_iir & SDE_ERROR_CPT) - cpt_serr_int_handler(dev_priv); + cpt_serr_int_handler(dev_priv, pch); } -static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) +static void icp_irq_ack(struct drm_i915_private *dev_priv, + struct pch_irq_regs *pch) { - struct hpd_irq_regs ddi = {}; - struct hpd_irq_regs tc = {}; + pch->ddi.hotplug_trigger = pch->iir & SDE_DDI_MASK_ICP; + pch->tc.hotplug_trigger = pch->iir & SDE_TC_MASK_ICP; + + if (pch->ddi.hotplug_trigger) { + pch->ddi.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); + I915_WRITE(SHOTPLUG_CTL_DDI, pch->ddi.dig_hotplug_reg); + } + + if (pch->tc.hotplug_trigger) { + pch->tc.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); + I915_WRITE(SHOTPLUG_CTL_TC, pch->tc.dig_hotplug_reg); + } +} + +static void icp_irq_handler(struct drm_i915_private *dev_priv, + const struct pch_irq_regs *pch) +{ + u32 pch_iir = pch->iir; u32 pin_mask = 0, long_mask = 0; - ddi.hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; - tc.hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; - - if (ddi.hotplug_trigger) { - ddi.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); - I915_WRITE(SHOTPLUG_CTL_DDI, ddi.dig_hotplug_reg); - + if (pch->ddi.hotplug_trigger) { intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, - &ddi, hpd_icp, + &pch->ddi, hpd_icp, icp_ddi_port_hotplug_long_detect); } - if (tc.hotplug_trigger) { - tc.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); - I915_WRITE(SHOTPLUG_CTL_TC, tc.dig_hotplug_reg); - + if (pch->tc.hotplug_trigger) { intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, - &tc, hpd_icp, + &pch->tc, hpd_icp, icp_tc_port_hotplug_long_detect); } @@ -2474,31 +2516,39 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) gmbus_irq_handler(dev_priv); } -static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) +static void spt_irq_ack(struct drm_i915_private *dev_priv, + struct pch_irq_regs *pch) { - u32 pin_mask = 0, long_mask = 0; - struct hpd_irq_regs hpd = {}; - struct hpd_irq_regs hpd2 = {}; - - hpd.hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & + pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK_SPT & ~SDE_PORTE_HOTPLUG_SPT; - hpd2.hotplug_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; + pch->hpd2.hotplug_trigger = pch->iir & SDE_PORTE_HOTPLUG_SPT; - if (hpd.hotplug_trigger) { - hpd.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); - I915_WRITE(PCH_PORT_HOTPLUG, hpd.dig_hotplug_reg); + if (pch->hpd.hotplug_trigger) { + pch->hpd.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + I915_WRITE(PCH_PORT_HOTPLUG, pch->hpd.dig_hotplug_reg); + } + if (pch->hpd2.hotplug_trigger) { + pch->hpd2.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); + I915_WRITE(PCH_PORT_HOTPLUG2, pch->hpd2.dig_hotplug_reg); + } +} + +static void spt_irq_handler(struct drm_i915_private *dev_priv, + const struct pch_irq_regs *pch) +{ + u32 pch_iir = pch->iir; + u32 pin_mask = 0, long_mask = 0; + + if (pch->hpd.hotplug_trigger) { intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, - &hpd, hpd_spt, + &pch->hpd, hpd_spt, spt_port_hotplug_long_detect); } - if (hpd2.hotplug_trigger) { - hpd2.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); - I915_WRITE(PCH_PORT_HOTPLUG2, hpd2.dig_hotplug_reg); - + if (pch->hpd2.hotplug_trigger) { intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, - &hpd2, hpd_spt, + &pch->hpd2, hpd_spt, spt_port_hotplug2_long_detect); } @@ -2563,15 +2613,20 @@ static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { - u32 pch_iir = I915_READ(SDEIIR); + struct pch_irq_regs pch = {}; - if (HAS_PCH_CPT(dev_priv)) - cpt_irq_handler(dev_priv, pch_iir); - else - ibx_irq_handler(dev_priv, pch_iir); + pch.iir = I915_READ(SDEIIR); + + if (HAS_PCH_CPT(dev_priv)) { + cpt_irq_ack(dev_priv, &pch); + cpt_irq_handler(dev_priv, &pch); + } else { + ibx_irq_ack(dev_priv, &pch); + ibx_irq_handler(dev_priv, &pch); + } /* should clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch_iir); + I915_WRITE(SDEIIR, pch.iir); } if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT) @@ -2613,12 +2668,15 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, /* check event from PCH */ if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { - u32 pch_iir = I915_READ(SDEIIR); + struct pch_irq_regs pch = {}; - cpt_irq_handler(dev_priv, pch_iir); + pch.iir = I915_READ(SDEIIR); + + cpt_irq_ack(dev_priv, &pch); + cpt_irq_handler(dev_priv, &pch); /* clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch_iir); + I915_WRITE(SDEIIR, pch.iir); } } @@ -2902,22 +2960,28 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && master_ctl & GEN8_DE_PCH_IRQ) { + struct pch_irq_regs pch = {}; + /* * FIXME(BDW): Assume for now that the new interrupt handling * scheme also closed the SDE interrupt handling race we've seen * on older pch-split platforms. But this needs testing. */ - iir = I915_READ(SDEIIR); - if (iir) { - I915_WRITE(SDEIIR, iir); + pch.iir = I915_READ(SDEIIR); + if (pch.iir) { + I915_WRITE(SDEIIR, pch.iir); ret = IRQ_HANDLED; - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_irq_handler(dev_priv, iir); - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) - spt_irq_handler(dev_priv, iir); - else - cpt_irq_handler(dev_priv, iir); + if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) { + icp_irq_ack(dev_priv, &pch); + icp_irq_handler(dev_priv, &pch); + } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) { + spt_irq_ack(dev_priv, &pch); + spt_irq_handler(dev_priv, &pch); + } else { + cpt_irq_ack(dev_priv, &pch); + cpt_irq_handler(dev_priv, &pch); + } } else { /* * Like on previous PCH there seems to be something