From 080691d7b1af67205081dff5a7fc4a988e080981 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
Date: Mon, 10 Jan 2022 02:12:45 +0100
Subject: [PATCH] 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 <kabel@kernel.org>
---
 ...lace-custom-PCIE_CORE_INT_-macros-wi.patch |  45 +++++
 ...ark-Fix-reading-MSI-interrupt-number.patch |  62 ++++++
 ...dvark-Fix-support-for-MSI-interrupts.patch |  77 ++++++++
 ...rite-IRQ-code-to-chained-IRQ-handler.patch | 130 +++++++++++++
 ...ck-return-value-of-generic_handle_do.patch |  36 ++++
 ...e-MSI-irq_chip-structures-static-dri.patch |  98 ++++++++++
 ...e-msi_domain_info-structure-a-static.patch |  69 +++++++
 ...-dev_fwnode-instead-of-of_node_to_fw.patch |  45 +++++
 ...actor-unmasking-summary-MSI-interrup.patch |  49 +++++
 ...d-support-for-masking-MSI-interrupts.patch | 122 ++++++++++++
 ...PCI-aardvark-Fix-setting-MSI-address.patch |  96 ++++++++++
 ...12-PCI-aardvark-Enable-MSI-X-support.patch |  43 +++++
 ...-support-for-ERR-interrupt-on-emulat.patch | 105 +++++++++++
 ...-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch |  49 +++++
 ...imize-writing-PCI_EXP_RTCTL_PMEIE-an.patch |  57 ++++++
 ...dvark-Add-support-for-PME-interrupts.patch |  52 +++++
 ...-support-for-PME-requester-on-emulat.patch | 178 ++++++++++++++++++
 ...-separate-INTA-interrupt-for-emulate.patch | 166 ++++++++++++++++
 ...ove-irq_mask_ack-callback-for-INTx-i.patch |  34 ++++
 ...aardvark-Don-t-mask-irq-when-mapping.patch |  32 ++++
 ...p-__maybe_unused-from-advk_pcie_disa.patch |  33 ++++
 ...ate-comment-about-link-going-down-af.patch |  40 ++++
 ...e-main-irq_chip-structure-a-static-d.patch | 107 +++++++++++
 23 files changed, 1725 insertions(+)
 create mode 100644 target/linux/generic/pending-5.10/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0012-PCI-aardvark-Enable-MSI-X-support.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch
 create mode 100644 target/linux/generic/pending-5.10/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch

diff --git a/target/linux/generic/pending-5.10/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch b/target/linux/generic/pending-5.10/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch
new file mode 100644
index 00000000000..c63d016c35c
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch
@@ -0,0 +1,45 @@
+From 43f3f187e6f62ca40802afe39495c8a3e20b4bfa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Mon, 10 Jan 2022 01:50:50 +0100
+Subject: [PATCH] PCI: aardvark: Replace custom PCIE_CORE_INT_* macros with
+ PCI_INTERRUPT_*
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Header file linux/pci.h defines enum pci_interrupt_pin with corresponding
+PCI_INTERRUPT_* values.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 226bce2f98f6..a573fc1aa4dd 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -37,10 +37,6 @@
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN			BIT(6)
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHCK			BIT(7)
+ #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV			BIT(8)
+-#define     PCIE_CORE_INT_A_ASSERT_ENABLE			1
+-#define     PCIE_CORE_INT_B_ASSERT_ENABLE			2
+-#define     PCIE_CORE_INT_C_ASSERT_ENABLE			3
+-#define     PCIE_CORE_INT_D_ASSERT_ENABLE			4
+ /* PIO registers base address and register offsets */
+ #define PIO_BASE_ADDR				0x4000
+ #define PIO_CTRL				(PIO_BASE_ADDR + 0x0)
+@@ -967,7 +963,7 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
+ 	bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
+ 
+ 	/* Support interrupt A for MSI feature */
+-	bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
++	bridge->conf.intpin = PCI_INTERRUPT_INTA;
+ 
+ 	/* Indicates supports for Completion Retry Status */
+ 	bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch b/target/linux/generic/pending-5.10/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch
new file mode 100644
index 00000000000..25922eeb0a3
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch
@@ -0,0 +1,62 @@
+From a29a7d01cd778854e08108461cba321a63d98871 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 2 Jul 2021 16:39:47 +0200
+Subject: [PATCH] PCI: aardvark: Fix reading MSI interrupt number
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In advk_pcie_handle_msi() the authors expect that when bit i in the W1C
+register PCIE_MSI_STATUS_REG is cleared, the PCIE_MSI_PAYLOAD_REG is
+updated to contain the MSI number corresponding to index i.
+
+Experiments show that this is not so, and instead PCIE_MSI_PAYLOAD_REG
+always contains the number of the last received MSI, overall.
+
+Do not read PCIE_MSI_PAYLOAD_REG register for determining MSI interrupt
+number. Since Aardvark already forbids more than 32 interrupts and uses
+own allocated hwirq numbers, the msi_idx already corresponds to the
+received MSI number.
+
+Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index a573fc1aa4dd..1c6980a78975 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1391,7 +1391,7 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
+ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
+ {
+ 	u32 msi_val, msi_mask, msi_status, msi_idx;
+-	u16 msi_data;
++	int virq;
+ 
+ 	msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
+ 	msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG);
+@@ -1401,13 +1401,12 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
+ 		if (!(BIT(msi_idx) & msi_status))
+ 			continue;
+ 
+-		/*
+-		 * msi_idx contains bits [4:0] of the msi_data and msi_data
+-		 * contains 16bit MSI interrupt number
+-		 */
+ 		advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG);
+-		msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK;
+-		generic_handle_irq(msi_data);
++		virq = irq_find_mapping(pcie->msi_inner_domain, msi_idx);
++		if (virq)
++			generic_handle_irq(virq);
++		else
++			dev_err_ratelimited(&pcie->pdev->dev, "unexpected MSI 0x%02x\n", msi_idx);
+ 	}
+ 
+ 	advk_writel(pcie, PCIE_ISR0_MSI_INT_PENDING,
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch b/target/linux/generic/pending-5.10/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch
new file mode 100644
index 00000000000..1735399dc15
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch
@@ -0,0 +1,77 @@
+From bb03b126ea6c9e57177b537dd022246fa5dbef16 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 12 Feb 2021 16:24:07 +0100
+Subject: [PATCH] PCI: aardvark: Fix support for MSI interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Aardvark hardware supports Multi-MSI and MSI_FLAG_MULTI_PCI_MSI is already
+set for the MSI chip. But when allocating MSI interrupt numbers for
+Multi-MSI, the numbers need to be properly aligned, otherwise endpoint
+devices send MSI interrupt with incorrect numbers.
+
+Fix this issue by using function bitmap_find_free_region() instead of
+bitmap_find_next_zero_area().
+
+To ensure that aligned MSI interrupt numbers are used by endpoint devices,
+we cannot use Linux virtual irq numbers (as they are random and not
+properly aligned). Instead we need to use the aligned hwirq numbers.
+
+This change fixes receiving MSI interrupts on Armada 3720 boards and
+allows using NVMe disks which use Multi-MSI feature with 3 interrupts.
+
+Without this NVMe disks freeze booting as linux nvme-core.c is waiting
+60s for an interrupt.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 1c6980a78975..e68773527171 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1187,7 +1187,7 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
+ 
+ 	msg->address_lo = lower_32_bits(msi_msg);
+ 	msg->address_hi = upper_32_bits(msi_msg);
+-	msg->data = data->irq;
++	msg->data = data->hwirq;
+ }
+ 
+ static int advk_msi_set_affinity(struct irq_data *irq_data,
+@@ -1204,15 +1204,11 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+ 	int hwirq, i;
+ 
+ 	mutex_lock(&pcie->msi_used_lock);
+-	hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
+-					   0, nr_irqs, 0);
+-	if (hwirq >= MSI_IRQ_NUM) {
+-		mutex_unlock(&pcie->msi_used_lock);
+-		return -ENOSPC;
+-	}
+-
+-	bitmap_set(pcie->msi_used, hwirq, nr_irqs);
++	hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
++					order_base_2(nr_irqs));
+ 	mutex_unlock(&pcie->msi_used_lock);
++	if (hwirq < 0)
++		return -ENOSPC;
+ 
+ 	for (i = 0; i < nr_irqs; i++)
+ 		irq_domain_set_info(domain, virq + i, hwirq + i,
+@@ -1230,7 +1226,7 @@ static void advk_msi_irq_domain_free(struct irq_domain *domain,
+ 	struct advk_pcie *pcie = domain->host_data;
+ 
+ 	mutex_lock(&pcie->msi_used_lock);
+-	bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
++	bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
+ 	mutex_unlock(&pcie->msi_used_lock);
+ }
+ 
+-- 
+2.34.1
+
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 00000000000..fbed9cc5069
--- /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?= <pali@kernel.org>
+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 <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ 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
+
diff --git a/target/linux/generic/pending-5.10/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch b/target/linux/generic/pending-5.10/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch
new file mode 100644
index 00000000000..0428d30f086
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch
@@ -0,0 +1,36 @@
+From 69c1f2c6f45a556361fd8e8d2d4eb20e2c8d3d95 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 18 Mar 2021 17:04:32 +0100
+Subject: [PATCH] PCI: aardvark: Check return value of
+ generic_handle_domain_irq() when processing INTx IRQ
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is possible that we receive spurious INTx interrupt. Check for the
+return value of generic_handle_domain_irq() when processing INTx IRQ.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 01dfe70d9c2c..4be05b52d835 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1437,7 +1437,9 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ 			    PCIE_ISR1_REG);
+ 
+ 		virq = irq_find_mapping(pcie->irq_domain, i);
+-		generic_handle_irq(virq);
++		if (generic_handle_irq(virq) == -EINVAL)
++			dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n",
++					    (char)i + 'A');
+ 	}
+ }
+ 
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch b/target/linux/generic/pending-5.10/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch
new file mode 100644
index 00000000000..b7d41088936
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch
@@ -0,0 +1,98 @@
+From 5eb36a6b9508da442aac80f4df23e3951bbfa7aa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Mon, 10 Jan 2022 00:03:41 +0100
+Subject: [PATCH] PCI: aardvark: Make MSI irq_chip structures static driver
+ structures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Marc Zyngier says [1] that we should use struct irq_chip as a global
+static struct in the driver. Even though the structure currently
+contains a dynamic member (parent_device), Marc says [2] that he plans
+to kill it and make the structure completely static.
+
+Convert Aardvark's priv->msi_bottom_irq_chip and priv->msi_irq_chip to
+static driver structure.
+
+[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/
+[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 4be05b52d835..c7bd6b123857 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -281,8 +281,6 @@ struct advk_pcie {
+ 	raw_spinlock_t irq_lock;
+ 	struct irq_domain *msi_domain;
+ 	struct irq_domain *msi_inner_domain;
+-	struct irq_chip msi_bottom_irq_chip;
+-	struct irq_chip msi_irq_chip;
+ 	struct msi_domain_info msi_domain_info;
+ 	DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
+ 	struct mutex msi_used_lock;
+@@ -1197,6 +1195,12 @@ static int advk_msi_set_affinity(struct irq_data *irq_data,
+ 	return -EINVAL;
+ }
+ 
++static struct irq_chip advk_msi_bottom_irq_chip = {
++	.name			= "MSI",
++	.irq_compose_msi_msg	= advk_msi_irq_compose_msi_msg,
++	.irq_set_affinity	= advk_msi_set_affinity,
++};
++
+ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+ 				     unsigned int virq,
+ 				     unsigned int nr_irqs, void *args)
+@@ -1213,7 +1217,7 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+ 
+ 	for (i = 0; i < nr_irqs; i++)
+ 		irq_domain_set_info(domain, virq + i, hwirq + i,
+-				    &pcie->msi_bottom_irq_chip,
++				    &advk_msi_bottom_irq_chip,
+ 				    domain->host_data, handle_simple_irq,
+ 				    NULL, NULL);
+ 
+@@ -1283,29 +1287,23 @@ static const struct irq_domain_ops advk_pcie_irq_domain_ops = {
+ 	.xlate = irq_domain_xlate_onecell,
+ };
+ 
++static struct irq_chip advk_msi_irq_chip = {
++	.name = "advk-MSI",
++};
++
+ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ {
+ 	struct device *dev = &pcie->pdev->dev;
+ 	struct device_node *node = dev->of_node;
+-	struct irq_chip *bottom_ic, *msi_ic;
+ 	struct msi_domain_info *msi_di;
+ 	phys_addr_t msi_msg_phys;
+ 
+ 	mutex_init(&pcie->msi_used_lock);
+ 
+-	bottom_ic = &pcie->msi_bottom_irq_chip;
+-
+-	bottom_ic->name = "MSI";
+-	bottom_ic->irq_compose_msi_msg = advk_msi_irq_compose_msi_msg;
+-	bottom_ic->irq_set_affinity = advk_msi_set_affinity;
+-
+-	msi_ic = &pcie->msi_irq_chip;
+-	msi_ic->name = "advk-MSI";
+-
+ 	msi_di = &pcie->msi_domain_info;
+ 	msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ 		MSI_FLAG_MULTI_PCI_MSI;
+-	msi_di->chip = msi_ic;
++	msi_di->chip = &advk_msi_irq_chip;
+ 
+ 	msi_msg_phys = virt_to_phys(&pcie->msi_msg);
+ 
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch b/target/linux/generic/pending-5.10/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch
new file mode 100644
index 00000000000..e388bc2ea78
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch
@@ -0,0 +1,69 @@
+From c092ab8994f1f777054c0179a9deb40b87ee606f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Mon, 10 Jan 2022 00:10:46 +0100
+Subject: [PATCH] PCI: aardvark: Make msi_domain_info structure a static driver
+ structure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Make Aardvark's msi_domain_info structure into a private driver structure.
+Domain info is same for every potential instatination of a controller.
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index c7bd6b123857..b5e5c922ad0d 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -281,7 +281,6 @@ struct advk_pcie {
+ 	raw_spinlock_t irq_lock;
+ 	struct irq_domain *msi_domain;
+ 	struct irq_domain *msi_inner_domain;
+-	struct msi_domain_info msi_domain_info;
+ 	DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
+ 	struct mutex msi_used_lock;
+ 	u16 msi_msg;
+@@ -1291,20 +1290,20 @@ static struct irq_chip advk_msi_irq_chip = {
+ 	.name = "advk-MSI",
+ };
+ 
++static struct msi_domain_info advk_msi_domain_info = {
++	.flags	= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
++		  MSI_FLAG_MULTI_PCI_MSI,
++	.chip	= &advk_msi_irq_chip,
++};
++
+ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ {
+ 	struct device *dev = &pcie->pdev->dev;
+ 	struct device_node *node = dev->of_node;
+-	struct msi_domain_info *msi_di;
+ 	phys_addr_t msi_msg_phys;
+ 
+ 	mutex_init(&pcie->msi_used_lock);
+ 
+-	msi_di = &pcie->msi_domain_info;
+-	msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+-		MSI_FLAG_MULTI_PCI_MSI;
+-	msi_di->chip = &advk_msi_irq_chip;
+-
+ 	msi_msg_phys = virt_to_phys(&pcie->msi_msg);
+ 
+ 	advk_writel(pcie, lower_32_bits(msi_msg_phys),
+@@ -1320,7 +1319,8 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ 
+ 	pcie->msi_domain =
+ 		pci_msi_create_irq_domain(of_node_to_fwnode(node),
+-					  msi_di, pcie->msi_inner_domain);
++					  &advk_msi_domain_info,
++					  pcie->msi_inner_domain);
+ 	if (!pcie->msi_domain) {
+ 		irq_domain_remove(pcie->msi_inner_domain);
+ 		return -ENOMEM;
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch b/target/linux/generic/pending-5.10/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch
new file mode 100644
index 00000000000..baba1744c26
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch
@@ -0,0 +1,45 @@
+From 59029739d42b439628e2f64f3d8f2db9be97deff Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Mon, 10 Jan 2022 00:15:17 +0100
+Subject: [PATCH] PCI: aardvark: Use dev_fwnode() instead of
+ of_node_to_fwnode(dev->of_node)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use simple
+  dev_fwnode(dev)
+instead of
+  struct device_node *node = dev->of_node;
+  of_node_to_fwnode(node)
+especially since the node variable is not used elsewhere in the function.
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index b5e5c922ad0d..e641ad566488 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1299,7 +1299,6 @@ static struct msi_domain_info advk_msi_domain_info = {
+ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ {
+ 	struct device *dev = &pcie->pdev->dev;
+-	struct device_node *node = dev->of_node;
+ 	phys_addr_t msi_msg_phys;
+ 
+ 	mutex_init(&pcie->msi_used_lock);
+@@ -1318,7 +1317,7 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ 		return -ENOMEM;
+ 
+ 	pcie->msi_domain =
+-		pci_msi_create_irq_domain(of_node_to_fwnode(node),
++		pci_msi_create_irq_domain(dev_fwnode(dev),
+ 					  &advk_msi_domain_info,
+ 					  pcie->msi_inner_domain);
+ 	if (!pcie->msi_domain) {
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch b/target/linux/generic/pending-5.10/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch
new file mode 100644
index 00000000000..8189f0b1f1e
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch
@@ -0,0 +1,49 @@
+From 98feaf97bc64fc640a6c5b1394cd18fc7cd7dac8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Sun, 28 Mar 2021 14:34:49 +0200
+Subject: [PATCH] PCI: aardvark: Refactor unmasking summary MSI interrupt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Refactor the masking of ISR0/1 Sources and unmasking of summary MSI interrupt
+so that it corresponds to the comments:
+- first mask all ISR0/1
+- then unmask all MSIs
+- then unmask summary MSI interrupt
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index e641ad566488..5c887772fa97 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -578,15 +578,17 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ 	advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
+ 
+ 	/* Disable All ISR0/1 Sources */
+-	reg = PCIE_ISR0_ALL_MASK;
+-	reg &= ~PCIE_ISR0_MSI_INT_PENDING;
+-	advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
+-
++	advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
+ 	advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
+ 
+ 	/* Unmask all MSIs */
+ 	advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
+ 
++	/* Unmask summary MSI interrupt */
++	reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++	reg &= ~PCIE_ISR0_MSI_INT_PENDING;
++	advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
++
+ 	/* Enable summary interrupt for GIC SPI source */
+ 	reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
+ 	advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch b/target/linux/generic/pending-5.10/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch
new file mode 100644
index 00000000000..cdd76eed1ca
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch
@@ -0,0 +1,122 @@
+From 7f353accca6e4a3222991c65b1a6801503973bd3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 2 Jul 2021 16:44:10 +0200
+Subject: [PATCH] PCI: aardvark: Add support for masking MSI interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We should not unmask MSIs at setup, but only when kernel asks for them
+to be unmasked.
+
+At setup, mask all MSIs, and implement IRQ chip callbacks for masking
+and unmasking particular MSIs.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 54 ++++++++++++++++++++++++---
+ 1 file changed, 49 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 5c887772fa97..43db884c81a1 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -281,6 +281,7 @@ struct advk_pcie {
+ 	raw_spinlock_t irq_lock;
+ 	struct irq_domain *msi_domain;
+ 	struct irq_domain *msi_inner_domain;
++	raw_spinlock_t msi_irq_lock;
+ 	DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
+ 	struct mutex msi_used_lock;
+ 	u16 msi_msg;
+@@ -577,12 +578,10 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ 	advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
+ 	advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
+ 
+-	/* Disable All ISR0/1 Sources */
++	/* Disable All ISR0/1 and MSI Sources */
+ 	advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
+ 	advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
+-
+-	/* Unmask all MSIs */
+-	advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
++	advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
+ 
+ 	/* Unmask summary MSI interrupt */
+ 	reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+@@ -1196,10 +1195,52 @@ static int advk_msi_set_affinity(struct irq_data *irq_data,
+ 	return -EINVAL;
+ }
+ 
++static void advk_msi_irq_mask(struct irq_data *d)
++{
++	struct advk_pcie *pcie = d->domain->host_data;
++	irq_hw_number_t hwirq = irqd_to_hwirq(d);
++	unsigned long flags;
++	u32 mask;
++
++	raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
++	mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
++	mask |= BIT(hwirq);
++	advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
++	raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
++}
++
++static void advk_msi_irq_unmask(struct irq_data *d)
++{
++	struct advk_pcie *pcie = d->domain->host_data;
++	irq_hw_number_t hwirq = irqd_to_hwirq(d);
++	unsigned long flags;
++	u32 mask;
++
++	raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
++	mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
++	mask &= ~BIT(hwirq);
++	advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
++	raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
++}
++
++static void advk_msi_top_irq_mask(struct irq_data *d)
++{
++	pci_msi_mask_irq(d);
++	irq_chip_mask_parent(d);
++}
++
++static void advk_msi_top_irq_unmask(struct irq_data *d)
++{
++	pci_msi_unmask_irq(d);
++	irq_chip_unmask_parent(d);
++}
++
+ static struct irq_chip advk_msi_bottom_irq_chip = {
+ 	.name			= "MSI",
+ 	.irq_compose_msi_msg	= advk_msi_irq_compose_msi_msg,
+ 	.irq_set_affinity	= advk_msi_set_affinity,
++	.irq_mask		= advk_msi_irq_mask,
++	.irq_unmask		= advk_msi_irq_unmask,
+ };
+ 
+ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+@@ -1289,7 +1330,9 @@ static const struct irq_domain_ops advk_pcie_irq_domain_ops = {
+ };
+ 
+ static struct irq_chip advk_msi_irq_chip = {
+-	.name = "advk-MSI",
++	.name		= "advk-MSI",
++	.irq_mask	= advk_msi_top_irq_mask,
++	.irq_unmask	= advk_msi_top_irq_unmask,
+ };
+ 
+ static struct msi_domain_info advk_msi_domain_info = {
+@@ -1303,6 +1346,7 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ 	struct device *dev = &pcie->pdev->dev;
+ 	phys_addr_t msi_msg_phys;
+ 
++	raw_spin_lock_init(&pcie->msi_irq_lock);
+ 	mutex_init(&pcie->msi_used_lock);
+ 
+ 	msi_msg_phys = virt_to_phys(&pcie->msi_msg);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch b/target/linux/generic/pending-5.10/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch
new file mode 100644
index 00000000000..083b93f4202
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch
@@ -0,0 +1,96 @@
+From fa73c200f181436eab859374657c53a73778d8ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 26 Mar 2021 17:35:44 +0100
+Subject: [PATCH] PCI: aardvark: Fix setting MSI address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+MSI address for receiving MSI interrupts needs to be correctly set before
+enabling processing of MSI interrupts.
+
+Move code for setting PCIE_MSI_ADDR_LOW_REG and PCIE_MSI_ADDR_HIGH_REG
+from advk_pcie_init_msi_irq_domain() to advk_pcie_setup_hw(), before
+enabling PCIE_CORE_CTRL2_MSI_ENABLE.
+
+After this we can remove the now unused member msi_msg, which was used
+only for MSI doorbell address. MSI address can be any address which cannot
+be used to DMA to. So change it to the address of the main struct advk_pcie.
+
+Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Acked-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling using generic MSI support")
+---
+ drivers/pci/controller/pci-aardvark.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 43db884c81a1..76a65c592b5c 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -284,7 +284,6 @@ struct advk_pcie {
+ 	raw_spinlock_t msi_irq_lock;
+ 	DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
+ 	struct mutex msi_used_lock;
+-	u16 msi_msg;
+ 	int link_gen;
+ 	struct pci_bridge_emul bridge;
+ 	struct gpio_desc *reset_gpio;
+@@ -479,6 +478,7 @@ static void advk_pcie_disable_ob_win(struct advk_pcie *pcie, u8 win_num)
+ 
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
++	phys_addr_t msi_addr;
+ 	u32 reg;
+ 	int i;
+ 
+@@ -567,6 +567,11 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ 	reg |= LANE_COUNT_1;
+ 	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+ 
++	/* Set MSI address */
++	msi_addr = virt_to_phys(pcie);
++	advk_writel(pcie, lower_32_bits(msi_addr), PCIE_MSI_ADDR_LOW_REG);
++	advk_writel(pcie, upper_32_bits(msi_addr), PCIE_MSI_ADDR_HIGH_REG);
++
+ 	/* Enable MSI */
+ 	reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
+ 	reg |= PCIE_CORE_CTRL2_MSI_ENABLE;
+@@ -1182,10 +1187,10 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
+ 					 struct msi_msg *msg)
+ {
+ 	struct advk_pcie *pcie = irq_data_get_irq_chip_data(data);
+-	phys_addr_t msi_msg = virt_to_phys(&pcie->msi_msg);
++	phys_addr_t msi_addr = virt_to_phys(pcie);
+ 
+-	msg->address_lo = lower_32_bits(msi_msg);
+-	msg->address_hi = upper_32_bits(msi_msg);
++	msg->address_lo = lower_32_bits(msi_addr);
++	msg->address_hi = upper_32_bits(msi_addr);
+ 	msg->data = data->hwirq;
+ }
+ 
+@@ -1344,18 +1349,10 @@ static struct msi_domain_info advk_msi_domain_info = {
+ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
+ {
+ 	struct device *dev = &pcie->pdev->dev;
+-	phys_addr_t msi_msg_phys;
+ 
+ 	raw_spin_lock_init(&pcie->msi_irq_lock);
+ 	mutex_init(&pcie->msi_used_lock);
+ 
+-	msi_msg_phys = virt_to_phys(&pcie->msi_msg);
+-
+-	advk_writel(pcie, lower_32_bits(msi_msg_phys),
+-		    PCIE_MSI_ADDR_LOW_REG);
+-	advk_writel(pcie, upper_32_bits(msi_msg_phys),
+-		    PCIE_MSI_ADDR_HIGH_REG);
+-
+ 	pcie->msi_inner_domain =
+ 		irq_domain_add_linear(NULL, MSI_IRQ_NUM,
+ 				      &advk_msi_domain_ops, pcie);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0012-PCI-aardvark-Enable-MSI-X-support.patch b/target/linux/generic/pending-5.10/850-0012-PCI-aardvark-Enable-MSI-X-support.patch
new file mode 100644
index 00000000000..d5d40054452
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0012-PCI-aardvark-Enable-MSI-X-support.patch
@@ -0,0 +1,43 @@
+From 735a4ac9782b96fbe1543c578aa8334364f21abd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 2 Apr 2021 14:05:24 +0200
+Subject: [PATCH] PCI: aardvark: Enable MSI-X support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+According to PCI 3.0 specification, sending both MSI and MSI-X interrupts
+is done by DWORD memory write operation to doorbell message address. The
+write operation for MSI has zero upper 16 bits and the MSI interrupt number
+in the lower 16 bits, while the write operation for MSI-X contains a 32-bit
+value from MSI-X table.
+
+Since the driver only uses interrupt numbers from range 0..31, the upper
+16 bits of the DWORD memory write operation to doorbell message address
+are zero even for MSI-X interrupts. Thus we can enable MSI-X interrupts.
+
+Testing proves that kernel can correctly receive MSI-X interrupts from PCIe
+cards which supports both MSI and MSI-X interrupts.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 76a65c592b5c..e6cfee3b41a2 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1342,7 +1342,7 @@ static struct irq_chip advk_msi_irq_chip = {
+ 
+ static struct msi_domain_info advk_msi_domain_info = {
+ 	.flags	= MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+-		  MSI_FLAG_MULTI_PCI_MSI,
++		  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+ 	.chip	= &advk_msi_irq_chip,
+ };
+ 
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch b/target/linux/generic/pending-5.10/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch
new file mode 100644
index 00000000000..9b15b7917e7
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch
@@ -0,0 +1,105 @@
+From 7f3e55a3890fa26d15e2e4e90213962d1a7f6df9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 12 Feb 2021 20:32:55 +0100
+Subject: [PATCH] PCI: aardvark: Add support for ERR interrupt on emulated
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+ERR interrupt is triggered when corresponding bit is unmasked in both ISR0
+and PCI_EXP_DEVCTL registers. Unmasking ERR bits in PCI_EXP_DEVCTL register
+is not enough. This means that currently the ERR interrupt is never
+triggered.
+
+Unmask ERR bits in ISR0 register at driver probe time. ERR interrupt is not
+triggered until ERR bits are unmasked also in PCI_EXP_DEVCTL register,
+which is done by AER driver. So it is safe to unconditionally unmask all
+ERR bits in aardvark probe.
+
+Aardvark HW sets PCI_ERR_ROOT_AER_IRQ to zero and when corresponding bits
+in ISR0 and PCI_EXP_DEVCTL are enabled, the HW triggers a generic interrupt
+on GIC. Chain this interrupt to PCIe interrupt 0 with
+generic_handle_domain_irq() to allow processing of ERR interrupts.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 36 ++++++++++++++++++++++++++-
+ 1 file changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index e6cfee3b41a2..7956b103d3c7 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -97,6 +97,10 @@
+ #define PCIE_MSG_PM_PME_MASK			BIT(7)
+ #define PCIE_ISR0_MASK_REG			(CONTROL_BASE_ADDR + 0x44)
+ #define     PCIE_ISR0_MSI_INT_PENDING		BIT(24)
++#define     PCIE_ISR0_CORR_ERR			BIT(11)
++#define     PCIE_ISR0_NFAT_ERR			BIT(12)
++#define     PCIE_ISR0_FAT_ERR			BIT(13)
++#define     PCIE_ISR0_ERR_MASK			GENMASK(13, 11)
+ #define     PCIE_ISR0_INTX_ASSERT(val)		BIT(16 + (val))
+ #define     PCIE_ISR0_INTX_DEASSERT(val)	BIT(20 + (val))
+ #define     PCIE_ISR0_ALL_MASK			GENMASK(31, 0)
+@@ -785,11 +789,15 @@ advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
+ 	case PCI_INTERRUPT_LINE: {
+ 		/*
+ 		 * From the whole 32bit register we support reading from HW only
+-		 * one bit: PCI_BRIDGE_CTL_BUS_RESET.
++		 * two bits: PCI_BRIDGE_CTL_BUS_RESET and PCI_BRIDGE_CTL_SERR.
+ 		 * Other bits are retrieved only from emulated config buffer.
+ 		 */
+ 		__le32 *cfgspace = (__le32 *)&bridge->conf;
+ 		u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
++		if (advk_readl(pcie, PCIE_ISR0_MASK_REG) & PCIE_ISR0_ERR_MASK)
++			val &= ~(PCI_BRIDGE_CTL_SERR << 16);
++		else
++			val |= PCI_BRIDGE_CTL_SERR << 16;
+ 		if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN)
+ 			val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
+ 		else
+@@ -815,6 +823,19 @@ advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+ 		break;
+ 
+ 	case PCI_INTERRUPT_LINE:
++		/*
++		 * According to Figure 6-3: Pseudo Logic Diagram for Error
++		 * Message Controls in PCIe base specification, SERR# Enable bit
++		 * in Bridge Control register enable receiving of ERR_* messages
++		 */
++		if (mask & (PCI_BRIDGE_CTL_SERR << 16)) {
++			u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++			if (new & (PCI_BRIDGE_CTL_SERR << 16))
++				val &= ~PCIE_ISR0_ERR_MASK;
++			else
++				val |= PCIE_ISR0_ERR_MASK;
++			advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
++		}
+ 		if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
+ 			u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG);
+ 			if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
+@@ -1464,6 +1485,19 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ 	isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
+ 	isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
+ 
++	/* Process ERR interrupt */
++	if (isr0_status & PCIE_ISR0_ERR_MASK) {
++		advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG);
++
++		/*
++		 * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use
++		 * PCIe interrupt 0
++		 */
++		virq = irq_find_mapping(pcie->irq_domain, 0);
++		if (generic_handle_irq(virq) == -EINVAL)
++			dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n");
++	}
++
+ 	/* Process MSI interrupts */
+ 	if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
+ 		advk_pcie_handle_msi(pcie);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch b/target/linux/generic/pending-5.10/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch
new file mode 100644
index 00000000000..5b0d7b341a6
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch
@@ -0,0 +1,49 @@
+From 5f354992eeef9a51c67796dc9f7f578d3584baa2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Wed, 8 Dec 2021 05:57:54 +0100
+Subject: [PATCH] PCI: aardvark: Fix reading PCI_EXP_RTSTA_PME bit on emulated
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The emulated bridge returns incorrect value for PCI_EXP_RTSTA register
+during readout in advk_pci_bridge_emul_pcie_conf_read() function: the
+correct bit is BIT(16), but we are setting BIT(23), because the code
+does
+  *value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16
+where
+  PCIE_MSG_PM_PME_MASK
+is
+  BIT(7).
+
+The code should probably have been something like
+  *value = (!!(isr0 & PCIE_MSG_PM_PME_MASK)) << 16,
+but we are better of using an if() and using the proper macro for this
+bit.
+
+Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 7956b103d3c7..44d9c8c4d258 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -874,7 +874,9 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+ 	case PCI_EXP_RTSTA: {
+ 		u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
+ 		u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
+-		*value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16);
++		*value = msglog >> 16;
++		if (isr0 & PCIE_MSG_PM_PME_MASK)
++			*value |= PCI_EXP_RTSTA_PME;
+ 		return PCI_BRIDGE_EMUL_HANDLED;
+ 	}
+ 
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch b/target/linux/generic/pending-5.10/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch
new file mode 100644
index 00000000000..52af732c445
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch
@@ -0,0 +1,57 @@
+From 3fe0073d116d9902df08761c1cf0d733dd4c38fc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Wed, 8 Dec 2021 06:03:50 +0100
+Subject: [PATCH] PCI: aardvark: Optimize writing PCI_EXP_RTCTL_PMEIE and
+ PCI_EXP_RTSTA_PME on emulated bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+To optimize advk_pci_bridge_emul_pcie_conf_write() code, touch
+PCIE_ISR0_REG and PCIE_ISR0_MASK_REG registers only when it is really
+needed, when processing PCI_EXP_RTCTL_PMEIE and PCI_EXP_RTSTA_PME bits.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 44d9c8c4d258..efd7e53b5e06 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -933,19 +933,21 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ 			advk_pcie_wait_for_retrain(pcie);
+ 		break;
+ 
+-	case PCI_EXP_RTCTL: {
++	case PCI_EXP_RTCTL:
+ 		/* Only mask/unmask PME interrupt */
+-		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) &
+-			~PCIE_MSG_PM_PME_MASK;
+-		if ((new & PCI_EXP_RTCTL_PMEIE) == 0)
+-			val |= PCIE_MSG_PM_PME_MASK;
+-		advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
++		if (mask & PCI_EXP_RTCTL_PMEIE) {
++			u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++			if (new & PCI_EXP_RTCTL_PMEIE)
++				val &= ~PCIE_MSG_PM_PME_MASK;
++			else
++				val |= PCIE_MSG_PM_PME_MASK;
++			advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
++		}
+ 		break;
+-	}
+ 
+ 	case PCI_EXP_RTSTA:
+-		new = (new & PCI_EXP_RTSTA_PME) >> 9;
+-		advk_writel(pcie, new, PCIE_ISR0_REG);
++		if (new & PCI_EXP_RTSTA_PME)
++			advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
+ 		break;
+ 
+ 	case PCI_EXP_DEVCTL:
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch b/target/linux/generic/pending-5.10/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch
new file mode 100644
index 00000000000..76ed7e60a4e
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch
@@ -0,0 +1,52 @@
+From 7acd8ef92e8789e10b5d736d73cea3b625087f26 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Wed, 8 Dec 2021 06:07:44 +0100
+Subject: [PATCH] PCI: aardvark: Add support for PME interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently enabling PCI_EXP_RTSTA_PME bit in PCI_EXP_RTCTL register does
+nothing. This is because PCIe PME driver expects to receive PCIe interrupt
+defined in PCI_EXP_FLAGS_IRQ register, but aardvark hardware does not
+trigger PCIe INTx/MSI interrupt for PME event, rather it triggers custom
+aardvark interrupt which this driver is not processing yet.
+
+Fix this issue by handling PME interrupt in advk_pcie_handle_int() and
+chaining it to PCIe interrupt 0 with generic_handle_domain_irq() (since
+aardvark sets PCI_EXP_FLAGS_IRQ to zero). With this change PCIe PME driver
+finally starts receiving PME interrupt.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index efd7e53b5e06..e2b66b0e8fb3 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1489,6 +1489,19 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ 	isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
+ 	isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
+ 
++	/* Process PME interrupt */
++	if (isr0_status & PCIE_MSG_PM_PME_MASK) {
++		/*
++		 * Do not clear PME interrupt bit in ISR0, it is cleared by IRQ
++		 * receiver by writing to the PCI_EXP_RTSTA register of emulated
++		 * root bridge. Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ,
++		 * so use PCIe interrupt 0.
++		 */
++		virq = irq_find_mapping(pcie->irq_domain, 0);
++		if (generic_handle_irq(virq) == -EINVAL)
++			dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
++	}
++
+ 	/* Process ERR interrupt */
+ 	if (isr0_status & PCIE_ISR0_ERR_MASK) {
+ 		advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch b/target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch
new file mode 100644
index 00000000000..692d4ee5557
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch
@@ -0,0 +1,178 @@
+From 68727b545332327b4c2f9c0f8d006be8970e7832 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Fri, 19 Feb 2021 14:22:22 +0100
+Subject: [PATCH] PCI: aardvark: Fix support for PME requester on emulated
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Enable aardvark PME interrupt unconditionally by unmasking it and read PME
+requester ID to emulated bridge config space immediately after receiving
+interrupt.
+
+PME requester ID is stored in the PCIE_MSG_LOG_REG register, which contains
+the last inbound message. So when new inbound message is received by HW
+(including non-PM), the content in PCIE_MSG_LOG_REG register is replaced by
+a new value.
+
+PCIe specification mandates that subsequent PMEs are kept pending until the
+PME Status Register bit is cleared by software by writing a 1b.
+
+Support for masking/unmasking PME interrupt on emulated bridge via
+PCI_EXP_RTCTL_PMEIE bit is now implemented only in emulated bridge config
+space, to ensure that we do not miss any aardvark PME interrupt.
+
+Reading of PCI_EXP_RTCAP and PCI_EXP_RTSTA registers is simplified as final
+value is now always stored into emulated bridge config space by the
+interrupt handler, so there is no need to implement support for these
+registers in read_pcie callback.
+
+Clearing of W1C bit PCI_EXP_RTSTA_PME is now also simplified as it is done
+by pci-bridge-emul.c code for emulated bridge config space. So there is no
+need to implement support for clearing this bit in write_pcie callback.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 94 +++++++++++++++------------
+ 1 file changed, 52 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index e2b66b0e8fb3..85a632537b70 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -597,6 +597,11 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ 	reg &= ~PCIE_ISR0_MSI_INT_PENDING;
+ 	advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
+ 
++	/* Unmask PME interrupt for processing of PME requester */
++	reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
++	reg &= ~PCIE_MSG_PM_PME_MASK;
++	advk_writel(pcie, reg, PCIE_ISR0_MASK_REG);
++
+ 	/* Enable summary interrupt for GIC SPI source */
+ 	reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
+ 	advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG);
+@@ -863,22 +868,11 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+ 		*value = PCI_EXP_SLTSTA_PDS << 16;
+ 		return PCI_BRIDGE_EMUL_HANDLED;
+ 
+-	case PCI_EXP_RTCTL: {
+-		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+-		*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
+-		*value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE;
+-		*value |= PCI_EXP_RTCAP_CRSVIS << 16;
+-		return PCI_BRIDGE_EMUL_HANDLED;
+-	}
+-
+-	case PCI_EXP_RTSTA: {
+-		u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
+-		u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
+-		*value = msglog >> 16;
+-		if (isr0 & PCIE_MSG_PM_PME_MASK)
+-			*value |= PCI_EXP_RTSTA_PME;
+-		return PCI_BRIDGE_EMUL_HANDLED;
+-	}
++	/*
++	 * PCI_EXP_RTCTL and PCI_EXP_RTSTA are also supported, but do not need
++	 * to be handled here, because their values are stored in emulated
++	 * config space buffer, and we read them from there when needed.
++	 */
+ 
+ 	case PCI_EXP_LNKCAP: {
+ 		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
+@@ -933,22 +927,19 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ 			advk_pcie_wait_for_retrain(pcie);
+ 		break;
+ 
+-	case PCI_EXP_RTCTL:
+-		/* Only mask/unmask PME interrupt */
+-		if (mask & PCI_EXP_RTCTL_PMEIE) {
+-			u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
+-			if (new & PCI_EXP_RTCTL_PMEIE)
+-				val &= ~PCIE_MSG_PM_PME_MASK;
+-			else
+-				val |= PCIE_MSG_PM_PME_MASK;
+-			advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
+-		}
++	case PCI_EXP_RTCTL: {
++		u16 rootctl = le16_to_cpu(bridge->pcie_conf.rootctl);
++		/* Only emulation of PMEIE and CRSSVE bits is provided */
++		rootctl &= PCI_EXP_RTCTL_PMEIE | PCI_EXP_RTCTL_CRSSVE;
++		bridge->pcie_conf.rootctl = cpu_to_le16(rootctl);
+ 		break;
++	}
+ 
+-	case PCI_EXP_RTSTA:
+-		if (new & PCI_EXP_RTSTA_PME)
+-			advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
+-		break;
++	/*
++	 * PCI_EXP_RTSTA is also supported, but does not need to be handled
++	 * here, because its value is stored in emulated config space buffer,
++	 * and we write it there when needed.
++	 */
+ 
+ 	case PCI_EXP_DEVCTL:
+ 	case PCI_EXP_DEVCTL2:
+@@ -1450,6 +1441,34 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
+ 	irq_domain_remove(pcie->irq_domain);
+ }
+ 
++static void advk_pcie_handle_pme(struct advk_pcie *pcie)
++{
++	u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16;
++	int virq;
++
++	advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG);
++
++	/*
++	 * PCIE_MSG_LOG_REG contains the last inbound message, so store
++	 * the requester ID only when PME was not asserted yet.
++	 * Also do not trigger PME interrupt when PME is still asserted.
++	 */
++	if (!(le32_to_cpu(pcie->bridge.pcie_conf.rootsta) & PCI_EXP_RTSTA_PME)) {
++		pcie->bridge.pcie_conf.rootsta = cpu_to_le32(requester | PCI_EXP_RTSTA_PME);
++
++		/*
++		 * Trigger PME interrupt only if PMEIE bit in Root Control is set.
++		 * Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, so use PCIe interrupt 0.
++		 */
++		if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE))
++			return;
++
++		virq = irq_find_mapping(pcie->irq_domain, 0);
++		if (generic_handle_irq(virq) == -EINVAL)
++			dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
++	}
++}
++
+ static void advk_pcie_handle_msi(struct advk_pcie *pcie)
+ {
+ 	u32 msi_val, msi_mask, msi_status, msi_idx;
+@@ -1489,18 +1508,9 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ 	isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
+ 	isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
+ 
+-	/* Process PME interrupt */
+-	if (isr0_status & PCIE_MSG_PM_PME_MASK) {
+-		/*
+-		 * Do not clear PME interrupt bit in ISR0, it is cleared by IRQ
+-		 * receiver by writing to the PCI_EXP_RTSTA register of emulated
+-		 * root bridge. Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ,
+-		 * so use PCIe interrupt 0.
+-		 */
+-		virq = irq_find_mapping(pcie->irq_domain, 0);
+-		if (generic_handle_irq(virq) == -EINVAL)
+-			dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
+-	}
++	/* Process PME interrupt as the first one to do not miss PME requester id */
++	if (isr0_status & PCIE_MSG_PM_PME_MASK)
++		advk_pcie_handle_pme(pcie);
+ 
+ 	/* Process ERR interrupt */
+ 	if (isr0_status & PCIE_ISR0_ERR_MASK) {
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch b/target/linux/generic/pending-5.10/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch
new file mode 100644
index 00000000000..46fb548d928
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch
@@ -0,0 +1,166 @@
+From db305233136f5aa2444a8287a279384e8458c458 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 1 Apr 2021 20:12:48 +0200
+Subject: [PATCH] PCI: aardvark: Use separate INTA interrupt for emulated root
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Emulated root bridge currently provides only one Legacy INTA interrupt
+which is used for reporting PCIe PME and ERR events and handled by kernel
+PCIe PME and AER drivers.
+
+Aardvark HW reports these PME and ERR events separately, so there is no
+need to mix real INTA interrupt and emulated INTA interrupt for PCIe PME
+and AER drivers.
+
+Register a new advk-RP (as in Root Port) irq chip and a new irq domain
+for emulated root bridge and use this new separate irq domain for
+providing INTA interrupt from emulated root bridge for PME and ERR events.
+
+The real INTA interrupt from real devices is now separate.
+
+A custom map_irq callback function on PCI host bridge structure is used to
+allocate IRQ mapping for emulated root bridge from new irq domain. Original
+callback of_irq_parse_and_map_pci() is used for all other devices as before.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 69 ++++++++++++++++++++++++++-
+ 1 file changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 85a632537b70..b6e723c5725c 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -280,6 +280,7 @@ struct advk_pcie {
+ 	} wins[OB_WIN_COUNT];
+ 	u8 wins_count;
+ 	int irq;
++	struct irq_domain *rp_irq_domain;
+ 	struct irq_domain *irq_domain;
+ 	struct irq_chip irq_chip;
+ 	raw_spinlock_t irq_lock;
+@@ -1441,6 +1442,44 @@ static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
+ 	irq_domain_remove(pcie->irq_domain);
+ }
+ 
++static struct irq_chip advk_rp_irq_chip = {
++	.name = "advk-RP",
++};
++
++static int advk_pcie_rp_irq_map(struct irq_domain *h,
++				unsigned int virq, irq_hw_number_t hwirq)
++{
++	struct advk_pcie *pcie = h->host_data;
++
++	irq_set_chip_and_handler(virq, &advk_rp_irq_chip, handle_simple_irq);
++	irq_set_chip_data(virq, pcie);
++
++	return 0;
++}
++
++static const struct irq_domain_ops advk_pcie_rp_irq_domain_ops = {
++	.map = advk_pcie_rp_irq_map,
++	.xlate = irq_domain_xlate_onecell,
++};
++
++static int advk_pcie_init_rp_irq_domain(struct advk_pcie *pcie)
++{
++	pcie->rp_irq_domain = irq_domain_add_linear(NULL, 1,
++						    &advk_pcie_rp_irq_domain_ops,
++						    pcie);
++	if (!pcie->rp_irq_domain) {
++		dev_err(&pcie->pdev->dev, "Failed to add Root Port IRQ domain\n");
++		return -ENOMEM;
++	}
++
++	return 0;
++}
++
++static void advk_pcie_remove_rp_irq_domain(struct advk_pcie *pcie)
++{
++	irq_domain_remove(pcie->rp_irq_domain);
++}
++
+ static void advk_pcie_handle_pme(struct advk_pcie *pcie)
+ {
+ 	u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16;
+@@ -1463,7 +1502,7 @@ static void advk_pcie_handle_pme(struct advk_pcie *pcie)
+ 		if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE))
+ 			return;
+ 
+-		virq = irq_find_mapping(pcie->irq_domain, 0);
++		virq = irq_find_mapping(pcie->rp_irq_domain, 0);
+ 		if (generic_handle_irq(virq) == -EINVAL)
+ 			dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
+ 	}
+@@ -1520,7 +1559,7 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
+ 		 * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use
+ 		 * PCIe interrupt 0
+ 		 */
+-		virq = irq_find_mapping(pcie->irq_domain, 0);
++		virq = irq_find_mapping(pcie->rp_irq_domain, 0);
+ 		if (generic_handle_irq(virq) == -EINVAL)
+ 			dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n");
+ 	}
+@@ -1566,6 +1605,21 @@ static void advk_pcie_irq_handler(struct irq_desc *desc)
+ 	chained_irq_exit(chip, desc);
+ }
+ 
++static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	struct advk_pcie *pcie = dev->bus->sysdata;
++
++	/*
++	 * Emulated root bridge has its own emulated irq chip and irq domain.
++	 * Argument pin is the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) and
++	 * hwirq for irq_create_mapping() is indexed from zero.
++	 */
++	if (pci_is_root_bus(dev->bus))
++		return irq_create_mapping(pcie->rp_irq_domain, pin - 1);
++	else
++		return of_irq_parse_and_map_pci(dev, slot, pin);
++}
++
+ static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie)
+ {
+ 	phy_power_off(pcie->phy);
+@@ -1769,14 +1823,24 @@ static int advk_pcie_probe(struct platform_device *pdev)
+ 		return ret;
+ 	}
+ 
++	ret = advk_pcie_init_rp_irq_domain(pcie);
++	if (ret) {
++		dev_err(dev, "Failed to initialize irq\n");
++		advk_pcie_remove_msi_irq_domain(pcie);
++		advk_pcie_remove_irq_domain(pcie);
++		return ret;
++	}
++
+ 	irq_set_chained_handler_and_data(pcie->irq, advk_pcie_irq_handler, pcie);
+ 
+ 	bridge->sysdata = pcie;
+ 	bridge->ops = &advk_pcie_ops;
++	bridge->map_irq = advk_pcie_map_irq;
+ 
+ 	ret = pci_host_probe(bridge);
+ 	if (ret < 0) {
+ 		irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
++		advk_pcie_remove_rp_irq_domain(pcie);
+ 		advk_pcie_remove_msi_irq_domain(pcie);
+ 		advk_pcie_remove_irq_domain(pcie);
+ 		return ret;
+@@ -1828,6 +1892,7 @@ static int advk_pcie_remove(struct platform_device *pdev)
+ 	irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
+ 
+ 	/* Remove IRQ domains */
++	advk_pcie_remove_rp_irq_domain(pcie);
+ 	advk_pcie_remove_msi_irq_domain(pcie);
+ 	advk_pcie_remove_irq_domain(pcie);
+ 
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch b/target/linux/generic/pending-5.10/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch
new file mode 100644
index 00000000000..d9a6de0dc90
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch
@@ -0,0 +1,34 @@
+From 8c9eef96e24f34ff8b62b230700416b822691a37 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 1 Apr 2021 14:24:12 +0200
+Subject: [PATCH] PCI: aardvark: Remove irq_mask_ack callback for INTx
+ interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Callback for irq_mask_ack is the same as for irq_mask. As there is no
+special handling for irq_ack, there is no need to define irq_mask_ack too.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Acked-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index b6e723c5725c..99469e3dc945 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1420,7 +1420,6 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
+ 	}
+ 
+ 	irq_chip->irq_mask = advk_pcie_irq_mask;
+-	irq_chip->irq_mask_ack = advk_pcie_irq_mask;
+ 	irq_chip->irq_unmask = advk_pcie_irq_unmask;
+ 
+ 	pcie->irq_domain =
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch b/target/linux/generic/pending-5.10/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch
new file mode 100644
index 00000000000..e407fc26f9d
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch
@@ -0,0 +1,32 @@
+From dc01fca5a9d9c09ce9a3fb2bc2e7715c37ff3bd9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 1 Apr 2021 14:30:06 +0200
+Subject: [PATCH] PCI: aardvark: Don't mask irq when mapping
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By default, all Legacy INTx interrupts are masked, so there is no need to
+mask this interrupt during irq_map callback.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 99469e3dc945..e090276ef902 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1337,7 +1337,6 @@ static int advk_pcie_irq_map(struct irq_domain *h,
+ {
+ 	struct advk_pcie *pcie = h->host_data;
+ 
+-	advk_pcie_irq_mask(irq_get_irq_data(virq));
+ 	irq_set_status_flags(virq, IRQ_LEVEL);
+ 	irq_set_chip_and_handler(virq, &pcie->irq_chip,
+ 				 handle_level_irq);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch b/target/linux/generic/pending-5.10/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch
new file mode 100644
index 00000000000..62e748d1497
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch
@@ -0,0 +1,33 @@
+From a511c99262ce19ee06908d27212b39ec4c5aeb17 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Wed, 8 Dec 2021 04:40:29 +0100
+Subject: [PATCH] PCI: aardvark: Drop __maybe_unused from
+ advk_pcie_disable_phy()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This function is now always used in driver remove method, drop the
+__maybe_unused attribute.
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index e090276ef902..aa5629b8b5c9 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1618,7 +1618,7 @@ static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+ 		return of_irq_parse_and_map_pci(dev, slot, pin);
+ }
+ 
+-static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie)
++static void advk_pcie_disable_phy(struct advk_pcie *pcie)
+ {
+ 	phy_power_off(pcie->phy);
+ 	phy_exit(pcie->phy);
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch b/target/linux/generic/pending-5.10/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch
new file mode 100644
index 00000000000..5a2f065125d
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch
@@ -0,0 +1,40 @@
+From bafda858364003a70b9cda84282f9761587f8033 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Mon, 10 Jan 2022 00:47:38 +0100
+Subject: [PATCH] PCI: aardvark: Update comment about link going down after
+ link-up
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Update the comment about what happens when link goes down after we have
+checked for link-up. If a PIO request is done while link-down, we have
+a serious problem.
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index aa5629b8b5c9..3c0b6b931061 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1003,8 +1003,12 @@ static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
+ 		return false;
+ 
+ 	/*
+-	 * If the link goes down after we check for link-up, nothing bad
+-	 * happens but the config access times out.
++	 * If the link goes down after we check for link-up, we have a problem:
++	 * if a PIO request is executed while link-down, the whole controller
++	 * gets stuck in a non-functional state, and even after link comes up
++	 * again, PIO requests won't work anymore, and a reset of the whole PCIe
++	 * controller is needed. Therefore we need to prevent sending PIO
++	 * requests while the link is down.
+ 	 */
+ 	if (!pci_is_root_bus(bus) && !advk_pcie_link_up(pcie))
+ 		return false;
+-- 
+2.34.1
+
diff --git a/target/linux/generic/pending-5.10/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.10/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch
new file mode 100644
index 00000000000..2951529df73
--- /dev/null
+++ b/target/linux/generic/pending-5.10/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch
@@ -0,0 +1,107 @@
+From 663b9f99bb35dbc0c7b685f71ee3668a60d31320 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Mon, 10 Jan 2022 02:02:00 +0100
+Subject: [PATCH] PCI: aardvark: Make main irq_chip structure a static driver
+ structure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Marc Zyngier says [1] that we should use struct irq_chip as a global
+static struct in the driver. Even though the structure currently
+contains a dynamic member (parent_device), Marc says [2] that he plans
+to kill it and make the structure completely static.
+
+We have already converted others irq_chip structures in this driver in
+this way, but we omitted this one because the .name member is
+dynamically created from device's name, and the name is displayed in
+sysfs, so changing it would break sysfs ABI.
+
+The rationale for changing the name (to "advk-INT") in spite of sysfs
+ABI, and thus allowing to convert to a static structure, is that after
+the other changes we made in this series, the IRQ chip is basically
+something different: it no logner generates ERR and PME interrupts (they
+are generated by emulated bridge's rp_irq_chip).
+
+[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/
+[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 25 +++++++------------------
+ 1 file changed, 7 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 3c0b6b931061..319dd830e36e 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -282,7 +282,6 @@ struct advk_pcie {
+ 	int irq;
+ 	struct irq_domain *rp_irq_domain;
+ 	struct irq_domain *irq_domain;
+-	struct irq_chip irq_chip;
+ 	raw_spinlock_t irq_lock;
+ 	struct irq_domain *msi_domain;
+ 	struct irq_domain *msi_inner_domain;
+@@ -1336,14 +1335,19 @@ static void advk_pcie_irq_unmask(struct irq_data *d)
+ 	raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
+ }
+ 
++static struct irq_chip advk_irq_chip = {
++	.name		= "advk-INT",
++	.irq_mask	= advk_pcie_irq_mask,
++	.irq_unmask	= advk_pcie_irq_unmask,
++};
++
+ static int advk_pcie_irq_map(struct irq_domain *h,
+ 			     unsigned int virq, irq_hw_number_t hwirq)
+ {
+ 	struct advk_pcie *pcie = h->host_data;
+ 
+ 	irq_set_status_flags(virq, IRQ_LEVEL);
+-	irq_set_chip_and_handler(virq, &pcie->irq_chip,
+-				 handle_level_irq);
++	irq_set_chip_and_handler(virq, &advk_irq_chip, handle_level_irq);
+ 	irq_set_chip_data(virq, pcie);
+ 
+ 	return 0;
+@@ -1402,7 +1406,6 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
+ 	struct device *dev = &pcie->pdev->dev;
+ 	struct device_node *node = dev->of_node;
+ 	struct device_node *pcie_intc_node;
+-	struct irq_chip *irq_chip;
+ 	int ret = 0;
+ 
+ 	raw_spin_lock_init(&pcie->irq_lock);
+@@ -1413,28 +1416,14 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
+ 		return -ENODEV;
+ 	}
+ 
+-	irq_chip = &pcie->irq_chip;
+-
+-	irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq",
+-					dev_name(dev));
+-	if (!irq_chip->name) {
+-		ret = -ENOMEM;
+-		goto out_put_node;
+-	}
+-
+-	irq_chip->irq_mask = advk_pcie_irq_mask;
+-	irq_chip->irq_unmask = advk_pcie_irq_unmask;
+-
+ 	pcie->irq_domain =
+ 		irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+ 				      &advk_pcie_irq_domain_ops, pcie);
+ 	if (!pcie->irq_domain) {
+ 		dev_err(dev, "Failed to get a INTx IRQ domain\n");
+ 		ret = -ENOMEM;
+-		goto out_put_node;
+ 	}
+ 
+-out_put_node:
+ 	of_node_put(pcie_intc_node);
+ 	return ret;
+ }
+-- 
+2.34.1
+
-- 
GitLab