History

ACPI / LPSS: Power up LPSS devices during enumeration

Commit 7cd8407 (ACPI / PM: Do not execute _PS0 for devices without _PSC during initialization) introduced a regression on some systems with Intel Lynxpoint Low-Power Subsystem (LPSS) where some devices need to be powered up during initialization, but their device objects in the ACPI namespace have _PS0 and _PS3 only (without _PSC or power resources). To work around this problem, make the ACPI LPSS driver power up devices it knows about by using a new helper function acpi_device_fix_up_power() that does all of the necessary sanity checks and calls acpi_dev_pm_explicit_set() to put the device into D0.

Rafael J. Wysocki committed 13 years ago

Commit b9e95fc1 parent 6ee22e93 files · +36 −6Browse files

Unified · Split

3 files
  1. drivers/acpi/acpi_lpss.c +15 −6
  2. drivers/acpi/device_pm.c +20 −0
  3. include/acpi/acpi_bus.h +1 −0
drivers/acpi/acpi_lpss.c+15−6
@@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev, · 163 unmodified lines
164164 if (dev_desc->clk_required) {
165165 ret = register_device_clock(adev, pdata);
166166 if (ret) {
167− /*
168− * Skip the device, but don't terminate the namespace
169− * scan.
170− */
171− kfree(pdata);
172− return 0;
167+ /* Skip the device, but continue the namespace scan. */
168+ ret = 0;
169+ goto err_out;
173170 }
174171 }
175172
173+ /*
174+ * This works around a known issue in ACPI tables where LPSS devices
175+ * have _PS0 and _PS3 without _PSC (and no power resources), so
176+ * acpi_bus_init_power() will assume that the BIOS has put them into D0.
177+ */
178+ ret = acpi_device_fix_up_power(adev);
179+ if (ret) {
180+ /* Skip the device, but continue the namespace scan. */
181+ ret = 0;
182+ goto err_out;
183+ }
184+
176185 adev->driver_data = pdata;
177186 ret = acpi_create_platform_device(adev, id);
178187 if (ret > 0)
drivers/acpi/device_pm.c+20−0
@@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device) · 289 unmodified lines
290290 return 0;
291291 }
292292
293+/**
294+ * acpi_device_fix_up_power - Force device with missing _PSC into D0.
295+ * @device: Device object whose power state is to be fixed up.
296+ *
297+ * Devices without power resources and _PSC, but having _PS0 and _PS3 defined,
298+ * are assumed to be put into D0 by the BIOS. However, in some cases that may
299+ * not be the case and this function should be used then.
300+ */
301+int acpi_device_fix_up_power(struct acpi_device *device)
302+{
303+ int ret = 0;
304+
305+ if (!device->power.flags.power_resources
306+ && !device->power.flags.explicit_get
307+ && device->power.state == ACPI_STATE_D0)
308+ ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
309+
310+ return ret;
311+}
312+
293313 int acpi_bus_update_power(acpi_handle handle, int *state_p)
294314 {
295315 struct acpi_device *device;
include/acpi/acpi_bus.h+1−0
@@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state); · 381 unmodified lines
382382 int acpi_device_get_power(struct acpi_device *device, int *state);
383383 int acpi_device_set_power(struct acpi_device *device, int state);
384384 int acpi_bus_init_power(struct acpi_device *device);
385+int acpi_device_fix_up_power(struct acpi_device *device);
385386 int acpi_bus_update_power(acpi_handle handle, int *state_p);
386387 bool acpi_bus_power_manageable(acpi_handle handle);
387388