tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / wsp / wsp_debugfs.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * Copyright (C) Samsung Electronics, 2014
17  *
18  * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
19  *
20  */
21
22
23 #include <linux/slab.h>
24 #include <linux/debugfs.h>
25 #include <linux/uaccess.h>
26 #include <master/swap_debugfs.h>
27 #include "wsp.h"
28
29
30 static int do_write_cmd(const char *buf, size_t count)
31 {
32         int n, ret = 0;
33         char *name;
34         unsigned long offset;
35
36         name = kmalloc(count, GFP_KERNEL);
37         if (name == NULL)
38                 return -ENOMEM;
39
40         n = sscanf(buf, "%lx %s", &offset, name);
41         if (n != 2) {
42                 ret = -EINVAL;
43                 goto free_name;
44         }
45
46         ret = wsp_set_addr(name, offset);
47
48 free_name:
49         kfree(name);
50         return ret;
51 }
52
53 /* ============================================================================
54  * ===                         DEBUGFS FOR ENABLE                           ===
55  * ============================================================================
56  */
57 static ssize_t write_cmd(struct file *file, const char __user *user_buf,
58                          size_t count, loff_t *ppos)
59 {
60         enum { max_count = 1024 };
61         int ret;
62         char *buf;
63
64         if (count > max_count)
65                 return -ENOMEM;
66
67         buf = kmalloc(count + 1, GFP_KERNEL);
68         if (buf == NULL)
69                 return -ENOMEM;
70
71         if (copy_from_user(buf, user_buf, count)) {
72                 ret = -EFAULT;
73                 goto free_buf;
74         }
75
76         buf[count] = '\0';
77         ret = do_write_cmd(buf, count);
78
79 free_buf:
80         kfree(buf);
81         return ret ? ret : count;
82 }
83
84 static const struct file_operations fops_cmd = {
85         .write =        write_cmd,
86         .llseek =       default_llseek,
87 };
88
89
90
91
92 /* ============================================================================
93  * ===                         DEBUGFS FOR ENABLE                           ===
94  * ============================================================================
95  */
96 static ssize_t read_enabled(struct file *file, char __user *user_buf,
97                             size_t count, loff_t *ppos)
98 {
99         char buf[2];
100
101         buf[0] = wsp_get_mode() == WSP_OFF ? '0' : '1';
102         buf[1] = '\n';
103
104         return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
105 }
106
107 static ssize_t write_enabled(struct file *file, const char __user *user_buf,
108                              size_t count, loff_t *ppos)
109 {
110         int ret = 0;
111         char buf[32];
112         size_t buf_size;
113
114         buf_size = min(count, (sizeof(buf) - 1));
115         if (copy_from_user(buf, user_buf, buf_size))
116                 return -EFAULT;
117
118         buf[buf_size] = '\0';
119         switch (buf[0]) {
120         case '1':
121                 ret = wsp_set_mode(WSP_ON);
122                 break;
123         case '0':
124                 ret = wsp_set_mode(WSP_OFF);
125                 break;
126         default:
127                 return -EINVAL;
128         }
129
130         if (ret)
131                 return ret;
132
133         return count;
134 }
135
136 static const struct file_operations fops_enabled = {
137         .read =         read_enabled,
138         .write =        write_enabled,
139         .llseek =       default_llseek,
140 };
141
142
143 static struct dentry *wsp_dir;
144
145 void wsp_debugfs_exit(void)
146 {
147         if (wsp_dir)
148                 debugfs_remove_recursive(wsp_dir);
149
150         wsp_dir = NULL;
151 }
152
153 int wsp_debugfs_init(void)
154 {
155         struct dentry *dentry;
156
157         dentry = swap_debugfs_getdir();
158         if (dentry == NULL)
159                 return -ENOENT;
160
161         wsp_dir = debugfs_create_dir("wsp", dentry);
162         if (wsp_dir == NULL)
163                 return -ENOMEM;
164
165         dentry = debugfs_create_file("enabled", 0600, wsp_dir, NULL,
166                                      &fops_enabled);
167         if (dentry == NULL)
168                 goto fail;
169
170         dentry = debugfs_create_file("cmd", 0600, wsp_dir, NULL, &fops_cmd);
171         if (dentry == NULL)
172                 goto fail;
173
174         return 0;
175
176 fail:
177         wsp_debugfs_exit();
178         return -ENOMEM;
179 }