1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 /**
20 * DOC: Implements static configuration on vdev attach
21 */
22
23 #include "wlan_pmo_static_config.h"
24 #include "wlan_pmo_tgt_api.h"
25 #include "wlan_pmo_main.h"
26 #include "wlan_pmo_wow.h"
27 #include "wlan_pmo_obj_mgmt_public_struct.h"
28
29 static const uint8_t arp_ptrn[] = {0x08, 0x06};
30 static const uint8_t arp_mask[] = {0xff, 0xff};
31 static const uint8_t ns_ptrn[] = {0x86, 0xDD};
32 static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8};
33 static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
34 static const uint8_t arp_offset = 12;
35
pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev * vdev)36 void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev)
37 {
38 uint32_t event_bitmap[PMO_WOW_MAX_EVENT_BM_LEN] = {0};
39 uint8_t vdev_id;
40 enum QDF_OPMODE vdev_opmode;
41 struct pmo_psoc_priv_obj *psoc_ctx;
42 pmo_is_device_in_low_pwr_mode is_low_pwr_mode;
43 struct pmo_vdev_priv_obj *vdev_ctx;
44
45 vdev_opmode = pmo_get_vdev_opmode(vdev);
46 vdev_id = pmo_vdev_get_id(vdev);
47 pmo_debug("vdev_opmode %d vdev_id %d", vdev_opmode, vdev_id);
48
49 vdev_ctx = pmo_vdev_get_priv(vdev);
50
51 switch (vdev_opmode) {
52 case QDF_STA_MODE:
53 case QDF_P2P_CLIENT_MODE:
54 /* set power on failure event only for STA and P2P_CLI mode*/
55 psoc_ctx = pmo_vdev_get_psoc_priv(vdev);
56 if (psoc_ctx->psoc_cfg.auto_power_save_fail_mode ==
57 PMO_FW_TO_SEND_WOW_IND_ON_PWR_FAILURE){
58 qdf_spin_lock(&psoc_ctx->lock);
59 is_low_pwr_mode = psoc_ctx->is_device_in_low_pwr_mode;
60 qdf_spin_unlock(&psoc_ctx->lock);
61 if (is_low_pwr_mode && is_low_pwr_mode(vdev_id))
62 pmo_set_wow_event_bitmap(
63 WOW_CHIP_POWER_FAILURE_DETECT_EVENT,
64 PMO_WOW_MAX_EVENT_BM_LEN,
65 event_bitmap);
66 }
67
68 fallthrough;
69 case QDF_P2P_DEVICE_MODE:
70 case QDF_OCB_MODE:
71 case QDF_MONITOR_MODE:
72 pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
73 if (vdev_ctx->magic_ptrn_enable)
74 pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT,
75 PMO_WOW_MAX_EVENT_BM_LEN,
76 event_bitmap);
77 break;
78
79 case QDF_IBSS_MODE:
80 pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
81 if (vdev_ctx->magic_ptrn_enable)
82 pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT,
83 PMO_WOW_MAX_EVENT_BM_LEN,
84 event_bitmap);
85 pmo_set_wow_event_bitmap(WOW_BEACON_EVENT,
86 PMO_WOW_MAX_EVENT_BM_LEN,
87 event_bitmap);
88 break;
89
90 case QDF_P2P_GO_MODE:
91 case QDF_SAP_MODE:
92 pmo_set_sap_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
93 break;
94
95 case QDF_NDI_MODE:
96 pmo_set_ndp_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
97 break;
98
99 default:
100 pmo_err("Skipping wake event configuration for vdev_opmode %d",
101 vdev_opmode);
102 return;
103 }
104
105 pmo_tgt_enable_wow_wakeup_event(vdev, event_bitmap);
106 }
107
108 /**
109 * pmo_configure_wow_ap() - set WOW patterns in ap mode
110 * @vdev: objmgr vdev handle
111 *
112 * Configures default WOW pattern for the given vdev_id which is in AP mode.
113 *
114 * Return: QDF status
115 */
pmo_configure_wow_ap(struct wlan_objmgr_vdev * vdev)116 static QDF_STATUS pmo_configure_wow_ap(struct wlan_objmgr_vdev *vdev)
117 {
118 QDF_STATUS ret;
119 uint8_t mac_mask[QDF_MAC_ADDR_SIZE];
120 struct pmo_vdev_priv_obj *vdev_ctx;
121 struct qdf_mac_addr bridgeaddr;
122
123 vdev_ctx = pmo_vdev_get_priv(vdev);
124
125 /*
126 * Setup unicast pkt pattern
127 * WoW pattern id should be unique for each vdev
128 * WoW pattern id can be same on 2 different VDEVs
129 */
130 qdf_mem_set(&mac_mask, QDF_MAC_ADDR_SIZE, 0xFF);
131 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
132 pmo_get_and_increment_wow_default_ptrn(vdev_ctx),
133 wlan_vdev_mlme_get_macaddr(vdev),
134 QDF_MAC_ADDR_SIZE, 0, mac_mask,
135 QDF_MAC_ADDR_SIZE, false);
136 if (ret != QDF_STATUS_SUCCESS) {
137 pmo_err("Failed to add WOW unicast pattern ret %d", ret);
138 return ret;
139 }
140
141 /* Setup Bridge MAC address */
142 pmo_get_vdev_bridge_addr(vdev, &bridgeaddr);
143 if (!qdf_is_macaddr_zero(&bridgeaddr)) {
144 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
145 pmo_get_and_increment_wow_default_ptrn(vdev_ctx),
146 bridgeaddr.bytes, QDF_MAC_ADDR_SIZE, 0, mac_mask,
147 QDF_MAC_ADDR_SIZE, false);
148 if (ret != QDF_STATUS_SUCCESS) {
149 pmo_err("Failed to add Bridge MAC address");
150 return ret;
151 }
152 }
153
154 /* Setup ARP pkt pattern */
155 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
156 pmo_get_and_increment_wow_default_ptrn(vdev_ctx),
157 arp_ptrn, sizeof(arp_ptrn), arp_offset, arp_mask,
158 sizeof(arp_mask), false);
159 if (ret != QDF_STATUS_SUCCESS) {
160 pmo_err("Failed to add WOW ARP pattern");
161 return ret;
162 }
163
164 return ret;
165 }
166
167 /**
168 * pmo_configure_mc_ssdp() - API to configure SSDP address as MC list
169 * @vdev: objmgr vdev handle.
170 *
171 * SSDP address 239.255.255.250 is converted to Multicast Mac address
172 * and configure it to FW. Firmware will apply this pattern on the incoming
173 * packets to filter them out during chatter/wow mode.
174 *
175 * Return: Success/Failure
176 */
pmo_configure_mc_ssdp(struct wlan_objmgr_vdev * vdev)177 static QDF_STATUS pmo_configure_mc_ssdp(
178 struct wlan_objmgr_vdev *vdev)
179 {
180 struct wlan_objmgr_psoc *psoc;
181 const uint8_t ssdp_addr[QDF_MAC_ADDR_SIZE] = {
182 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa };
183 struct qdf_mac_addr multicast_addr;
184 QDF_STATUS status = QDF_STATUS_SUCCESS;
185
186 psoc = pmo_vdev_get_psoc(vdev);
187
188 qdf_mem_copy(&multicast_addr.bytes, &ssdp_addr, QDF_MAC_ADDR_SIZE);
189 status = pmo_tgt_set_mc_filter_req(vdev,
190 multicast_addr);
191 if (status != QDF_STATUS_SUCCESS)
192 pmo_err("unable to set ssdp as mc addr list filter");
193
194 return status;
195 }
196
197 /**
198 * pmo_configure_wow_ssdp() - API to configure WoW SSDP
199 *@vdev: objmgr vdev handle
200 *
201 * API to configure SSDP pattern as WoW pattern
202 *
203 * Return: Success/Failure
204 */
pmo_configure_wow_ssdp(struct wlan_objmgr_vdev * vdev)205 static QDF_STATUS pmo_configure_wow_ssdp(
206 struct wlan_objmgr_vdev *vdev)
207 {
208 QDF_STATUS status = QDF_STATUS_SUCCESS;
209 uint8_t discvr_offset = 30;
210 struct pmo_vdev_priv_obj *vdev_ctx;
211
212 vdev_ctx = pmo_vdev_get_priv(vdev);
213
214 /*
215 * WoW pattern ID should be unique for each vdev
216 * Different WoW patterns can use same pattern ID
217 */
218 status = pmo_tgt_send_wow_patterns_to_fw(vdev,
219 pmo_get_and_increment_wow_default_ptrn(vdev_ctx),
220 discvr_ptrn, sizeof(discvr_ptrn), discvr_offset,
221 discvr_mask, sizeof(discvr_ptrn), false);
222
223 if (status != QDF_STATUS_SUCCESS)
224 pmo_err("Failed to add WOW mDNS/SSDP/LLMNR pattern");
225
226 return status;
227 }
228
229 /**
230 * pmo_configure_ssdp() - API to Configure SSDP pattern to FW
231 *@vdev: objmgr vdev handle
232 *
233 * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR
234 * 224.0.0.252
235 *
236 * Return: Success/Failure.
237 */
pmo_configure_ssdp(struct wlan_objmgr_vdev * vdev)238 static QDF_STATUS pmo_configure_ssdp(struct wlan_objmgr_vdev *vdev)
239 {
240 struct pmo_vdev_priv_obj *vdev_ctx;
241
242 vdev_ctx = pmo_vdev_get_priv(vdev);
243
244 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ssdp) {
245 pmo_debug("mDNS, SSDP, LLMNR patterns are disabled from ini");
246 return QDF_STATUS_SUCCESS;
247 }
248
249 pmo_debug("enable_mc_list:%d",
250 vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list);
251
252 if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list)
253 return pmo_configure_mc_ssdp(vdev);
254
255 return pmo_configure_wow_ssdp(vdev);
256 }
257
258 /**
259 * pmo_configure_wow_sta() - set WOW patterns in sta mode
260 * @vdev: objmgr vdev handle
261 *
262 * Configures default WOW pattern for the given vdev_id which is in sta mode.
263 *
264 * Return: QDF status
265 */
pmo_configure_wow_sta(struct wlan_objmgr_vdev * vdev)266 static QDF_STATUS pmo_configure_wow_sta(struct wlan_objmgr_vdev *vdev)
267 {
268 uint8_t mac_mask[QDF_MAC_ADDR_SIZE];
269 QDF_STATUS ret = QDF_STATUS_SUCCESS;
270 struct pmo_vdev_priv_obj *vdev_ctx;
271 struct qdf_mac_addr *ucast_addr;
272
273 vdev_ctx = pmo_vdev_get_priv(vdev);
274
275 qdf_mem_set(&mac_mask, QDF_MAC_ADDR_SIZE, 0xFF);
276 /*
277 * Set up unicast wow pattern
278 * WoW pattern ID should be unique for each vdev
279 * Different WoW patterns can use same pattern ID
280 */
281
282 /* On ML VDEV, configure WoW pattern with MLD address only */
283 ucast_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
284 if (qdf_is_macaddr_zero(ucast_addr)) {
285 ucast_addr =
286 (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(vdev);
287 }
288
289 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
290 pmo_get_and_increment_wow_default_ptrn(vdev_ctx),
291 (uint8_t *)ucast_addr, QDF_MAC_ADDR_SIZE, 0,
292 mac_mask, QDF_MAC_ADDR_SIZE, false);
293 if (QDF_IS_STATUS_ERROR(ret)) {
294 pmo_err("Failed to add WOW unicast pattern ret %d", ret);
295 return ret;
296 }
297
298 ret = pmo_configure_ssdp(vdev);
299 if (ret != QDF_STATUS_SUCCESS)
300 pmo_err("Failed to configure SSDP patterns to FW");
301
302 /*
303 * when arp offload or ns offloaded is disabled
304 * or active offload is disabled from ini file,
305 * configure broad cast arp pattern to fw, so
306 * that host can wake up
307 */
308 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.arp_offload_enable ||
309 !vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
310 /* Setup all ARP pkt pattern */
311 pmo_debug("ARP offload is disabled in INI enable WoW for ARP");
312 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
313 pmo_get_and_increment_wow_default_ptrn(
314 vdev_ctx),
315 arp_ptrn, sizeof(arp_ptrn), arp_offset,
316 arp_mask, sizeof(arp_mask), false);
317 if (ret != QDF_STATUS_SUCCESS) {
318 pmo_err("Failed to add WOW ARP pattern");
319 return ret;
320 }
321 }
322 /* for NS or NDP offload packets */
323 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_static ||
324 !vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
325 /* Setup all NS pkt pattern */
326 pmo_debug("NS offload is disabled in INI enable WoW for NS");
327 ret = pmo_tgt_send_wow_patterns_to_fw(vdev,
328 pmo_get_and_increment_wow_default_ptrn(
329 vdev_ctx),
330 ns_ptrn, sizeof(arp_ptrn), arp_offset,
331 arp_mask, sizeof(arp_mask), false);
332 if (ret != QDF_STATUS_SUCCESS) {
333 pmo_err("Failed to add WOW NS pattern");
334 return ret;
335 }
336 }
337
338 return ret;
339 }
340
pmo_register_wow_default_patterns(struct wlan_objmgr_vdev * vdev)341 void pmo_register_wow_default_patterns(struct wlan_objmgr_vdev *vdev)
342 {
343 enum QDF_OPMODE vdev_opmode = QDF_MAX_NO_OF_MODE;
344 struct pmo_vdev_priv_obj *vdev_ctx;
345 uint8_t vdev_id;
346 struct pmo_psoc_priv_obj *psoc_ctx;
347
348 vdev_ctx = pmo_vdev_get_priv(vdev);
349
350 vdev_id = pmo_vdev_get_id(vdev);
351 if (vdev_id > WLAN_UMAC_PSOC_MAX_VDEVS) {
352 pmo_err("Invalid vdev id %d", vdev_id);
353 return;
354 }
355
356 vdev_opmode = pmo_get_vdev_opmode(vdev);
357 if (vdev_opmode == QDF_MAX_NO_OF_MODE) {
358 pmo_err("Invalid vdev opmode %d", vdev_id);
359 return;
360 }
361
362 if (!vdev_ctx->ptrn_match_enable) {
363 pmo_err("ptrn_match is disable for vdev %d", vdev_id);
364 return;
365 }
366
367 if (pmo_is_vdev_in_beaconning_mode(vdev_opmode)) {
368 /* Configure SAP/GO/IBSS mode default wow patterns */
369 pmo_debug("Config SAP default wow patterns vdev_id %d",
370 vdev_id);
371 pmo_configure_wow_ap(vdev);
372 } else {
373 /* Configure STA/P2P CLI mode default wow patterns */
374 pmo_debug("Config STA default wow patterns vdev_id %d",
375 vdev_id);
376 pmo_configure_wow_sta(vdev);
377 psoc_ctx = vdev_ctx->pmo_psoc_ctx;
378 if (!psoc_ctx) {
379 pmo_err("PMO PSOC Context is NULL!");
380 return;
381 }
382
383 /*
384 * No need for configuring RA filter while APF is enabled, since
385 * APF internally handles RA filtering.
386 */
387 if (psoc_ctx->psoc_cfg.ra_ratelimit_enable &&
388 !pmo_intersect_apf(psoc_ctx)) {
389 pmo_debug("Config STA RA wow pattern vdev_id %d",
390 vdev_id);
391 pmo_tgt_send_ra_filter_req(vdev);
392 }
393 }
394
395 }
396
397 #ifdef CONFIG_LITHIUM
398 static void
set_action_id_drop_pattern_for_block_ack(uint32_t * action_category_map)399 set_action_id_drop_pattern_for_block_ack(uint32_t *action_category_map)
400 {
401 action_category_map[0] |= 1 << PMO_MAC_ACTION_BLKACK;
402 }
403 #else
404 static inline void
set_action_id_drop_pattern_for_block_ack(uint32_t * action_category_map)405 set_action_id_drop_pattern_for_block_ack(uint32_t *action_category_map)
406 {
407 }
408 #endif
409
410 /**
411 * set_action_id_drop_pattern_for_spec_mgmt() - Set action id of action
412 * frames for spectrum mgmt frames to be dropped in fw.
413 *
414 * @action_id_per_category: Pointer to action id bitmaps.
415 */
set_action_id_drop_pattern_for_spec_mgmt(uint32_t * action_id_per_category)416 static void set_action_id_drop_pattern_for_spec_mgmt(
417 uint32_t *action_id_per_category)
418 {
419 action_id_per_category[PMO_MAC_ACTION_SPECTRUM_MGMT]
420 = DROP_SPEC_MGMT_ACTION_FRAME_BITMAP;
421 }
422
423 /**
424 * set_action_id_drop_pattern_for_public_action() - Set action id of action
425 * frames for public action frames to be dropped in fw.
426 *
427 * @action_id_per_category: Pointer to action id bitmaps.
428 */
set_action_id_drop_pattern_for_public_action(uint32_t * action_id_per_category)429 static void set_action_id_drop_pattern_for_public_action(
430 uint32_t *action_id_per_category)
431 {
432 action_id_per_category[PMO_MAC_ACTION_PUBLIC_USAGE]
433 = DROP_PUBLIC_ACTION_FRAME_BITMAP;
434 }
435
436 #define PMO_MAX_WAKE_PATTERN_LEN 350
437
438 /* Considering 4 char for i and 10 char for action wakeup pattern and
439 * 2 char for brackets, 2 char for 0x and 1 for space and 1 to end string
440 */
441 #define PMO_MAX_SINGLE_WAKE_PATTERN_LEN 20
442
443 QDF_STATUS
pmo_register_action_frame_patterns(struct wlan_objmgr_vdev * vdev,enum qdf_suspend_type suspend_type)444 pmo_register_action_frame_patterns(struct wlan_objmgr_vdev *vdev,
445 enum qdf_suspend_type suspend_type)
446 {
447 struct pmo_action_wakeup_set_params *cmd;
448 int i = 0;
449 uint8_t *info;
450 uint32_t len = 0;
451 int ret;
452
453 QDF_STATUS status = QDF_STATUS_SUCCESS;
454
455 cmd = qdf_mem_malloc(sizeof(*cmd));
456 if (!cmd) {
457 pmo_err("memory allocation failed for wakeup set params");
458 return QDF_STATUS_E_NOMEM;
459 }
460
461 cmd->vdev_id = pmo_vdev_get_id(vdev);
462 cmd->operation = pmo_action_wakeup_set;
463
464 if (suspend_type == QDF_SYSTEM_SUSPEND)
465 cmd->action_category_map[i++] =
466 SYSTEM_SUSPEND_ALLOWED_ACTION_FRAMES_BITMAP0;
467 else
468 cmd->action_category_map[i++] =
469 RUNTIME_PM_ALLOWED_ACTION_FRAMES_BITMAP0;
470
471 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP1;
472 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP2;
473 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP3;
474 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP4;
475 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP5;
476 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP6;
477 cmd->action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP7;
478
479 set_action_id_drop_pattern_for_spec_mgmt(cmd->action_per_category);
480 set_action_id_drop_pattern_for_public_action(cmd->action_per_category);
481 set_action_id_drop_pattern_for_block_ack(&cmd->action_category_map[0]);
482
483 info = qdf_mem_malloc(PMO_MAX_WAKE_PATTERN_LEN);
484 if (!info) {
485 qdf_mem_free(cmd);
486 return -ENOMEM;
487 }
488
489 for (i = 0; i < PMO_SUPPORTED_ACTION_CATE_ELE_LIST; i++) {
490 if (i < ALLOWED_ACTION_FRAME_MAP_WORDS) {
491 ret = qdf_scnprintf(info + len,
492 PMO_MAX_WAKE_PATTERN_LEN - len,
493 " %d[0x%x]", i, cmd->action_category_map[i]);
494 if (ret <= 0)
495 break;
496 len += ret;
497
498 if (len >= (PMO_MAX_WAKE_PATTERN_LEN -
499 PMO_MAX_SINGLE_WAKE_PATTERN_LEN)) {
500 pmo_nofl_debug("serial_num[action wakeup pattern in fw]:%s",
501 info);
502 len = 0;
503 }
504 } else {
505 cmd->action_category_map[i] = 0;
506 }
507 }
508
509 if (len > 0)
510 pmo_nofl_debug("serial_num[action wakeup pattern in fw]:%s",
511 info);
512 pmo_debug("Spectrum mgmt action id drop bitmap: 0x%x, Public action id drop bitmap: 0x%x",
513 cmd->action_per_category[PMO_MAC_ACTION_SPECTRUM_MGMT],
514 cmd->action_per_category[PMO_MAC_ACTION_PUBLIC_USAGE]);
515
516 /* config action frame patterns */
517 status = pmo_tgt_send_action_frame_pattern_req(vdev, cmd);
518 if (status != QDF_STATUS_SUCCESS)
519 pmo_err("Failed to config wow action frame map, ret %d",
520 status);
521
522 qdf_mem_free(cmd);
523 qdf_mem_free(info);
524
525 return status;
526 }
527
528 QDF_STATUS
pmo_clear_action_frame_patterns(struct wlan_objmgr_vdev * vdev)529 pmo_clear_action_frame_patterns(struct wlan_objmgr_vdev *vdev)
530 {
531 struct pmo_action_wakeup_set_params *cmd;
532 QDF_STATUS status = QDF_STATUS_SUCCESS;
533
534 cmd = qdf_mem_malloc(sizeof(*cmd));
535 if (!cmd) {
536 pmo_err("memory allocation failed for wakeup set params");
537 return QDF_STATUS_E_NOMEM;
538 }
539
540 cmd->vdev_id = pmo_vdev_get_id(vdev);
541 cmd->operation = pmo_action_wakeup_reset;
542
543 /* clear action frame pattern */
544 status = pmo_tgt_send_action_frame_pattern_req(vdev, cmd);
545 if (QDF_IS_STATUS_ERROR(status))
546 pmo_err("Failed to clear wow action frame map, ret %d",
547 status);
548
549 qdf_mem_free(cmd);
550
551 return status;
552 }
553