diff options
Diffstat (limited to 'target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch')
-rw-r--r-- | target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch | 173 |
1 files changed, 0 insertions, 173 deletions
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 deleted file mode 100644 index a59ff36b51..0000000000 --- a/target/linux/generic/pending-5.10/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch +++ /dev/null @@ -1,173 +0,0 @@ -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(-) - ---- 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 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); -@@ -863,22 +868,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); -@@ -932,22 +926,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: -@@ -1452,6 +1443,34 @@ 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; -+ 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; -@@ -1488,18 +1507,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. -- */ -- 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) { |