From 915413ab92504caa3de6eade077e1efee2b1da65 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 13 May 2016 19:33:07 +0200 Subject: [PATCH] Disable DSM if power resources are in use The Optimus _DSM function would prepare a device to be put in D3cold state when _PS3 is called. Newer laptops should not use this since Windows 8 introduced a new method to put devices in D3cold state[1]. Hopefully this fixes an infinite loop on a Clevo P651RA. Actually putting the parent device (PCIe port) is not done in this patch. [1]: https://msdn.microsoft.com/windows/hardware/drivers/bringup/firmware-requirements-for-d3cold --- bbswitch.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/bbswitch.c b/bbswitch.c index 341608f..975794a 100644 --- a/bbswitch.c +++ b/bbswitch.c @@ -197,6 +197,26 @@ static int bbswitch_optimus_dsm(void) { return 0; } +// Windows 8/8.1/10 do not use DSM to put the device in D3cold state, +// instead it disables power resources on the parent PCIe port device. +static bool has_pr3_support(void) { + acpi_handle parent_handle; + struct acpi_device *ad = NULL; + + if (ACPI_FAILURE(acpi_get_parent(dis_handle, &parent_handle))) { + pr_warn("Failed to obtain the parent device\n"); + return false; + } + + acpi_bus_get_device(parent_handle, &ad); + if (!ad) { + pr_warn("Failed to obtain an ACPI device for handle\n"); + return false; + } + + return ad->power.flags.power_resources; +} + static int bbswitch_acpi_off(void) { if (dsm_type == DSM_TYPE_NVIDIA) { char args[] = {2, 0, 0, 0}; @@ -436,7 +456,9 @@ static int __init bbswitch_init(void) { return -ENODEV; } - if (!skip_optimus_dsm && + if (has_pr3_support()) { + pr_info("skipping _DSM as _PR3 support is detected\n"); + } else if (!skip_optimus_dsm && has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) { dsm_type = DSM_TYPE_OPTIMUS; pr_info("detected an Optimus _DSM function\n");