diff options
Diffstat (limited to 'arch/x86/kernel/apm_32.c')
-rw-r--r-- | arch/x86/kernel/apm_32.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index bf9290e29013..00e6d1370954 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
@@ -228,6 +228,7 @@ | |||
228 | #include <linux/suspend.h> | 228 | #include <linux/suspend.h> |
229 | #include <linux/kthread.h> | 229 | #include <linux/kthread.h> |
230 | #include <linux/jiffies.h> | 230 | #include <linux/jiffies.h> |
231 | #include <linux/smp_lock.h> | ||
231 | 232 | ||
232 | #include <asm/system.h> | 233 | #include <asm/system.h> |
233 | #include <asm/uaccess.h> | 234 | #include <asm/uaccess.h> |
@@ -1149,7 +1150,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender) | |||
1149 | as->event_tail = 0; | 1150 | as->event_tail = 0; |
1150 | } | 1151 | } |
1151 | as->events[as->event_head] = event; | 1152 | as->events[as->event_head] = event; |
1152 | if ((!as->suser) || (!as->writer)) | 1153 | if (!as->suser || !as->writer) |
1153 | continue; | 1154 | continue; |
1154 | switch (event) { | 1155 | switch (event) { |
1155 | case APM_SYS_SUSPEND: | 1156 | case APM_SYS_SUSPEND: |
@@ -1396,7 +1397,7 @@ static void apm_mainloop(void) | |||
1396 | 1397 | ||
1397 | static int check_apm_user(struct apm_user *as, const char *func) | 1398 | static int check_apm_user(struct apm_user *as, const char *func) |
1398 | { | 1399 | { |
1399 | if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { | 1400 | if (as == NULL || as->magic != APM_BIOS_MAGIC) { |
1400 | printk(KERN_ERR "apm: %s passed bad filp\n", func); | 1401 | printk(KERN_ERR "apm: %s passed bad filp\n", func); |
1401 | return 1; | 1402 | return 1; |
1402 | } | 1403 | } |
@@ -1459,18 +1460,19 @@ static unsigned int do_poll(struct file *fp, poll_table *wait) | |||
1459 | return 0; | 1460 | return 0; |
1460 | } | 1461 | } |
1461 | 1462 | ||
1462 | static int do_ioctl(struct inode *inode, struct file *filp, | 1463 | static long do_ioctl(struct file *filp, u_int cmd, u_long arg) |
1463 | u_int cmd, u_long arg) | ||
1464 | { | 1464 | { |
1465 | struct apm_user *as; | 1465 | struct apm_user *as; |
1466 | int ret; | ||
1466 | 1467 | ||
1467 | as = filp->private_data; | 1468 | as = filp->private_data; |
1468 | if (check_apm_user(as, "ioctl")) | 1469 | if (check_apm_user(as, "ioctl")) |
1469 | return -EIO; | 1470 | return -EIO; |
1470 | if ((!as->suser) || (!as->writer)) | 1471 | if (!as->suser || !as->writer) |
1471 | return -EPERM; | 1472 | return -EPERM; |
1472 | switch (cmd) { | 1473 | switch (cmd) { |
1473 | case APM_IOC_STANDBY: | 1474 | case APM_IOC_STANDBY: |
1475 | lock_kernel(); | ||
1474 | if (as->standbys_read > 0) { | 1476 | if (as->standbys_read > 0) { |
1475 | as->standbys_read--; | 1477 | as->standbys_read--; |
1476 | as->standbys_pending--; | 1478 | as->standbys_pending--; |
@@ -1479,8 +1481,10 @@ static int do_ioctl(struct inode *inode, struct file *filp, | |||
1479 | queue_event(APM_USER_STANDBY, as); | 1481 | queue_event(APM_USER_STANDBY, as); |
1480 | if (standbys_pending <= 0) | 1482 | if (standbys_pending <= 0) |
1481 | standby(); | 1483 | standby(); |
1484 | unlock_kernel(); | ||
1482 | break; | 1485 | break; |
1483 | case APM_IOC_SUSPEND: | 1486 | case APM_IOC_SUSPEND: |
1487 | lock_kernel(); | ||
1484 | if (as->suspends_read > 0) { | 1488 | if (as->suspends_read > 0) { |
1485 | as->suspends_read--; | 1489 | as->suspends_read--; |
1486 | as->suspends_pending--; | 1490 | as->suspends_pending--; |
@@ -1488,16 +1492,17 @@ static int do_ioctl(struct inode *inode, struct file *filp, | |||
1488 | } else | 1492 | } else |
1489 | queue_event(APM_USER_SUSPEND, as); | 1493 | queue_event(APM_USER_SUSPEND, as); |
1490 | if (suspends_pending <= 0) { | 1494 | if (suspends_pending <= 0) { |
1491 | return suspend(1); | 1495 | ret = suspend(1); |
1492 | } else { | 1496 | } else { |
1493 | as->suspend_wait = 1; | 1497 | as->suspend_wait = 1; |
1494 | wait_event_interruptible(apm_suspend_waitqueue, | 1498 | wait_event_interruptible(apm_suspend_waitqueue, |
1495 | as->suspend_wait == 0); | 1499 | as->suspend_wait == 0); |
1496 | return as->suspend_result; | 1500 | ret = as->suspend_result; |
1497 | } | 1501 | } |
1498 | break; | 1502 | unlock_kernel(); |
1503 | return ret; | ||
1499 | default: | 1504 | default: |
1500 | return -EINVAL; | 1505 | return -ENOTTY; |
1501 | } | 1506 | } |
1502 | return 0; | 1507 | return 0; |
1503 | } | 1508 | } |
@@ -1860,7 +1865,7 @@ static const struct file_operations apm_bios_fops = { | |||
1860 | .owner = THIS_MODULE, | 1865 | .owner = THIS_MODULE, |
1861 | .read = do_read, | 1866 | .read = do_read, |
1862 | .poll = do_poll, | 1867 | .poll = do_poll, |
1863 | .ioctl = do_ioctl, | 1868 | .unlocked_ioctl = do_ioctl, |
1864 | .open = do_open, | 1869 | .open = do_open, |
1865 | .release = do_release, | 1870 | .release = do_release, |
1866 | }; | 1871 | }; |