]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Freezer: Fix APM emulation breakage
authorRafael J. Wysocki <rjw@sisk.pl>
Mon, 17 Dec 2007 00:03:46 +0000 (01:03 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 8 Feb 2008 20:01:33 +0000 (12:01 -0800)
The APM emulation is currently broken as a result of commit
831441862956fffa17b9801db37e6ea1650b0f69
"Freezer: make kernel threads nonfreezable by default"
that removed the PF_NOFREEZE annotations from apm_ioctl() without
adding the appropriate freezer hooks.  Fix it and remove the
unnecessary variable flags from apm_ioctl().

This problem has been fixed in the mainline by
commit cb43c54ca05c01533c45e4d3abfe8f99b7acf624
"Freezer: Fix APM emulation breakage".

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/char/apm-emulation.c
include/linux/freezer.h

index ec116df919d97c043b45ed89637e73624d59810f..72183bd1b3fcc9380862975218385f4ae36c3eca 100644 (file)
@@ -295,7 +295,6 @@ static int
 apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 {
        struct apm_user *as = filp->private_data;
-       unsigned long flags;
        int err = -EINVAL;
 
        if (!as->suser || !as->writer)
@@ -331,10 +330,16 @@ apm_ioctl(struct inode * inode, 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.
                         */
-                       flags = current->flags;
+                       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();
                } else {
                        as->suspend_state = SUSPEND_WAIT;
                        mutex_unlock(&state_lock);
@@ -362,14 +367,10 @@ apm_ioctl(struct inode * inode, 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.
                         */
-                       flags = current->flags;
-
-                       wait_event_interruptible(apm_suspend_waitqueue,
+                       wait_event_freezable(apm_suspend_waitqueue,
                                         as->suspend_state == SUSPEND_DONE);
                }
 
-               current->flags = flags;
-
                mutex_lock(&state_lock);
                err = as->suspend_result;
                as->suspend_state = SUSPEND_NONE;
index efded00ad08c5003bebd89964bb8b8619630a2c2..7fa9500da1f48818800858181f9ca34b17bcb1d6 100644 (file)
@@ -4,6 +4,7 @@
 #define FREEZER_H_INCLUDED
 
 #include <linux/sched.h>
+#include <linux/wait.h>
 
 #ifdef CONFIG_PM_SLEEP
 /*
@@ -126,6 +127,24 @@ static inline void set_freezable(void)
        current->flags &= ~PF_NOFREEZE;
 }
 
+/*
+ * Freezer-friendly wrapper around wait_event_interruptible(), originally
+ * defined in <linux/wait.h>
+ */
+
+#define wait_event_freezable(wq, condition)                            \
+({                                                                     \
+       int __retval;                                                   \
+       do {                                                            \
+               __retval = wait_event_interruptible(wq,                 \
+                               (condition) || freezing(current));      \
+               if (__retval && !freezing(current))                     \
+                       break;                                          \
+               else if (!(condition))                                  \
+                       __retval = -ERESTARTSYS;                        \
+       } while (try_to_freeze());                                      \
+       __retval;                                                       \
+})
 #else /* !CONFIG_PM_SLEEP */
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
@@ -143,6 +162,10 @@ static inline void freezer_do_not_count(void) {}
 static inline void freezer_count(void) {}
 static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 static inline void set_freezable(void) {}
+
+#define wait_event_freezable(wq, condition)                            \
+               wait_event_interruptible(wq, condition)
+
 #endif /* !CONFIG_PM_SLEEP */
 
 #endif /* FREEZER_H_INCLUDED */