[PATCH v2 01/53] MIPS: PCI: xtalk-bridge: refuse device numbers past the last slot

From: Imre Kaloz

Date: Tue Oct 13 2026 - 12:39:45 EST


Config slots 8 and up alias the type 1 window, so a root bus scan finds
phantom copies of whatever device b_pci_cfg selects. Refuse root bus
accesses past the ASIC's last slot.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Imre Kaloz <kaloz@xxxxxxxxxx>
---
arch/mips/pci/pci-xtalk-bridge.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index cf115abb54e0..9451b7546068 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -92,6 +92,11 @@ static int ioc3_cfg_wr(void *addr, int where, int size, u32 value)
return PCIBIOS_SUCCESSFUL;
}

+static int bridge_nslots(struct bridge_controller *bc)
+{
+ return BRIDGE_DEV_CNT;
+}
+
static void bridge_disable_swapping(struct pci_dev *dev)
{
struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
@@ -127,6 +132,13 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
u32 cf;
int res;

+ /*
+ * Only bridge_nslots() slots exist. Config slots 8 and up alias the
+ * type 1 window and would answer for whatever b_pci_cfg selects.
+ */
+ if (slot >= bridge_nslots(bc))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
if (get_dbe(cf, (u32 *)addr))
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -212,6 +224,9 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
u32 cf;
int res;

+ if (slot >= bridge_nslots(bc))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
if (get_dbe(cf, (u32 *)addr))
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -695,7 +710,7 @@ static int bridge_probe(struct platform_device *pdev)
bridge_write(bc, b_dir_map, (bd->masterwid << 20)); /* DMA */
bridge_write(bc, b_int_enable, 0);

- for (slot = 0; slot < 8; slot++) {
+ for (slot = 0; slot < bridge_nslots(bc); slot++) {
bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR);
bc->pci_int[slot][0] = -1;
bc->pci_int[slot][1] = -1;
--
2.47.3