ARM: tizen_tm1_defconfig: Enable missing features related with CGROUPS
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / driver / device_driver.c
1 /**
2  * driver/device_driver.c
3  * @author Alexander Aksenov <a.aksenov@samsung.com>
4  *
5  * @section LICENSE
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * @section COPYRIGHT
22  *
23  * Copyright (C) Samsung Electronics, 2013
24  *
25  * @section DESCRIPTION
26  *
27  * Provides SWAP device.
28  */
29
30 #include <linux/types.h>
31 #include <linux/fs.h>
32 #include <linux/cdev.h>
33 #include <linux/err.h>
34 #include <linux/device.h>
35 #include <linux/ioctl.h>
36 #include <linux/slab.h>
37 #include <linux/mm.h>
38 #include <linux/splice.h>
39 #include <linux/sched.h>
40 #include <linux/module.h>
41 #include <linux/wait.h>
42 #include <linux/workqueue.h>
43 #include <linux/uaccess.h>
44
45 #include <ksyms/ksyms.h>
46 #include <master/swap_initializer.h>
47
48 #include "device_driver.h"
49 #include "swap_driver_errors.h"
50 #include "driver_to_buffer.h"
51 #include "swap_ioctl.h"
52 #include "driver_defs.h"
53 #include "device_driver_to_driver_to_buffer.h"
54 #include "driver_to_buffer.h"
55 #include "driver_to_msg.h"
56
57 /** SWAP device name as it is in /dev/. */
58 #define SWAP_DEVICE_NAME "swap_device"
59
60 /** Maximum subbuffer size. Used for sanitization checks. */
61 #define MAXIMUM_SUBBUFFER_SIZE (64 * 1024)
62
63 /* swap_device driver routines */
64 static ssize_t swap_device_read(struct file *filp, char __user *buf,
65                                 size_t count, loff_t *f_pos);
66 static long swap_device_ioctl(struct file *filp, unsigned int cmd,
67                               unsigned long arg);
68 static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
69                                        struct pipe_inode_info *pipe, size_t len,
70                                        unsigned int flags);
71
72 /**
73  * @var swap_device_fops
74  * @brief SWAP device file operations.
75  */
76 const struct file_operations swap_device_fops = {
77         .owner = THIS_MODULE,
78         .read = swap_device_read,
79         .open = swap_init_simple_open,
80         .release = swap_init_simple_release,
81         .unlocked_ioctl = swap_device_ioctl,
82         .splice_read = swap_device_splice_read,
83 };
84
85 /* Typedefs for splice_* funcs. Prototypes are for linux-3.8.6 */
86 /** Splice to pipe pointer type. */
87 typedef ssize_t(*splice_to_pipe_p_t)(struct pipe_inode_info *pipe,
88                                          struct splice_pipe_desc *spd);
89 /** Splice grow spd pointer type. */
90 typedef int(*splice_grow_spd_p_t)(const struct pipe_inode_info *pipe,
91                                         struct splice_pipe_desc *spd);
92
93 static splice_to_pipe_p_t splice_to_pipe_p;
94 static splice_grow_spd_p_t splice_grow_spd_p;
95
96 static msg_handler_t msg_handler;
97
98 /* Device numbers */
99 static dev_t swap_device_no;
100
101 /* Device cdev struct */
102 static struct cdev *swap_device_cdev;
103
104 /* Device class struct */
105 static struct class *swap_device_class;
106
107 /* Device device struct */
108 static struct device *swap_device_device;
109
110 /* Reading tasks queue */
111 static DECLARE_WAIT_QUEUE_HEAD(swap_device_wait);
112
113
114 static atomic_t flag_wake_up = ATOMIC_INIT(0);
115
116 static void __bottom_wake_up(void)
117 {
118         if (waitqueue_active(&swap_device_wait))
119                 wake_up_interruptible(&swap_device_wait);
120 }
121
122 static void bottom_wake_up(struct work_struct *work)
123 {
124         if (atomic_read(&flag_wake_up)) {
125                 atomic_set(&flag_wake_up, 0);
126                 __bottom_wake_up();
127         }
128 }
129
130 static DECLARE_WORK(w_wake_up, bottom_wake_up);
131
132 static void exit_w_wake_up(void)
133 {
134         flush_scheduled_work();
135         __bottom_wake_up();
136 }
137
138
139 /**
140  * @brief We need this realization of splice_shrink_spd() because its desing
141  * frequently changes in custom kernels.
142  *
143  * @param pipe Pointer to the pipe whereto splice data.
144  * @param spd Pointer to the splice_pipe_desc structure.
145  * @return Void.
146  */
147 void swap_device_splice_shrink_spd(struct pipe_inode_info *pipe,
148                                    struct splice_pipe_desc *spd)
149 {
150         if (pipe->buffers <= PIPE_DEF_BUFFERS)
151                 return;
152
153         kfree(spd->pages);
154         kfree(spd->partial);
155 }
156
157
158 /* TODO Think of permanent major */
159
160 /**
161  * @brief Register device.
162  *
163  * @return 0 on success, negative error code otherwise.
164  */
165 int swap_device_init(void)
166 {
167         int result;
168
169         /* Allocating device major and minor nums for swap_device */
170         result = alloc_chrdev_region(&swap_device_no, 0, 1, SWAP_DEVICE_NAME);
171         if (result < 0) {
172                 print_crit("Major number allocation has failed\n");
173                 result = -E_SD_ALLOC_CHRDEV_FAIL;
174                 goto init_fail;
175         }
176
177         /* Creating device class. Using IS_ERR, because class_create
178          * returns ERR_PTR on error. */
179         swap_device_class = class_create(THIS_MODULE, SWAP_DEVICE_NAME);
180         if (IS_ERR(swap_device_class)) {
181                 print_crit("Class creation has failed\n");
182                 result = -E_SD_CLASS_CREATE_FAIL;
183                 goto init_fail;
184         }
185
186         /* Cdev allocation */
187         swap_device_cdev = cdev_alloc();
188         if (!swap_device_cdev) {
189                 print_crit("Cdev structure allocation has failed\n");
190                 result = -E_SD_CDEV_ALLOC_FAIL;
191                 goto init_fail;
192         }
193
194         /* Cdev intialization and setting file operations */
195         cdev_init(swap_device_cdev, &swap_device_fops);
196
197         /* Adding cdev to system */
198         result = cdev_add(swap_device_cdev, swap_device_no, 1);
199         if (result < 0) {
200                 print_crit("Device adding has failed\n");
201                 result = -E_SD_CDEV_ADD_FAIL;
202                 goto init_fail;
203         }
204
205         /* Create device struct */
206         swap_device_device = device_create(swap_device_class, NULL,
207                                            swap_device_no,
208                                            "%s", SWAP_DEVICE_NAME);
209         if (IS_ERR(swap_device_device)) {
210                 print_crit("Device struct creating has failed\n");
211                 result = -E_SD_DEVICE_CREATE_FAIL;
212                 goto init_fail;
213         }
214
215         /* Find splice_* funcs addresses */
216         splice_to_pipe_p = (splice_to_pipe_p_t)swap_ksyms("splice_to_pipe");
217         if (!splice_to_pipe_p) {
218                 print_err("splice_to_pipe() not found!\n");
219                 result = -E_SD_NO_SPLICE_FUNCS;
220                 goto init_fail;
221         }
222
223         splice_grow_spd_p = (splice_grow_spd_p_t)swap_ksyms("splice_grow_spd");
224         if (!splice_grow_spd_p) {
225                 print_err("splice_grow_spd() not found!\n");
226                 result = -E_SD_NO_SPLICE_FUNCS;
227                 goto init_fail;
228         }
229
230         return 0;
231
232 init_fail:
233         if (swap_device_cdev)
234                 cdev_del(swap_device_cdev);
235         if (swap_device_class)
236                 class_destroy(swap_device_class);
237         if (swap_device_no)
238                 unregister_chrdev_region(swap_device_no, 1);
239         return result;
240 }
241
242 /* TODO Check wether driver is registered */
243
244 /**
245  * @brief Unregister device.
246  *
247  * @return Void.
248  */
249 void swap_device_exit(void)
250 {
251         exit_w_wake_up();
252
253         splice_to_pipe_p = NULL;
254         splice_grow_spd_p = NULL;
255
256         device_destroy(swap_device_class, swap_device_no);
257         cdev_del(swap_device_cdev);
258         class_destroy(swap_device_class);
259         unregister_chrdev_region(swap_device_no, 1);
260 }
261
262 static ssize_t swap_device_read(struct file *filp, char __user *buf,
263                                 size_t count, loff_t *f_pos)
264 {
265         /* Wait queue item that consists current task. It is used to be added in
266          * swap_device_wait queue if there is no data to be read. */
267         DEFINE_WAIT(wait);
268         int result;
269
270         /* TODO : Think about spin_locks to prevent reading race condition. */
271         while ((result =
272                 driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
273
274                 /* Add process to the swap_device_wait queue and set the current
275                  * task state TASK_INTERRUPTIBLE. If there is any data to be
276                  * read, then the current task is removed from the
277                  * swap_device_wait queue and its state is changed to this. */
278                 prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
279
280                 if (result < 0) {
281                         result = 0;
282                         goto swap_device_read_error;
283                 } else if (result == E_SD_NO_DATA_TO_READ) {
284                         /* Yes, E_SD_NO_DATA_TO_READ should be positive,
285                          * cause it's not really an error */
286                         if (filp->f_flags & O_NONBLOCK) {
287                                 result = -EAGAIN;
288                                 goto swap_device_read_error;
289                         }
290                         if (signal_pending(current)) {
291                                 result = -ERESTARTSYS;
292                                 goto swap_device_read_error;
293                         }
294                         schedule();
295                         finish_wait(&swap_device_wait, &wait);
296                 }
297         }
298
299         result = driver_to_buffer_read(buf, count);
300         /* If there is an error - return 0 */
301         if (result < 0)
302                 result = 0;
303
304
305         return result;
306
307 swap_device_read_error:
308         finish_wait(&swap_device_wait, &wait);
309
310         return result;
311 }
312
313 static long swap_device_ioctl(struct file *filp, unsigned int cmd,
314                                                          unsigned long arg)
315 {
316         int result;
317
318         switch (cmd) {
319         case SWAP_DRIVER_BUFFER_INITIALIZE:
320         {
321                 struct buffer_initialize initialize_struct;
322
323                 result = copy_from_user(&initialize_struct, (void *)arg,
324                                         sizeof(struct buffer_initialize));
325                 if (result)
326                         break;
327
328                 if (initialize_struct.size > MAXIMUM_SUBBUFFER_SIZE) {
329                         print_err("Wrong subbuffer size\n");
330                         result = -E_SD_WRONG_ARGS;
331                         break;
332                 }
333
334                 result = driver_to_buffer_initialize(initialize_struct.size,
335                                                      initialize_struct.count);
336                 if (result < 0) {
337                         print_err("Buffer initialization failed %d\n", result);
338                         break;
339                 }
340                 result = E_SD_SUCCESS;
341
342                 break;
343         }
344         case SWAP_DRIVER_BUFFER_UNINITIALIZE:
345         {
346                 result = driver_to_buffer_uninitialize();
347                 if (result < 0)
348                         print_err("Buffer uninitialization failed %d\n",
349                                   result);
350                 break;
351         }
352         case SWAP_DRIVER_NEXT_BUFFER_TO_READ:
353         {
354                 /* Use this carefully */
355                 result = driver_to_buffer_next_buffer_to_read();
356                 if (result == E_SD_NO_DATA_TO_READ) {
357                         /* TODO Do what we usually do when there are no
358                          * subbuffers to read (make daemon sleep ?) */
359                 }
360                 break;
361         }
362         case SWAP_DRIVER_FLUSH_BUFFER:
363         {
364                 result = driver_to_buffer_flush();
365                 break;
366         }
367         case SWAP_DRIVER_MSG:
368         {
369                 if (msg_handler) {
370                         result = msg_handler((void __user *)arg);
371                 } else {
372                         print_warn("msg_handler() is not register\n");
373                         result = -EINVAL;
374                 }
375                 break;
376         }
377         case SWAP_DRIVER_WAKE_UP:
378         {
379                 swap_device_wake_up_process();
380                 result = E_SD_SUCCESS;
381                 break;
382         }
383         default:
384                 print_warn("Unknown command %d\n", cmd);
385                 result = -EINVAL;
386                 break;
387
388         }
389         return result;
390 }
391
392 static void swap_device_pipe_buf_release(struct pipe_inode_info *inode,
393                                          struct pipe_buffer *pipe)
394 {
395         __free_page(pipe->page);
396 }
397
398 static void swap_device_page_release(struct splice_pipe_desc *spd,
399                                      unsigned int i)
400 {
401         __free_page(spd->pages[i]);
402 }
403
404 static const struct pipe_buf_operations swap_device_pipe_buf_ops = {
405         .can_merge = 0,
406         .map = generic_pipe_buf_map,
407         .unmap = generic_pipe_buf_unmap,
408         .confirm = generic_pipe_buf_confirm,
409         .release = swap_device_pipe_buf_release,
410         .steal = generic_pipe_buf_steal,
411         .get = generic_pipe_buf_get
412 };
413
414 static ssize_t swap_device_splice_read(struct file *filp, loff_t *ppos,
415                                        struct pipe_inode_info *pipe,
416                                        size_t len, unsigned int flags)
417 {
418         /* Wait queue item that consists current task. It is used to be added in
419          * swap_device_wait queue if there is no data to be read. */
420         DEFINE_WAIT(wait);
421
422         int result;
423         struct page *pages[PIPE_DEF_BUFFERS];
424         struct partial_page partial[PIPE_DEF_BUFFERS];
425         struct splice_pipe_desc spd = {
426                 .pages = pages,
427                 .partial = partial,
428                 .nr_pages_max = PIPE_DEF_BUFFERS,
429                 .nr_pages = 0,
430                 .flags = flags,
431                 .ops = &swap_device_pipe_buf_ops,
432                 .spd_release = swap_device_page_release,
433         };
434
435         /* Get next buffer to read */
436         /* TODO : Think about spin_locks to prevent reading race condition.*/
437         while ((result =
438                 driver_to_buffer_next_buffer_to_read()) != E_SD_SUCCESS) {
439
440                 /* Add process to the swap_device_wait queue and set the current
441                  * task state TASK_INTERRUPTIBLE. If there is any data to be
442                  * read, then the current task is removed from the
443                  * swap_device_wait queue and its state is changed. */
444                 prepare_to_wait(&swap_device_wait, &wait, TASK_INTERRUPTIBLE);
445                 if (result < 0) {
446                         print_err("driver_to_buffer_next_buffer_to_read error "
447                                   "%d\n", result);
448                         /* TODO Error return to OS */
449                         result = 0;
450                         goto swap_device_splice_read_error;
451                 } else if (result == E_SD_NO_DATA_TO_READ) {
452                         if (filp->f_flags & O_NONBLOCK) {
453                                 result = -EAGAIN;
454                                 goto swap_device_splice_read_error;
455                         }
456                         if (signal_pending(current)) {
457                                 result = -ERESTARTSYS;
458                                 goto swap_device_splice_read_error;
459                         }
460                         schedule();
461                         finish_wait(&swap_device_wait, &wait);
462                 }
463         }
464
465         if (splice_grow_spd_p(pipe, &spd)) {
466                 result = -ENOMEM;
467                 goto swap_device_splice_read_out;
468         }
469
470         result = driver_to_buffer_fill_spd(&spd);
471         if (result != 0) {
472                 print_err("Cannot fill spd for splice\n");
473                 goto swap_device_shrink_spd;
474         }
475
476         result = splice_to_pipe_p(pipe, &spd);
477
478 swap_device_shrink_spd:
479         swap_device_splice_shrink_spd(pipe, &spd);
480
481 swap_device_splice_read_out:
482         return result;
483
484 swap_device_splice_read_error:
485         finish_wait(&swap_device_wait, &wait);
486
487         return result;
488 }
489
490 /**
491  * @brief Wakes up daemon that splicing data from driver.
492  *
493  * @return Void.
494  */
495 void swap_device_wake_up_process(void)
496 {
497         if (atomic_read(&flag_wake_up) == 0) {
498                 atomic_set(&flag_wake_up, 1);
499                 schedule_work(&w_wake_up);
500         }
501 }
502
503 /**
504  * @brief Registers received message handler.
505  *
506  * @param mh Pointer to message handler.
507  * @return Void.
508  */
509 void set_msg_handler(msg_handler_t mh)
510 {
511         msg_handler = mh;
512 }
513 EXPORT_SYMBOL_GPL(set_msg_handler);