xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_tx_api.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: wlan_vdev_mgr_tgt_if_tx_api.c
21  *
22  * This file provides definitions for mlme tgt_if APIs, which will
23  * further call target_if/mlme component using LMAC MLME txops
24  */
25 #include <wlan_vdev_mgr_tgt_if_tx_api.h>
26 #include <target_if_vdev_mgr_tx_ops.h>
27 #include "include/wlan_vdev_mlme.h"
28 #include <wlan_mlme_dbg.h>
29 #include <cdp_txrx_cmn_struct.h>
30 #include <cdp_txrx_cmn.h>
31 #include <wlan_lmac_if_api.h>
32 #include <wlan_utility.h>
33 #include <cdp_txrx_ctrl.h>
34 #include <wlan_vdev_mlme_api.h>
35 #include <wlan_dfs_utils_api.h>
36 #include <wlan_vdev_mgr_utils_api.h>
37 #include <wlan_vdev_mgr_ucfg_api.h>
38 #include <wlan_vdev_mlme_main.h>
39 
40 static inline struct wlan_lmac_if_mlme_tx_ops
41 *wlan_vdev_mlme_get_lmac_txops(struct wlan_objmgr_vdev *vdev)
42 {
43 	struct wlan_objmgr_psoc *psoc;
44 
45 	psoc = wlan_vdev_get_psoc(vdev);
46 
47 	return target_if_vdev_mgr_get_tx_ops(psoc);
48 }
49 
50 QDF_STATUS tgt_vdev_mgr_create_send(
51 				struct vdev_mlme_obj *mlme_obj,
52 				struct vdev_create_params *param)
53 {
54 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
55 	struct wlan_lmac_if_mlme_tx_ops *txops;
56 	struct wlan_objmgr_psoc *psoc;
57 	struct wlan_objmgr_pdev *pdev;
58 	struct wlan_objmgr_vdev *vdev;
59 	ol_txrx_soc_handle soc_txrx_handle;
60 	struct cdp_pdev *pdev_txrx_handle;
61 	struct cdp_vdev *vdev_txrx_handle;
62 	enum wlan_op_mode cdp_txrx_opmode;
63 	uint32_t vdev_id;
64 	uint8_t *vdev_addr;
65 	struct vdev_response_timer *vdev_rsp;
66 
67 	if (!param) {
68 		mlme_err("Invalid input");
69 		return QDF_STATUS_E_INVAL;
70 	}
71 
72 	vdev = mlme_obj->vdev;
73 	vdev_id = wlan_vdev_get_id(vdev);
74 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
75 	if (!txops || !txops->vdev_create_send ||
76 	    !txops->vdev_mgr_rsp_timer_init) {
77 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
78 		return QDF_STATUS_E_INVAL;
79 	}
80 
81 	status = txops->vdev_create_send(vdev, param);
82 	if (QDF_IS_STATUS_SUCCESS(status)) {
83 		vdev_rsp = &mlme_obj->vdev_rt;
84 		txops->vdev_mgr_rsp_timer_init(vdev, &vdev_rsp->rsp_timer);
85 	} else {
86 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
87 		return status;
88 	}
89 
90 	cdp_txrx_opmode = wlan_util_vdev_get_cdp_txrx_opmode(vdev);
91 	vdev_addr = wlan_vdev_mlme_get_macaddr(vdev);
92 	psoc = wlan_vdev_get_psoc(vdev);
93 	pdev = wlan_vdev_get_pdev(vdev);
94 	soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
95 	pdev_txrx_handle = wlan_pdev_get_dp_handle(pdev);
96 	if (!soc_txrx_handle || !pdev_txrx_handle)
97 		return QDF_STATUS_E_FAILURE;
98 
99 	vdev_txrx_handle = cdp_vdev_attach(soc_txrx_handle,
100 					   pdev_txrx_handle,
101 					   vdev_addr, vdev_id,
102 					   cdp_txrx_opmode);
103 	if (!vdev_txrx_handle)
104 		return QDF_STATUS_E_FAILURE;
105 
106 	wlan_vdev_set_dp_handle(vdev, vdev_txrx_handle);
107 
108 	return status;
109 }
110 
111 QDF_STATUS tgt_vdev_mgr_create_complete(struct vdev_mlme_obj *vdev_mlme)
112 {
113 	struct wlan_objmgr_vdev *vdev;
114 	struct vdev_set_params param = {0};
115 	struct wlan_lmac_if_mlme_tx_ops *txops;
116 	struct vdev_mlme_inactivity_params *inactivity;
117 	uint8_t vdev_id;
118 	QDF_STATUS status = QDF_STATUS_SUCCESS;
119 
120 	vdev = vdev_mlme->vdev;
121 	vdev_id = wlan_vdev_get_id(vdev);
122 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
123 	if (!txops || !txops->vdev_set_param_send) {
124 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
125 		return QDF_STATUS_E_INVAL;
126 	}
127 
128 	inactivity = &vdev_mlme->mgmt.inactivity_params;
129 
130 	param.vdev_id = vdev_id;
131 
132 	param.param_value =
133 		inactivity->keepalive_min_idle_inactive_time_secs;
134 	param.param_id = WLAN_MLME_CFG_MIN_IDLE_INACTIVE_TIME;
135 	status = txops->vdev_set_param_send(vdev, &param);
136 	if (QDF_IS_STATUS_ERROR(status))
137 		mlme_err("VDEV_%d: Failed to set min idle inactive time!",
138 			 vdev_id);
139 
140 	param.param_value =
141 		inactivity->keepalive_max_idle_inactive_time_secs;
142 	param.param_id = WLAN_MLME_CFG_MAX_IDLE_INACTIVE_TIME;
143 	status = txops->vdev_set_param_send(vdev, &param);
144 	if (QDF_IS_STATUS_ERROR(status))
145 		mlme_err("VDEV_%d: Failed to set max idle inactive time!",
146 			 vdev_id);
147 
148 	param.param_value =
149 		inactivity->keepalive_max_unresponsive_time_secs;
150 	param.param_id = WLAN_MLME_CFG_MAX_UNRESPONSIVE_INACTIVE_TIME;
151 	status = txops->vdev_set_param_send(vdev, &param);
152 	if (QDF_IS_STATUS_ERROR(status))
153 		mlme_err("VDEV_%d: Failed to set max unresponse inactive time!",
154 			 vdev_id);
155 
156 	return status;
157 }
158 
159 QDF_STATUS tgt_vdev_mgr_start_send(
160 				struct vdev_mlme_obj *mlme_obj,
161 				struct vdev_start_params *param)
162 {
163 	QDF_STATUS status;
164 	struct wlan_lmac_if_mlme_tx_ops *txops;
165 	struct wlan_objmgr_vdev *vdev;
166 	uint8_t vdev_id;
167 
168 	if (!param) {
169 		mlme_err("Invalid input");
170 		return QDF_STATUS_E_INVAL;
171 	}
172 
173 	vdev = mlme_obj->vdev;
174 	vdev_id = wlan_vdev_get_id(vdev);
175 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
176 	if (!txops || !txops->vdev_start_send) {
177 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
178 		return QDF_STATUS_E_INVAL;
179 	}
180 
181 	status = txops->vdev_start_send(vdev, param);
182 	if (QDF_IS_STATUS_ERROR(status))
183 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
184 
185 	return status;
186 }
187 
188 QDF_STATUS tgt_vdev_mgr_delete_send(
189 				struct vdev_mlme_obj *mlme_obj,
190 				struct vdev_delete_params *param)
191 {
192 	QDF_STATUS status;
193 	struct wlan_lmac_if_mlme_tx_ops *txops;
194 	struct wlan_objmgr_vdev *vdev;
195 	uint8_t vdev_id;
196 
197 	if (!param) {
198 		mlme_err("Invalid input");
199 		return QDF_STATUS_E_INVAL;
200 	}
201 
202 	vdev = mlme_obj->vdev;
203 	vdev_id = wlan_vdev_get_id(vdev);
204 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
205 	if (!txops || !txops->vdev_delete_send) {
206 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
207 		return QDF_STATUS_E_INVAL;
208 	}
209 
210 	status = txops->vdev_delete_send(vdev, param);
211 	if (QDF_IS_STATUS_ERROR(status))
212 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
213 
214 	return status;
215 }
216 
217 QDF_STATUS tgt_vdev_mgr_peer_flush_tids_send(
218 				struct vdev_mlme_obj *mlme_obj,
219 				struct peer_flush_params *param)
220 {
221 	QDF_STATUS status;
222 	struct wlan_lmac_if_mlme_tx_ops *txops;
223 	struct wlan_objmgr_vdev *vdev;
224 	uint8_t vdev_id;
225 
226 	if (!param) {
227 		mlme_err("Invalid input");
228 		return QDF_STATUS_E_INVAL;
229 	}
230 
231 	vdev = mlme_obj->vdev;
232 	vdev_id = wlan_vdev_get_id(vdev);
233 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
234 	if (!txops || !txops->peer_flush_tids_send) {
235 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
236 		return QDF_STATUS_E_INVAL;
237 	}
238 
239 	status = txops->peer_flush_tids_send(vdev, param);
240 	if (QDF_IS_STATUS_ERROR(status))
241 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
242 
243 	return QDF_STATUS_SUCCESS;
244 }
245 
246 QDF_STATUS tgt_vdev_mgr_stop_send(
247 				struct vdev_mlme_obj *mlme_obj,
248 				struct vdev_stop_params *param)
249 {
250 	QDF_STATUS status;
251 	struct wlan_lmac_if_mlme_tx_ops *txops;
252 	struct wlan_objmgr_vdev *vdev;
253 	uint8_t vdev_id;
254 
255 	if (!param) {
256 		mlme_err("Invalid input");
257 		return QDF_STATUS_E_INVAL;
258 	}
259 
260 	vdev = mlme_obj->vdev;
261 	vdev_id = wlan_vdev_get_id(vdev);
262 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
263 	if (!txops || !txops->vdev_stop_send) {
264 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
265 		return QDF_STATUS_E_INVAL;
266 	}
267 
268 	status = txops->vdev_stop_send(vdev, param);
269 	if (QDF_IS_STATUS_ERROR(status))
270 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
271 
272 	return status;
273 }
274 
275 QDF_STATUS tgt_vdev_mgr_beacon_stop(struct vdev_mlme_obj *mlme_obj)
276 {
277 	return QDF_STATUS_SUCCESS;
278 }
279 
280 QDF_STATUS tgt_vdev_mgr_beacon_free(struct vdev_mlme_obj *mlme_obj)
281 {
282 	return QDF_STATUS_SUCCESS;
283 }
284 
285 QDF_STATUS tgt_vdev_mgr_up_send(
286 				struct vdev_mlme_obj *mlme_obj,
287 				struct vdev_up_params *param)
288 {
289 	QDF_STATUS status;
290 	struct wlan_lmac_if_mlme_tx_ops *txops;
291 	ol_txrx_soc_handle soc_txrx_handle;
292 	struct cdp_vdev *vdev_txrx_handle;
293 	struct wlan_objmgr_psoc *psoc;
294 	struct wlan_objmgr_vdev *vdev;
295 	uint8_t vdev_id;
296 
297 	if (!param) {
298 		mlme_err("Invalid input");
299 		return QDF_STATUS_E_INVAL;
300 	}
301 
302 	vdev = mlme_obj->vdev;
303 	vdev_id = wlan_vdev_get_id(vdev);
304 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
305 	if (!txops || !txops->vdev_up_send) {
306 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
307 		return QDF_STATUS_E_INVAL;
308 	}
309 
310 	/* cdp set rx and tx decap type */
311 	psoc = wlan_vdev_get_psoc(vdev);
312 	soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
313 	vdev_txrx_handle = wlan_vdev_get_dp_handle(vdev);
314 	if (!soc_txrx_handle || !vdev_txrx_handle)
315 		return QDF_STATUS_E_INVAL;
316 
317 	cdp_set_vdev_rx_decap_type(soc_txrx_handle,
318 				   (struct cdp_vdev *)vdev_txrx_handle,
319 				   mlme_obj->mgmt.generic.rx_decap_type);
320 	cdp_set_tx_encap_type(soc_txrx_handle,
321 			      (struct cdp_vdev *)vdev_txrx_handle,
322 			      mlme_obj->mgmt.generic.tx_decap_type);
323 
324 	status = txops->vdev_up_send(vdev, param);
325 	if (QDF_IS_STATUS_ERROR(status))
326 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
327 
328 	return status;
329 }
330 
331 QDF_STATUS tgt_vdev_mgr_down_send(
332 				struct vdev_mlme_obj *mlme_obj,
333 				struct vdev_down_params *param)
334 {
335 	QDF_STATUS status;
336 	struct wlan_lmac_if_mlme_tx_ops *txops;
337 	struct wlan_objmgr_pdev *pdev;
338 	struct wlan_objmgr_vdev *vdev;
339 	enum QDF_OPMODE opmode;
340 	uint8_t vdev_id;
341 
342 	if (!param) {
343 		mlme_err("Invalid input");
344 		return QDF_STATUS_E_INVAL;
345 	}
346 
347 	vdev = mlme_obj->vdev;
348 	vdev_id = wlan_vdev_get_id(vdev);
349 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
350 	if (!txops || !txops->vdev_down_send) {
351 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
352 		return QDF_STATUS_E_INVAL;
353 	}
354 
355 	pdev = wlan_vdev_get_pdev(vdev);
356 	if (!pdev) {
357 		mlme_err("PDEV is NULL");
358 		return QDF_STATUS_E_INVAL;
359 	}
360 
361 	opmode = wlan_vdev_mlme_get_opmode(vdev);
362 	if (wlan_util_is_vdev_active(pdev, WLAN_VDEV_TARGET_IF_ID) ==
363 						QDF_STATUS_SUCCESS) {
364 
365 		if (opmode == QDF_SAP_MODE)
366 			utils_dfs_cancel_precac_timer(pdev);
367 	}
368 
369 	status = txops->vdev_down_send(vdev, param);
370 	if (QDF_IS_STATUS_ERROR(status))
371 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
372 
373 	return status;
374 }
375 
376 QDF_STATUS tgt_vdev_mgr_set_neighbour_rx_cmd_send(
377 				struct vdev_mlme_obj *mlme_obj,
378 				struct set_neighbour_rx_params *param)
379 {
380 	return QDF_STATUS_SUCCESS;
381 }
382 
383 QDF_STATUS tgt_vdev_mgr_nac_rssi_send(
384 				struct vdev_mlme_obj *mlme_obj,
385 				struct vdev_scan_nac_rssi_params *param)
386 {
387 	return QDF_STATUS_SUCCESS;
388 }
389 
390 QDF_STATUS tgt_vdev_mgr_sifs_trigger_send(
391 				struct vdev_mlme_obj *mlme_obj,
392 				struct sifs_trigger_param *param)
393 {
394 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
395 	struct wlan_lmac_if_mlme_tx_ops *txops;
396 	struct wlan_objmgr_vdev *vdev;
397 	uint8_t vdev_id;
398 
399 	if (!param) {
400 		mlme_err("Invalid input");
401 		return QDF_STATUS_E_INVAL;
402 	}
403 
404 	vdev = mlme_obj->vdev;
405 	vdev_id = wlan_vdev_get_id(vdev);
406 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
407 	if (!txops || !txops->vdev_sifs_trigger_send) {
408 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
409 		return QDF_STATUS_E_INVAL;
410 	}
411 
412 	status = txops->vdev_sifs_trigger_send(vdev, param);
413 	if (QDF_IS_STATUS_ERROR(status))
414 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
415 
416 	return status;
417 }
418 
419 QDF_STATUS tgt_vdev_mgr_set_custom_aggr_size_send(
420 				struct vdev_mlme_obj *mlme_obj,
421 				struct set_custom_aggr_size_params *param)
422 {
423 	QDF_STATUS status;
424 	struct wlan_lmac_if_mlme_tx_ops *txops;
425 	struct wlan_objmgr_vdev *vdev;
426 	uint8_t vdev_id;
427 
428 	if (!param) {
429 		mlme_err("Invalid input");
430 		return QDF_STATUS_E_INVAL;
431 	}
432 
433 	vdev = mlme_obj->vdev;
434 	vdev_id = wlan_vdev_get_id(vdev);
435 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
436 	if (!txops || !txops->vdev_set_custom_aggr_size_cmd_send) {
437 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
438 		return QDF_STATUS_E_INVAL;
439 	}
440 
441 	status = txops->vdev_set_custom_aggr_size_cmd_send(vdev, param);
442 	if (QDF_IS_STATUS_ERROR(status))
443 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
444 
445 	return status;
446 }
447 
448 QDF_STATUS tgt_vdev_mgr_config_ratemask_cmd_send(
449 				struct vdev_mlme_obj *mlme_obj,
450 				struct config_ratemask_params *param)
451 {
452 	QDF_STATUS status;
453 	struct wlan_lmac_if_mlme_tx_ops *txops;
454 	struct wlan_objmgr_vdev *vdev;
455 	uint8_t vdev_id;
456 
457 	vdev = mlme_obj->vdev;
458 	vdev_id = wlan_vdev_get_id(vdev);
459 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
460 	if (!txops || !txops->vdev_config_ratemask_cmd_send) {
461 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
462 		return QDF_STATUS_E_INVAL;
463 	}
464 
465 	status = txops->vdev_config_ratemask_cmd_send(vdev, param);
466 	if (QDF_IS_STATUS_ERROR(status))
467 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
468 
469 	return status;
470 }
471 
472 QDF_STATUS tgt_vdev_mgr_beacon_cmd_send(
473 				struct vdev_mlme_obj *mlme_obj,
474 				struct beacon_params *param)
475 {
476 	return QDF_STATUS_SUCCESS;
477 }
478 
479 QDF_STATUS tgt_vdev_mgr_beacon_tmpl_send(
480 				struct vdev_mlme_obj *mlme_obj,
481 				struct beacon_tmpl_params *param)
482 {
483 	return QDF_STATUS_SUCCESS;
484 }
485 
486 QDF_STATUS tgt_vdev_mgr_multiple_vdev_restart_send(
487 				struct wlan_objmgr_pdev *pdev,
488 				struct multiple_vdev_restart_params *param)
489 {
490 	QDF_STATUS status = QDF_STATUS_SUCCESS;
491 	struct wlan_lmac_if_mlme_tx_ops *txops;
492 	struct wlan_objmgr_vdev *vdev;
493 
494 	if (!param) {
495 		mlme_err("Invalid input");
496 		return QDF_STATUS_E_INVAL;
497 	}
498 
499 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev,
500 						    param->vdev_ids[0],
501 						    WLAN_VDEV_TARGET_IF_ID);
502 	if (vdev) {
503 		txops = wlan_vdev_mlme_get_lmac_txops(vdev);
504 		if (!txops || !txops->multiple_vdev_restart_req_cmd) {
505 			mlme_err("VDEV_%d: No Tx Ops", wlan_vdev_get_id(vdev));
506 			wlan_objmgr_vdev_release_ref(vdev,
507 						     WLAN_VDEV_TARGET_IF_ID);
508 			return QDF_STATUS_E_INVAL;
509 		}
510 
511 		status = txops->multiple_vdev_restart_req_cmd(pdev, param);
512 		if (QDF_IS_STATUS_ERROR(status))
513 			mlme_err("Tx Ops Error: %d", status);
514 
515 		wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID);
516 	}
517 
518 	return status;
519 }
520 
521 QDF_STATUS tgt_vdev_mgr_set_param_send(
522 				struct vdev_mlme_obj *mlme_obj,
523 				struct vdev_set_params *param)
524 {
525 	QDF_STATUS status;
526 	struct wlan_lmac_if_mlme_tx_ops *txops;
527 	struct wlan_objmgr_vdev *vdev;
528 	uint8_t vdev_id;
529 
530 	if (!param) {
531 		mlme_err("Invalid input");
532 		return QDF_STATUS_E_INVAL;
533 	}
534 
535 	vdev = mlme_obj->vdev;
536 	vdev_id = wlan_vdev_get_id(vdev);
537 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
538 	if (!txops || !txops->vdev_set_param_send) {
539 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
540 		return QDF_STATUS_E_INVAL;
541 	}
542 
543 	status = txops->vdev_set_param_send(vdev, param);
544 	if (QDF_IS_STATUS_ERROR(status))
545 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
546 
547 	return status;
548 }
549 
550 QDF_STATUS tgt_vdev_mgr_sta_ps_param_send(
551 				struct vdev_mlme_obj *mlme_obj,
552 				struct sta_ps_params *param)
553 {
554 	QDF_STATUS status;
555 	struct wlan_lmac_if_mlme_tx_ops *txops;
556 	struct wlan_objmgr_vdev *vdev;
557 	uint8_t vdev_id;
558 
559 	if (!param) {
560 		mlme_err("Invalid input");
561 		return QDF_STATUS_E_INVAL;
562 	}
563 
564 	vdev = mlme_obj->vdev;
565 	vdev_id = wlan_vdev_get_id(vdev);
566 	txops = wlan_vdev_mlme_get_lmac_txops(vdev);
567 	if (!txops || !txops->vdev_sta_ps_param_send) {
568 		mlme_err("VDEV_%d: No Tx Ops", vdev_id);
569 		return QDF_STATUS_E_INVAL;
570 	}
571 
572 	status = txops->vdev_sta_ps_param_send(vdev, param);
573 	if (QDF_IS_STATUS_ERROR(status))
574 		mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status);
575 
576 	return status;
577 }
578