1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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 /**
21  * DOC: This file contains green ap north bound interface definitions
22  */
23 
24 #include <qdf_status.h>
25 #include <wlan_green_ap_ucfg_api.h>
26 #include <../../core/src/wlan_green_ap_main_i.h>
27 
ucfg_green_ap_enable_egap(struct wlan_objmgr_pdev * pdev)28 QDF_STATUS ucfg_green_ap_enable_egap(struct wlan_objmgr_pdev *pdev)
29 {
30 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
31 	struct wlan_lmac_if_green_ap_tx_ops *green_ap_tx_ops;
32 
33 	if (!pdev) {
34 		green_ap_err("pdev context passed is NULL");
35 		return QDF_STATUS_E_INVAL;
36 	}
37 
38 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
39 			pdev, WLAN_UMAC_COMP_GREEN_AP);
40 	if (!green_ap_ctx) {
41 		green_ap_err("green ap context obtained is NULL");
42 		return QDF_STATUS_E_FAILURE;
43 	}
44 
45 	green_ap_tx_ops = wlan_psoc_get_green_ap_tx_ops(green_ap_ctx);
46 	if (!green_ap_tx_ops) {
47 		green_ap_err("green ap tx ops obtained are NULL");
48 		return  QDF_STATUS_E_FAILURE;
49 	}
50 
51 	if (!green_ap_tx_ops->enable_egap) {
52 		green_ap_err("tx op for sending enable/disable green ap is NULL");
53 		return QDF_STATUS_E_FAILURE;
54 	}
55 
56 	return green_ap_tx_ops->enable_egap(pdev, &green_ap_ctx->egap_params);
57 }
58 
ucfg_green_ap_set_ps_config(struct wlan_objmgr_pdev * pdev,uint8_t value)59 QDF_STATUS ucfg_green_ap_set_ps_config(struct wlan_objmgr_pdev *pdev,
60 				       uint8_t value)
61 {
62 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
63 
64 	if (!pdev) {
65 		green_ap_err("pdev context passed is NULL");
66 		return QDF_STATUS_E_INVAL;
67 	}
68 
69 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
70 			pdev, WLAN_UMAC_COMP_GREEN_AP);
71 	if (!green_ap_ctx) {
72 		green_ap_err("green ap context obtained is NULL");
73 		return QDF_STATUS_E_FAILURE;
74 	}
75 
76 	qdf_spin_lock_bh(&green_ap_ctx->lock);
77 	if (wlan_is_egap_enabled(green_ap_ctx)) {
78 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
79 		return QDF_STATUS_SUCCESS;
80 	}
81 
82 	green_ap_ctx->ps_enable = value;
83 	if (value == WLAN_GREEN_AP_MODE_NUM_STREAM)
84 		green_ap_ctx->ps_mode = WLAN_GREEN_AP_MODE_NUM_STREAM;
85 	else
86 		green_ap_ctx->ps_mode = WLAN_GREEN_AP_MODE_NO_STA;
87 
88 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
89 
90 	return QDF_STATUS_SUCCESS;
91 }
92 
93 #ifdef WLAN_SUPPORT_GAP_LL_PS_MODE
94 #define MAX_COOKIE_ID 256
95 
ucfg_green_ap_ll_ps(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_green_ap_ll_ps_state state,uint32_t bcn_interval,uint64_t * cookie_id)96 QDF_STATUS ucfg_green_ap_ll_ps(struct wlan_objmgr_pdev *pdev,
97 			       struct wlan_objmgr_vdev *vdev,
98 			       enum wlan_green_ap_ll_ps_state state,
99 			       uint32_t bcn_interval,
100 			       uint64_t *cookie_id)
101 {
102 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
103 	struct wlan_lmac_if_green_ap_tx_ops *green_ap_tx_ops;
104 	struct green_ap_ll_ps_cmd_param green_ap_ll_ps_params;
105 
106 	if (!pdev) {
107 		green_ap_err("pdev context passed is NULL");
108 		return QDF_STATUS_E_INVAL;
109 	}
110 
111 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
112 			pdev, WLAN_UMAC_COMP_GREEN_AP);
113 	if (!green_ap_ctx) {
114 		green_ap_err("green ap context obtained is NULL");
115 		return QDF_STATUS_E_FAILURE;
116 	}
117 
118 	green_ap_tx_ops = wlan_psoc_get_green_ap_tx_ops(green_ap_ctx);
119 	if (!green_ap_tx_ops) {
120 		green_ap_err("green ap tx ops obtained are NULL");
121 		return  QDF_STATUS_E_FAILURE;
122 	}
123 
124 	if (!green_ap_tx_ops->ll_ps) {
125 		green_ap_err("tx op for sending green ap ll pwr save is NULL");
126 		return QDF_STATUS_E_FAILURE;
127 	}
128 
129 	green_ap_ctx->vdev = vdev;
130 	green_ap_ll_ps_params.state = state;
131 	green_ap_ll_ps_params.bcn_interval = bcn_interval;
132 
133 	if (state)
134 		green_ap_ll_ps_params.bcn_interval *=
135 			green_ap_ctx->bcn_mult;
136 
137 	green_ap_ll_ps_params.cookie =
138 		wlan_green_ap_get_cookie_id(
139 				green_ap_ctx,
140 				(enum wlan_green_ap_ll_ps_state)state);
141 
142 	*cookie_id = green_ap_ll_ps_params.cookie;
143 
144 	return green_ap_tx_ops->ll_ps(vdev, &green_ap_ll_ps_params);
145 }
146 #endif
147 
ucfg_green_ap_get_ps_config(struct wlan_objmgr_pdev * pdev,uint8_t * ps_enable)148 QDF_STATUS ucfg_green_ap_get_ps_config(struct wlan_objmgr_pdev *pdev,
149 				       uint8_t *ps_enable)
150 {
151 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
152 
153 	if (!pdev) {
154 		green_ap_err("pdev context passed is NULL");
155 		return QDF_STATUS_E_INVAL;
156 	}
157 
158 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
159 				pdev, WLAN_UMAC_COMP_GREEN_AP);
160 
161 	if (!green_ap_ctx) {
162 		green_ap_err("green ap context obtained is NULL");
163 		return QDF_STATUS_E_FAILURE;
164 	}
165 
166 	qdf_spin_lock_bh(&green_ap_ctx->lock);
167 	if (wlan_is_egap_enabled(green_ap_ctx)) {
168 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
169 		return QDF_STATUS_SUCCESS;
170 	}
171 
172 	*ps_enable = green_ap_ctx->ps_enable;
173 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
174 
175 	return QDF_STATUS_SUCCESS;
176 }
177 
ucfg_green_ap_set_transition_time(struct wlan_objmgr_pdev * pdev,uint32_t val)178 QDF_STATUS ucfg_green_ap_set_transition_time(struct wlan_objmgr_pdev *pdev,
179 					     uint32_t val)
180 {
181 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
182 
183 	if (!pdev) {
184 		green_ap_err("pdev context passed is NULL");
185 		return QDF_STATUS_E_INVAL;
186 	}
187 
188 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
189 			pdev, WLAN_UMAC_COMP_GREEN_AP);
190 
191 	if (!green_ap_ctx) {
192 		green_ap_err("green ap context obtained is NULL");
193 		return QDF_STATUS_E_FAILURE;
194 	}
195 
196 	qdf_spin_lock_bh(&green_ap_ctx->lock);
197 	if (wlan_is_egap_enabled(green_ap_ctx)) {
198 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
199 		return QDF_STATUS_SUCCESS;
200 	}
201 
202 	green_ap_ctx->ps_trans_time = val;
203 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
204 
205 	return QDF_STATUS_SUCCESS;
206 }
207 
ucfg_green_ap_get_transition_time(struct wlan_objmgr_pdev * pdev,uint32_t * ps_trans_time)208 QDF_STATUS ucfg_green_ap_get_transition_time(struct wlan_objmgr_pdev *pdev,
209 					     uint32_t *ps_trans_time)
210 {
211 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
212 
213 	if (!pdev) {
214 		green_ap_err("pdev context passed is NULL");
215 		return QDF_STATUS_E_INVAL;
216 	}
217 
218 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
219 			pdev, WLAN_UMAC_COMP_GREEN_AP);
220 
221 	if (!green_ap_ctx) {
222 		green_ap_err("green ap context obtained is NULL");
223 		return QDF_STATUS_E_FAILURE;
224 	}
225 
226 	qdf_spin_lock_bh(&green_ap_ctx->lock);
227 	if (wlan_is_egap_enabled(green_ap_ctx)) {
228 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
229 		return QDF_STATUS_SUCCESS;
230 	}
231 
232 	*ps_trans_time = green_ap_ctx->ps_trans_time;
233 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
234 
235 	return QDF_STATUS_SUCCESS;
236 }
237 
ucfg_green_ap_config(struct wlan_objmgr_pdev * pdev,uint8_t val)238 QDF_STATUS ucfg_green_ap_config(struct wlan_objmgr_pdev *pdev, uint8_t val)
239 {
240 
241 	uint8_t flag;
242 
243 	if (wlan_green_ap_get_capab(pdev) == QDF_STATUS_E_NOSUPPORT) {
244 		green_ap_err("GreenAP not supported on radio\n");
245 		return QDF_STATUS_E_NOSUPPORT;
246 	}
247 
248 	if (val) {
249 		struct wlan_pdev_green_ap_ctx *green_ap_ctx;
250 
251 		wlan_objmgr_pdev_iterate_obj_list(pdev,
252 					WLAN_VDEV_OP,
253 					wlan_green_ap_check_mode,
254 					&flag, 0, WLAN_GREEN_AP_ID);
255 		if (flag == 1) {
256 			green_ap_err("Radio not in AP/RE mode."
257 					"Feature not supported");
258 			return QDF_STATUS_E_NOSUPPORT;
259 		}
260 
261 		green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(pdev,
262 					WLAN_UMAC_COMP_GREEN_AP);
263 
264 		if (!green_ap_ctx) {
265 			green_ap_err("green ap context obtained is NULL");
266 			return QDF_STATUS_E_NOSUPPORT;
267 		}
268 
269 		ucfg_green_ap_set_ps_config(pdev, val);
270 
271 		if (wlan_util_is_vdev_active(pdev, WLAN_GREEN_AP_ID) ==
272 					    QDF_STATUS_SUCCESS)
273 			wlan_green_ap_start(pdev);
274 	} else {
275 		wlan_green_ap_stop(pdev);
276 	}
277 
278 	return QDF_STATUS_SUCCESS;
279 }
280 
ucfg_green_ap_enable_debug_prints(struct wlan_objmgr_pdev * pdev,uint32_t val)281 void ucfg_green_ap_enable_debug_prints(struct wlan_objmgr_pdev *pdev,
282 				uint32_t val)
283 {
284 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
285 
286 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
287 			pdev, WLAN_UMAC_COMP_GREEN_AP);
288 
289 	if (!green_ap_ctx) {
290 		green_ap_err("green ap context obtained is NULL");
291 		return;
292 	}
293 
294 	green_ap_ctx->dbg_enable = val;
295 }
296 
ucfg_green_ap_get_debug_prints(struct wlan_objmgr_pdev * pdev)297 bool ucfg_green_ap_get_debug_prints(struct wlan_objmgr_pdev *pdev)
298 {
299 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
300 
301 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
302 			pdev, WLAN_UMAC_COMP_GREEN_AP);
303 
304 	if (!green_ap_ctx) {
305 		green_ap_err("green ap context obtained is NULL");
306 		return false;
307 	}
308 
309 	return green_ap_ctx->dbg_enable;
310 }
311 
312