1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3*5113495bSYour Name *
4*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for any
5*5113495bSYour Name * purpose with or without fee is hereby granted, provided that the above
6*5113495bSYour Name * copyright notice and this permission notice appear in all copies.
7*5113495bSYour Name *
8*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*5113495bSYour Name * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*5113495bSYour Name * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*5113495bSYour Name * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*5113495bSYour Name * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*5113495bSYour Name * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*5113495bSYour Name * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*5113495bSYour Name */
16*5113495bSYour Name
17*5113495bSYour Name /**
18*5113495bSYour Name * DOC: contains EPCS APIs
19*5113495bSYour Name */
20*5113495bSYour Name
21*5113495bSYour Name #include <wlan_objmgr_pdev_obj.h>
22*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
23*5113495bSYour Name #include <wlan_objmgr_peer_obj.h>
24*5113495bSYour Name #include <wlan_mlo_mgr_public_structs.h>
25*5113495bSYour Name #include <wlan_mlo_mgr_cmn.h>
26*5113495bSYour Name #include <qdf_util.h>
27*5113495bSYour Name #include <wlan_cm_api.h>
28*5113495bSYour Name #include <utils_mlo.h>
29*5113495bSYour Name #include <wlan_mlo_epcs.h>
30*5113495bSYour Name
31*5113495bSYour Name /**
32*5113495bSYour Name * wlan_mlo_is_node_epcs_authorized() - API to check mac address is
33*5113495bSYour Name * EPCS authorized or not
34*5113495bSYour Name * @ml_peer: pointer to mlo context of peer
35*5113495bSYour Name *
36*5113495bSYour Name * Return: QDF_STATUS
37*5113495bSYour Name */
38*5113495bSYour Name static QDF_STATUS
wlan_mlo_is_node_epcs_authorized(struct wlan_mlo_peer_context * ml_peer)39*5113495bSYour Name wlan_mlo_is_node_epcs_authorized(struct wlan_mlo_peer_context *ml_peer)
40*5113495bSYour Name {
41*5113495bSYour Name struct wlan_mlo_dev_context *mlo_dev_ctx;
42*5113495bSYour Name struct wlan_epcs_context *epcs_ctx;
43*5113495bSYour Name enum QDF_OPMODE opmode;
44*5113495bSYour Name struct wlan_objmgr_vdev *vdev = NULL;
45*5113495bSYour Name int i;
46*5113495bSYour Name
47*5113495bSYour Name if (!ml_peer) {
48*5113495bSYour Name epcs_err("ml_peer is null");
49*5113495bSYour Name return QDF_STATUS_E_INVAL;
50*5113495bSYour Name }
51*5113495bSYour Name
52*5113495bSYour Name mlo_dev_ctx = ml_peer->ml_dev;
53*5113495bSYour Name if (!mlo_dev_ctx) {
54*5113495bSYour Name epcs_err("mlo dev ctx is null");
55*5113495bSYour Name return QDF_STATUS_E_INVAL;
56*5113495bSYour Name }
57*5113495bSYour Name
58*5113495bSYour Name /* Get first valid vdev */
59*5113495bSYour Name for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
60*5113495bSYour Name if (!mlo_dev_ctx->wlan_vdev_list[i])
61*5113495bSYour Name continue;
62*5113495bSYour Name
63*5113495bSYour Name vdev = mlo_dev_ctx->wlan_vdev_list[i];
64*5113495bSYour Name opmode = wlan_vdev_mlme_get_opmode(vdev);
65*5113495bSYour Name break;
66*5113495bSYour Name }
67*5113495bSYour Name
68*5113495bSYour Name if (!vdev) {
69*5113495bSYour Name epcs_err("no valid vdev entry found");
70*5113495bSYour Name return QDF_STATUS_E_INVAL;
71*5113495bSYour Name }
72*5113495bSYour Name
73*5113495bSYour Name epcs_debug("ml peer type %d", opmode);
74*5113495bSYour Name if (opmode != QDF_SAP_MODE)
75*5113495bSYour Name return QDF_STATUS_SUCCESS;
76*5113495bSYour Name
77*5113495bSYour Name epcs_ctx = &mlo_dev_ctx->epcs_ctx;
78*5113495bSYour Name if (!epcs_ctx) {
79*5113495bSYour Name epcs_err("epcs info is null");
80*5113495bSYour Name return QDF_STATUS_E_INVAL;
81*5113495bSYour Name }
82*5113495bSYour Name
83*5113495bSYour Name epcs_dev_lock_acquire(epcs_ctx);
84*5113495bSYour Name for (i = 0; i < EPCS_MAX_AUTHORIZE_MAC_ADDR; i++) {
85*5113495bSYour Name if (epcs_ctx->authorize_info[i].valid &&
86*5113495bSYour Name !qdf_mem_cmp(epcs_ctx->authorize_info[i].peer_mld_mac,
87*5113495bSYour Name ml_peer->peer_mld_addr.bytes,
88*5113495bSYour Name QDF_MAC_ADDR_SIZE)) {
89*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
90*5113495bSYour Name return QDF_STATUS_SUCCESS;
91*5113495bSYour Name }
92*5113495bSYour Name }
93*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
94*5113495bSYour Name
95*5113495bSYour Name return QDF_STATUS_E_INVAL;
96*5113495bSYour Name }
97*5113495bSYour Name
98*5113495bSYour Name /**
99*5113495bSYour Name * mlo_process_ml_priorityaccess_ie() - API to parse Priority access ML IE
100*5113495bSYour Name * @ml_ie: Pointer to start of ML IE
101*5113495bSYour Name * @ml_ie_len: Length of ML IE
102*5113495bSYour Name * @priority_access_info: pointer to fill multi link priority access information
103*5113495bSYour Name *
104*5113495bSYour Name * Return: QDF_STATUS
105*5113495bSYour Name */
106*5113495bSYour Name static QDF_STATUS
mlo_process_ml_priorityaccess_ie(uint8_t * ml_ie,qdf_size_t ml_ie_len,struct ml_pa_info * priority_access_info)107*5113495bSYour Name mlo_process_ml_priorityaccess_ie(uint8_t *ml_ie, qdf_size_t ml_ie_len,
108*5113495bSYour Name struct ml_pa_info *priority_access_info)
109*5113495bSYour Name {
110*5113495bSYour Name uint8_t *ml_pa_ie = NULL;
111*5113495bSYour Name qdf_size_t ml_pa_ie_len = 0;
112*5113495bSYour Name QDF_STATUS status;
113*5113495bSYour Name
114*5113495bSYour Name if (!ml_ie) {
115*5113495bSYour Name mlo_err("NULL ml_ie");
116*5113495bSYour Name return QDF_STATUS_E_INVAL;
117*5113495bSYour Name }
118*5113495bSYour Name
119*5113495bSYour Name if (!priority_access_info) {
120*5113495bSYour Name mlo_err("NULL priority_access_info");
121*5113495bSYour Name return QDF_STATUS_E_INVAL;
122*5113495bSYour Name }
123*5113495bSYour Name
124*5113495bSYour Name status = util_find_mlie_by_variant(ml_ie,
125*5113495bSYour Name ml_ie_len,
126*5113495bSYour Name &ml_pa_ie,
127*5113495bSYour Name &ml_pa_ie_len,
128*5113495bSYour Name WLAN_ML_VARIANT_PRIORITYACCESS);
129*5113495bSYour Name
130*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status) || !ml_pa_ie) {
131*5113495bSYour Name mlo_debug("ML IE for reconfig variant not found");
132*5113495bSYour Name return QDF_STATUS_E_INVAL;
133*5113495bSYour Name }
134*5113495bSYour Name epcs_debug("PAV ML IE with length %zu is present", ml_pa_ie_len);
135*5113495bSYour Name
136*5113495bSYour Name status = util_get_pav_mlie_link_info(ml_pa_ie, ml_pa_ie_len,
137*5113495bSYour Name priority_access_info);
138*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
139*5113495bSYour Name mlo_err("Unable to get sta link info from ML PAV IE");
140*5113495bSYour Name return QDF_STATUS_E_INVAL;
141*5113495bSYour Name }
142*5113495bSYour Name return QDF_STATUS_SUCCESS;
143*5113495bSYour Name }
144*5113495bSYour Name
145*5113495bSYour Name /**
146*5113495bSYour Name * wlan_mlo_parse_epcs_request_action_frame() - API to parse EPCS request action
147*5113495bSYour Name * frame.
148*5113495bSYour Name * @epcs: Pointer to EPCS structure
149*5113495bSYour Name * @action_frm: Pointer to action frame
150*5113495bSYour Name * @frm_len: frame length
151*5113495bSYour Name *
152*5113495bSYour Name * Return: QDF_STATUS
153*5113495bSYour Name */
154*5113495bSYour Name static QDF_STATUS
wlan_mlo_parse_epcs_request_action_frame(struct wlan_epcs_info * epcs,struct wlan_action_frame * action_frm,uint32_t frm_len)155*5113495bSYour Name wlan_mlo_parse_epcs_request_action_frame(struct wlan_epcs_info *epcs,
156*5113495bSYour Name struct wlan_action_frame *action_frm,
157*5113495bSYour Name uint32_t frm_len)
158*5113495bSYour Name {
159*5113495bSYour Name struct epcs_frm *epcs_action_frm;
160*5113495bSYour Name struct ml_pa_info *priority_access_info = &epcs->pa_info;
161*5113495bSYour Name uint8_t *pa_ie;
162*5113495bSYour Name uint16_t pa_ie_len;
163*5113495bSYour Name
164*5113495bSYour Name /*
165*5113495bSYour Name * EPCS request action frame
166*5113495bSYour Name *
167*5113495bSYour Name * 1-byte 1-byte 1-byte variable
168*5113495bSYour Name *--------------------------------------------
169*5113495bSYour Name * | | | | |
170*5113495bSYour Name * | Category| Protected | Dialog | PA ML IE |
171*5113495bSYour Name * | | EHT | token | |
172*5113495bSYour Name * | | Action | | |
173*5113495bSYour Name *--------------------------------------------
174*5113495bSYour Name */
175*5113495bSYour Name
176*5113495bSYour Name epcs_action_frm = (struct epcs_frm *)action_frm;
177*5113495bSYour Name
178*5113495bSYour Name epcs->cat = epcs_action_frm->protected_eht_action;
179*5113495bSYour Name epcs->dialog_token = epcs_action_frm->dialog_token;
180*5113495bSYour Name epcs_info("EPCS frame rcv : category:%d action:%d dialog_token:%d frmlen %d",
181*5113495bSYour Name epcs_action_frm->category,
182*5113495bSYour Name epcs_action_frm->protected_eht_action,
183*5113495bSYour Name epcs_action_frm->dialog_token, frm_len);
184*5113495bSYour Name
185*5113495bSYour Name if (frm_len > EPCS_REQ_MIN_LENGTH) {
186*5113495bSYour Name pa_ie = (uint8_t *)epcs_action_frm + EPCS_REQ_MIN_LENGTH;
187*5113495bSYour Name pa_ie_len = frm_len - EPCS_REQ_MIN_LENGTH;
188*5113495bSYour Name return mlo_process_ml_priorityaccess_ie(pa_ie,
189*5113495bSYour Name pa_ie_len,
190*5113495bSYour Name priority_access_info);
191*5113495bSYour Name } else {
192*5113495bSYour Name return QDF_STATUS_SUCCESS;
193*5113495bSYour Name }
194*5113495bSYour Name }
195*5113495bSYour Name
196*5113495bSYour Name /**
197*5113495bSYour Name * wlan_mlo_parse_epcs_response_action_frame() - API to parse EPCS response
198*5113495bSYour Name * action frame.
199*5113495bSYour Name * @epcs: Pointer to EPCS structure
200*5113495bSYour Name * @action_frm: Pointer to action frame
201*5113495bSYour Name * @frm_len: frame length
202*5113495bSYour Name *
203*5113495bSYour Name * Return: QDF_STATUS
204*5113495bSYour Name */
205*5113495bSYour Name static QDF_STATUS
wlan_mlo_parse_epcs_response_action_frame(struct wlan_epcs_info * epcs,struct wlan_action_frame * action_frm,uint32_t frm_len)206*5113495bSYour Name wlan_mlo_parse_epcs_response_action_frame(struct wlan_epcs_info *epcs,
207*5113495bSYour Name struct wlan_action_frame *action_frm,
208*5113495bSYour Name uint32_t frm_len)
209*5113495bSYour Name {
210*5113495bSYour Name struct epcs_frm *epcs_action_frm;
211*5113495bSYour Name struct ml_pa_info *priority_access_info = &epcs->pa_info;
212*5113495bSYour Name uint8_t *pa_ie;
213*5113495bSYour Name uint16_t pa_ie_len;
214*5113495bSYour Name
215*5113495bSYour Name /*
216*5113495bSYour Name * EPCS response action frame
217*5113495bSYour Name *
218*5113495bSYour Name * 1-byte 1-byte 1-byte 1-byte variable
219*5113495bSYour Name *----------------------------------------------------
220*5113495bSYour Name * | | | | | |
221*5113495bSYour Name * | Category| Protected | Dialog | Status | PA IE |
222*5113495bSYour Name * | | EHT | token | code | |
223*5113495bSYour Name * | | Action | | | |
224*5113495bSYour Name *----------------------------------------------------
225*5113495bSYour Name */
226*5113495bSYour Name
227*5113495bSYour Name epcs_action_frm = (struct epcs_frm *)action_frm;
228*5113495bSYour Name
229*5113495bSYour Name epcs->cat = epcs_action_frm->protected_eht_action;
230*5113495bSYour Name epcs->dialog_token = epcs_action_frm->dialog_token;
231*5113495bSYour Name QDF_SET_BITS(epcs->status, 0, 8, epcs_action_frm->resp.status_code[0]);
232*5113495bSYour Name QDF_SET_BITS(epcs->status, 8, 8, epcs_action_frm->resp.status_code[1]);
233*5113495bSYour Name epcs_info("EPCS frame rcv : category:%d action:%d dialog_token:%d status %x %x frmlen %d",
234*5113495bSYour Name epcs_action_frm->category,
235*5113495bSYour Name epcs_action_frm->protected_eht_action,
236*5113495bSYour Name epcs_action_frm->dialog_token,
237*5113495bSYour Name epcs_action_frm->resp.status_code[0],
238*5113495bSYour Name epcs_action_frm->resp.status_code[1], frm_len);
239*5113495bSYour Name
240*5113495bSYour Name if (frm_len > EPCS_RESP_MIN_LENGTH) {
241*5113495bSYour Name pa_ie = (uint8_t *)epcs_action_frm + EPCS_RESP_MIN_LENGTH;
242*5113495bSYour Name pa_ie_len = frm_len - EPCS_RESP_MIN_LENGTH;
243*5113495bSYour Name return mlo_process_ml_priorityaccess_ie(pa_ie,
244*5113495bSYour Name pa_ie_len,
245*5113495bSYour Name priority_access_info);
246*5113495bSYour Name } else {
247*5113495bSYour Name return QDF_STATUS_SUCCESS;
248*5113495bSYour Name }
249*5113495bSYour Name }
250*5113495bSYour Name
251*5113495bSYour Name /**
252*5113495bSYour Name * wlan_mlo_parse_epcs_teardown_action_frame() - API to parse EPCS teardown
253*5113495bSYour Name * action frame.
254*5113495bSYour Name * @epcs: Pointer to EPCS structure
255*5113495bSYour Name * @action_frm: Pointer to action frame
256*5113495bSYour Name * @frm_len: frame length
257*5113495bSYour Name *
258*5113495bSYour Name * Return: QDF_STATUS
259*5113495bSYour Name */
260*5113495bSYour Name static QDF_STATUS
wlan_mlo_parse_epcs_teardown_action_frame(struct wlan_epcs_info * epcs,struct wlan_action_frame * action_frm,uint32_t frm_len)261*5113495bSYour Name wlan_mlo_parse_epcs_teardown_action_frame(struct wlan_epcs_info *epcs,
262*5113495bSYour Name struct wlan_action_frame *action_frm,
263*5113495bSYour Name uint32_t frm_len)
264*5113495bSYour Name {
265*5113495bSYour Name struct epcs_frm *epcs_action_frm;
266*5113495bSYour Name
267*5113495bSYour Name /*
268*5113495bSYour Name * EPCS teardown action frame
269*5113495bSYour Name *
270*5113495bSYour Name * 1-byte 1-byte
271*5113495bSYour Name *------------------------
272*5113495bSYour Name * | | |
273*5113495bSYour Name * | Category| Protected |
274*5113495bSYour Name * | | EHT |
275*5113495bSYour Name * | | Action |
276*5113495bSYour Name *------------------------
277*5113495bSYour Name */
278*5113495bSYour Name
279*5113495bSYour Name epcs_action_frm = (struct epcs_frm *)action_frm;
280*5113495bSYour Name
281*5113495bSYour Name epcs->cat = epcs_action_frm->protected_eht_action;
282*5113495bSYour Name epcs_info("EPCS frame rcv : category:%d action:%d frmlen %d",
283*5113495bSYour Name epcs_action_frm->category,
284*5113495bSYour Name epcs_action_frm->protected_eht_action, frm_len);
285*5113495bSYour Name
286*5113495bSYour Name return QDF_STATUS_SUCCESS;
287*5113495bSYour Name }
288*5113495bSYour Name
289*5113495bSYour Name QDF_STATUS
wlan_mlo_parse_epcs_action_frame(struct wlan_epcs_info * epcs,struct wlan_action_frame * action_frm,uint32_t frm_len)290*5113495bSYour Name wlan_mlo_parse_epcs_action_frame(struct wlan_epcs_info *epcs,
291*5113495bSYour Name struct wlan_action_frame *action_frm,
292*5113495bSYour Name uint32_t frm_len)
293*5113495bSYour Name {
294*5113495bSYour Name QDF_STATUS ret_val = QDF_STATUS_SUCCESS;
295*5113495bSYour Name
296*5113495bSYour Name switch (action_frm->action) {
297*5113495bSYour Name case WLAN_EPCS_CATEGORY_REQUEST:
298*5113495bSYour Name return wlan_mlo_parse_epcs_request_action_frame(
299*5113495bSYour Name epcs, action_frm, frm_len);
300*5113495bSYour Name case WLAN_EPCS_CATEGORY_RESPONSE:
301*5113495bSYour Name return wlan_mlo_parse_epcs_response_action_frame(
302*5113495bSYour Name epcs, action_frm, frm_len);
303*5113495bSYour Name case WLAN_EPCS_CATEGORY_TEARDOWN:
304*5113495bSYour Name return wlan_mlo_parse_epcs_teardown_action_frame(
305*5113495bSYour Name epcs, action_frm, frm_len);
306*5113495bSYour Name default:
307*5113495bSYour Name ret_val = QDF_STATUS_E_INVAL;
308*5113495bSYour Name epcs_err("Invalid action :%d", action_frm->action);
309*5113495bSYour Name }
310*5113495bSYour Name
311*5113495bSYour Name return ret_val;
312*5113495bSYour Name }
313*5113495bSYour Name
314*5113495bSYour Name static uint8_t *
wlan_mlo_add_epcs_request_action_frame(uint8_t * frm,struct wlan_action_frame_args * args,uint8_t * buf)315*5113495bSYour Name wlan_mlo_add_epcs_request_action_frame(uint8_t *frm,
316*5113495bSYour Name struct wlan_action_frame_args *args,
317*5113495bSYour Name uint8_t *buf)
318*5113495bSYour Name {
319*5113495bSYour Name *frm++ = args->category;
320*5113495bSYour Name *frm++ = args->action;
321*5113495bSYour Name /* Dialog token*/
322*5113495bSYour Name *frm++ = args->arg1;
323*5113495bSYour Name
324*5113495bSYour Name epcs_info("EPCS frame: category:%d action:%d dialog_token:%d",
325*5113495bSYour Name args->category, args->action, args->arg1);
326*5113495bSYour Name
327*5113495bSYour Name /* Add priority access ml ie in caller for AP mode */
328*5113495bSYour Name return frm;
329*5113495bSYour Name }
330*5113495bSYour Name
331*5113495bSYour Name static uint8_t *
wlan_mlo_add_epcs_response_action_frame(uint8_t * frm,struct wlan_action_frame_args * args,uint8_t * buf)332*5113495bSYour Name wlan_mlo_add_epcs_response_action_frame(uint8_t *frm,
333*5113495bSYour Name struct wlan_action_frame_args *args,
334*5113495bSYour Name uint8_t *buf)
335*5113495bSYour Name {
336*5113495bSYour Name *frm++ = args->category;
337*5113495bSYour Name *frm++ = args->action;
338*5113495bSYour Name /* Dialog token*/
339*5113495bSYour Name *frm++ = args->arg1;
340*5113495bSYour Name /* Status code (2 bytes) */
341*5113495bSYour Name *frm++ = QDF_GET_BITS(args->arg2, 0, 8);
342*5113495bSYour Name *frm++ = QDF_GET_BITS(args->arg2, 8, 8);
343*5113495bSYour Name
344*5113495bSYour Name epcs_info("EPCS response frame: category:%d action:%d dialog_token:%d status_code:%d",
345*5113495bSYour Name args->category, args->action, args->arg1, args->arg2);
346*5113495bSYour Name
347*5113495bSYour Name /* Add priority access ml ie for AP mode */
348*5113495bSYour Name return frm;
349*5113495bSYour Name }
350*5113495bSYour Name
351*5113495bSYour Name uint8_t *
wlan_mlo_add_epcs_action_frame(uint8_t * frm,struct wlan_action_frame_args * args,uint8_t * buf)352*5113495bSYour Name wlan_mlo_add_epcs_action_frame(uint8_t *frm,
353*5113495bSYour Name struct wlan_action_frame_args *args,
354*5113495bSYour Name uint8_t *buf)
355*5113495bSYour Name {
356*5113495bSYour Name switch (args->action) {
357*5113495bSYour Name case WLAN_EPCS_CATEGORY_REQUEST:
358*5113495bSYour Name return wlan_mlo_add_epcs_request_action_frame(frm, args,
359*5113495bSYour Name buf);
360*5113495bSYour Name case WLAN_EPCS_CATEGORY_RESPONSE:
361*5113495bSYour Name return wlan_mlo_add_epcs_response_action_frame(frm, args,
362*5113495bSYour Name buf);
363*5113495bSYour Name case WLAN_EPCS_CATEGORY_TEARDOWN:
364*5113495bSYour Name *frm++ = args->category;
365*5113495bSYour Name *frm++ = args->action;
366*5113495bSYour Name return frm;
367*5113495bSYour Name default:
368*5113495bSYour Name epcs_err("Invalid category:%d", args->category);
369*5113495bSYour Name }
370*5113495bSYour Name
371*5113495bSYour Name return frm;
372*5113495bSYour Name }
373*5113495bSYour Name
374*5113495bSYour Name QDF_STATUS
wlan_mlo_peer_rcv_cmd(struct wlan_mlo_peer_context * ml_peer,struct wlan_epcs_info * epcs,bool * updparam)375*5113495bSYour Name wlan_mlo_peer_rcv_cmd(struct wlan_mlo_peer_context *ml_peer,
376*5113495bSYour Name struct wlan_epcs_info *epcs,
377*5113495bSYour Name bool *updparam)
378*5113495bSYour Name {
379*5113495bSYour Name uint32_t cur_state;
380*5113495bSYour Name uint32_t new_state;
381*5113495bSYour Name QDF_STATUS status = QDF_STATUS_E_INVAL;
382*5113495bSYour Name
383*5113495bSYour Name if (!ml_peer) {
384*5113495bSYour Name epcs_err("Null MLO peer");
385*5113495bSYour Name return QDF_STATUS_E_INVAL;
386*5113495bSYour Name }
387*5113495bSYour Name
388*5113495bSYour Name *updparam = false;
389*5113495bSYour Name
390*5113495bSYour Name epcs_dev_peer_lock_acquire(&ml_peer->epcs_info);
391*5113495bSYour Name cur_state = ml_peer->epcs_info.state;
392*5113495bSYour Name switch (ml_peer->epcs_info.state) {
393*5113495bSYour Name case EPCS_DOWN:
394*5113495bSYour Name if (epcs->cat == WLAN_EPCS_CATEGORY_REQUEST) {
395*5113495bSYour Name /* check authorization */
396*5113495bSYour Name if (wlan_mlo_is_node_epcs_authorized(ml_peer) ==
397*5113495bSYour Name QDF_STATUS_SUCCESS) {
398*5113495bSYour Name status = QDF_STATUS_SUCCESS;
399*5113495bSYour Name epcs->dialog_token =
400*5113495bSYour Name ++ml_peer->epcs_info.self_gen_dialog_token;
401*5113495bSYour Name } else {
402*5113495bSYour Name epcs_info("peer not authorized to enable EPCS");
403*5113495bSYour Name }
404*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_TEARDOWN) {
405*5113495bSYour Name epcs_info("peer already in EPCS down state");
406*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_RESPONSE) {
407*5113495bSYour Name epcs_err("Invalid command");
408*5113495bSYour Name }
409*5113495bSYour Name break;
410*5113495bSYour Name case EPCS_ENABLE:
411*5113495bSYour Name if (epcs->cat == WLAN_EPCS_CATEGORY_TEARDOWN) {
412*5113495bSYour Name ml_peer->epcs_info.state = EPCS_DOWN;
413*5113495bSYour Name status = QDF_STATUS_SUCCESS;
414*5113495bSYour Name *updparam = true;
415*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_REQUEST) {
416*5113495bSYour Name epcs_info("peer already in EPCS enable state");
417*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_RESPONSE) {
418*5113495bSYour Name epcs_err("Invalid command");
419*5113495bSYour Name }
420*5113495bSYour Name break;
421*5113495bSYour Name default:
422*5113495bSYour Name epcs_err("Invalid peer state %d",
423*5113495bSYour Name ml_peer->epcs_info.state);
424*5113495bSYour Name }
425*5113495bSYour Name
426*5113495bSYour Name new_state = ml_peer->epcs_info.state;
427*5113495bSYour Name epcs_debug("cmd:old state %d new state %d ev cat %d dialog token %d status %d",
428*5113495bSYour Name cur_state, new_state, epcs->cat,
429*5113495bSYour Name epcs->dialog_token, epcs->status);
430*5113495bSYour Name
431*5113495bSYour Name epcs_dev_peer_lock_release(&ml_peer->epcs_info);
432*5113495bSYour Name
433*5113495bSYour Name return status;
434*5113495bSYour Name }
435*5113495bSYour Name
436*5113495bSYour Name QDF_STATUS
wlan_mlo_peer_rcv_action_frame(struct wlan_mlo_peer_context * ml_peer,struct wlan_epcs_info * epcs,bool * respond,bool * updparam)437*5113495bSYour Name wlan_mlo_peer_rcv_action_frame(struct wlan_mlo_peer_context *ml_peer,
438*5113495bSYour Name struct wlan_epcs_info *epcs,
439*5113495bSYour Name bool *respond,
440*5113495bSYour Name bool *updparam)
441*5113495bSYour Name {
442*5113495bSYour Name uint32_t cur_state;
443*5113495bSYour Name uint32_t new_state;
444*5113495bSYour Name QDF_STATUS status = QDF_STATUS_E_INVAL;
445*5113495bSYour Name
446*5113495bSYour Name if (!ml_peer) {
447*5113495bSYour Name epcs_err("Null MLO peer");
448*5113495bSYour Name return QDF_STATUS_E_INVAL;
449*5113495bSYour Name }
450*5113495bSYour Name
451*5113495bSYour Name *respond = false;
452*5113495bSYour Name *updparam = false;
453*5113495bSYour Name
454*5113495bSYour Name epcs_dev_peer_lock_acquire(&ml_peer->epcs_info);
455*5113495bSYour Name cur_state = ml_peer->epcs_info.state;
456*5113495bSYour Name switch (ml_peer->epcs_info.state) {
457*5113495bSYour Name case EPCS_DOWN:
458*5113495bSYour Name if (epcs->cat == WLAN_EPCS_CATEGORY_RESPONSE) {
459*5113495bSYour Name if (epcs->status == STATUS_SUCCESS) {
460*5113495bSYour Name if (epcs->dialog_token ==
461*5113495bSYour Name ml_peer->epcs_info.self_gen_dialog_token) {
462*5113495bSYour Name ml_peer->epcs_info.state = EPCS_ENABLE;
463*5113495bSYour Name status = QDF_STATUS_SUCCESS;
464*5113495bSYour Name *updparam = true;
465*5113495bSYour Name } else {
466*5113495bSYour Name epcs_err("Response dialog token mismatch self_gen_dialog_token %d response token %d", ml_peer->epcs_info.self_gen_dialog_token, epcs->dialog_token);
467*5113495bSYour Name }
468*5113495bSYour Name } else {
469*5113495bSYour Name epcs_info("epcs rejected with status code %d",
470*5113495bSYour Name epcs->status);
471*5113495bSYour Name }
472*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_REQUEST) {
473*5113495bSYour Name /* check authorization */
474*5113495bSYour Name if (wlan_mlo_is_node_epcs_authorized(ml_peer) ==
475*5113495bSYour Name QDF_STATUS_SUCCESS) {
476*5113495bSYour Name ml_peer->epcs_info.state = EPCS_ENABLE;
477*5113495bSYour Name status = QDF_STATUS_SUCCESS;
478*5113495bSYour Name *respond = true;
479*5113495bSYour Name *updparam = true;
480*5113495bSYour Name } else {
481*5113495bSYour Name epcs_info("peer not authorized to enable EPCS");
482*5113495bSYour Name }
483*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_TEARDOWN) {
484*5113495bSYour Name epcs_info("peer not in EPCS enable state");
485*5113495bSYour Name }
486*5113495bSYour Name break;
487*5113495bSYour Name case EPCS_ENABLE:
488*5113495bSYour Name if (epcs->cat == WLAN_EPCS_CATEGORY_TEARDOWN) {
489*5113495bSYour Name ml_peer->epcs_info.state = EPCS_DOWN;
490*5113495bSYour Name status = QDF_STATUS_SUCCESS;
491*5113495bSYour Name *updparam = true;
492*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_REQUEST) {
493*5113495bSYour Name epcs_info("peer already in EPCS enable state");
494*5113495bSYour Name } else if (epcs->cat == WLAN_EPCS_CATEGORY_RESPONSE) {
495*5113495bSYour Name epcs_info("peer already in EPCS enable state");
496*5113495bSYour Name }
497*5113495bSYour Name break;
498*5113495bSYour Name default:
499*5113495bSYour Name epcs_err("Invalid peer state %d", ml_peer->epcs_info.state);
500*5113495bSYour Name }
501*5113495bSYour Name
502*5113495bSYour Name new_state = ml_peer->epcs_info.state;
503*5113495bSYour Name epcs_debug("action:old state %d new state %d ev cat %d dialog token %d status %d",
504*5113495bSYour Name cur_state, new_state, epcs->cat,
505*5113495bSYour Name epcs->dialog_token, epcs->status);
506*5113495bSYour Name
507*5113495bSYour Name epcs_dev_peer_lock_release(&ml_peer->epcs_info);
508*5113495bSYour Name
509*5113495bSYour Name return status;
510*5113495bSYour Name }
511*5113495bSYour Name
512*5113495bSYour Name QDF_STATUS
wlan_mlo_update_authorize_epcs_mac_addr(struct wlan_objmgr_vdev * vdev,uint8_t * peer_mld_mac)513*5113495bSYour Name wlan_mlo_update_authorize_epcs_mac_addr(struct wlan_objmgr_vdev *vdev,
514*5113495bSYour Name uint8_t *peer_mld_mac)
515*5113495bSYour Name {
516*5113495bSYour Name bool found_entry = false;
517*5113495bSYour Name int free_index = -1;
518*5113495bSYour Name int i = 0;
519*5113495bSYour Name struct wlan_epcs_context *epcs_ctx;
520*5113495bSYour Name
521*5113495bSYour Name if (!vdev) {
522*5113495bSYour Name epcs_err("vdev is null");
523*5113495bSYour Name return QDF_STATUS_E_INVAL;
524*5113495bSYour Name }
525*5113495bSYour Name
526*5113495bSYour Name epcs_ctx = &vdev->mlo_dev_ctx->epcs_ctx;
527*5113495bSYour Name
528*5113495bSYour Name epcs_dev_lock_acquire(epcs_ctx);
529*5113495bSYour Name for (i = 0; i < EPCS_MAX_AUTHORIZE_MAC_ADDR; i++) {
530*5113495bSYour Name /* Finding first available slot */
531*5113495bSYour Name if ((!epcs_ctx->authorize_info[i].valid) && (free_index < 0))
532*5113495bSYour Name free_index = i;
533*5113495bSYour Name
534*5113495bSYour Name /* Checking for already available valid entry */
535*5113495bSYour Name if (epcs_ctx->authorize_info[i].valid &&
536*5113495bSYour Name !qdf_mem_cmp(epcs_ctx->authorize_info[i].peer_mld_mac,
537*5113495bSYour Name peer_mld_mac,
538*5113495bSYour Name QDF_MAC_ADDR_SIZE)) {
539*5113495bSYour Name found_entry = true;
540*5113495bSYour Name break;
541*5113495bSYour Name }
542*5113495bSYour Name }
543*5113495bSYour Name
544*5113495bSYour Name if (found_entry) {
545*5113495bSYour Name epcs_debug("Mac add "QDF_MAC_ADDR_FMT" is already authorized",
546*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mld_mac));
547*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
548*5113495bSYour Name return QDF_STATUS_E_INVAL;
549*5113495bSYour Name }
550*5113495bSYour Name
551*5113495bSYour Name if (free_index < 0) {
552*5113495bSYour Name epcs_debug("EPCS authorize database is full");
553*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
554*5113495bSYour Name return QDF_STATUS_E_INVAL;
555*5113495bSYour Name }
556*5113495bSYour Name
557*5113495bSYour Name epcs_ctx->authorize_info[free_index].valid = true;
558*5113495bSYour Name qdf_mem_copy(epcs_ctx->authorize_info[free_index]. peer_mld_mac,
559*5113495bSYour Name peer_mld_mac,
560*5113495bSYour Name QDF_MAC_ADDR_SIZE);
561*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
562*5113495bSYour Name
563*5113495bSYour Name epcs_debug("EPCS Stored authorize mac addr is"QDF_MAC_ADDR_FMT" at index %d",
564*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mld_mac), free_index);
565*5113495bSYour Name
566*5113495bSYour Name return QDF_STATUS_SUCCESS;
567*5113495bSYour Name }
568*5113495bSYour Name
569*5113495bSYour Name QDF_STATUS
wlan_mlo_update_deauthorize_epcs_mac_addr(struct wlan_objmgr_vdev * vdev,uint8_t * peer_mld_mac)570*5113495bSYour Name wlan_mlo_update_deauthorize_epcs_mac_addr(struct wlan_objmgr_vdev *vdev,
571*5113495bSYour Name uint8_t *peer_mld_mac)
572*5113495bSYour Name {
573*5113495bSYour Name int i = 0;
574*5113495bSYour Name struct wlan_epcs_context *epcs_ctx;
575*5113495bSYour Name bool found_entry = false;
576*5113495bSYour Name
577*5113495bSYour Name if (!vdev) {
578*5113495bSYour Name epcs_err("vdev is null");
579*5113495bSYour Name return QDF_STATUS_E_INVAL;
580*5113495bSYour Name }
581*5113495bSYour Name
582*5113495bSYour Name epcs_ctx = &vdev->mlo_dev_ctx->epcs_ctx;
583*5113495bSYour Name
584*5113495bSYour Name epcs_dev_lock_acquire(epcs_ctx);
585*5113495bSYour Name for (i = 0; i < EPCS_MAX_AUTHORIZE_MAC_ADDR; i++) {
586*5113495bSYour Name if (!qdf_mem_cmp(epcs_ctx->authorize_info[i].peer_mld_mac,
587*5113495bSYour Name peer_mld_mac,
588*5113495bSYour Name QDF_MAC_ADDR_SIZE)) {
589*5113495bSYour Name found_entry = true;
590*5113495bSYour Name break;
591*5113495bSYour Name }
592*5113495bSYour Name }
593*5113495bSYour Name
594*5113495bSYour Name if (!found_entry) {
595*5113495bSYour Name epcs_debug("Mac addr "QDF_MAC_ADDR_FMT" not found in authorized database",
596*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mld_mac));
597*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
598*5113495bSYour Name return QDF_STATUS_E_INVAL;
599*5113495bSYour Name }
600*5113495bSYour Name
601*5113495bSYour Name if (found_entry && !epcs_ctx->authorize_info[i].valid) {
602*5113495bSYour Name epcs_debug("Mac addr "QDF_MAC_ADDR_FMT" is already deauthorized in database",
603*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mld_mac));
604*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
605*5113495bSYour Name return QDF_STATUS_E_INVAL;
606*5113495bSYour Name }
607*5113495bSYour Name
608*5113495bSYour Name epcs_ctx->authorize_info[i].valid = false;
609*5113495bSYour Name epcs_dev_lock_release(epcs_ctx);
610*5113495bSYour Name epcs_debug("EPCS Stored authorize mac addr is "QDF_MAC_ADDR_FMT" at idx %d is removed",
611*5113495bSYour Name QDF_MAC_ADDR_REF(peer_mld_mac), i);
612*5113495bSYour Name
613*5113495bSYour Name return QDF_STATUS_SUCCESS;
614*5113495bSYour Name }
615