[PATCH 5/8] PM: suspend_block: Switch to list of active and inactive suspend blockers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This allows active suspend blockers to be listed
Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx>--- include/linux/suspend_block.h |    5 ++- kernel/power/suspend_block.c  |   77 ++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 24 deletions(-)
diff --git a/include/linux/suspend_block.h b/include/linux/suspend_block.hindex 7820c60..73ac5f7 100755--- a/include/linux/suspend_block.h+++ b/include/linux/suspend_block.h@@ -16,12 +16,15 @@ #ifndef _LINUX_SUSPEND_BLOCK_H #define _LINUX_SUSPEND_BLOCK_H +#include <linux/list.h>+ /* A suspend_blocker prevents the system from entering suspend when active.  */  struct suspend_blocker { #ifdef CONFIG_SUSPEND_BLOCK-	atomic_t            flags;+	struct list_head    link;+	int                 flags; 	const char         *name; #endif };diff --git a/kernel/power/suspend_block.c b/kernel/power/suspend_block.cindex b4f2191..697f52a 100644--- a/kernel/power/suspend_block.c+++ b/kernel/power/suspend_block.c@@ -33,19 +33,29 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); #define SB_INITIALIZED            (1U << 8) #define SB_ACTIVE                 (1U << 9) +static DEFINE_SPINLOCK(list_lock); static DEFINE_SPINLOCK(state_lock);-static atomic_t suspend_block_count;-static atomic_t current_event_num;+static LIST_HEAD(inactive_blockers);+static LIST_HEAD(active_blockers);+static int current_event_num; struct workqueue_struct *suspend_work_queue; struct suspend_blocker main_suspend_blocker; static suspend_state_t requested_suspend_state = PM_SUSPEND_MEM; static bool enable_suspend_blockers; +static void print_active_blockers_locked(void)+{+	struct suspend_blocker *blocker;++	list_for_each_entry(blocker, &active_blockers, link)+		pr_info("active suspend blocker %s\n", blocker->name);+}+ bool suspend_is_blocked(void) { 	if (WARN_ONCE(!enable_suspend_blockers, "ignoring suspend blockers\n")) 		return 0;-	return !!atomic_read(&suspend_block_count);+	return !list_empty(&active_blockers); }  static void suspend_worker(struct work_struct *work)@@ -62,7 +72,7 @@ retry: 		goto abort; 	} -	entry_event_num = atomic_read(&current_event_num);+	entry_event_num = current_event_num; 	if (debug_mask & DEBUG_SUSPEND) 		pr_info("suspend: enter suspend\n"); 	ret = pm_suspend(requested_suspend_state);@@ -76,7 +86,7 @@ retry: 			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); 	}-	if (atomic_read(&current_event_num) == entry_event_num) {+	if (current_event_num == entry_event_num) { 		if (debug_mask & DEBUG_SUSPEND) 			pr_info("suspend: pm_suspend returned with no event\n"); 		goto retry;@@ -110,6 +120,8 @@ static struct sys_device suspend_block_sysdev = {  */ void suspend_blocker_init(struct suspend_blocker *blocker, const char *name) {+	unsigned long irqflags = 0;+ 	if (name) 		blocker->name = name; 	BUG_ON(!blocker->name);@@ -117,7 +129,12 @@ void suspend_blocker_init(struct suspend_blocker *blocker, const char *name) 	if (debug_mask & DEBUG_SUSPEND_BLOCKER) 		pr_info("suspend_blocker_init name=%s\n", blocker->name); -	atomic_set(&blocker->flags, SB_INITIALIZED);+	blocker->flags = SB_INITIALIZED;+	INIT_LIST_HEAD(&blocker->link);++	spin_lock_irqsave(&list_lock, irqflags);+	list_add(&blocker->link, &inactive_blockers);+	spin_unlock_irqrestore(&list_lock, irqflags); } EXPORT_SYMBOL(suspend_blocker_init); @@ -127,15 +144,15 @@ EXPORT_SYMBOL(suspend_blocker_init);  */ void suspend_blocker_destroy(struct suspend_blocker *blocker) {-	int flags;+	unsigned long irqflags; 	if (debug_mask & DEBUG_SUSPEND_BLOCKER) 		pr_info("suspend_blocker_destroy name=%s\n", blocker->name);-	flags = atomic_xchg(&blocker->flags, 0);-	WARN(!(flags & SB_INITIALIZED), "suspend_blocker_destroy called on "-					"uninitialized suspend_blocker\n");-	if (flags == (SB_INITIALIZED | SB_ACTIVE))-		if (atomic_dec_and_test(&suspend_block_count))-			queue_work(suspend_work_queue, &suspend_work);+	spin_lock_irqsave(&list_lock, irqflags);+	blocker->flags &= ~SB_INITIALIZED;+	list_del(&blocker->link);+	if ((blocker->flags & SB_ACTIVE) && list_empty(&active_blockers))+		queue_work(suspend_work_queue, &suspend_work);+	spin_unlock_irqrestore(&list_lock, irqflags); } EXPORT_SYMBOL(suspend_blocker_destroy); @@ -145,15 +162,19 @@ EXPORT_SYMBOL(suspend_blocker_destroy);  */ void suspend_block(struct suspend_blocker *blocker) {-	BUG_ON(!(atomic_read(&blocker->flags) & SB_INITIALIZED));+	unsigned long irqflags;++	spin_lock_irqsave(&list_lock, irqflags);+	BUG_ON(!(blocker->flags & SB_INITIALIZED)); +	blocker->flags |= SB_ACTIVE;+	list_del(&blocker->link); 	if (debug_mask & DEBUG_SUSPEND_BLOCKER) 		pr_info("suspend_block: %s\n", blocker->name);-	if (atomic_cmpxchg(&blocker->flags, SB_INITIALIZED,-	    SB_INITIALIZED | SB_ACTIVE) == SB_INITIALIZED)-		atomic_inc(&suspend_block_count);+	list_add(&blocker->link, &active_blockers); -	atomic_inc(&current_event_num);+	current_event_num++;+	spin_unlock_irqrestore(&list_lock, irqflags); } EXPORT_SYMBOL(suspend_block); @@ -165,13 +186,23 @@ EXPORT_SYMBOL(suspend_block);  */ void suspend_unblock(struct suspend_blocker *blocker) {+	unsigned long irqflags;++	spin_lock_irqsave(&list_lock, irqflags);+ 	if (debug_mask & DEBUG_SUSPEND_BLOCKER) 		pr_info("suspend_unblock: %s\n", blocker->name);+	list_del(&blocker->link);+	list_add(&blocker->link, &inactive_blockers); -	if (atomic_cmpxchg(&blocker->flags, SB_INITIALIZED | SB_ACTIVE,-	    SB_INITIALIZED) == (SB_INITIALIZED | SB_ACTIVE))-		if (atomic_dec_and_test(&suspend_block_count))-			queue_work(suspend_work_queue, &suspend_work);+	if ((blocker->flags & SB_ACTIVE) && list_empty(&active_blockers))+		queue_work(suspend_work_queue, &suspend_work);+	blocker->flags &= ~(SB_ACTIVE);+	if (blocker == &main_suspend_blocker) {+		if (debug_mask & DEBUG_SUSPEND)+			print_active_blockers_locked();+	}+	spin_unlock_irqrestore(&list_lock, irqflags); } EXPORT_SYMBOL(suspend_unblock); @@ -181,7 +212,7 @@ EXPORT_SYMBOL(suspend_unblock);  */ bool is_blocking_suspend(struct suspend_blocker *blocker) {-	return !!(atomic_read(&blocker->flags) & SB_ACTIVE);+	return !!(blocker->flags & SB_ACTIVE); } EXPORT_SYMBOL(is_blocking_suspend); -- 1.6.1
_______________________________________________linux-pm mailing listlinux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux