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