xref: /wlan-driver/qcacld-3.0/components/pmo/core/src/wlan_pmo_static_config.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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