OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [kernel/] [power/] [user.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * linux/kernel/power/user.c
3
 *
4
 * This file provides the user space interface for software suspend/resume.
5
 *
6
 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
7
 *
8
 * This file is released under the GPLv2.
9
 *
10
 */
11
 
12
#include <linux/suspend.h>
13
#include <linux/syscalls.h>
14
#include <linux/reboot.h>
15
#include <linux/string.h>
16
#include <linux/device.h>
17
#include <linux/miscdevice.h>
18
#include <linux/mm.h>
19
#include <linux/swap.h>
20
#include <linux/swapops.h>
21
#include <linux/pm.h>
22
#include <linux/fs.h>
23
#include <linux/console.h>
24
#include <linux/cpu.h>
25
#include <linux/freezer.h>
26
 
27
#include <asm/uaccess.h>
28
 
29
#include "power.h"
30
 
31
#define SNAPSHOT_MINOR  231
32
 
33
static struct snapshot_data {
34
        struct snapshot_handle handle;
35
        int swap;
36
        int mode;
37
        char frozen;
38
        char ready;
39
        char platform_suspend;
40
} snapshot_state;
41
 
42
atomic_t snapshot_device_available = ATOMIC_INIT(1);
43
 
44
static int snapshot_open(struct inode *inode, struct file *filp)
45
{
46
        struct snapshot_data *data;
47
 
48
        if (!atomic_add_unless(&snapshot_device_available, -1, 0))
49
                return -EBUSY;
50
 
51
        if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
52
                atomic_inc(&snapshot_device_available);
53
                return -ENOSYS;
54
        }
55
        if(create_basic_memory_bitmaps()) {
56
                atomic_inc(&snapshot_device_available);
57
                return -ENOMEM;
58
        }
59
        nonseekable_open(inode, filp);
60
        data = &snapshot_state;
61
        filp->private_data = data;
62
        memset(&data->handle, 0, sizeof(struct snapshot_handle));
63
        if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
64
                data->swap = swsusp_resume_device ?
65
                        swap_type_of(swsusp_resume_device, 0, NULL) : -1;
66
                data->mode = O_RDONLY;
67
        } else {
68
                data->swap = -1;
69
                data->mode = O_WRONLY;
70
        }
71
        data->frozen = 0;
72
        data->ready = 0;
73
        data->platform_suspend = 0;
74
 
75
        return 0;
76
}
77
 
78
static int snapshot_release(struct inode *inode, struct file *filp)
79
{
80
        struct snapshot_data *data;
81
 
82
        swsusp_free();
83
        free_basic_memory_bitmaps();
84
        data = filp->private_data;
85
        free_all_swap_pages(data->swap);
86
        if (data->frozen) {
87
                mutex_lock(&pm_mutex);
88
                thaw_processes();
89
                mutex_unlock(&pm_mutex);
90
        }
91
        atomic_inc(&snapshot_device_available);
92
        return 0;
93
}
94
 
95
static ssize_t snapshot_read(struct file *filp, char __user *buf,
96
                             size_t count, loff_t *offp)
97
{
98
        struct snapshot_data *data;
99
        ssize_t res;
100
 
101
        data = filp->private_data;
102
        if (!data->ready)
103
                return -ENODATA;
104
        res = snapshot_read_next(&data->handle, count);
105
        if (res > 0) {
106
                if (copy_to_user(buf, data_of(data->handle), res))
107
                        res = -EFAULT;
108
                else
109
                        *offp = data->handle.offset;
110
        }
111
        return res;
112
}
113
 
114
static ssize_t snapshot_write(struct file *filp, const char __user *buf,
115
                              size_t count, loff_t *offp)
116
{
117
        struct snapshot_data *data;
118
        ssize_t res;
119
 
120
        data = filp->private_data;
121
        res = snapshot_write_next(&data->handle, count);
122
        if (res > 0) {
123
                if (copy_from_user(data_of(data->handle), buf, res))
124
                        res = -EFAULT;
125
                else
126
                        *offp = data->handle.offset;
127
        }
128
        return res;
129
}
130
 
131
static int snapshot_ioctl(struct inode *inode, struct file *filp,
132
                          unsigned int cmd, unsigned long arg)
133
{
134
        int error = 0;
135
        struct snapshot_data *data;
136
        loff_t avail;
137
        sector_t offset;
138
 
139
        if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
140
                return -ENOTTY;
141
        if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
142
                return -ENOTTY;
143
        if (!capable(CAP_SYS_ADMIN))
144
                return -EPERM;
145
 
146
        data = filp->private_data;
147
 
148
        switch (cmd) {
149
 
150
        case SNAPSHOT_FREEZE:
151
                if (data->frozen)
152
                        break;
153
                mutex_lock(&pm_mutex);
154
                error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
155
                if (!error) {
156
                        printk("Syncing filesystems ... ");
157
                        sys_sync();
158
                        printk("done.\n");
159
 
160
                        error = freeze_processes();
161
                        if (error)
162
                                thaw_processes();
163
                }
164
                if (error)
165
                        pm_notifier_call_chain(PM_POST_HIBERNATION);
166
                mutex_unlock(&pm_mutex);
167
                if (!error)
168
                        data->frozen = 1;
169
                break;
170
 
171
        case SNAPSHOT_UNFREEZE:
172
                if (!data->frozen || data->ready)
173
                        break;
174
                mutex_lock(&pm_mutex);
175
                thaw_processes();
176
                pm_notifier_call_chain(PM_POST_HIBERNATION);
177
                mutex_unlock(&pm_mutex);
178
                data->frozen = 0;
179
                break;
180
 
181
        case SNAPSHOT_ATOMIC_SNAPSHOT:
182
                if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
183
                        error = -EPERM;
184
                        break;
185
                }
186
                error = hibernation_snapshot(data->platform_suspend);
187
                if (!error)
188
                        error = put_user(in_suspend, (unsigned int __user *)arg);
189
                if (!error)
190
                        data->ready = 1;
191
                break;
192
 
193
        case SNAPSHOT_ATOMIC_RESTORE:
194
                snapshot_write_finalize(&data->handle);
195
                if (data->mode != O_WRONLY || !data->frozen ||
196
                    !snapshot_image_loaded(&data->handle)) {
197
                        error = -EPERM;
198
                        break;
199
                }
200
                error = hibernation_restore(data->platform_suspend);
201
                break;
202
 
203
        case SNAPSHOT_FREE:
204
                swsusp_free();
205
                memset(&data->handle, 0, sizeof(struct snapshot_handle));
206
                data->ready = 0;
207
                break;
208
 
209
        case SNAPSHOT_SET_IMAGE_SIZE:
210
                image_size = arg;
211
                break;
212
 
213
        case SNAPSHOT_AVAIL_SWAP:
214
                avail = count_swap_pages(data->swap, 1);
215
                avail <<= PAGE_SHIFT;
216
                error = put_user(avail, (loff_t __user *)arg);
217
                break;
218
 
219
        case SNAPSHOT_GET_SWAP_PAGE:
220
                if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
221
                        error = -ENODEV;
222
                        break;
223
                }
224
                offset = alloc_swapdev_block(data->swap);
225
                if (offset) {
226
                        offset <<= PAGE_SHIFT;
227
                        error = put_user(offset, (sector_t __user *)arg);
228
                } else {
229
                        error = -ENOSPC;
230
                }
231
                break;
232
 
233
        case SNAPSHOT_FREE_SWAP_PAGES:
234
                if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
235
                        error = -ENODEV;
236
                        break;
237
                }
238
                free_all_swap_pages(data->swap);
239
                break;
240
 
241
        case SNAPSHOT_SET_SWAP_FILE:
242
                if (!swsusp_swap_in_use()) {
243
                        /*
244
                         * User space encodes device types as two-byte values,
245
                         * so we need to recode them
246
                         */
247
                        if (old_decode_dev(arg)) {
248
                                data->swap = swap_type_of(old_decode_dev(arg),
249
                                                        0, NULL);
250
                                if (data->swap < 0)
251
                                        error = -ENODEV;
252
                        } else {
253
                                data->swap = -1;
254
                                error = -EINVAL;
255
                        }
256
                } else {
257
                        error = -EPERM;
258
                }
259
                break;
260
 
261
        case SNAPSHOT_S2RAM:
262
                if (!data->frozen) {
263
                        error = -EPERM;
264
                        break;
265
                }
266
                if (!mutex_trylock(&pm_mutex)) {
267
                        error = -EBUSY;
268
                        break;
269
                }
270
                /*
271
                 * Tasks are frozen and the notifiers have been called with
272
                 * PM_HIBERNATION_PREPARE
273
                 */
274
                error = suspend_devices_and_enter(PM_SUSPEND_MEM);
275
                mutex_unlock(&pm_mutex);
276
                break;
277
 
278
        case SNAPSHOT_PMOPS:
279
                error = -EINVAL;
280
 
281
                switch (arg) {
282
 
283
                case PMOPS_PREPARE:
284
                        data->platform_suspend = 1;
285
                        error = 0;
286
                        break;
287
 
288
                case PMOPS_ENTER:
289
                        if (data->platform_suspend)
290
                                error = hibernation_platform_enter();
291
 
292
                        break;
293
 
294
                case PMOPS_FINISH:
295
                        if (data->platform_suspend)
296
                                error = 0;
297
 
298
                        break;
299
 
300
                default:
301
                        printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
302
 
303
                }
304
                break;
305
 
306
        case SNAPSHOT_SET_SWAP_AREA:
307
                if (swsusp_swap_in_use()) {
308
                        error = -EPERM;
309
                } else {
310
                        struct resume_swap_area swap_area;
311
                        dev_t swdev;
312
 
313
                        error = copy_from_user(&swap_area, (void __user *)arg,
314
                                        sizeof(struct resume_swap_area));
315
                        if (error) {
316
                                error = -EFAULT;
317
                                break;
318
                        }
319
 
320
                        /*
321
                         * User space encodes device types as two-byte values,
322
                         * so we need to recode them
323
                         */
324
                        swdev = old_decode_dev(swap_area.dev);
325
                        if (swdev) {
326
                                offset = swap_area.offset;
327
                                data->swap = swap_type_of(swdev, offset, NULL);
328
                                if (data->swap < 0)
329
                                        error = -ENODEV;
330
                        } else {
331
                                data->swap = -1;
332
                                error = -EINVAL;
333
                        }
334
                }
335
                break;
336
 
337
        default:
338
                error = -ENOTTY;
339
 
340
        }
341
 
342
        return error;
343
}
344
 
345
static const struct file_operations snapshot_fops = {
346
        .open = snapshot_open,
347
        .release = snapshot_release,
348
        .read = snapshot_read,
349
        .write = snapshot_write,
350
        .llseek = no_llseek,
351
        .ioctl = snapshot_ioctl,
352
};
353
 
354
static struct miscdevice snapshot_device = {
355
        .minor = SNAPSHOT_MINOR,
356
        .name = "snapshot",
357
        .fops = &snapshot_fops,
358
};
359
 
360
static int __init snapshot_device_init(void)
361
{
362
        return misc_register(&snapshot_device);
363
};
364
 
365
device_initcall(snapshot_device_init);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.