From 1c1a3b4d3e86b997a313ffb297c1129540882859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 24 Nov 2021 16:59:39 +0100 Subject: PCI: pci-bridge-emul: Make expansion ROM Base Address register read-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If expansion ROM is unsupported (which is the case of pci-bridge-emul.c driver) then ROM Base Address register must be implemented as read-only register that return 0 when read, same as for unused Base Address registers. Link: https://lore.kernel.org/r/20211124155944.1290-2-pali@kernel.org Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Signed-off-by: Pali Rohár Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org --- drivers/pci/pci-bridge-emul.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/pci/pci-bridge-emul.c') diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index db97cddfc85e..5de8b8dde209 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -139,8 +139,13 @@ struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = { .ro = GENMASK(7, 0), }, + /* + * If expansion ROM is unsupported then ROM Base Address register must + * be implemented as read-only register that return 0 when read, same + * as for unused Base Address registers. + */ [PCI_ROM_ADDRESS1 / 4] = { - .rw = GENMASK(31, 11) | BIT(0), + .ro = ~0, }, /* -- cgit v1.2.3 From 7b067ac63a5730d2fae18399fed7e45f23d36912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 24 Nov 2021 16:59:40 +0100 Subject: PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some bits in PCI config space are reserved when device is PCIe. Properly define behavior of PCI registers for PCIe emulated bridge and ensure that it would not be possible change these reserved bits. Link: https://lore.kernel.org/r/20211124155944.1290-3-pali@kernel.org Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Signed-off-by: Pali Rohár Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org --- drivers/pci/pci-bridge-emul.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/pci/pci-bridge-emul.c') diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 5de8b8dde209..0cbb4e3ca827 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -295,6 +295,27 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, kfree(bridge->pci_regs_behavior); return -ENOMEM; } + /* These bits are applicable only for PCI and reserved on PCIe */ + bridge->pci_regs_behavior[PCI_CACHE_LINE_SIZE / 4].ro &= + ~GENMASK(15, 8); + bridge->pci_regs_behavior[PCI_COMMAND / 4].ro &= + ~((PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE | + PCI_COMMAND_VGA_PALETTE | PCI_COMMAND_WAIT | + PCI_COMMAND_FAST_BACK) | + (PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK | + PCI_STATUS_DEVSEL_MASK) << 16); + bridge->pci_regs_behavior[PCI_PRIMARY_BUS / 4].ro &= + ~GENMASK(31, 24); + bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro &= + ~((PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK | + PCI_STATUS_DEVSEL_MASK) << 16); + bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].rw &= + ~((PCI_BRIDGE_CTL_MASTER_ABORT | + BIT(8) | BIT(9) | BIT(11)) << 16); + bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].ro &= + ~((PCI_BRIDGE_CTL_FAST_BACK) << 16); + bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].w1c &= + ~(BIT(10) << 16); } if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) { -- cgit v1.2.3 From 12998087d9f48b66965b97412069c7826502cd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 24 Nov 2021 16:59:42 +0100 Subject: PCI: pci-bridge-emul: Fix definitions of reserved bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some bits in PCI_EXP registers are reserved for non-root ports. Driver pci-bridge-emul.c implements PCIe Root Port device therefore it should not allow setting reserved bits of registers. Properly define non-reserved bits for all PCI_EXP registers. Link: https://lore.kernel.org/r/20211124155944.1290-5-pali@kernel.org Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Signed-off-by: Pali Rohár Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org --- drivers/pci/pci-bridge-emul.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers/pci/pci-bridge-emul.c') diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 0cbb4e3ca827..2c7e04fb2685 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -176,41 +176,55 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = [PCI_CAP_LIST_ID / 4] = { /* * Capability ID, Next Capability Pointer and - * Capabilities register are all read-only. + * bits [14:0] of Capabilities register are all read-only. + * Bit 15 of Capabilities register is reserved. */ - .ro = ~0, + .ro = GENMASK(30, 0), }, [PCI_EXP_DEVCAP / 4] = { - .ro = ~0, + /* + * Bits [31:29] and [17:16] are reserved. + * Bits [27:18] are reserved for non-upstream ports. + * Bits 28 and [14:6] are reserved for non-endpoint devices. + * Other bits are read-only. + */ + .ro = BIT(15) | GENMASK(5, 0), }, [PCI_EXP_DEVCTL / 4] = { - /* Device control register is RW */ - .rw = GENMASK(15, 0), + /* + * Device control register is RW, except bit 15 which is + * reserved for non-endpoints or non-PCIe-to-PCI/X bridges. + */ + .rw = GENMASK(14, 0), /* * Device status register has bits 6 and [3:0] W1C, [5:4] RO, - * the rest is reserved + * the rest is reserved. Also bit 6 is reserved for non-upstream + * ports. */ - .w1c = (BIT(6) | GENMASK(3, 0)) << 16, + .w1c = GENMASK(3, 0) << 16, .ro = GENMASK(5, 4) << 16, }, [PCI_EXP_LNKCAP / 4] = { - /* All bits are RO, except bit 23 which is reserved */ - .ro = lower_32_bits(~BIT(23)), + /* + * All bits are RO, except bit 23 which is reserved and + * bit 18 which is reserved for non-upstream ports. + */ + .ro = lower_32_bits(~(BIT(23) | PCI_EXP_LNKCAP_CLKPM)), }, [PCI_EXP_LNKCTL / 4] = { /* * Link control has bits [15:14], [11:3] and [1:0] RW, the - * rest is reserved. + * rest is reserved. Bit 8 is reserved for non-upstream ports. * * Link status has bits [13:0] RO, and bits [15:14] * W1C. */ - .rw = GENMASK(15, 14) | GENMASK(11, 3) | GENMASK(1, 0), + .rw = GENMASK(15, 14) | GENMASK(11, 9) | GENMASK(7, 3) | GENMASK(1, 0), .ro = GENMASK(13, 0) << 16, .w1c = GENMASK(15, 14) << 16, }, -- cgit v1.2.3 From 1f1050c5e1fefb34ac90a506b43e9da803b5f8f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 24 Nov 2021 16:59:43 +0100 Subject: PCI: pci-bridge-emul: Correctly set PCIe capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older mvebu hardware provides PCIe Capability structure only in version 1. New mvebu and aardvark hardware provides it in version 2. So do not force version to 2 in pci_bridge_emul_init() and rather allow drivers to set correct version. Drivers need to set version in pcie_conf.cap field without overwriting PCI_CAP_LIST_ID register. Both drivers (mvebu and aardvark) do not provide slot support yet, so do not set PCI_EXP_FLAGS_SLOT flag. Link: https://lore.kernel.org/r/20211124155944.1290-6-pali@kernel.org Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Signed-off-by: Pali Rohár Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org --- drivers/pci/pci-bridge-emul.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/pci/pci-bridge-emul.c') diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 2c7e04fb2685..867159562d07 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -297,10 +297,7 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, if (bridge->has_pcie) { bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START; bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP; - /* Set PCIe v2, root port, slot support */ - bridge->pcie_conf.cap = - cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4 | 2 | - PCI_EXP_FLAGS_SLOT); + bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4); bridge->pcie_cap_regs_behavior = kmemdup(pcie_cap_regs_behavior, sizeof(pcie_cap_regs_behavior), -- cgit v1.2.3 From 3be9d243b21724d49b65043d4520d688b6040b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 24 Nov 2021 16:59:44 +0100 Subject: PCI: pci-bridge-emul: Set PCI_STATUS_CAP_LIST for PCIe device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since all PCI Express device Functions are required to implement the PCI Express Capability structure, Capabilities List bit in PCI Status Register must be hardwired to 1b. Capabilities Pointer register (which is already set by pci-bride-emul.c driver) is valid only when Capabilities List is set to 1b. Link: https://lore.kernel.org/r/20211124155944.1290-7-pali@kernel.org Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Signed-off-by: Pali Rohár Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org --- drivers/pci/pci-bridge-emul.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pci/pci-bridge-emul.c') diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 867159562d07..37504c2cce9b 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -296,6 +296,7 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, if (bridge->has_pcie) { bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START; + bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST); bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP; bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4); bridge->pcie_cap_regs_behavior = -- cgit v1.2.3