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.c38
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
1397static int check_apm_user(struct apm_user *as, const char *func) 1398static 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
1462static int do_ioctl(struct inode *inode, struct file *filp, 1463static 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};