diff mbox series

[OpenWrt-Devel] ath79: ar7100: remove IRQ code from PCI driver

Message ID 1534928794-8740-1-git-send-email-hanipouspilot@gmail.com
State Superseded
Delegated to: John Crispin
Headers show
Series [OpenWrt-Devel] ath79: ar7100: remove IRQ code from PCI driver | expand

Commit Message

Dmitry Tunin Aug. 22, 2018, 9:06 a.m. UTC
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 <hanipouspilot@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

Comments

John Crispin Aug. 22, 2018, 9:14 a.m. UTC | #1
On 22/08/18 11:06, Dmitry Tunin wrote:
> 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 <hanipouspilot@gmail.com>

looking good and much cleaner than the previous attempts, i am building 
an image for my wndr3800. if this works out i'd like to merge this patch 
asap
     John

> ---
>   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;
John Crispin Aug. 22, 2018, 9:20 a.m. UTC | #2
On 22/08/18 11:06, Dmitry Tunin wrote:
> 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.

we need a comparable patch for ar724x, right ? and then these 2 patches 
obsolete the PR on github ?

     John

>
> Signed-off-by: Dmitry Tunin <hanipouspilot@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;
Dmitry Tunin Aug. 22, 2018, 9:27 a.m. UTC | #3
> we need a comparable patch for ar724x, right ? and then these 2 patches
> obsolete the PR on github ?
>
>      John

Frankly speaking I didn't look into ar724x code. It has a PCIE, not a
PCI controller, so it wasn't affected that badly.
Chuanhong Guo knows that better.
Dmitry Tunin Aug. 22, 2018, 9:31 a.m. UTC | #4
I looked now and I think ro ar724x we need only
https://github.com/openwrt/openwrt/pull/1299/commits/0d2c51cc04b6f3872806970b1de6967ccd30289c

It looks OK in that case that IRQ is handled inside PCIE.
ср, 22 авг. 2018 г. в 12:27, Dmitry Tunin <hanipouspilot@gmail.com>:
>
> > we need a comparable patch for ar724x, right ? and then these 2 patches
> > obsolete the PR on github ?
> >
> >      John
>
> Frankly speaking I didn't look into ar724x code. It has a PCIE, not a
> PCI controller, so it wasn't affected that badly.
> Chuanhong Guo knows that better.
Chuanhong Guo Aug. 22, 2018, 11:47 a.m. UTC | #5
Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月22日周三 下午5:07写道:
>
> 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 <hanipouspilot@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>;
I guess this should be <0x18060018 0x8>?
Interrupt status is at 0x18060018-0x1806001c and interrupt mask is at
0x1806001c-0x18060020. The length of used memory space is 8 bytes.
BTW I noticed that reg of miscintc is <0x18060010 0x4> but the
register of interrupt status and mask is 0x18060010-0x18060018, also 8
bytes.
Are these two mistakes or my misunderstanding of the size in reg property?
> +                               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
Dmitry Tunin Aug. 22, 2018, 4:57 p.m. UTC | #6
Looking into irq-ath79-misc.c I found a few things to cleanup.

1. It appears that two chips are declared: "qca,ar7100-misc-intc" and
"qca,ar7240-misc-intc".
The only difference is mask-ack proc. The registers seem to work the
same way and practically we are using "qca,ar7240-misc-intc" on ar7100
according to dtsi.
I found that the other chip was declared only when looking into the code.

At the same time the code I removed from the PCI driver used the
ar7100 type of mask-ack, that worked also OK.

I see no reason of having two different ways of mask-ack for similar
hardware. We need to chose one that looks better and drop the other.

2. Instead of declaring two different chips this way, since we are
reusing this driver for PCI, I suggest to declare also
"qca,ath79-pci-intc" that will
have a different chip name = "PCI", so that "MISC and "PCI" will be
seen separately in /proc/interrupts.

3. I suggest removing legacy __init ath79_misc_irq_init() and leaving
only the OF stuff.

Any comments?
ср, 22 авг. 2018 г. в 14:47, Chuanhong Guo <gch981213@gmail.com>:
>
> Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月22日周三 下午5:07写道:
> >
> > 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 <hanipouspilot@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>;
> I guess this should be <0x18060018 0x8>?
> Interrupt status is at 0x18060018-0x1806001c and interrupt mask is at
> 0x1806001c-0x18060020. The length of used memory space is 8 bytes.
> BTW I noticed that reg of miscintc is <0x18060010 0x4> but the
> register of interrupt status and mask is 0x18060010-0x18060018, also 8
> bytes.
> Are these two mistakes or my misunderstanding of the size in reg property?
> > +                               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
Dmitry Tunin Aug. 22, 2018, 5:24 p.m. UTC | #7
I looked into the specs and now I see that the
AR71XX_RESET_REG_MISC_INT_STATUS is read-only on ar7100, so we need to
change the compatible
to "qca,ar7100-misc-intc" and also change it for the "real" misc
controller. Writing to RO register makes no sense at all.

Nothing is said about these registers in AR7240 datasheet, but I
suspect they work exactly same way ;-).

>
> Looking into irq-ath79-misc.c I found a few things to cleanup.
>
> 1. It appears that two chips are declared: "qca,ar7100-misc-intc" and
> "qca,ar7240-misc-intc".
> The only difference is mask-ack proc. The registers seem to work the
> same way and practically we are using "qca,ar7240-misc-intc" on ar7100
> according to dtsi.
> I found that the other chip was declared only when looking into the code.
>
> At the same time the code I removed from the PCI driver used the
> ar7100 type of mask-ack, that worked also OK.
>
> I see no reason of having two different ways of mask-ack for similar
> hardware. We need to chose one that looks better and drop the other.
>
> 2. Instead of declaring two different chips this way, since we are
> reusing this driver for PCI, I suggest to declare also
> "qca,ath79-pci-intc" that will
> have a different chip name = "PCI", so that "MISC and "PCI" will be
> seen separately in /proc/interrupts.
>
> 3. I suggest removing legacy __init ath79_misc_irq_init() and leaving
> only the OF stuff.
>
> Any comments?
> ср, 22 авг. 2018 г. в 14:47, Chuanhong Guo <gch981213@gmail.com>:
> >
> > Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月22日周三 下午5:07写道:
> > >
> > > 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 <hanipouspilot@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>;
> > I guess this should be <0x18060018 0x8>?
> > Interrupt status is at 0x18060018-0x1806001c and interrupt mask is at
> > 0x1806001c-0x18060020. The length of used memory space is 8 bytes.
> > BTW I noticed that reg of miscintc is <0x18060010 0x4> but the
> > register of interrupt status and mask is 0x18060010-0x18060018, also 8
> > bytes.
> > Are these two mistakes or my misunderstanding of the size in reg property?
> > > +                               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
Thomas Richard via openwrt-devel Aug. 22, 2018, 7:26 p.m. UTC | #8
The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
On Wed, Aug 22, 2018 at 6:58 PM Dmitry Tunin <hanipouspilot@gmail.com> wrote:
>
> Looking into irq-ath79-misc.c I found a few things to cleanup.
>
> 1. It appears that two chips are declared: "qca,ar7100-misc-intc" and
> "qca,ar7240-misc-intc".
> The only difference is mask-ack proc. The registers seem to work the
> same way and practically we are using "qca,ar7240-misc-intc" on ar7100
> according to dtsi.
> I found that the other chip was declared only when looking into the code.
>
> At the same time the code I removed from the PCI driver used the
> ar7100 type of mask-ack, that worked also OK.
>
> I see no reason of having two different ways of mask-ack for similar
> hardware. We need to chose one that looks better and drop the other.
I suggest discussing any irq-ath79-misc changes with the upstream developers
Alban Bedel did *a lot* of work to make the ath79 code devicetree
compatible. it would be a shame not to "use" his knowledge by
including him in the discussion upstream

> 2. Instead of declaring two different chips this way, since we are
> reusing this driver for PCI, I suggest to declare also
> "qca,ath79-pci-intc" that will
> have a different chip name = "PCI", so that "MISC and "PCI" will be
> seen separately in /proc/interrupts.
some existing irqchip drivers:
- set the name dynamically, see drivers/irqchip/irq-ts4800.c for example
- have a different number of interrupts per "compatible", see
drivers/irqchip/irq-meson-gpio.c for example

you may need the latter for your other patch which tries to reduce
ATH79_MISC_IRQ_COUNT anyways

> 3. I suggest removing legacy __init ath79_misc_irq_init() and leaving
> only the OF stuff.
I suggest coordinating this with the upstream developers as well as
that function is part of the upstream code

> Any comments?
slightly off-topic: please try not to top-post as it can be confusing


Regards
Martin
Dmitry Tunin Aug. 22, 2018, 7:38 p.m. UTC | #9
> > I see no reason of having two different ways of mask-ack for similar
> > hardware. We need to chose one that looks better and drop the other.
> I suggest discussing any irq-ath79-misc changes with the upstream developers
> Alban Bedel did *a lot* of work to make the ath79 code devicetree
> compatible. it would be a shame not to "use" his knowledge by
> including him in the discussion upstream

Now I see that the ack method for ar7240 is batantly wrong, probably
copied from some other place.
The driver was initially sent upsteam from Openwrt ;-)
I don't think anyone there looked into the hardware specs thoroughly.
I noticed this bug accidentally. Just got how the regs work and then
found that the ack is writing to a wrong reg.

We can always CC Alban.


> I suggest coordinating this with the upstream developers as well as
> that function is part of the upstream code

Lot's of things are part of upstream code ;-) But these type of things
are mostly developed here and sent upstream.

> > Any comments?
> slightly off-topic: please try not to top-post as it can be confusing
I am trying, but when I have to use web mailer I get in trouble with
that sometimes.
Chuanhong Guo Aug. 23, 2018, 3:36 a.m. UTC | #10
Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月23日周四 上午1:24写道:
>
> I looked into the specs and now I see that the
> AR71XX_RESET_REG_MISC_INT_STATUS is read-only on ar7100, so we need to
> change the compatible
> to "qca,ar7100-misc-intc" and also change it for the "real" misc
> controller. Writing to RO register makes no sense at all.
Please be aware that the access mode is *RO/RWC*, meaning *Read/Write to Clear*.
>
> Nothing is said about these registers in AR7240 datasheet, but I
> suspect they work exactly same way ;-).
>
> >
> > Looking into irq-ath79-misc.c I found a few things to cleanup.
> >
> > 1. It appears that two chips are declared: "qca,ar7100-misc-intc" and
> > "qca,ar7240-misc-intc".
> > The only difference is mask-ack proc. The registers seem to work the
> > same way and practically we are using "qca,ar7240-misc-intc" on ar7100
> > according to dtsi.
> > I found that the other chip was declared only when looking into the code.
> >
> > At the same time the code I removed from the PCI driver used the
> > ar7100 type of mask-ack, that worked also OK.
> >
> > I see no reason of having two different ways of mask-ack for similar
> > hardware. We need to chose one that looks better and drop the other.
> >
> > 2. Instead of declaring two different chips this way, since we are
> > reusing this driver for PCI, I suggest to declare also
> > "qca,ath79-pci-intc" that will
> > have a different chip name = "PCI", so that "MISC and "PCI" will be
> > seen separately in /proc/interrupts.
> >
> > 3. I suggest removing legacy __init ath79_misc_irq_init() and leaving
> > only the OF stuff.
> >
> > Any comments?
> > ср, 22 авг. 2018 г. в 14:47, Chuanhong Guo <gch981213@gmail.com>:
> > >
> > > Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月22日周三 下午5:07写道:
> > > >
> > > > 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 <hanipouspilot@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>;
> > > I guess this should be <0x18060018 0x8>?
> > > Interrupt status is at 0x18060018-0x1806001c and interrupt mask is at
> > > 0x1806001c-0x18060020. The length of used memory space is 8 bytes.
> > > BTW I noticed that reg of miscintc is <0x18060010 0x4> but the
> > > register of interrupt status and mask is 0x18060010-0x18060018, also 8
> > > bytes.
> > > Are these two mistakes or my misunderstanding of the size in reg property?
> > > > +                               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
Dmitry Tunin Aug. 23, 2018, 6:07 a.m. UTC | #11
чт, 23 авг. 2018 г. в 6:36, Chuanhong Guo <gch981213@gmail.com>:
>
> Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月23日周四 上午1:24写道:
> >
> > I looked into the specs and now I see that the
> > AR71XX_RESET_REG_MISC_INT_STATUS is read-only on ar7100, so we need to
> > change the compatible
> > to "qca,ar7100-misc-intc" and also change it for the "real" misc
> > controller. Writing to RO register makes no sense at all.
> Please be aware that the access mode is *RO/RWC*, meaning *Read/Write to Clear*.

I noticed that, and it is implemented, and only some bits are RWC.
It makes no sense to have a separate ack done this way. It slow things down.

And we already tested it both ways. It works either way, but one way
is faster than another.
Chuanhong Guo Aug. 23, 2018, 6:54 a.m. UTC | #12
Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月23日周四 下午2:07写道:
>
> чт, 23 авг. 2018 г. в 6:36, Chuanhong Guo <gch981213@gmail.com>:
> >
> > Dmitry Tunin <hanipouspilot@gmail.com> 于2018年8月23日周四 上午1:24写道:
> > >
> > > I looked into the specs and now I see that the
> > > AR71XX_RESET_REG_MISC_INT_STATUS is read-only on ar7100, so we need to
> > > change the compatible
> > > to "qca,ar7100-misc-intc" and also change it for the "real" misc
> > > controller. Writing to RO register makes no sense at all.
> > Please be aware that the access mode is *RO/RWC*, meaning *Read/Write to Clear*.
>
> I noticed that, and it is implemented, and only some bits are RWC.
This is true for ar7100. On other chips the entire
RST_MISC_INTERRUPT_STATUS block is marked as Read/Write-to-Clear.
> It makes no sense to have a separate ack done this way. It slow things down.
You can use an implementation without ack for PCI but you should keep
the one used for MISC_INTC unchanged.
>
> And we already tested it both ways. It works either way, but one way
> is faster than another.
Dmitry Tunin Aug. 23, 2018, 7:06 a.m. UTC | #13
> This is true for ar7100. On other chips the entire
> RST_MISC_INTERRUPT_STATUS block is marked as Read/Write-to-Clear.
Do you have the ar7240 datasheet with those specs?

> > It makes no sense to have a separate ack done this way. It slow things down.
> You can use an implementation without ack for PCI but you should keep
> the one used for MISC_INTC unchanged.

It is not "without ack". Implementations can be with separate "mask"
and "ack", or with "mask_ack" that does both.
The second way is faster and recommended.

For this simple controller there is no reason of using separate "mask"
and "ack", especially doing "ack" by writhing to the status register.
What is the point of doing it? What is the goal?

It looks like someone when writing the code didn't know what to define
for "ack" and wrote that.
Then someone else did a better job for 7100, by doing a correct way.
A third person merged these two ways in one driver without having a
clue why it is done this way.

Regarding the "real" miscintc controller it doesn't make much
difference because it serves slow devices like ohci.
But for PCI it is not a good idea.

Anyway in my current patch the compatible should be changed to
"qca,ar7100-misc-intc".

I can suggest other changes for discussion and testing later on.
Dmitry Tunin Aug. 23, 2018, 8 a.m. UTC | #14
It may have sense of doing the ack this in some cases. I need to do
some hardware testing to look at it more closely.
I think we can leave it is is. It's not important as I said before for
slow devices.

But the miscintc is redefined in ar7100.dtsi. So I am happy with that.
We need to have change it only for pci_intc to have all working.

The next step would be to declare a PCI chip for the same driver and
solve the size **problem** some way or another.
diff mbox series

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;