Commit 9b707712 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pci fixes from Bjorn Helgaas:

 - Create pwrctrl devices only for DT nodes below a PCI controller that
   describe PCI devices and are related to a power supply; this prevents
   waiting indefinitely for pwrctrl drivers that will never probe
   (Manivannan Sadhasivam)

 - Restore endpoint BAR mapping on subrange setup failure to make
   selftest reliable (Koichiro Den)

* tag 'pci-v7.0-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
  PCI: endpoint: pci-epf-test: Roll back BAR mapping when subrange setup fails
  PCI/pwrctrl: Create pwrctrl devices only for PCI device nodes
  PCI/pwrctrl: Ensure that remote endpoint node parent has supply requirement
parents a1d9d8e8 21647677
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -894,6 +894,11 @@ static void pci_epf_test_bar_subrange_setup(struct pci_epf_test *epf_test,
		dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret);
		bar->submap = old_submap;
		bar->num_submap = old_nsub;
		ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, bar);
		if (ret)
			dev_warn(&epf->dev, "Failed to restore the original BAR mapping: %d\n",
				 ret);

		kfree(submap);
		goto err;
	}
+41 −13
Original line number Diff line number Diff line
@@ -268,6 +268,46 @@ int pci_pwrctrl_power_on_devices(struct device *parent)
}
EXPORT_SYMBOL_GPL(pci_pwrctrl_power_on_devices);

/*
 * Check whether the pwrctrl device really needs to be created or not. The
 * pwrctrl device will only be created if the node satisfies below requirements:
 *
 * 1. Presence of compatible property with "pci" prefix to match against the
 *    pwrctrl driver (AND)
 * 2. At least one of the power supplies defined in the devicetree node of the
 *    device (OR) in the remote endpoint parent node to indicate pwrctrl
 *    requirement.
 */
static bool pci_pwrctrl_is_required(struct device_node *np)
{
	struct device_node *endpoint;
	const char *compat;
	int ret;

	ret = of_property_read_string(np, "compatible", &compat);
	if (ret < 0)
		return false;

	if (!strstarts(compat, "pci"))
		return false;

	if (of_pci_supply_present(np))
		return true;

	if (of_graph_is_present(np)) {
		for_each_endpoint_of_node(np, endpoint) {
			struct device_node *remote __free(device_node) =
				of_graph_get_remote_port_parent(endpoint);
			if (remote) {
				if (of_pci_supply_present(remote))
					return true;
			}
		}
	}

	return false;
}

static int pci_pwrctrl_create_device(struct device_node *np,
				     struct device *parent)
{
@@ -287,19 +327,7 @@ static int pci_pwrctrl_create_device(struct device_node *np,
		return 0;
	}

	/*
	 * Sanity check to make sure that the node has the compatible property
	 * to allow driver binding.
	 */
	if (!of_property_present(np, "compatible"))
		return 0;

	/*
	 * Check whether the pwrctrl device really needs to be created or not.
	 * This is decided based on at least one of the power supplies defined
	 * in the devicetree node of the device or the graph property.
	 */
	if (!of_pci_supply_present(np) && !of_graph_is_present(np)) {
	if (!pci_pwrctrl_is_required(np)) {
		dev_dbg(parent, "Skipping OF node: %s\n", np->name);
		return 0;
	}