Commit 3f6eb5a6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
parents 433b23a3 8c746e22
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, u8 func_no, enum pci
		dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index);
		clear_bit(atu_index, ep->ib_window_map);
		ep_func->bar_to_atu[bar] = 0;
		return;
	}

	/* 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,
		/*
		 * We can only dynamically change a BAR if the new BAR size and
		 * BAR flags do not differ from the existing configuration.
		 *
		 * Note: this safety check only works when the caller uses
		 * a new struct pci_epf_bar in the second set_bar() call.
		 * If the same instance is updated in place and passed in,
		 * we cannot reliably detect invalid barno/size/flags
		 * changes here.
		 */
		if (ep_func->epf_bar[bar]->barno != bar ||
		    ep_func->epf_bar[bar]->size != size ||
@@ -526,9 +533,11 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,

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

		/*
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
config PCI_EPF_TEST
	tristate "PCI Endpoint Test driver"
	depends on PCI_ENDPOINT
	select CONFIGFS_FS
	select CRC32
	help
	   Enable this configuration option to enable the test driver
+26 −16
Original line number Diff line number Diff line
@@ -224,14 +224,21 @@ static struct resource *pbus_select_window_for_type(struct pci_bus *bus,

	switch (iores_type) {
	case IORESOURCE_IO:
		return pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
		win = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
		if (win && (win->flags & IORESOURCE_IO))
			return win;
		return NULL;

	case IORESOURCE_MEM:
		mmio = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_MEM_WINDOW);
		mmio_pref = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_PREF_MEM_WINDOW);

		if (!(type & IORESOURCE_PREFETCH) ||
		    !(mmio_pref->flags & IORESOURCE_MEM))
		if (mmio && !(mmio->flags & IORESOURCE_MEM))
			mmio = NULL;
		if (mmio_pref && !(mmio_pref->flags & IORESOURCE_MEM))
			mmio_pref = NULL;

		if (!(type & IORESOURCE_PREFETCH) || !mmio_pref)
			return mmio;

		if ((type & IORESOURCE_MEM_64) ||
@@ -1217,30 +1224,33 @@ static bool pbus_size_mem_optional(struct pci_dev *dev, int resno,
	struct resource *res = pci_resource_n(dev, resno);
	bool optional = pci_resource_is_optional(dev, resno);
	resource_size_t r_size = resource_size(res);
	struct pci_dev_resource *dev_res;
	struct pci_dev_resource *dev_res = NULL;

	if (!realloc_head)
		return false;

	if (!optional) {
	/*
	 * Only bridges have optional sizes in realloc_head at this
	 * point. As res_to_dev_res() walks the entire realloc_head
	 * list, skip calling it when known unnecessary.
	 */
		if (!pci_resource_is_bridge_win(resno))
			return false;

	if (pci_resource_is_bridge_win(resno)) {
		dev_res = res_to_dev_res(realloc_head, res);
		if (dev_res) {
			*children_add_size += dev_res->add_size;
			*add_align = max(*add_align, dev_res->min_align);
		}
	}

	if (!optional)
		return false;
	}

	/* Put SRIOV requested res to the optional list */
	/*
	 * Put requested res to the optional list if not there yet (SR-IOV,
	 * disabled ROM). Bridge windows with an optional part are already
	 * on the list.
	 */
	if (!dev_res)
		pci_dev_res_add_to_list(realloc_head, dev, res, 0, align);
	*children_add_size += r_size;
	*add_align = max(align, *add_align);