Exemplo n.º 1
0
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();
}
Exemplo n.º 2
0
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();
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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();
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
static ssize_t wakeup_count_show(struct kobject *kobj,
				struct kobj_attribute *attr,
				char *buf)
{
	return sprintf(buf, "%lu\n", pm_get_wakeup_count());
}
Exemplo n.º 8
0
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();
}