diff options
| -rw-r--r-- | drivers/acpi/device_pm.c | 39 | 
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index dd314ef9bff..96de787e610 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -145,27 +145,36 @@ int acpi_device_get_power(struct acpi_device *device, int *state)  	}  	/* -	 * Get the device's power state either directly (via _PSC) or -	 * indirectly (via power resources). +	 * Get the device's power state from power resources settings and _PSC, +	 * if available.  	 */ +	if (device->power.flags.power_resources) { +		int error = acpi_power_get_inferred_state(device, &result); +		if (error) +			return error; +	}  	if (device->power.flags.explicit_get) { +		acpi_handle handle = device->handle;  		unsigned long long psc; -		acpi_status status = acpi_evaluate_integer(device->handle, -							   "_PSC", NULL, &psc); +		acpi_status status; + +		status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc);  		if (ACPI_FAILURE(status))  			return -ENODEV; -		result = psc; -	} -	/* The test below covers ACPI_STATE_UNKNOWN too. */ -	if (result <= ACPI_STATE_D2) { -	  ; /* Do nothing. */ -	} else if (device->power.flags.power_resources) { -		int error = acpi_power_get_inferred_state(device, &result); -		if (error) -			return error; -	} else if (result == ACPI_STATE_D3_HOT) { -		result = ACPI_STATE_D3; +		/* +		 * The power resources settings may indicate a power state +		 * shallower than the actual power state of the device. +		 * +		 * Moreover, on systems predating ACPI 4.0, if the device +		 * doesn't depend on any power resources and _PSC returns 3, +		 * that means "power off".  We need to maintain compatibility +		 * with those systems. +		 */ +		if (psc > result && psc < ACPI_STATE_D3_COLD) +			result = psc; +		else if (result == ACPI_STATE_UNKNOWN) +			result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_COLD : psc;  	}  	/*  |