power: fix suspend_sys_sync_wait()
Since the workqueue code deletes the work before executing it, checking for no work item being currently queued to the workqueue is not sufficient to guarantee that all the works have finished execution. Use a counter to guarantee that all the pending suspend_sys_sync() works have finished execution before returning from suspend_sys_sync_wait(). CRs-Fixed: 293595 Signed-off-by: Pratik Patel <pratikp@codeaurora.org> Conflicts: kernel/power/wakelock.c (cherry picked from commit 529461b70c7dc20b0371e54a63844edae905d7a2) Conflicts: kernel/power/wakelock.c Change-Id: I501743b6b76e492e1598df83ebc1178835ae8405
This commit is contained in:
committed by
Stephen Boyd
parent
77c5678ea8
commit
2da9b910c0
@@ -44,6 +44,8 @@ static DEFINE_SPINLOCK(list_lock);
|
||||
static LIST_HEAD(inactive_locks);
|
||||
static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
|
||||
static int current_event_num;
|
||||
static int suspend_sys_sync_count;
|
||||
static DEFINE_SPINLOCK(suspend_sys_sync_lock);
|
||||
static struct workqueue_struct *suspend_sys_sync_work_queue;
|
||||
static DECLARE_COMPLETION(suspend_sys_sync_comp);
|
||||
struct workqueue_struct *suspend_work_queue;
|
||||
@@ -268,7 +270,6 @@ long has_wake_lock(int type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void suspend_sys_sync(struct work_struct *work)
|
||||
{
|
||||
if (debug_mask & DEBUG_SUSPEND)
|
||||
@@ -278,12 +279,22 @@ static void suspend_sys_sync(struct work_struct *work)
|
||||
|
||||
if (debug_mask & DEBUG_SUSPEND)
|
||||
pr_info("sync done.\n");
|
||||
|
||||
spin_lock(&suspend_sys_sync_lock);
|
||||
suspend_sys_sync_count--;
|
||||
spin_unlock(&suspend_sys_sync_lock);
|
||||
}
|
||||
static DECLARE_WORK(suspend_sys_sync_work, suspend_sys_sync);
|
||||
|
||||
void suspend_sys_sync_queue(void)
|
||||
{
|
||||
queue_work(suspend_sys_sync_work_queue, &suspend_sys_sync_work);
|
||||
int ret;
|
||||
|
||||
spin_lock(&suspend_sys_sync_lock);
|
||||
ret = queue_work(suspend_sys_sync_work_queue, &suspend_sys_sync_work);
|
||||
if (ret)
|
||||
suspend_sys_sync_count++;
|
||||
spin_unlock(&suspend_sys_sync_lock);
|
||||
}
|
||||
|
||||
static bool suspend_sys_sync_abort;
|
||||
@@ -295,12 +306,10 @@ static DEFINE_TIMER(suspend_sys_sync_timer, suspend_sys_sync_handler, 0, 0);
|
||||
#define SUSPEND_SYS_SYNC_TIMEOUT (HZ/4)
|
||||
static void suspend_sys_sync_handler(unsigned long arg)
|
||||
{
|
||||
if (workqueue_empty(suspend_sys_sync_work_queue)) {
|
||||
del_timer(&suspend_sys_sync_timer);
|
||||
if (suspend_sys_sync_count == 0) {
|
||||
complete(&suspend_sys_sync_comp);
|
||||
} else if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
|
||||
suspend_sys_sync_abort = true;
|
||||
del_timer(&suspend_sys_sync_timer);
|
||||
complete(&suspend_sys_sync_comp);
|
||||
} else {
|
||||
mod_timer(&suspend_sys_sync_timer, jiffies +
|
||||
@@ -311,7 +320,8 @@ static void suspend_sys_sync_handler(unsigned long arg)
|
||||
int suspend_sys_sync_wait(void)
|
||||
{
|
||||
suspend_sys_sync_abort = false;
|
||||
if (!workqueue_empty(suspend_sys_sync_work_queue)) {
|
||||
|
||||
if (suspend_sys_sync_count != 0) {
|
||||
mod_timer(&suspend_sys_sync_timer, jiffies +
|
||||
SUSPEND_SYS_SYNC_TIMEOUT);
|
||||
wait_for_completion(&suspend_sys_sync_comp);
|
||||
|
||||
Reference in New Issue
Block a user