Skip to content

Commit 8783202

Browse files
palismb49
authored andcommitted
PCI: aardvark: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated bridge
BugLink: https://bugs.launchpad.net/bugs/1956380 commit bc4fac4 upstream. Aardvark supports PCIe Hot Reset via PCIE_CORE_CTRL1_REG. Use it for implementing PCI_BRIDGE_CTL_BUS_RESET bit of PCI_BRIDGE_CONTROL register on emulated bridge. With this, the function pci_reset_secondary_bus() starts working and can reset connected PCIe card. Custom userspace script [1] which uses setpci can trigger PCIe Hot Reset and reset the card manually. [1] https://alexforencich.com/wiki/en/pcie/hot-reset-linux Link: https://lore.kernel.org/r/20211028185659.20329-7-kabel@kernel.org Fixes: 8a3ebd8 ("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> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: stable@vger.kernel.org Signed-off-by: Marek Behún <kabel@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 5a74445 commit 8783202

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,22 @@ advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
764764
*value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
765765
return PCI_BRIDGE_EMUL_HANDLED;
766766

767+
case PCI_INTERRUPT_LINE: {
768+
/*
769+
* From the whole 32bit register we support reading from HW only
770+
* one bit: PCI_BRIDGE_CTL_BUS_RESET.
771+
* Other bits are retrieved only from emulated config buffer.
772+
*/
773+
__le32 *cfgspace = (__le32 *)&bridge->conf;
774+
u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
775+
if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN)
776+
val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
777+
else
778+
val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16);
779+
*value = val;
780+
return PCI_BRIDGE_EMUL_HANDLED;
781+
}
782+
767783
default:
768784
return PCI_BRIDGE_EMUL_NOT_HANDLED;
769785
}
@@ -780,6 +796,17 @@ advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
780796
advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG);
781797
break;
782798

799+
case PCI_INTERRUPT_LINE:
800+
if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
801+
u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG);
802+
if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
803+
val |= HOT_RESET_GEN;
804+
else
805+
val &= ~HOT_RESET_GEN;
806+
advk_writel(pcie, val, PCIE_CORE_CTRL1_REG);
807+
}
808+
break;
809+
783810
default:
784811
break;
785812
}

0 commit comments

Comments
 (0)