Skip to content

Commit 3f6eb5a

Browse files
committed
Merge tag 'pci-v7.0-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
Pull pci fixes from Bjorn Helgaas: - Fix bridge window selection bug that prevented resource assignment (Kai-Heng Feng) - Fix bridge window sizing, which failed to assign resources for windows containing only optional resources (ROMs, SR-IOV BARs, etc) (Ilpo Järvinen) - Select CONFIGFS_FS when PCI_EPF_TEST is enabled to avoid a link error (Arnd Bergmann) - Fix recently merged Endpoint inbound submapping feature (Koichiro Den) * tag 'pci-v7.0-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: PCI: dwc: ep: Always clear IB maps on BAR update PCI: dwc: ep: Return after clearing BAR-match inbound mapping PCI: endpoint: pci-epf-test: Select configfs PCI: Account fully optional bridge windows correctly PCI: Validate window resource type in pbus_select_window_for_type()
2 parents 433b23a + 8c746e2 commit 3f6eb5a

File tree

3 files changed

+39
-19
lines changed

3 files changed

+39
-19
lines changed

drivers/pci/controller/dwc/pcie-designware-ep.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, u8 func_no, enum pci
165165
dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index);
166166
clear_bit(atu_index, ep->ib_window_map);
167167
ep_func->bar_to_atu[bar] = 0;
168+
return;
168169
}
169170

170171
/* Tear down all Address Match Mode mappings, if any. */
@@ -518,6 +519,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
518519
/*
519520
* We can only dynamically change a BAR if the new BAR size and
520521
* BAR flags do not differ from the existing configuration.
522+
*
523+
* Note: this safety check only works when the caller uses
524+
* a new struct pci_epf_bar in the second set_bar() call.
525+
* If the same instance is updated in place and passed in,
526+
* we cannot reliably detect invalid barno/size/flags
527+
* changes here.
521528
*/
522529
if (ep_func->epf_bar[bar]->barno != bar ||
523530
ep_func->epf_bar[bar]->size != size ||
@@ -526,10 +533,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
526533

527534
/*
528535
* When dynamically changing a BAR, tear down any existing
529-
* mappings before re-programming.
536+
* mappings before re-programming. This is redundant when
537+
* both the old and new mappings are BAR Match Mode, but
538+
* required to handle in-place updates and match-mode
539+
* changes reliably.
530540
*/
531-
if (ep_func->epf_bar[bar]->num_submap || epf_bar->num_submap)
532-
dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
541+
dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
533542

534543
/*
535544
* When dynamically changing a BAR, skip writing the BAR reg, as

drivers/pci/endpoint/functions/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
config PCI_EPF_TEST
77
tristate "PCI Endpoint Test driver"
88
depends on PCI_ENDPOINT
9+
select CONFIGFS_FS
910
select CRC32
1011
help
1112
Enable this configuration option to enable the test driver

drivers/pci/setup-bus.c

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,21 @@ static struct resource *pbus_select_window_for_type(struct pci_bus *bus,
224224

225225
switch (iores_type) {
226226
case IORESOURCE_IO:
227-
return pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
227+
win = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
228+
if (win && (win->flags & IORESOURCE_IO))
229+
return win;
230+
return NULL;
228231

229232
case IORESOURCE_MEM:
230233
mmio = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_MEM_WINDOW);
231234
mmio_pref = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_PREF_MEM_WINDOW);
232235

233-
if (!(type & IORESOURCE_PREFETCH) ||
234-
!(mmio_pref->flags & IORESOURCE_MEM))
236+
if (mmio && !(mmio->flags & IORESOURCE_MEM))
237+
mmio = NULL;
238+
if (mmio_pref && !(mmio_pref->flags & IORESOURCE_MEM))
239+
mmio_pref = NULL;
240+
241+
if (!(type & IORESOURCE_PREFETCH) || !mmio_pref)
235242
return mmio;
236243

237244
if ((type & IORESOURCE_MEM_64) ||
@@ -1217,31 +1224,34 @@ static bool pbus_size_mem_optional(struct pci_dev *dev, int resno,
12171224
struct resource *res = pci_resource_n(dev, resno);
12181225
bool optional = pci_resource_is_optional(dev, resno);
12191226
resource_size_t r_size = resource_size(res);
1220-
struct pci_dev_resource *dev_res;
1227+
struct pci_dev_resource *dev_res = NULL;
12211228

12221229
if (!realloc_head)
12231230
return false;
12241231

1225-
if (!optional) {
1226-
/*
1227-
* Only bridges have optional sizes in realloc_head at this
1228-
* point. As res_to_dev_res() walks the entire realloc_head
1229-
* list, skip calling it when known unnecessary.
1230-
*/
1231-
if (!pci_resource_is_bridge_win(resno))
1232-
return false;
1233-
1232+
/*
1233+
* Only bridges have optional sizes in realloc_head at this
1234+
* point. As res_to_dev_res() walks the entire realloc_head
1235+
* list, skip calling it when known unnecessary.
1236+
*/
1237+
if (pci_resource_is_bridge_win(resno)) {
12341238
dev_res = res_to_dev_res(realloc_head, res);
12351239
if (dev_res) {
12361240
*children_add_size += dev_res->add_size;
12371241
*add_align = max(*add_align, dev_res->min_align);
12381242
}
1243+
}
12391244

1245+
if (!optional)
12401246
return false;
1241-
}
12421247

1243-
/* Put SRIOV requested res to the optional list */
1244-
pci_dev_res_add_to_list(realloc_head, dev, res, 0, align);
1248+
/*
1249+
* Put requested res to the optional list if not there yet (SR-IOV,
1250+
* disabled ROM). Bridge windows with an optional part are already
1251+
* on the list.
1252+
*/
1253+
if (!dev_res)
1254+
pci_dev_res_add_to_list(realloc_head, dev, res, 0, align);
12451255
*children_add_size += r_size;
12461256
*add_align = max(align, *add_align);
12471257

0 commit comments

Comments
 (0)