Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f64c1464 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/hotplug'

  - fix use-before-set error in ibmphp (Dan Carpenter)

  - fix pciehp timeouts caused by Command Completed errata (Bjorn Helgaas)

  - fix refcounting in pnv_php hotplug (Julia Lawall)

  - clear pciehp Presence Detect and Data Link Layer Status Changed on
    resume so we don't miss hotplug events (Mika Westerberg)

  - only request pciehp control if we support it, so platform can use ACPI
    hotplug otherwise (Mika Westerberg)

  - convert SHPC to be builtin only (Mika Westerberg)

  - request SHPC control via _OSC if we support it (Mika Westerberg)

  - simplify SHPC handoff from firmware (Mika Westerberg)

* pci/hotplug:
  PCI: Improve "partially hidden behind bridge" log message
  PCI: Improve pci_scan_bridge() and pci_scan_bridge_extend() doc
  PCI: Move resource distribution for single bridge outside loop
  PCI: Account for all bridges on bus when distributing bus numbers
  ACPI / hotplug / PCI: Drop unnecessary parentheses
  ACPI / hotplug / PCI: Mark stale PCI devices disconnected
  ACPI / hotplug / PCI: Don't scan bridges managed by native hotplug
  PCI: hotplug: Add hotplug_is_native()
  PCI: shpchp: Add shpchp_is_native()
  PCI: shpchp: Fix AMD POGO identification
  PCI: shpchp: Use dev_printk() for OSHP-related messages
  PCI: shpchp: Remove get_hp_hw_control_from_firmware() wrapper
  PCI: shpchp: Remove acpi_get_hp_hw_control_from_firmware() flags
  PCI: shpchp: Rely on previous _OSC results
  PCI: shpchp: Request SHPC control via _OSC when adding host bridge
  PCI: shpchp: Convert SHPC to be builtin only
  PCI: pciehp: Make pciehp_is_native() stricter
  PCI: pciehp: Rename host->native_hotplug to host->native_pcie_hotplug
  PCI: pciehp: Request control of native hotplug only if supported
  PCI: pciehp: Clear Presence Detect and Data Link Layer Status Changed on resume
  PCI: pnv_php: Add missing of_node_put()
  PCI: pciehp: Add quirk for Command Completed errata
  PCI: Add Qualcomm vendor ID
  PCI: ibmphp: Fix use-before-set in get_max_bus_speed()

# Conflicts:
#	drivers/acpi/pci_root.c
parents 5e3165d1 e412d63d
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -473,12 +473,17 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
	}

	control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL
		| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
		| OSC_PCI_EXPRESS_PME_CONTROL;

	if (IS_ENABLED(CONFIG_PCIEASPM))
		control |= OSC_PCI_EXPRESS_LTR_CONTROL;

	if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
		control |= OSC_PCI_EXPRESS_NATIVE_HP_CONTROL;

	if (IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC))
		control |= OSC_PCI_SHPC_NATIVE_HP_CONTROL;

	if (pci_aer_available()) {
		if (aer_acpi_firmware_first())
			dev_info(&device->dev,
@@ -904,7 +909,9 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,

	host_bridge = to_pci_host_bridge(bus->bridge);
	if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
		host_bridge->native_hotplug = 0;
		host_bridge->native_pcie_hotplug = 0;
	if (!(root->osc_control_set & OSC_PCI_SHPC_NATIVE_HP_CONTROL))
		host_bridge->native_shpc_hotplug = 0;
	if (!(root->osc_control_set & OSC_PCI_EXPRESS_AER_CONTROL))
		host_bridge->native_aer = 0;
	if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL))
+1 −4
Original line number Diff line number Diff line
@@ -104,14 +104,11 @@ config HOTPLUG_PCI_CPCI_GENERIC
	  When in doubt, say N.

config HOTPLUG_PCI_SHPC
	tristate "SHPC PCI Hotplug driver"
	bool "SHPC PCI Hotplug driver"
	help
	  Say Y here if you have a motherboard with a SHPC PCI Hotplug
	  controller.

	  To compile this driver as a module, choose M here: the
	  module will be called shpchp.

	  When in doubt, say N.

config HOTPLUG_PCI_POWERNV
+17 −28
Original line number Diff line number Diff line
@@ -63,22 +63,17 @@ static acpi_status acpi_run_oshp(acpi_handle handle)
/**
 * acpi_get_hp_hw_control_from_firmware
 * @dev: the pci_dev of the bridge that has a hotplug controller
 * @flags: requested control bits for _OSC
 *
 * Attempt to take hotplug control from firmware.
 */
int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
{
	const struct pci_host_bridge *host;
	const struct acpi_pci_root *root;
	acpi_status status;
	acpi_handle chandle, handle;
	struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };

	flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL;
	if (!flags) {
		err("Invalid flags %u specified!\n", flags);
		return -EINVAL;
	}

	/*
	 * Per PCI firmware specification, we should run the ACPI _OSC
	 * method to get control of hotplug hardware before using it. If
@@ -88,25 +83,20 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
	 * OSHP within the scope of the hotplug controller and its parents,
	 * up to the host bridge under which this controller exists.
	 */
	handle = acpi_find_root_bridge_handle(pdev);
	if (handle) {
		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
		dbg("Trying to get hotplug control for %s\n",
				(char *)string.pointer);
		status = acpi_pci_osc_control_set(handle, &flags, flags);
		if (ACPI_SUCCESS(status))
			goto got_one;
		if (status == AE_SUPPORT)
	if (shpchp_is_native(pdev))
		return 0;

	/* If _OSC exists, we should not evaluate OSHP */
	host = pci_find_host_bridge(pdev->bus);
	root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
	if (root->osc_support_set)
		goto no_control;
		kfree(string.pointer);
		string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
	}

	handle = ACPI_HANDLE(&pdev->dev);
	if (!handle) {
		/*
		 * This hotplug controller was not listed in the ACPI name
		 * space at all. Try to get acpi handle of parent pci bus.
		 * space at all. Try to get ACPI handle of parent PCI bus.
		 */
		struct pci_bus *pbus;
		for (pbus = pdev->bus; pbus; pbus = pbus->parent) {
@@ -118,7 +108,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)

	while (handle) {
		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
		dbg("Trying to get hotplug control for %s\n",
		pci_info(pdev, "Requesting control of SHPC hotplug via OSHP (%s)\n",
			 (char *)string.pointer);
		status = acpi_run_oshp(handle);
		if (ACPI_SUCCESS(status))
@@ -131,13 +121,12 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
			break;
	}
no_control:
	dbg("Cannot get control of hotplug hardware for pci %s\n",
	    pci_name(pdev));
	pci_info(pdev, "Cannot get control of SHPC hotplug\n");
	kfree(string.pointer);
	return -ENODEV;
got_one:
	dbg("Gained control for hotplug HW for pci %s (%s)\n",
	    pci_name(pdev), (char *)string.pointer);
	pci_info(pdev, "Gained control of SHPC hotplug (%s)\n",
		 (char *)string.pointer);
	kfree(string.pointer);
	return 0;
}
+65 −19
Original line number Diff line number Diff line
@@ -287,11 +287,12 @@ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data,
	/*
	 * Expose slots to user space for functions that have _EJ0 or _RMV or
	 * are located in dock stations.  Do not expose them for devices handled
	 * by the native PCIe hotplug (PCIeHP), becuase that code is supposed to
	 * expose slots to user space in those cases.
	 * by the native PCIe hotplug (PCIeHP) or standard PCI hotplug
	 * (SHPCHP), because that code is supposed to expose slots to user
	 * space in those cases.
	 */
	if ((acpi_pci_check_ejectable(pbus, handle) || is_dock_device(adev))
	    && !(pdev && pdev->is_hotplug_bridge && pciehp_is_native(pdev))) {
	    && !(pdev && hotplug_is_native(pdev))) {
		unsigned long long sun;
		int retval;

@@ -430,6 +431,29 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot)
	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
}

static void acpiphp_native_scan_bridge(struct pci_dev *bridge)
{
	struct pci_bus *bus = bridge->subordinate;
	struct pci_dev *dev;
	int max;

	if (!bus)
		return;

	max = bus->busn_res.start;
	/* Scan already configured non-hotplug bridges */
	for_each_pci_bridge(dev, bus) {
		if (!hotplug_is_native(dev))
			max = pci_scan_bridge(bus, dev, max, 0);
	}

	/* Scan non-hotplug bridges that need to be reconfigured */
	for_each_pci_bridge(dev, bus) {
		if (!hotplug_is_native(dev))
			max = pci_scan_bridge(bus, dev, max, 1);
	}
}

/**
 * enable_slot - enable, configure a slot
 * @slot: slot to be enabled
@@ -442,8 +466,23 @@ static void enable_slot(struct acpiphp_slot *slot)
	struct pci_dev *dev;
	struct pci_bus *bus = slot->bus;
	struct acpiphp_func *func;
	int max, pass;

	if (bus->self && hotplug_is_native(bus->self)) {
		/*
		 * If native hotplug is used, it will take care of hotplug
		 * slot management and resource allocation for hotplug
		 * bridges. However, ACPI hotplug may still be used for
		 * non-hotplug bridges to bring in additional devices such
		 * as a Thunderbolt host controller.
		 */
		for_each_pci_bridge(dev, bus) {
			if (PCI_SLOT(dev->devfn) == slot->device)
				acpiphp_native_scan_bridge(dev);
		}
		pci_assign_unassigned_bridge_resources(bus->self);
	} else {
		LIST_HEAD(add_list);
		int max, pass;

		acpiphp_rescan_slot(slot);
		max = acpiphp_max_busnr(bus);
@@ -456,11 +495,13 @@ static void enable_slot(struct acpiphp_slot *slot)
				if (pass && dev->subordinate) {
					check_hotplug_bridge(slot, dev);
					pcibios_resource_survey_bus(dev->subordinate);
				__pci_bus_size_bridges(dev->subordinate, &add_list);
					__pci_bus_size_bridges(dev->subordinate,
							       &add_list);
				}
			}
		}
		__pci_bus_assign_resources(bus, &add_list, NULL);
	}

	acpiphp_sanitize_bus(bus);
	pcie_bus_configure_settings(bus);
@@ -481,7 +522,7 @@ static void enable_slot(struct acpiphp_slot *slot)
		if (!dev) {
			/* Do not set SLOT_ENABLED flag if some funcs
			   are not added. */
			slot->flags &= (~SLOT_ENABLED);
			slot->flags &= ~SLOT_ENABLED;
			continue;
		}
	}
@@ -510,7 +551,7 @@ static void disable_slot(struct acpiphp_slot *slot)
	list_for_each_entry(func, &slot->funcs, sibling)
		acpi_bus_trim(func_to_acpi_device(func));

	slot->flags &= (~SLOT_ENABLED);
	slot->flags &= ~SLOT_ENABLED;
}

static bool slot_no_hotplug(struct acpiphp_slot *slot)
@@ -608,6 +649,11 @@ static void trim_stale_devices(struct pci_dev *dev)
		alive = pci_device_is_present(dev);

	if (!alive) {
		pci_dev_set_disconnected(dev, NULL);
		if (pci_has_subordinate(dev))
			pci_walk_bus(dev->subordinate, pci_dev_set_disconnected,
				     NULL);

		pci_stop_and_remove_bus_device(dev);
		if (adev)
			acpi_bus_trim(adev);
+1 −1
Original line number Diff line number Diff line
@@ -379,7 +379,7 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 *value)

static int get_max_bus_speed(struct slot *slot)
{
	int rc;
	int rc = 0;
	u8 mode = 0;
	enum pci_bus_speed speed;
	struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus;
Loading