1 /* 2 * Copyright (c) 2022 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: wlan_twt_common.c 19 */ 20 #include "include/wlan_mlme_cmn.h" 21 #include "wlan_twt_common.h" 22 #include "wlan_twt_priv.h" 23 #include <wlan_twt_public_structs.h> 24 #include <wlan_objmgr_peer_obj.h> 25 #include <wlan_twt_tgt_if_tx_api.h> 26 #include "twt/core/src/wlan_twt_cfg.h" 27 28 QDF_STATUS 29 wlan_twt_tgt_caps_get_requestor(struct wlan_objmgr_psoc *psoc, bool *val) 30 { 31 struct twt_psoc_priv_obj *twt_psoc; 32 33 if (!psoc) { 34 twt_err("null psoc"); 35 return QDF_STATUS_E_FAILURE; 36 } 37 38 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 39 WLAN_UMAC_COMP_TWT); 40 if (!twt_psoc) { 41 twt_err("null twt psoc priv obj"); 42 return QDF_STATUS_E_FAILURE; 43 } 44 45 *val = twt_psoc->twt_caps.twt_requestor; 46 return QDF_STATUS_SUCCESS; 47 } 48 49 QDF_STATUS 50 wlan_twt_tgt_caps_get_responder(struct wlan_objmgr_psoc *psoc, bool *val) 51 { 52 struct twt_psoc_priv_obj *twt_psoc; 53 54 if (!psoc) { 55 twt_err("null psoc"); 56 return QDF_STATUS_E_FAILURE; 57 } 58 59 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 60 WLAN_UMAC_COMP_TWT); 61 if (!twt_psoc) { 62 twt_err("null twt psoc priv obj"); 63 return QDF_STATUS_E_FAILURE; 64 } 65 66 *val = twt_psoc->twt_caps.twt_responder; 67 return QDF_STATUS_SUCCESS; 68 } 69 70 QDF_STATUS 71 wlan_twt_tgt_caps_get_legacy_bcast_support(struct wlan_objmgr_psoc *psoc, 72 bool *val) 73 { 74 struct twt_psoc_priv_obj *twt_psoc; 75 76 if (!psoc) { 77 twt_err("null psoc"); 78 return QDF_STATUS_E_FAILURE; 79 } 80 81 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 82 WLAN_UMAC_COMP_TWT); 83 if (!twt_psoc) { 84 twt_err("null twt psoc priv obj"); 85 return QDF_STATUS_E_FAILURE; 86 } 87 88 *val = twt_psoc->twt_caps.legacy_bcast_twt_support; 89 return QDF_STATUS_SUCCESS; 90 } 91 92 QDF_STATUS 93 wlan_twt_tgt_caps_get_bcast_req_support(struct wlan_objmgr_psoc *psoc, 94 bool *val) 95 { 96 struct twt_psoc_priv_obj *twt_psoc; 97 98 if (!psoc) { 99 twt_err("null psoc"); 100 return QDF_STATUS_E_FAILURE; 101 } 102 103 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 104 WLAN_UMAC_COMP_TWT); 105 if (!twt_psoc) { 106 twt_err("null twt psoc priv obj"); 107 return QDF_STATUS_E_FAILURE; 108 } 109 110 *val = twt_psoc->twt_caps.twt_bcast_req_support; 111 return QDF_STATUS_SUCCESS; 112 } 113 114 QDF_STATUS 115 wlan_twt_tgt_caps_get_bcast_res_support(struct wlan_objmgr_psoc *psoc, 116 bool *val) 117 { 118 struct twt_psoc_priv_obj *twt_psoc; 119 120 if (!psoc) { 121 twt_err("null psoc"); 122 return QDF_STATUS_E_FAILURE; 123 } 124 125 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 126 WLAN_UMAC_COMP_TWT); 127 if (!twt_psoc) { 128 twt_err("null twt psoc priv obj"); 129 return QDF_STATUS_E_FAILURE; 130 } 131 132 *val = twt_psoc->twt_caps.twt_bcast_res_support; 133 return QDF_STATUS_SUCCESS; 134 } 135 136 QDF_STATUS 137 wlan_twt_tgt_caps_get_nudge_enabled(struct wlan_objmgr_psoc *psoc, 138 bool *val) 139 { 140 struct twt_psoc_priv_obj *twt_psoc; 141 142 if (!psoc) { 143 twt_err("null psoc"); 144 return QDF_STATUS_E_FAILURE; 145 } 146 147 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 148 WLAN_UMAC_COMP_TWT); 149 if (!twt_psoc) { 150 twt_err("null twt psoc priv obj"); 151 return QDF_STATUS_E_FAILURE; 152 } 153 154 *val = twt_psoc->twt_caps.twt_nudge_enabled; 155 return QDF_STATUS_SUCCESS; 156 } 157 158 QDF_STATUS 159 wlan_twt_tgt_caps_get_all_twt_enabled(struct wlan_objmgr_psoc *psoc, 160 bool *val) 161 { 162 struct twt_psoc_priv_obj *twt_psoc; 163 164 if (!psoc) { 165 twt_err("null psoc"); 166 return QDF_STATUS_E_FAILURE; 167 } 168 169 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 170 WLAN_UMAC_COMP_TWT); 171 if (!twt_psoc) { 172 twt_err("null twt psoc priv obj"); 173 return QDF_STATUS_E_FAILURE; 174 } 175 176 *val = twt_psoc->twt_caps.all_twt_enabled; 177 return QDF_STATUS_SUCCESS; 178 } 179 180 QDF_STATUS 181 wlan_twt_tgt_caps_get_stats_enabled(struct wlan_objmgr_psoc *psoc, 182 bool *val) 183 { 184 struct twt_psoc_priv_obj *twt_psoc; 185 186 if (!psoc) { 187 twt_err("null psoc"); 188 return QDF_STATUS_E_FAILURE; 189 } 190 191 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 192 WLAN_UMAC_COMP_TWT); 193 if (!twt_psoc) { 194 twt_err("null twt psoc priv obj"); 195 return QDF_STATUS_E_FAILURE; 196 } 197 198 *val = twt_psoc->twt_caps.twt_stats_enabled; 199 return QDF_STATUS_SUCCESS; 200 } 201 202 QDF_STATUS wlan_twt_check_all_twt_support(struct wlan_objmgr_psoc *psoc, 203 uint32_t dialog_id) 204 { 205 bool is_all_twt_enabled = false; 206 QDF_STATUS status; 207 208 /* Cap check is check NOT required if id is for a single session */ 209 if (dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) 210 return QDF_STATUS_SUCCESS; 211 212 status = wlan_twt_tgt_caps_get_all_twt_enabled(psoc, 213 &is_all_twt_enabled); 214 if (QDF_IS_STATUS_ERROR(status)) 215 return QDF_STATUS_E_INVAL; 216 217 if (!is_all_twt_enabled) 218 return QDF_STATUS_E_NOSUPPORT; 219 220 return QDF_STATUS_SUCCESS; 221 } 222 223 QDF_STATUS 224 wlan_twt_tgt_caps_get_ack_supported(struct wlan_objmgr_psoc *psoc, 225 bool *val) 226 { 227 struct twt_psoc_priv_obj *twt_psoc; 228 229 if (!psoc) { 230 twt_err("null psoc"); 231 *val = false; 232 return QDF_STATUS_E_FAILURE; 233 } 234 235 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 236 WLAN_UMAC_COMP_TWT); 237 if (!twt_psoc) { 238 twt_err("null twt psoc priv obj"); 239 *val = false; 240 return QDF_STATUS_E_FAILURE; 241 } 242 243 *val = twt_psoc->twt_caps.twt_ack_supported; 244 return QDF_STATUS_SUCCESS; 245 } 246 247 QDF_STATUS 248 wlan_twt_requestor_disable(struct wlan_objmgr_psoc *psoc, 249 struct twt_disable_param *req, 250 void *context) 251 { 252 struct twt_psoc_priv_obj *twt_psoc; 253 254 if (!psoc) { 255 twt_err("null psoc"); 256 return QDF_STATUS_E_FAILURE; 257 } 258 259 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 260 WLAN_UMAC_COMP_TWT); 261 if (!twt_psoc) { 262 twt_err("null twt psoc priv obj"); 263 return QDF_STATUS_E_FAILURE; 264 } 265 266 twt_psoc->disable_context.twt_role = TWT_ROLE_REQUESTOR; 267 twt_psoc->disable_context.context = context; 268 269 req->twt_role = TWT_ROLE_REQUESTOR; 270 271 twt_debug("TWT req disable: pdev_id:%d role:%d ext:%d reason_code:%d", 272 req->pdev_id, req->twt_role, req->ext_conf_present, 273 req->dis_reason_code); 274 275 return tgt_twt_disable_req_send(psoc, req); 276 } 277 278 QDF_STATUS 279 wlan_twt_responder_disable(struct wlan_objmgr_psoc *psoc, 280 struct twt_disable_param *req, 281 void *context) 282 { 283 struct twt_psoc_priv_obj *twt_psoc; 284 285 if (!psoc) { 286 twt_err("null psoc"); 287 return QDF_STATUS_E_FAILURE; 288 } 289 290 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 291 WLAN_UMAC_COMP_TWT); 292 if (!twt_psoc) { 293 twt_err("null twt psoc priv obj"); 294 return QDF_STATUS_E_FAILURE; 295 } 296 297 twt_psoc->disable_context.twt_role = TWT_ROLE_RESPONDER; 298 twt_psoc->disable_context.context = context; 299 300 req->twt_role = TWT_ROLE_RESPONDER; 301 302 twt_debug("TWT res disable: pdev_id:%d role:%d ext:%d reason_code:%d", 303 req->pdev_id, req->twt_role, req->ext_conf_present, 304 req->dis_reason_code); 305 306 return tgt_twt_disable_req_send(psoc, req); 307 } 308 309 QDF_STATUS 310 wlan_twt_requestor_enable(struct wlan_objmgr_psoc *psoc, 311 struct twt_enable_param *req, 312 void *context) 313 { 314 struct twt_psoc_priv_obj *twt_psoc; 315 bool requestor_en = false, twt_bcast_requestor = false; 316 317 if (!psoc) { 318 twt_err("null psoc"); 319 return QDF_STATUS_E_FAILURE; 320 } 321 322 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 323 WLAN_UMAC_COMP_TWT); 324 if (!twt_psoc) { 325 twt_err("null twt psoc priv obj"); 326 return QDF_STATUS_E_FAILURE; 327 } 328 329 wlan_twt_cfg_get_requestor(psoc, &requestor_en); 330 if (!requestor_en) { 331 twt_warn("twt requestor ini is not enabled"); 332 return QDF_STATUS_E_FAILURE; 333 } 334 335 twt_psoc->enable_context.twt_role = TWT_ROLE_REQUESTOR; 336 twt_psoc->enable_context.context = context; 337 338 wlan_twt_cfg_get_congestion_timeout(psoc, &req->sta_cong_timer_ms); 339 wlan_twt_cfg_get_bcast_requestor(psoc, &twt_bcast_requestor); 340 req->b_twt_enable = twt_bcast_requestor; 341 req->twt_role = TWT_ROLE_REQUESTOR; 342 if (twt_bcast_requestor) 343 req->twt_oper = TWT_OPERATION_BROADCAST; 344 else 345 req->twt_oper = TWT_OPERATION_INDIVIDUAL; 346 347 twt_debug("TWT req enable: pdev_id:%d cong:%d bcast:%d", 348 req->pdev_id, req->sta_cong_timer_ms, req->b_twt_enable); 349 twt_debug("TWT req enable: role:%d ext:%d oper:%d", 350 req->twt_role, req->ext_conf_present, req->twt_oper); 351 352 return tgt_twt_enable_req_send(psoc, req); 353 } 354 355 QDF_STATUS 356 wlan_twt_responder_enable(struct wlan_objmgr_psoc *psoc, 357 struct twt_enable_param *req, 358 void *context) 359 { 360 struct twt_psoc_priv_obj *twt_psoc; 361 bool responder_en = false, twt_bcast_responder = false; 362 363 if (!psoc) { 364 twt_err("null psoc"); 365 return QDF_STATUS_E_FAILURE; 366 } 367 368 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 369 WLAN_UMAC_COMP_TWT); 370 if (!twt_psoc) { 371 twt_err("null twt psoc priv obj"); 372 return QDF_STATUS_E_FAILURE; 373 } 374 375 wlan_twt_cfg_get_responder(psoc, &responder_en); 376 if (!responder_en) { 377 twt_warn("twt responder ini is not enabled"); 378 return QDF_STATUS_E_FAILURE; 379 } 380 381 twt_psoc->enable_context.twt_role = TWT_ROLE_RESPONDER; 382 twt_psoc->enable_context.context = context; 383 384 wlan_twt_cfg_get_bcast_responder(psoc, &twt_bcast_responder); 385 req->b_twt_enable = twt_bcast_responder; 386 req->twt_role = TWT_ROLE_RESPONDER; 387 if (twt_bcast_responder) 388 req->twt_oper = TWT_OPERATION_BROADCAST; 389 else 390 req->twt_oper = TWT_OPERATION_INDIVIDUAL; 391 392 twt_debug("TWT res enable: pdev_id:%d bcast:%d", 393 req->pdev_id, req->b_twt_enable); 394 twt_debug("TWT res enable: role:%d ext:%d oper:%d", 395 req->twt_role, req->ext_conf_present, req->twt_oper); 396 397 return tgt_twt_enable_req_send(psoc, req); 398 } 399 400 QDF_STATUS 401 wlan_twt_set_peer_capabilities(struct wlan_objmgr_psoc *psoc, 402 struct qdf_mac_addr *peer_mac, 403 uint8_t peer_cap) 404 { 405 struct twt_peer_priv_obj *peer_priv; 406 struct wlan_objmgr_peer *peer; 407 408 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, 409 WLAN_TWT_ID); 410 if (!peer) { 411 twt_err("Peer object not found "QDF_MAC_ADDR_FMT, 412 QDF_MAC_ADDR_REF(peer_mac->bytes)); 413 return QDF_STATUS_E_FAILURE; 414 } 415 416 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, 417 WLAN_UMAC_COMP_TWT); 418 if (!peer_priv) { 419 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID); 420 twt_err("peer twt component object is NULL"); 421 return QDF_STATUS_E_FAILURE; 422 } 423 424 twt_lock_acquire(&peer_priv->twt_peer_lock); 425 peer_priv->peer_capability = peer_cap; 426 twt_lock_release(&peer_priv->twt_peer_lock); 427 428 twt_debug("set peer cap: 0x%x", peer_cap); 429 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID); 430 return QDF_STATUS_SUCCESS; 431 } 432 433 QDF_STATUS 434 wlan_twt_get_peer_capabilities(struct wlan_objmgr_psoc *psoc, 435 struct qdf_mac_addr *peer_mac, 436 uint8_t *peer_cap) 437 { 438 struct twt_peer_priv_obj *peer_priv; 439 struct wlan_objmgr_peer *peer; 440 441 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac->bytes, 442 WLAN_TWT_ID); 443 if (!peer) { 444 twt_err("Peer object not found "QDF_MAC_ADDR_FMT, 445 QDF_MAC_ADDR_REF(peer_mac->bytes)); 446 *peer_cap = 0; 447 return QDF_STATUS_E_FAILURE; 448 } 449 450 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer, 451 WLAN_UMAC_COMP_TWT); 452 if (!peer_priv) { 453 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID); 454 *peer_cap = 0; 455 twt_err("peer twt component object is NULL"); 456 return QDF_STATUS_E_FAILURE; 457 } 458 459 twt_lock_acquire(&peer_priv->twt_peer_lock); 460 *peer_cap = peer_priv->peer_capability; 461 twt_lock_release(&peer_priv->twt_peer_lock); 462 463 twt_debug("get peer cap: 0x%x", *peer_cap); 464 wlan_objmgr_peer_release_ref(peer, WLAN_TWT_ID); 465 return QDF_STATUS_SUCCESS; 466 } 467 468 QDF_STATUS 469 wlan_twt_enable_event_handler(struct wlan_objmgr_psoc *psoc, 470 struct twt_enable_complete_event_param *event) 471 { 472 struct twt_psoc_priv_obj *twt_psoc; 473 struct twt_en_dis_context *twt_context; 474 475 if (!psoc) { 476 twt_err("null psoc"); 477 return QDF_STATUS_E_FAILURE; 478 } 479 480 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 481 WLAN_UMAC_COMP_TWT); 482 if (!twt_psoc) { 483 twt_err("null twt psoc priv obj"); 484 return QDF_STATUS_E_FAILURE; 485 } 486 487 twt_context = &twt_psoc->enable_context; 488 489 twt_debug("pdev_id:%d status:%d twt_role:%d", 490 event->pdev_id, event->status, twt_context->twt_role); 491 switch (event->status) { 492 case HOST_TWT_ENABLE_STATUS_OK: 493 case HOST_TWT_ENABLE_STATUS_ALREADY_ENABLED: 494 if (twt_context->twt_role == TWT_ROLE_REQUESTOR) 495 wlan_twt_cfg_set_requestor_flag(psoc, true); 496 else if (twt_context->twt_role == TWT_ROLE_RESPONDER) 497 wlan_twt_cfg_set_responder_flag(psoc, true); 498 else 499 twt_err("Invalid role:%d", twt_context->twt_role); 500 501 break; 502 503 default: 504 twt_err("twt enable status:%d", event->status); 505 break; 506 } 507 508 return mlme_twt_osif_enable_complete_ind(psoc, event, 509 twt_context->context); 510 } 511 512 QDF_STATUS 513 wlan_twt_disable_event_handler(struct wlan_objmgr_psoc *psoc, 514 struct twt_disable_complete_event_param *event) 515 { 516 struct twt_psoc_priv_obj *twt_psoc; 517 struct twt_en_dis_context *twt_context; 518 519 if (!psoc) { 520 twt_err("null psoc"); 521 return QDF_STATUS_E_FAILURE; 522 } 523 524 twt_psoc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 525 WLAN_UMAC_COMP_TWT); 526 if (!twt_psoc) { 527 twt_err("null twt psoc priv obj"); 528 return QDF_STATUS_E_FAILURE; 529 } 530 531 twt_context = &twt_psoc->disable_context; 532 533 twt_debug("pdev_id:%d status:%d twt_role:%d", 534 event->pdev_id, event->status, twt_context->twt_role); 535 switch (event->status) { 536 case HOST_TWT_DISABLE_STATUS_OK: 537 if (twt_context->twt_role == TWT_ROLE_REQUESTOR) 538 wlan_twt_cfg_set_requestor_flag(psoc, false); 539 else if (twt_context->twt_role == TWT_ROLE_RESPONDER) 540 wlan_twt_cfg_set_responder_flag(psoc, false); 541 else 542 twt_err("Invalid role:%d", twt_context->twt_role); 543 544 break; 545 546 default: 547 twt_err("twt disable status:%d", event->status); 548 break; 549 } 550 551 return mlme_twt_osif_disable_complete_ind(psoc, event, 552 twt_context->context); 553 } 554 555