blob: c7eeb578cd1699ec8653530bfb4ffcfb8ffa995d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -07002 * Copyright (c) 2013-2017 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 * @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
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053060static void hdd_wowl_callback(void *pContext, QDF_STATUS qdf_ret_status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080061{
Rajeev Kumar8ce712f2016-05-19 15:03:45 -070062 hdd_info("Return code = (%d)", qdf_ret_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063}
64
65#ifdef WLAN_WAKEUP_EVENTS
66static void hdd_wowl_wake_indication_callback(void *pContext,
67 tpSirWakeReasonInd wake_reason_ind)
68{
Rajeev Kumar8ce712f2016-05-19 15:03:45 -070069 hdd_info("Wake Reason %d", wake_reason_ind->ulReason);
Jeff Johnson0c751e22017-08-29 14:15:25 -070070 hdd_exit_wowl((struct hdd_adapter *) pContext);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071}
72#endif
73
74/**
75 * dump_hdd_wowl_ptrn() - log wow patterns
76 * @ptrn: pointer to wow pattern
77 *
78 * Return: none
79 */
80static void dump_hdd_wowl_ptrn(struct wow_add_pattern *ptrn)
81{
82 int i;
83
Rajeev Kumar8ce712f2016-05-19 15:03:45 -070084 hdd_info("Pattern Id = 0x%x", ptrn->pattern_id);
85 hdd_info("Pattern Byte Offset = 0x%x", ptrn->pattern_byte_offset);
86 hdd_info("Pattern_size = 0x%x", ptrn->pattern_size);
87 hdd_info("Pattern_mask_size = 0x%x", ptrn->pattern_mask_size);
88 hdd_info("Pattern: ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089 for (i = 0; i < ptrn->pattern_size; i++)
Rajeev Kumar8ce712f2016-05-19 15:03:45 -070090 hdd_info(" %02X", ptrn->pattern[i]);
91 hdd_info("pattern_mask: ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092 for (i = 0; i < ptrn->pattern_mask_size; i++)
Rajeev Kumar8ce712f2016-05-19 15:03:45 -070093 hdd_info("%02X", ptrn->pattern_mask[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094}
95
96/**
97 * hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be
98 * used when PBM filtering is enabled
99 * @pAdapter: pointer to the adapter
100 * @ptrn: pointer to the pattern string to be added
101 *
102 * Return: false if any errors encountered, true otherwise
103 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700104bool hdd_add_wowl_ptrn(struct hdd_adapter *pAdapter, const char *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105{
106 struct wow_add_pattern localPattern;
107 int i, first_empty_slot, len, offset;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530108 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109 const char *temp;
110 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
111 uint8_t sessionId = pAdapter->sessionId;
Jeff Johnsonc1ad7412017-08-28 11:34:08 -0700112 struct hdd_context *pHddCtx = pAdapter->pHddCtx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113
114 len = find_ptrn_len(ptrn);
115
116 /* There has to have at least 1 byte for each field (pattern
117 * size, mask size, pattern, mask) e.g. PP:QQ:RR:SS ==> 11
118 * chars
119 */
120 while (len >= 11) {
121 /* Detect duplicate pattern */
122 for (i = 0; i < pHddCtx->config->maxWoWFilters; i++) {
123 if (g_hdd_wowl_ptrns[i] == NULL)
124 continue;
125
126 if (!memcmp(ptrn, g_hdd_wowl_ptrns[i], len)) {
127 /* Pattern Already configured, skip to
128 * next pattern
129 */
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700130 hdd_err("Trying to add duplicate WoWL pattern. Skip it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 ptrn += len;
132 goto next_ptrn;
133 }
134 }
135
136 first_empty_slot = -1;
137
138 /* Find an empty slot to store the pattern */
139 for (i = 0; i < pHddCtx->config->maxWoWFilters; i++) {
140 if (g_hdd_wowl_ptrns[i] == NULL) {
141 first_empty_slot = i;
142 break;
143 }
144 }
145
146 /* Maximum number of patterns have been configured already */
147 if (first_empty_slot == -1) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700148 hdd_err("Cannot add anymore patterns. No free slot!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 return false;
150 }
151 /* Validate the pattern */
152 if (ptrn[2] != WOWL_INTRA_PTRN_TOKENIZER ||
153 ptrn[5] != WOWL_INTRA_PTRN_TOKENIZER) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700154 hdd_err("Malformed pattern string. Skip!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155 ptrn += len;
156 goto next_ptrn;
157 }
158 /* Extract the pattern size */
159 localPattern.pattern_size =
160 (hex_to_bin(ptrn[0]) * 0x10) +
161 hex_to_bin(ptrn[1]);
162
163 /* Extract the pattern mask size */
164 localPattern.pattern_mask_size =
165 (hex_to_bin(ptrn[3]) * 0x10) +
166 hex_to_bin(ptrn[4]);
167
168 if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE
169 || localPattern.pattern_mask_size >
170 WOWL_PTRN_MASK_MAX_SIZE) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700171 hdd_err("Invalid length specified. Skip!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 ptrn += len;
173 goto next_ptrn;
174 }
175 /* compute the offset of tokenizer after the pattern */
176 offset = 5 + 2 * localPattern.pattern_size + 1;
177 if ((offset >= len) ||
178 (ptrn[offset] != WOWL_INTRA_PTRN_TOKENIZER)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700179 hdd_err("Malformed pattern string..skip!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 ptrn += len;
181 goto next_ptrn;
182 }
183 /* compute the end of pattern sring */
184 offset = offset + 2 * localPattern.pattern_mask_size;
185 if (offset + 1 != len) {
186 /* offset begins with 0 */
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700187 hdd_err("Malformed pattern string...skip!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 ptrn += len;
189 goto next_ptrn;
190 }
191
192 temp = ptrn;
193
194 /* Now advance to where pattern begins */
195 ptrn += 6;
196
197 /* Extract the pattern */
198 for (i = 0; i < localPattern.pattern_size; i++) {
199 localPattern.pattern[i] =
200 (hex_to_bin(ptrn[0]) * 0x10) +
201 hex_to_bin(ptrn[1]);
202 ptrn += 2; /* skip to next byte */
203 }
204
205 /* Skip over the ':' seperator after the pattern */
206 ptrn++;
207
208 /* Extract the pattern Mask */
209 for (i = 0; i < localPattern.pattern_mask_size; i++) {
210 localPattern.pattern_mask[i] =
211 (hex_to_bin(ptrn[0]) * 0x10) +
212 hex_to_bin(ptrn[1]);
213 ptrn += 2; /* skip to next byte */
214 }
215
216 /* All is good. Store the pattern locally */
217 g_hdd_wowl_ptrns[first_empty_slot] =
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -0700218 qdf_mem_malloc(len + 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 if (g_hdd_wowl_ptrns[first_empty_slot] == NULL) {
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -0700220 hdd_err("memory allocation failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221 return false;
222 }
223
224 memcpy(g_hdd_wowl_ptrns[first_empty_slot], temp, len);
225 g_hdd_wowl_ptrns[first_empty_slot][len] = '\0';
226 localPattern.pattern_id = first_empty_slot;
227 localPattern.pattern_byte_offset = 0;
228 localPattern.session_id = sessionId;
229
230 /* Register the pattern downstream */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530231 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 sme_wow_add_pattern(hHal, &localPattern,
233 sessionId);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530234 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 /* Add failed, so invalidate the local storage */
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700236 hdd_err("sme_wowl_add_bcast_pattern failed with error code (%d)",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530237 qdf_ret_status);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -0700238 qdf_mem_free(g_hdd_wowl_ptrns[first_empty_slot]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 g_hdd_wowl_ptrns[first_empty_slot] = NULL;
240 }
241
242 dump_hdd_wowl_ptrn(&localPattern);
243
244next_ptrn:
245 if (*ptrn == WOWL_INTER_PTRN_TOKENIZER) {
246 /* move past the tokenizer */
247 ptrn += 1;
248 len = find_ptrn_len(ptrn);
249 continue;
250 } else
251 break;
252 }
253
254 return true;
255}
256
257/**
258 * hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern
259 * @pAdapter: pointer to the adapter
260 * @ptrn: pointer to the pattern string to be removed
261 *
262 * Return: false if any errors encountered, true otherwise
263 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700264bool hdd_del_wowl_ptrn(struct hdd_adapter *pAdapter, const char *ptrn)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265{
266 struct wow_delete_pattern delPattern;
267 unsigned char id;
268 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
269 bool patternFound = false;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530270 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 uint8_t sessionId = pAdapter->sessionId;
Jeff Johnsonc1ad7412017-08-28 11:34:08 -0700272 struct hdd_context *pHddCtx = pAdapter->pHddCtx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273
274 /* Detect pattern */
275 for (id = 0;
276 id < pHddCtx->config->maxWoWFilters
277 && g_hdd_wowl_ptrns[id] != NULL; id++) {
278 if (!strcmp(ptrn, g_hdd_wowl_ptrns[id])) {
279 patternFound = true;
280 break;
281 }
282 }
283
284 /* If pattern present, remove it from downstream */
285 if (patternFound) {
286 delPattern.pattern_id = id;
287 delPattern.session_id = sessionId;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530288 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 sme_wow_delete_pattern(hHal, &delPattern,
290 sessionId);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530291 if (QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 /* Remove from local storage as well */
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700293 hdd_err("Deleted pattern with id %d [%s]", id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 g_hdd_wowl_ptrns[id]);
295
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -0700296 qdf_mem_free(g_hdd_wowl_ptrns[id]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 g_hdd_wowl_ptrns[id] = NULL;
298 return true;
299 }
300 }
301 return false;
302}
303
304/**
305 * hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern
306 * sent from debugfs interface
307 * @pAdapter: pointer to the adapter
308 * @pattern_idx: index of the pattern to be added
309 * @pattern_offset: offset of the pattern in the frame payload
310 * @pattern_buf: pointer to the pattern hex string to be added
311 * @pattern_mask: pointer to the pattern mask hex string
312 *
313 * Return: false if any errors encountered, true otherwise
314 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700315bool hdd_add_wowl_ptrn_debugfs(struct hdd_adapter *pAdapter, uint8_t pattern_idx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316 uint8_t pattern_offset, char *pattern_buf,
317 char *pattern_mask)
318{
319 struct wow_add_pattern localPattern;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530320 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
322 uint8_t session_id = pAdapter->sessionId;
323 uint16_t pattern_len, mask_len, i;
324
325 if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700326 hdd_err("WoW pattern index %d is out of range (0 ~ %d)",
327 pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328
329 return false;
330 }
331
332 pattern_len = strlen(pattern_buf);
333
334 /* Since the pattern is a hex string, 2 characters represent 1 byte. */
335 if (pattern_len % 2) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700336 hdd_err("Malformed WoW pattern!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800337
338 return false;
Jeff Johnson68755312017-02-10 11:46:55 -0800339 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340
Jeff Johnson68755312017-02-10 11:46:55 -0800341 pattern_len >>= 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342 if (!pattern_len || pattern_len > WOWL_PTRN_MAX_SIZE) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700343 hdd_err("WoW pattern length %d is out of range (1 ~ %d).",
344 pattern_len, WOWL_PTRN_MAX_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345
346 return false;
347 }
348
349 localPattern.pattern_id = pattern_idx;
350 localPattern.pattern_byte_offset = pattern_offset;
351 localPattern.pattern_size = pattern_len;
352 localPattern.session_id = session_id;
353
354 if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700355 hdd_err("WoW pattern size (%d) greater than max (%d)",
356 localPattern.pattern_size,
357 SIR_WOWL_BCAST_PATTERN_MAX_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358 return false;
359 }
360 /* Extract the pattern */
361 for (i = 0; i < localPattern.pattern_size; i++) {
362 localPattern.pattern[i] =
363 (hex_to_bin(pattern_buf[0]) << 4) +
364 hex_to_bin(pattern_buf[1]);
365
366 /* Skip to next byte */
367 pattern_buf += 2;
368 }
369
370 /* Get pattern mask size by pattern length */
371 localPattern.pattern_mask_size = pattern_len >> 3;
372 if (pattern_len % 8)
373 localPattern.pattern_mask_size += 1;
374
375 mask_len = strlen(pattern_mask);
376 if ((mask_len % 2)
377 || (localPattern.pattern_mask_size != (mask_len >> 1))) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700378 hdd_err("Malformed WoW pattern mask!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379
380 return false;
381 }
382 if (localPattern.pattern_mask_size > WOWL_PTRN_MASK_MAX_SIZE) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700383 hdd_err("WoW pattern mask size (%d) greater than max (%d)",
384 localPattern.pattern_mask_size,
385 WOWL_PTRN_MASK_MAX_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 return false;
387 }
388 /* Extract the pattern mask */
389 for (i = 0; i < localPattern.pattern_mask_size; i++) {
390 localPattern.pattern_mask[i] =
391 (hex_to_bin(pattern_mask[0]) << 4) +
392 hex_to_bin(pattern_mask[1]);
393
394 /* Skip to next byte */
395 pattern_mask += 2;
396 }
397
398 /* Register the pattern downstream */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530399 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 sme_wow_add_pattern(hHal, &localPattern, session_id);
401
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530402 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700403 hdd_err("sme_wowl_add_bcast_pattern failed with error code (%d).",
404 qdf_ret_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405
406 return false;
407 }
408
409 /* All is good. */
410 if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) {
411 g_hdd_wowl_ptrns_debugfs[pattern_idx] = 1;
412 g_hdd_wowl_ptrns_count++;
413 }
414
415 dump_hdd_wowl_ptrn(&localPattern);
416
417 return true;
418}
419
420/**
421 * hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern
422 * sent from debugfs interface
423 * @pAdapter: pointer to the adapter
424 * @pattern_idx: index of the pattern to be removed
425 *
426 * Return: false if any errors encountered, true otherwise
427 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700428bool hdd_del_wowl_ptrn_debugfs(struct hdd_adapter *pAdapter, uint8_t pattern_idx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429{
430 struct wow_delete_pattern delPattern;
431 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530432 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 uint8_t sessionId = pAdapter->sessionId;
434
435 if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700436 hdd_err("WoW pattern index %d is not in the range (0 ~ %d).",
437 pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438
439 return false;
440 }
441
442 if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700443 hdd_err("WoW pattern %d is not in the table.",
444 pattern_idx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800445
446 return false;
447 }
448
449 delPattern.pattern_id = pattern_idx;
450 delPattern.session_id = sessionId;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530451 qdf_ret_status = sme_wow_delete_pattern(hHal, &delPattern,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800452 sessionId);
453
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530454 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700455 hdd_err("sme_wowl_del_bcast_pattern failed with error code (%d).",
456 qdf_ret_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457
458 return false;
459 }
460
461 g_hdd_wowl_ptrns_debugfs[pattern_idx] = 0;
462 g_hdd_wowl_ptrns_count--;
463
464 return true;
465}
466
467/**
468 * hdd_enter_wowl() - Function which will enable WoWL. At least one
469 * of MP and PBM must be enabled
470 * @pAdapter: pointer to the adapter
471 * @enable_mp: Whether to enable magic packet WoWL mode
472 * @enable_pbm: Whether to enable pattern byte matching WoWL mode
473 *
474 * Return: false if any errors encountered, true otherwise
475 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700476bool hdd_enter_wowl(struct hdd_adapter *pAdapter, bool enable_mp, bool enable_pbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477{
478 tSirSmeWowlEnterParams wowParams;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530479 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
481
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530482 qdf_mem_zero(&wowParams, sizeof(tSirSmeWowlEnterParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483
484 wowParams.ucPatternFilteringEnable = enable_pbm;
485 wowParams.ucMagicPktEnable = enable_mp;
486 wowParams.sessionId = pAdapter->sessionId;
487 if (enable_mp) {
Anurag Chouhanc5548422016-02-24 18:33:27 +0530488 qdf_copy_macaddr(&wowParams.magic_ptrn,
Srinivas Girigowdaca40f982015-11-25 12:31:44 -0800489 &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490 }
491#ifdef WLAN_WAKEUP_EVENTS
492 wowParams.ucWoWEAPIDRequestEnable = true;
493 wowParams.ucWoWEAPOL4WayEnable = true;
494 wowParams.ucWowNetScanOffloadMatch = true;
495 wowParams.ucWowGTKRekeyError = true;
496 wowParams.ucWoWBSSConnLoss = true;
497#endif /* WLAN_WAKEUP_EVENTS */
498
Srinivas Girigowdaca40f982015-11-25 12:31:44 -0800499 /* Request to put FW into WoWL */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530500 qdf_ret_status = sme_enter_wowl(hHal, hdd_wowl_callback, pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501#ifdef WLAN_WAKEUP_EVENTS
502 hdd_wowl_wake_indication_callback,
503 pAdapter,
504#endif /* WLAN_WAKEUP_EVENTS */
505 &wowParams, pAdapter->sessionId);
506
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530507 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
508 if (QDF_STATUS_PMC_PENDING != qdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800509 /* We failed to enter WoWL */
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700510 hdd_err("sme_enter_wowl failed with error code (%d)",
511 qdf_ret_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 return false;
513 }
514 }
515 return true;
516}
517
518/**
519 * hdd_exit_wowl() - Function which will disable WoWL
520 * @pAdapter: pointer to the adapter
521 *
522 * Return: false if any errors encountered, true otherwise
523 */
Jeff Johnson0c751e22017-08-29 14:15:25 -0700524bool hdd_exit_wowl(struct hdd_adapter *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525{
526 tSirSmeWowlExitParams wowParams;
527 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529
530 wowParams.sessionId = pAdapter->sessionId;
531
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530532 qdf_ret_status = sme_exit_wowl(hHal, &wowParams);
533 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Rajeev Kumar8ce712f2016-05-19 15:03:45 -0700534 hdd_err("sme_exit_wowl failed with error code (%d)",
535 qdf_ret_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 return false;
537 }
538
539 return true;
540}
541
Dustin Brownedce4a52017-05-10 11:59:15 -0700542void hdd_deinit_wowl(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543{
Dustin Brownedce4a52017-05-10 11:59:15 -0700544 int i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545
Dustin Brownedce4a52017-05-10 11:59:15 -0700546 for (i = 0; i < WOWL_MAX_PTRNS_ALLOWED; ++i) {
547 if (g_hdd_wowl_ptrns[i]) {
548 qdf_mem_free(g_hdd_wowl_ptrns[i]);
549 g_hdd_wowl_ptrns[i] = NULL;
550 }
551 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552}