From 080691d7b1af67205081dff5a7fc4a988e080981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 10 Jan 2022 02:12:45 +0100 Subject: kernel: 5.10: Backport pending pci-aardvark changes fixing MSI support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport Aardvark PCIe controller driver changes that fix MSI support, that were recently sent to the linux-pci mailing list [1]. These changes fix MSI and MSI-X support for this PCIe controller, which, among other things, make it possible to use NVMe drives with this PCIe controllers. [1] https://lore.kernel.org/linux-pci/20220110015018.26359-1-kabel@kernel.org/ Signed-off-by: Marek Behún --- ...k-Rewrite-IRQ-code-to-chained-IRQ-handler.patch | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch (limited to 'target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch') diff --git a/target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch b/target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch new file mode 100644 index 0000000000..fbed9cc506 --- /dev/null +++ b/target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch @@ -0,0 +1,130 @@ +From 0cd5141d1866afb23286fe90cd846441fe7aeb39 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Sat, 27 Mar 2021 14:44:11 +0100 +Subject: [PATCH] PCI: aardvark: Rewrite IRQ code to chained IRQ handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rewrite the code to use irq_set_chained_handler_and_data() handler with +chained_irq_enter() and chained_irq_exit() processing instead of using +devm_request_irq(). + +advk_pcie_irq_handler() reads IRQ status bits and calls other functions +based on which bits are set. These functions then read its own IRQ status +bits and calls other aardvark functions based on these bits. Finally +generic_handle_domain_irq() with translated linux IRQ numbers are called. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 48 +++++++++++++++------------ + 1 file changed, 26 insertions(+), 22 deletions(-) + +diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c +index e68773527171..01dfe70d9c2c 100644 +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -275,6 +275,7 @@ struct advk_pcie { + u32 actions; + } wins[OB_WIN_COUNT]; + u8 wins_count; ++ int irq; + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + raw_spinlock_t irq_lock; +@@ -1440,21 +1441,26 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie) + } + } + +-static irqreturn_t advk_pcie_irq_handler(int irq, void *arg) ++static void advk_pcie_irq_handler(struct irq_desc *desc) + { +- struct advk_pcie *pcie = arg; +- u32 status; ++ struct advk_pcie *pcie = irq_desc_get_handler_data(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ u32 val, mask, status; + +- status = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); +- if (!(status & PCIE_IRQ_CORE_INT)) +- return IRQ_NONE; ++ chained_irq_enter(chip, desc); + +- advk_pcie_handle_int(pcie); ++ val = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); ++ mask = advk_readl(pcie, HOST_CTRL_INT_MASK_REG); ++ status = val & ((~mask) & PCIE_IRQ_ALL_MASK); + +- /* Clear interrupt */ +- advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG); ++ if (status & PCIE_IRQ_CORE_INT) { ++ advk_pcie_handle_int(pcie); + +- return IRQ_HANDLED; ++ /* Clear interrupt */ ++ advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG); ++ } ++ ++ chained_irq_exit(chip, desc); + } + + static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) +@@ -1521,7 +1527,7 @@ static int advk_pcie_probe(struct platform_device *pdev) + struct advk_pcie *pcie; + struct pci_host_bridge *bridge; + struct resource_entry *entry; +- int ret, irq; ++ int ret; + + bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie)); + if (!bridge) +@@ -1609,17 +1615,9 @@ static int advk_pcie_probe(struct platform_device *pdev) + if (IS_ERR(pcie->base)) + return PTR_ERR(pcie->base); + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; +- +- ret = devm_request_irq(dev, irq, advk_pcie_irq_handler, +- IRQF_SHARED | IRQF_NO_THREAD, "advk-pcie", +- pcie); +- if (ret) { +- dev_err(dev, "Failed to register interrupt\n"); +- return ret; +- } ++ pcie->irq = platform_get_irq(pdev, 0); ++ if (pcie->irq < 0) ++ return pcie->irq; + + pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node, + "reset-gpios", 0, +@@ -1668,11 +1666,14 @@ static int advk_pcie_probe(struct platform_device *pdev) + return ret; + } + ++ irq_set_chained_handler_and_data(pcie->irq, advk_pcie_irq_handler, pcie); ++ + bridge->sysdata = pcie; + bridge->ops = &advk_pcie_ops; + + ret = pci_host_probe(bridge); + if (ret < 0) { ++ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + return ret; +@@ -1720,6 +1721,9 @@ static int advk_pcie_remove(struct platform_device *pdev) + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + ++ /* Remove IRQ handler */ ++ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); ++ + /* Remove IRQ domains */ + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); +-- +2.34.1 + -- cgit v1.2.3