--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:28 +0200
+Subject: PCI: aardvark: Add support for DEVCAP2, DEVCTL2, LNKCAP2 and LNKCTL2 registers on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-4-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1d3e170344dff2cef8827db6c09909b78cbc11d7 upstream.
+
+PCI aardvark hardware supports access to DEVCAP2, DEVCTL2, LNKCAP2 and
+LNKCTL2 configuration registers of PCIe core via PCIE_CORE_PCIEXP_CAP.
+Export them via emulated software root bridge.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-4-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -876,8 +876,13 @@ advk_pci_bridge_emul_pcie_conf_read(stru
+
+ case PCI_EXP_DEVCAP:
+ case PCI_EXP_DEVCTL:
++ case PCI_EXP_DEVCAP2:
++ case PCI_EXP_DEVCTL2:
++ case PCI_EXP_LNKCAP2:
++ case PCI_EXP_LNKCTL2:
+ *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
+ return PCI_BRIDGE_EMUL_HANDLED;
++
+ default:
+ return PCI_BRIDGE_EMUL_NOT_HANDLED;
+ }
+@@ -891,10 +896,6 @@ advk_pci_bridge_emul_pcie_conf_write(str
+ struct advk_pcie *pcie = bridge->data;
+
+ switch (reg) {
+- case PCI_EXP_DEVCTL:
+- advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+- break;
+-
+ case PCI_EXP_LNKCTL:
+ advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+ if (new & PCI_EXP_LNKCTL_RL)
+@@ -916,6 +917,12 @@ advk_pci_bridge_emul_pcie_conf_write(str
+ advk_writel(pcie, new, PCIE_ISR0_REG);
+ break;
+
++ case PCI_EXP_DEVCTL:
++ case PCI_EXP_DEVCTL2:
++ case PCI_EXP_LNKCTL2:
++ advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
++ break;
++
+ default:
+ break;
+ }
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:47 +0200
+Subject: PCI: aardvark: Add support for ERR interrupt on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-23-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 3ebfefa396ebee21061fd5fa36073368ed2cd467 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-14-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 35 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 34 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -98,6 +98,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)
+@@ -778,11 +782,15 @@ advk_pci_bridge_emul_base_conf_read(stru
+ 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
+@@ -808,6 +816,19 @@ advk_pci_bridge_emul_base_conf_write(str
+ 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))
+@@ -1457,6 +1478,18 @@ static void advk_pcie_handle_int(struct
+ 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
++ */
++ if (generic_handle_domain_irq(pcie->irq_domain, 0) == -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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:44 +0200
+Subject: PCI: aardvark: Add support for masking MSI interrupts
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-20-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit e77d9c90691071769cd2b86ef097f7d07167dc3b upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-11-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 54 ++++++++++++++++++++++++++++++----
+ 1 file changed, 49 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -274,6 +274,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;
+@@ -570,12 +571,10 @@ static void advk_pcie_setup_hw(struct ad
+ 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);
+@@ -1193,10 +1192,52 @@ static int advk_msi_set_affinity(struct
+ 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,
+@@ -1286,7 +1327,9 @@ static const struct irq_domain_ops advk_
+ };
+
+ 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 = {
+@@ -1300,6 +1343,7 @@ static int advk_pcie_init_msi_irq_domain
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:49 +0200
+Subject: PCI: aardvark: Add support for PME interrupts
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-25-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 0fc75d87454195885bd1a81fc7e6ce92572b6109 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-17-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1480,6 +1480,18 @@ static void advk_pcie_handle_int(struct
+ 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.
++ */
++ if (generic_handle_domain_irq(pcie->irq_domain, 0) == -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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:34 +0200
+Subject: PCI: aardvark: Assert PERST# when unbinding driver
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-10-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1f54391be8ce0c981d312cb93acdc5608def576a upstream.
+
+Put the PCIe card into reset by asserting PERST# signal when unbinding
+driver. It doesn't make sense to leave the card working if it can't
+communicate with the host. This should also save some power.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-10-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1721,6 +1721,10 @@ static int advk_pcie_remove(struct platf
+ /* Free config space for emulated root bridge */
+ pci_bridge_emul_cleanup(&pcie->bridge);
+
++ /* Assert PERST# signal which prepares PCIe card for power down */
++ if (pcie->reset_gpio)
++ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
++
+ /* Disable outbound address windows mapping */
+ for (i = 0; i < OB_WIN_COUNT; i++)
+ advk_pcie_disable_ob_win(pcie, i);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:39 +0200
+Subject: PCI: aardvark: Check return value of generic_handle_domain_irq() when processing INTx IRQ
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-15-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 51f96e287c6f003d3bb29672811c757c5fbf0028 upstream.
+
+It is possible that we receive spurious INTx interrupt. Check for the
+return value of generic_handle_domain_irq() when processing INTx IRQ.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-6-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1429,7 +1429,9 @@ static void advk_pcie_handle_int(struct
+ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
+ PCIE_ISR1_REG);
+
+- generic_handle_domain_irq(pcie->irq_domain, i);
++ if (generic_handle_domain_irq(pcie->irq_domain, i) == -EINVAL)
++ dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n",
++ (char)i + 'A');
+ }
+ }
+
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:29 +0200
+Subject: PCI: aardvark: Clear all MSIs at setup
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-5-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 7d8dc1f7cd007a7ce94c5b4c20d63a8b8d6d7751 upstream.
+
+We already clear all the other interrupts (ISR0, ISR1, HOST_CTRL_INT).
+
+Define a new macro PCIE_MSI_ALL_MASK and do the same clearing for MSIs,
+to ensure that we don't start receiving spurious interrupts.
+
+Use this new mask in advk_pcie_handle_msi();
+
+Link: https://lore.kernel.org/r/20211130172913.9727-5-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -115,6 +115,7 @@
+ #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
+ #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
+ #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C)
++#define PCIE_MSI_ALL_MASK GENMASK(31, 0)
+ #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C)
+ #define PCIE_MSI_DATA_MASK GENMASK(15, 0)
+
+@@ -570,6 +571,7 @@ static void advk_pcie_setup_hw(struct ad
+ advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
+
+ /* Clear all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
+ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
+ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
+ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
+@@ -582,7 +584,7 @@ static void advk_pcie_setup_hw(struct ad
+ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
+
+ /* Unmask all MSIs */
+- advk_writel(pcie, 0, PCIE_MSI_MASK_REG);
++ advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
+
+ /* Enable summary interrupt for GIC SPI source */
+ reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
+@@ -1389,7 +1391,7 @@ static void advk_pcie_handle_msi(struct
+
+ msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
+ msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG);
+- msi_status = msi_val & ~msi_mask;
++ msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK);
+
+ for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) {
+ if (!(BIT(msi_idx) & msi_status))
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:30 +0200
+Subject: PCI: aardvark: Comment actions in driver remove method
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-6-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit a4ca7948e1d47275f8f3e5023243440c40561916 upstream.
+
+Add two more comments into the advk_pcie_remove() method.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-6-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1681,11 +1681,13 @@ static int advk_pcie_remove(struct platf
+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
+ int i;
+
++ /* Remove PCI bus with all devices */
+ pci_lock_rescan_remove();
+ pci_stop_root_bus(bridge->bus);
+ pci_remove_root_bus(bridge->bus);
+ pci_unlock_rescan_remove();
+
++ /* Remove IRQ domains */
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
+
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:31 +0200
+Subject: PCI: aardvark: Disable bus mastering when unbinding driver
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-7-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit a46f2f6dd4093438d9615dfbf5c0fea2a9835dba upstream.
+
+Ensure that after driver unbind PCIe cards are not able to forward
+memory and I/O requests in the upstream direction.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-7-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1679,6 +1679,7 @@ static int advk_pcie_remove(struct platf
+ {
+ struct advk_pcie *pcie = platform_get_drvdata(pdev);
+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ u32 val;
+ int i;
+
+ /* Remove PCI bus with all devices */
+@@ -1687,6 +1688,11 @@ static int advk_pcie_remove(struct platf
+ pci_remove_root_bus(bridge->bus);
+ pci_unlock_rescan_remove();
+
++ /* Disable Root Bridge I/O space, memory space and bus mastering */
++ val = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
++ val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++ advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG);
++
+ /* Remove IRQ domains */
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:36 +0200
+Subject: PCI: aardvark: Disable common PHY when unbinding driver
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-12-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit fdbbe242c15a8f2cd0e3ad8a56cd0a447b771d0d upstream.
+
+Disable the PCIe PHY when unbinding driver. This should save some power.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-12-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1734,6 +1734,9 @@ static int advk_pcie_remove(struct platf
+ for (i = 0; i < OB_WIN_COUNT; i++)
+ advk_pcie_disable_ob_win(pcie, i);
+
++ /* Disable phy */
++ advk_pcie_disable_phy(pcie);
++
+ return 0;
+ }
+
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:35 +0200
+Subject: PCI: aardvark: Disable link training when unbinding driver
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-11-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 759dec2e3dfdbd261c41d2279f04f2351c971a49 upstream.
+
+Disable link training circuit in driver unbind sequence. We want to
+leave link training in the same state as it was before the driver was
+probed.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-11-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1725,6 +1725,11 @@ static int advk_pcie_remove(struct platf
+ if (pcie->reset_gpio)
+ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
+
++ /* Disable link training */
++ val = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
++ val &= ~LINK_TRAINING_EN;
++ advk_writel(pcie, val, PCIE_CORE_CTRL0_REG);
++
+ /* Disable outbound address windows mapping */
+ for (i = 0; i < OB_WIN_COUNT; i++)
+ advk_pcie_disable_ob_win(pcie, i);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:53 +0200
+Subject: PCI: aardvark: Don't mask irq when mapping
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-29-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit befa71000160b39c1bf6cdfca6837bb5e9d372d7 upstream.
+
+By default, all Legacy INTx interrupts are masked, so there is no need to
+mask this interrupt during irq_map() callback.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-21-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1332,7 +1332,6 @@ static int advk_pcie_irq_map(struct irq_
+ {
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:54 +0200
+Subject: PCI: aardvark: Drop __maybe_unused from advk_pcie_disable_phy()
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-30-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit 0c36ab437e1d94b6628b006a1d48f05ea3b0b222 upstream.
+
+This function is now always used in driver remove method, drop the
+__maybe_unused attribute.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-22-kabel@kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1605,7 +1605,7 @@ static int advk_pcie_map_irq(const struc
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:46 +0200
+Subject: PCI: aardvark: Enable MSI-X support
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-22-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 754e449889b22fc3c34235e8836f08f51121d307 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-13-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1339,7 +1339,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,
+ };
+
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:33 +0200
+Subject: PCI: aardvark: Fix memory leak in driver unbind
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-9-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 2f040a17f5061457ae95035326d3159eddc1e5cc upstream.
+
+Free config space for emulated root bridge when unbinding driver to fix
+memory leak. Do it after disabling and masking all interrupts, since
+aardvark interrupt handler accesses config space of emulated root
+bridge.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-9-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1718,6 +1718,9 @@ static int advk_pcie_remove(struct platf
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
+
++ /* Free config space for emulated root bridge */
++ pci_bridge_emul_cleanup(&pcie->bridge);
++
+ /* Disable outbound address windows mapping */
+ for (i = 0; i < OB_WIN_COUNT; i++)
+ advk_pcie_disable_ob_win(pcie, i);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:45 +0200
+Subject: PCI: aardvark: Fix setting MSI address
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-21-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 46ad3dc4171b5ee1d12267d70112563d5760210a upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-12-kabel@kernel.org
+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>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling using generic MSI support")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -277,7 +277,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;
+@@ -472,6 +471,7 @@ static void advk_pcie_disable_ob_win(str
+
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
++ phys_addr_t msi_addr;
+ u32 reg;
+ int i;
+
+@@ -560,6 +560,11 @@ static void advk_pcie_setup_hw(struct ad
+ 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;
+@@ -1179,10 +1184,10 @@ static void advk_msi_irq_compose_msi_msg
+ 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;
+ }
+
+@@ -1341,18 +1346,10 @@ static struct msi_domain_info advk_msi_d
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:50 +0200
+Subject: PCI: aardvark: Fix support for PME requester on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-26-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 273ddd86d67694e3639e3bfe337a96d8861798b8 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-18-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 91 ++++++++++++++++++----------------
+ 1 file changed, 50 insertions(+), 41 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -590,6 +590,11 @@ static void advk_pcie_setup_hw(struct ad
+ 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);
+@@ -856,22 +861,11 @@ advk_pci_bridge_emul_pcie_conf_read(stru
+ *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);
+@@ -925,22 +919,19 @@ advk_pci_bridge_emul_pcie_conf_write(str
+ 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:
+@@ -1445,6 +1436,32 @@ static void advk_pcie_remove_irq_domain(
+ 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;
++
++ 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;
++
++ if (generic_handle_domain_irq(pcie->irq_domain, 0) == -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;
+@@ -1480,17 +1497,9 @@ static void advk_pcie_handle_int(struct
+ 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.
+- */
+- if (generic_handle_domain_irq(pcie->irq_domain, 0) == -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) {
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:40 +0200
+Subject: PCI: aardvark: Make MSI irq_chip structures static driver structures
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-16-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit c3cb8e51839adc0aaef478c47665443d02f5aa07 upstream.
+
+In [1] it was agreed 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), In [2] the plans to kill it
+and make the structure completely static were set out.
+
+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/
+
+Link: https://lore.kernel.org/r/20220110015018.26359-7-kabel@kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -274,8 +274,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;
+@@ -1194,6 +1192,12 @@ static int advk_msi_set_affinity(struct
+ 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)
+@@ -1210,7 +1214,7 @@ static int advk_msi_irq_domain_alloc(str
+
+ 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);
+
+@@ -1280,29 +1284,23 @@ static const struct irq_domain_ops advk_
+ .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);
+
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:41 +0200
+Subject: PCI: aardvark: Make msi_domain_info structure a static driver structure
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-17-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit 26bcd54e4a5cd51ec12d06fdc30e22863ed4c422 upstream.
+
+Make Aardvark's msi_domain_info structure into a private driver structure.
+Domain info is same for every potential instatination of a controller.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-8-kabel@kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -274,7 +274,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;
+@@ -1288,20 +1287,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),
+@@ -1317,7 +1316,8 @@ static int advk_pcie_init_msi_irq_domain
+
+ 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;
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:32 +0200
+Subject: PCI: aardvark: Mask all interrupts when unbinding driver
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-8-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 13bcdf07cb2ecff5d45d2c141df2539b15211448 upstream.
+
+Ensure that no interrupt can be triggered after driver unbind.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-8-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1693,6 +1693,27 @@ static int advk_pcie_remove(struct platf
+ val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG);
+
++ /* Disable MSI */
++ val = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
++ val &= ~PCIE_CORE_CTRL2_MSI_ENABLE;
++ advk_writel(pcie, val, PCIE_CORE_CTRL2_REG);
++
++ /* Clear MSI address */
++ advk_writel(pcie, 0, PCIE_MSI_ADDR_LOW_REG);
++ advk_writel(pcie, 0, PCIE_MSI_ADDR_HIGH_REG);
++
++ /* Mask all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_MASK_REG);
++
++ /* Clear all interrupts */
++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
++
+ /* Remove IRQ domains */
+ advk_pcie_remove_msi_irq_domain(pcie);
+ advk_pcie_remove_irq_domain(pcie);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:48 +0200
+Subject: PCI: aardvark: Optimize writing PCI_EXP_RTCTL_PMEIE and PCI_EXP_RTSTA_PME on emulated bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-24-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 7122bcb33295228c882c0aa32a04b2547beba2c3 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-16-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -925,19 +925,21 @@ advk_pci_bridge_emul_pcie_conf_write(str
+ 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:
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:43 +0200
+Subject: PCI: aardvark: Refactor unmasking summary MSI interrupt
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-19-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 4689c0916320f112a8a33f2689d3addc3262f02c upstream.
+
+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
+
+Link: https://lore.kernel.org/r/20220110015018.26359-10-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -571,15 +571,17 @@ static void advk_pcie_setup_hw(struct ad
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:52 +0200
+Subject: PCI: aardvark: Remove irq_mask_ack() callback for INTx interrupts
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-28-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit b08e5b53d17be58eb2311d6790a84fe2c200ee47 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-20-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1415,7 +1415,6 @@ static int advk_pcie_init_irq_domain(str
+ }
+
+ 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 =
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:37 +0200
+Subject: PCI: aardvark: Replace custom PCIE_CORE_INT_* macros with PCI_INTERRUPT_*
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-13-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1d86abf1f89672a70f2ab65f6000299feb1f1781 upstream.
+
+Header file linux/pci.h defines enum pci_interrupt_pin with corresponding
+PCI_INTERRUPT_* values.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-2-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -38,10 +38,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)
+@@ -961,7 +957,7 @@ static int advk_sw_pci_bridge_init(struc
+ 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;
+
+ /* Aardvark HW provides PCIe Capability structure in version 2 */
+ bridge->pcie_conf.cap = cpu_to_le16(2);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:38 +0200
+Subject: PCI: aardvark: Rewrite IRQ code to chained IRQ handler
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-14-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1571d67dc190e50c6c56e8f88cdc39f7cc53166e upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-5-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 48 ++++++++++++++++++----------------
+ 1 file changed, 26 insertions(+), 22 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -268,6 +268,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;
+@@ -1432,21 +1433,26 @@ static void advk_pcie_handle_int(struct
+ }
+ }
+
+-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)
+@@ -1513,7 +1519,7 @@ static int advk_pcie_probe(struct platfo
+ 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)
+@@ -1599,17 +1605,9 @@ static int advk_pcie_probe(struct platfo
+ 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,
+@@ -1658,11 +1656,14 @@ static int advk_pcie_probe(struct platfo
+ 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;
+@@ -1710,6 +1711,9 @@ static int advk_pcie_remove(struct platf
+ 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);
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:55 +0200
+Subject: PCI: aardvark: Update comment about link going down after link-up
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-31-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit 92f4ffecc4170ce29e67a1f8d51c168c3de95fb2 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-23-kabel@kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -998,8 +998,12 @@ static bool advk_pcie_valid_device(struc
+ 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;
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:42 +0200
+Subject: PCI: aardvark: Use dev_fwnode() instead of of_node_to_fwnode(dev->of_node)
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-18-kabel@kernel.org>
+
+From: "Marek Behún" <kabel@kernel.org>
+
+commit 222af78532fa299cd9b1008e49c347b7f5a45c17 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-9-kabel@kernel.org
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1296,7 +1296,6 @@ static struct msi_domain_info advk_msi_d
+ 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);
+@@ -1315,7 +1314,7 @@ static int advk_pcie_init_msi_irq_domain
+ 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) {
--- /dev/null
+From foo@baz Tue May 10 01:59:12 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:51 +0200
+Subject: PCI: aardvark: Use separate INTA interrupt for emulated root bridge
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-27-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 815bc313686783e3a1823ec0efc332c70e6bd976 upstream.
+
+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.
+
+Link: https://lore.kernel.org/r/20220110015018.26359-19-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 69 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 67 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -273,6 +273,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;
+@@ -1436,6 +1437,44 @@ static void advk_pcie_remove_irq_domain(
+ 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;
+@@ -1457,7 +1496,7 @@ static void advk_pcie_handle_pme(struct
+ if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE))
+ return;
+
+- if (generic_handle_domain_irq(pcie->irq_domain, 0) == -EINVAL)
++ if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL)
+ dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n");
+ }
+ }
+@@ -1509,7 +1548,7 @@ static void advk_pcie_handle_int(struct
+ * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use
+ * PCIe interrupt 0
+ */
+- if (generic_handle_domain_irq(pcie->irq_domain, 0) == -EINVAL)
++ if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL)
+ dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n");
+ }
+
+@@ -1553,6 +1592,21 @@ static void advk_pcie_irq_handler(struct
+ 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);
+@@ -1754,14 +1808,24 @@ static int advk_pcie_probe(struct platfo
+ 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;
+@@ -1813,6 +1877,7 @@ static int advk_pcie_remove(struct platf
+ 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);
+
--- /dev/null
+From foo@baz Tue May 10 01:59:11 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:27 +0200
+Subject: PCI: pci-bridge-emul: Add definitions for missing capabilities registers
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-3-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 8ea673a8b30b4a32516b8adabb15e2a68ff02ec8 upstream.
+
+pci-bridge-emul driver already allocates buffer for capabilities up to the
+PCI_EXP_SLTSTA2 register, but does not define bit access behavior for these
+registers. Add these missing definitions.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-3-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pci-bridge-emul.c | 43 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+--- a/drivers/pci/pci-bridge-emul.c
++++ b/drivers/pci/pci-bridge-emul.c
+@@ -270,6 +270,49 @@ struct pci_bridge_reg_behavior pcie_cap_
+ .ro = GENMASK(15, 0) | PCI_EXP_RTSTA_PENDING,
+ .w1c = PCI_EXP_RTSTA_PME,
+ },
++
++ [PCI_EXP_DEVCAP2 / 4] = {
++ /*
++ * Device capabilities 2 register has reserved bits [30:27].
++ * Also bits [26:24] are reserved for non-upstream ports.
++ */
++ .ro = BIT(31) | GENMASK(23, 0),
++ },
++
++ [PCI_EXP_DEVCTL2 / 4] = {
++ /*
++ * Device control 2 register is RW. Bit 11 is reserved for
++ * non-upstream ports.
++ *
++ * Device status 2 register is reserved.
++ */
++ .rw = GENMASK(15, 12) | GENMASK(10, 0),
++ },
++
++ [PCI_EXP_LNKCAP2 / 4] = {
++ /* Link capabilities 2 register has reserved bits [30:25] and 0. */
++ .ro = BIT(31) | GENMASK(24, 1),
++ },
++
++ [PCI_EXP_LNKCTL2 / 4] = {
++ /*
++ * Link control 2 register is RW.
++ *
++ * Link status 2 register has bits 5, 15 W1C;
++ * bits 10, 11 reserved and others are RO.
++ */
++ .rw = GENMASK(15, 0),
++ .w1c = (BIT(15) | BIT(5)) << 16,
++ .ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16,
++ },
++
++ [PCI_EXP_SLTCAP2 / 4] = {
++ /* Slot capabilities 2 register is reserved. */
++ },
++
++ [PCI_EXP_SLTCTL2 / 4] = {
++ /* Both Slot control 2 and Slot status 2 registers are reserved. */
++ },
+ };
+
+ /*
--- /dev/null
+From foo@baz Tue May 10 01:59:11 PM CEST 2022
+From: "Marek Behún" <kabel@kernel.org>
+Date: Wed, 4 May 2022 18:57:26 +0200
+Subject: PCI: pci-bridge-emul: Add description for class_revision field
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org, pali@kernel.org, "Marek Behún" <kabel@kernel.org>
+Message-ID: <20220504165755.30002-2-kabel@kernel.org>
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 9319230ac147067652b58fe849ffe0ceec098665 upstream.
+
+The current assignment to the class_revision member
+
+ class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
+
+can make the reader think that class is at high 16 bits of the member and
+revision at low 16 bits.
+
+In reality, class is at high 24 bits, but the class for PCI Bridge Normal
+Decode is PCI_CLASS_BRIDGE_PCI << 8.
+
+Change the assignment and add a comment to make this clearer.
+
+Link: https://lore.kernel.org/r/20211130172913.9727-2-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pci-bridge-emul.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/pci-bridge-emul.c
++++ b/drivers/pci/pci-bridge-emul.c
+@@ -284,7 +284,11 @@ int pci_bridge_emul_init(struct pci_brid
+ {
+ BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END);
+
+- bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
++ /*
++ * class_revision: Class is high 24 bits and revision is low 8 bit of this member,
++ * while class for PCI Bridge Normal Decode has the 24-bit value: PCI_CLASS_BRIDGE_PCI << 8
++ */
++ bridge->conf.class_revision |= cpu_to_le32((PCI_CLASS_BRIDGE_PCI << 8) << 8);
+ bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
+ bridge->conf.cache_line_size = 0x10;
+ bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);
revert-parisc-mark-sched_clock-unstable-only-if-clocks-are-not-syncronized.patch
rcu-fix-callbacks-processing-time-limit-retaining-cond_resched.patch
rcu-apply-callbacks-processing-time-limit-only-on-softirq.patch
+pci-pci-bridge-emul-add-description-for-class_revision-field.patch
+pci-pci-bridge-emul-add-definitions-for-missing-capabilities-registers.patch
+pci-aardvark-add-support-for-devcap2-devctl2-lnkcap2-and-lnkctl2-registers-on-emulated-bridge.patch
+pci-aardvark-clear-all-msis-at-setup.patch
+pci-aardvark-comment-actions-in-driver-remove-method.patch
+pci-aardvark-disable-bus-mastering-when-unbinding-driver.patch
+pci-aardvark-mask-all-interrupts-when-unbinding-driver.patch
+pci-aardvark-fix-memory-leak-in-driver-unbind.patch
+pci-aardvark-assert-perst-when-unbinding-driver.patch
+pci-aardvark-disable-link-training-when-unbinding-driver.patch
+pci-aardvark-disable-common-phy-when-unbinding-driver.patch
+pci-aardvark-replace-custom-pcie_core_int_-macros-with-pci_interrupt_.patch
+pci-aardvark-rewrite-irq-code-to-chained-irq-handler.patch
+pci-aardvark-check-return-value-of-generic_handle_domain_irq-when-processing-intx-irq.patch
+pci-aardvark-make-msi-irq_chip-structures-static-driver-structures.patch
+pci-aardvark-make-msi_domain_info-structure-a-static-driver-structure.patch
+pci-aardvark-use-dev_fwnode-instead-of-of_node_to_fwnode-dev-of_node.patch
+pci-aardvark-refactor-unmasking-summary-msi-interrupt.patch
+pci-aardvark-add-support-for-masking-msi-interrupts.patch
+pci-aardvark-fix-setting-msi-address.patch
+pci-aardvark-enable-msi-x-support.patch
+pci-aardvark-add-support-for-err-interrupt-on-emulated-bridge.patch
+pci-aardvark-optimize-writing-pci_exp_rtctl_pmeie-and-pci_exp_rtsta_pme-on-emulated-bridge.patch
+pci-aardvark-add-support-for-pme-interrupts.patch
+pci-aardvark-fix-support-for-pme-requester-on-emulated-bridge.patch
+pci-aardvark-use-separate-inta-interrupt-for-emulated-root-bridge.patch
+pci-aardvark-remove-irq_mask_ack-callback-for-intx-interrupts.patch
+pci-aardvark-don-t-mask-irq-when-mapping.patch
+pci-aardvark-drop-__maybe_unused-from-advk_pcie_disable_phy.patch
+pci-aardvark-update-comment-about-link-going-down-after-link-up.patch