diff options
Diffstat (limited to 'drivers/char/apm-emulation.c')
| -rw-r--r-- | drivers/char/apm-emulation.c | 40 | 
1 files changed, 17 insertions, 23 deletions
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index 45b987c9889..dd9dfa15e9d 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c @@ -31,7 +31,6 @@  #include <linux/kthread.h>  #include <linux/delay.h> -#include <asm/system.h>  /*   * The apm_bios device is one of the misc char devices. @@ -40,10 +39,7 @@  #define APM_MINOR_DEV	134  /* - * See Documentation/Config.help for the configuration options. - * - * Various options can be changed at boot time as follows: - * (We allow underscores for compatibility with the modules code) + * One option can be changed at boot time as follows:   *	apm=on/off			enable/disable APM   */ @@ -126,7 +122,6 @@ struct apm_user {  /*   * Local variables   */ -static DEFINE_MUTEX(apm_mutex);  static atomic_t suspend_acks_pending = ATOMIC_INIT(0);  static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);  static int apm_disabled; @@ -275,7 +270,6 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)  	if (!as->suser || !as->writer)  		return -EPERM; -	mutex_lock(&apm_mutex);  	switch (cmd) {  	case APM_IOC_SUSPEND:  		mutex_lock(&state_lock); @@ -302,17 +296,13 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)  			/*  			 * Wait for the suspend/resume to complete.  If there  			 * are pending acknowledges, we wait here for them. +			 * wait_event_freezable() is interruptible and pending +			 * signal can cause busy looping.  We aren't doing +			 * anything critical, chill a bit on each iteration.  			 */ -			freezer_do_not_count(); - -			wait_event(apm_suspend_waitqueue, -				   as->suspend_state == SUSPEND_DONE); - -			/* -			 * Since we are waiting until the suspend is done, the -			 * try_to_freeze() in freezer_count() will not trigger -			 */ -			freezer_count(); +			while (wait_event_freezable(apm_suspend_waitqueue, +					as->suspend_state != SUSPEND_ACKED)) +				msleep(10);  			break;  		case SUSPEND_ACKTO:  			as->suspend_result = -ETIMEDOUT; @@ -336,7 +326,6 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)  		mutex_unlock(&state_lock);  		break;  	} -	mutex_unlock(&apm_mutex);  	return err;  } @@ -371,7 +360,6 @@ static int apm_open(struct inode * inode, struct file * filp)  {  	struct apm_user *as; -	mutex_lock(&apm_mutex);  	as = kzalloc(sizeof(*as), GFP_KERNEL);  	if (as) {  		/* @@ -391,7 +379,6 @@ static int apm_open(struct inode * inode, struct file * filp)  		filp->private_data = as;  	} -	mutex_unlock(&apm_mutex);  	return as ? 0 : -ENOMEM;  } @@ -544,6 +531,7 @@ static int apm_suspend_notifier(struct notifier_block *nb,  {  	struct apm_user *as;  	int err; +	unsigned long apm_event;  	/* short-cut emergency suspends */  	if (atomic_read(&userspace_notification_inhibit)) @@ -551,6 +539,9 @@ static int apm_suspend_notifier(struct notifier_block *nb,  	switch (event) {  	case PM_SUSPEND_PREPARE: +	case PM_HIBERNATION_PREPARE: +		apm_event = (event == PM_SUSPEND_PREPARE) ? +			APM_USER_SUSPEND : APM_USER_HIBERNATION;  		/*  		 * Queue an event to all "writer" users that we want  		 * to suspend and need their ack. @@ -563,7 +554,7 @@ static int apm_suspend_notifier(struct notifier_block *nb,  			    as->writer && as->suser) {  				as->suspend_state = SUSPEND_PENDING;  				atomic_inc(&suspend_acks_pending); -				queue_add_event(&as->queue, APM_USER_SUSPEND); +				queue_add_event(&as->queue, apm_event);  			}  		} @@ -611,14 +602,17 @@ static int apm_suspend_notifier(struct notifier_block *nb,  			return NOTIFY_OK;  		/* interrupted by signal */ -		return NOTIFY_BAD; +		return notifier_from_errno(err);  	case PM_POST_SUSPEND: +	case PM_POST_HIBERNATION: +		apm_event = (event == PM_POST_SUSPEND) ? +			APM_NORMAL_RESUME : APM_HIBERNATION_RESUME;  		/*  		 * Anyone on the APM queues will think we're still suspended.  		 * Send a message so everyone knows we're now awake again.  		 */ -		queue_event(APM_NORMAL_RESUME); +		queue_event(apm_event);  		/*  		 * Finally, wake up anyone who is sleeping on the suspend.  | 
