1 /*
2 * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wlan_hdd_sysfs_dp_trace.c
19 *
20 * Implementation for creating sysfs files:
21 *
22 * dp_trace
23 * dump_dp_trace
24 * clear_dp_trace
25 */
26
27 #include <wlan_hdd_includes.h>
28 #include "osif_psoc_sync.h"
29 #include <wlan_hdd_sysfs.h>
30 #include <wlan_hdd_sysfs_dp_trace.h>
31 #include "qdf_trace.h"
32
33 static ssize_t
__hdd_sysfs_dp_trace_store(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,const char * buf,size_t count)34 __hdd_sysfs_dp_trace_store(struct hdd_context *hdd_ctx,
35 struct kobj_attribute *attr,
36 const char *buf,
37 size_t count)
38 {
39 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
40 char *sptr, *token;
41 uint32_t val1;
42 uint8_t val2, val3;
43 int ret;
44
45 if (!wlan_hdd_validate_modules_state(hdd_ctx))
46 return -EINVAL;
47
48 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
49 buf, count);
50
51 if (ret) {
52 hdd_err_rl("invalid input");
53 return ret;
54 }
55
56 sptr = buf_local;
57 hdd_debug("set_dp_trace: count %zu buf_local:(%s)",
58 count, buf_local);
59
60 /* Get val1 */
61 token = strsep(&sptr, " ");
62 if (!token)
63 return -EINVAL;
64 if (kstrtou32(token, 0, &val1))
65 return -EINVAL;
66
67 /* Get val2 */
68 token = strsep(&sptr, " ");
69 if (!token)
70 return -EINVAL;
71 if (kstrtou8(token, 0, &val2))
72 return -EINVAL;
73
74 /* Get val3 */
75 token = strsep(&sptr, " ");
76 if (!token)
77 return -EINVAL;
78 if (kstrtou8(token, 0, &val3))
79 return -EINVAL;
80
81 qdf_dp_trace_set_value(val1, val2, val3);
82
83 return count;
84 }
85
86 static ssize_t
hdd_sysfs_dp_trace_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)87 hdd_sysfs_dp_trace_store(struct kobject *kobj,
88 struct kobj_attribute *attr,
89 const char *buf,
90 size_t count)
91 {
92 struct osif_psoc_sync *psoc_sync;
93 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
94 ssize_t errno_size;
95 int ret;
96
97 ret = wlan_hdd_validate_context(hdd_ctx);
98 if (ret != 0)
99 return ret;
100
101 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
102 &psoc_sync);
103 if (errno_size)
104 return errno_size;
105
106 errno_size = __hdd_sysfs_dp_trace_store(hdd_ctx, attr,
107 buf, count);
108
109 osif_psoc_sync_op_stop(psoc_sync);
110
111 return errno_size;
112 }
113
114 static struct kobj_attribute dp_trace_attribute =
115 __ATTR(dp_trace, 0220, NULL,
116 hdd_sysfs_dp_trace_store);
117
118 static uint32_t dump_dp_trace_count = 0;
119
120 static ssize_t
__hdd_sysfs_dump_dp_trace_store(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char const * buf,size_t count)121 __hdd_sysfs_dump_dp_trace_store(struct hdd_context *hdd_ctx,
122 struct kobj_attribute *attr,
123 char const *buf, size_t count)
124 {
125 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
126 char *sptr, *token;
127 int value, ret;
128
129 if (!wlan_hdd_validate_modules_state(hdd_ctx))
130 return -EINVAL;
131
132 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
133 buf, count);
134 if (ret) {
135 hdd_err_rl("invalid input");
136 return ret;
137 }
138
139 sptr = buf_local;
140 token = strsep(&sptr, " ");
141 if (!token)
142 return -EINVAL;
143 if (kstrtou32(token, 0, &value))
144 return -EINVAL;
145
146 hdd_debug("dump_dp_trace %d", value);
147
148 switch (value) {
149 case HDD_SYSFS_DISABLE_DP_TRACE_LIVE_MODE:
150 qdf_dp_trace_disable_live_mode();
151 break;
152 case HDD_SYSFS_ENABLE_DP_TRACE_LIVE_MODE:
153 qdf_dp_trace_enable_live_mode();
154 break;
155 case HDD_SYSFS_DUMP_DP_TRACE:
156 token = strsep(&sptr, " ");
157 if (!token)
158 return -EINVAL;
159 if (kstrtou32(token, 0, &dump_dp_trace_count))
160 return -EINVAL;
161 break;
162 default:
163 hdd_err_rl("invalid input");
164 return -EINVAL;
165 }
166
167 return count;
168 }
169
hdd_sysfs_dump_dp_trace_store(struct kobject * kobj,struct kobj_attribute * attr,char const * buf,size_t count)170 static ssize_t hdd_sysfs_dump_dp_trace_store(struct kobject *kobj,
171 struct kobj_attribute *attr,
172 char const *buf, size_t count)
173 {
174 struct osif_psoc_sync *psoc_sync;
175 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
176 ssize_t errno_size;
177 int ret;
178
179 ret = wlan_hdd_validate_context(hdd_ctx);
180 if (ret != 0)
181 return ret;
182
183 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
184 &psoc_sync);
185 if (errno_size)
186 return errno_size;
187
188 errno_size = __hdd_sysfs_dump_dp_trace_store(hdd_ctx, attr,
189 buf, count);
190
191 osif_psoc_sync_op_stop(psoc_sync);
192
193 return errno_size;
194 }
195
196 static ssize_t
__hdd_sysfs_dump_dp_trace_show(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char * buf)197 __hdd_sysfs_dump_dp_trace_show(struct hdd_context *hdd_ctx,
198 struct kobj_attribute *attr, char *buf)
199 {
200 if (!wlan_hdd_validate_modules_state(hdd_ctx))
201 return -EINVAL;
202
203 qdf_dp_trace_dump_all(dump_dp_trace_count, QDF_TRACE_DEFAULT_PDEV_ID);
204
205 return 0;
206 }
207
hdd_sysfs_dump_dp_trace_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)208 static ssize_t hdd_sysfs_dump_dp_trace_show(struct kobject *kobj,
209 struct kobj_attribute *attr,
210 char *buf)
211 {
212 struct osif_psoc_sync *psoc_sync;
213 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
214 ssize_t errno_size;
215 int ret;
216
217 ret = wlan_hdd_validate_context(hdd_ctx);
218 if (ret != 0)
219 return ret;
220
221 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
222 &psoc_sync);
223 if (errno_size)
224 return errno_size;
225
226 errno_size = __hdd_sysfs_dump_dp_trace_show(hdd_ctx, attr, buf);
227
228 osif_psoc_sync_op_stop(psoc_sync);
229
230 return errno_size;
231 }
232
233 static struct kobj_attribute dump_dp_trace_attribute =
234 __ATTR(dump_dp_trace, 0660, hdd_sysfs_dump_dp_trace_show,
235 hdd_sysfs_dump_dp_trace_store);
236
237 static ssize_t
__hdd_sysfs_clear_dp_trace_store(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char const * buf,size_t count)238 __hdd_sysfs_clear_dp_trace_store(struct hdd_context *hdd_ctx,
239 struct kobj_attribute *attr,
240 char const *buf, size_t count)
241 {
242 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
243 char *sptr, *token;
244 int value, ret;
245
246 if (!wlan_hdd_validate_modules_state(hdd_ctx))
247 return -EINVAL;
248
249 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
250 buf, count);
251 if (ret) {
252 hdd_err_rl("invalid input");
253 return ret;
254 }
255
256 sptr = buf_local;
257 token = strsep(&sptr, " ");
258 if (!token)
259 return -EINVAL;
260 if (kstrtou32(token, 0, &value))
261 return -EINVAL;
262
263 hdd_debug("clear_dp_trace %d", value);
264
265 qdf_dp_trace_clear_buffer();
266
267 return count;
268 }
269
270 static ssize_t
hdd_sysfs_clear_dp_trace_store(struct kobject * kobj,struct kobj_attribute * attr,char const * buf,size_t count)271 hdd_sysfs_clear_dp_trace_store(struct kobject *kobj,
272 struct kobj_attribute *attr,
273 char const *buf, size_t count)
274 {
275 struct osif_psoc_sync *psoc_sync;
276 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
277 ssize_t errno_size;
278 int ret;
279
280 ret = wlan_hdd_validate_context(hdd_ctx);
281 if (ret != 0)
282 return ret;
283
284 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
285 &psoc_sync);
286 if (errno_size)
287 return errno_size;
288
289 errno_size = __hdd_sysfs_clear_dp_trace_store(hdd_ctx, attr,
290 buf, count);
291
292 osif_psoc_sync_op_stop(psoc_sync);
293
294 return errno_size;
295 }
296
297 static struct kobj_attribute clear_dp_trace_attribute =
298 __ATTR(clear_dp_trace, 0220, NULL,
299 hdd_sysfs_clear_dp_trace_store);
300
hdd_sysfs_dp_trace_create(struct kobject * driver_kobject)301 int hdd_sysfs_dp_trace_create(struct kobject *driver_kobject)
302 {
303 int error;
304
305 if (!driver_kobject) {
306 hdd_err("could not get driver kobject!");
307 return -EINVAL;
308 }
309
310 error = sysfs_create_file(driver_kobject,
311 &dp_trace_attribute.attr);
312 if (error)
313 hdd_err("could not create dp_trace sysfs file");
314
315 error = sysfs_create_file(driver_kobject,
316 &dump_dp_trace_attribute.attr);
317 if (error)
318 hdd_err("could not create dump_dp_trace sysfs file");
319
320 error = sysfs_create_file(driver_kobject,
321 &clear_dp_trace_attribute.attr);
322 if (error)
323 hdd_err("could not create clear_dp_trace sysfs file");
324
325 return error;
326 }
327
328 void
hdd_sysfs_dp_trace_destroy(struct kobject * driver_kobject)329 hdd_sysfs_dp_trace_destroy(struct kobject *driver_kobject)
330 {
331 if (!driver_kobject) {
332 hdd_err("could not get driver kobject!");
333 return;
334 }
335 sysfs_remove_file(driver_kobject, &clear_dp_trace_attribute.attr);
336 sysfs_remove_file(driver_kobject, &dump_dp_trace_attribute.attr);
337 sysfs_remove_file(driver_kobject, &dp_trace_attribute.attr);
338 }
339