aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/frv/kernel/pm.c8
-rw-r--r--arch/mips/au1000/common/power.c17
-rw-r--r--arch/x86/kernel/apm_32.c15
-rw-r--r--kernel/power/Kconfig10
-rw-r--r--kernel/power/Makefile1
-rw-r--r--kernel/power/pm.c205
6 files changed, 2 insertions, 254 deletions
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index c57ce3f1f2e2..73f3aeefd203 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
163 if ((mode != 1) && (mode != 5)) 163 if ((mode != 1) && (mode != 5))
164 return -EINVAL; 164 return -EINVAL;
165 165
166 retval = pm_send_all(PM_SUSPEND, (void *)3);
167
168 if (retval == 0) { 166 if (retval == 0) {
169 if (mode == 5) 167 if (mode == 5)
170 retval = pm_do_bus_sleep(); 168 retval = pm_do_bus_sleep();
171 else 169 else
172 retval = pm_do_suspend(); 170 retval = pm_do_suspend();
173 pm_send_all(PM_RESUME, (void *)0);
174 } 171 }
175 172
176 return retval; 173 return retval;
@@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode)
183 if (!(clock_cmodes_permitted & (1<<new_cmode))) 180 if (!(clock_cmodes_permitted & (1<<new_cmode)))
184 return -EINVAL; 181 return -EINVAL;
185 182
186 /* tell all the drivers we're suspending */
187 pm_send_all(PM_SUSPEND, (void *)3);
188
189 /* now change cmode */ 183 /* now change cmode */
190 local_irq_disable(); 184 local_irq_disable();
191 frv_dma_pause_all(); 185 frv_dma_pause_all();
@@ -201,8 +195,6 @@ static int try_set_cmode(int new_cmode)
201 frv_dma_resume_all(); 195 frv_dma_resume_all();
202 local_irq_enable(); 196 local_irq_enable();
203 197
204 /* tell all the drivers we're resuming */
205 pm_send_all(PM_RESUME, (void *)0);
206 return 0; 198 return 0;
207} 199}
208 200
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index 54047d69b820..a9f7f6371e4b 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -258,7 +258,6 @@ int au_sleep(void)
258static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, 258static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
259 void __user *buffer, size_t * len, loff_t *ppos) 259 void __user *buffer, size_t * len, loff_t *ppos)
260{ 260{
261 int retval = 0;
262#ifdef SLEEP_TEST_TIMEOUT 261#ifdef SLEEP_TEST_TIMEOUT
263#define TMPBUFLEN2 16 262#define TMPBUFLEN2 16
264 char buf[TMPBUFLEN2], *p; 263 char buf[TMPBUFLEN2], *p;
@@ -278,33 +277,21 @@ static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
278 p = buf; 277 p = buf;
279 sleep_ticks = simple_strtoul(p, &p, 0); 278 sleep_ticks = simple_strtoul(p, &p, 0);
280#endif 279#endif
281 retval = pm_send_all(PM_SUSPEND, (void *) 2);
282
283 if (retval)
284 return retval;
285 280
286 au_sleep(); 281 au_sleep();
287 retval = pm_send_all(PM_RESUME, (void *) 0);
288 } 282 }
289 return retval; 283 return 0;
290} 284}
291 285
292static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, 286static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
293 void __user *buffer, size_t * len, loff_t *ppos) 287 void __user *buffer, size_t * len, loff_t *ppos)
294{ 288{
295 int retval = 0;
296
297 if (!write) { 289 if (!write) {
298 *len = 0; 290 *len = 0;
299 } else { 291 } else {
300 retval = pm_send_all(PM_SUSPEND, (void *) 2);
301 if (retval)
302 return retval;
303 suspend_mode = 1; 292 suspend_mode = 1;
304
305 retval = pm_send_all(PM_RESUME, (void *) 0);
306 } 293 }
307 return retval; 294 return 0;
308} 295}
309 296
310 297
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index d4438ef296d8..d7e92bfb8f66 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1189,19 +1189,6 @@ static int suspend(int vetoable)
1189 int err; 1189 int err;
1190 struct apm_user *as; 1190 struct apm_user *as;
1191 1191
1192 if (pm_send_all(PM_SUSPEND, (void *)3)) {
1193 /* Vetoed */
1194 if (vetoable) {
1195 if (apm_info.connection_version > 0x100)
1196 set_system_power_state(APM_STATE_REJECT);
1197 err = -EBUSY;
1198 ignore_sys_suspend = 0;
1199 printk(KERN_WARNING "apm: suspend was vetoed.\n");
1200 goto out;
1201 }
1202 printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
1203 }
1204
1205 device_suspend(PMSG_SUSPEND); 1192 device_suspend(PMSG_SUSPEND);
1206 local_irq_disable(); 1193 local_irq_disable();
1207 device_power_down(PMSG_SUSPEND); 1194 device_power_down(PMSG_SUSPEND);
@@ -1224,7 +1211,6 @@ static int suspend(int vetoable)
1224 device_power_up(); 1211 device_power_up();
1225 local_irq_enable(); 1212 local_irq_enable();
1226 device_resume(); 1213 device_resume();
1227 pm_send_all(PM_RESUME, (void *)0);
1228 queue_event(APM_NORMAL_RESUME, NULL); 1214 queue_event(APM_NORMAL_RESUME, NULL);
1229 out: 1215 out:
1230 spin_lock(&user_list_lock); 1216 spin_lock(&user_list_lock);
@@ -1337,7 +1323,6 @@ static void check_events(void)
1337 if ((event != APM_NORMAL_RESUME) 1323 if ((event != APM_NORMAL_RESUME)
1338 || (ignore_normal_resume == 0)) { 1324 || (ignore_normal_resume == 0)) {
1339 device_resume(); 1325 device_resume();
1340 pm_send_all(PM_RESUME, (void *)0);
1341 queue_event(event, NULL); 1326 queue_event(event, NULL);
1342 } 1327 }
1343 ignore_normal_resume = 0; 1328 ignore_normal_resume = 0;
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 6233f3b4ae66..b45da40e8d25 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -19,16 +19,6 @@ config PM
19 will issue the hlt instruction if nothing is to be done, thereby 19 will issue the hlt instruction if nothing is to be done, thereby
20 sending the processor to sleep and saving power. 20 sending the processor to sleep and saving power.
21 21
22config PM_LEGACY
23 bool "Legacy Power Management API (DEPRECATED)"
24 depends on PM
25 default n
26 ---help---
27 Support for pm_register() and friends. This old API is obsoleted
28 by the driver model.
29
30 If unsure, say N.
31
32config PM_DEBUG 22config PM_DEBUG
33 bool "Power Management Debug Support" 23 bool "Power Management Debug Support"
34 depends on PM 24 depends on PM
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index f7dfff28ecdb..597823b5b700 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -4,7 +4,6 @@ EXTRA_CFLAGS += -DDEBUG
4endif 4endif
5 5
6obj-y := main.o 6obj-y := main.o
7obj-$(CONFIG_PM_LEGACY) += pm.o
8obj-$(CONFIG_PM_SLEEP) += process.o console.o 7obj-$(CONFIG_PM_SLEEP) += process.o console.o
9obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o 8obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o
10 9
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
deleted file mode 100644
index 60c73fa670d5..000000000000
--- a/kernel/power/pm.c
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * pm.c - Power management interface
3 *
4 * Copyright (C) 2000 Andrew Henroid
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/init.h>
21#include <linux/module.h>
22#include <linux/spinlock.h>
23#include <linux/mm.h>
24#include <linux/slab.h>
25#include <linux/pm.h>
26#include <linux/pm_legacy.h>
27#include <linux/interrupt.h>
28#include <linux/mutex.h>
29
30/*
31 * Locking notes:
32 * pm_devs_lock can be a semaphore providing pm ops are not called
33 * from an interrupt handler (already a bad idea so no change here). Each
34 * change must be protected so that an unlink of an entry doesn't clash
35 * with a pm send - which is permitted to sleep in the current architecture
36 *
37 * Module unloads clashing with pm events now work out safely, the module
38 * unload path will block until the event has been sent. It may well block
39 * until a resume but that will be fine.
40 */
41
42static DEFINE_MUTEX(pm_devs_lock);
43static LIST_HEAD(pm_devs);
44
45/**
46 * pm_register - register a device with power management
47 * @type: device type
48 * @id: device ID
49 * @callback: callback function
50 *
51 * Add a device to the list of devices that wish to be notified about
52 * power management events. A &pm_dev structure is returned on success,
53 * on failure the return is %NULL.
54 *
55 * The callback function will be called in process context and
56 * it may sleep.
57 */
58
59struct pm_dev *pm_register(pm_dev_t type,
60 unsigned long id,
61 pm_callback callback)
62{
63 struct pm_dev *dev = kzalloc(sizeof(struct pm_dev), GFP_KERNEL);
64 if (dev) {
65 dev->type = type;
66 dev->id = id;
67 dev->callback = callback;
68
69 mutex_lock(&pm_devs_lock);
70 list_add(&dev->entry, &pm_devs);
71 mutex_unlock(&pm_devs_lock);
72 }
73 return dev;
74}
75
76/**
77 * pm_send - send request to a single device
78 * @dev: device to send to
79 * @rqst: power management request
80 * @data: data for the callback
81 *
82 * Issue a power management request to a given device. The
83 * %PM_SUSPEND and %PM_RESUME events are handled specially. The
84 * data field must hold the intended next state. No call is made
85 * if the state matches.
86 *
87 * BUGS: what stops two power management requests occurring in parallel
88 * and conflicting.
89 *
90 * WARNING: Calling pm_send directly is not generally recommended, in
91 * particular there is no locking against the pm_dev going away. The
92 * caller must maintain all needed locking or have 'inside knowledge'
93 * on the safety. Also remember that this function is not locked against
94 * pm_unregister. This means that you must handle SMP races on callback
95 * execution and unload yourself.
96 */
97
98static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
99{
100 int status = 0;
101 unsigned long prev_state, next_state;
102
103 if (in_interrupt())
104 BUG();
105
106 switch (rqst) {
107 case PM_SUSPEND:
108 case PM_RESUME:
109 prev_state = dev->state;
110 next_state = (unsigned long) data;
111 if (prev_state != next_state) {
112 if (dev->callback)
113 status = (*dev->callback)(dev, rqst, data);
114 if (!status) {
115 dev->state = next_state;
116 dev->prev_state = prev_state;
117 }
118 }
119 else {
120 dev->prev_state = prev_state;
121 }
122 break;
123 default:
124 if (dev->callback)
125 status = (*dev->callback)(dev, rqst, data);
126 break;
127 }
128 return status;
129}
130
131/*
132 * Undo incomplete request
133 */
134static void pm_undo_all(struct pm_dev *last)
135{
136 struct list_head *entry = last->entry.prev;
137 while (entry != &pm_devs) {
138 struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
139 if (dev->state != dev->prev_state) {
140 /* previous state was zero (running) resume or
141 * previous state was non-zero (suspended) suspend
142 */
143 pm_request_t undo = (dev->prev_state
144 ? PM_SUSPEND:PM_RESUME);
145 pm_send(dev, undo, (void*) dev->prev_state);
146 }
147 entry = entry->prev;
148 }
149}
150
151/**
152 * pm_send_all - send request to all managed devices
153 * @rqst: power management request
154 * @data: data for the callback
155 *
156 * Issue a power management request to a all devices. The
157 * %PM_SUSPEND events are handled specially. Any device is
158 * permitted to fail a suspend by returning a non zero (error)
159 * value from its callback function. If any device vetoes a
160 * suspend request then all other devices that have suspended
161 * during the processing of this request are restored to their
162 * previous state.
163 *
164 * WARNING: This function takes the pm_devs_lock. The lock is not dropped until
165 * the callbacks have completed. This prevents races against pm locking
166 * functions, races against module unload pm_unregister code. It does
167 * mean however that you must not issue pm_ functions within the callback
168 * or you will deadlock and users will hate you.
169 *
170 * Zero is returned on success. If a suspend fails then the status
171 * from the device that vetoes the suspend is returned.
172 *
173 * BUGS: what stops two power management requests occurring in parallel
174 * and conflicting.
175 */
176
177int pm_send_all(pm_request_t rqst, void *data)
178{
179 struct list_head *entry;
180
181 mutex_lock(&pm_devs_lock);
182 entry = pm_devs.next;
183 while (entry != &pm_devs) {
184 struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
185 if (dev->callback) {
186 int status = pm_send(dev, rqst, data);
187 if (status) {
188 /* return devices to previous state on
189 * failed suspend request
190 */
191 if (rqst == PM_SUSPEND)
192 pm_undo_all(dev);
193 mutex_unlock(&pm_devs_lock);
194 return status;
195 }
196 }
197 entry = entry->next;
198 }
199 mutex_unlock(&pm_devs_lock);
200 return 0;
201}
202
203EXPORT_SYMBOL(pm_register);
204EXPORT_SYMBOL(pm_send_all);
205