diff options
Diffstat (limited to 'arch/x86/kernel/apm_32.c')
-rw-r--r-- | arch/x86/kernel/apm_32.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index bf9290e29013..9ee24e6bc4b0 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
@@ -204,6 +204,7 @@ | |||
204 | #include <linux/module.h> | 204 | #include <linux/module.h> |
205 | 205 | ||
206 | #include <linux/poll.h> | 206 | #include <linux/poll.h> |
207 | #include <linux/smp_lock.h> | ||
207 | #include <linux/types.h> | 208 | #include <linux/types.h> |
208 | #include <linux/stddef.h> | 209 | #include <linux/stddef.h> |
209 | #include <linux/timer.h> | 210 | #include <linux/timer.h> |
@@ -218,7 +219,6 @@ | |||
218 | #include <linux/time.h> | 219 | #include <linux/time.h> |
219 | #include <linux/sched.h> | 220 | #include <linux/sched.h> |
220 | #include <linux/pm.h> | 221 | #include <linux/pm.h> |
221 | #include <linux/pm_legacy.h> | ||
222 | #include <linux/capability.h> | 222 | #include <linux/capability.h> |
223 | #include <linux/device.h> | 223 | #include <linux/device.h> |
224 | #include <linux/kernel.h> | 224 | #include <linux/kernel.h> |
@@ -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: |
@@ -1211,9 +1212,9 @@ static int suspend(int vetoable) | |||
1211 | if (err != APM_SUCCESS) | 1212 | if (err != APM_SUCCESS) |
1212 | apm_error("suspend", err); | 1213 | apm_error("suspend", err); |
1213 | err = (err == APM_SUCCESS) ? 0 : -EIO; | 1214 | err = (err == APM_SUCCESS) ? 0 : -EIO; |
1214 | device_power_up(); | 1215 | device_power_up(PMSG_RESUME); |
1215 | local_irq_enable(); | 1216 | local_irq_enable(); |
1216 | device_resume(); | 1217 | device_resume(PMSG_RESUME); |
1217 | queue_event(APM_NORMAL_RESUME, NULL); | 1218 | queue_event(APM_NORMAL_RESUME, NULL); |
1218 | spin_lock(&user_list_lock); | 1219 | spin_lock(&user_list_lock); |
1219 | for (as = user_list; as != NULL; as = as->next) { | 1220 | for (as = user_list; as != NULL; as = as->next) { |
@@ -1238,7 +1239,7 @@ static void standby(void) | |||
1238 | apm_error("standby", err); | 1239 | apm_error("standby", err); |
1239 | 1240 | ||
1240 | local_irq_disable(); | 1241 | local_irq_disable(); |
1241 | device_power_up(); | 1242 | device_power_up(PMSG_RESUME); |
1242 | local_irq_enable(); | 1243 | local_irq_enable(); |
1243 | } | 1244 | } |
1244 | 1245 | ||
@@ -1324,7 +1325,7 @@ static void check_events(void) | |||
1324 | ignore_bounce = 1; | 1325 | ignore_bounce = 1; |
1325 | if ((event != APM_NORMAL_RESUME) | 1326 | if ((event != APM_NORMAL_RESUME) |
1326 | || (ignore_normal_resume == 0)) { | 1327 | || (ignore_normal_resume == 0)) { |
1327 | device_resume(); | 1328 | device_resume(PMSG_RESUME); |
1328 | queue_event(event, NULL); | 1329 | queue_event(event, NULL); |
1329 | } | 1330 | } |
1330 | ignore_normal_resume = 0; | 1331 | ignore_normal_resume = 0; |
@@ -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 | } |
@@ -1544,10 +1549,12 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1544 | { | 1549 | { |
1545 | struct apm_user *as; | 1550 | struct apm_user *as; |
1546 | 1551 | ||
1552 | lock_kernel(); | ||
1547 | as = kmalloc(sizeof(*as), GFP_KERNEL); | 1553 | as = kmalloc(sizeof(*as), GFP_KERNEL); |
1548 | if (as == NULL) { | 1554 | if (as == NULL) { |
1549 | printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", | 1555 | printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", |
1550 | sizeof(*as)); | 1556 | sizeof(*as)); |
1557 | unlock_kernel(); | ||
1551 | return -ENOMEM; | 1558 | return -ENOMEM; |
1552 | } | 1559 | } |
1553 | as->magic = APM_BIOS_MAGIC; | 1560 | as->magic = APM_BIOS_MAGIC; |
@@ -1569,6 +1576,7 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1569 | user_list = as; | 1576 | user_list = as; |
1570 | spin_unlock(&user_list_lock); | 1577 | spin_unlock(&user_list_lock); |
1571 | filp->private_data = as; | 1578 | filp->private_data = as; |
1579 | unlock_kernel(); | ||
1572 | return 0; | 1580 | return 0; |
1573 | } | 1581 | } |
1574 | 1582 | ||
@@ -1860,7 +1868,7 @@ static const struct file_operations apm_bios_fops = { | |||
1860 | .owner = THIS_MODULE, | 1868 | .owner = THIS_MODULE, |
1861 | .read = do_read, | 1869 | .read = do_read, |
1862 | .poll = do_poll, | 1870 | .poll = do_poll, |
1863 | .ioctl = do_ioctl, | 1871 | .unlocked_ioctl = do_ioctl, |
1864 | .open = do_open, | 1872 | .open = do_open, |
1865 | .release = do_release, | 1873 | .release = do_release, |
1866 | }; | 1874 | }; |