blob: e5652b4f1c53c896aca5f45897f9d77a73b9c2b9 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_debugfs.c
30 *
31 * This driver currently supports the following debugfs files:
32 * wlan_wcnss/wow_enable to enable/disable WoWL.
33 * wlan_wcnss/wow_pattern to configure WoWL patterns.
34 * wlan_wcnss/pattern_gen to configure periodic TX patterns.
35 */
36
37#ifdef WLAN_OPEN_SOURCE
Jeff Johnson85c0abf2016-08-05 12:28:24 -070038/* denote that this file does not allow legacy hddLog */
39#define HDD_DISALLOW_LEGACY_HDDLOG 1
40
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080041#include <wlan_hdd_includes.h>
Jeff Johnson510779e2016-10-05 15:51:12 -070042#include <wlan_hdd_debugfs.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include <wlan_hdd_wowl.h>
44#include <cds_sched.h>
45
46#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8
47#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
48#define MAX_USER_COMMAND_SIZE_FRAME 4096
49
50/**
51 * __wcnss_wowenable_write() - wow_enable debugfs handler
52 * @file: debugfs file handle
53 * @buf: text being written to the debugfs
54 * @count: size of @buf
55 * @ppos: (unused) offset into the virtual file system
56 *
57 * Return: number of bytes processed
58 */
59static ssize_t __wcnss_wowenable_write(struct file *file,
60 const char __user *buf, size_t count,
61 loff_t *ppos)
62{
63 hdd_adapter_t *pAdapter;
64 hdd_context_t *hdd_ctx;
65 char cmd[MAX_USER_COMMAND_SIZE_WOWL_ENABLE + 1];
66 char *sptr, *token;
67 uint8_t wow_enable = 0;
68 uint8_t wow_mp = 0;
69 uint8_t wow_pbm = 0;
70 int ret;
71
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053072 ENTER();
73
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080074 pAdapter = (hdd_adapter_t *)file->private_data;
75 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070076 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077
78 return -EINVAL;
79 }
80
81 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
82 ret = wlan_hdd_validate_context(hdd_ctx);
83 if (0 != ret)
84 return ret;
85
86
87 if (!sme_is_feature_supported_by_fw(WOW)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070088 hdd_err("Wake-on-Wireless feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089
90 return -EINVAL;
91 }
92
93 if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070094 hdd_err("Command length is larger than %d bytes.",
95 MAX_USER_COMMAND_SIZE_WOWL_ENABLE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
97 return -EINVAL;
98 }
99
100 /* Get command from user */
101 if (copy_from_user(cmd, buf, count))
102 return -EFAULT;
103 cmd[count] = '\0';
104 sptr = cmd;
105
106 /* Get enable or disable wow */
107 token = strsep(&sptr, " ");
108 if (!token)
109 return -EINVAL;
110 if (kstrtou8(token, 0, &wow_enable))
111 return -EINVAL;
112
113 /* Disable wow */
114 if (!wow_enable) {
115 if (!hdd_exit_wowl(pAdapter)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700116 hdd_err("hdd_exit_wowl failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117
118 return -EFAULT;
119 }
120
121 return count;
122 }
123
124 /* Get enable or disable magic packet mode */
125 token = strsep(&sptr, " ");
126 if (!token)
127 return -EINVAL;
128 if (kstrtou8(token, 0, &wow_mp))
129 return -EINVAL;
130 if (wow_mp > 1)
131 wow_mp = 1;
132
133 /* Get enable or disable pattern byte matching mode */
134 token = strsep(&sptr, " ");
135 if (!token)
136 return -EINVAL;
137 if (kstrtou8(token, 0, &wow_pbm))
138 return -EINVAL;
139 if (wow_pbm > 1)
140 wow_pbm = 1;
141
142 if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700143 hdd_err("hdd_enter_wowl failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144
145 return -EFAULT;
146 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530147 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148 return count;
149}
150
151/**
152 * wcnss_wowenable_write() - SSR wrapper for wcnss_wowenable_write
153 * @file: file pointer
154 * @buf: buffer
155 * @count: count
156 * @ppos: position pointer
157 *
158 * Return: 0 on success, error number otherwise
159 */
160static ssize_t wcnss_wowenable_write(struct file *file,
161 const char __user *buf,
162 size_t count, loff_t *ppos)
163{
164 ssize_t ret;
165
166 cds_ssr_protect(__func__);
167 ret = __wcnss_wowenable_write(file, buf, count, ppos);
168 cds_ssr_unprotect(__func__);
169
170 return ret;
171}
172
173/**
174 * __wcnss_wowpattern_write() - wow_pattern debugfs handler
175 * @file: debugfs file handle
176 * @buf: text being written to the debugfs
177 * @count: size of @buf
178 * @ppos: (unused) offset into the virtual file system
179 *
180 * Return: number of bytes processed
181 */
182static ssize_t __wcnss_wowpattern_write(struct file *file,
183 const char __user *buf, size_t count,
184 loff_t *ppos)
185{
186 hdd_adapter_t *pAdapter = (hdd_adapter_t *) file->private_data;
187 hdd_context_t *hdd_ctx;
188 char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN + 1];
189 char *sptr, *token;
190 uint8_t pattern_idx = 0;
191 uint8_t pattern_offset = 0;
192 char *pattern_buf;
193 char *pattern_mask;
194 int ret;
195
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530196 ENTER();
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700199 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200
201 return -EINVAL;
202 }
203
204 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
205 ret = wlan_hdd_validate_context(hdd_ctx);
206 if (0 != ret)
207 return ret;
208
209 if (!sme_is_feature_supported_by_fw(WOW)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700210 hdd_err("Wake-on-Wireless feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211
212 return -EINVAL;
213 }
214
215 if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700216 hdd_err("Command length is larger than %d bytes.",
217 MAX_USER_COMMAND_SIZE_WOWL_PATTERN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218
219 return -EINVAL;
220 }
221
222 /* Get command from user */
223 if (copy_from_user(cmd, buf, count))
224 return -EFAULT;
225 cmd[count] = '\0';
226 sptr = cmd;
227
228 /* Get pattern idx */
229 token = strsep(&sptr, " ");
230 if (!token)
231 return -EINVAL;
232
233 if (kstrtou8(token, 0, &pattern_idx))
234 return -EINVAL;
235
236 /* Get pattern offset */
237 token = strsep(&sptr, " ");
238
239 /* Delete pattern if no further argument */
240 if (!token) {
241 hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx);
242
243 return count;
244 }
245
246 if (kstrtou8(token, 0, &pattern_offset))
247 return -EINVAL;
248
249 /* Get pattern */
250 token = strsep(&sptr, " ");
251 if (!token)
252 return -EINVAL;
253
254 pattern_buf = token;
255
256 /* Get pattern mask */
257 token = strsep(&sptr, " ");
258 if (!token)
259 return -EINVAL;
260
261 pattern_mask = token;
262 pattern_mask[strlen(pattern_mask) - 1] = '\0';
263
264 hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset,
265 pattern_buf, pattern_mask);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530266 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 return count;
268}
269
270/**
271 * wcnss_wowpattern_write() - SSR wrapper for __wcnss_wowpattern_write
272 * @file: file pointer
273 * @buf: buffer
274 * @count: count
275 * @ppos: position pointer
276 *
277 * Return: 0 on success, error number otherwise
278 */
279static ssize_t wcnss_wowpattern_write(struct file *file,
280 const char __user *buf,
281 size_t count, loff_t *ppos)
282{
283 ssize_t ret;
284
285 cds_ssr_protect(__func__);
286 ret = __wcnss_wowpattern_write(file, buf, count, ppos);
287 cds_ssr_unprotect(__func__);
288
289 return ret;
290}
291
292/**
293 * wcnss_patterngen_write() - pattern_gen debugfs handler
294 * @file: debugfs file handle
295 * @buf: text being written to the debugfs
296 * @count: size of @buf
297 * @ppos: (unused) offset into the virtual file system
298 *
299 * Return: number of bytes processed
300 */
301static ssize_t __wcnss_patterngen_write(struct file *file,
302 const char __user *buf, size_t count,
303 loff_t *ppos)
304{
305 hdd_adapter_t *pAdapter;
306 hdd_context_t *pHddCtx;
307 tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams;
308 tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams;
309
310 char *cmd, *sptr, *token;
311 uint8_t pattern_idx = 0;
312 uint8_t pattern_duration = 0;
313 char *pattern_buf;
314 uint16_t pattern_len = 0;
315 uint16_t i = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530316 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317 int ret;
318
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530319 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320
321 pAdapter = (hdd_adapter_t *)file->private_data;
322 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700323 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324
325 return -EINVAL;
326 }
327
328 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
329 ret = wlan_hdd_validate_context(pHddCtx);
330 if (0 != ret)
331 return ret;
332
333 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700334 hdd_err("Periodic Tx Pattern Offload feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335 return -EINVAL;
336 }
337
338 /* Get command from user */
339 if (count <= MAX_USER_COMMAND_SIZE_FRAME)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530340 cmd = qdf_mem_malloc(count + 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341 else {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700342 hdd_err("Command length is larger than %d bytes.",
343 MAX_USER_COMMAND_SIZE_FRAME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344
345 return -EINVAL;
346 }
347
348 if (!cmd) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700349 hdd_err("Memory allocation for cmd failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800350 return -ENOMEM;
351 }
352
353 if (copy_from_user(cmd, buf, count)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530354 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 return -EFAULT;
356 }
357 cmd[count] = '\0';
358 sptr = cmd;
359
360 /* Get pattern idx */
361 token = strsep(&sptr, " ");
362 if (!token)
363 goto failure;
364 if (kstrtou8(token, 0, &pattern_idx))
365 goto failure;
366
367 if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700368 hdd_err("Pattern index %d is not in the range (0 ~ %d).",
369 pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370
371 goto failure;
372 }
373
374 /* Get pattern duration */
375 token = strsep(&sptr, " ");
376 if (!token)
377 goto failure;
378 if (kstrtou8(token, 0, &pattern_duration))
379 goto failure;
380
381 /* Delete pattern using index if duration is 0 */
382 if (!pattern_duration) {
383 delPeriodicTxPtrnParams =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530384 qdf_mem_malloc(sizeof(tSirDelPeriodicTxPtrn));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 if (!delPeriodicTxPtrnParams) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700386 hdd_err("Memory allocation failed!");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530387 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return -ENOMEM;
389 }
390 delPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
391 delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530392 qdf_copy_macaddr(&delPeriodicTxPtrnParams->mac_address,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -0800393 &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394
395 /* Delete pattern */
396 status = sme_del_periodic_tx_ptrn(pHddCtx->hHal,
397 delPeriodicTxPtrnParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530398 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700399 hdd_err("sme_del_periodic_tx_ptrn() failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530401 qdf_mem_free(delPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 goto failure;
403 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530404 qdf_mem_free(cmd);
405 qdf_mem_free(delPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406 return count;
407 }
408
409 /*
410 * In SAP mode allow configuration without any connection check
411 * In STA mode check if it's in connected state before adding
412 * patterns
413 */
414 hdd_info("device mode %d", pAdapter->device_mode);
Krunal Sonibe766b02016-03-10 13:00:44 -0800415 if ((QDF_STA_MODE == pAdapter->device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700417 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 goto failure;
419 }
420
421 /* Get pattern */
422 token = strsep(&sptr, " ");
423 if (!token)
424 goto failure;
425
426 pattern_buf = token;
427 pattern_buf[strlen(pattern_buf) - 1] = '\0';
428 pattern_len = strlen(pattern_buf);
429
430 /* Since the pattern is a hex string, 2 characters represent 1 byte. */
431 if (pattern_len % 2) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700432 hdd_err("Malformed pattern!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433
434 goto failure;
435 } else
436 pattern_len >>= 1;
437
438 if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700439 hdd_err("Not an 802.3 frame!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440
441 goto failure;
442 }
443
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530444 addPeriodicTxPtrnParams = qdf_mem_malloc(sizeof(tSirAddPeriodicTxPtrn));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800445 if (!addPeriodicTxPtrnParams) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700446 hdd_err("Memory allocation failed!");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530447 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800448 return -ENOMEM;
449 }
450
451 addPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
452 addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500;
453 addPeriodicTxPtrnParams->ucPtrnSize = pattern_len;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530454 qdf_copy_macaddr(&addPeriodicTxPtrnParams->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -0800455 &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456
457 /* Extract the pattern */
458 for (i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) {
459 addPeriodicTxPtrnParams->ucPattern[i] =
460 (hex_to_bin(pattern_buf[0]) << 4) +
461 hex_to_bin(pattern_buf[1]);
462
463 /* Skip to next byte */
464 pattern_buf += 2;
465 }
466
467 /* Add pattern */
468 status = sme_add_periodic_tx_ptrn(pHddCtx->hHal,
469 addPeriodicTxPtrnParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530470 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700471 hdd_err("sme_add_periodic_tx_ptrn() failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530473 qdf_mem_free(addPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 goto failure;
475 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530476 qdf_mem_free(cmd);
477 qdf_mem_free(addPeriodicTxPtrnParams);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530478 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479 return count;
480
481failure:
Rajeev Kumarb08f39c2016-02-04 17:50:54 -0800482 hdd_err("Invalid input. Input format is: ptrn_idx duration pattern");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530483 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484 return -EINVAL;
485}
486
487/**
488 * wcnss_patterngen_write() - SSR wrapper for __wcnss_patterngen_write
489 * @file: file pointer
490 * @buf: buffer
491 * @count: count
492 * @ppos: position pointer
493 *
494 * Return: 0 on success, error number otherwise
495 */
496static ssize_t wcnss_patterngen_write(struct file *file,
497 const char __user *buf,
498 size_t count, loff_t *ppos)
499{
500 ssize_t ret;
501
502 cds_ssr_protect(__func__);
503 ret = __wcnss_patterngen_write(file, buf, count, ppos);
504 cds_ssr_unprotect(__func__);
505
506 return ret;
507}
508
509/**
510 * __wcnss_debugfs_open() - Generic debugfs open() handler
511 * @inode: inode of the debugfs file
512 * @file: file handle of the debugfs file
513 *
514 * Return: 0
515 */
516static int __wcnss_debugfs_open(struct inode *inode, struct file *file)
517{
518 hdd_adapter_t *adapter;
519 hdd_context_t *hdd_ctx;
520 int ret;
521
522 ENTER();
523
524 if (inode->i_private)
525 file->private_data = inode->i_private;
526
527 adapter = (hdd_adapter_t *)file->private_data;
528 if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700529 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 return -EINVAL;
531 }
532
533 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
534 ret = wlan_hdd_validate_context(hdd_ctx);
535 if (0 != ret)
536 return ret;
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530537 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 return 0;
539}
540
541/**
542 * wcnss_debugfs_open() - SSR wrapper for __wcnss_debugfs_open
543 * @inode: inode pointer
544 * @file: file pointer
545 *
546 * Return: 0 on success, error number otherwise
547 */
548static int wcnss_debugfs_open(struct inode *inode, struct file *file)
549{
550 int ret;
551
552 cds_ssr_protect(__func__);
553 ret = __wcnss_debugfs_open(inode, file);
554 cds_ssr_unprotect(__func__);
555
556 return ret;
557}
558
559static const struct file_operations fops_wowenable = {
560 .write = wcnss_wowenable_write,
561 .open = wcnss_debugfs_open,
562 .owner = THIS_MODULE,
563 .llseek = default_llseek,
564};
565
566static const struct file_operations fops_wowpattern = {
567 .write = wcnss_wowpattern_write,
568 .open = wcnss_debugfs_open,
569 .owner = THIS_MODULE,
570 .llseek = default_llseek,
571};
572
573static const struct file_operations fops_patterngen = {
574 .write = wcnss_patterngen_write,
575 .open = wcnss_debugfs_open,
576 .owner = THIS_MODULE,
577 .llseek = default_llseek,
578};
579
580/**
581 * hdd_debugfs_init() - Initialize debugfs interface
Rajeev Kumardca5f812016-02-04 17:28:06 -0800582 * @adapter: interface adapter pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583 *
584 * Register support for the debugfs files supported by the driver.
585 *
586 * NB: The current implementation only supports debugfs operations
587 * on the primary interface, i.e. wlan0
588 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530589 * Return: QDF_STATUS_SUCCESS if all files registered,
590 * QDF_STATUS_E_FAILURE on failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 */
Rajeev Kumardca5f812016-02-04 17:28:06 -0800592QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593{
Rajeev Kumardca5f812016-02-04 17:28:06 -0800594 struct net_device *dev = adapter->dev;
595 adapter->debugfs_phy = debugfs_create_dir(dev->name, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596
Rajeev Kumardca5f812016-02-04 17:28:06 -0800597 if (NULL == adapter->debugfs_phy)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530598 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599
600 if (NULL == debugfs_create_file("wow_enable", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800601 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 &fops_wowenable))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530603 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604
605 if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800606 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 &fops_wowpattern))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530608 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609
610 if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800611 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 &fops_patterngen))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530613 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800614
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530615 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616}
617
618/**
619 * hdd_debugfs_exit() - Shutdown debugfs interface
Rajeev Kumardca5f812016-02-04 17:28:06 -0800620 * @adapter: interface adapter pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621 *
622 * Unregister support for the debugfs files supported by the driver.
623 *
624 * Return: None
625 */
Rajeev Kumardca5f812016-02-04 17:28:06 -0800626void hdd_debugfs_exit(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627{
Rajeev Kumardca5f812016-02-04 17:28:06 -0800628 struct net_device *dev = adapter->dev;
629
630 if (adapter->debugfs_phy)
631 debugfs_remove_recursive(adapter->debugfs_phy);
632 else
633 hdd_info("Interface %s has no debugfs entry", dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634}
635#endif /* #ifdef WLAN_OPEN_SOURCE */