1 /* 2 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: defines DP interaction with FW using WMI 22 */ 23 24 #include <qdf_status.h> 25 #include "target_if_dp.h" 26 #include <init_deinit_lmac.h> 27 #ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF 28 #include <wmi_unified_param.h> 29 #include <wlan_objmgr_peer_obj.h> 30 #endif 31 32 uint32_t target_if_get_active_mac_phy_number(struct wlan_objmgr_psoc *psoc) 33 { 34 struct target_psoc_info *psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 35 struct target_supported_modes *hw_modes; 36 uint32_t i, phy_bit_map, mac_phy_cnt, max_mac_phy_cnt = 0; 37 38 if (!psoc_info) { 39 target_if_err("invalid psoc info"); 40 return 0; 41 } 42 hw_modes = &psoc_info->info.hw_modes; 43 for (i = 0; i < hw_modes->num_modes; i++) { 44 phy_bit_map = hw_modes->phy_bit_map[i]; 45 mac_phy_cnt = 0; 46 while (phy_bit_map) { 47 mac_phy_cnt++; 48 phy_bit_map &= (phy_bit_map - 1); 49 } 50 if (mac_phy_cnt > max_mac_phy_cnt) 51 max_mac_phy_cnt = mac_phy_cnt; 52 } 53 54 return max_mac_phy_cnt; 55 } 56 57 void 58 target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_psoc *psoc, 59 uint8_t pdev_id, uint8_t *peer_macaddr, 60 uint8_t vdev_id, 61 bool hash_based, uint8_t ring_num, 62 uint8_t lmac_peer_id_msb) 63 { 64 uint32_t value; 65 struct peer_set_params param; 66 struct wmi_unified *pdev_wmi_handle; 67 struct wlan_objmgr_pdev *pdev = 68 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 69 pdev_id, WLAN_PDEV_TARGET_IF_ID); 70 71 if (!pdev) { 72 target_if_err("pdev with id %d is NULL", pdev_id); 73 return; 74 } 75 76 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 77 if (!pdev_wmi_handle) { 78 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 79 target_if_err("pdev wmi handle NULL"); 80 return; 81 } 82 83 qdf_mem_zero(¶m, sizeof(param)); 84 85 /* TODO: Need bit definitions for ring number and hash based routing 86 * fields in common wmi header file 87 */ 88 value = ((hash_based) ? 1 : 0) | (ring_num << 1); 89 90 if (lmac_peer_id_msb) 91 QDF_SET_BITS(value, PEER_ROUTING_LMAC_ID_INDEX, 92 PEER_ROUTING_LMAC_ID_BITS, lmac_peer_id_msb); 93 94 param.param_id = WMI_HOST_PEER_SET_DEFAULT_ROUTING; 95 param.vdev_id = vdev_id; 96 param.param_value = value; 97 98 if (wmi_set_peer_param_send(pdev_wmi_handle, peer_macaddr, ¶m)) { 99 target_if_err("Unable to set default routing for peer " 100 QDF_MAC_ADDR_FMT, 101 QDF_MAC_ADDR_REF(peer_macaddr)); 102 } 103 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 104 } 105 106 #ifdef SERIALIZE_QUEUE_SETUP 107 static QDF_STATUS 108 target_if_rx_reorder_queue_setup(struct scheduler_msg *msg) 109 { 110 struct rx_reorder_queue_setup_params param; 111 struct wmi_unified *pdev_wmi_handle; 112 struct reorder_q_setup *q_params; 113 QDF_STATUS status; 114 struct wlan_objmgr_pdev *pdev; 115 struct wlan_objmgr_psoc *psoc; 116 117 if (!(msg->bodyptr)) { 118 target_if_err("rx_reorder: Invalid message body"); 119 return QDF_STATUS_E_INVAL; 120 } 121 122 q_params = msg->bodyptr; 123 psoc = (struct wlan_objmgr_psoc *)q_params->psoc; 124 125 pdev = wlan_objmgr_get_pdev_by_id(psoc, q_params->pdev_id, 126 WLAN_PDEV_TARGET_IF_ID); 127 128 if (!pdev) { 129 target_if_err("pdev with id %d is NULL", q_params->pdev_id); 130 return QDF_STATUS_E_INVAL; 131 } 132 133 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 134 if (!pdev_wmi_handle) { 135 target_if_err("pdev wmi handle NULL"); 136 status = QDF_STATUS_E_FAILURE; 137 goto out; 138 } 139 140 param.tid = q_params->tid; 141 param.vdev_id = q_params->vdev_id; 142 param.peer_macaddr = q_params->peer_mac; 143 param.hw_qdesc_paddr_lo = q_params->hw_qdesc_paddr & 0xffffffff; 144 param.hw_qdesc_paddr_hi = (uint64_t)q_params->hw_qdesc_paddr >> 32; 145 param.queue_no = q_params->queue_no; 146 param.ba_window_size_valid = q_params->ba_window_size_valid; 147 param.ba_window_size = q_params->ba_window_size; 148 149 status = wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, 150 ¶m); 151 out: 152 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 153 qdf_mem_free(q_params); 154 155 return status; 156 } 157 158 static QDF_STATUS 159 target_if_multi_rx_reorder_queue_setup(struct scheduler_msg *msg) 160 { 161 struct multi_rx_reorder_queue_setup_params param = {0}; 162 struct wmi_unified *pdev_wmi_handle; 163 struct multi_reorder_q_setup *q_params; 164 QDF_STATUS status; 165 struct wlan_objmgr_pdev *pdev; 166 struct wlan_objmgr_psoc *psoc; 167 int tid; 168 169 if (!(msg->bodyptr)) { 170 target_if_err("rx_reorder: Invalid message body"); 171 return QDF_STATUS_E_INVAL; 172 } 173 174 q_params = msg->bodyptr; 175 psoc = (struct wlan_objmgr_psoc *)q_params->psoc; 176 177 pdev = wlan_objmgr_get_pdev_by_id(psoc, q_params->pdev_id, 178 WLAN_PDEV_TARGET_IF_ID); 179 if (!pdev) { 180 target_if_err("pdev with id %d is NULL", q_params->pdev_id); 181 return QDF_STATUS_E_INVAL; 182 } 183 184 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 185 if (!pdev_wmi_handle) { 186 target_if_err("pdev wmi handle NULL"); 187 status = QDF_STATUS_E_FAILURE; 188 goto out; 189 } 190 191 param.tid_bitmap = q_params->tid_bitmap; 192 param.vdev_id = q_params->vdev_id; 193 param.peer_macaddr = q_params->peer_mac; 194 param.tid_num = q_params->tid_num; 195 196 for (tid = 0; tid < DP_MAX_TIDS; tid++) { 197 if (!(BIT(tid) & q_params->tid_bitmap)) 198 continue; 199 param.queue_params_list[tid].hw_qdesc_paddr = 200 q_params->q_setup_list[tid].hw_qdesc_paddr; 201 param.queue_params_list[tid].queue_no = 202 q_params->q_setup_list[tid].queue_no; 203 param.queue_params_list[tid].ba_window_size_valid = 204 q_params->q_setup_list[tid].ba_window_size_valid; 205 param.queue_params_list[tid].ba_window_size = 206 q_params->q_setup_list[tid].ba_window_size; 207 } 208 209 status = wmi_unified_peer_multi_rx_reorder_queue_setup_send( 210 pdev_wmi_handle, ¶m); 211 out: 212 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 213 qdf_mem_free(q_params); 214 215 return status; 216 } 217 218 QDF_STATUS 219 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 220 uint8_t pdev_id, 221 uint8_t vdev_id, uint8_t *peer_macaddr, 222 qdf_dma_addr_t hw_qdesc, int tid, 223 uint16_t queue_no, 224 uint8_t ba_window_size_valid, 225 uint16_t ba_window_size) 226 { 227 struct scheduler_msg msg = {0}; 228 struct reorder_q_setup *q_params; 229 QDF_STATUS status; 230 231 q_params = qdf_mem_malloc(sizeof(*q_params)); 232 if (!q_params) 233 return QDF_STATUS_E_NOMEM; 234 235 q_params->psoc = psoc; 236 q_params->vdev_id = vdev_id; 237 q_params->pdev_id = pdev_id; 238 q_params->hw_qdesc_paddr = hw_qdesc; 239 q_params->tid = tid; 240 q_params->queue_no = queue_no; 241 q_params->ba_window_size_valid = ba_window_size_valid; 242 q_params->ba_window_size = ba_window_size; 243 qdf_mem_copy(q_params->peer_mac, peer_macaddr, QDF_MAC_ADDR_SIZE); 244 245 msg.bodyptr = q_params; 246 msg.callback = target_if_rx_reorder_queue_setup; 247 status = scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 248 QDF_MODULE_ID_TARGET_IF, 249 QDF_MODULE_ID_TARGET_IF, &msg); 250 251 if (status != QDF_STATUS_SUCCESS) 252 qdf_mem_free(q_params); 253 254 return status; 255 } 256 257 QDF_STATUS 258 target_if_peer_multi_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 259 uint8_t pdev_id, 260 struct multi_rx_reorder_queue_setup_params *tid_params) 261 { 262 struct scheduler_msg msg = {0}; 263 struct multi_reorder_q_setup *q_params; 264 QDF_STATUS status; 265 int tid; 266 267 q_params = qdf_mem_malloc(sizeof(*q_params)); 268 if (!q_params) 269 return QDF_STATUS_E_NOMEM; 270 271 q_params->psoc = psoc; 272 q_params->vdev_id = tid_params->vdev_id; 273 q_params->pdev_id = pdev_id; 274 q_params->tid_bitmap = tid_params->tid_bitmap; 275 q_params->tid_num = tid_params->tid_num; 276 qdf_mem_copy(q_params->peer_mac, tid_params->peer_macaddr, 277 QDF_MAC_ADDR_SIZE); 278 279 for (tid = 0; tid < DP_MAX_TIDS; tid++) { 280 if (!(BIT(tid) & tid_params->tid_bitmap)) 281 continue; 282 q_params->q_setup_list[tid].hw_qdesc_paddr = 283 tid_params->queue_params_list[tid].hw_qdesc_paddr; 284 q_params->q_setup_list[tid].queue_no = 285 tid_params->queue_params_list[tid].queue_no; 286 q_params->q_setup_list[tid].ba_window_size_valid = 287 tid_params->queue_params_list[tid].ba_window_size_valid; 288 q_params->q_setup_list[tid].ba_window_size = 289 tid_params->queue_params_list[tid].ba_window_size; 290 } 291 292 msg.bodyptr = q_params; 293 msg.callback = target_if_multi_rx_reorder_queue_setup; 294 status = scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 295 QDF_MODULE_ID_TARGET_IF, 296 QDF_MODULE_ID_TARGET_IF, &msg); 297 298 if (status != QDF_STATUS_SUCCESS) 299 qdf_mem_free(q_params); 300 301 return status; 302 } 303 #else 304 QDF_STATUS 305 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 306 uint8_t pdev_id, 307 uint8_t vdev_id, uint8_t *peer_macaddr, 308 qdf_dma_addr_t hw_qdesc, int tid, 309 uint16_t queue_no, 310 uint8_t ba_window_size_valid, 311 uint16_t ba_window_size) 312 { 313 struct rx_reorder_queue_setup_params param; 314 struct wmi_unified *pdev_wmi_handle; 315 QDF_STATUS status; 316 struct wlan_objmgr_pdev *pdev = 317 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 318 pdev_id, WLAN_PDEV_TARGET_IF_ID); 319 320 if (!pdev) { 321 target_if_err("pdev with id %d is NULL", pdev_id); 322 return QDF_STATUS_E_INVAL; 323 } 324 325 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 326 if (!pdev_wmi_handle) { 327 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 328 target_if_err("pdev wmi handle NULL"); 329 return QDF_STATUS_E_FAILURE; 330 } 331 param.tid = tid; 332 param.vdev_id = vdev_id; 333 param.peer_macaddr = peer_macaddr; 334 param.hw_qdesc_paddr_lo = hw_qdesc & 0xffffffff; 335 param.hw_qdesc_paddr_hi = (uint64_t)hw_qdesc >> 32; 336 param.queue_no = queue_no; 337 param.ba_window_size_valid = ba_window_size_valid; 338 param.ba_window_size = ba_window_size; 339 340 status = wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, 341 ¶m); 342 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 343 344 return status; 345 } 346 347 QDF_STATUS 348 target_if_peer_multi_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 349 uint8_t pdev_id, 350 struct multi_rx_reorder_queue_setup_params *tid_params) 351 { 352 struct wmi_unified *pdev_wmi_handle; 353 QDF_STATUS status; 354 struct wlan_objmgr_pdev *pdev = 355 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 356 pdev_id, WLAN_PDEV_TARGET_IF_ID); 357 if (!pdev) { 358 target_if_err("pdev with id %d is NULL", pdev_id); 359 return QDF_STATUS_E_INVAL; 360 } 361 362 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 363 if (!pdev_wmi_handle) { 364 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 365 target_if_err("pdev wmi handle NULL"); 366 return QDF_STATUS_E_FAILURE; 367 } 368 369 status = wmi_unified_peer_multi_rx_reorder_queue_setup_send( 370 pdev_wmi_handle, tid_params); 371 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 372 373 return status; 374 } 375 #endif 376 377 QDF_STATUS 378 target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_psoc *psoc, 379 uint8_t pdev_id, 380 uint8_t vdev_id, uint8_t *peer_macaddr, 381 uint32_t peer_tid_bitmap) 382 { 383 struct rx_reorder_queue_remove_params param; 384 struct wmi_unified *pdev_wmi_handle; 385 QDF_STATUS status; 386 struct wlan_objmgr_pdev *pdev = 387 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 388 pdev_id, WLAN_PDEV_TARGET_IF_ID); 389 390 if (!pdev) { 391 target_if_err("pdev with id %d is NULL", pdev_id); 392 return QDF_STATUS_E_INVAL; 393 } 394 395 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 396 if (!pdev_wmi_handle) { 397 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 398 target_if_err("pdev wmi handle NULL"); 399 return QDF_STATUS_E_FAILURE; 400 } 401 param.vdev_id = vdev_id; 402 param.peer_macaddr = peer_macaddr; 403 param.peer_tid_bitmap = peer_tid_bitmap; 404 status = wmi_unified_peer_rx_reorder_queue_remove_send(pdev_wmi_handle, 405 ¶m); 406 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 407 408 return status; 409 } 410 411 QDF_STATUS 412 target_if_lro_hash_config(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, 413 struct cdp_lro_hash_config *lro_hash_cfg) 414 { 415 struct wmi_lro_config_cmd_t wmi_lro_cmd = {0}; 416 struct wmi_unified *pdev_wmi_handle; 417 QDF_STATUS status; 418 struct wlan_objmgr_pdev *pdev = 419 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 420 pdev_id, WLAN_PDEV_TARGET_IF_ID); 421 422 if (!pdev) { 423 target_if_err("pdev with id %d is NULL", pdev_id); 424 return QDF_STATUS_E_INVAL; 425 } 426 427 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 428 if (!lro_hash_cfg || !pdev_wmi_handle) { 429 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 430 target_if_err("wmi_handle: 0x%pK, lro_hash_cfg: 0x%pK", 431 pdev_wmi_handle, lro_hash_cfg); 432 return QDF_STATUS_E_FAILURE; 433 } 434 435 wmi_lro_cmd.lro_enable = lro_hash_cfg->lro_enable; 436 wmi_lro_cmd.tcp_flag = lro_hash_cfg->tcp_flag; 437 wmi_lro_cmd.tcp_flag_mask = lro_hash_cfg->tcp_flag_mask; 438 wmi_lro_cmd.pdev_id = pdev_id; 439 440 qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv4, 441 lro_hash_cfg->toeplitz_hash_ipv4, 442 LRO_IPV4_SEED_ARR_SZ * sizeof(uint32_t)); 443 444 qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv6, 445 lro_hash_cfg->toeplitz_hash_ipv6, 446 LRO_IPV6_SEED_ARR_SZ * sizeof(uint32_t)); 447 448 status = wmi_unified_lro_config_cmd(pdev_wmi_handle, 449 &wmi_lro_cmd); 450 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 451 452 return status; 453 } 454 455 #ifdef WLAN_SUPPORT_PPEDS 456 QDF_STATUS 457 target_if_peer_set_ppeds_default_routing(struct cdp_ctrl_objmgr_psoc *soc, 458 uint8_t *peer_macaddr, 459 uint16_t service_code, 460 uint8_t priority_valid, 461 uint16_t src_info, 462 uint8_t vdev_id, uint8_t use_ppe, 463 uint8_t ppe_routing_enabled) 464 { 465 struct wmi_unified *pdev_wmi_handle; 466 struct wlan_objmgr_pdev *pdev; 467 struct wlan_objmgr_vdev *vdev; 468 struct peer_ppe_ds_param param; 469 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 470 471 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 472 if (!psoc) { 473 target_if_err("PSOC is NULL!"); 474 return QDF_STATUS_E_NULL_VALUE; 475 } 476 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 477 WLAN_WDS_ID); 478 if (!vdev) { 479 target_if_err("vdev with id %d is NULL", vdev_id); 480 return QDF_STATUS_E_INVAL; 481 } 482 483 pdev = wlan_vdev_get_pdev(vdev); 484 485 if (!pdev) { 486 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 487 target_if_err("pdev is NULL"); 488 return QDF_STATUS_E_INVAL; 489 } 490 491 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 492 if (!pdev_wmi_handle) { 493 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 494 target_if_err("pdev_wmi_handle is NULL"); 495 return QDF_STATUS_E_INVAL; 496 } 497 498 qdf_mem_zero(¶m, sizeof(param)); 499 500 qdf_mem_copy(¶m.peer_macaddr[0], peer_macaddr, QDF_MAC_ADDR_SIZE); 501 param.ppe_routing_enabled = ppe_routing_enabled; 502 param.service_code = service_code; 503 param.priority_valid = priority_valid; 504 param.src_info = src_info; 505 param.vdev_id = vdev_id; 506 param.use_ppe = use_ppe; 507 508 qdf_status = wmi_unified_peer_ppe_ds_param_send(pdev_wmi_handle, 509 ¶m); 510 if (qdf_status != QDF_STATUS_SUCCESS) { 511 target_if_err("Unable to set PPE default routing for peer " 512 QDF_MAC_ADDR_FMT, 513 QDF_MAC_ADDR_REF(peer_macaddr)); 514 } 515 516 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 517 return qdf_status; 518 } 519 #endif /* WLAN_SUPPORT_PPEDS */ 520 521 #ifdef WDS_CONV_TARGET_IF_OPS_ENABLE 522 QDF_STATUS 523 target_if_add_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 524 uint8_t *peer_mac, const uint8_t *dest_mac, 525 uint32_t flags, uint8_t type) 526 { 527 struct peer_add_wds_entry_params wmi_wds_param = {0}; 528 struct wmi_unified *pdev_wmi_handle; 529 struct wlan_objmgr_pdev *pdev; 530 struct wlan_objmgr_vdev *vdev; 531 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 532 QDF_STATUS status; 533 534 if (type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) 535 return QDF_STATUS_E_FAILURE; 536 537 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 538 WLAN_WDS_ID); 539 if (!vdev) { 540 target_if_err("vdev with id %d is NULL", vdev_id); 541 return QDF_STATUS_E_INVAL; 542 } 543 544 pdev = wlan_vdev_get_pdev(vdev); 545 if (!pdev) { 546 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 547 target_if_err("pdev is NULL"); 548 return QDF_STATUS_E_INVAL; 549 } 550 551 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 552 if (!pdev_wmi_handle) { 553 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 554 target_if_err("pdev_wmi_handle is NULL"); 555 return QDF_STATUS_E_INVAL; 556 } 557 558 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 559 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 560 wmi_wds_param.vdev_id = vdev_id; 561 wmi_wds_param.flags = flags; 562 563 status = wmi_unified_peer_add_wds_entry_cmd(pdev_wmi_handle, 564 &wmi_wds_param); 565 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 566 567 return status; 568 } 569 570 void 571 target_if_del_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 572 uint8_t *dest_mac, uint8_t type, uint8_t delete_in_fw) 573 { 574 struct peer_del_wds_entry_params wmi_wds_param = {0}; 575 struct wmi_unified *pdev_wmi_handle; 576 struct wlan_objmgr_pdev *pdev; 577 struct wlan_objmgr_vdev *vdev; 578 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 579 580 if (!delete_in_fw || type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) { 581 target_if_err("delete_in_fw: %d type: %d", delete_in_fw, type); 582 return; 583 } 584 585 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 586 WLAN_WDS_ID); 587 if (!vdev) { 588 target_if_err("vdev with id %d is NULL", vdev_id); 589 return; 590 } 591 592 pdev = wlan_vdev_get_pdev(vdev); 593 if (!pdev) { 594 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 595 target_if_err("pdev is NULL"); 596 return; 597 } 598 599 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 600 if (!pdev_wmi_handle) { 601 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 602 target_if_err("pdev_wmi_handle is NULL"); 603 return; 604 } 605 606 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 607 wmi_wds_param.vdev_id = vdev_id; 608 609 wmi_unified_peer_del_wds_entry_cmd(pdev_wmi_handle, 610 &wmi_wds_param); 611 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 612 } 613 614 QDF_STATUS 615 target_if_update_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 616 uint8_t *dest_mac, uint8_t *peer_mac, 617 uint32_t flags) 618 { 619 struct peer_update_wds_entry_params wmi_wds_param = {0}; 620 struct wmi_unified *pdev_wmi_handle; 621 struct wlan_objmgr_pdev *pdev; 622 struct wlan_objmgr_vdev *vdev; 623 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 624 QDF_STATUS status; 625 626 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 627 WLAN_WDS_ID); 628 if (!vdev) { 629 target_if_err("vdev with id %d is NULL", vdev_id); 630 return QDF_STATUS_E_INVAL; 631 } 632 633 pdev = wlan_vdev_get_pdev(vdev); 634 if (!pdev) { 635 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 636 target_if_err("pdev is NULL"); 637 return QDF_STATUS_E_INVAL; 638 } 639 640 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 641 if (!pdev_wmi_handle) { 642 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 643 target_if_err("pdev_wmi_handle is NULL"); 644 return QDF_STATUS_E_INVAL; 645 } 646 647 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 648 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 649 wmi_wds_param.vdev_id = vdev_id; 650 wmi_wds_param.flags = flags; 651 652 status = wmi_unified_update_wds_entry_cmd(pdev_wmi_handle, 653 &wmi_wds_param); 654 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 655 656 return status; 657 } 658 #endif 659 660 #ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF 661 /** 662 * map_flush_policy() - Map DP layer flush policy values to target i/f layer 663 * @policy: The DP layer flush policy value 664 * 665 * Return: Peer flush policy 666 */ 667 static enum peer_txq_flush_policy 668 map_flush_policy(enum cdp_peer_txq_flush_policy policy) 669 { 670 switch (policy) { 671 case CDP_PEER_TXQ_FLUSH_POLICY_NONE: 672 return PEER_TXQ_FLUSH_POLICY_NONE; 673 case CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END: 674 return PEER_TXQ_FLUSH_POLICY_TWT_SP_END; 675 default: 676 return PEER_TXQ_FLUSH_POLICY_INVALID; 677 } 678 } 679 680 /** 681 * send_peer_txq_flush_conf() - Send flush config for peers TID queues 682 * @psoc: Opaque handle for posc object manager object 683 * @mac: MAC addr of peer for which the tx queue flush is intended 684 * @vdev_id: VDEV identifier 685 * @tid: TID mask for identifying the tx queues to be flushed 686 * @policy: The peer tid queue flush policy 687 * 688 * Return: 0 for success or error code 689 */ 690 static int send_peer_txq_flush_conf(struct cdp_ctrl_objmgr_psoc *psoc, 691 uint8_t *mac, uint8_t vdev_id, 692 uint32_t tid, 693 enum cdp_peer_txq_flush_policy policy) 694 { 695 struct wlan_objmgr_psoc *obj_soc; 696 struct wmi_unified *wmi_handle; 697 enum peer_txq_flush_policy flush_policy; 698 struct peer_txq_flush_config_params param = {0}; 699 QDF_STATUS status; 700 701 obj_soc = (struct wlan_objmgr_psoc *)psoc; 702 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 703 if (!wmi_handle) { 704 target_if_err("Invalid wmi handle"); 705 return -EINVAL; 706 } 707 708 flush_policy = map_flush_policy(policy); 709 if (flush_policy >= PEER_TXQ_FLUSH_POLICY_INVALID) { 710 target_if_err("Invalid flush policy : %d", policy); 711 return -EINVAL; 712 } 713 714 param.vdev_id = vdev_id; 715 param.tid_mask = tid; 716 param.policy = flush_policy; 717 qdf_mem_copy(param.peer, mac, QDF_MAC_ADDR_SIZE); 718 719 status = wmi_unified_peer_txq_flush_config_send(wmi_handle, ¶m); 720 return qdf_status_to_os_return(status); 721 } 722 723 /** 724 * send_peer_txq_flush_tids() - Send flush command peers TID queues 725 * @psoc: Opaque handle for psoc object manager object 726 * @mac: MAC addr of peer for which the tx queue flush is intended 727 * @vdev_id: VDEV identifier 728 * @tid: TID mask for identifying the tx queues to be flushed 729 * 730 * Return: 0 for success or error code 731 */ 732 static int send_peer_txq_flush_tids(struct cdp_ctrl_objmgr_psoc *psoc, 733 uint8_t *mac, uint8_t vdev_id, 734 uint32_t tid) 735 { 736 struct wlan_objmgr_psoc *obj_soc; 737 struct wmi_unified *wmi_handle; 738 struct peer_flush_params param; 739 QDF_STATUS status; 740 741 if (!psoc || !mac) { 742 target_if_err("Invalid params"); 743 return -EINVAL; 744 } 745 746 obj_soc = (struct wlan_objmgr_psoc *)psoc; 747 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 748 if (!wmi_handle) { 749 target_if_err("Invalid wmi handle"); 750 return -EINVAL; 751 } 752 753 param.vdev_id = vdev_id; 754 param.peer_tid_bitmap = tid; 755 qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE); 756 757 status = wmi_unified_peer_flush_tids_send(wmi_handle, mac, ¶m); 758 return qdf_status_to_os_return(status); 759 } 760 761 int target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc, 762 uint8_t vdev_id, uint8_t *addr, 763 uint8_t ac, uint32_t tid, 764 enum cdp_peer_txq_flush_policy policy) 765 { 766 static uint8_t ac_to_tid[4][2] = { {0, 3}, {1, 2}, {4, 5}, {6, 7} }; 767 struct wlan_objmgr_psoc *obj_soc; 768 struct wlan_objmgr_peer *peer; 769 int i, rc; 770 771 if (!psoc || !addr) { 772 target_if_err("Invalid params"); 773 return -EINVAL; 774 } 775 776 if (!tid && !ac) { 777 target_if_err("no ac/tid mask setting"); 778 return -EINVAL; 779 } 780 781 if (tid && policy == CDP_PEER_TXQ_FLUSH_POLICY_INVALID) { 782 target_if_err("Invalid flush policy"); 783 return -EINVAL; 784 } 785 obj_soc = (struct wlan_objmgr_psoc *)psoc; 786 787 peer = wlan_objmgr_get_peer_by_mac(obj_soc, addr, WLAN_DP_ID); 788 if (!peer) { 789 target_if_err("Peer not found in the list"); 790 return -EINVAL; 791 } 792 /* If tid mask is provided and policy is immediate use legacy WMI. 793 * If tid mask is provided and policy is other than immediate use 794 * the new WMI command for flush config. 795 * If tid mask is not provided and ac mask is provided, convert to tid, 796 * use the legacy WMI cmd for flushing the queues immediately. 797 */ 798 if (tid) { 799 if (policy == CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE) { 800 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 801 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 802 return rc; 803 } 804 rc = send_peer_txq_flush_conf(psoc, addr, vdev_id, tid, policy); 805 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 806 return rc; 807 } 808 809 if (ac) { 810 tid = 0; 811 for (i = 0; i < 4; ++i) { 812 if (((ac & 0x0f) >> i) & 0x01) { 813 tid |= (1 << ac_to_tid[i][0]) | 814 (1 << ac_to_tid[i][1]); 815 } 816 } 817 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 818 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 819 return rc; 820 } 821 /* should not hit this line */ 822 return 0; 823 } 824 #endif 825