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

Commit 4706515a authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'acpi-pci-pm' and 'acpi-pci-hotplug'

* acpi-pci-pm:
  PCI / ACPI: Install wakeup notify handlers for all PCI devs with ACPI

* acpi-pci-hotplug:
  ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug
  ACPI / PCI / hotplug: Avoid warning when _ADR not present
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
}
EXPORT_SYMBOL(acpi_bus_get_private_data);

void acpi_bus_no_hotplug(acpi_handle handle)
{
	struct acpi_device *adev = NULL;

	acpi_bus_get_device(handle, &adev);
	if (adev)
		adev->flags.no_hotplug = true;
}
EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);

static void acpi_print_osc_error(acpi_handle handle,
	struct acpi_osc_context *context, char *error)
{
+14 −2
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
	bool dsm_detected;
	bool optimus_detected;
	acpi_handle dhandle;
	acpi_handle other_handle;
	acpi_handle rom_handle;
} nouveau_dsm_priv;

@@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
	if (!dhandle)
		return false;

	if (!acpi_has_method(dhandle, "_DSM"))
	if (!acpi_has_method(dhandle, "_DSM")) {
		nouveau_dsm_priv.other_handle = dhandle;
		return false;

	}
	if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
		retval |= NOUVEAU_DSM_HAS_MUX;

@@ -338,6 +340,16 @@ static bool nouveau_dsm_detect(void)
		printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
			acpi_method_name);
		nouveau_dsm_priv.dsm_detected = true;
		/*
		 * On some systems hotplug events are generated for the device
		 * being switched off when _DSM is executed.  They cause ACPI
		 * hotplug to trigger and attempt to remove the device from
		 * the system, which causes it to break down.  Prevent that from
		 * happening by setting the no_hotplug flag for the involved
		 * ACPI device objects.
		 */
		acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
		acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
		ret = true;
	}

+14 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
	bool atpx_detected;
	/* handle for device - and atpx */
	acpi_handle dhandle;
	acpi_handle other_handle;
	struct radeon_atpx atpx;
} radeon_atpx_priv;

@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
		return false;

	status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
	if (ACPI_FAILURE(status))
	if (ACPI_FAILURE(status)) {
		radeon_atpx_priv.other_handle = dhandle;
		return false;

	}
	radeon_atpx_priv.dhandle = dhandle;
	radeon_atpx_priv.atpx.handle = atpx_handle;
	return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
		printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
		       acpi_method_name);
		radeon_atpx_priv.atpx_detected = true;
		/*
		 * On some systems hotplug events are generated for the device
		 * being switched off when ATPX is executed.  They cause ACPI
		 * hotplug to trigger and attempt to remove the device from
		 * the system, which causes it to break down.  Prevent that from
		 * happening by setting the no_hotplug flag for the involved
		 * ACPI device objects.
		 */
		acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
		acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
		return true;
	}
	return false;
+26 −4
Original line number Diff line number Diff line
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,

	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
	if (ACPI_FAILURE(status)) {
		acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
		if (status != AE_NOT_FOUND)
			acpi_handle_warn(handle,
				"can't evaluate _ADR (%#x)\n", status);
		return AE_OK;
	}

@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
	slot->flags &= (~SLOT_ENABLED);
}

static bool acpiphp_no_hotplug(acpi_handle handle)
{
	struct acpi_device *adev = NULL;

	acpi_bus_get_device(handle, &adev);
	return adev && adev->flags.no_hotplug;
}

static bool slot_no_hotplug(struct acpiphp_slot *slot)
{
	struct acpiphp_func *func;

	list_for_each_entry(func, &slot->funcs, sibling)
		if (acpiphp_no_hotplug(func_to_handle(func)))
			return true;

	return false;
}

/**
 * get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev)
		unsigned long long sta;

		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
		alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
		alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
			|| acpiphp_no_hotplug(handle);
	}
	if (!alive) {
		u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
		struct pci_dev *dev, *tmp;

		mutex_lock(&slot->crit_sect);
		/* wake up all functions */
		if (get_slot_status(slot) == ACPI_STA_ALL) {
		if (slot_no_hotplug(slot)) {
			; /* do nothing */
		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
			/* remove stale devices if any */
			list_for_each_entry_safe(dev, tmp, &bus->devices,
						 bus_list)
+12 −9
Original line number Diff line number Diff line
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
static void pci_acpi_setup(struct device *dev)
{
	struct pci_dev *pci_dev = to_pci_dev(dev);
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *adev;
	struct acpi_device *adev = ACPI_COMPANION(dev);

	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
	if (!adev)
		return;

	pci_acpi_add_pm_notifier(adev, pci_dev);
	if (!adev->wakeup.flags.valid)
		return;

	device_set_wakeup_capable(dev, true);
	acpi_pci_sleep_wake(pci_dev, false);

	pci_acpi_add_pm_notifier(adev, pci_dev);
	if (adev->wakeup.flags.run_wake)
		device_set_run_wake(dev, true);
}

static void pci_acpi_cleanup(struct device *dev)
{
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *adev;
	struct acpi_device *adev = ACPI_COMPANION(dev);

	if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
	if (!adev)
		return;

	pci_acpi_remove_pm_notifier(adev);
	if (adev->wakeup.flags.valid) {
		device_set_wakeup_capable(dev, false);
		device_set_run_wake(dev, false);
		pci_acpi_remove_pm_notifier(adev);
	}
}

Loading