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