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