1 /* 2 * Copyright (c) 2022-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 T2LM APIs 19 */ 20 21 #include <wlan_objmgr_pdev_obj.h> 22 #include <wlan_objmgr_vdev_obj.h> 23 #include <wlan_objmgr_peer_obj.h> 24 #include <wlan_mlo_mgr_public_structs.h> 25 #include <wlan_mlo_mgr_cmn.h> 26 #include <qdf_util.h> 27 #include <wlan_cm_api.h> 28 #include "wlan_utility.h" 29 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 30 #include <wlan_t2lm_api.h> 31 #endif 32 33 QDF_STATUS wlan_mlo_parse_t2lm_info(uint8_t *ie, 34 struct wlan_t2lm_info *t2lm) 35 { 36 struct wlan_ie_tid_to_link_mapping *t2lm_ie; 37 enum wlan_t2lm_direction dir; 38 uint8_t *t2lm_control_field; 39 uint16_t t2lm_control; 40 uint8_t link_mapping_presence_ind; 41 uint8_t *link_mapping_of_tids; 42 uint8_t tid_num; 43 uint8_t *ie_ptr = NULL; 44 45 t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)ie; 46 47 t2lm_control_field = t2lm_ie->data; 48 if (!t2lm_control_field) { 49 t2lm_err("t2lm_control_field is null"); 50 return QDF_STATUS_E_NULL_VALUE; 51 } 52 53 t2lm_control = qdf_le16_to_cpu(*(uint16_t *)t2lm_control_field); 54 55 dir = QDF_GET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DIRECTION_IDX, 56 WLAN_T2LM_CONTROL_DIRECTION_BITS); 57 if (dir > WLAN_T2LM_BIDI_DIRECTION) { 58 t2lm_err("Invalid direction"); 59 return QDF_STATUS_E_NULL_VALUE; 60 } 61 62 t2lm->direction = dir; 63 t2lm->default_link_mapping = 64 QDF_GET_BITS(t2lm_control, 65 WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_IDX, 66 WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_BITS); 67 68 t2lm->mapping_switch_time_present = 69 QDF_GET_BITS(t2lm_control, 70 WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_IDX, 71 WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_BITS); 72 73 t2lm->expected_duration_present = 74 QDF_GET_BITS(t2lm_control, 75 WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_IDX, 76 WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_BITS); 77 78 t2lm->link_mapping_size = 79 QDF_GET_BITS(t2lm_control, 80 WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_IDX, 81 WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_BITS); 82 83 t2lm_debug("direction:%d default_link_mapping:%d mapping_switch_time_present:%d expected_duration_present:%d link_mapping_size:%d", 84 t2lm->direction, t2lm->default_link_mapping, 85 t2lm->mapping_switch_time_present, 86 t2lm->expected_duration_present, 87 t2lm->link_mapping_size); 88 89 if (t2lm->default_link_mapping) { 90 ie_ptr = t2lm_control_field + sizeof(uint8_t); 91 } else { 92 link_mapping_presence_ind = 93 QDF_GET_BITS(t2lm_control, 94 WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_IDX, 95 WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_BITS); 96 ie_ptr = t2lm_control_field + sizeof(t2lm_control); 97 } 98 99 if (t2lm->mapping_switch_time_present) { 100 t2lm->mapping_switch_time = 101 qdf_le16_to_cpu(*(uint16_t *)ie_ptr); 102 ie_ptr += sizeof(uint16_t); 103 } 104 105 if (t2lm->expected_duration_present) { 106 qdf_mem_copy(&t2lm->expected_duration, ie_ptr, 107 WLAN_T2LM_EXPECTED_DURATION_SIZE * 108 (sizeof(uint8_t))); 109 ie_ptr += WLAN_T2LM_EXPECTED_DURATION_SIZE * (sizeof(uint8_t)); 110 } 111 112 t2lm_debug("mapping_switch_time:%d expected_duration:%d", 113 t2lm->mapping_switch_time, t2lm->expected_duration); 114 115 if (t2lm->default_link_mapping) 116 return QDF_STATUS_SUCCESS; 117 118 link_mapping_of_tids = ie_ptr; 119 120 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 121 if (!(link_mapping_presence_ind & BIT(tid_num))) 122 continue; 123 124 if (!t2lm->link_mapping_size) { 125 t2lm->ieee_link_map_tid[tid_num] = 126 qdf_le16_to_cpu(*(uint16_t *)link_mapping_of_tids); 127 link_mapping_of_tids += sizeof(uint16_t); 128 } else { 129 t2lm->ieee_link_map_tid[tid_num] = 130 *(uint8_t *)link_mapping_of_tids; 131 link_mapping_of_tids += sizeof(uint8_t); 132 } 133 134 t2lm_rl_debug("link mapping of TID%d is %x", tid_num, 135 t2lm->ieee_link_map_tid[tid_num]); 136 } 137 138 return QDF_STATUS_SUCCESS; 139 } 140 141 QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie( 142 struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie) 143 { 144 struct wlan_t2lm_info t2lm = {0}; 145 struct extn_ie_header *ext_ie_hdr; 146 QDF_STATUS retval; 147 int i = 0; 148 149 qdf_mem_zero(&t2lm_ctx->established_t2lm, 150 sizeof(struct wlan_mlo_t2lm_ie)); 151 qdf_mem_zero(&t2lm_ctx->upcoming_t2lm, sizeof(struct wlan_mlo_t2lm_ie)); 152 153 t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION; 154 t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION; 155 156 for (i = 0; i < WLAN_MAX_T2LM_IE; i++) { 157 if (!ie) { 158 t2lm_err("ie is null"); 159 return QDF_STATUS_E_NULL_VALUE; 160 } 161 162 ext_ie_hdr = (struct extn_ie_header *)ie; 163 164 if (!(ext_ie_hdr->ie_id == WLAN_ELEMID_EXTN_ELEM && 165 ext_ie_hdr->ie_extn_id == WLAN_EXTN_ELEMID_T2LM)) 166 continue; 167 168 t2lm.direction = WLAN_T2LM_INVALID_DIRECTION; 169 retval = wlan_mlo_parse_t2lm_info(ie, &t2lm); 170 if (retval) { 171 t2lm_err("Failed to parse the T2LM IE"); 172 return retval; 173 } 174 175 if (!t2lm.mapping_switch_time_present && 176 t2lm.expected_duration_present) { 177 qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm, &t2lm, 178 sizeof(struct wlan_t2lm_info)); 179 } else if (t2lm.mapping_switch_time_present) { 180 qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm, &t2lm, 181 sizeof(struct wlan_t2lm_info)); 182 } 183 184 ie += ext_ie_hdr->ie_len + sizeof(struct ie_header); 185 } 186 187 return QDF_STATUS_SUCCESS; 188 } 189 190 QDF_STATUS wlan_mlo_parse_t2lm_ie( 191 struct wlan_t2lm_onging_negotiation_info *t2lm, uint8_t *ie, 192 uint32_t frame_len) 193 { 194 struct extn_ie_header *ext_ie_hdr = NULL; 195 QDF_STATUS retval; 196 enum wlan_t2lm_direction dir; 197 struct wlan_t2lm_info t2lm_info; 198 uint32_t ie_len_parsed = 0; 199 200 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) 201 t2lm->t2lm_info[dir].direction = WLAN_T2LM_INVALID_DIRECTION; 202 203 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 204 if (!ie || !frame_len) { 205 t2lm_err("ie is null or len is 0"); 206 return QDF_STATUS_E_NULL_VALUE; 207 } 208 209 if (frame_len < (ie_len_parsed + sizeof(struct ie_header))) { 210 t2lm_err("Frame length is lesser than parsed T2LM IE header length"); 211 return QDF_STATUS_E_PROTO; 212 } 213 214 ext_ie_hdr = (struct extn_ie_header *)ie; 215 216 if (ext_ie_hdr->ie_id == WLAN_ELEMID_EXTN_ELEM && 217 ext_ie_hdr->ie_extn_id == WLAN_EXTN_ELEMID_T2LM) { 218 ie_len_parsed += ext_ie_hdr->ie_len + sizeof(struct ie_header); 219 if (frame_len < ie_len_parsed) { 220 t2lm_err("Frame length is lesser than parsed T2LM IE length"); 221 return QDF_STATUS_E_PROTO; 222 } 223 qdf_mem_zero(&t2lm_info, sizeof(t2lm_info)); 224 retval = wlan_mlo_parse_t2lm_info(ie, &t2lm_info); 225 if (!retval && 226 t2lm_info.direction < WLAN_T2LM_MAX_DIRECTION) { 227 qdf_mem_copy(&t2lm->t2lm_info[t2lm_info.direction], 228 &t2lm_info, 229 sizeof(struct wlan_t2lm_info)); 230 } else { 231 t2lm_err("Failed to parse the T2LM IE"); 232 return retval; 233 } 234 ie += ext_ie_hdr->ie_len + sizeof(struct ie_header); 235 } 236 } 237 238 if ((t2lm->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction == 239 WLAN_T2LM_DL_DIRECTION || 240 t2lm->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction == 241 WLAN_T2LM_UL_DIRECTION) && 242 t2lm->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction == 243 WLAN_T2LM_BIDI_DIRECTION) { 244 t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time"); 245 246 qdf_mem_zero(t2lm, sizeof(*t2lm)); 247 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 248 t2lm->t2lm_info[dir].direction = 249 WLAN_T2LM_INVALID_DIRECTION; 250 } 251 252 return QDF_STATUS_E_FAILURE; 253 } 254 255 return QDF_STATUS_SUCCESS; 256 } 257 258 uint8_t *wlan_mlo_add_t2lm_info_ie(uint8_t *frm, struct wlan_t2lm_info *t2lm, 259 struct wlan_objmgr_vdev *vdev) 260 { 261 struct wlan_ie_tid_to_link_mapping *t2lm_ie; 262 uint16_t t2lm_control = 0; 263 uint8_t *t2lm_control_field; 264 uint8_t *link_mapping_of_tids; 265 uint8_t tid_num; 266 uint8_t num_tids = 0; 267 uint8_t link_mapping_presence_indicator = 0; 268 struct vdev_mlme_obj *vdev_mlme; 269 270 t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)frm; 271 t2lm_ie->elem_id = WLAN_ELEMID_EXTN_ELEM; 272 t2lm_ie->elem_id_extn = WLAN_EXTN_ELEMID_T2LM; 273 274 t2lm_ie->elem_len = sizeof(*t2lm_ie) - sizeof(struct ie_header); 275 276 t2lm_control_field = t2lm_ie->data; 277 278 QDF_SET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DIRECTION_IDX, 279 WLAN_T2LM_CONTROL_DIRECTION_BITS, t2lm->direction); 280 281 QDF_SET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_IDX, 282 WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_BITS, 283 t2lm->default_link_mapping); 284 285 QDF_SET_BITS(t2lm_control, 286 WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_IDX, 287 WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_BITS, 288 t2lm->mapping_switch_time_present); 289 290 QDF_SET_BITS(t2lm_control, 291 WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_IDX, 292 WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_BITS, 293 t2lm->expected_duration_present); 294 295 QDF_SET_BITS(t2lm_control, 296 WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_IDX, 297 WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_BITS, 298 t2lm->link_mapping_size); 299 300 if (t2lm->default_link_mapping) { 301 /* Link mapping of TIDs are not present when default mapping is 302 * set. Hence, the size of TID-To-Link mapping control is one 303 * octet. 304 */ 305 *t2lm_control_field = (uint8_t)t2lm_control; 306 307 t2lm_ie->elem_len += sizeof(uint8_t); 308 309 t2lm_rl_debug("T2LM IE added, default_link_mapping: %d dir:%d", 310 t2lm->default_link_mapping, t2lm->direction); 311 312 frm += sizeof(*t2lm_ie) + sizeof(uint8_t); 313 } else { 314 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) 315 if (t2lm->hw_link_map_tid[tid_num] || 316 t2lm->ieee_link_map_tid[tid_num]) 317 link_mapping_presence_indicator |= BIT(tid_num); 318 319 QDF_SET_BITS(t2lm_control, 320 WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_IDX, 321 WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_BITS, 322 link_mapping_presence_indicator); 323 t2lm_rl_debug("T2LM IE added, direction:%d link_mapping_presence_indicator:%x", 324 t2lm->direction, link_mapping_presence_indicator); 325 326 /* The size of TID-To-Link mapping control is two octets when 327 * default link mapping is not set. 328 */ 329 *(uint16_t *)t2lm_control_field = htole16(t2lm_control); 330 frm += sizeof(*t2lm_ie) + sizeof(uint16_t); 331 t2lm_ie->elem_len += sizeof(uint16_t); 332 } 333 334 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 335 if (vdev_mlme && t2lm->mapping_switch_time_present) { 336 /* Mapping switch time is different for each vdevs. Hence, 337 * populate the mapping switch time from vdev_mlme_obj. 338 */ 339 *(uint16_t *)frm = 340 htole16(vdev_mlme->proto.ap.mapping_switch_time); 341 frm += sizeof(uint16_t); 342 t2lm_ie->elem_len += sizeof(uint16_t); 343 } 344 345 if (t2lm->expected_duration_present) { 346 qdf_mem_copy(frm, &t2lm->expected_duration, 347 WLAN_T2LM_EXPECTED_DURATION_SIZE * 348 sizeof(uint8_t)); 349 frm += WLAN_T2LM_EXPECTED_DURATION_SIZE * sizeof(uint8_t); 350 t2lm_ie->elem_len += 351 WLAN_T2LM_EXPECTED_DURATION_SIZE * sizeof(uint8_t); 352 } 353 354 t2lm_rl_debug("mapping_switch_time:%d expected_duration:%u", 355 t2lm->mapping_switch_time, t2lm->expected_duration); 356 357 if (t2lm->default_link_mapping) 358 return frm; 359 360 link_mapping_of_tids = frm; 361 362 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 363 if (!t2lm->ieee_link_map_tid[tid_num]) 364 continue; 365 366 if (!t2lm->link_mapping_size) { 367 *(uint16_t *)link_mapping_of_tids = 368 htole16(t2lm->ieee_link_map_tid[tid_num]); 369 t2lm_rl_debug("link mapping of TID%d is %x", 370 tid_num, 371 htole16(t2lm->ieee_link_map_tid[tid_num])); 372 link_mapping_of_tids += sizeof(uint16_t); 373 } else { 374 *(uint8_t *)link_mapping_of_tids = 375 t2lm->ieee_link_map_tid[tid_num]; 376 t2lm_rl_debug("link mapping of TID%d is %x", 377 tid_num, 378 t2lm->ieee_link_map_tid[tid_num]); 379 link_mapping_of_tids += sizeof(uint8_t); 380 } 381 num_tids++; 382 } 383 384 if (!t2lm->link_mapping_size) { 385 frm += num_tids * sizeof(uint16_t); 386 t2lm_ie->elem_len += (num_tids * sizeof(uint16_t)); 387 } else { 388 frm += num_tids * sizeof(uint8_t); 389 t2lm_ie->elem_len += (num_tids * sizeof(uint8_t)); 390 } 391 392 return frm; 393 } 394 395 uint8_t *wlan_mlo_add_t2lm_ie(uint8_t *frm, 396 struct wlan_t2lm_onging_negotiation_info *t2lm, 397 struct wlan_objmgr_vdev *vdev) 398 { 399 uint8_t dir; 400 401 if (!frm) { 402 t2lm_err("frm is null"); 403 return NULL; 404 } 405 406 if (!t2lm) { 407 t2lm_err("t2lm is null"); 408 return NULL; 409 } 410 411 /* As per spec, the frame should include one or two T2LM IEs. When it is 412 * two, then direction should DL and UL. 413 */ 414 if ((t2lm->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction == 415 WLAN_T2LM_DL_DIRECTION || 416 t2lm->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction == 417 WLAN_T2LM_UL_DIRECTION) && 418 t2lm->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction == 419 WLAN_T2LM_BIDI_DIRECTION) { 420 t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time"); 421 return NULL; 422 } 423 424 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 425 if (t2lm->t2lm_info[dir].direction != 426 WLAN_T2LM_INVALID_DIRECTION) 427 frm = wlan_mlo_add_t2lm_info_ie(frm, 428 &t2lm->t2lm_info[dir], 429 vdev); 430 } 431 432 return frm; 433 } 434 435 /** 436 * wlan_mlo_parse_t2lm_request_action_frame() - API to parse T2LM request action 437 * frame. 438 * @t2lm: Pointer to T2LM structure 439 * @action_frm: Pointer to action frame 440 * @frame_len: Received frame pointer 441 * @category: T2LM action frame category 442 * 443 * Return: QDF_STATUS 444 */ 445 static QDF_STATUS wlan_mlo_parse_t2lm_request_action_frame( 446 struct wlan_t2lm_onging_negotiation_info *t2lm, 447 struct wlan_action_frame *action_frm, 448 uint32_t frame_len, 449 enum wlan_t2lm_category category) 450 { 451 uint8_t *t2lm_action_frm; 452 453 t2lm->category = category; 454 455 /* 456 * T2LM request action frame 457 * 458 * 1-byte 1-byte 1-byte variable 459 *------------------------------------------- 460 * | | | | | 461 * | Category| Protected | Dialog | T2LM IE | 462 * | | EHT | token | | 463 * | | Action | | | 464 *------------------------------------------- 465 */ 466 467 t2lm_action_frm = (uint8_t *)action_frm + sizeof(*action_frm); 468 469 t2lm->dialog_token = *t2lm_action_frm; 470 471 return wlan_mlo_parse_t2lm_ie(t2lm, 472 t2lm_action_frm + sizeof(uint8_t), 473 frame_len); 474 } 475 476 /** 477 * wlan_mlo_parse_t2lm_response_action_frame() - API to parse T2LM response 478 * action frame. 479 * @t2lm: Pointer to T2LM structure 480 * @action_frm: Pointer to action frame 481 * @frame_len: Action frame length 482 * @category: T2LM action frame category 483 * 484 * Return: QDF_STATUS 485 */ 486 static QDF_STATUS wlan_mlo_parse_t2lm_response_action_frame( 487 struct wlan_t2lm_onging_negotiation_info *t2lm, 488 struct wlan_action_frame *action_frm, 489 uint32_t frame_len, 490 enum wlan_t2lm_category category) 491 { 492 uint8_t *t2lm_action_frm; 493 QDF_STATUS ret_val = QDF_STATUS_SUCCESS; 494 495 t2lm->category = WLAN_T2LM_CATEGORY_RESPONSE; 496 /* 497 * T2LM response action frame 498 * 499 * 1-byte 1-byte 1-byte 2-byte variable 500 *---------------------------------------------------- 501 * | | | | | | 502 * | Category| Protected | Dialog | Status | T2LM IE | 503 * | | EHT | token | code | | 504 * | | Action | | | | 505 *---------------------------------------------------- 506 */ 507 508 t2lm_action_frm = (uint8_t *)action_frm + sizeof(*action_frm); 509 510 t2lm->dialog_token = *t2lm_action_frm; 511 t2lm->t2lm_resp_type = 512 qdf_le16_to_cpu(*(uint16_t *)(t2lm_action_frm + sizeof(uint8_t))); 513 514 if (t2lm->t2lm_resp_type == 515 WLAN_T2LM_RESP_TYPE_PREFERRED_TID_TO_LINK_MAPPING) { 516 t2lm_action_frm += sizeof(uint8_t) + sizeof(uint16_t); 517 ret_val = wlan_mlo_parse_t2lm_ie(t2lm, t2lm_action_frm, 518 frame_len); 519 } 520 521 return ret_val; 522 } 523 524 int wlan_mlo_parse_t2lm_action_frame( 525 struct wlan_t2lm_onging_negotiation_info *t2lm, 526 struct wlan_action_frame *action_frm, 527 uint32_t frame_len, 528 enum wlan_t2lm_category category) 529 { 530 QDF_STATUS ret_val = QDF_STATUS_SUCCESS; 531 532 switch (category) { 533 case WLAN_T2LM_CATEGORY_REQUEST: 534 { 535 ret_val = wlan_mlo_parse_t2lm_request_action_frame( 536 t2lm, action_frm, frame_len, category); 537 return qdf_status_to_os_return(ret_val); 538 } 539 case WLAN_T2LM_CATEGORY_RESPONSE: 540 { 541 ret_val = wlan_mlo_parse_t2lm_response_action_frame( 542 t2lm, action_frm, frame_len, category); 543 544 return qdf_status_to_os_return(ret_val); 545 } 546 case WLAN_T2LM_CATEGORY_TEARDOWN: 547 /* Nothing to parse from T2LM teardown frame, just reset 548 * the mapping to default mapping. 549 * 550 * T2LM teardown action frame 551 * 552 * 1-byte 1-byte 553 *------------------------ 554 * | | | 555 * | Category| Protected | 556 * | | EHT | 557 * | | Action | 558 *------------------------ 559 */ 560 break; 561 default: 562 t2lm_err("Invalid category:%d", category); 563 } 564 565 return ret_val; 566 } 567 568 static uint8_t *wlan_mlo_add_t2lm_request_action_frame( 569 uint8_t *frm, 570 struct wlan_action_frame_args *args, uint8_t *buf, 571 enum wlan_t2lm_category category) 572 { 573 *frm++ = args->category; 574 *frm++ = args->action; 575 /* Dialog token*/ 576 *frm++ = args->arg1; 577 578 t2lm_info("T2LM request frame: category:%d action:%d dialog_token:%d", 579 args->category, args->action, args->arg1); 580 return wlan_mlo_add_t2lm_ie(frm, (void *)buf, NULL); 581 } 582 583 static uint8_t *wlan_mlo_add_t2lm_response_action_frame( 584 uint8_t *frm, 585 struct wlan_action_frame_args *args, uint8_t *buf, 586 enum wlan_t2lm_category category) 587 { 588 *frm++ = args->category; 589 *frm++ = args->action; 590 /* Dialog token*/ 591 *frm++ = args->arg1; 592 /* Status code (2 bytes)*/ 593 *(uint16_t *)frm = htole16(args->arg2); 594 frm += sizeof(uint16_t); 595 596 t2lm_info("T2LM response frame: category:%d action:%d dialog_token:%d status_code:%d", 597 args->category, args->action, args->arg1, args->arg2); 598 599 if (args->arg2 == WLAN_T2LM_RESP_TYPE_PREFERRED_TID_TO_LINK_MAPPING) 600 frm = wlan_mlo_add_t2lm_ie(frm, (void *)buf, NULL); 601 602 return frm; 603 } 604 605 uint8_t *wlan_mlo_add_t2lm_action_frame( 606 uint8_t *frm, 607 struct wlan_action_frame_args *args, uint8_t *buf, 608 enum wlan_t2lm_category category) 609 { 610 611 switch (category) { 612 case WLAN_T2LM_CATEGORY_REQUEST: 613 return wlan_mlo_add_t2lm_request_action_frame(frm, args, 614 buf, category); 615 case WLAN_T2LM_CATEGORY_RESPONSE: 616 return wlan_mlo_add_t2lm_response_action_frame(frm, args, 617 buf, category); 618 case WLAN_T2LM_CATEGORY_TEARDOWN: 619 *frm++ = args->category; 620 *frm++ = args->action; 621 return frm; 622 default: 623 t2lm_err("Invalid category:%d", category); 624 } 625 626 return frm; 627 } 628 629 /** 630 * wlan_mlo_t2lm_handle_mapping_switch_time_expiry() - API to handle the mapping 631 * switch timer expiry. 632 * @t2lm_ctx: Pointer to T2LM context 633 * @vdev: Pointer to vdev structure 634 * 635 * Return: None 636 */ 637 static void wlan_mlo_t2lm_handle_mapping_switch_time_expiry( 638 struct wlan_t2lm_context *t2lm_ctx, 639 struct wlan_objmgr_vdev *vdev) 640 { 641 struct wlan_t2lm_info *t2lm; 642 643 t2lm_debug("Mapping switch time expired for vdev_id:%d ", 644 wlan_vdev_get_id(vdev)); 645 646 qdf_mem_copy(&t2lm_ctx->established_t2lm, &t2lm_ctx->upcoming_t2lm, 647 sizeof(struct wlan_mlo_t2lm_ie)); 648 649 t2lm_ctx->established_t2lm.t2lm.mapping_switch_time_present = false; 650 t2lm_ctx->established_t2lm.t2lm.mapping_switch_time = 0; 651 652 t2lm = &t2lm_ctx->established_t2lm.t2lm; 653 t2lm_debug("Established mapping: disabled_link_bitmap:%x dir:%d default_map:%d MSTP:%d EDP:%d MST:%d ED:%d ieee_link_map:%x hw_link_map:%x", 654 t2lm_ctx->established_t2lm.disabled_link_bitmap, 655 t2lm->direction, t2lm->default_link_mapping, 656 t2lm->mapping_switch_time_present, 657 t2lm->expected_duration_present, 658 t2lm->mapping_switch_time, t2lm->expected_duration, 659 t2lm->ieee_link_map_tid[0], t2lm->hw_link_map_tid[0]); 660 661 qdf_mem_zero(&t2lm_ctx->upcoming_t2lm, sizeof(struct wlan_mlo_t2lm_ie)); 662 t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION; 663 } 664 665 /** 666 * wlan_mlo_t2lm_handle_expected_duration_expiry() - API to handle the expected 667 * duration timer expiry. 668 * @t2lm_ctx: Pointer to T2LM context 669 * @vdev: Pointer to vdev structure 670 * 671 * Return: none 672 */ 673 static void wlan_mlo_t2lm_handle_expected_duration_expiry( 674 struct wlan_t2lm_context *t2lm_ctx, 675 struct wlan_objmgr_vdev *vdev) 676 { 677 t2lm_debug("Expected duration expired for vdev_id:%d ", 678 wlan_vdev_get_id(vdev)); 679 680 if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) { 681 /* Copy the new non-default ongoing mapping to established 682 * mapping if expected duration expires for the established 683 * mapping. 684 */ 685 wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, 686 vdev); 687 return; 688 } 689 690 /* Use the default mapping when expected duration expires for the 691 * established mapping and no new non-default T2LM announcement is 692 * ongoing. 693 */ 694 qdf_mem_zero(&t2lm_ctx->established_t2lm, 695 sizeof(struct wlan_mlo_t2lm_ie)); 696 697 t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_BIDI_DIRECTION; 698 t2lm_ctx->established_t2lm.t2lm.default_link_mapping = 1; 699 t2lm_ctx->established_t2lm.disabled_link_bitmap = 0; 700 t2lm_ctx->established_t2lm.t2lm.link_mapping_size = 0; 701 t2lm_debug("Set established mapping to default mapping"); 702 703 wlan_clear_peer_level_tid_to_link_mapping(vdev); 704 } 705 706 QDF_STATUS wlan_mlo_vdev_tid_to_link_map_event( 707 struct wlan_objmgr_psoc *psoc, 708 struct mlo_vdev_host_tid_to_link_map_resp *event) 709 { 710 struct wlan_objmgr_vdev *vdev; 711 struct wlan_t2lm_context *t2lm_ctx; 712 struct vdev_mlme_obj *vdev_mlme; 713 714 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id, 715 WLAN_MLO_MGR_ID); 716 if (!vdev) { 717 t2lm_err("null vdev"); 718 return QDF_STATUS_E_NULL_VALUE; 719 } 720 721 if (!vdev->mlo_dev_ctx) { 722 t2lm_err("null mlo_dev_ctx"); 723 return QDF_STATUS_E_NULL_VALUE; 724 } 725 726 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 727 if (!vdev_mlme) { 728 t2lm_err("null vdev_mlme"); 729 return QDF_STATUS_E_FAILURE; 730 } 731 732 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx; 733 734 t2lm_debug("psoc_id:%d vdev_id:%d status:%d", 735 wlan_psoc_get_id(psoc), event->vdev_id, event->status); 736 737 t2lm_dev_lock_acquire(t2lm_ctx); 738 switch (event->status) { 739 case WLAN_MAP_SWITCH_TIMER_TSF: 740 741 /* Mapping switch time is different for each AP vdev of a given 742 * MLD as these vdevs can have separate beacon TDF value. 743 */ 744 if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) 745 vdev_mlme->proto.ap.mapping_switch_time = 746 (event->mapping_switch_tsf & 747 WLAN_T2LM_MAPPING_SWITCH_TSF_BITS) >> 10; 748 749 t2lm_debug("vdev_id:%d updated mapping switch time:%d", 750 event->vdev_id, 751 vdev_mlme->proto.ap.mapping_switch_time); 752 break; 753 case WLAN_MAP_SWITCH_TIMER_EXPIRED: 754 vdev_mlme->proto.ap.mapping_switch_time = 0; 755 wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, vdev); 756 757 /* Notify the registered caller about the link update*/ 758 wlan_mlo_dev_t2lm_notify_link_update(vdev, 759 &t2lm_ctx->established_t2lm.t2lm); 760 break; 761 case WLAN_EXPECTED_DUR_EXPIRED: 762 wlan_mlo_t2lm_handle_expected_duration_expiry(t2lm_ctx, vdev); 763 764 /* Notify the registered caller about the link update*/ 765 wlan_mlo_dev_t2lm_notify_link_update(vdev, 766 &t2lm_ctx->established_t2lm.t2lm); 767 break; 768 default: 769 t2lm_err("Invalid status"); 770 } 771 772 t2lm_dev_lock_release(t2lm_ctx); 773 mlo_release_vdev_ref(vdev); 774 775 return QDF_STATUS_SUCCESS; 776 } 777 778 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 779 static 780 QDF_STATUS wlan_send_t2lm_info(struct wlan_objmgr_vdev *vdev, 781 struct wlan_t2lm_info *t2lm, 782 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 783 { 784 QDF_STATUS status = QDF_STATUS_E_FAILURE; 785 786 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 787 t2lm_err("vdev is not MLO vdev"); 788 return status; 789 } 790 791 status = mlo_tx_ops->send_tid_to_link_mapping(vdev, t2lm); 792 if (QDF_IS_STATUS_ERROR(status)) 793 t2lm_err("Failed to send T2LM command to FW"); 794 795 return status; 796 } 797 #else 798 static 799 QDF_STATUS wlan_send_t2lm_info(struct wlan_objmgr_vdev *vdev, 800 struct wlan_t2lm_info *t2lm, 801 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 802 { 803 struct wlan_objmgr_vdev *co_mld_vdev; 804 struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS]; 805 uint16_t vdev_count = 0; 806 int i = 0; 807 QDF_STATUS status = QDF_STATUS_E_FAILURE; 808 809 mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list); 810 if (!vdev_count) { 811 t2lm_err("Number of VDEVs under MLD is reported as 0"); 812 return QDF_STATUS_E_NULL_VALUE; 813 } 814 815 for (i = 0; i < vdev_count; i++) { 816 co_mld_vdev = wlan_vdev_list[i]; 817 if (!co_mld_vdev) { 818 t2lm_err("co_mld_vdev is null"); 819 mlo_release_vdev_ref(co_mld_vdev); 820 continue; 821 } 822 823 status = mlo_tx_ops->send_tid_to_link_mapping(co_mld_vdev, 824 t2lm); 825 if (QDF_IS_STATUS_ERROR(status)) 826 t2lm_err("Failed to send T2LM command to FW"); 827 mlo_release_vdev_ref(co_mld_vdev); 828 } 829 830 return status; 831 } 832 #endif 833 834 QDF_STATUS wlan_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev, 835 struct wlan_t2lm_info *t2lm) 836 { 837 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 838 struct wlan_objmgr_psoc *psoc; 839 QDF_STATUS status = QDF_STATUS_E_FAILURE; 840 841 psoc = wlan_vdev_get_psoc(vdev); 842 if (!psoc) { 843 t2lm_err("null psoc"); 844 return QDF_STATUS_E_NULL_VALUE; 845 } 846 847 mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops; 848 if (!mlo_tx_ops) { 849 t2lm_err("tx_ops is null!"); 850 return QDF_STATUS_E_NULL_VALUE; 851 } 852 853 if (!mlo_tx_ops->send_tid_to_link_mapping) { 854 t2lm_err("send_tid_to_link_mapping is null"); 855 return QDF_STATUS_E_NULL_VALUE; 856 } 857 858 status = wlan_send_t2lm_info(vdev, t2lm, mlo_tx_ops); 859 860 return status; 861 } 862 863 /** 864 * wlan_get_vdev_t2lm_mapping_status() - API to get vdev level T2LM info 865 * @vdev: vdev object 866 * @t2lm: T2LM info 867 * 868 * Return: QDF_STATUS 869 */ 870 static 871 QDF_STATUS wlan_get_vdev_t2lm_mapping_status(struct wlan_objmgr_vdev *vdev, 872 struct wlan_t2lm_info *t2lm) 873 { 874 struct wlan_t2lm_context *t2lm_ctx; 875 int i = 0; 876 877 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx; 878 879 t2lm_dev_lock_acquire(t2lm_ctx); 880 qdf_mem_copy(&t2lm[i++], &t2lm_ctx->established_t2lm.t2lm, 881 sizeof(struct wlan_t2lm_info)); 882 t2lm_dev_lock_release(t2lm_ctx); 883 884 return QDF_STATUS_SUCCESS; 885 } 886 887 /** 888 * wlan_get_peer_t2lm_mapping_status() - API to get peer level T2LM info 889 * @peer: peer object 890 * @t2lm: T2LM info 891 * 892 * Return: QDF_STATUS 893 */ 894 static 895 QDF_STATUS wlan_get_peer_t2lm_mapping_status(struct wlan_objmgr_peer *peer, 896 struct wlan_t2lm_info *t2lm) 897 { 898 enum wlan_t2lm_direction dir = WLAN_T2LM_INVALID_DIRECTION; 899 struct wlan_mlo_peer_context *ml_peer; 900 struct wlan_prev_t2lm_negotiated_info *t2lm_req; 901 int i = 0; 902 903 ml_peer = peer->mlo_peer_ctx; 904 if (!ml_peer) 905 return QDF_STATUS_E_FAILURE; 906 907 t2lm_req = &ml_peer->t2lm_policy.t2lm_negotiated_info; 908 if ((t2lm_req->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction == 909 WLAN_T2LM_DL_DIRECTION || 910 t2lm_req->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction == 911 WLAN_T2LM_UL_DIRECTION) && 912 t2lm_req->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction == 913 WLAN_T2LM_BIDI_DIRECTION) { 914 t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time"); 915 return QDF_STATUS_E_FAILURE; 916 } 917 918 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 919 if (t2lm_req->t2lm_info[dir].direction != 920 WLAN_T2LM_INVALID_DIRECTION) 921 qdf_mem_copy(&t2lm[i++], &t2lm_req->t2lm_info[dir], 922 sizeof(struct wlan_t2lm_info)); 923 } 924 925 if (i == 0) 926 return QDF_STATUS_E_EMPTY; 927 928 return QDF_STATUS_SUCCESS; 929 } 930 931 QDF_STATUS wlan_get_t2lm_mapping_status(struct wlan_objmgr_vdev *vdev, 932 struct wlan_t2lm_info *t2lm) 933 { 934 struct wlan_objmgr_peer *peer; 935 QDF_STATUS status = QDF_STATUS_E_FAILURE; 936 937 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 938 if (!peer) { 939 t2lm_err("peer not found"); 940 return QDF_STATUS_E_NULL_VALUE; 941 } 942 943 status = wlan_get_peer_t2lm_mapping_status(peer, t2lm); 944 if (QDF_IS_STATUS_SUCCESS(status)) { 945 t2lm_debug("peer level T2LM info"); 946 goto peer_release; 947 } 948 949 t2lm_debug("vdev level T2LM info"); 950 status = wlan_get_vdev_t2lm_mapping_status(vdev, t2lm); 951 952 peer_release: 953 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 954 955 return status; 956 } 957 958 QDF_STATUS 959 wlan_send_peer_level_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev, 960 struct wlan_objmgr_peer *peer) 961 { 962 uint8_t dir, idx = 0; 963 struct wlan_mlo_peer_context *ml_peer; 964 struct wlan_t2lm_info *t2lm_info; 965 QDF_STATUS status = QDF_STATUS_E_NULL_VALUE; 966 967 if (!peer) { 968 t2lm_err("peer is null"); 969 return status; 970 } 971 972 ml_peer = peer->mlo_peer_ctx; 973 if (!ml_peer) { 974 t2lm_err("ml peer is null"); 975 return status; 976 } 977 978 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 979 t2lm_info = &ml_peer->t2lm_policy.t2lm_negotiated_info.t2lm_info[dir]; 980 if (t2lm_info && t2lm_info->direction != 981 WLAN_T2LM_INVALID_DIRECTION) { 982 t2lm_debug("send peer-level mapping to FW for dir: %d", dir); 983 984 /* Notify the registered caller about the link update*/ 985 wlan_mlo_dev_t2lm_notify_link_update(vdev, t2lm_info); 986 status = wlan_send_tid_to_link_mapping(vdev, t2lm_info); 987 idx++; 988 } 989 } 990 991 if (!idx) 992 t2lm_debug("No peer-level mapping present"); 993 994 return status; 995 } 996 997 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 998 void 999 wlan_clear_peer_level_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev) 1000 { 1001 struct wlan_objmgr_peer *peer; 1002 1003 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 1004 if (!peer) { 1005 t2lm_err("Peer not found"); 1006 return; 1007 } 1008 1009 wlan_t2lm_clear_peer_negotiation(peer); 1010 1011 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 1012 } 1013 #endif 1014 1015 void wlan_mlo_t2lm_timer_expiry_handler(void *vdev) 1016 { 1017 struct wlan_objmgr_vdev *vdev_ctx = (struct wlan_objmgr_vdev *)vdev; 1018 1019 struct wlan_t2lm_timer *t2lm_timer; 1020 struct wlan_t2lm_context *t2lm_ctx; 1021 1022 if (!vdev_ctx || !vdev_ctx->mlo_dev_ctx) 1023 return; 1024 1025 t2lm_ctx = &vdev_ctx->mlo_dev_ctx->t2lm_ctx; 1026 t2lm_timer = &vdev_ctx->mlo_dev_ctx->t2lm_ctx.t2lm_timer; 1027 1028 wlan_mlo_t2lm_timer_stop(vdev_ctx); 1029 1030 /* Since qdf_mutex_acquire cannot be called from interrupt context, 1031 * change needed to create a workqueue and offload the timer expiry 1032 * handling to workqueue. 1033 */ 1034 if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present) { 1035 wlan_mlo_t2lm_handle_expected_duration_expiry(t2lm_ctx, vdev); 1036 1037 /* Notify the registered caller about the link update*/ 1038 wlan_mlo_dev_t2lm_notify_link_update(vdev_ctx, 1039 &t2lm_ctx->established_t2lm.t2lm); 1040 wlan_send_tid_to_link_mapping( 1041 vdev, &t2lm_ctx->established_t2lm.t2lm); 1042 1043 wlan_handle_t2lm_timer(vdev_ctx); 1044 } else if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) { 1045 wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, vdev); 1046 1047 /* Notify the registered caller about the link update*/ 1048 wlan_mlo_dev_t2lm_notify_link_update(vdev_ctx, 1049 &t2lm_ctx->established_t2lm.t2lm); 1050 wlan_send_tid_to_link_mapping( 1051 vdev, &t2lm_ctx->established_t2lm.t2lm); 1052 wlan_handle_t2lm_timer(vdev_ctx); 1053 } 1054 1055 } 1056 1057 QDF_STATUS 1058 wlan_mlo_t2lm_timer_init(struct wlan_objmgr_vdev *vdev) 1059 { 1060 struct wlan_t2lm_timer *t2lm_timer = NULL; 1061 1062 if (!vdev || !vdev->mlo_dev_ctx) 1063 return QDF_STATUS_E_FAILURE; 1064 1065 t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer; 1066 if (!t2lm_timer) { 1067 t2lm_err("t2lm timer ctx is null"); 1068 return QDF_STATUS_E_NULL_VALUE; 1069 } 1070 1071 t2lm_dev_lock_create(&vdev->mlo_dev_ctx->t2lm_ctx); 1072 t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx); 1073 qdf_timer_init(NULL, &t2lm_timer->t2lm_timer, 1074 wlan_mlo_t2lm_timer_expiry_handler, 1075 vdev, QDF_TIMER_TYPE_WAKE_APPS); 1076 1077 t2lm_timer->timer_started = false; 1078 t2lm_timer->timer_interval = 0; 1079 t2lm_timer->timer_out_time = 0; 1080 t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx); 1081 return QDF_STATUS_SUCCESS; 1082 } 1083 1084 QDF_STATUS 1085 wlan_mlo_t2lm_timer_start(struct wlan_objmgr_vdev *vdev, 1086 uint32_t interval) 1087 { 1088 struct wlan_t2lm_timer *t2lm_timer; 1089 struct wlan_t2lm_context *t2lm_ctx; 1090 uint32_t target_out_time; 1091 struct wlan_mlo_dev_context *mlo_dev_ctx; 1092 1093 if (!interval) { 1094 t2lm_debug("Timer interval is 0"); 1095 return QDF_STATUS_E_NULL_VALUE; 1096 } 1097 1098 if (!vdev) 1099 return QDF_STATUS_E_NULL_VALUE; 1100 1101 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 1102 if (!mlo_dev_ctx) 1103 return QDF_STATUS_E_NULL_VALUE; 1104 1105 t2lm_ctx = &mlo_dev_ctx->t2lm_ctx; 1106 t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer; 1107 if (!t2lm_timer) { 1108 t2lm_err("t2lm timer ctx is null"); 1109 return QDF_STATUS_E_NULL_VALUE; 1110 } 1111 1112 interval = (interval * 1024) / 1000; 1113 target_out_time = qdf_system_ticks_to_msecs(qdf_system_ticks()); 1114 target_out_time += interval; 1115 t2lm_debug("earlier timer @%u ms out, new @%u ms out", 1116 t2lm_timer->timer_out_time, target_out_time); 1117 1118 /* sometimes the host process the beacon maybe delay, it may help for 1119 * update the new expected time. 1120 */ 1121 if (t2lm_timer->timer_out_time && 1122 (target_out_time > t2lm_timer->timer_out_time || 1123 (t2lm_timer->timer_out_time - target_out_time) < 1124 WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY)) 1125 return QDF_STATUS_E_NULL_VALUE; 1126 1127 if (t2lm_timer->timer_started) 1128 qdf_timer_stop(&t2lm_timer->t2lm_timer); 1129 1130 t2lm_debug("t2lm timer started with interval %d ms", interval); 1131 t2lm_timer->timer_interval = interval; 1132 t2lm_timer->timer_started = true; 1133 t2lm_timer->timer_out_time = target_out_time; 1134 qdf_timer_start(&t2lm_timer->t2lm_timer, t2lm_timer->timer_interval); 1135 1136 return QDF_STATUS_SUCCESS; 1137 } 1138 1139 QDF_STATUS 1140 wlan_mlo_t2lm_timer_stop(struct wlan_objmgr_vdev *vdev) 1141 { 1142 struct wlan_t2lm_timer *t2lm_timer; 1143 1144 if (!vdev || !vdev->mlo_dev_ctx) 1145 return QDF_STATUS_E_NULL_VALUE; 1146 1147 t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer; 1148 if (!t2lm_timer) { 1149 t2lm_err("t2lm timer ctx is null"); 1150 return QDF_STATUS_E_NULL_VALUE; 1151 } 1152 1153 if (t2lm_timer->timer_started) { 1154 qdf_timer_stop(&t2lm_timer->t2lm_timer); 1155 t2lm_timer->timer_started = false; 1156 t2lm_timer->timer_interval = 0; 1157 t2lm_timer->timer_out_time = 0; 1158 } 1159 return QDF_STATUS_SUCCESS; 1160 } 1161 1162 QDF_STATUS wlan_handle_t2lm_timer(struct wlan_objmgr_vdev *vdev) 1163 { 1164 struct wlan_t2lm_context *t2lm_ctx; 1165 struct vdev_mlme_obj *vdev_mlme; 1166 QDF_STATUS status = QDF_STATUS_SUCCESS; 1167 1168 if (!vdev || !vdev->mlo_dev_ctx) 1169 return QDF_STATUS_E_NULL_VALUE; 1170 1171 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx; 1172 1173 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 1174 if (!vdev_mlme) 1175 return QDF_STATUS_E_FAILURE; 1176 1177 if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present) { 1178 if (t2lm_ctx->established_t2lm.t2lm.expected_duration == 1179 T2LM_EXPECTED_DURATION_MAX_VALUE) { 1180 return status; 1181 } 1182 1183 status = wlan_mlo_t2lm_timer_start( 1184 vdev, 1185 t2lm_ctx->established_t2lm.t2lm.expected_duration); 1186 } else if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) { 1187 status = wlan_mlo_t2lm_timer_start( 1188 vdev, 1189 t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time); 1190 } 1191 1192 return status; 1193 } 1194 1195 /** 1196 * wlan_update_mapping_switch_time_expected_dur() - API to update the mapping 1197 * switch time and expected duration. 1198 * @vdev:Pointer to vdev 1199 * @rx_t2lm: Pointer to received T2LM IE 1200 * @tsf: TSF value of beacon/probe response 1201 * 1202 * Return: None 1203 */ 1204 static QDF_STATUS wlan_update_mapping_switch_time_expected_dur( 1205 struct wlan_objmgr_vdev *vdev, 1206 struct wlan_t2lm_context *rx_t2lm, uint64_t tsf) 1207 { 1208 struct wlan_t2lm_context *t2lm_ctx; 1209 uint16_t tsf_bit25_10, ms_time; 1210 struct wlan_mlo_dev_context *mlo_dev_ctx; 1211 1212 if (!vdev) 1213 return QDF_STATUS_E_NULL_VALUE; 1214 1215 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 1216 if (!mlo_dev_ctx) 1217 return QDF_STATUS_E_NULL_VALUE; 1218 1219 tsf_bit25_10 = (tsf & WLAN_T2LM_MAPPING_SWITCH_TSF_BITS) >> 10; 1220 t2lm_ctx = &mlo_dev_ctx->t2lm_ctx; 1221 1222 t2lm_dev_lock_acquire(t2lm_ctx); 1223 1224 if ((t2lm_ctx->established_t2lm.t2lm.expected_duration_present && 1225 rx_t2lm->established_t2lm.t2lm.expected_duration_present) && 1226 (rx_t2lm->established_t2lm.t2lm.expected_duration < 1227 t2lm_ctx->established_t2lm.t2lm.expected_duration)) { 1228 /* Established T2LM is already saved in the T2LM context. 1229 * T2LM IE in the beacon/probe response frame has the updated 1230 * expected duration. 1231 */ 1232 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid, 1233 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid, 1234 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) { 1235 t2lm_ctx->established_t2lm.t2lm.expected_duration = 1236 rx_t2lm->established_t2lm.t2lm.expected_duration; 1237 } 1238 } else if (rx_t2lm->established_t2lm.t2lm.expected_duration_present && 1239 !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present) { 1240 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid, 1241 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid, 1242 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) { 1243 t2lm_debug("T2LM mapping is already configured"); 1244 t2lm_dev_lock_release(t2lm_ctx); 1245 return QDF_STATUS_E_ALREADY; 1246 } 1247 1248 /* Mapping switch time is already expired when STA receives the 1249 * T2LM IE from beacon/probe response frame. 1250 */ 1251 qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm, 1252 &rx_t2lm->established_t2lm.t2lm, 1253 sizeof(struct wlan_t2lm_info)); 1254 1255 /* Notify the registered caller about the link update*/ 1256 wlan_mlo_dev_t2lm_notify_link_update(vdev, 1257 &t2lm_ctx->established_t2lm.t2lm); 1258 wlan_clear_peer_level_tid_to_link_mapping(vdev); 1259 wlan_send_tid_to_link_mapping( 1260 vdev, &t2lm_ctx->established_t2lm.t2lm); 1261 } 1262 1263 if (rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) { 1264 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid, 1265 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid, 1266 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) { 1267 t2lm_debug("Ongoing mapping is already established"); 1268 t2lm_dev_lock_release(t2lm_ctx); 1269 return QDF_STATUS_E_ALREADY; 1270 } 1271 1272 qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm, 1273 &rx_t2lm->upcoming_t2lm.t2lm, 1274 sizeof(struct wlan_t2lm_info)); 1275 1276 ms_time = t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time; 1277 /* Per test, -300ms is fine */ 1278 if (ms_time > tsf_bit25_10) { 1279 t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time = 1280 (ms_time - tsf_bit25_10 - (3 * WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY)); 1281 } else { 1282 t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time = 1283 0xFFFF - (tsf_bit25_10 - ms_time) - (3 * WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY); 1284 } 1285 } 1286 1287 t2lm_dev_lock_release(t2lm_ctx); 1288 1289 return QDF_STATUS_SUCCESS; 1290 } 1291 1292 QDF_STATUS wlan_process_bcn_prbrsp_t2lm_ie( 1293 struct wlan_objmgr_vdev *vdev, 1294 struct wlan_t2lm_context *rx_t2lm_ie, uint64_t tsf) 1295 { 1296 struct wlan_t2lm_context *t2lm_ctx; 1297 QDF_STATUS status; 1298 struct wlan_mlo_dev_context *mlo_dev_ctx; 1299 1300 /* Do not parse the T2LM IE if STA is not in connected state */ 1301 if (!wlan_cm_is_vdev_connected(vdev)) 1302 return QDF_STATUS_SUCCESS; 1303 1304 if (!vdev) 1305 return QDF_STATUS_E_NULL_VALUE; 1306 1307 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 1308 if (!mlo_dev_ctx) 1309 return QDF_STATUS_E_NULL_VALUE; 1310 1311 t2lm_ctx = &mlo_dev_ctx->t2lm_ctx; 1312 1313 status = wlan_update_mapping_switch_time_expected_dur( 1314 vdev, rx_t2lm_ie, tsf); 1315 if (QDF_IS_STATUS_ERROR(status)) 1316 return status; 1317 1318 t2lm_dev_lock_acquire(t2lm_ctx); 1319 if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present || 1320 t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) { 1321 wlan_handle_t2lm_timer(vdev); 1322 } 1323 t2lm_dev_lock_release(t2lm_ctx); 1324 1325 return QDF_STATUS_SUCCESS; 1326 } 1327 1328 int wlan_register_t2lm_link_update_notify_handler( 1329 wlan_mlo_t2lm_link_update_handler handler, 1330 struct wlan_mlo_dev_context *mldev) 1331 { 1332 struct wlan_t2lm_context *t2lm_ctx = &mldev->t2lm_ctx; 1333 int i; 1334 1335 for (i = 0; i < MAX_T2LM_HANDLERS; i++) { 1336 if (t2lm_ctx->is_valid_handler[i]) 1337 continue; 1338 1339 t2lm_ctx->link_update_handler[i] = handler; 1340 t2lm_ctx->is_valid_handler[i] = true; 1341 break; 1342 } 1343 1344 if (i == MAX_T2LM_HANDLERS) { 1345 t2lm_err("Failed to register the link disablement callback"); 1346 return -EINVAL; 1347 } 1348 1349 return i; 1350 } 1351 1352 void wlan_unregister_t2lm_link_update_notify_handler( 1353 struct wlan_mlo_dev_context *mldev, 1354 uint8_t index) 1355 { 1356 if (index >= MAX_T2LM_HANDLERS) 1357 return; 1358 1359 mldev->t2lm_ctx.link_update_handler[index] = NULL; 1360 mldev->t2lm_ctx.is_valid_handler[index] = false; 1361 } 1362 1363 QDF_STATUS wlan_mlo_dev_t2lm_notify_link_update( 1364 struct wlan_objmgr_vdev *vdev, 1365 struct wlan_t2lm_info *t2lm) 1366 { 1367 struct wlan_t2lm_context *t2lm_ctx; 1368 wlan_mlo_t2lm_link_update_handler handler; 1369 int i; 1370 1371 if (!vdev || !vdev->mlo_dev_ctx) 1372 return QDF_STATUS_E_FAILURE; 1373 1374 if (!wlan_cm_is_vdev_connected(vdev)) { 1375 t2lm_err("Not associated!"); 1376 return QDF_STATUS_E_AGAIN; 1377 } 1378 1379 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1380 t2lm_err("failed due to non-ML connection"); 1381 return QDF_STATUS_E_INVAL; 1382 } 1383 1384 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx; 1385 for (i = 0; i < MAX_T2LM_HANDLERS; i++) { 1386 if (!t2lm_ctx->is_valid_handler[i]) 1387 continue; 1388 1389 handler = t2lm_ctx->link_update_handler[i]; 1390 if (!handler) 1391 continue; 1392 1393 handler(vdev, t2lm); 1394 } 1395 return QDF_STATUS_SUCCESS; 1396 } 1397 1398 QDF_STATUS 1399 wlan_mlo_t2lm_timer_deinit(struct wlan_objmgr_vdev *vdev) 1400 { 1401 struct wlan_t2lm_timer *t2lm_timer = NULL; 1402 1403 if (!vdev || !vdev->mlo_dev_ctx) 1404 return QDF_STATUS_E_FAILURE; 1405 1406 t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer; 1407 if (!t2lm_timer) { 1408 t2lm_err("t2lm timer ctx is null"); 1409 return QDF_STATUS_E_NULL_VALUE; 1410 } 1411 1412 t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx); 1413 t2lm_timer->timer_started = false; 1414 t2lm_timer->timer_interval = 0; 1415 t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx); 1416 qdf_timer_free(&t2lm_timer->t2lm_timer); 1417 t2lm_dev_lock_destroy(&vdev->mlo_dev_ctx->t2lm_ctx); 1418 return QDF_STATUS_SUCCESS; 1419 } 1420 1421 #if defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) && defined(WLAN_FEATURE_11BE) 1422 QDF_STATUS 1423 wlan_mlo_link_disable_request_handler(struct wlan_objmgr_psoc *psoc, 1424 void *evt_params) 1425 { 1426 struct wlan_objmgr_vdev *vdev; 1427 QDF_STATUS status = QDF_STATUS_SUCCESS; 1428 uint8_t vdev_id; 1429 bool is_connected = false; 1430 struct mlo_link_disable_request_evt_params *params; 1431 1432 if (!psoc) 1433 return QDF_STATUS_E_NULL_VALUE; 1434 1435 if (!evt_params) { 1436 t2lm_err("event params is null"); 1437 return QDF_STATUS_E_NULL_VALUE; 1438 } 1439 1440 params = (struct mlo_link_disable_request_evt_params *)evt_params; 1441 if (qdf_is_macaddr_zero(¶ms->mld_addr)) { 1442 t2lm_err("mld mac addr in event params is null"); 1443 return QDF_STATUS_E_NULL_VALUE; 1444 } 1445 1446 if (!params->link_id_bitmap) { 1447 t2lm_debug("Link id bitmap is 0, no action frame to be sent"); 1448 return QDF_STATUS_SUCCESS; 1449 } 1450 1451 is_connected = wlan_get_connected_vdev_by_mld_addr(psoc, 1452 params->mld_addr.bytes, 1453 &vdev_id); 1454 if (!is_connected) { 1455 t2lm_err("Not connected to peer MLD " QDF_MAC_ADDR_FMT, 1456 QDF_MAC_ADDR_REF(params->mld_addr.bytes)); 1457 return QDF_STATUS_E_FAILURE; 1458 } 1459 1460 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 1461 WLAN_MLO_MGR_ID); 1462 if (!vdev) { 1463 t2lm_err("vdev is null"); 1464 return QDF_STATUS_E_NULL_VALUE; 1465 } 1466 1467 status = wlan_populate_link_disable_t2lm_frame(vdev, params); 1468 1469 if (QDF_IS_STATUS_ERROR(status)) 1470 t2lm_err("Failed to handle link disable"); 1471 1472 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 1473 return status; 1474 } 1475 #endif 1476 1477