x86: Switch apm to unlocked_kernel
Alan Cox [Thu, 22 May 2008 20:22:04 +0000 (21:22 +0100)]
This pushes the lock a fair way down and the final kill looks like it
should be an easy project for someone who wants to have a shot at it.

Signed-off-by: Alan Cox <alan@redhat.com>
Cc: mingo@redhat.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

arch/x86/kernel/apm_32.c

index bf9290e..00e6d13 100644 (file)
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
+#include <linux/smp_lock.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -1149,7 +1150,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
                                as->event_tail = 0;
                }
                as->events[as->event_head] = event;
-               if ((!as->suser) || (!as->writer))
+               if (!as->suser || !as->writer)
                        continue;
                switch (event) {
                case APM_SYS_SUSPEND:
@@ -1396,7 +1397,7 @@ static void apm_mainloop(void)
 
 static int check_apm_user(struct apm_user *as, const char *func)
 {
-       if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
+       if (as == NULL || as->magic != APM_BIOS_MAGIC) {
                printk(KERN_ERR "apm: %s passed bad filp\n", func);
                return 1;
        }
@@ -1459,18 +1460,19 @@ static unsigned int do_poll(struct file *fp, poll_table *wait)
        return 0;
 }
 
-static int do_ioctl(struct inode *inode, struct file *filp,
-                   u_int cmd, u_long arg)
+static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
 {
        struct apm_user *as;
+       int ret;
 
        as = filp->private_data;
        if (check_apm_user(as, "ioctl"))
                return -EIO;
-       if ((!as->suser) || (!as->writer))
+       if (!as->suser || !as->writer)
                return -EPERM;
        switch (cmd) {
        case APM_IOC_STANDBY:
+               lock_kernel();
                if (as->standbys_read > 0) {
                        as->standbys_read--;
                        as->standbys_pending--;
@@ -1479,8 +1481,10 @@ static int do_ioctl(struct inode *inode, struct file *filp,
                        queue_event(APM_USER_STANDBY, as);
                if (standbys_pending <= 0)
                        standby();
+               unlock_kernel();
                break;
        case APM_IOC_SUSPEND:
+               lock_kernel();
                if (as->suspends_read > 0) {
                        as->suspends_read--;
                        as->suspends_pending--;
@@ -1488,16 +1492,17 @@ static int do_ioctl(struct inode *inode, struct file *filp,
                } else
                        queue_event(APM_USER_SUSPEND, as);
                if (suspends_pending <= 0) {
-                       return suspend(1);
+                       ret = suspend(1);
                } else {
                        as->suspend_wait = 1;
                        wait_event_interruptible(apm_suspend_waitqueue,
                                        as->suspend_wait == 0);
-                       return as->suspend_result;
+                       ret = as->suspend_result;
                }
-               break;
+               unlock_kernel();
+               return ret;
        default:
-               return -EINVAL;
+               return -ENOTTY;
        }
        return 0;
 }
@@ -1860,7 +1865,7 @@ static const struct file_operations apm_bios_fops = {
        .owner          = THIS_MODULE,
        .read           = do_read,
        .poll           = do_poll,
-       .ioctl          = do_ioctl,
+       .unlocked_ioctl = do_ioctl,
        .open           = do_open,
        .release        = do_release,
 };