Merge branch 'acpi-general'
* acpi-general:
ACPI / PNP: Do not crash due to stale pointer use during system resume
ACPI / video: Add "Asus UL30VT" to ACPI video detect blacklist
ACPI: do acpisleep dmi check when CONFIG_ACPI_SLEEP is set
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 1e25319..2fcc67d 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -129,283 +129,9 @@
old_suspend_ordering = true;
}
-/**
- * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
- */
-static int acpi_pm_freeze(void)
-{
- acpi_disable_all_gpes();
- acpi_os_wait_events_complete();
- acpi_ec_block_transactions();
- return 0;
-}
-
-/**
- * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS.
- */
-static int acpi_pm_pre_suspend(void)
-{
- acpi_pm_freeze();
- return suspend_nvs_save();
-}
-
-/**
- * __acpi_pm_prepare - Prepare the platform to enter the target state.
- *
- * If necessary, set the firmware waking vector and do arch-specific
- * nastiness to get the wakeup code to the waking vector.
- */
-static int __acpi_pm_prepare(void)
-{
- int error = acpi_sleep_prepare(acpi_target_sleep_state);
- if (error)
- acpi_target_sleep_state = ACPI_STATE_S0;
-
- return error;
-}
-
-/**
- * acpi_pm_prepare - Prepare the platform to enter the target sleep
- * state and disable the GPEs.
- */
-static int acpi_pm_prepare(void)
-{
- int error = __acpi_pm_prepare();
- if (!error)
- error = acpi_pm_pre_suspend();
-
- return error;
-}
-
-static int find_powerf_dev(struct device *dev, void *data)
-{
- struct acpi_device *device = to_acpi_device(dev);
- const char *hid = acpi_device_hid(device);
-
- return !strcmp(hid, ACPI_BUTTON_HID_POWERF);
-}
-
-/**
- * acpi_pm_finish - Instruct the platform to leave a sleep state.
- *
- * This is called after we wake back up (or if entering the sleep state
- * failed).
- */
-static void acpi_pm_finish(void)
-{
- struct device *pwr_btn_dev;
- u32 acpi_state = acpi_target_sleep_state;
-
- acpi_ec_unblock_transactions();
- suspend_nvs_free();
-
- if (acpi_state == ACPI_STATE_S0)
- return;
-
- printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
- acpi_state);
- acpi_disable_wakeup_devices(acpi_state);
- acpi_leave_sleep_state(acpi_state);
-
- /* reset firmware waking vector */
- acpi_set_firmware_waking_vector((acpi_physical_address) 0);
-
- acpi_target_sleep_state = ACPI_STATE_S0;
-
- /* If we were woken with the fixed power button, provide a small
- * hint to userspace in the form of a wakeup event on the fixed power
- * button device (if it can be found).
- *
- * We delay the event generation til now, as the PM layer requires
- * timekeeping to be running before we generate events. */
- if (!pwr_btn_event_pending)
- return;
-
- pwr_btn_event_pending = false;
- pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL,
- find_powerf_dev);
- if (pwr_btn_dev) {
- pm_wakeup_event(pwr_btn_dev, 0);
- put_device(pwr_btn_dev);
- }
-}
-
-/**
- * acpi_pm_end - Finish up suspend sequence.
- */
-static void acpi_pm_end(void)
-{
- /*
- * This is necessary in case acpi_pm_finish() is not called during a
- * failing transition to a sleep state.
- */
- acpi_target_sleep_state = ACPI_STATE_S0;
- acpi_sleep_tts_switch(acpi_target_sleep_state);
-}
-#else /* !CONFIG_ACPI_SLEEP */
-#define acpi_target_sleep_state ACPI_STATE_S0
-#endif /* CONFIG_ACPI_SLEEP */
-
-#ifdef CONFIG_SUSPEND
-static u32 acpi_suspend_states[] = {
- [PM_SUSPEND_ON] = ACPI_STATE_S0,
- [PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
- [PM_SUSPEND_MEM] = ACPI_STATE_S3,
- [PM_SUSPEND_MAX] = ACPI_STATE_S5
-};
-
-/**
- * acpi_suspend_begin - Set the target system sleep state to the state
- * associated with given @pm_state, if supported.
- */
-static int acpi_suspend_begin(suspend_state_t pm_state)
-{
- u32 acpi_state = acpi_suspend_states[pm_state];
- int error = 0;
-
- error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
- if (error)
- return error;
-
- if (sleep_states[acpi_state]) {
- acpi_target_sleep_state = acpi_state;
- acpi_sleep_tts_switch(acpi_target_sleep_state);
- } else {
- printk(KERN_ERR "ACPI does not support this state: %d\n",
- pm_state);
- error = -ENOSYS;
- }
- return error;
-}
-
-/**
- * acpi_suspend_enter - Actually enter a sleep state.
- * @pm_state: ignored
- *
- * Flush caches and go to sleep. For STR we have to call arch-specific
- * assembly, which in turn call acpi_enter_sleep_state().
- * It's unfortunate, but it works. Please fix if you're feeling frisky.
- */
-static int acpi_suspend_enter(suspend_state_t pm_state)
-{
- acpi_status status = AE_OK;
- u32 acpi_state = acpi_target_sleep_state;
- int error;
-
- ACPI_FLUSH_CPU_CACHE();
-
- switch (acpi_state) {
- case ACPI_STATE_S1:
- barrier();
- status = acpi_enter_sleep_state(acpi_state);
- break;
-
- case ACPI_STATE_S3:
- error = acpi_suspend_lowlevel();
- if (error)
- return error;
- pr_info(PREFIX "Low-level resume complete\n");
- break;
- }
-
- /* This violates the spec but is required for bug compatibility. */
- acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
-
- /* Reprogram control registers */
- acpi_leave_sleep_state_prep(acpi_state);
-
- /* ACPI 3.0 specs (P62) says that it's the responsibility
- * of the OSPM to clear the status bit [ implying that the
- * POWER_BUTTON event should not reach userspace ]
- *
- * However, we do generate a small hint for userspace in the form of
- * a wakeup event. We flag this condition for now and generate the
- * event later, as we're currently too early in resume to be able to
- * generate wakeup events.
- */
- if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
- acpi_event_status pwr_btn_status;
-
- acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
-
- if (pwr_btn_status & ACPI_EVENT_FLAG_SET) {
- acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
- /* Flag for later */
- pwr_btn_event_pending = true;
- }
- }
-
- /*
- * Disable and clear GPE status before interrupt is enabled. Some GPEs
- * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
- * acpi_leave_sleep_state will reenable specific GPEs later
- */
- acpi_disable_all_gpes();
- /* Allow EC transactions to happen. */
- acpi_ec_unblock_transactions_early();
-
- suspend_nvs_restore();
-
- return ACPI_SUCCESS(status) ? 0 : -EFAULT;
-}
-
-static int acpi_suspend_state_valid(suspend_state_t pm_state)
-{
- u32 acpi_state;
-
- switch (pm_state) {
- case PM_SUSPEND_ON:
- case PM_SUSPEND_STANDBY:
- case PM_SUSPEND_MEM:
- acpi_state = acpi_suspend_states[pm_state];
-
- return sleep_states[acpi_state];
- default:
- return 0;
- }
-}
-
-static const struct platform_suspend_ops acpi_suspend_ops = {
- .valid = acpi_suspend_state_valid,
- .begin = acpi_suspend_begin,
- .prepare_late = acpi_pm_prepare,
- .enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
- .end = acpi_pm_end,
-};
-
-/**
- * acpi_suspend_begin_old - Set the target system sleep state to the
- * state associated with given @pm_state, if supported, and
- * execute the _PTS control method. This function is used if the
- * pre-ACPI 2.0 suspend ordering has been requested.
- */
-static int acpi_suspend_begin_old(suspend_state_t pm_state)
-{
- int error = acpi_suspend_begin(pm_state);
- if (!error)
- error = __acpi_pm_prepare();
-
- return error;
-}
-
-/*
- * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
- * been requested.
- */
-static const struct platform_suspend_ops acpi_suspend_ops_old = {
- .valid = acpi_suspend_state_valid,
- .begin = acpi_suspend_begin_old,
- .prepare_late = acpi_pm_pre_suspend,
- .enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
- .end = acpi_pm_end,
- .recover = acpi_pm_finish,
-};
-
static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
{
- old_suspend_ordering = true;
+ acpi_old_suspend_ordering();
return 0;
}
@@ -571,6 +297,286 @@
},
{},
};
+
+static void acpi_sleep_dmi_check(void)
+{
+ dmi_check_system(acpisleep_dmi_table);
+}
+
+/**
+ * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
+ */
+static int acpi_pm_freeze(void)
+{
+ acpi_disable_all_gpes();
+ acpi_os_wait_events_complete();
+ acpi_ec_block_transactions();
+ return 0;
+}
+
+/**
+ * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS.
+ */
+static int acpi_pm_pre_suspend(void)
+{
+ acpi_pm_freeze();
+ return suspend_nvs_save();
+}
+
+/**
+ * __acpi_pm_prepare - Prepare the platform to enter the target state.
+ *
+ * If necessary, set the firmware waking vector and do arch-specific
+ * nastiness to get the wakeup code to the waking vector.
+ */
+static int __acpi_pm_prepare(void)
+{
+ int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ if (error)
+ acpi_target_sleep_state = ACPI_STATE_S0;
+
+ return error;
+}
+
+/**
+ * acpi_pm_prepare - Prepare the platform to enter the target sleep
+ * state and disable the GPEs.
+ */
+static int acpi_pm_prepare(void)
+{
+ int error = __acpi_pm_prepare();
+ if (!error)
+ error = acpi_pm_pre_suspend();
+
+ return error;
+}
+
+static int find_powerf_dev(struct device *dev, void *data)
+{
+ struct acpi_device *device = to_acpi_device(dev);
+ const char *hid = acpi_device_hid(device);
+
+ return !strcmp(hid, ACPI_BUTTON_HID_POWERF);
+}
+
+/**
+ * acpi_pm_finish - Instruct the platform to leave a sleep state.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+static void acpi_pm_finish(void)
+{
+ struct device *pwr_btn_dev;
+ u32 acpi_state = acpi_target_sleep_state;
+
+ acpi_ec_unblock_transactions();
+ suspend_nvs_free();
+
+ if (acpi_state == ACPI_STATE_S0)
+ return;
+
+ printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
+ acpi_state);
+ acpi_disable_wakeup_devices(acpi_state);
+ acpi_leave_sleep_state(acpi_state);
+
+ /* reset firmware waking vector */
+ acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+
+ acpi_target_sleep_state = ACPI_STATE_S0;
+
+ /* If we were woken with the fixed power button, provide a small
+ * hint to userspace in the form of a wakeup event on the fixed power
+ * button device (if it can be found).
+ *
+ * We delay the event generation til now, as the PM layer requires
+ * timekeeping to be running before we generate events. */
+ if (!pwr_btn_event_pending)
+ return;
+
+ pwr_btn_event_pending = false;
+ pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL,
+ find_powerf_dev);
+ if (pwr_btn_dev) {
+ pm_wakeup_event(pwr_btn_dev, 0);
+ put_device(pwr_btn_dev);
+ }
+}
+
+/**
+ * acpi_pm_end - Finish up suspend sequence.
+ */
+static void acpi_pm_end(void)
+{
+ /*
+ * This is necessary in case acpi_pm_finish() is not called during a
+ * failing transition to a sleep state.
+ */
+ acpi_target_sleep_state = ACPI_STATE_S0;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
+}
+#else /* !CONFIG_ACPI_SLEEP */
+#define acpi_target_sleep_state ACPI_STATE_S0
+static inline void acpi_sleep_dmi_check(void) {}
+#endif /* CONFIG_ACPI_SLEEP */
+
+#ifdef CONFIG_SUSPEND
+static u32 acpi_suspend_states[] = {
+ [PM_SUSPEND_ON] = ACPI_STATE_S0,
+ [PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
+ [PM_SUSPEND_MEM] = ACPI_STATE_S3,
+ [PM_SUSPEND_MAX] = ACPI_STATE_S5
+};
+
+/**
+ * acpi_suspend_begin - Set the target system sleep state to the state
+ * associated with given @pm_state, if supported.
+ */
+static int acpi_suspend_begin(suspend_state_t pm_state)
+{
+ u32 acpi_state = acpi_suspend_states[pm_state];
+ int error = 0;
+
+ error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
+ if (error)
+ return error;
+
+ if (sleep_states[acpi_state]) {
+ acpi_target_sleep_state = acpi_state;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
+ } else {
+ printk(KERN_ERR "ACPI does not support this state: %d\n",
+ pm_state);
+ error = -ENOSYS;
+ }
+ return error;
+}
+
+/**
+ * acpi_suspend_enter - Actually enter a sleep state.
+ * @pm_state: ignored
+ *
+ * Flush caches and go to sleep. For STR we have to call arch-specific
+ * assembly, which in turn call acpi_enter_sleep_state().
+ * It's unfortunate, but it works. Please fix if you're feeling frisky.
+ */
+static int acpi_suspend_enter(suspend_state_t pm_state)
+{
+ acpi_status status = AE_OK;
+ u32 acpi_state = acpi_target_sleep_state;
+ int error;
+
+ ACPI_FLUSH_CPU_CACHE();
+
+ switch (acpi_state) {
+ case ACPI_STATE_S1:
+ barrier();
+ status = acpi_enter_sleep_state(acpi_state);
+ break;
+
+ case ACPI_STATE_S3:
+ error = acpi_suspend_lowlevel();
+ if (error)
+ return error;
+ pr_info(PREFIX "Low-level resume complete\n");
+ break;
+ }
+
+ /* This violates the spec but is required for bug compatibility. */
+ acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
+
+ /* Reprogram control registers */
+ acpi_leave_sleep_state_prep(acpi_state);
+
+ /* ACPI 3.0 specs (P62) says that it's the responsibility
+ * of the OSPM to clear the status bit [ implying that the
+ * POWER_BUTTON event should not reach userspace ]
+ *
+ * However, we do generate a small hint for userspace in the form of
+ * a wakeup event. We flag this condition for now and generate the
+ * event later, as we're currently too early in resume to be able to
+ * generate wakeup events.
+ */
+ if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
+ acpi_event_status pwr_btn_status;
+
+ acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
+
+ if (pwr_btn_status & ACPI_EVENT_FLAG_SET) {
+ acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
+ /* Flag for later */
+ pwr_btn_event_pending = true;
+ }
+ }
+
+ /*
+ * Disable and clear GPE status before interrupt is enabled. Some GPEs
+ * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
+ * acpi_leave_sleep_state will reenable specific GPEs later
+ */
+ acpi_disable_all_gpes();
+ /* Allow EC transactions to happen. */
+ acpi_ec_unblock_transactions_early();
+
+ suspend_nvs_restore();
+
+ return ACPI_SUCCESS(status) ? 0 : -EFAULT;
+}
+
+static int acpi_suspend_state_valid(suspend_state_t pm_state)
+{
+ u32 acpi_state;
+
+ switch (pm_state) {
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ acpi_state = acpi_suspend_states[pm_state];
+
+ return sleep_states[acpi_state];
+ default:
+ return 0;
+ }
+}
+
+static const struct platform_suspend_ops acpi_suspend_ops = {
+ .valid = acpi_suspend_state_valid,
+ .begin = acpi_suspend_begin,
+ .prepare_late = acpi_pm_prepare,
+ .enter = acpi_suspend_enter,
+ .wake = acpi_pm_finish,
+ .end = acpi_pm_end,
+};
+
+/**
+ * acpi_suspend_begin_old - Set the target system sleep state to the
+ * state associated with given @pm_state, if supported, and
+ * execute the _PTS control method. This function is used if the
+ * pre-ACPI 2.0 suspend ordering has been requested.
+ */
+static int acpi_suspend_begin_old(suspend_state_t pm_state)
+{
+ int error = acpi_suspend_begin(pm_state);
+ if (!error)
+ error = __acpi_pm_prepare();
+
+ return error;
+}
+
+/*
+ * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
+ * been requested.
+ */
+static const struct platform_suspend_ops acpi_suspend_ops_old = {
+ .valid = acpi_suspend_state_valid,
+ .begin = acpi_suspend_begin_old,
+ .prepare_late = acpi_pm_pre_suspend,
+ .enter = acpi_suspend_enter,
+ .wake = acpi_pm_finish,
+ .end = acpi_pm_end,
+ .recover = acpi_pm_finish,
+};
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
@@ -730,13 +736,13 @@
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0;
-
- dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled)
return 0;
+ acpi_sleep_dmi_check();
+
sleep_states[ACPI_STATE_S0] = 1;
printk(KERN_INFO PREFIX "(supports S0");
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index b728880..4ac2593 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -156,6 +156,14 @@
DMI_MATCH(DMI_BOARD_NAME, "X360"),
},
},
+ {
+ .callback = video_detect_force_vendor,
+ .ident = "Asus UL30VT",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
+ },
+ },
{ },
};
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 653d563..93a16ee 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -95,6 +95,9 @@
return -ENODEV;
}
+ if (WARN_ON_ONCE(acpi_dev != dev->data))
+ dev->data = acpi_dev;
+
ret = pnpacpi_build_resource_template(dev, &buffer);
if (ret)
return ret;