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