GNU Linux-libre 4.14.290-gnu1
[releases.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  * 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., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA.
19  *
20  */
21
22 #include <linux/err.h>
23 #include <linux/kernel.h>
24 #include <linux/pci.h>
25
26 #include "atomisp_compat.h"
27 #include "atomisp_internal.h"
28 #include "atomisp_ioctl.h"
29 #include "hmm/hmm.h"
30
31 /*
32  * _iunit_debug:
33  * dbglvl: iunit css driver trace level
34  * dbgopt: iunit debug option:
35  *        bit 0: binary list
36  *        bit 1: running binary
37  *        bit 2: memory statistic
38 */
39 struct _iunit_debug {
40         struct pci_driver       *drv;
41         struct atomisp_device   *isp;
42         unsigned int            dbglvl;
43         unsigned int            dbgfun;
44         unsigned int            dbgopt;
45 };
46
47 #define OPTION_BIN_LIST                 (1<<0)
48 #define OPTION_BIN_RUN                  (1<<1)
49 #define OPTION_MEM_STAT                 (1<<2)
50 #define OPTION_VALID                    (OPTION_BIN_LIST \
51                                         | OPTION_BIN_RUN \
52                                         | OPTION_MEM_STAT)
53
54 static struct _iunit_debug iunit_debug = {
55         .dbglvl = 0,
56         .dbgopt = OPTION_BIN_LIST,
57 };
58
59 static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
60                                 unsigned int opt)
61 {
62         int ret = 0;
63
64         if (opt & OPTION_VALID) {
65                 if (opt & OPTION_BIN_LIST) {
66                         ret = atomisp_css_dump_blob_infor();
67                         if (ret) {
68                                 dev_err(atomisp_dev, "%s dump blob infor err[ret:%d]\n",
69                                         __func__, ret);
70                                 goto opt_err;
71                         }
72                 }
73
74                 if (opt & OPTION_BIN_RUN) {
75                         if (atomisp_streaming_count(isp)) {
76                                 atomisp_css_dump_sp_raw_copy_linecount(true);
77                                 atomisp_css_debug_dump_isp_binary();
78                         } else {
79                                 ret = -EPERM;
80                                 dev_err(atomisp_dev, "%s dump running bin err[ret:%d]\n",
81                                         __func__, ret);
82                                 goto opt_err;
83                         }
84                 }
85
86                 if (opt & OPTION_MEM_STAT)
87                         hmm_show_mem_stat(__func__, __LINE__);
88         } else {
89                 ret = -EINVAL;
90                 dev_err(atomisp_dev, "%s dump nothing[ret=%d]\n", __func__,
91                         ret);
92         }
93
94 opt_err:
95         return ret;
96 }
97
98 static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
99 {
100         iunit_debug.dbglvl = atomisp_css_debug_get_dtrace_level();
101         return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
102 }
103
104 static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
105                                 size_t size)
106 {
107         if (kstrtouint(buf, 10, &iunit_debug.dbglvl)
108                 || iunit_debug.dbglvl < 1
109                 || iunit_debug.dbglvl > 9) {
110                 return -ERANGE;
111         }
112         atomisp_css_debug_set_dtrace_level(iunit_debug.dbglvl);
113
114         return size;
115 }
116
117 static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
118 {
119         iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
120         return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
121 }
122
123 static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
124                                 size_t size)
125 {
126         unsigned int opt;
127         int ret;
128
129         ret = kstrtouint(buf, 10, &opt);
130         if (ret)
131                 return ret;
132
133         ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt);
134         if (ret)
135                 return ret;
136
137         iunit_debug.dbgfun = opt;
138
139         return size;
140 }
141
142 static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
143 {
144         return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt);
145 }
146
147 static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
148                                 size_t size)
149 {
150         unsigned int opt;
151         int ret;
152
153         ret = kstrtouint(buf, 10, &opt);
154         if (ret)
155                 return ret;
156
157         iunit_debug.dbgopt = opt;
158         ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt);
159         if (ret)
160                 return ret;
161
162         return size;
163 }
164
165 static struct driver_attribute iunit_drvfs_attrs[] = {
166         __ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store),
167         __ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store),
168         __ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store),
169 };
170
171 static int iunit_drvfs_create_files(struct pci_driver *drv)
172 {
173         int i, ret = 0;
174
175         for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
176                 ret |= driver_create_file(&(drv->driver),
177                                         &iunit_drvfs_attrs[i]);
178
179         return ret;
180 }
181
182 static void iunit_drvfs_remove_files(struct pci_driver *drv)
183 {
184         int i;
185
186         for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
187                 driver_remove_file(&(drv->driver), &iunit_drvfs_attrs[i]);
188 }
189
190 int atomisp_drvfs_init(struct pci_driver *drv, struct atomisp_device *isp)
191 {
192         int ret;
193
194         iunit_debug.isp = isp;
195         iunit_debug.drv = drv;
196
197         ret = iunit_drvfs_create_files(iunit_debug.drv);
198         if (ret) {
199                 dev_err(atomisp_dev, "drvfs_create_files error: %d\n", ret);
200                 iunit_drvfs_remove_files(drv);
201         }
202
203         return ret;
204 }
205
206 void atomisp_drvfs_exit(void)
207 {
208         iunit_drvfs_remove_files(iunit_debug.drv);
209 }