PCI: host: Mark PCIe/PCI (MSI) IRQ cascade handlers as IRQF_NO_THREAD
authorGrygorii Strashko <grygorii.strashko@ti.com>
Thu, 10 Dec 2015 19:18:20 +0000 (21:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Feb 2016 20:30:56 +0000 (12:30 -0800)
commit 8ff0ef996ca00028519c70e8d51d32bd37eb51dc upstream.

On -RT and if kernel is booting with "threadirqs" cmd line parameter,
PCIe/PCI (MSI) IRQ cascade handlers (like dra7xx_pcie_msi_irq_handler())
will be forced threaded and, as result, will generate warnings like this:

  WARNING: CPU: 1 PID: 82 at kernel/irq/handle.c:150 handle_irq_event_percpu+0x14c/0x174()
  irq 460 handler irq_default_primary_handler+0x0/0x14 enabled interrupts
  Backtrace:
   (warn_slowpath_common) from (warn_slowpath_fmt+0x38/0x40)
   (warn_slowpath_fmt) from (handle_irq_event_percpu+0x14c/0x174)
   (handle_irq_event_percpu) from (handle_irq_event+0x84/0xb8)
   (handle_irq_event) from (handle_simple_irq+0x90/0x118)
   (handle_simple_irq) from (generic_handle_irq+0x30/0x44)
   (generic_handle_irq) from (dra7xx_pcie_msi_irq_handler+0x7c/0x8c)
   (dra7xx_pcie_msi_irq_handler) from (irq_forced_thread_fn+0x28/0x5c)
   (irq_forced_thread_fn) from (irq_thread+0x128/0x204)

This happens because all of them invoke generic_handle_irq() from the
requested handler.  generic_handle_irq() grabs raw_locks and thus needs to
run in raw-IRQ context.

This issue was originally reproduced on TI dra7-evem, but, as was
identified during discussion [1], other hosts can also suffer from this
issue.  Fix all them at once by marking PCIe/PCI (MSI) IRQ cascade handlers
IRQF_NO_THREAD explicitly.

[1] http://lkml.kernel.org/r/1448027966-21610-1-git-send-email-grygorii.strashko@ti.com

[bhelgaas: add stable tag, fix typos]
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
CC: Kishon Vijay Abraham I <kishon@ti.com>
CC: Jingoo Han <jingoohan1@gmail.com>
CC: Kukjin Kim <kgene@kernel.org>
CC: Krzysztof Kozlowski <k.kozlowski@samsung.com>
CC: Richard Zhu <Richard.Zhu@freescale.com>
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Stephen Warren <swarren@wwwdotorg.org>
CC: Alexandre Courbot <gnurou@gmail.com>
CC: Simon Horman <horms@verge.net.au>
CC: Pratyush Anand <pratyush.anand@gmail.com>
CC: Michal Simek <michal.simek@xilinx.com>
CC: "Sören Brinkmann" <soren.brinkmann@xilinx.com>
CC: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/host/pci-dra7xx.c
drivers/pci/host/pci-exynos.c
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-spear13xx.c
drivers/pci/host/pcie-xilinx.c

index 8c3688046c02ff40446833f1a8f3eecebfd9713f..923607bdabc5c63ef940453f3ffe42180b29b02b 100644 (file)
@@ -302,7 +302,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
        }
 
        ret = devm_request_irq(&pdev->dev, pp->irq,
-                              dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
+                              dra7xx_pcie_msi_irq_handler,
+                              IRQF_SHARED | IRQF_NO_THREAD,
                               "dra7-pcie-msi", pp);
        if (ret) {
                dev_err(&pdev->dev, "failed to request irq\n");
index 01095e1160a474b414112cdc1dddae1d8f3b9434..d997d22d4231da6de08cab29dd101d699dbb4fe0 100644 (file)
@@ -522,7 +522,8 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 
                ret = devm_request_irq(&pdev->dev, pp->msi_irq,
                                        exynos_pcie_msi_irq_handler,
-                                       IRQF_SHARED, "exynos-pcie", pp);
+                                       IRQF_SHARED | IRQF_NO_THREAD,
+                                       "exynos-pcie", pp);
                if (ret) {
                        dev_err(&pdev->dev, "failed to request msi irq\n");
                        return ret;
index 22e8224126fd9d9885ee06f2fb81cbf1f023b06b..9ce7cd148c86685fc812f79d8da981af8e778101 100644 (file)
@@ -537,7 +537,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 
                ret = devm_request_irq(&pdev->dev, pp->msi_irq,
                                       imx6_pcie_msi_handler,
-                                      IRQF_SHARED, "mx6-pcie-msi", pp);
+                                      IRQF_SHARED | IRQF_NO_THREAD,
+                                      "mx6-pcie-msi", pp);
                if (ret) {
                        dev_err(&pdev->dev, "failed to request MSI irq\n");
                        return ret;
index 3018ae52e0923d4e2e8c8c2dc75f07d5528598bc..30323114c53cca80b0c4f7bee7f361d65565fc26 100644 (file)
@@ -1288,7 +1288,7 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
 
        msi->irq = err;
 
-       err = request_irq(msi->irq, tegra_pcie_msi_irq, 0,
+       err = request_irq(msi->irq, tegra_pcie_msi_irq, IRQF_NO_THREAD,
                          tegra_msi_irq_chip.name, pcie);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
index f4fa6c537448cae9d25519a8697e212aa70facaa..414c3368662186793c634af12fa5700414b8eea6 100644 (file)
@@ -720,14 +720,16 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 
        /* Two irqs are for MSI, but they are also used for non-MSI irqs */
        err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq,
-                              IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+                              IRQF_SHARED | IRQF_NO_THREAD,
+                              rcar_msi_irq_chip.name, pcie);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
                goto err;
        }
 
        err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq,
-                              IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+                              IRQF_SHARED | IRQF_NO_THREAD,
+                              rcar_msi_irq_chip.name, pcie);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
                goto err;
index b95b7563c052135bbad5407073685d9ff8930df6..a6cd8233e8c08c8fee6e1df3a1a7d40fdc2250a8 100644 (file)
@@ -279,7 +279,8 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
                return -ENODEV;
        }
        ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
-                              IRQF_SHARED, "spear1340-pcie", pp);
+                              IRQF_SHARED | IRQF_NO_THREAD,
+                              "spear1340-pcie", pp);
        if (ret) {
                dev_err(dev, "failed to request irq %d\n", pp->irq);
                return ret;
index 3c7a0d580b1ed990d9978efc5927c3a8d2abc8af..4cfa46360d1229976533f3a0c42152c30a282099 100644 (file)
@@ -781,7 +781,8 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
 
        port->irq = irq_of_parse_and_map(node, 0);
        err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler,
-                              IRQF_SHARED, "xilinx-pcie", port);
+                              IRQF_SHARED | IRQF_NO_THREAD,
+                              "xilinx-pcie", port);
        if (err) {
                dev_err(dev, "unable to request irq %d\n", port->irq);
                return err;