Skip to content

Commit 74afce3

Browse files
ij-intelbjorn-helgaas
authored andcommitted
PCI: Add bridge window selection functions
Various places in the PCI core code independently decide into which bridge window a child resource should be placed. It is hard to see whether these decisions always end up in agreement, especially in the corner cases, and in some places it requires complex logic to pass multiple resource types and/or bridge windows around. Add pbus_select_window() and pbus_select_window_for_type() for cases where the former cannot be used so that eventually the same helper can be used to select the bridge window everywhere. Using the same function ensures the selected bridge window remains always the same and it can be easily recalculated in-situ allowing simplifying the interfaces between internal functions in upcoming changes. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20250829131113.36754-13-ilpo.jarvinen@linux.intel.com
1 parent e493483 commit 74afce3

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

drivers/pci/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ static inline int pci_resource_num(const struct pci_dev *dev,
385385
return resno;
386386
}
387387

388+
struct resource *pbus_select_window(struct pci_bus *bus,
389+
const struct resource *res);
388390
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
389391
void pci_disable_bridge_window(struct pci_dev *dev);
390392
struct pci_bus *pci_bus_get(struct pci_bus *bus);

drivers/pci/setup-bus.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,107 @@ static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
172172
return r_assigned;
173173
}
174174

175+
/**
176+
* pbus_select_window_for_type - Select bridge window for a resource type
177+
* @bus: PCI bus
178+
* @type: Resource type (resource flags can be passed as is)
179+
*
180+
* Select the bridge window based on a resource @type.
181+
*
182+
* For memory resources, the selection is done as follows:
183+
*
184+
* Any non-prefetchable resource is put into the non-prefetchable window.
185+
*
186+
* If there is no prefetchable MMIO window, put all memory resources into the
187+
* non-prefetchable window.
188+
*
189+
* If there's a 64-bit prefetchable MMIO window, put all 64-bit prefetchable
190+
* resources into it and place 32-bit prefetchable memory into the
191+
* non-prefetchable window.
192+
*
193+
* Otherwise, put all prefetchable resources into the prefetchable window.
194+
*
195+
* Return: the bridge window resource or NULL if no bridge window is found.
196+
*/
197+
static struct resource *pbus_select_window_for_type(struct pci_bus *bus,
198+
unsigned long type)
199+
{
200+
int iores_type = type & IORESOURCE_TYPE_BITS; /* w/o 64bit & pref */
201+
struct resource *mmio, *mmio_pref, *win;
202+
203+
type &= PCI_RES_TYPE_MASK; /* with 64bit & pref */
204+
205+
if ((iores_type != IORESOURCE_IO) && (iores_type != IORESOURCE_MEM))
206+
return NULL;
207+
208+
if (pci_is_root_bus(bus)) {
209+
win = find_bus_resource_of_type(bus, type, type);
210+
if (win)
211+
return win;
212+
213+
type &= ~IORESOURCE_MEM_64;
214+
win = find_bus_resource_of_type(bus, type, type);
215+
if (win)
216+
return win;
217+
218+
type &= ~IORESOURCE_PREFETCH;
219+
return find_bus_resource_of_type(bus, type, type);
220+
}
221+
222+
switch (iores_type) {
223+
case IORESOURCE_IO:
224+
return pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
225+
226+
case IORESOURCE_MEM:
227+
mmio = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_MEM_WINDOW);
228+
mmio_pref = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_PREF_MEM_WINDOW);
229+
230+
if (!(type & IORESOURCE_PREFETCH) ||
231+
!(mmio_pref->flags & IORESOURCE_MEM))
232+
return mmio;
233+
234+
if ((type & IORESOURCE_MEM_64) ||
235+
!(mmio_pref->flags & IORESOURCE_MEM_64))
236+
return mmio_pref;
237+
238+
return mmio;
239+
default:
240+
return NULL;
241+
}
242+
}
243+
244+
/**
245+
* pbus_select_window - Select bridge window for a resource
246+
* @bus: PCI bus
247+
* @res: Resource
248+
*
249+
* Select the bridge window for @res. If the resource is already assigned,
250+
* return the current bridge window.
251+
*
252+
* For memory resources, the selection is done as follows:
253+
*
254+
* Any non-prefetchable resource is put into the non-prefetchable window.
255+
*
256+
* If there is no prefetchable MMIO window, put all memory resources into the
257+
* non-prefetchable window.
258+
*
259+
* If there's a 64-bit prefetchable MMIO window, put all 64-bit prefetchable
260+
* resources into it and place 32-bit prefetchable memory into the
261+
* non-prefetchable window.
262+
*
263+
* Otherwise, put all prefetchable resources into the prefetchable window.
264+
*
265+
* Return: the bridge window resource or NULL if no bridge window is found.
266+
*/
267+
struct resource *pbus_select_window(struct pci_bus *bus,
268+
const struct resource *res)
269+
{
270+
if (res->parent)
271+
return res->parent;
272+
273+
return pbus_select_window_for_type(bus, res->flags);
274+
}
275+
175276
static bool pdev_resources_assignable(struct pci_dev *dev)
176277
{
177278
u16 class = dev->class >> 8, command;

0 commit comments

Comments
 (0)