aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apm_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apm_32.c')
-rw-r--r--arch/x86/kernel/apm_32.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index bf9290e29013..bf9b441331e9 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>
@@ -228,6 +229,7 @@
228#include <linux/suspend.h> 229#include <linux/suspend.h>
229#include <linux/kthread.h> 230#include <linux/kthread.h>
230#include <linux/jiffies.h> 231#include <linux/jiffies.h>
232#include <linux/smp_lock.h>
231 233
232#include <asm/system.h> 234#include <asm/system.h>
233#include <asm/uaccess.h> 235#include <asm/uaccess.h>
@@ -1149,7 +1151,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
1149 as->event_tail = 0; 1151 as->event_tail = 0;
1150 } 1152 }
1151 as->events[as->event_head] = event; 1153 as->events[as->event_head] = event;
1152 if ((!as->suser) || (!as->writer)) 1154 if (!as->suser || !as->writer)
1153 continue; 1155 continue;
1154 switch (event) { 1156 switch (event) {
1155 case APM_SYS_SUSPEND: 1157 case APM_SYS_SUSPEND:
@@ -1211,9 +1213,9 @@ static int suspend(int vetoable)
1211 if (err != APM_SUCCESS) 1213 if (err != APM_SUCCESS)
1212 apm_error("suspend", err); 1214 apm_error("suspend", err);
1213 err = (err == APM_SUCCESS) ? 0 : -EIO; 1215 err = (err == APM_SUCCESS) ? 0 : -EIO;
1214 device_power_up(); 1216 device_power_up(PMSG_RESUME);
1215 local_irq_enable(); 1217 local_irq_enable();
1216 device_resume(); 1218 device_resume(PMSG_RESUME);
1217 queue_event(APM_NORMAL_RESUME, NULL); 1219 queue_event(APM_NORMAL_RESUME, NULL);
1218 spin_lock(&user_list_lock); 1220 spin_lock(&user_list_lock);
1219 for (as = user_list; as != NULL; as = as->next) { 1221 for (as = user_list; as != NULL; as = as->next) {
@@ -1238,7 +1240,7 @@ static void standby(void)
1238 apm_error("standby", err); 1240 apm_error("standby", err);
1239 1241
1240 local_irq_disable(); 1242 local_irq_disable();
1241 device_power_up(); 1243 device_power_up(PMSG_RESUME);
1242 local_irq_enable(); 1244 local_irq_enable();
1243} 1245}
1244 1246
@@ -1324,7 +1326,7 @@ static void check_events(void)
1324 ignore_bounce = 1; 1326 ignore_bounce = 1;
1325 if ((event != APM_NORMAL_RESUME) 1327 if ((event != APM_NORMAL_RESUME)
1326 || (ignore_normal_resume == 0)) { 1328 || (ignore_normal_resume == 0)) {
1327 device_resume(); 1329 device_resume(PMSG_RESUME);
1328 queue_event(event, NULL); 1330 queue_event(event, NULL);
1329 } 1331 }
1330 ignore_normal_resume = 0; 1332 ignore_normal_resume = 0;
@@ -1396,7 +1398,7 @@ static void apm_mainloop(void)
1396 1398
1397static int check_apm_user(struct apm_user *as, const char *func) 1399static int check_apm_user(struct apm_user *as, const char *func)
1398{ 1400{
1399 if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { 1401 if (as == NULL || as->magic != APM_BIOS_MAGIC) {
1400 printk(KERN_ERR "apm: %s passed bad filp\n", func); 1402 printk(KERN_ERR "apm: %s passed bad filp\n", func);
1401 return 1; 1403 return 1;
1402 } 1404 }
@@ -1459,18 +1461,19 @@ static unsigned int do_poll(struct file *fp, poll_table *wait)
1459 return 0; 1461 return 0;
1460} 1462}
1461 1463
1462static int do_ioctl(struct inode *inode, struct file *filp, 1464static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1463 u_int cmd, u_long arg)
1464{ 1465{
1465 struct apm_user *as; 1466 struct apm_user *as;
1467 int ret;
1466 1468
1467 as = filp->private_data; 1469 as = filp->private_data;
1468 if (check_apm_user(as, "ioctl")) 1470 if (check_apm_user(as, "ioctl"))
1469 return -EIO; 1471 return -EIO;
1470 if ((!as->suser) || (!as->writer)) 1472 if (!as->suser || !as->writer)
1471 return -EPERM; 1473 return -EPERM;
1472 switch (cmd) { 1474 switch (cmd) {
1473 case APM_IOC_STANDBY: 1475 case APM_IOC_STANDBY:
1476 lock_kernel();
1474 if (as->standbys_read > 0) { 1477 if (as->standbys_read > 0) {
1475 as->standbys_read--; 1478 as->standbys_read--;
1476 as->standbys_pending--; 1479 as->standbys_pending--;
@@ -1479,8 +1482,10 @@ static int do_ioctl(struct inode *inode, struct file *filp,
1479 queue_event(APM_USER_STANDBY, as); 1482 queue_event(APM_USER_STANDBY, as);
1480 if (standbys_pending <= 0) 1483 if (standbys_pending <= 0)
1481 standby(); 1484 standby();
1485 unlock_kernel();
1482 break; 1486 break;
1483 case APM_IOC_SUSPEND: 1487 case APM_IOC_SUSPEND:
1488 lock_kernel();
1484 if (as->suspends_read > 0) { 1489 if (as->suspends_read > 0) {
1485 as->suspends_read--; 1490 as->suspends_read--;
1486 as->suspends_pending--; 1491 as->suspends_pending--;
@@ -1488,16 +1493,17 @@ static int do_ioctl(struct inode *inode, struct file *filp,
1488 } else 1493 } else
1489 queue_event(APM_USER_SUSPEND, as); 1494 queue_event(APM_USER_SUSPEND, as);
1490 if (suspends_pending <= 0) { 1495 if (suspends_pending <= 0) {
1491 return suspend(1); 1496 ret = suspend(1);
1492 } else { 1497 } else {
1493 as->suspend_wait = 1; 1498 as->suspend_wait = 1;
1494 wait_event_interruptible(apm_suspend_waitqueue, 1499 wait_event_interruptible(apm_suspend_waitqueue,
1495 as->suspend_wait == 0); 1500 as->suspend_wait == 0);
1496 return as->suspend_result; 1501 ret = as->suspend_result;
1497 } 1502 }
1498 break; 1503 unlock_kernel();
1504 return ret;
1499 default: 1505 default:
1500 return -EINVAL; 1506 return -ENOTTY;
1501 } 1507 }
1502 return 0; 1508 return 0;
1503} 1509}
@@ -1544,10 +1550,12 @@ static int do_open(struct inode *inode, struct file *filp)
1544{ 1550{
1545 struct apm_user *as; 1551 struct apm_user *as;
1546 1552
1553 lock_kernel();
1547 as = kmalloc(sizeof(*as), GFP_KERNEL); 1554 as = kmalloc(sizeof(*as), GFP_KERNEL);
1548 if (as == NULL) { 1555 if (as == NULL) {
1549 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", 1556 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
1550 sizeof(*as)); 1557 sizeof(*as));
1558 unlock_kernel();
1551 return -ENOMEM; 1559 return -ENOMEM;
1552 } 1560 }
1553 as->magic = APM_BIOS_MAGIC; 1561 as->magic = APM_BIOS_MAGIC;
@@ -1569,6 +1577,7 @@ static int do_open(struct inode *inode, struct file *filp)
1569 user_list = as; 1577 user_list = as;
1570 spin_unlock(&user_list_lock); 1578 spin_unlock(&user_list_lock);
1571 filp->private_data = as; 1579 filp->private_data = as;
1580 unlock_kernel();
1572 return 0; 1581 return 0;
1573} 1582}
1574 1583
@@ -1860,7 +1869,7 @@ static const struct file_operations apm_bios_fops = {
1860 .owner = THIS_MODULE, 1869 .owner = THIS_MODULE,
1861 .read = do_read, 1870 .read = do_read,
1862 .poll = do_poll, 1871 .poll = do_poll,
1863 .ioctl = do_ioctl, 1872 .unlocked_ioctl = do_ioctl,
1864 .open = do_open, 1873 .open = do_open,
1865 .release = do_release, 1874 .release = do_release,
1866}; 1875};