blob: cb1155f8e161e52b050ea1bf0cf20bf12879d6d6 [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>
42#include <wlan_hdd_wowl.h>
43#include <cds_sched.h>
44
45#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8
46#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
47#define MAX_USER_COMMAND_SIZE_FRAME 4096
48
49/**
50 * __wcnss_wowenable_write() - wow_enable debugfs handler
51 * @file: debugfs file handle
52 * @buf: text being written to the debugfs
53 * @count: size of @buf
54 * @ppos: (unused) offset into the virtual file system
55 *
56 * Return: number of bytes processed
57 */
58static ssize_t __wcnss_wowenable_write(struct file *file,
59 const char __user *buf, size_t count,
60 loff_t *ppos)
61{
62 hdd_adapter_t *pAdapter;
63 hdd_context_t *hdd_ctx;
64 char cmd[MAX_USER_COMMAND_SIZE_WOWL_ENABLE + 1];
65 char *sptr, *token;
66 uint8_t wow_enable = 0;
67 uint8_t wow_mp = 0;
68 uint8_t wow_pbm = 0;
69 int ret;
70
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053071 ENTER();
72
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073 pAdapter = (hdd_adapter_t *)file->private_data;
74 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070075 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076
77 return -EINVAL;
78 }
79
80 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
81 ret = wlan_hdd_validate_context(hdd_ctx);
82 if (0 != ret)
83 return ret;
84
85
86 if (!sme_is_feature_supported_by_fw(WOW)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070087 hdd_err("Wake-on-Wireless feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088
89 return -EINVAL;
90 }
91
92 if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -070093 hdd_err("Command length is larger than %d bytes.",
94 MAX_USER_COMMAND_SIZE_WOWL_ENABLE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
96 return -EINVAL;
97 }
98
99 /* Get command from user */
100 if (copy_from_user(cmd, buf, count))
101 return -EFAULT;
102 cmd[count] = '\0';
103 sptr = cmd;
104
105 /* Get enable or disable wow */
106 token = strsep(&sptr, " ");
107 if (!token)
108 return -EINVAL;
109 if (kstrtou8(token, 0, &wow_enable))
110 return -EINVAL;
111
112 /* Disable wow */
113 if (!wow_enable) {
114 if (!hdd_exit_wowl(pAdapter)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700115 hdd_err("hdd_exit_wowl failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116
117 return -EFAULT;
118 }
119
120 return count;
121 }
122
123 /* Get enable or disable magic packet mode */
124 token = strsep(&sptr, " ");
125 if (!token)
126 return -EINVAL;
127 if (kstrtou8(token, 0, &wow_mp))
128 return -EINVAL;
129 if (wow_mp > 1)
130 wow_mp = 1;
131
132 /* Get enable or disable pattern byte matching mode */
133 token = strsep(&sptr, " ");
134 if (!token)
135 return -EINVAL;
136 if (kstrtou8(token, 0, &wow_pbm))
137 return -EINVAL;
138 if (wow_pbm > 1)
139 wow_pbm = 1;
140
141 if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700142 hdd_err("hdd_enter_wowl failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143
144 return -EFAULT;
145 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530146 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 return count;
148}
149
150/**
151 * wcnss_wowenable_write() - SSR wrapper for wcnss_wowenable_write
152 * @file: file pointer
153 * @buf: buffer
154 * @count: count
155 * @ppos: position pointer
156 *
157 * Return: 0 on success, error number otherwise
158 */
159static ssize_t wcnss_wowenable_write(struct file *file,
160 const char __user *buf,
161 size_t count, loff_t *ppos)
162{
163 ssize_t ret;
164
165 cds_ssr_protect(__func__);
166 ret = __wcnss_wowenable_write(file, buf, count, ppos);
167 cds_ssr_unprotect(__func__);
168
169 return ret;
170}
171
172/**
173 * __wcnss_wowpattern_write() - wow_pattern debugfs handler
174 * @file: debugfs file handle
175 * @buf: text being written to the debugfs
176 * @count: size of @buf
177 * @ppos: (unused) offset into the virtual file system
178 *
179 * Return: number of bytes processed
180 */
181static ssize_t __wcnss_wowpattern_write(struct file *file,
182 const char __user *buf, size_t count,
183 loff_t *ppos)
184{
185 hdd_adapter_t *pAdapter = (hdd_adapter_t *) file->private_data;
186 hdd_context_t *hdd_ctx;
187 char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN + 1];
188 char *sptr, *token;
189 uint8_t pattern_idx = 0;
190 uint8_t pattern_offset = 0;
191 char *pattern_buf;
192 char *pattern_mask;
193 int ret;
194
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530195 ENTER();
196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700198 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199
200 return -EINVAL;
201 }
202
203 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
204 ret = wlan_hdd_validate_context(hdd_ctx);
205 if (0 != ret)
206 return ret;
207
208 if (!sme_is_feature_supported_by_fw(WOW)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700209 hdd_err("Wake-on-Wireless feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210
211 return -EINVAL;
212 }
213
214 if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700215 hdd_err("Command length is larger than %d bytes.",
216 MAX_USER_COMMAND_SIZE_WOWL_PATTERN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217
218 return -EINVAL;
219 }
220
221 /* Get command from user */
222 if (copy_from_user(cmd, buf, count))
223 return -EFAULT;
224 cmd[count] = '\0';
225 sptr = cmd;
226
227 /* Get pattern idx */
228 token = strsep(&sptr, " ");
229 if (!token)
230 return -EINVAL;
231
232 if (kstrtou8(token, 0, &pattern_idx))
233 return -EINVAL;
234
235 /* Get pattern offset */
236 token = strsep(&sptr, " ");
237
238 /* Delete pattern if no further argument */
239 if (!token) {
240 hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx);
241
242 return count;
243 }
244
245 if (kstrtou8(token, 0, &pattern_offset))
246 return -EINVAL;
247
248 /* Get pattern */
249 token = strsep(&sptr, " ");
250 if (!token)
251 return -EINVAL;
252
253 pattern_buf = token;
254
255 /* Get pattern mask */
256 token = strsep(&sptr, " ");
257 if (!token)
258 return -EINVAL;
259
260 pattern_mask = token;
261 pattern_mask[strlen(pattern_mask) - 1] = '\0';
262
263 hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset,
264 pattern_buf, pattern_mask);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530265 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 return count;
267}
268
269/**
270 * wcnss_wowpattern_write() - SSR wrapper for __wcnss_wowpattern_write
271 * @file: file pointer
272 * @buf: buffer
273 * @count: count
274 * @ppos: position pointer
275 *
276 * Return: 0 on success, error number otherwise
277 */
278static ssize_t wcnss_wowpattern_write(struct file *file,
279 const char __user *buf,
280 size_t count, loff_t *ppos)
281{
282 ssize_t ret;
283
284 cds_ssr_protect(__func__);
285 ret = __wcnss_wowpattern_write(file, buf, count, ppos);
286 cds_ssr_unprotect(__func__);
287
288 return ret;
289}
290
291/**
292 * wcnss_patterngen_write() - pattern_gen debugfs handler
293 * @file: debugfs file handle
294 * @buf: text being written to the debugfs
295 * @count: size of @buf
296 * @ppos: (unused) offset into the virtual file system
297 *
298 * Return: number of bytes processed
299 */
300static ssize_t __wcnss_patterngen_write(struct file *file,
301 const char __user *buf, size_t count,
302 loff_t *ppos)
303{
304 hdd_adapter_t *pAdapter;
305 hdd_context_t *pHddCtx;
306 tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams;
307 tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams;
308
309 char *cmd, *sptr, *token;
310 uint8_t pattern_idx = 0;
311 uint8_t pattern_duration = 0;
312 char *pattern_buf;
313 uint16_t pattern_len = 0;
314 uint16_t i = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530315 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316 int ret;
317
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530318 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319
320 pAdapter = (hdd_adapter_t *)file->private_data;
321 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700322 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323
324 return -EINVAL;
325 }
326
327 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
328 ret = wlan_hdd_validate_context(pHddCtx);
329 if (0 != ret)
330 return ret;
331
332 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700333 hdd_err("Periodic Tx Pattern Offload feature is not supported in firmware!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334 return -EINVAL;
335 }
336
337 /* Get command from user */
338 if (count <= MAX_USER_COMMAND_SIZE_FRAME)
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530339 cmd = qdf_mem_malloc(count + 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 else {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700341 hdd_err("Command length is larger than %d bytes.",
342 MAX_USER_COMMAND_SIZE_FRAME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343
344 return -EINVAL;
345 }
346
347 if (!cmd) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700348 hdd_err("Memory allocation for cmd failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800349 return -ENOMEM;
350 }
351
352 if (copy_from_user(cmd, buf, count)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530353 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354 return -EFAULT;
355 }
356 cmd[count] = '\0';
357 sptr = cmd;
358
359 /* Get pattern idx */
360 token = strsep(&sptr, " ");
361 if (!token)
362 goto failure;
363 if (kstrtou8(token, 0, &pattern_idx))
364 goto failure;
365
366 if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700367 hdd_err("Pattern index %d is not in the range (0 ~ %d).",
368 pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369
370 goto failure;
371 }
372
373 /* Get pattern duration */
374 token = strsep(&sptr, " ");
375 if (!token)
376 goto failure;
377 if (kstrtou8(token, 0, &pattern_duration))
378 goto failure;
379
380 /* Delete pattern using index if duration is 0 */
381 if (!pattern_duration) {
382 delPeriodicTxPtrnParams =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530383 qdf_mem_malloc(sizeof(tSirDelPeriodicTxPtrn));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 if (!delPeriodicTxPtrnParams) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700385 hdd_err("Memory allocation failed!");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530386 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return -ENOMEM;
388 }
389 delPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
390 delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530391 qdf_copy_macaddr(&delPeriodicTxPtrnParams->mac_address,
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -0800392 &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393
394 /* Delete pattern */
395 status = sme_del_periodic_tx_ptrn(pHddCtx->hHal,
396 delPeriodicTxPtrnParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530397 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700398 hdd_err("sme_del_periodic_tx_ptrn() failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800399
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530400 qdf_mem_free(delPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 goto failure;
402 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530403 qdf_mem_free(cmd);
404 qdf_mem_free(delPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 return count;
406 }
407
408 /*
409 * In SAP mode allow configuration without any connection check
410 * In STA mode check if it's in connected state before adding
411 * patterns
412 */
413 hdd_info("device mode %d", pAdapter->device_mode);
Krunal Sonibe766b02016-03-10 13:00:44 -0800414 if ((QDF_STA_MODE == pAdapter->device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700416 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 goto failure;
418 }
419
420 /* Get pattern */
421 token = strsep(&sptr, " ");
422 if (!token)
423 goto failure;
424
425 pattern_buf = token;
426 pattern_buf[strlen(pattern_buf) - 1] = '\0';
427 pattern_len = strlen(pattern_buf);
428
429 /* Since the pattern is a hex string, 2 characters represent 1 byte. */
430 if (pattern_len % 2) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700431 hdd_err("Malformed pattern!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432
433 goto failure;
434 } else
435 pattern_len >>= 1;
436
437 if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700438 hdd_err("Not an 802.3 frame!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439
440 goto failure;
441 }
442
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530443 addPeriodicTxPtrnParams = qdf_mem_malloc(sizeof(tSirAddPeriodicTxPtrn));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800444 if (!addPeriodicTxPtrnParams) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700445 hdd_err("Memory allocation failed!");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530446 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800447 return -ENOMEM;
448 }
449
450 addPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
451 addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500;
452 addPeriodicTxPtrnParams->ucPtrnSize = pattern_len;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530453 qdf_copy_macaddr(&addPeriodicTxPtrnParams->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -0800454 &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800455
456 /* Extract the pattern */
457 for (i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) {
458 addPeriodicTxPtrnParams->ucPattern[i] =
459 (hex_to_bin(pattern_buf[0]) << 4) +
460 hex_to_bin(pattern_buf[1]);
461
462 /* Skip to next byte */
463 pattern_buf += 2;
464 }
465
466 /* Add pattern */
467 status = sme_add_periodic_tx_ptrn(pHddCtx->hHal,
468 addPeriodicTxPtrnParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530469 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700470 hdd_err("sme_add_periodic_tx_ptrn() failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530472 qdf_mem_free(addPeriodicTxPtrnParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 goto failure;
474 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530475 qdf_mem_free(cmd);
476 qdf_mem_free(addPeriodicTxPtrnParams);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530477 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 return count;
479
480failure:
Rajeev Kumarb08f39c2016-02-04 17:50:54 -0800481 hdd_err("Invalid input. Input format is: ptrn_idx duration pattern");
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530482 qdf_mem_free(cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 return -EINVAL;
484}
485
486/**
487 * wcnss_patterngen_write() - SSR wrapper for __wcnss_patterngen_write
488 * @file: file pointer
489 * @buf: buffer
490 * @count: count
491 * @ppos: position pointer
492 *
493 * Return: 0 on success, error number otherwise
494 */
495static ssize_t wcnss_patterngen_write(struct file *file,
496 const char __user *buf,
497 size_t count, loff_t *ppos)
498{
499 ssize_t ret;
500
501 cds_ssr_protect(__func__);
502 ret = __wcnss_patterngen_write(file, buf, count, ppos);
503 cds_ssr_unprotect(__func__);
504
505 return ret;
506}
507
508/**
509 * __wcnss_debugfs_open() - Generic debugfs open() handler
510 * @inode: inode of the debugfs file
511 * @file: file handle of the debugfs file
512 *
513 * Return: 0
514 */
515static int __wcnss_debugfs_open(struct inode *inode, struct file *file)
516{
517 hdd_adapter_t *adapter;
518 hdd_context_t *hdd_ctx;
519 int ret;
520
521 ENTER();
522
523 if (inode->i_private)
524 file->private_data = inode->i_private;
525
526 adapter = (hdd_adapter_t *)file->private_data;
527 if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
Jeff Johnson85c0abf2016-08-05 12:28:24 -0700528 hdd_alert("Invalid adapter or adapter has invalid magic.");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 return -EINVAL;
530 }
531
532 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
533 ret = wlan_hdd_validate_context(hdd_ctx);
534 if (0 != ret)
535 return ret;
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530536 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 return 0;
538}
539
540/**
541 * wcnss_debugfs_open() - SSR wrapper for __wcnss_debugfs_open
542 * @inode: inode pointer
543 * @file: file pointer
544 *
545 * Return: 0 on success, error number otherwise
546 */
547static int wcnss_debugfs_open(struct inode *inode, struct file *file)
548{
549 int ret;
550
551 cds_ssr_protect(__func__);
552 ret = __wcnss_debugfs_open(inode, file);
553 cds_ssr_unprotect(__func__);
554
555 return ret;
556}
557
558static const struct file_operations fops_wowenable = {
559 .write = wcnss_wowenable_write,
560 .open = wcnss_debugfs_open,
561 .owner = THIS_MODULE,
562 .llseek = default_llseek,
563};
564
565static const struct file_operations fops_wowpattern = {
566 .write = wcnss_wowpattern_write,
567 .open = wcnss_debugfs_open,
568 .owner = THIS_MODULE,
569 .llseek = default_llseek,
570};
571
572static const struct file_operations fops_patterngen = {
573 .write = wcnss_patterngen_write,
574 .open = wcnss_debugfs_open,
575 .owner = THIS_MODULE,
576 .llseek = default_llseek,
577};
578
579/**
580 * hdd_debugfs_init() - Initialize debugfs interface
Rajeev Kumardca5f812016-02-04 17:28:06 -0800581 * @adapter: interface adapter pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 *
583 * Register support for the debugfs files supported by the driver.
584 *
585 * NB: The current implementation only supports debugfs operations
586 * on the primary interface, i.e. wlan0
587 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530588 * Return: QDF_STATUS_SUCCESS if all files registered,
589 * QDF_STATUS_E_FAILURE on failure
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 */
Rajeev Kumardca5f812016-02-04 17:28:06 -0800591QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592{
Rajeev Kumardca5f812016-02-04 17:28:06 -0800593 struct net_device *dev = adapter->dev;
594 adapter->debugfs_phy = debugfs_create_dir(dev->name, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595
Rajeev Kumardca5f812016-02-04 17:28:06 -0800596 if (NULL == adapter->debugfs_phy)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530597 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598
599 if (NULL == debugfs_create_file("wow_enable", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800600 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 &fops_wowenable))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603
604 if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800605 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 &fops_wowpattern))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530607 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608
609 if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR,
Rajeev Kumardca5f812016-02-04 17:28:06 -0800610 adapter->debugfs_phy, adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 &fops_patterngen))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530612 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530614 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615}
616
617/**
618 * hdd_debugfs_exit() - Shutdown debugfs interface
Rajeev Kumardca5f812016-02-04 17:28:06 -0800619 * @adapter: interface adapter pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 *
621 * Unregister support for the debugfs files supported by the driver.
622 *
623 * Return: None
624 */
Rajeev Kumardca5f812016-02-04 17:28:06 -0800625void hdd_debugfs_exit(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626{
Rajeev Kumardca5f812016-02-04 17:28:06 -0800627 struct net_device *dev = adapter->dev;
628
629 if (adapter->debugfs_phy)
630 debugfs_remove_recursive(adapter->debugfs_phy);
631 else
632 hdd_info("Interface %s has no debugfs entry", dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633}
634#endif /* #ifdef WLAN_OPEN_SOURCE */