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