From patchwork Tue Sep 6 16:51:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 9317589 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 43B03601C0 for ; Tue, 6 Sep 2016 16:53:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3BFE428DEF for ; Tue, 6 Sep 2016 16:53:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 309CD28DF3; Tue, 6 Sep 2016 16:53:05 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5CB8128DEF for ; Tue, 6 Sep 2016 16:53:03 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bhJaz-0005rq-0J; Tue, 06 Sep 2016 16:51:37 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bhJak-0005Sm-2p for linux-arm-kernel@lists.infradead.org; Tue, 06 Sep 2016 16:51:25 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1F794A5E; Tue, 6 Sep 2016 09:51:01 -0700 (PDT) Received: from red-moon.cambridge.arm.com (red-moon.cambridge.arm.com [10.1.206.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8529D3F211; Tue, 6 Sep 2016 09:50:59 -0700 (PDT) From: Lorenzo Pieralisi To: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v2] drivers: acpi: fix GIC irq model default PCI IRQ polarity Date: Tue, 6 Sep 2016 17:51:03 +0100 Message-Id: <1473180663-20590-1-git-send-email-lorenzo.pieralisi@arm.com> X-Mailer: git-send-email 2.6.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160906_095122_388131_CA087CF4 X-CRM114-Status: GOOD ( 11.14 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lorenzo Pieralisi , Punit Agrawal , Marc Zyngier , Duc Dang , "Rafael J. Wysocki" , Sinan Kaya , Bjorn Helgaas , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP On ACPI ARM based systems the GIC interrupt controller and corresponding interrupt model permit only the high polarity for level interrupts. ACPI firmware describes PCI legacy IRQs through entries in the _PRT objects. Entries in the _PRT can be of two types: - Static: not configurable, trigger/polarity default to level-low, _PRT entry defines the global GSI interrupt number - Configurable: _PRT interrupt entry contains a reference to the corresponding PCI interrupt link device (that in turn provides the interrupt descriptor through its _CRS/_PRS methods) Configurable IRQ entries are not currently allowed by the ACPI specification on ARM since they can only be used for interrupt pins that are routable, as per ACPI specifications (version 6.1, 6.2.13): "[...] There are two ways that _PRT can be used. Typically, the interrupt input that a given PCI interrupt is on is configurable. For example, a given PCI interrupt might be configured for either IRQ 10 or 11 on an 8259 interrupt controller. In this model, each interrupt is represented in the ACPI namespace as a PCI Interrupt Link Device. [...]" ARM platforms GIC configurations do not allow dynamic IRQ routing, since routing is statically laid out at synthesis time; therefore PCI interrupt links cannot be used for PCI legacy IRQ descriptions in the _PRT on ARM systems. On the other hand, current core ACPI code handling PCI legacy IRQs consider IRQ trigger/polarity for static _PRT entries as level-low. On ARM systems with a GIC interrupt controller and corresponding ACPI interrupt model this does not work in that GIC interrupt controller is only capable of handling level interrupts whose polarity is high (for PCI legacy IRQs - that are level-low by specification - this means that the legacy IRQs are inverted before reaching the interrupt controller pin), resulting in IRQ allocation failures such as: genirq: Setting trigger mode 8 for irq 18 failed (gic_set_type+0x0/0x48) Change the default polarity for PCI legacy IRQs to high on systems booting wth ACPI on platforms with a GIC interrupt controller model, fixing the discrepancy between specification and HW behaviour. Signed-off-by: Lorenzo Pieralisi Acked-by: Marc Zyngier Tested-by: Duc Dang Cc: Punit Agrawal Cc: Duc Dang Cc: Bjorn Helgaas Cc: Sinan Kaya Cc: "Rafael J. Wysocki" Cc: Marc Zyngier --- v1 -> v2: - Added ACPI specs PCI Interrupt Link device usage restrictions in the patch commit log for explanation - Added review tags drivers/acpi/pci_irq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2c45dd3..c576a6f 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -411,7 +411,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) int gsi; u8 pin; int triggering = ACPI_LEVEL_SENSITIVE; - int polarity = ACPI_ACTIVE_LOW; + /* + * On ARM systems with the GIC interrupt model, level interrupts + * are always polarity high by specification; PCI legacy + * IRQs lines are inverted before reaching the interrupt + * controller and must therefore be considered active high + * as default. + */ + int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? + ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; char *link = NULL; char link_desc[16]; int rc;