1 /*
2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /*
18 * DOC: contains EPCS (Emergency Preparedness Communications Service)
19 * related functionality
20 */
21 #include <wlan_cmn.h>
22 #include <wlan_cm_public_struct.h>
23 #include "wlan_epcs_api.h"
24 #include <wlan_mlo_epcs.h>
25 #include "wlan_cm_api.h"
26 #include "wlan_mlo_mgr_roam.h"
27 #include "wlan_cmn_ieee80211.h"
28 #include "dot11f.h"
29
30 #define EPCS_MIN_DIALOG_TOKEN 1
31 #define EPCS_MAX_DIALOG_TOKEN 0xFF
32
33 static struct ac_param_record default_epcs_edca[] = {
34 #ifndef ANI_LITTLE_BIT_ENDIAN
35 /* The txop is multiple of 32us units */
36 {0x07, 0x95, 79 /* 2.528ms */},
37 {0x03, 0x95, 79 /* 2.528ms */},
38 {0x02, 0x54, 128 /* 4.096ms */},
39 {0x02, 0x43, 65 /* 2.080ms */}
40 #else
41 {0x70, 0x59, 79 /* 2.528ms */},
42 {0x30, 0x59, 79 /* 2.528ms */},
43 {0x20, 0x45, 128 /* 4.096ms */},
44 {0x20, 0x34, 65 /* 2.080ms */}
45 #endif
46 };
47
48 static
epcs_get_event_str(enum wlan_epcs_evt event)49 const char *epcs_get_event_str(enum wlan_epcs_evt event)
50 {
51 if (event > WLAN_EPCS_EV_ACTION_FRAME_MAX)
52 return "";
53
54 switch (event) {
55 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_RX_REQ);
56 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_TX_RESP);
57 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_TX_REQ);
58 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_RX_RESP);
59 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_RX_TEARDOWN);
60 CASE_RETURN_STRING(WLAN_EPCS_EV_ACTION_FRAME_TX_TEARDOWN);
61 default:
62 return "Unknown";
63 }
64 }
65
66 static uint8_t
epcs_gen_dialog_token(struct wlan_mlo_peer_epcs_info * epcs_info)67 epcs_gen_dialog_token(struct wlan_mlo_peer_epcs_info *epcs_info)
68 {
69 if (!epcs_info)
70 return 0;
71
72 if (epcs_info->self_gen_dialog_token == EPCS_MAX_DIALOG_TOKEN)
73 /* wrap is ok */
74 epcs_info->self_gen_dialog_token = EPCS_MIN_DIALOG_TOKEN;
75 else
76 epcs_info->self_gen_dialog_token += 1;
77
78 mlme_debug("gen dialog token %d", epcs_info->self_gen_dialog_token);
79 return epcs_info->self_gen_dialog_token;
80 }
81
epcs_update_ac_value(tSirMacEdcaParamRecord * edca,struct ac_param_record * epcs)82 static void epcs_update_ac_value(tSirMacEdcaParamRecord *edca,
83 struct ac_param_record *epcs)
84 {
85 edca->aci.rsvd = epcs->aci_aifsn >> RSVD_SHIFT_BIT & RSVD_MASK;
86 edca->aci.aci = epcs->aci_aifsn >> ACI_SHIFT_BIT & ACI_MASK;
87 edca->aci.acm = epcs->aci_aifsn >> ACM_SHIFT_BIT & ACM_MASK;
88 edca->aci.aifsn = epcs->aci_aifsn >> AIFSN_SHIFT_BIT & AIFSN_MASK;
89
90 edca->cw.max = epcs->ecw_min_max >> CWMAX_SHIFT_BIT & CWMAX_MASK;
91 edca->cw.min = epcs->ecw_min_max >> CWMIN_SHIFT_BIT & CWMIN_MASK;
92
93 edca->txoplimit = epcs->txop_limit;
94 mlme_debug("edca rsvd %d, aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
95 edca->aci.rsvd, edca->aci.aci, edca->aci.acm,
96 edca->aci.aifsn, edca->cw.max, edca->cw.min);
97 }
98
epcs_update_mu_ac_value(tSirMacEdcaParamRecord * edca,struct muac_param_record * epcs)99 static void epcs_update_mu_ac_value(tSirMacEdcaParamRecord *edca,
100 struct muac_param_record *epcs)
101 {
102 edca->aci.rsvd = epcs->aci_aifsn >> RSVD_SHIFT_BIT & RSVD_MASK;
103 edca->aci.aci = epcs->aci_aifsn >> ACI_SHIFT_BIT & ACI_MASK;
104 edca->aci.acm = epcs->aci_aifsn >> ACM_SHIFT_BIT & ACM_MASK;
105 edca->aci.aifsn = epcs->aci_aifsn >> AIFSN_SHIFT_BIT & AIFSN_MASK;
106
107 edca->cw.max = epcs->ecw_min_max >> CWMAX_SHIFT_BIT & CWMAX_MASK;
108 edca->cw.min = epcs->ecw_min_max >> CWMIN_SHIFT_BIT & CWMIN_MASK;
109
110 edca->txoplimit = epcs->mu_edca_timer;
111 mlme_debug("muac rsvd %d, aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
112 edca->aci.rsvd, edca->aci.aci, edca->aci.acm,
113 edca->aci.aifsn, edca->cw.max, edca->cw.min);
114 }
115
116 static QDF_STATUS
epcs_update_def_edca_param(struct wlan_objmgr_vdev * vdev)117 epcs_update_def_edca_param(struct wlan_objmgr_vdev *vdev)
118 {
119 int i;
120 struct mac_context *mac_ctx;
121 tSirMacEdcaParamRecord edca[QCA_WLAN_AC_ALL] = {0};
122
123 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
124 if (!mac_ctx)
125 return QDF_STATUS_E_INVAL;
126
127 for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
128 epcs_update_ac_value(&edca[i], &default_epcs_edca[i]);
129 edca[i].no_ack = mac_ctx->no_ack_policy_cfg[i];
130 }
131
132 mlme_debug("using default edca info");
133 return lim_send_epcs_update_edca_params(vdev, edca, false);
134 }
135
136 static QDF_STATUS
epcs_update_edca_param(struct wlan_objmgr_vdev * vdev,struct edca_ie * edca_ie)137 epcs_update_edca_param(struct wlan_objmgr_vdev *vdev,
138 struct edca_ie *edca_ie)
139 {
140 struct mac_context *mac_ctx;
141 struct ac_param_record *ac_record;
142 tSirMacEdcaParamRecord edca[QCA_WLAN_AC_ALL] = {0};
143 int i;
144
145 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
146 if (!mac_ctx)
147 return QDF_STATUS_E_INVAL;
148
149 if (edca_ie->ie != DOT11F_EID_EDCAPARAMSET ||
150 edca_ie->len != DOT11F_IE_EDCAPARAMSET_MIN_LEN) {
151 mlme_debug("edca info is not valid or not exist");
152 return QDF_STATUS_E_INVAL;
153 }
154
155 ac_record = edca_ie->ac_record;
156 for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
157 epcs_update_ac_value(&edca[i], &ac_record[i]);
158 edca[i].no_ack = mac_ctx->no_ack_policy_cfg[i];
159 }
160
161 return lim_send_epcs_update_edca_params(vdev, edca, false);
162 }
163
164 static QDF_STATUS
epcs_update_ven_wmm_param(struct wlan_objmgr_vdev * vdev,uint8_t * ven_wme_ie)165 epcs_update_ven_wmm_param(struct wlan_objmgr_vdev *vdev, uint8_t *ven_wme_ie)
166 {
167 struct mac_context *mac_ctx;
168 tDot11fIEWMMParams wmm_para = {0};
169 tSirMacEdcaParamRecord edca[QCA_WLAN_AC_ALL] = {0};
170 uint32_t status;
171
172 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
173 if (!mac_ctx)
174 return QDF_STATUS_E_INVAL;
175
176 status = dot11f_unpack_ie_wmm_params(mac_ctx,
177 ven_wme_ie + WMM_VENDOR_HEADER_LEN,
178 DOT11F_IE_WMMPARAMS_MIN_LEN,
179 &wmm_para, false);
180 if (status != DOT11F_PARSE_SUCCESS) {
181 mlme_debug("EPCS parsing wmm ie error");
182 return QDF_STATUS_E_INVAL;
183 }
184
185 edca[QCA_WLAN_AC_BE].aci.rsvd = wmm_para.unused1;
186 edca[QCA_WLAN_AC_BE].aci.aci = wmm_para.acbe_aci;
187 edca[QCA_WLAN_AC_BE].aci.acm = wmm_para.acbe_acm;
188 edca[QCA_WLAN_AC_BE].aci.aifsn = wmm_para.acbe_aifsn;
189 edca[QCA_WLAN_AC_BE].cw.max = wmm_para.acbe_acwmax;
190 edca[QCA_WLAN_AC_BE].cw.min = wmm_para.acbe_acwmin;
191 edca[QCA_WLAN_AC_BE].txoplimit = wmm_para.acbe_txoplimit;
192 edca[QCA_WLAN_AC_BE].no_ack =
193 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BE];
194 mlme_debug("WMM BE aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
195 edca[QCA_WLAN_AC_BE].aci.aci,
196 edca[QCA_WLAN_AC_BE].aci.acm,
197 edca[QCA_WLAN_AC_BE].aci.aifsn,
198 edca[QCA_WLAN_AC_BE].cw.max,
199 edca[QCA_WLAN_AC_BE].cw.min);
200
201 edca[QCA_WLAN_AC_BK].aci.rsvd = wmm_para.unused2;
202 edca[QCA_WLAN_AC_BK].aci.aci = wmm_para.acbk_aci;
203 edca[QCA_WLAN_AC_BK].aci.acm = wmm_para.acbk_acm;
204 edca[QCA_WLAN_AC_BK].aci.aifsn = wmm_para.acbk_aifsn;
205 edca[QCA_WLAN_AC_BK].cw.max = wmm_para.acbk_acwmax;
206 edca[QCA_WLAN_AC_BK].cw.min = wmm_para.acbk_acwmin;
207 edca[QCA_WLAN_AC_BK].txoplimit = wmm_para.acbk_txoplimit;
208 edca[QCA_WLAN_AC_BK].no_ack =
209 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BK];
210 mlme_debug("WMM BK aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
211 edca[QCA_WLAN_AC_BK].aci.aci,
212 edca[QCA_WLAN_AC_BK].aci.acm,
213 edca[QCA_WLAN_AC_BK].aci.aifsn,
214 edca[QCA_WLAN_AC_BK].cw.max,
215 edca[QCA_WLAN_AC_BK].cw.min);
216
217 edca[QCA_WLAN_AC_VI].aci.rsvd = wmm_para.unused3;
218 edca[QCA_WLAN_AC_VI].aci.aci = wmm_para.acvi_aci;
219 edca[QCA_WLAN_AC_VI].aci.acm = wmm_para.acvi_acm;
220 edca[QCA_WLAN_AC_VI].aci.aifsn = wmm_para.acvi_aifsn;
221 edca[QCA_WLAN_AC_VI].cw.max = wmm_para.acvi_acwmax;
222 edca[QCA_WLAN_AC_VI].cw.min = wmm_para.acvi_acwmin;
223 edca[QCA_WLAN_AC_VI].txoplimit = wmm_para.acvi_txoplimit;
224 edca[QCA_WLAN_AC_VI].no_ack =
225 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VI];
226 mlme_debug("WMM VI aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
227 edca[QCA_WLAN_AC_VI].aci.aci,
228 edca[QCA_WLAN_AC_VI].aci.acm,
229 edca[QCA_WLAN_AC_VI].aci.aifsn,
230 edca[QCA_WLAN_AC_VI].cw.max,
231 edca[QCA_WLAN_AC_VI].cw.min);
232
233 edca[QCA_WLAN_AC_VO].aci.rsvd = wmm_para.unused4;
234 edca[QCA_WLAN_AC_VO].aci.aci = wmm_para.acvo_aci;
235 edca[QCA_WLAN_AC_VO].aci.acm = wmm_para.acvo_acm;
236 edca[QCA_WLAN_AC_VO].aci.aifsn = wmm_para.acvo_aifsn;
237 edca[QCA_WLAN_AC_VO].cw.max = wmm_para.acvo_acwmax;
238 edca[QCA_WLAN_AC_VO].cw.min = wmm_para.acvo_acwmin;
239 edca[QCA_WLAN_AC_VO].txoplimit = wmm_para.acvo_txoplimit;
240 edca[QCA_WLAN_AC_VO].no_ack =
241 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VO];
242 mlme_debug("WMM VO aci %d, acm %d, aifsn %d, cwmax %d, cwmin %d",
243 edca[QCA_WLAN_AC_VO].aci.aci,
244 edca[QCA_WLAN_AC_VO].aci.acm,
245 edca[QCA_WLAN_AC_VO].aci.aifsn,
246 edca[QCA_WLAN_AC_VO].cw.max,
247 edca[QCA_WLAN_AC_VO].cw.min);
248
249 return lim_send_epcs_update_edca_params(vdev, edca, false);
250 }
251
252 static QDF_STATUS
epcs_update_mu_edca_param(struct wlan_objmgr_vdev * vdev,struct muedca_ie * muedca)253 epcs_update_mu_edca_param(struct wlan_objmgr_vdev *vdev,
254 struct muedca_ie *muedca)
255 {
256 struct mac_context *mac_ctx;
257 struct muac_param_record *mu_record;
258 tSirMacEdcaParamRecord edca[QCA_WLAN_AC_ALL] = {0};
259 int i;
260
261 if (muedca->elem_id != DOT11F_EID_MU_EDCA_PARAM_SET ||
262 muedca->elem_len != (DOT11F_IE_MU_EDCA_PARAM_SET_MIN_LEN + 1)) {
263 mlme_debug("mu edca info for epcs is not valid or not exist");
264 return QDF_STATUS_SUCCESS;
265 }
266
267 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
268 if (!mac_ctx)
269 return QDF_STATUS_E_INVAL;
270
271 mu_record = muedca->mu_record;
272 for (i = 0; i < QCA_WLAN_AC_ALL; i++) {
273 epcs_update_mu_ac_value(&edca[i], &mu_record[i]);
274 edca[i].no_ack = mac_ctx->no_ack_policy_cfg[i];
275 }
276
277 return lim_send_epcs_update_edca_params(vdev, edca, true);
278 }
279
280 static QDF_STATUS
epcs_restore_edca_param(struct wlan_objmgr_vdev * vdev)281 epcs_restore_edca_param(struct wlan_objmgr_vdev *vdev)
282 {
283 struct wlan_objmgr_vdev *link_vdev;
284 struct wlan_mlo_dev_context *mlo_dev_ctx;
285 int i;
286
287 if (!vdev)
288 return QDF_STATUS_E_INVAL;
289
290 mlo_dev_ctx = vdev->mlo_dev_ctx;
291 if (!mlo_dev_ctx)
292 return QDF_STATUS_E_INVAL;
293
294 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
295 link_vdev = mlo_dev_ctx->wlan_vdev_list[i];
296 if (!link_vdev)
297 continue;
298 lim_send_epcs_restore_edca_params(link_vdev);
299 }
300
301 return QDF_STATUS_SUCCESS;
302 }
303
epcs_handle_rx_req(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint32_t len)304 static QDF_STATUS epcs_handle_rx_req(struct wlan_objmgr_vdev *vdev,
305 struct wlan_objmgr_peer *peer,
306 void *event_data, uint32_t len)
307 {
308 struct wlan_mlo_peer_context *ml_peer;
309 struct wlan_mlo_peer_epcs_info *epcs_info;
310 struct wlan_epcs_info epcs_req = {0};
311 struct wlan_action_frame_args args;
312 struct ml_pa_info *edca_info;
313 struct ml_pa_partner_link_info *link;
314 struct wlan_objmgr_vdev *link_vdev;
315 uint32_t i;
316 QDF_STATUS status;
317
318 if (!vdev || !peer)
319 return QDF_STATUS_E_INVAL;
320
321 ml_peer = peer->mlo_peer_ctx;
322 if (!ml_peer)
323 return QDF_STATUS_E_FAILURE;
324
325 epcs_info = &ml_peer->epcs_info;
326 if (epcs_info->state == EPCS_ENABLE) {
327 mlme_err("EPCS has been enable, ignore the req.");
328 return QDF_STATUS_E_ALREADY;
329 }
330
331 status = wlan_mlo_parse_epcs_action_frame(&epcs_req, event_data, len);
332 if (status != QDF_STATUS_SUCCESS) {
333 mlme_err("Unable to parse EPCS request action frame");
334 return QDF_STATUS_E_FAILURE;
335 }
336
337 epcs_info->self_gen_dialog_token = epcs_req.dialog_token;
338 edca_info = &epcs_req.pa_info;
339 for (i = 0; i < edca_info->num_links; i++) {
340 link = &edca_info->link_info[i];
341 link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id,
342 WLAN_MLO_MGR_ID);
343 if (!link_vdev)
344 continue;
345
346 if (link->edca_ie_present)
347 epcs_update_edca_param(link_vdev, &link->edca);
348 else if (link->ven_wme_ie_present)
349 epcs_update_ven_wmm_param(link_vdev,
350 &link->ven_wme_ie_bytes[0]);
351 else
352 epcs_update_def_edca_param(link_vdev);
353
354 if (link->muedca_ie_present)
355 epcs_update_mu_edca_param(link_vdev, &link->muedca);
356
357 wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLO_MGR_ID);
358 }
359
360 args.category = ACTION_CATEGORY_PROTECTED_EHT;
361 args.action = EHT_EPCS_RESPONSE;
362 args.arg1 = epcs_info->self_gen_dialog_token;
363 args.arg2 = QDF_STATUS_SUCCESS;
364
365 status = lim_send_epcs_action_rsp_frame(vdev,
366 wlan_peer_get_macaddr(peer),
367 &args);
368 if (status != QDF_STATUS_SUCCESS) {
369 mlme_err("Send EPCS response frame error");
370 epcs_restore_edca_param(vdev);
371 } else {
372 epcs_info->state = EPCS_ENABLE;
373 mlme_debug("EPCS (responder) state: Teardown -> Enable");
374 }
375
376 return status;
377 }
378
epcs_handle_rx_resp(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint32_t len)379 static QDF_STATUS epcs_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
380 struct wlan_objmgr_peer *peer,
381 void *event_data, uint32_t len)
382 {
383 struct wlan_mlo_peer_context *ml_peer;
384 struct wlan_mlo_peer_epcs_info *epcs_info;
385 struct wlan_epcs_info epcs_rsp = {0};
386 struct ml_pa_info *edca_info;
387 struct ml_pa_partner_link_info *link;
388 struct wlan_objmgr_vdev *link_vdev;
389 uint32_t i;
390 QDF_STATUS status;
391
392 if (!vdev || !peer)
393 return QDF_STATUS_E_NULL_VALUE;
394
395 ml_peer = peer->mlo_peer_ctx;
396 if (!ml_peer)
397 return QDF_STATUS_E_NULL_VALUE;
398
399 epcs_info = &ml_peer->epcs_info;
400 if (epcs_info->state == EPCS_ENABLE) {
401 mlme_err("EPCS has been enable, ignore the rsp.");
402 return QDF_STATUS_E_ALREADY;
403 }
404
405 status = wlan_mlo_parse_epcs_action_frame(&epcs_rsp, event_data, len);
406 if (status != QDF_STATUS_SUCCESS) {
407 mlme_err("Unable to parse EPCS response action frame");
408 return QDF_STATUS_E_FAILURE;
409 }
410
411 if (epcs_info->self_gen_dialog_token != epcs_rsp.dialog_token) {
412 mlme_err("epcs rsp dialog token %d does not match",
413 epcs_rsp.dialog_token);
414 return QDF_STATUS_E_FAILURE;
415 }
416
417 if (epcs_rsp.status) {
418 mlme_err("epcs rsp status error %d", epcs_rsp.status);
419 return QDF_STATUS_E_FAILURE;
420 }
421
422 edca_info = &epcs_rsp.pa_info;
423 for (i = 0; i < edca_info->num_links; i++) {
424 link = &edca_info->link_info[i];
425 link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id,
426 WLAN_MLO_MGR_ID);
427 if (!link_vdev)
428 continue;
429
430 if (link->edca_ie_present)
431 epcs_update_edca_param(link_vdev, &link->edca);
432 else if (link->ven_wme_ie_present)
433 epcs_update_ven_wmm_param(link_vdev,
434 &link->ven_wme_ie_bytes[0]);
435 else
436 epcs_update_def_edca_param(link_vdev);
437
438 if (link->muedca_ie_present)
439 epcs_update_mu_edca_param(link_vdev, &link->muedca);
440
441 wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLO_MGR_ID);
442 }
443
444 epcs_info->state = EPCS_ENABLE;
445 mlme_debug("EPCS (initiator) state: Teardown -> Enable");
446
447 return status;
448 }
449
epcs_handle_rx_teardown(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint32_t len)450 static QDF_STATUS epcs_handle_rx_teardown(struct wlan_objmgr_vdev *vdev,
451 struct wlan_objmgr_peer *peer,
452 void *event_data, uint32_t len)
453 {
454 struct wlan_mlo_peer_context *ml_peer;
455 struct wlan_mlo_peer_epcs_info *epcs_info;
456 struct wlan_epcs_info epcs_req = {0};
457 struct mac_context *mac_ctx;
458 QDF_STATUS status;
459
460 if (!vdev || !peer)
461 return QDF_STATUS_E_INVAL;
462
463 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
464 if (!mac_ctx)
465 return QDF_STATUS_E_INVAL;
466
467 ml_peer = peer->mlo_peer_ctx;
468 if (!ml_peer)
469 return QDF_STATUS_E_FAILURE;
470
471 epcs_info = &ml_peer->epcs_info;
472 if (epcs_info->state == EPCS_DOWN) {
473 mlme_err("EPCS has been down, ignore the teardown req.");
474 return QDF_STATUS_E_ALREADY;
475 }
476
477 status = wlan_mlo_parse_epcs_action_frame(&epcs_req, event_data, len);
478 if (status != QDF_STATUS_SUCCESS) {
479 mlme_err("Unable to parse EPCS teardown action frame");
480 return QDF_STATUS_E_FAILURE;
481 }
482
483 epcs_restore_edca_param(vdev);
484
485 epcs_info->state = EPCS_DOWN;
486 mlme_debug("EPCS state: Enale -> Teardown.");
487
488 return QDF_STATUS_SUCCESS;
489 }
490
epcs_handle_tx_req(struct wlan_objmgr_vdev * vdev)491 static QDF_STATUS epcs_handle_tx_req(struct wlan_objmgr_vdev *vdev)
492 {
493 struct wlan_mlo_peer_context *ml_peer;
494 struct wlan_objmgr_peer *peer;
495 struct wlan_action_frame_args args;
496 struct wlan_mlo_peer_epcs_info *epcs_info;
497 QDF_STATUS status;
498
499 if (!vdev)
500 return QDF_STATUS_E_NULL_VALUE;
501
502 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
503 if (!peer)
504 return QDF_STATUS_E_NULL_VALUE;
505
506 ml_peer = peer->mlo_peer_ctx;
507 if (!ml_peer) {
508 status = QDF_STATUS_E_NULL_VALUE;
509 goto release_peer;
510 }
511
512 epcs_info = &ml_peer->epcs_info;
513 if (epcs_info->state == EPCS_ENABLE) {
514 mlme_err("EPCS has been enable, ignore the req cmd.");
515 status = QDF_STATUS_E_ALREADY;
516 goto release_peer;
517 }
518
519 args.category = ACTION_CATEGORY_PROTECTED_EHT;
520 args.action = EHT_EPCS_REQUEST;
521 args.arg1 = epcs_gen_dialog_token(epcs_info);
522
523 status = lim_send_epcs_action_req_frame(vdev,
524 wlan_peer_get_macaddr(peer),
525 &args);
526 if (QDF_IS_STATUS_ERROR(status))
527 mlme_err("Failed to send EPCS action request frame");
528
529 release_peer:
530 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
531
532 return status;
533 }
534
epcs_handle_tx_teardown(struct wlan_objmgr_vdev * vdev)535 static QDF_STATUS epcs_handle_tx_teardown(struct wlan_objmgr_vdev *vdev)
536 {
537 struct wlan_mlo_peer_context *ml_peer;
538 struct wlan_objmgr_peer *peer;
539 struct wlan_action_frame_args args;
540 struct wlan_mlo_peer_epcs_info *epcs_info;
541 QDF_STATUS status;
542
543 if (!vdev)
544 return QDF_STATUS_E_NULL_VALUE;
545
546 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
547 if (!peer)
548 return QDF_STATUS_E_NULL_VALUE;
549
550 ml_peer = peer->mlo_peer_ctx;
551 if (!ml_peer) {
552 status = QDF_STATUS_E_NULL_VALUE;
553 goto release_peer;
554 }
555
556 epcs_info = &ml_peer->epcs_info;
557 if (epcs_info->state == EPCS_DOWN) {
558 mlme_err("EPCS has been down, ignore the teardwon cmd.");
559 status = QDF_STATUS_E_ALREADY;
560 goto release_peer;
561 }
562
563 args.category = ACTION_CATEGORY_PROTECTED_EHT;
564 args.action = EHT_EPCS_TEARDOWN;
565
566 status =
567 lim_send_epcs_action_teardown_frame(vdev,
568 wlan_peer_get_macaddr(peer),
569 &args);
570 if (QDF_IS_STATUS_ERROR(status)) {
571 mlme_err("Failed to send EPCS tear down frame");
572 } else {
573 epcs_restore_edca_param(vdev);
574 epcs_info->state = EPCS_DOWN;
575 mlme_debug("EPCS state: Enale -> Teardown.");
576 }
577
578 release_peer:
579 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
580
581 return status;
582 }
583
epcs_deliver_event(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,enum wlan_epcs_evt event,void * event_data,uint32_t len)584 static QDF_STATUS epcs_deliver_event(struct wlan_objmgr_vdev *vdev,
585 struct wlan_objmgr_peer *peer,
586 enum wlan_epcs_evt event,
587 void *event_data, uint32_t len)
588 {
589 QDF_STATUS status;
590
591 mlme_debug("EPCS event received: %s(%d)",
592 epcs_get_event_str(event), event);
593
594 switch (event) {
595 case WLAN_EPCS_EV_ACTION_FRAME_RX_REQ:
596 status = epcs_handle_rx_req(vdev, peer, event_data, len);
597 break;
598 case WLAN_EPCS_EV_ACTION_FRAME_RX_RESP:
599 status = epcs_handle_rx_resp(vdev, peer, event_data, len);
600 break;
601 case WLAN_EPCS_EV_ACTION_FRAME_RX_TEARDOWN:
602 status = epcs_handle_rx_teardown(vdev, peer, event_data, len);
603 break;
604 default:
605 status = QDF_STATUS_E_FAILURE;
606 mlme_err("Unhandled EPCS event");
607 }
608
609 return status;
610 }
611
wlan_epcs_deliver_event(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,enum wlan_epcs_evt event,void * event_data,uint32_t len)612 QDF_STATUS wlan_epcs_deliver_event(struct wlan_objmgr_vdev *vdev,
613 struct wlan_objmgr_peer *peer,
614 enum wlan_epcs_evt event,
615 void *event_data, uint32_t len)
616 {
617 return epcs_deliver_event(vdev, peer, event, event_data, len);
618 }
619
epcs_deliver_cmd(struct wlan_objmgr_vdev * vdev,enum wlan_epcs_evt event)620 static QDF_STATUS epcs_deliver_cmd(struct wlan_objmgr_vdev *vdev,
621 enum wlan_epcs_evt event)
622 {
623 QDF_STATUS status;
624
625 mlme_debug("EPCS cmd received: %s(%d)",
626 epcs_get_event_str(event), event);
627
628 switch (event) {
629 case WLAN_EPCS_EV_ACTION_FRAME_TX_REQ:
630 status = epcs_handle_tx_req(vdev);
631 break;
632 case WLAN_EPCS_EV_ACTION_FRAME_TX_TEARDOWN:
633 status = epcs_handle_tx_teardown(vdev);
634 break;
635 default:
636 status = QDF_STATUS_E_FAILURE;
637 mlme_err("Unhandled EPCS cmd");
638 }
639
640 return status;
641 }
642
wlan_epcs_deliver_cmd(struct wlan_objmgr_vdev * vdev,enum wlan_epcs_evt event)643 QDF_STATUS wlan_epcs_deliver_cmd(struct wlan_objmgr_vdev *vdev,
644 enum wlan_epcs_evt event)
645 {
646 if (!vdev)
647 return QDF_STATUS_E_FAILURE;
648
649 if (!wlan_mlme_get_epcs_capability(wlan_vdev_get_psoc(vdev))) {
650 mlme_info("EPCS has been disabled");
651 return QDF_STATUS_E_FAILURE;
652 }
653
654 return epcs_deliver_cmd(vdev, event);
655 }
656
wlan_epcs_set_config(struct wlan_objmgr_vdev * vdev,uint8_t flag)657 QDF_STATUS wlan_epcs_set_config(struct wlan_objmgr_vdev *vdev, uint8_t flag)
658 {
659 struct mac_context *mac_ctx;
660
661 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
662 if (!mac_ctx)
663 return QDF_STATUS_E_INVAL;
664
665 if (!vdev)
666 return QDF_STATUS_E_FAILURE;
667
668 if (flag)
669 wlan_mlme_set_epcs_capability(wlan_vdev_get_psoc(vdev), true);
670 else
671 wlan_mlme_set_epcs_capability(wlan_vdev_get_psoc(vdev), false);
672
673 return lim_send_eht_caps_ie(mac_ctx, QDF_STA_MODE,
674 wlan_vdev_get_id(vdev));
675 }
676
wlan_epcs_get_config(struct wlan_objmgr_vdev * vdev)677 bool wlan_epcs_get_config(struct wlan_objmgr_vdev *vdev)
678 {
679 bool epcs_flag;
680
681 if (!vdev)
682 return false;
683
684 epcs_flag = wlan_mlme_get_epcs_capability(wlan_vdev_get_psoc(vdev));
685 mlme_debug("EPCS %s", epcs_flag ? "Enabled" : "Disabled");
686
687 return epcs_flag;
688 }
689