From: Imre Kaloz <kaloz@kernel.org>
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org,
Lee Jones <lee@kernel.org>,
linux-pci@vger.kernel.org
Subject: [PATCH v2 02/53] MIPS: PCI: xtalk-bridge: assign slots the PROM leaves unconfigured
Date: Tue, 13 Oct 2026 15:16:22 +0200 [thread overview]
Message-ID: <938cb58f1db3a1272aff33a4d70ead1f711017ee.1791890466.git.kaloz@kernel.org> (raw)
In-Reply-To: <cover.1791890466.git.kaloz@kernel.org>
The PROM leaves some slots unassigned, such as an LSI SAS1064 or the bus
behind a PCI-to-PCI bridge, so their drivers cannot bind. Map their devio
windows, borrowing an empty slot's for I/O when memory takes their own.
Signed-off-by: Imre Kaloz <kaloz@kernel.org>
---
arch/mips/pci/pci-xtalk-bridge.c | 192 +++++++++++++++++++++++++++++++
1 file changed, 192 insertions(+)
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index 9451b7546068..2fa9ac8d0a1c 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -619,6 +619,192 @@ static int bridge_get_partnum(u64 baddr, char *partnum)
return 0;
}
+static unsigned long bridge_dev_space(struct pci_dev *pdev)
+{
+ unsigned long flags = 0;
+ struct resource *res;
+ int i;
+
+ pci_dev_for_each_resource(pdev, res, i)
+ if (i < PCI_ROM_RESOURCE && resource_size(res))
+ flags |= res->flags & (IORESOURCE_IO | IORESOURCE_MEM);
+
+ return flags;
+}
+
+static bool bridge_ppb_window(struct pci_dev *ppb, int idx,
+ struct resource *win)
+{
+ struct resource *res = &ppb->resource[idx];
+
+ if (!win)
+ return false;
+ res->start = win->start;
+ res->end = win->end;
+ res->flags = win->flags;
+ if (request_resource(win, res))
+ return false;
+ pci_info(ppb, "bridge window %pR: assigned\n", res);
+ return true;
+}
+
+static void bridge_setup_ppb(struct pci_dev *ppb,
+ struct xtalk_bridge_platform_data *bd,
+ struct resource *io, struct resource *mem)
+{
+ u32 start, end;
+ u8 io_type;
+
+ pci_read_config_byte(ppb, PCI_IO_BASE, &io_type);
+ if (io && (io_type & PCI_IO_RANGE_TYPE_MASK) != PCI_IO_RANGE_TYPE_32) {
+ pci_warn(ppb, "no 32-bit I/O window\n");
+ io = NULL;
+ }
+ if (!bridge_ppb_window(ppb, PCI_BRIDGE_IO_WINDOW, io))
+ io = NULL;
+ if (!bridge_ppb_window(ppb, PCI_BRIDGE_MEM_WINDOW, mem))
+ mem = NULL;
+ if (!io && !mem)
+ return;
+
+ if (io) {
+ start = io->start - bd->io_offset;
+ end = io->end - bd->io_offset;
+ pci_write_config_dword(ppb, PCI_IO_BASE_UPPER16,
+ (end & 0xffff0000) | (start >> 16));
+ pci_write_config_word(ppb, PCI_IO_BASE,
+ (end & 0xf000) | (start >> 8 & 0xf0));
+ } else {
+ pci_write_config_dword(ppb, PCI_IO_BASE_UPPER16, 0);
+ pci_write_config_word(ppb, PCI_IO_BASE, 0x00f0);
+ }
+ if (mem) {
+ start = mem->start - bd->mem_offset;
+ end = mem->end - bd->mem_offset;
+ pci_write_config_dword(ppb, PCI_MEMORY_BASE,
+ (end & 0xfff00000) | (start >> 16));
+ } else {
+ pci_write_config_dword(ppb, PCI_MEMORY_BASE, 0x0000fff0);
+ }
+ pci_write_config_dword(ppb, PCI_PREF_MEMORY_BASE, 0x0000fff0);
+ pci_write_config_dword(ppb, PCI_PREF_BASE_UPPER32, 0);
+ pci_write_config_dword(ppb, PCI_PREF_LIMIT_UPPER32, 0);
+
+ pci_bus_assign_resources(ppb->subordinate);
+}
+
+/* Map devio window @win, at its own address, in memory or I/O space. */
+static struct resource *bridge_map_devio(struct bridge_controller *bc,
+ struct xtalk_bridge_platform_data *bd,
+ struct device *dev, int win, bool mem)
+{
+ struct resource *root = mem ? &bd->mem : &bd->io;
+ resource_size_t offset = mem ? bd->mem_offset : bd->io_offset;
+ struct resource *res;
+ u32 devreg;
+
+ res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return NULL;
+ res->name = "Bridge PCI slot";
+ res->start = root->start - BRIDGE_DEVIO0 + BRIDGE_DEVIO(win);
+ res->end = res->start + (win <= 1 ? BRIDGE_DEVIO_2MB :
+ BRIDGE_DEVIO_1MB) - 1;
+ res->flags = root->flags;
+ if (devm_request_resource(dev, root, res))
+ return NULL;
+
+ devreg = bridge_read(bc, b_device[win].reg);
+ devreg &= ~(BRIDGE_DEV_OFF_MASK | BRIDGE_DEV_DEV_IO_MEM);
+ devreg |= (res->start - offset) >> BRIDGE_DEV_OFF_ADDR_SHFT;
+ if (mem)
+ devreg |= BRIDGE_DEV_DEV_IO_MEM;
+ bridge_write(bc, b_device[win].reg, devreg);
+ bridge_read(bc, b_wid_tflush);
+
+ return res;
+}
+
+/*
+ * A slot's BARs are reached only through a devio window, which Device(x)
+ * points at either PCI I/O or PCI memory space. The PROM leaves some slots
+ * without resources, the secondary bus of a PCI-to-PCI bridge among them.
+ * Give such a slot its own window, in memory space if anything in the slot
+ * needs memory, and the window of a slot with no device for I/O space if
+ * it needs both: PIO through any devio window reaches every device on the
+ * bus.
+ */
+static void bridge_setup_slot(struct bridge_controller *bc,
+ struct xtalk_bridge_platform_data *bd,
+ struct device *dev, struct pci_bus *bus, int slot,
+ unsigned long *busy)
+{
+ struct resource *res, *win, *io = NULL, *mem = NULL;
+ struct pci_dev *pdev, *child;
+ unsigned long flags = 0;
+ int i;
+
+ list_for_each_entry(pdev, &bus->devices, bus_list) {
+ if (PCI_SLOT(pdev->devfn) != slot)
+ continue;
+ pci_dev_for_each_resource(pdev, res)
+ if (res->parent)
+ return;
+ if (!pdev->subordinate)
+ flags |= bridge_dev_space(pdev);
+ else
+ list_for_each_entry(child, &pdev->subordinate->devices,
+ bus_list)
+ flags |= bridge_dev_space(child);
+ }
+ if (!flags)
+ return;
+
+ if (flags & IORESOURCE_MEM)
+ mem = bridge_map_devio(bc, bd, dev, slot, true);
+ else
+ io = bridge_map_devio(bc, bd, dev, slot, false);
+ if (!io && !mem)
+ return;
+
+ if ((flags & IORESOURCE_IO) && !io) {
+ i = find_first_zero_bit(busy, bridge_nslots(bc));
+ if (i < bridge_nslots(bc)) {
+ __set_bit(i, busy);
+ io = bridge_map_devio(bc, bd, dev, i, false);
+ }
+ if (!io)
+ dev_warn(dev, "slot %d: no devio window for I/O space\n",
+ slot);
+ }
+
+ list_for_each_entry(pdev, &bus->devices, bus_list) {
+ if (PCI_SLOT(pdev->devfn) != slot)
+ continue;
+ if (pdev->subordinate) {
+ bridge_setup_ppb(pdev, bd, io, mem);
+ continue;
+ }
+ pci_dev_for_each_resource(pdev, res, i) {
+ win = res->flags & IORESOURCE_MEM ? mem : io;
+ if (i >= PCI_ROM_RESOURCE || !win ||
+ !(res->flags & win->flags) || !resource_size(res))
+ continue;
+ if (allocate_resource(win, res, resource_size(res),
+ win->start, win->end,
+ resource_alignment(res),
+ NULL, NULL)) {
+ pci_warn(pdev, "BAR %d %pR: no space in slot\n",
+ i, res);
+ continue;
+ }
+ res->flags &= ~IORESOURCE_UNSET;
+ pci_update_resource(pdev, i);
+ pci_info(pdev, "BAR %d %pR: assigned\n", i, res);
+ }
+ }
+}
+
static int bridge_probe(struct platform_device *pdev)
{
struct xtalk_bridge_platform_data *bd = dev_get_platdata(&pdev->dev);
@@ -627,6 +813,8 @@ static int bridge_probe(struct platform_device *pdev)
struct pci_host_bridge *host;
struct irq_domain *domain, *parent;
struct fwnode_handle *fn;
+ struct pci_dev *pcidev;
+ unsigned long busy = 0;
char partnum[26];
int slot;
int err;
@@ -734,6 +922,10 @@ static int bridge_probe(struct platform_device *pdev)
goto err_free_resource;
pci_bus_claim_resources(host->bus);
+ list_for_each_entry(pcidev, &host->bus->devices, bus_list)
+ __set_bit(PCI_SLOT(pcidev->devfn), &busy);
+ for (slot = 0; slot < bridge_nslots(bc); slot++)
+ bridge_setup_slot(bc, bd, dev, host->bus, slot, &busy);
pci_bus_add_devices(host->bus);
platform_set_drvdata(pdev, host->bus);
--
2.47.3
next prev parent reply other threads:[~2026-10-13 13:18 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 13:16 [PATCH v2 00/53] MIPS: SGI-IP27: add support for the IP35 (Bedrock hub) machines Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 01/53] MIPS: PCI: xtalk-bridge: refuse device numbers past the last slot Imre Kaloz
2026-10-13 13:16 ` Imre Kaloz [this message]
2026-10-13 13:16 ` [PATCH v2 03/53] MIPS: PCI: xtalk-bridge: write a type 1 IOC3 through the type 1 window Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 04/53] MIPS: PCI: xtalk-bridge: flush config space writes Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 05/53] MIPS: PCI: xtalk-bridge: reassign slots whose devio window maps elsewhere Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 06/53] MIPS: Xtalk: guard the widget identification table from assembly Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 07/53] MIPS: SGI-IP27: dump the NMI save areas the CPU scan recorded Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 08/53] MIPS: SGI-IP27: add REMOTE_HUB_PI_S()/REMOTE_HUB_PI_L() Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 09/53] MIPS: SGI-IP27: detect Bedrock hubs at boot Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 10/53] MIPS: SGI-IP27: widen Kconfig for the Bedrock-based machines Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 11/53] MIPS: SGI-IP27: fold the dead SN1 arm out of klconfig.h Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 12/53] MIPS: SGI-IP27: choose the node address layout at runtime Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 13/53] MIPS: SGI-IP27: add the Bedrock hub register windows Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 14/53] MIPS: SGI-IP27: decode a Bedrock hub's node id and system size Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 15/53] MIPS: SGI-IP27: put a Bedrock hub's boot CPU in slot 0 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 16/53] MIPS: SGI-IP27: lay out node memory in 1GB banks on Bedrock hubs Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 17/53] MIPS: SGI-IP27: reserve the bottom 64MB of node 0 " Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 18/53] MIPS: SGI-IP27: route interrupt masks and slices through both PIs Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 19/53] MIPS: SGI-IP27: address a CPU's own PI for NMI, IPI and RT counter Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 20/53] MIPS: SGI-IP27: take a CPU's node from the CPU table in per_cpu_init() Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 21/53] MIPS: SGI-IP27: resolve the mapped-kernel node shift at runtime Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 22/53] MIPS: SGI-IP27: load the kernel at node offset 0x40000 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 23/53] MIPS: SGI-IP27: xbow_probe(): recognize KLTYPE_PBRICK_XBOW Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 24/53] MIPS: ip27_defconfig: enable the IOC3 MFD, its cell drivers and tg3 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 25/53] net: ethernet: sgi: ioc3-eth: apply the DMA attributes only to 64-bit addresses Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 26/53] MIPS: SGI-IP27: pick the XBridge and PIC DMA address form by mask Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 27/53] MIPS: SGI-IP27: recognize the PXBow crossbar Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 28/53] MIPS: PCI: xtalk-bridge: recognize the PIC widget's 64-bit-only registers Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 29/53] MIPS: PCI: xtalk-bridge: match PIC's register-level differences Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 30/53] rtc: m48t35: support the SGI IP35 timekeeper's 1968 year base Imre Kaloz
2026-10-13 14:28 ` Alexandre Belloni
2026-10-13 13:16 ` [PATCH v2 31/53] mfd: ioc3: Add support for IOC4 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 32/53] MIPS: SGI-IP27: dispatch the early console between IOC3 and IOC4 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 33/53] MIPS: SGI-IP27: add L1 system controller support Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 34/53] MIPS: SGI-IP27: wire the L1 into reset and the Ethernet address Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 35/53] MIPS: PCI: xtalk-bridge: take the board part number from the L1 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 36/53] mfd: ioc3: Add IP34 system-board entry to ioc3_infos[] Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 37/53] mfd: ioc3: Cross the serial IRQs on the Origin 300 IO8 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 38/53] net: ethernet: sgi: ioc3-eth: fall back to the platform MAC address Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 39/53] MIPS: SGI-IP27: don't register a w1 master on an XBridge or PIC Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 40/53] MIPS: SGI-IP27: report a Bedrock machine as SGI IP35 Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 41/53] MIPS: SGI-IP27: identify the machine by the L1 brick type Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 42/53] MIPS: SGI-IP27: register the Odyssey graphics widget Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 43/53] MIPS: SGI-IP27: take the console from the KLCONFIG header on IP35 Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 44/53] MIPS: SGI-IP27: give each CPU its own topology package id Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 45/53] ata: add pata_sgiioc4 driver for the SGI IOC4 ATA/ATAPI controller Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 46/53] mfd: ioc3: Add IOC4 ATA/ATAPI cell Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 47/53] MAINTAINERS: add an entry for the SGI IOC4 ATA driver Imre Kaloz
2026-10-13 13:25 ` Damien Le Moal
2026-10-13 13:38 ` Imre Kaloz
2026-10-13 15:13 ` Damien Le Moal
2026-10-13 13:17 ` [PATCH v2 48/53] MIPS: ip27_defconfig: update for the onboard hardware Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 49/53] MIPS: ip27_defconfig: enable pata_sgiioc4 and the DVD-ROM path Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 50/53] MIPS: SGI-IP27: add L1 front-panel LED and display requests Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 51/53] leds: Add driver for the SGI Fuel and Tezro front-panel LEDs Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 52/53] MIPS: SGI-IP27: show the OS state on the Fuel and Tezro front panels Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 53/53] MIPS: ip27_defconfig: enable the Fuel and Tezro front-panel LEDs Imre Kaloz
2026-10-13 13:35 ` [PATCH v2 00/53] MIPS: SGI-IP27: add support for the IP35 (Bedrock hub) machines Niklas Cassel
2026-10-13 14:25 ` Imre Kaloz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=938cb58f1db3a1272aff33a4d70ead1f711017ee.1791890466.git.kaloz@kernel.org \
--to=kaloz@kernel.org \
--cc=lee@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=tsbogend@alpha.franken.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®