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