blob: 1c2ff5789ae70bc31793ace7349bda494483d5e5 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
3 *
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 * @file wlan_hdd_wowl.c
30 *
31 * @brief wake up on WLAN API file
32 */
33
34/* Include Files */
35
36#include <wlan_hdd_includes.h>
37#include <wlan_hdd_wowl.h>
38
39/* Preprocessor Definitions and Constants */
40#define WOWL_INTER_PTRN_TOKENIZER ';'
41#define WOWL_INTRA_PTRN_TOKENIZER ':'
42
43/* Type Declarations */
44
45static char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED];
46static bool g_hdd_wowl_ptrns_debugfs[WOWL_MAX_PTRNS_ALLOWED] = { 0 };
47
48static uint8_t g_hdd_wowl_ptrns_count;
49
50static inline int find_ptrn_len(const char *ptrn)
51{
52 int len = 0;
53 while (*ptrn != '\0' && *ptrn != WOWL_INTER_PTRN_TOKENIZER) {
54 len++;
55 ptrn++;
56 }
57 return len;
58}
59
60static void hdd_wowl_callback(void *pContext, CDF_STATUS cdf_ret_status)
61{
62 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
63 "%s: Return code = (%d)", __func__, cdf_ret_status);
64}
65
66#ifdef WLAN_WAKEUP_EVENTS
67static void hdd_wowl_wake_indication_callback(void *pContext,
68 tpSirWakeReasonInd wake_reason_ind)
69{
70 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: Wake Reason %d",
71 __func__, wake_reason_ind->ulReason);
72 hdd_exit_wowl((hdd_adapter_t *) pContext);
73}
74#endif
75
76/**
77 * dump_hdd_wowl_ptrn() - log wow patterns
78 * @ptrn: pointer to wow pattern
79 *
80 * Return: none
81 */
82static void dump_hdd_wowl_ptrn(struct wow_add_pattern *ptrn)
83{
84 int i;
85
86 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
87 "%s: Patetrn Id = 0x%x", __func__, ptrn->pattern_id);
88 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
89 "%s: Pattern Byte Offset = 0x%x", __func__,
90 ptrn->pattern_byte_offset);
91 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
92 "%s: pattern_size = 0x%x", __func__, ptrn->pattern_size);
93 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
94 "%s: pattern_mask_size = 0x%x", __func__,
95 ptrn->pattern_mask_size);
96 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: Pattern: ",
97 __func__);
98 for (i = 0; i < ptrn->pattern_size; i++)
99 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, " %02X",
100 ptrn->pattern[i]);
101 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: pattern_mask: ",
102 __func__);
103 for (i = 0; i < ptrn->pattern_mask_size; i++)
104 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%02X",
105 ptrn->pattern_mask[i]);
106}
107
108/**
109 * hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be
110 * used when PBM filtering is enabled
111 * @pAdapter: pointer to the adapter
112 * @ptrn: pointer to the pattern string to be added
113 *
114 * Return: false if any errors encountered, true otherwise
115 */
116bool hdd_add_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn)
117{
118 struct wow_add_pattern localPattern;
119 int i, first_empty_slot, len, offset;
120 CDF_STATUS cdf_ret_status;
121 const char *temp;
122 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
123 uint8_t sessionId = pAdapter->sessionId;
124 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
125
126 len = find_ptrn_len(ptrn);
127
128 /* There has to have at least 1 byte for each field (pattern
129 * size, mask size, pattern, mask) e.g. PP:QQ:RR:SS ==> 11
130 * chars
131 */
132 while (len >= 11) {
133 /* Detect duplicate pattern */
134 for (i = 0; i < pHddCtx->config->maxWoWFilters; i++) {
135 if (g_hdd_wowl_ptrns[i] == NULL)
136 continue;
137
138 if (!memcmp(ptrn, g_hdd_wowl_ptrns[i], len)) {
139 /* Pattern Already configured, skip to
140 * next pattern
141 */
142 CDF_TRACE(CDF_MODULE_ID_HDD,
143 CDF_TRACE_LEVEL_ERROR,
144 "Trying to add duplicate WoWL pattern. Skip it!");
145 ptrn += len;
146 goto next_ptrn;
147 }
148 }
149
150 first_empty_slot = -1;
151
152 /* Find an empty slot to store the pattern */
153 for (i = 0; i < pHddCtx->config->maxWoWFilters; i++) {
154 if (g_hdd_wowl_ptrns[i] == NULL) {
155 first_empty_slot = i;
156 break;
157 }
158 }
159
160 /* Maximum number of patterns have been configured already */
161 if (first_empty_slot == -1) {
162 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
163 "%s: Cannot add anymore patterns. No free slot!",
164 __func__);
165 return false;
166 }
167 /* Validate the pattern */
168 if (ptrn[2] != WOWL_INTRA_PTRN_TOKENIZER ||
169 ptrn[5] != WOWL_INTRA_PTRN_TOKENIZER) {
170 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
171 "%s: Malformed pattern string. Skip!",
172 __func__);
173 ptrn += len;
174 goto next_ptrn;
175 }
176 /* Extract the pattern size */
177 localPattern.pattern_size =
178 (hex_to_bin(ptrn[0]) * 0x10) +
179 hex_to_bin(ptrn[1]);
180
181 /* Extract the pattern mask size */
182 localPattern.pattern_mask_size =
183 (hex_to_bin(ptrn[3]) * 0x10) +
184 hex_to_bin(ptrn[4]);
185
186 if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE
187 || localPattern.pattern_mask_size >
188 WOWL_PTRN_MASK_MAX_SIZE) {
189 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
190 "%s: Invalid length specified. Skip!",
191 __func__);
192 ptrn += len;
193 goto next_ptrn;
194 }
195 /* compute the offset of tokenizer after the pattern */
196 offset = 5 + 2 * localPattern.pattern_size + 1;
197 if ((offset >= len) ||
198 (ptrn[offset] != WOWL_INTRA_PTRN_TOKENIZER)) {
199 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
200 "%s: Malformed pattern string..skip!",
201 __func__);
202 ptrn += len;
203 goto next_ptrn;
204 }
205 /* compute the end of pattern sring */
206 offset = offset + 2 * localPattern.pattern_mask_size;
207 if (offset + 1 != len) {
208 /* offset begins with 0 */
209 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
210 "%s: Malformed pattern string...skip!",
211 __func__);
212 ptrn += len;
213 goto next_ptrn;
214 }
215
216 temp = ptrn;
217
218 /* Now advance to where pattern begins */
219 ptrn += 6;
220
221 /* Extract the pattern */
222 for (i = 0; i < localPattern.pattern_size; i++) {
223 localPattern.pattern[i] =
224 (hex_to_bin(ptrn[0]) * 0x10) +
225 hex_to_bin(ptrn[1]);
226 ptrn += 2; /* skip to next byte */
227 }
228
229 /* Skip over the ':' seperator after the pattern */
230 ptrn++;
231
232 /* Extract the pattern Mask */
233 for (i = 0; i < localPattern.pattern_mask_size; i++) {
234 localPattern.pattern_mask[i] =
235 (hex_to_bin(ptrn[0]) * 0x10) +
236 hex_to_bin(ptrn[1]);
237 ptrn += 2; /* skip to next byte */
238 }
239
240 /* All is good. Store the pattern locally */
241 g_hdd_wowl_ptrns[first_empty_slot] =
242 kmalloc(len + 1, GFP_KERNEL);
243 if (g_hdd_wowl_ptrns[first_empty_slot] == NULL) {
244 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
245 "%s: kmalloc failure", __func__);
246 return false;
247 }
248
249 memcpy(g_hdd_wowl_ptrns[first_empty_slot], temp, len);
250 g_hdd_wowl_ptrns[first_empty_slot][len] = '\0';
251 localPattern.pattern_id = first_empty_slot;
252 localPattern.pattern_byte_offset = 0;
253 localPattern.session_id = sessionId;
254
255 /* Register the pattern downstream */
256 cdf_ret_status =
257 sme_wow_add_pattern(hHal, &localPattern,
258 sessionId);
259 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
260 /* Add failed, so invalidate the local storage */
261 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
262 "sme_wowl_add_bcast_pattern failed with error code (%d)",
263 cdf_ret_status);
264 kfree(g_hdd_wowl_ptrns[first_empty_slot]);
265 g_hdd_wowl_ptrns[first_empty_slot] = NULL;
266 }
267
268 dump_hdd_wowl_ptrn(&localPattern);
269
270next_ptrn:
271 if (*ptrn == WOWL_INTER_PTRN_TOKENIZER) {
272 /* move past the tokenizer */
273 ptrn += 1;
274 len = find_ptrn_len(ptrn);
275 continue;
276 } else
277 break;
278 }
279
280 return true;
281}
282
283/**
284 * hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern
285 * @pAdapter: pointer to the adapter
286 * @ptrn: pointer to the pattern string to be removed
287 *
288 * Return: false if any errors encountered, true otherwise
289 */
290bool hdd_del_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn)
291{
292 struct wow_delete_pattern delPattern;
293 unsigned char id;
294 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
295 bool patternFound = false;
296 CDF_STATUS cdf_ret_status;
297 uint8_t sessionId = pAdapter->sessionId;
298 hdd_context_t *pHddCtx = pAdapter->pHddCtx;
299
300 /* Detect pattern */
301 for (id = 0;
302 id < pHddCtx->config->maxWoWFilters
303 && g_hdd_wowl_ptrns[id] != NULL; id++) {
304 if (!strcmp(ptrn, g_hdd_wowl_ptrns[id])) {
305 patternFound = true;
306 break;
307 }
308 }
309
310 /* If pattern present, remove it from downstream */
311 if (patternFound) {
312 delPattern.pattern_id = id;
313 delPattern.session_id = sessionId;
314 cdf_ret_status =
315 sme_wow_delete_pattern(hHal, &delPattern,
316 sessionId);
317 if (CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
318 /* Remove from local storage as well */
319 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
320 "Deleted pattern with id %d [%s]", id,
321 g_hdd_wowl_ptrns[id]);
322
323 kfree(g_hdd_wowl_ptrns[id]);
324 g_hdd_wowl_ptrns[id] = NULL;
325 return true;
326 }
327 }
328 return false;
329}
330
331/**
332 * hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern
333 * sent from debugfs interface
334 * @pAdapter: pointer to the adapter
335 * @pattern_idx: index of the pattern to be added
336 * @pattern_offset: offset of the pattern in the frame payload
337 * @pattern_buf: pointer to the pattern hex string to be added
338 * @pattern_mask: pointer to the pattern mask hex string
339 *
340 * Return: false if any errors encountered, true otherwise
341 */
342bool hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx,
343 uint8_t pattern_offset, char *pattern_buf,
344 char *pattern_mask)
345{
346 struct wow_add_pattern localPattern;
347 CDF_STATUS cdf_ret_status;
348 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
349 uint8_t session_id = pAdapter->sessionId;
350 uint16_t pattern_len, mask_len, i;
351
352 if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) {
353 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
354 "%s: WoW pattern index %d is out of range (0 ~ %d).",
355 __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
356
357 return false;
358 }
359
360 pattern_len = strlen(pattern_buf);
361
362 /* Since the pattern is a hex string, 2 characters represent 1 byte. */
363 if (pattern_len % 2) {
364 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
365 "%s: Malformed WoW pattern!", __func__);
366
367 return false;
368 } else
369 pattern_len >>= 1;
370
371 if (!pattern_len || pattern_len > WOWL_PTRN_MAX_SIZE) {
372 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
373 "%s: WoW pattern length %d is out of range (1 ~ %d).",
374 __func__, pattern_len, WOWL_PTRN_MAX_SIZE);
375
376 return false;
377 }
378
379 localPattern.pattern_id = pattern_idx;
380 localPattern.pattern_byte_offset = pattern_offset;
381 localPattern.pattern_size = pattern_len;
382 localPattern.session_id = session_id;
383
384 if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE) {
385 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
386 "%s: WoW pattern size (%d) greater than max (%d)",
387 __func__, localPattern.pattern_size,
388 SIR_WOWL_BCAST_PATTERN_MAX_SIZE);
389 return false;
390 }
391 /* Extract the pattern */
392 for (i = 0; i < localPattern.pattern_size; i++) {
393 localPattern.pattern[i] =
394 (hex_to_bin(pattern_buf[0]) << 4) +
395 hex_to_bin(pattern_buf[1]);
396
397 /* Skip to next byte */
398 pattern_buf += 2;
399 }
400
401 /* Get pattern mask size by pattern length */
402 localPattern.pattern_mask_size = pattern_len >> 3;
403 if (pattern_len % 8)
404 localPattern.pattern_mask_size += 1;
405
406 mask_len = strlen(pattern_mask);
407 if ((mask_len % 2)
408 || (localPattern.pattern_mask_size != (mask_len >> 1))) {
409 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
410 "%s: Malformed WoW pattern mask!", __func__);
411
412 return false;
413 }
414 if (localPattern.pattern_mask_size > WOWL_PTRN_MASK_MAX_SIZE) {
415 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
416 "%s: WoW pattern mask size (%d) greater than max (%d)",
417 __func__, localPattern.pattern_mask_size,
418 WOWL_PTRN_MASK_MAX_SIZE);
419 return false;
420 }
421 /* Extract the pattern mask */
422 for (i = 0; i < localPattern.pattern_mask_size; i++) {
423 localPattern.pattern_mask[i] =
424 (hex_to_bin(pattern_mask[0]) << 4) +
425 hex_to_bin(pattern_mask[1]);
426
427 /* Skip to next byte */
428 pattern_mask += 2;
429 }
430
431 /* Register the pattern downstream */
432 cdf_ret_status =
433 sme_wow_add_pattern(hHal, &localPattern, session_id);
434
435 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
436 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
437 "%s: sme_wowl_add_bcast_pattern failed with error code (%d).",
438 __func__, cdf_ret_status);
439
440 return false;
441 }
442
443 /* All is good. */
444 if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) {
445 g_hdd_wowl_ptrns_debugfs[pattern_idx] = 1;
446 g_hdd_wowl_ptrns_count++;
447 }
448
449 dump_hdd_wowl_ptrn(&localPattern);
450
451 return true;
452}
453
454/**
455 * hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
456 * sent from debugfs interface
457 * @pAdapter: pointer to the adapter
458 * @pattern_idx: index of the pattern to be removed
459 *
460 * Return: false if any errors encountered, true otherwise
461 */
462bool hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx)
463{
464 struct wow_delete_pattern delPattern;
465 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
466 CDF_STATUS cdf_ret_status;
467 uint8_t sessionId = pAdapter->sessionId;
468
469 if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) {
470 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
471 "%s: WoW pattern index %d is not in the range (0 ~ %d).",
472 __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
473
474 return false;
475 }
476
477 if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) {
478 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
479 "%s: WoW pattern %d is not in the table.",
480 __func__, pattern_idx);
481
482 return false;
483 }
484
485 delPattern.pattern_id = pattern_idx;
486 delPattern.session_id = sessionId;
487 cdf_ret_status = sme_wow_delete_pattern(hHal, &delPattern,
488 sessionId);
489
490 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
491 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
492 "%s: sme_wowl_del_bcast_pattern failed with error code (%d).",
493 __func__, cdf_ret_status);
494
495 return false;
496 }
497
498 g_hdd_wowl_ptrns_debugfs[pattern_idx] = 0;
499 g_hdd_wowl_ptrns_count--;
500
501 return true;
502}
503
504/**
505 * hdd_enter_wowl() - Function which will enable WoWL. At least one
506 * of MP and PBM must be enabled
507 * @pAdapter: pointer to the adapter
508 * @enable_mp: Whether to enable magic packet WoWL mode
509 * @enable_pbm: Whether to enable pattern byte matching WoWL mode
510 *
511 * Return: false if any errors encountered, true otherwise
512 */
513bool hdd_enter_wowl(hdd_adapter_t *pAdapter, bool enable_mp, bool enable_pbm)
514{
515 tSirSmeWowlEnterParams wowParams;
516 CDF_STATUS cdf_ret_status;
517 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
518
519 cdf_mem_zero(&wowParams, sizeof(tSirSmeWowlEnterParams));
520
521 wowParams.ucPatternFilteringEnable = enable_pbm;
522 wowParams.ucMagicPktEnable = enable_mp;
523 wowParams.sessionId = pAdapter->sessionId;
524 if (enable_mp) {
525 cdf_copy_macaddr((struct cdf_mac_addr *) &(wowParams.magicPtrn),
526 &(pAdapter->macAddressCurrent));
527 }
528#ifdef WLAN_WAKEUP_EVENTS
529 wowParams.ucWoWEAPIDRequestEnable = true;
530 wowParams.ucWoWEAPOL4WayEnable = true;
531 wowParams.ucWowNetScanOffloadMatch = true;
532 wowParams.ucWowGTKRekeyError = true;
533 wowParams.ucWoWBSSConnLoss = true;
534#endif /* WLAN_WAKEUP_EVENTS */
535
536 /* Request to put Libra into WoWL */
537 cdf_ret_status = sme_enter_wowl(hHal, hdd_wowl_callback, pAdapter,
538#ifdef WLAN_WAKEUP_EVENTS
539 hdd_wowl_wake_indication_callback,
540 pAdapter,
541#endif /* WLAN_WAKEUP_EVENTS */
542 &wowParams, pAdapter->sessionId);
543
544 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
545 if (CDF_STATUS_PMC_PENDING != cdf_ret_status) {
546 /* We failed to enter WoWL */
547 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
548 "sme_enter_wowl failed with error code (%d)",
549 cdf_ret_status);
550 return false;
551 }
552 }
553 return true;
554}
555
556/**
557 * hdd_exit_wowl() - Function which will disable WoWL
558 * @pAdapter: pointer to the adapter
559 *
560 * Return: false if any errors encountered, true otherwise
561 */
562bool hdd_exit_wowl(hdd_adapter_t *pAdapter)
563{
564 tSirSmeWowlExitParams wowParams;
565 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
566 CDF_STATUS cdf_ret_status;
567
568 wowParams.sessionId = pAdapter->sessionId;
569
570 cdf_ret_status = sme_exit_wowl(hHal, &wowParams);
571 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
572 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
573 "sme_exit_wowl failed with error code (%d)",
574 cdf_ret_status);
575 return false;
576 }
577
578 return true;
579}
580
581/**
582 * hdd_init_wowl() - Init function which will initialize the WoWL module
583 * and perform any required initial configuration
584 * @pAdapter: pointer to the adapter
585 *
586 * Return: false if any errors encountered, true otherwise
587 */
588bool hdd_init_wowl(hdd_adapter_t *pAdapter)
589{
590 hdd_context_t *pHddCtx = NULL;
591 pHddCtx = pAdapter->pHddCtx;
592
593 memset(g_hdd_wowl_ptrns, 0, sizeof(g_hdd_wowl_ptrns));
594 g_hdd_wowl_ptrns_count = 0;
595
596 /* Add any statically configured patterns */
597 hdd_add_wowl_ptrn(pAdapter, pHddCtx->config->wowlPattern);
598
599 return true;
600}