static void try_to_suspend(struct work_struct *work) { unsigned int initial_count, final_count; if (!pm_get_wakeup_count(&initial_count, true)) { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[P] suspend abort, wakeup event nonzero\n"); htc_print_active_wakeup_sources(); #endif goto out; } mutex_lock(&autosleep_lock); if (!pm_save_wakeup_count(initial_count)) { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[P] suspend abort, events not matched or being processed\n"); #endif mutex_unlock(&autosleep_lock); goto out; } if (autosleep_state == PM_SUSPEND_ON) { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[P] suspend abort, autosleep_state is ON\n"); #endif mutex_unlock(&autosleep_lock); return; } if (autosleep_state >= PM_SUSPEND_MAX) hibernate(); else { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[R] suspend start\n"); #endif pm_suspend(autosleep_state); } mutex_unlock(&autosleep_lock); if (!pm_get_wakeup_count(&final_count, false)) { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[R] resume end\n"); #endif goto out; } if (final_count == initial_count) { #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[P] wakeup occured for an unknown reason, wait HZ/2\n"); #endif schedule_timeout_uninterruptible(HZ / 2); } #ifdef CONFIG_HTC_POWER_DEBUG pr_info("[R] resume end\n"); #endif out: queue_up_suspend_work(); }
static void try_to_suspend(struct work_struct *work) { unsigned int initial_count, final_count; int error = 0; if (!pm_get_wakeup_count(&initial_count, true)) goto out; mutex_lock(&autosleep_lock); if (!pm_save_wakeup_count(initial_count) || system_state != SYSTEM_RUNNING) { mutex_unlock(&autosleep_lock); goto out; } if (autosleep_state == PM_SUSPEND_ON) { mutex_unlock(&autosleep_lock); return; } if (autosleep_state >= PM_SUSPEND_MAX) hibernate(); else error = pm_suspend(autosleep_state); mutex_unlock(&autosleep_lock); #ifdef CONFIG_SEC_PM if (error) goto out; #endif if (!pm_get_wakeup_count(&final_count, false)) goto out; /* * If the wakeup occured for an unknown reason, wait to prevent the * system from trying to suspend and waking up in a tight loop. */ if (final_count == initial_count) schedule_timeout_uninterruptible(HZ / 2); out: #ifdef CONFIG_SEC_PM if (error) { pr_info("PM: suspend returned(%d)\n", error); schedule_timeout_uninterruptible(HZ / 2); } #endif queue_up_suspend_work(); }
static ssize_t wakeup_count_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { unsigned int val; return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR; }
static ssize_t wakeup_count_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { unsigned int val; pr_info("[autosleep] %s\n", __func__); return pm_get_wakeup_count(&val, true) ? sprintf(buf, "%u\n", val) : -EINTR; }
static void try_to_suspend(struct work_struct *work) { unsigned int initial_count, final_count; if (!pm_get_wakeup_count(&initial_count, true)) goto out; mutex_lock(&autosleep_lock); if (!pm_save_wakeup_count(initial_count)) { mutex_unlock(&autosleep_lock); goto out; } if (autosleep_state == PM_SUSPEND_ON) { mutex_unlock(&autosleep_lock); return; } if (autosleep_state >= PM_SUSPEND_MAX) hibernate(); else pm_suspend(autosleep_state); mutex_unlock(&autosleep_lock); if (!pm_get_wakeup_count(&final_count, false)) goto out; /* * If the wakeup occured for an unknown reason, wait to prevent the * system from trying to suspend and waking up in a tight loop. */ if (final_count == initial_count) schedule_timeout_uninterruptible(HZ / 2); out: queue_up_suspend_work(); }
static bool platform_suspend_again(void) { int count; bool suspend = suspend_ops->suspend_again ? suspend_ops->suspend_again() : false; if (suspend) { /* * pm_get_wakeup_count() gets an updated count of wakeup events * that have occured and will return false (i.e. abort suspend) * if a wakeup event has been started during suspend_again() and * is still active. pm_save_wakeup_count() stores the count * and enables pm_wakeup_pending() to properly analyze wakeup * events before entering suspend in suspend_enter(). */ suspend = pm_get_wakeup_count(&count, false) && pm_save_wakeup_count(count); } return suspend; }
static ssize_t wakeup_count_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%lu\n", pm_get_wakeup_count()); }
static void try_to_suspend(struct work_struct *work) { unsigned int initial_count, final_count; int error = 0; #ifdef CONFIG_PM_SLEEP_HISTORY int i; static unsigned int autosleep_active; static struct wakeup_source *last_ws[4]; struct timespec ts; if (autosleep_active == 0) { autosleep_active = 1; getnstimeofday(&ts); sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_ENTRY, &ts, NULL); } #endif if (!pm_get_wakeup_count(&initial_count, true)) goto out; mutex_lock(&autosleep_lock); if (!pm_save_wakeup_count(initial_count)) { mutex_unlock(&autosleep_lock); goto out; } #ifdef CONFIG_PM_SLEEP_HISTORY memset(last_ws, 0, sizeof(last_ws)); pm_get_last_wakeup_sources(&last_ws[0], sizeof(last_ws)/sizeof(struct wakeup_source *)); autosleep_active = 0; getnstimeofday(&ts); if (last_ws[0]) { sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, &ts, last_ws[0]); for (i = 1; last_ws[i] && i < sizeof(last_ws)/sizeof(struct wakeup_source *); i++) sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, NULL, last_ws[i]); memset(last_ws, 0, sizeof(last_ws)); } else sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, &ts, autosleep_ws); #endif if (autosleep_state == PM_SUSPEND_ON) { mutex_unlock(&autosleep_lock); return; } if (autosleep_state >= PM_SUSPEND_MAX) hibernate(); else error = pm_suspend(autosleep_state); mutex_unlock(&autosleep_lock); #ifdef CONFIG_PM_SLEEP_HISTORY if (autosleep_active == 0) { autosleep_active = 1; getnstimeofday(&ts); sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_ENTRY, &ts, NULL); } if (error) goto out; if (!pm_get_wakeup_count(&final_count, false)) { __pm_wakeup_event(autosleep_ws, AUTOSLEEP_SUSPEND_BLOCK_TIME); goto out; } #else if (error) goto out; if (!pm_get_wakeup_count(&final_count, false)) { __pm_wakeup_event(autosleep_ws, AUTOSLEEP_SUSPEND_BLOCK_TIME); goto out; } #endif /* * If the wakeup occured for an unknown reason, wait to prevent the * system from trying to suspend and waking up in a tight loop. */ if (final_count == initial_count) schedule_timeout_uninterruptible(HZ / 2); out: #ifdef CONFIG_PM_SLEEP_HISTORY memset(last_ws, 0, sizeof(last_ws)); pm_get_last_wakeup_sources(&last_ws[0], sizeof(last_ws)/sizeof(struct wakeup_source *)); if (autosleep_state == PM_SUSPEND_ON) { autosleep_active = 0; getnstimeofday(&ts); if (last_ws[0]) { sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, &ts, last_ws[0]); for (i = 1; last_ws[i] && i < sizeof(last_ws)/sizeof(struct wakeup_source *); i++) sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, NULL, last_ws[i]); memset(last_ws, 0, sizeof(last_ws)); } else sleep_history_marker(SLEEP_HISTORY_AUTOSLEEP_EXIT, &ts, autosleep_ws); } #endif /* * If the device failed to suspend, wait to prevent the * system from trying to suspend and waking up in a tight loop. */ if (error) { pr_info("PM: suspend returned(%d)\n", error); schedule_timeout_uninterruptible(HZ / 2); } queue_up_suspend_work(); }