xref: /wlan-driver/qca-wifi-host-cmn/umac/green_ap/dispatcher/src/wlan_green_ap_api.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: This file contains green ap north bound interface definitions
22*5113495bSYour Name  */
23*5113495bSYour Name #include <wlan_green_ap_api.h>
24*5113495bSYour Name #include <../../core/src/wlan_green_ap_main_i.h>
25*5113495bSYour Name #include <wlan_objmgr_global_obj.h>
26*5113495bSYour Name #include "cfg_green_ap_params.h"
27*5113495bSYour Name #include "cfg_ucfg_api.h"
28*5113495bSYour Name 
wlan_green_ap_get_capab(struct wlan_objmgr_pdev * pdev)29*5113495bSYour Name QDF_STATUS wlan_green_ap_get_capab(
30*5113495bSYour Name 			struct wlan_objmgr_pdev *pdev)
31*5113495bSYour Name {
32*5113495bSYour Name 	struct wlan_lmac_if_green_ap_tx_ops *green_ap_tx_ops;
33*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
34*5113495bSYour Name 
35*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(pdev,
36*5113495bSYour Name 					WLAN_UMAC_COMP_GREEN_AP);
37*5113495bSYour Name 
38*5113495bSYour Name 	if (!green_ap_ctx) {
39*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
40*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
41*5113495bSYour Name 	}
42*5113495bSYour Name 
43*5113495bSYour Name 
44*5113495bSYour Name 	green_ap_tx_ops = wlan_psoc_get_green_ap_tx_ops(green_ap_ctx);
45*5113495bSYour Name 	if (!green_ap_tx_ops) {
46*5113495bSYour Name 		green_ap_err("green ap tx ops obtained are NULL");
47*5113495bSYour Name 		return QDF_STATUS_E_EXISTS;
48*5113495bSYour Name 	}
49*5113495bSYour Name 
50*5113495bSYour Name 	if (green_ap_tx_ops->get_capab)
51*5113495bSYour Name 		return green_ap_tx_ops->get_capab(pdev);
52*5113495bSYour Name 
53*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
54*5113495bSYour Name }
55*5113495bSYour Name 
56*5113495bSYour Name /**
57*5113495bSYour Name  * wlan_green_ap_pdev_obj_create_notification() - called from objmgr when pdev
58*5113495bSYour Name  *                                                is created
59*5113495bSYour Name  * @pdev: pdev context
60*5113495bSYour Name  * @arg: argument
61*5113495bSYour Name  *
62*5113495bSYour Name  * This function gets called from object manager when pdev is being created and
63*5113495bSYour Name  * creates green ap context and attach it to objmgr.
64*5113495bSYour Name  *
65*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - in case of success
66*5113495bSYour Name  */
wlan_green_ap_pdev_obj_create_notification(struct wlan_objmgr_pdev * pdev,void * arg)67*5113495bSYour Name static QDF_STATUS wlan_green_ap_pdev_obj_create_notification(
68*5113495bSYour Name 			struct wlan_objmgr_pdev *pdev, void *arg)
69*5113495bSYour Name {
70*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
71*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
72*5113495bSYour Name 
73*5113495bSYour Name 	if (!pdev) {
74*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
75*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
76*5113495bSYour Name 	}
77*5113495bSYour Name 
78*5113495bSYour Name 	green_ap_ctx = qdf_mem_malloc(sizeof(*green_ap_ctx));
79*5113495bSYour Name 	if (!green_ap_ctx)
80*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
81*5113495bSYour Name 
82*5113495bSYour Name 	green_ap_ctx->ps_state = WLAN_GREEN_AP_PS_IDLE_STATE;
83*5113495bSYour Name 	green_ap_ctx->ps_event = WLAN_GREEN_AP_PS_WAIT_EVENT;
84*5113495bSYour Name 	green_ap_ctx->ps_mode = WLAN_GREEN_AP_MODE_NO_STA;
85*5113495bSYour Name 	green_ap_ctx->num_nodes = 0;
86*5113495bSYour Name 	green_ap_ctx->num_nodes_multistream = 0;
87*5113495bSYour Name 	green_ap_ctx->ps_on_time = WLAN_GREEN_AP_PS_ON_TIME;
88*5113495bSYour Name 	green_ap_ctx->ps_trans_time = WLAN_GREEN_AP_PS_TRANS_TIME;
89*5113495bSYour Name 
90*5113495bSYour Name 	green_ap_ctx->pdev = pdev;
91*5113495bSYour Name 
92*5113495bSYour Name 	qdf_timer_init(NULL, &green_ap_ctx->ps_timer,
93*5113495bSYour Name 		       wlan_green_ap_timer_fn,
94*5113495bSYour Name 		       pdev, QDF_TIMER_TYPE_WAKE_APPS);
95*5113495bSYour Name 
96*5113495bSYour Name 	qdf_spinlock_create(&green_ap_ctx->lock);
97*5113495bSYour Name 	if (wlan_objmgr_pdev_component_obj_attach(pdev,
98*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
99*5113495bSYour Name 				green_ap_ctx, QDF_STATUS_SUCCESS)
100*5113495bSYour Name 			!= QDF_STATUS_SUCCESS) {
101*5113495bSYour Name 		green_ap_err("Failed to attach green ap ctx in pdev ctx");
102*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
103*5113495bSYour Name 		goto err_pdev_attach;
104*5113495bSYour Name 	}
105*5113495bSYour Name 
106*5113495bSYour Name 	green_ap_info("Green AP creation successful, green ap ctx: %pK, pdev: %pK",
107*5113495bSYour Name 		      green_ap_ctx, pdev);
108*5113495bSYour Name 
109*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
110*5113495bSYour Name 
111*5113495bSYour Name err_pdev_attach:
112*5113495bSYour Name 	qdf_spinlock_destroy(&green_ap_ctx->lock);
113*5113495bSYour Name 	qdf_timer_free(&green_ap_ctx->ps_timer);
114*5113495bSYour Name 	qdf_mem_free(green_ap_ctx);
115*5113495bSYour Name 	return status;
116*5113495bSYour Name }
117*5113495bSYour Name 
118*5113495bSYour Name /**
119*5113495bSYour Name  * wlan_green_ap_pdev_obj_destroy_notification() - called from objmgr when
120*5113495bSYour Name  *                                                 pdev is destroyed
121*5113495bSYour Name  * @pdev: pdev context
122*5113495bSYour Name  * @arg: argument
123*5113495bSYour Name  *
124*5113495bSYour Name  * This function gets called from object manager when pdev is being destroyed
125*5113495bSYour Name  * and deletes green ap context and detach it from objmgr.
126*5113495bSYour Name  *
127*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - in case of success
128*5113495bSYour Name  */
wlan_green_ap_pdev_obj_destroy_notification(struct wlan_objmgr_pdev * pdev,void * arg)129*5113495bSYour Name static QDF_STATUS wlan_green_ap_pdev_obj_destroy_notification(
130*5113495bSYour Name 			struct wlan_objmgr_pdev *pdev, void *arg)
131*5113495bSYour Name {
132*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
133*5113495bSYour Name 
134*5113495bSYour Name 	if (!pdev) {
135*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
136*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
137*5113495bSYour Name 	}
138*5113495bSYour Name 
139*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
140*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
141*5113495bSYour Name 	if (!green_ap_ctx) {
142*5113495bSYour Name 		green_ap_err("green ap context is already NULL");
143*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
144*5113495bSYour Name 	}
145*5113495bSYour Name 
146*5113495bSYour Name 	green_ap_info("Deleting green ap pdev obj, green ap ctx: %pK, pdev: %pK",
147*5113495bSYour Name 		      green_ap_ctx, pdev);
148*5113495bSYour Name 
149*5113495bSYour Name 	if (wlan_objmgr_pdev_component_obj_detach(pdev,
150*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP, green_ap_ctx) !=
151*5113495bSYour Name 				QDF_STATUS_SUCCESS) {
152*5113495bSYour Name 		green_ap_err("Failed to detach green ap ctx in psoc ctx");
153*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
154*5113495bSYour Name 	}
155*5113495bSYour Name 
156*5113495bSYour Name 	qdf_timer_free(&green_ap_ctx->ps_timer);
157*5113495bSYour Name 	qdf_spinlock_destroy(&green_ap_ctx->lock);
158*5113495bSYour Name 
159*5113495bSYour Name 	qdf_mem_free(green_ap_ctx);
160*5113495bSYour Name 	green_ap_info("green ap deletion successful");
161*5113495bSYour Name 
162*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
163*5113495bSYour Name }
164*5113495bSYour Name 
wlan_green_ap_init(void)165*5113495bSYour Name QDF_STATUS wlan_green_ap_init(void)
166*5113495bSYour Name {
167*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
168*5113495bSYour Name 
169*5113495bSYour Name 	status = wlan_objmgr_register_pdev_create_handler(
170*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
171*5113495bSYour Name 				wlan_green_ap_pdev_obj_create_notification,
172*5113495bSYour Name 				NULL);
173*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
174*5113495bSYour Name 		green_ap_err("Failed to register green ap obj create handler");
175*5113495bSYour Name 		goto err_pdev_create;
176*5113495bSYour Name 	}
177*5113495bSYour Name 
178*5113495bSYour Name 	status = wlan_objmgr_register_pdev_destroy_handler(
179*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
180*5113495bSYour Name 				wlan_green_ap_pdev_obj_destroy_notification,
181*5113495bSYour Name 				NULL);
182*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
183*5113495bSYour Name 		green_ap_err("Failed to register green ap obj destroy handler");
184*5113495bSYour Name 		goto err_pdev_delete;
185*5113495bSYour Name 	}
186*5113495bSYour Name 
187*5113495bSYour Name 	green_ap_info("Successfully registered create and destroy handlers with objmgr");
188*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
189*5113495bSYour Name 
190*5113495bSYour Name err_pdev_delete:
191*5113495bSYour Name 	wlan_objmgr_unregister_pdev_create_handler(
192*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
193*5113495bSYour Name 				wlan_green_ap_pdev_obj_create_notification,
194*5113495bSYour Name 				NULL);
195*5113495bSYour Name err_pdev_create:
196*5113495bSYour Name 	return status;
197*5113495bSYour Name }
198*5113495bSYour Name 
wlan_green_ap_deinit(void)199*5113495bSYour Name QDF_STATUS wlan_green_ap_deinit(void)
200*5113495bSYour Name {
201*5113495bSYour Name 	if (wlan_objmgr_unregister_pdev_create_handler(
202*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
203*5113495bSYour Name 				wlan_green_ap_pdev_obj_create_notification,
204*5113495bSYour Name 				NULL)
205*5113495bSYour Name 			!= QDF_STATUS_SUCCESS) {
206*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
207*5113495bSYour Name 	}
208*5113495bSYour Name 
209*5113495bSYour Name 	if (wlan_objmgr_unregister_pdev_destroy_handler(
210*5113495bSYour Name 				WLAN_UMAC_COMP_GREEN_AP,
211*5113495bSYour Name 				wlan_green_ap_pdev_obj_destroy_notification,
212*5113495bSYour Name 				NULL)
213*5113495bSYour Name 			!= QDF_STATUS_SUCCESS) {
214*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
215*5113495bSYour Name 	}
216*5113495bSYour Name 
217*5113495bSYour Name 	green_ap_info("Successfully unregistered create and destroy handlers with objmgr");
218*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
219*5113495bSYour Name }
220*5113495bSYour Name 
221*5113495bSYour Name #ifdef WLAN_SUPPORT_GAP_LL_PS_MODE
222*5113495bSYour Name /**
223*5113495bSYour Name  * wlan_green_ap_set_bcn_mult() - API to set Green AP beacon
224*5113495bSYour Name  * multiplier
225*5113495bSYour Name  * @pdev: Pdev pointer
226*5113495bSYour Name  *
227*5113495bSYour Name  */
wlan_green_ap_set_bcn_mult(struct wlan_objmgr_pdev * pdev)228*5113495bSYour Name static void wlan_green_ap_set_bcn_mult(struct wlan_objmgr_pdev *pdev)
229*5113495bSYour Name {
230*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
231*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
232*5113495bSYour Name 
233*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
234*5113495bSYour Name 
235*5113495bSYour Name 	if (!psoc) {
236*5113495bSYour Name 		green_ap_err("psoc is NULL");
237*5113495bSYour Name 		return;
238*5113495bSYour Name 	}
239*5113495bSYour Name 
240*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
241*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
242*5113495bSYour Name 	if (!green_ap_ctx) {
243*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
244*5113495bSYour Name 		return;
245*5113495bSYour Name 	}
246*5113495bSYour Name 
247*5113495bSYour Name 	green_ap_ctx->bcn_mult = cfg_get(psoc,
248*5113495bSYour Name 					 CFG_GAP_LL_PS_LOW_BEACON_MULT);
249*5113495bSYour Name }
250*5113495bSYour Name 
251*5113495bSYour Name /**
252*5113495bSYour Name  * wlan_green_ap_init_cmd_count() - Initialize command count.
253*5113495bSYour Name  * @green_ap_ctx: green ap ctx
254*5113495bSYour Name  */
wlan_green_ap_init_cmd_count(struct wlan_pdev_green_ap_ctx * green_ap_ctx)255*5113495bSYour Name static void wlan_green_ap_init_cmd_count(struct wlan_pdev_green_ap_ctx *green_ap_ctx)
256*5113495bSYour Name {
257*5113495bSYour Name 	/* Disable cookie id will from 0,2,6,..*/
258*5113495bSYour Name 	qdf_atomic_init(&green_ap_ctx->ps_dis_cmd_cnt);
259*5113495bSYour Name 	/* Enable cookie id will be from 1,3,5,..*/
260*5113495bSYour Name 	qdf_atomic_set(&green_ap_ctx->ps_en_cmd_cnt, 1);
261*5113495bSYour Name }
262*5113495bSYour Name #else
wlan_green_ap_set_bcn_mult(struct wlan_objmgr_pdev * pdev)263*5113495bSYour Name static inline void wlan_green_ap_set_bcn_mult(struct wlan_objmgr_pdev *pdev)
264*5113495bSYour Name {
265*5113495bSYour Name }
266*5113495bSYour Name 
267*5113495bSYour Name static inline
wlan_green_ap_init_cmd_count(struct wlan_pdev_green_ap_ctx * green_ap_ctx)268*5113495bSYour Name void wlan_green_ap_init_cmd_count(struct wlan_pdev_green_ap_ctx *green_ap_ctx)
269*5113495bSYour Name {
270*5113495bSYour Name }
271*5113495bSYour Name #endif
272*5113495bSYour Name 
wlan_green_ap_pdev_open(struct wlan_objmgr_pdev * pdev)273*5113495bSYour Name QDF_STATUS wlan_green_ap_pdev_open(struct wlan_objmgr_pdev *pdev)
274*5113495bSYour Name {
275*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
276*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
277*5113495bSYour Name 
278*5113495bSYour Name 	if (!pdev) {
279*5113495bSYour Name 		green_ap_err("pdev is NULL");
280*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
281*5113495bSYour Name 	}
282*5113495bSYour Name 
283*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
284*5113495bSYour Name 
285*5113495bSYour Name 	if (!psoc) {
286*5113495bSYour Name 		green_ap_err("psoc is NULL");
287*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
288*5113495bSYour Name 	}
289*5113495bSYour Name 
290*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
291*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
292*5113495bSYour Name 	if (!green_ap_ctx) {
293*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
294*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
295*5113495bSYour Name 	}
296*5113495bSYour Name 
297*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
298*5113495bSYour Name 	green_ap_ctx->ps_enable = cfg_get(psoc,
299*5113495bSYour Name 					CFG_ENABLE_GREEN_AP_FEATURE);
300*5113495bSYour Name 	green_ap_ctx->egap_params.host_enable_egap = cfg_get(psoc,
301*5113495bSYour Name 					CFG_ENABLE_EGAP_FEATURE);
302*5113495bSYour Name 	green_ap_ctx->egap_params.egap_inactivity_time = cfg_get(psoc,
303*5113495bSYour Name 					CFG_EGAP_INACT_TIME_FEATURE);
304*5113495bSYour Name 	green_ap_ctx->egap_params.egap_wait_time = cfg_get(psoc,
305*5113495bSYour Name 					CFG_EGAP_WAIT_TIME_FEATURE);
306*5113495bSYour Name 	green_ap_ctx->egap_params.egap_feature_flags = cfg_get(psoc,
307*5113495bSYour Name 					CFG_EGAP_FLAGS_FEATURE);
308*5113495bSYour Name 
309*5113495bSYour Name 	wlan_green_ap_set_bcn_mult(pdev);
310*5113495bSYour Name 
311*5113495bSYour Name 	wlan_green_ap_init_cmd_count(green_ap_ctx);
312*5113495bSYour Name 
313*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
314*5113495bSYour Name 
315*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
316*5113495bSYour Name }
317*5113495bSYour Name 
wlan_green_ap_start(struct wlan_objmgr_pdev * pdev)318*5113495bSYour Name QDF_STATUS wlan_green_ap_start(struct wlan_objmgr_pdev *pdev)
319*5113495bSYour Name {
320*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
321*5113495bSYour Name 
322*5113495bSYour Name 	if (!pdev) {
323*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
324*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
325*5113495bSYour Name 	}
326*5113495bSYour Name 
327*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
328*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
329*5113495bSYour Name 	if (!green_ap_ctx) {
330*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
331*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
332*5113495bSYour Name 	}
333*5113495bSYour Name 
334*5113495bSYour Name 	green_ap_debug("Green AP start received");
335*5113495bSYour Name 
336*5113495bSYour Name 	/* Make sure the start function does not get called 2 times */
337*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
338*5113495bSYour Name 
339*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
340*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
341*5113495bSYour Name 		green_ap_debug("enhanced green ap support is enabled");
342*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
343*5113495bSYour Name 	}
344*5113495bSYour Name 
345*5113495bSYour Name 	if (green_ap_ctx->ps_state == WLAN_GREEN_AP_PS_IDLE_STATE) {
346*5113495bSYour Name 		if (green_ap_ctx->ps_enable) {
347*5113495bSYour Name 			qdf_spin_unlock_bh(&green_ap_ctx->lock);
348*5113495bSYour Name 			return wlan_green_ap_state_mc(green_ap_ctx,
349*5113495bSYour Name 					      WLAN_GREEN_AP_PS_START_EVENT);
350*5113495bSYour Name 		}
351*5113495bSYour Name 	}
352*5113495bSYour Name 
353*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
354*5113495bSYour Name 	return QDF_STATUS_E_ALREADY;
355*5113495bSYour Name }
356*5113495bSYour Name 
wlan_green_ap_stop(struct wlan_objmgr_pdev * pdev)357*5113495bSYour Name QDF_STATUS wlan_green_ap_stop(struct wlan_objmgr_pdev *pdev)
358*5113495bSYour Name {
359*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
360*5113495bSYour Name 
361*5113495bSYour Name 	if (!pdev) {
362*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
363*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
364*5113495bSYour Name 	}
365*5113495bSYour Name 
366*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
367*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
368*5113495bSYour Name 	if (!green_ap_ctx) {
369*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
370*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
371*5113495bSYour Name 	}
372*5113495bSYour Name 
373*5113495bSYour Name 	green_ap_debug("Green AP stop received");
374*5113495bSYour Name 
375*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
376*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
377*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
378*5113495bSYour Name 		green_ap_debug("enhanced green ap support is enabled");
379*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
380*5113495bSYour Name 	}
381*5113495bSYour Name 
382*5113495bSYour Name 	/* Delete the timer just to be sure */
383*5113495bSYour Name 	qdf_timer_stop(&green_ap_ctx->ps_timer);
384*5113495bSYour Name 
385*5113495bSYour Name 	/* Disable the power save */
386*5113495bSYour Name 	green_ap_ctx->ps_enable = WLAN_GREEN_AP_PS_DISABLE;
387*5113495bSYour Name 
388*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
389*5113495bSYour Name 	return wlan_green_ap_state_mc(green_ap_ctx,
390*5113495bSYour Name 				      WLAN_GREEN_AP_PS_STOP_EVENT);
391*5113495bSYour Name }
392*5113495bSYour Name 
wlan_green_ap_add_sta(struct wlan_objmgr_pdev * pdev)393*5113495bSYour Name QDF_STATUS wlan_green_ap_add_sta(struct wlan_objmgr_pdev *pdev)
394*5113495bSYour Name {
395*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
396*5113495bSYour Name 
397*5113495bSYour Name 	if (!pdev) {
398*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
399*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
400*5113495bSYour Name 	}
401*5113495bSYour Name 
402*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
403*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
404*5113495bSYour Name 	if (!green_ap_ctx) {
405*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
406*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
407*5113495bSYour Name 	}
408*5113495bSYour Name 
409*5113495bSYour Name 	green_ap_debug("Green AP add sta received");
410*5113495bSYour Name 
411*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
412*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
413*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
414*5113495bSYour Name 		green_ap_debug("enhanced green ap support is enabled");
415*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
416*5113495bSYour Name 	}
417*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
418*5113495bSYour Name 
419*5113495bSYour Name 	return wlan_green_ap_state_mc(green_ap_ctx,
420*5113495bSYour Name 				      WLAN_GREEN_AP_ADD_STA_EVENT);
421*5113495bSYour Name }
422*5113495bSYour Name 
wlan_green_ap_add_multistream_sta(struct wlan_objmgr_pdev * pdev)423*5113495bSYour Name QDF_STATUS wlan_green_ap_add_multistream_sta(struct wlan_objmgr_pdev *pdev)
424*5113495bSYour Name {
425*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
426*5113495bSYour Name 
427*5113495bSYour Name 	if (!pdev) {
428*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
429*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
430*5113495bSYour Name 	}
431*5113495bSYour Name 
432*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
433*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
434*5113495bSYour Name 	if (!green_ap_ctx) {
435*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
436*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
437*5113495bSYour Name 	}
438*5113495bSYour Name 
439*5113495bSYour Name 	green_ap_debug("Green AP add multistream sta received");
440*5113495bSYour Name 
441*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
442*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
443*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
444*5113495bSYour Name 		green_ap_debug("enhanced green ap support is enabled");
445*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
446*5113495bSYour Name 	}
447*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
448*5113495bSYour Name 
449*5113495bSYour Name 	return wlan_green_ap_state_mc(green_ap_ctx,
450*5113495bSYour Name 			WLAN_GREEN_AP_ADD_MULTISTREAM_STA_EVENT);
451*5113495bSYour Name }
452*5113495bSYour Name 
wlan_green_ap_del_sta(struct wlan_objmgr_pdev * pdev)453*5113495bSYour Name QDF_STATUS wlan_green_ap_del_sta(struct wlan_objmgr_pdev *pdev)
454*5113495bSYour Name {
455*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
456*5113495bSYour Name 
457*5113495bSYour Name 	if (!pdev) {
458*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
459*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
460*5113495bSYour Name 	}
461*5113495bSYour Name 
462*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
463*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
464*5113495bSYour Name 	if (!green_ap_ctx) {
465*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
466*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
467*5113495bSYour Name 	}
468*5113495bSYour Name 
469*5113495bSYour Name 	green_ap_debug("Green AP del sta received");
470*5113495bSYour Name 
471*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
472*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
473*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
474*5113495bSYour Name 		green_ap_debug("enhanced green ap support is enabled");
475*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
476*5113495bSYour Name 	}
477*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
478*5113495bSYour Name 
479*5113495bSYour Name 	return wlan_green_ap_state_mc(green_ap_ctx,
480*5113495bSYour Name 				      WLAN_GREEN_AP_DEL_STA_EVENT);
481*5113495bSYour Name }
482*5113495bSYour Name 
wlan_green_ap_del_multistream_sta(struct wlan_objmgr_pdev * pdev)483*5113495bSYour Name QDF_STATUS wlan_green_ap_del_multistream_sta(struct wlan_objmgr_pdev *pdev)
484*5113495bSYour Name {
485*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
486*5113495bSYour Name 
487*5113495bSYour Name 	if (!pdev) {
488*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
489*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
490*5113495bSYour Name 	}
491*5113495bSYour Name 
492*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
493*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
494*5113495bSYour Name 	if (!green_ap_ctx) {
495*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
496*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
497*5113495bSYour Name 	}
498*5113495bSYour Name 
499*5113495bSYour Name 	green_ap_debug("Green AP del multistream sta received");
500*5113495bSYour Name 
501*5113495bSYour Name 	qdf_spin_lock_bh(&green_ap_ctx->lock);
502*5113495bSYour Name 	if (wlan_is_egap_enabled(green_ap_ctx)) {
503*5113495bSYour Name 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
504*5113495bSYour Name 		green_ap_info("enhanced green ap support is enabled");
505*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
506*5113495bSYour Name 	}
507*5113495bSYour Name 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
508*5113495bSYour Name 
509*5113495bSYour Name 	return wlan_green_ap_state_mc(green_ap_ctx,
510*5113495bSYour Name 			WLAN_GREEN_AP_DEL_MULTISTREAM_STA_EVENT);
511*5113495bSYour Name }
512*5113495bSYour Name 
wlan_green_ap_is_ps_enabled(struct wlan_objmgr_pdev * pdev)513*5113495bSYour Name bool wlan_green_ap_is_ps_enabled(struct wlan_objmgr_pdev *pdev)
514*5113495bSYour Name {
515*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
516*5113495bSYour Name 
517*5113495bSYour Name 	if (!pdev) {
518*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
519*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
520*5113495bSYour Name 	}
521*5113495bSYour Name 
522*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
523*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
524*5113495bSYour Name 	if (!green_ap_ctx) {
525*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
526*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
527*5113495bSYour Name 	}
528*5113495bSYour Name 
529*5113495bSYour Name 	if ((green_ap_ctx->ps_state == WLAN_GREEN_AP_PS_ON_STATE) &&
530*5113495bSYour Name 			(green_ap_ctx->ps_enable))
531*5113495bSYour Name 		return true;
532*5113495bSYour Name 
533*5113495bSYour Name 	return false;
534*5113495bSYour Name 
535*5113495bSYour Name }
536*5113495bSYour Name 
wlan_green_ap_suspend_handle(struct wlan_objmgr_pdev * pdev)537*5113495bSYour Name void wlan_green_ap_suspend_handle(struct wlan_objmgr_pdev *pdev)
538*5113495bSYour Name {
539*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
540*5113495bSYour Name 
541*5113495bSYour Name 	if (!pdev) {
542*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
543*5113495bSYour Name 		return;
544*5113495bSYour Name 	}
545*5113495bSYour Name 
546*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
547*5113495bSYour Name 				pdev, WLAN_UMAC_COMP_GREEN_AP);
548*5113495bSYour Name 
549*5113495bSYour Name 	if (!green_ap_ctx) {
550*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
551*5113495bSYour Name 		return;
552*5113495bSYour Name 	}
553*5113495bSYour Name 
554*5113495bSYour Name 	wlan_green_ap_stop(pdev);
555*5113495bSYour Name 
556*5113495bSYour Name 	green_ap_ctx->ps_enable = WLAN_GREEN_AP_PS_SUSPEND;
557*5113495bSYour Name }
558*5113495bSYour Name 
wlan_green_ap_is_ps_waiting(struct wlan_objmgr_pdev * pdev)559*5113495bSYour Name bool wlan_green_ap_is_ps_waiting(struct wlan_objmgr_pdev *pdev)
560*5113495bSYour Name {
561*5113495bSYour Name 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
562*5113495bSYour Name 
563*5113495bSYour Name 	if (!pdev) {
564*5113495bSYour Name 		green_ap_err("pdev context passed is NULL");
565*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
566*5113495bSYour Name 	}
567*5113495bSYour Name 
568*5113495bSYour Name 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
569*5113495bSYour Name 			pdev, WLAN_UMAC_COMP_GREEN_AP);
570*5113495bSYour Name 	if (!green_ap_ctx) {
571*5113495bSYour Name 		green_ap_err("green ap context obtained is NULL");
572*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
573*5113495bSYour Name 	}
574*5113495bSYour Name 
575*5113495bSYour Name 	if ((green_ap_ctx->ps_state == WLAN_GREEN_AP_PS_WAIT_STATE) &&
576*5113495bSYour Name 	    (green_ap_ctx->ps_enable)) {
577*5113495bSYour Name 		return true;
578*5113495bSYour Name 	}
579*5113495bSYour Name 
580*5113495bSYour Name 	return false;
581*5113495bSYour Name }
582