Merge branch 'afs-dh' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-block.git] / drivers / staging / media / atomisp / pci / atomisp2 / atomisp_drvfs.c
1 /*
2  * Support for atomisp driver sysfs interface
3  *
4  * Copyright (c) 2014 Intel Corporation. All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version
8  * 2 as published by the Free Software Foundation.
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  *
16  */
17
18 #include <linux/device.h>
19 #include <linux/err.h>
20 #include <linux/kernel.h>
21
22 #include "atomisp_compat.h"
23 #include "atomisp_internal.h"
24 #include "atomisp_ioctl.h"
25 #include "atomisp_drvfs.h"
26 #include "hmm/hmm.h"
27
28 /*
29  * _iunit_debug:
30  * dbglvl: iunit css driver trace level
31  * dbgopt: iunit debug option:
32  *        bit 0: binary list
33  *        bit 1: running binary
34  *        bit 2: memory statistic
35 */
36 struct _iunit_debug {
37         struct device_driver    *drv;
38         struct atomisp_device   *isp;
39         unsigned int            dbglvl;
40         unsigned int            dbgfun;
41         unsigned int            dbgopt;
42 };
43
44 #define OPTION_BIN_LIST                 (1<<0)
45 #define OPTION_BIN_RUN                  (1<<1)
46 #define OPTION_MEM_STAT                 (1<<2)
47 #define OPTION_VALID                    (OPTION_BIN_LIST \
48                                         | OPTION_BIN_RUN \
49                                         | OPTION_MEM_STAT)
50
51 static struct _iunit_debug iunit_debug = {
52         .dbglvl = 0,
53         .dbgopt = OPTION_BIN_LIST,
54 };
55
56 static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
57                                 unsigned int opt)
58 {
59         int ret = 0;
60
61         if (opt & OPTION_VALID) {
62                 if (opt & OPTION_BIN_LIST) {
63                         ret = atomisp_css_dump_blob_infor();
64                         if (ret) {
65                                 dev_err(atomisp_dev, "%s dump blob infor err[ret:%d]\n",
66                                         __func__, ret);
67                                 goto opt_err;
68                         }
69                 }
70
71                 if (opt & OPTION_BIN_RUN) {
72                         if (atomisp_streaming_count(isp)) {
73                                 atomisp_css_dump_sp_raw_copy_linecount(true);
74                                 atomisp_css_debug_dump_isp_binary();
75                         } else {
76                                 ret = -EPERM;
77                                 dev_err(atomisp_dev, "%s dump running bin err[ret:%d]\n",
78                                         __func__, ret);
79                                 goto opt_err;
80                         }
81                 }
82
83                 if (opt & OPTION_MEM_STAT)
84                         hmm_show_mem_stat(__func__, __LINE__);
85         } else {
86                 ret = -EINVAL;
87                 dev_err(atomisp_dev, "%s dump nothing[ret=%d]\n", __func__,
88                         ret);
89         }
90
91 opt_err:
92         return ret;
93 }
94
95 static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
96 {
97         iunit_debug.dbglvl = atomisp_css_debug_get_dtrace_level();
98         return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
99 }
100
101 static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
102                                 size_t size)
103 {
104         if (kstrtouint(buf, 10, &iunit_debug.dbglvl)
105                 || iunit_debug.dbglvl < 1
106                 || iunit_debug.dbglvl > 9) {
107                 return -ERANGE;
108         }
109         atomisp_css_debug_set_dtrace_level(iunit_debug.dbglvl);
110
111         return size;
112 }
113
114 static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
115 {
116         iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
117         return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
118 }
119
120 static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
121                                 size_t size)
122 {
123         unsigned int opt;
124         int ret;
125
126         ret = kstrtouint(buf, 10, &opt);
127         if (ret)
128                 return ret;
129
130         ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt);
131         if (ret)
132                 return ret;
133
134         iunit_debug.dbgfun = opt;
135
136         return size;
137 }
138
139 static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
140 {
141         return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt);
142 }
143
144 static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
145                                 size_t size)
146 {
147         unsigned int opt;
148         int ret;
149
150         ret = kstrtouint(buf, 10, &opt);
151         if (ret)
152                 return ret;
153
154         iunit_debug.dbgopt = opt;
155         ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt);
156         if (ret)
157                 return ret;
158
159         return size;
160 }
161
162 static const struct driver_attribute iunit_drvfs_attrs[] = {
163         __ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store),
164         __ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store),
165         __ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store),
166 };
167
168 static int iunit_drvfs_create_files(struct device_driver *drv)
169 {
170         int i, ret = 0;
171
172         for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
173                 ret |= driver_create_file(drv, &iunit_drvfs_attrs[i]);
174
175         return ret;
176 }
177
178 static void iunit_drvfs_remove_files(struct device_driver *drv)
179 {
180         int i;
181
182         for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
183                 driver_remove_file(drv, &iunit_drvfs_attrs[i]);
184 }
185
186 int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp)
187 {
188         int ret;
189
190         iunit_debug.isp = isp;
191         iunit_debug.drv = drv;
192
193         ret = iunit_drvfs_create_files(iunit_debug.drv);
194         if (ret) {
195                 dev_err(atomisp_dev, "drvfs_create_files error: %d\n", ret);
196                 iunit_drvfs_remove_files(iunit_debug.drv);
197         }
198
199         return ret;
200 }
201
202 void atomisp_drvfs_exit(void)
203 {
204         iunit_drvfs_remove_files(iunit_debug.drv);
205 }