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