Currently all PCI devices get the same IRQ that affects performance badly.

This commit adresses this problem and cleans the code.

ar7100 has a special PCI interrupt controller@18060018 that works exactly
the same way as misc interrupt controller.

This patch does the following:

1. Removes all IRQ handling code from the PCI driver.
2. Defines pci-intc interrupt controller@18060018 in dtsi.
3. Removes interrupt-controller property from PCI node.
4. Sets a correct interrupt mask for PCI devices.

Run tested on DIR-825 B1.

Signed-off-by: Dmitry Tunin <hanipouspi...@gmail.com>
---
 target/linux/ath79/dts/ar7100.dtsi                 |  21 +++-
 .../0036-MIPS-ath79-remove-irq-code-from-pci.patch | 117 +++++++++++++++++++++
 2 files changed, 133 insertions(+), 5 deletions(-)
 create mode 100644 
target/linux/ath79/patches-4.14/0036-MIPS-ath79-remove-irq-code-from-pci.patch

diff --git a/target/linux/ath79/dts/ar7100.dtsi 
b/target/linux/ath79/dts/ar7100.dtsi
index 8994a7d..0632050 100644
--- a/target/linux/ath79/dts/ar7100.dtsi
+++ b/target/linux/ath79/dts/ar7100.dtsi
@@ -88,6 +88,14 @@
                                clock-names = "wdt";
                        };
 
+                       pci_intc: interrupt-controller@18060018 {
+                               compatible = "qca,ar7240-misc-intc";
+                               reg = <0x18060018 0x4>;
+                               interrupt-parent = <&cpuintc>;
+                               interrupts = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                       };
 
                        rst: reset-controller@18060024 {
                                compatible = "qca,ar7100-reset";
@@ -105,14 +113,17 @@
                                reg-names = "cfg_base";
                                ranges = <0x2000000 0 0x10000000 0x10000000 0 
0x07000000        /* pci memory */
                                          0x1000000 0 0x00000000 0x0000000 0 
0x000001>;         /* io space */
-                               interrupt-parent = <&cpuintc>;
-                               interrupts = <2>;
 
-                               interrupt-controller;
+                               interrupt-parent = <&pci_intc>;
+                               interrupts = <4>;
+
                                #interrupt-cells = <1>;
 
-                               interrupt-map-mask = <0 0 0 1>;
-                               interrupt-map = <0 0 0 0 &pcie0 0>;
+                               interrupt-map-mask = <0xf800 0 0 0>;
+                               interrupt-map = <0x8800 0 0 0 &pci_intc 0
+                                                0x9000 0 0 0 &pci_intc 1
+                                                0x9800 0 0 0 &pci_intc 2>;
+
                                status = "disabled";
                        };
                };
diff --git 
a/target/linux/ath79/patches-4.14/0036-MIPS-ath79-remove-irq-code-from-pci.patch
 
b/target/linux/ath79/patches-4.14/0036-MIPS-ath79-remove-irq-code-from-pci.patch
new file mode 100644
index 0000000..b3fc19a
--- /dev/null
+++ 
b/target/linux/ath79/patches-4.14/0036-MIPS-ath79-remove-irq-code-from-pci.patch
@@ -0,0 +1,117 @@
+Index: linux-4.14.65/arch/mips/pci/pci-ar71xx.c
+===================================================================
+--- linux-4.14.65.orig/arch/mips/pci/pci-ar71xx.c
++++ linux-4.14.65/arch/mips/pci/pci-ar71xx.c
+@@ -269,103 +269,6 @@ static struct pci_ops ar71xx_pci_ops = {
+       .write  = ar71xx_pci_write_config,
+ };
+ 
+-static void ar71xx_pci_irq_handler(struct irq_desc *desc)
+-{
+-      void __iomem *base = ath79_reset_base;
+-      struct irq_chip *chip = irq_desc_get_chip(desc);
+-      struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc);
+-      u32 pending;
+-
+-      chained_irq_enter(chip, desc);
+-      pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+-                __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      if (pending & AR71XX_PCI_INT_DEV0)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+-
+-      else if (pending & AR71XX_PCI_INT_DEV1)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 2));
+-
+-      else if (pending & AR71XX_PCI_INT_DEV2)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 3));
+-
+-      else if (pending & AR71XX_PCI_INT_CORE)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 4));
+-
+-      else
+-              spurious_interrupt();
+-      chained_irq_exit(chip, desc);
+-}
+-
+-static void ar71xx_pci_irq_unmask(struct irq_data *d)
+-{
+-      struct ar71xx_pci_controller *apc;
+-      unsigned int irq;
+-      void __iomem *base = ath79_reset_base;
+-      u32 t;
+-
+-      apc = irq_data_get_irq_chip_data(d);
+-      irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-      t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      /* flush write */
+-      __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static void ar71xx_pci_irq_mask(struct irq_data *d)
+-{
+-      struct ar71xx_pci_controller *apc;
+-      unsigned int irq;
+-      void __iomem *base = ath79_reset_base;
+-      u32 t;
+-
+-      apc = irq_data_get_irq_chip_data(d);
+-      irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-      t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      /* flush write */
+-      __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static struct irq_chip ar71xx_pci_irq_chip = {
+-      .name           = "AR71XX PCI",
+-      .irq_mask       = ar71xx_pci_irq_mask,
+-      .irq_unmask     = ar71xx_pci_irq_unmask,
+-      .irq_mask_ack   = ar71xx_pci_irq_mask,
+-};
+-
+-static int ar71xx_pci_irq_map(struct irq_domain *d, unsigned int irq, 
irq_hw_number_t hw)
+-{
+-      struct ar71xx_pci_controller *apc = d->host_data;
+-
+-      irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq);
+-      irq_set_chip_data(irq, apc);
+-
+-      return 0;
+-}
+-
+-static const struct irq_domain_ops ar71xx_pci_domain_ops = {
+-      .xlate = irq_domain_xlate_onecell,
+-      .map = ar71xx_pci_irq_map,
+-};
+-
+-static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+-{
+-      void __iomem *base = ath79_reset_base;
+-
+-      __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+-
+-      apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT,
+-                                          &ar71xx_pci_domain_ops, apc);
+-      irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+-                                       apc);
+-}
+-
+ static void ar71xx_pci_reset(void)
+ {
+       ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
+@@ -419,8 +322,6 @@ static int ar71xx_pci_probe(struct platf
+       apc->pci_ctrl.io_resource = &apc->io_res;
+       pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node);
+ 
+-      ar71xx_pci_irq_init(apc);
+-
+       register_pci_controller(&apc->pci_ctrl);
+ 
+       __ath79_pci_swizzle_b = ar71xx_pci_swizzle_b;
-- 
2.7.4


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to