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