From patchwork Thu Jan 3 19:06:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10747737 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 6CAB714E5 for ; Thu, 3 Jan 2019 19:06:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C0ED28A30 for ; Thu, 3 Jan 2019 19:06:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4C5E328D1D; Thu, 3 Jan 2019 19:06:07 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A416E28A30 for ; Thu, 3 Jan 2019 19:06:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726817AbfACTGG (ORCPT ); Thu, 3 Jan 2019 14:06:06 -0500 Received: from mail-pf1-f195.google.com ([209.85.210.195]:46308 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726564AbfACTGF (ORCPT ); Thu, 3 Jan 2019 14:06:05 -0500 Received: by mail-pf1-f195.google.com with SMTP id c73so17078857pfe.13 for ; Thu, 03 Jan 2019 11:06:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ewomomMsXpO5qGfU4Cug+z/PUAqOj7a9mC8x323VzVI=; b=FHTkfCTS5eSl7qGDWDaZMA9cBl/BCz+Yccc3LARiyr/uKROkxhn5GCIaLsjgSczfUk cToOUdbIDFzaH7aMr1HZOBAAeFYPMmN59pbFdTEss/CTQ6zCMEKVnZbeUJseNxpY4jQl 4KWtjXXlyVvppCyuBb5GLTcNiabJGTPsbDNIY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ewomomMsXpO5qGfU4Cug+z/PUAqOj7a9mC8x323VzVI=; b=oB8bYCvG3Sv7GbJhjwQwEJl2brXEMjSU1IUvugPizd90MSV1KRwPzbS0izjHPcJkrj a2DHHvQBdUFX4qNJq1AVHCIYfRQE+ipn00GvoOaUKJtqlrA/j92lj7iaz7V0KYeZd4xP 62enIv5AWKxOKKTdPJ+t+s4ld17J7ldax11zvG+waecPDiapG32a12oq8Yx3OAuHJ31T aTo52y+m4d9DaB58x+dN8MX7P6W0BzfxET5ztJNJ7v8LVM0Yh43pj8788LC9WeueBGiK w3+iW5zDs/fmrskwTVRzynTwBKlPGB9NhzfIuZrOg2aRMiRHeSiWBPUB11IicgGglRK1 IFNg== X-Gm-Message-State: AJcUukcnTbC2MEAhy/JhSe6brNf5tct5R7QxqNi2Kb0CY1ij2a+/H2UT dDAkaFSWcbYlUcgogN10x8093w== X-Google-Smtp-Source: ALg8bN6M/Cz7Y9fVHD++AD118PWidXjlIaJaqP1W8lbxvQougbc1V1cIVzAN+kV+bKRmztCMh21EqQ== X-Received: by 2002:a63:9d05:: with SMTP id i5mr16702212pgd.98.1546542363794; Thu, 03 Jan 2019 11:06:03 -0800 (PST) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id z127sm87830202pfb.80.2019.01.03.11.06.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 03 Jan 2019 11:06:03 -0800 (PST) From: Stephen Boyd To: Rob Clark Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Sean Paul , Jordan Crouse , Jayant Shekhar , Rajesh Yadav , Jeykumar Sankaran Subject: [PATCH] drm/msm/dpu: Convert to a chained irq chip Date: Thu, 3 Jan 2019 11:06:02 -0800 Message-Id: <20190103190602.92612-1-swboyd@chromium.org> X-Mailer: git-send-email 2.20.1.415.g653613c723-goog MIME-Version: 1.0 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Devices that make up DPU, i.e. graphics card, request their interrupts from this "virtual" interrupt chip. The interrupt chip builds upon a GIC SPI interrupt that raises high when any of the interrupts in the DPU's irq status register are triggered. From the kernel's perspective this is a chained irq chip, so requesting a flow handler for the GIC SPI and then calling generic IRQ handling code from that irq handler is not completely proper. It's better to convert this to a chained irq so that the GIC SPI irq doesn't appear in /proc/interrupts, can't have CPU affinity changed, and won't be accounted for with irq stats. Doing this also silences a recursive lockdep warning because we can specify a different lock class for the chained interrupts, silencing a warning that is easy to see with 'threadirqs' on the kernel commandline. WARNING: inconsistent lock state 4.19.10 #76 Tainted: G W -------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. irq/40-dpu_mdss/203 [HC0[0]:SC0[2]:HE1:SE0] takes: 0000000053ea9021 (&irq_desc_lock_class){?.-.}, at: handle_level_irq+0x34/0x26c {IN-HARDIRQ-W} state was registered at: lock_acquire+0x244/0x360 _raw_spin_lock+0x64/0xa0 handle_fasteoi_irq+0x54/0x2ec generic_handle_irq+0x44/0x5c __handle_domain_irq+0x9c/0x11c gic_handle_irq+0x208/0x260 el1_irq+0xb4/0x130 arch_cpu_idle+0x178/0x3cc default_idle_call+0x3c/0x54 do_idle+0x1a8/0x3dc cpu_startup_entry+0x24/0x28 rest_init+0x240/0x270 start_kernel+0x5a8/0x6bc irq event stamp: 18 hardirqs last enabled at (17): [] _raw_spin_unlock_irq+0x40/0xc0 hardirqs last disabled at (16): [] __schedule+0x20c/0x1bbc softirqs last enabled at (0): [] copy_process+0xb50/0x3964 softirqs last disabled at (18): [] local_bh_disable+0x8/0x20 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&irq_desc_lock_class); lock(&irq_desc_lock_class); *** DEADLOCK *** no locks held by irq/40-dpu_mdss/203. stack backtrace: CPU: 0 PID: 203 Comm: irq/40-dpu_mdss Tainted: G W 4.19.10 #76 Call trace: dump_backtrace+0x0/0x2f8 show_stack+0x20/0x2c __dump_stack+0x20/0x28 dump_stack+0xcc/0x10c mark_lock+0xbe0/0xe24 __lock_acquire+0x4cc/0x2708 lock_acquire+0x244/0x360 _raw_spin_lock+0x64/0xa0 handle_level_irq+0x34/0x26c generic_handle_irq+0x44/0x5c dpu_mdss_irq+0x64/0xec irq_forced_thread_fn+0x58/0x9c irq_thread+0x120/0x1dc kthread+0x248/0x260 ret_from_fork+0x10/0x18 ------------[ cut here ]------------ irq 169 handler irq_default_primary_handler+0x0/0x18 enabled interrupts Cc: Sean Paul Cc: Jordan Crouse Cc: Jayant Shekhar Cc: Rajesh Yadav Cc: Jeykumar Sankaran Signed-off-by: Stephen Boyd --- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 36 ++++++++++++++---------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index cb307a2abf06..7316b4ab1b85 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -23,11 +23,14 @@ struct dpu_mdss { struct dpu_irq_controller irq_controller; }; -static irqreturn_t dpu_mdss_irq(int irq, void *arg) +static void dpu_mdss_irq(struct irq_desc *desc) { - struct dpu_mdss *dpu_mdss = arg; + struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); u32 interrupts; + chained_irq_enter(chip, desc); + interrupts = readl_relaxed(dpu_mdss->mmio + HW_INTR_STATUS); while (interrupts) { @@ -39,20 +42,20 @@ static irqreturn_t dpu_mdss_irq(int irq, void *arg) hwirq); if (mapping == 0) { DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq); - return IRQ_NONE; + break; } rc = generic_handle_irq(mapping); if (rc < 0) { DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n", hwirq, mapping, rc); - return IRQ_NONE; + break; } interrupts &= ~(1 << hwirq); } - return IRQ_HANDLED; + chained_irq_exit(chip, desc); } static void dpu_mdss_irq_mask(struct irq_data *irqd) @@ -83,16 +86,16 @@ static struct irq_chip dpu_mdss_irq_chip = { .irq_unmask = dpu_mdss_irq_unmask, }; +static struct lock_class_key dpu_mdss_lock_key, dpu_mdss_request_key; + static int dpu_mdss_irqdomain_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq) { struct dpu_mdss *dpu_mdss = domain->host_data; - int ret; + irq_set_lockdep_class(irq, &dpu_mdss_lock_key, &dpu_mdss_request_key); irq_set_chip_and_handler(irq, &dpu_mdss_irq_chip, handle_level_irq); - ret = irq_set_chip_data(irq, dpu_mdss); - - return ret; + return irq_set_chip_data(irq, dpu_mdss); } static const struct irq_domain_ops dpu_mdss_irqdomain_ops = { @@ -159,11 +162,13 @@ static void dpu_mdss_destroy(struct drm_device *dev) struct msm_drm_private *priv = dev->dev_private; struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss); struct dss_module_power *mp = &dpu_mdss->mp; + int irq; pm_runtime_suspend(dev->dev); pm_runtime_disable(dev->dev); _dpu_mdss_irq_domain_fini(dpu_mdss); - free_irq(platform_get_irq(pdev, 0), dpu_mdss); + irq = platform_get_irq(pdev, 0); + irq_set_chained_handler_and_data(irq, NULL, NULL); msm_dss_put_clk(mp->clk_config, mp->num_clk); devm_kfree(&pdev->dev, mp->clk_config); @@ -187,6 +192,7 @@ int dpu_mdss_init(struct drm_device *dev) struct dpu_mdss *dpu_mdss; struct dss_module_power *mp; int ret = 0; + int irq; dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL); if (!dpu_mdss) @@ -219,12 +225,12 @@ int dpu_mdss_init(struct drm_device *dev) if (ret) goto irq_domain_error; - ret = request_irq(platform_get_irq(pdev, 0), - dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss); - if (ret) { - DPU_ERROR("failed to init irq: %d\n", ret); + irq = platform_get_irq(pdev, 0); + if (irq < 0) goto irq_error; - } + + irq_set_chained_handler_and_data(irq, dpu_mdss_irq, + dpu_mdss); pm_runtime_enable(dev->dev);