1 /* 2 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 QDF_STATUS 159 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 160 uint8_t pdev_id, 161 uint8_t vdev_id, uint8_t *peer_macaddr, 162 qdf_dma_addr_t hw_qdesc, int tid, 163 uint16_t queue_no, 164 uint8_t ba_window_size_valid, 165 uint16_t ba_window_size) 166 { 167 struct scheduler_msg msg = {0}; 168 struct reorder_q_setup *q_params; 169 QDF_STATUS status; 170 171 q_params = qdf_mem_malloc(sizeof(*q_params)); 172 if (!q_params) 173 return QDF_STATUS_E_NOMEM; 174 175 q_params->psoc = psoc; 176 q_params->vdev_id = vdev_id; 177 q_params->pdev_id = pdev_id; 178 q_params->hw_qdesc_paddr = hw_qdesc; 179 q_params->tid = tid; 180 q_params->queue_no = queue_no; 181 q_params->ba_window_size_valid = ba_window_size_valid; 182 q_params->ba_window_size = ba_window_size; 183 qdf_mem_copy(q_params->peer_mac, peer_macaddr, QDF_MAC_ADDR_SIZE); 184 185 msg.bodyptr = q_params; 186 msg.callback = target_if_rx_reorder_queue_setup; 187 status = scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 188 QDF_MODULE_ID_TARGET_IF, 189 QDF_MODULE_ID_TARGET_IF, &msg); 190 191 if (status != QDF_STATUS_SUCCESS) 192 qdf_mem_free(q_params); 193 194 return status; 195 } 196 197 #else 198 199 QDF_STATUS 200 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, 201 uint8_t pdev_id, 202 uint8_t vdev_id, uint8_t *peer_macaddr, 203 qdf_dma_addr_t hw_qdesc, int tid, 204 uint16_t queue_no, 205 uint8_t ba_window_size_valid, 206 uint16_t ba_window_size) 207 { 208 struct rx_reorder_queue_setup_params param; 209 struct wmi_unified *pdev_wmi_handle; 210 QDF_STATUS status; 211 struct wlan_objmgr_pdev *pdev = 212 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 213 pdev_id, WLAN_PDEV_TARGET_IF_ID); 214 215 if (!pdev) { 216 target_if_err("pdev with id %d is NULL", pdev_id); 217 return QDF_STATUS_E_INVAL; 218 } 219 220 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 221 if (!pdev_wmi_handle) { 222 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 223 target_if_err("pdev wmi handle NULL"); 224 return QDF_STATUS_E_FAILURE; 225 } 226 param.tid = tid; 227 param.vdev_id = vdev_id; 228 param.peer_macaddr = peer_macaddr; 229 param.hw_qdesc_paddr_lo = hw_qdesc & 0xffffffff; 230 param.hw_qdesc_paddr_hi = (uint64_t)hw_qdesc >> 32; 231 param.queue_no = queue_no; 232 param.ba_window_size_valid = ba_window_size_valid; 233 param.ba_window_size = ba_window_size; 234 235 status = wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, 236 ¶m); 237 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 238 239 return status; 240 } 241 #endif 242 243 QDF_STATUS 244 target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_psoc *psoc, 245 uint8_t pdev_id, 246 uint8_t vdev_id, uint8_t *peer_macaddr, 247 uint32_t peer_tid_bitmap) 248 { 249 struct rx_reorder_queue_remove_params param; 250 struct wmi_unified *pdev_wmi_handle; 251 QDF_STATUS status; 252 struct wlan_objmgr_pdev *pdev = 253 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 254 pdev_id, WLAN_PDEV_TARGET_IF_ID); 255 256 if (!pdev) { 257 target_if_err("pdev with id %d is NULL", pdev_id); 258 return QDF_STATUS_E_INVAL; 259 } 260 261 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 262 if (!pdev_wmi_handle) { 263 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 264 target_if_err("pdev wmi handle NULL"); 265 return QDF_STATUS_E_FAILURE; 266 } 267 param.vdev_id = vdev_id; 268 param.peer_macaddr = peer_macaddr; 269 param.peer_tid_bitmap = peer_tid_bitmap; 270 status = wmi_unified_peer_rx_reorder_queue_remove_send(pdev_wmi_handle, 271 ¶m); 272 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 273 274 return status; 275 } 276 277 QDF_STATUS 278 target_if_lro_hash_config(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, 279 struct cdp_lro_hash_config *lro_hash_cfg) 280 { 281 struct wmi_lro_config_cmd_t wmi_lro_cmd = {0}; 282 struct wmi_unified *pdev_wmi_handle; 283 QDF_STATUS status; 284 struct wlan_objmgr_pdev *pdev = 285 wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, 286 pdev_id, WLAN_PDEV_TARGET_IF_ID); 287 288 if (!pdev) { 289 target_if_err("pdev with id %d is NULL", pdev_id); 290 return QDF_STATUS_E_INVAL; 291 } 292 293 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 294 if (!lro_hash_cfg || !pdev_wmi_handle) { 295 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 296 target_if_err("wmi_handle: 0x%pK, lro_hash_cfg: 0x%pK", 297 pdev_wmi_handle, lro_hash_cfg); 298 return QDF_STATUS_E_FAILURE; 299 } 300 301 wmi_lro_cmd.lro_enable = lro_hash_cfg->lro_enable; 302 wmi_lro_cmd.tcp_flag = lro_hash_cfg->tcp_flag; 303 wmi_lro_cmd.tcp_flag_mask = lro_hash_cfg->tcp_flag_mask; 304 wmi_lro_cmd.pdev_id = pdev_id; 305 306 qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv4, 307 lro_hash_cfg->toeplitz_hash_ipv4, 308 LRO_IPV4_SEED_ARR_SZ * sizeof(uint32_t)); 309 310 qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv6, 311 lro_hash_cfg->toeplitz_hash_ipv6, 312 LRO_IPV6_SEED_ARR_SZ * sizeof(uint32_t)); 313 314 status = wmi_unified_lro_config_cmd(pdev_wmi_handle, 315 &wmi_lro_cmd); 316 wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); 317 318 return status; 319 } 320 321 #ifdef WDS_CONV_TARGET_IF_OPS_ENABLE 322 QDF_STATUS 323 target_if_add_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 324 uint8_t *peer_mac, const uint8_t *dest_mac, 325 uint32_t flags, uint8_t type) 326 { 327 struct peer_add_wds_entry_params wmi_wds_param = {0}; 328 struct wmi_unified *pdev_wmi_handle; 329 struct wlan_objmgr_pdev *pdev; 330 struct wlan_objmgr_vdev *vdev; 331 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 332 QDF_STATUS status; 333 334 if (type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) 335 return QDF_STATUS_E_FAILURE; 336 337 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 338 WLAN_WDS_ID); 339 if (!vdev) { 340 target_if_err("vdev with id %d is NULL", vdev_id); 341 return QDF_STATUS_E_INVAL; 342 } 343 344 pdev = wlan_vdev_get_pdev(vdev); 345 if (!pdev) { 346 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 347 target_if_err("pdev is NULL"); 348 return QDF_STATUS_E_INVAL; 349 } 350 351 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 352 if (!pdev_wmi_handle) { 353 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 354 target_if_err("pdev_wmi_handle is NULL"); 355 return QDF_STATUS_E_INVAL; 356 } 357 358 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 359 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 360 wmi_wds_param.vdev_id = vdev_id; 361 wmi_wds_param.flags = flags; 362 363 status = wmi_unified_peer_add_wds_entry_cmd(pdev_wmi_handle, 364 &wmi_wds_param); 365 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 366 367 return status; 368 } 369 370 void 371 target_if_del_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 372 uint8_t *dest_mac, uint8_t type, uint8_t delete_in_fw) 373 { 374 struct peer_del_wds_entry_params wmi_wds_param = {0}; 375 struct wmi_unified *pdev_wmi_handle; 376 struct wlan_objmgr_pdev *pdev; 377 struct wlan_objmgr_vdev *vdev; 378 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 379 380 if (!delete_in_fw || type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) { 381 target_if_err("delete_in_fw: %d type: %d", delete_in_fw, type); 382 return; 383 } 384 385 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 386 WLAN_WDS_ID); 387 if (!vdev) { 388 target_if_err("vdev with id %d is NULL", vdev_id); 389 return; 390 } 391 392 pdev = wlan_vdev_get_pdev(vdev); 393 if (!pdev) { 394 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 395 target_if_err("pdev is NULL"); 396 return; 397 } 398 399 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 400 if (!pdev_wmi_handle) { 401 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 402 target_if_err("pdev_wmi_handle is NULL"); 403 return; 404 } 405 406 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 407 wmi_wds_param.vdev_id = vdev_id; 408 409 wmi_unified_peer_del_wds_entry_cmd(pdev_wmi_handle, 410 &wmi_wds_param); 411 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 412 } 413 414 QDF_STATUS 415 target_if_update_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 416 uint8_t *dest_mac, uint8_t *peer_mac, 417 uint32_t flags) 418 { 419 struct peer_update_wds_entry_params wmi_wds_param = {0}; 420 struct wmi_unified *pdev_wmi_handle; 421 struct wlan_objmgr_pdev *pdev; 422 struct wlan_objmgr_vdev *vdev; 423 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 424 QDF_STATUS status; 425 426 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 427 WLAN_WDS_ID); 428 if (!vdev) { 429 target_if_err("vdev with id %d is NULL", vdev_id); 430 return QDF_STATUS_E_INVAL; 431 } 432 433 pdev = wlan_vdev_get_pdev(vdev); 434 if (!pdev) { 435 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 436 target_if_err("pdev is NULL"); 437 return QDF_STATUS_E_INVAL; 438 } 439 440 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 441 if (!pdev_wmi_handle) { 442 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 443 target_if_err("pdev_wmi_handle is NULL"); 444 return QDF_STATUS_E_INVAL; 445 } 446 447 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 448 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 449 wmi_wds_param.vdev_id = vdev_id; 450 wmi_wds_param.flags = flags; 451 452 status = wmi_unified_update_wds_entry_cmd(pdev_wmi_handle, 453 &wmi_wds_param); 454 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 455 456 return status; 457 } 458 #endif 459 460 #ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF 461 /** 462 * map_flush_policy() - Map DP layer flush policy values to target i/f layer 463 * @policy: The DP layer flush policy value 464 * 465 * Return: Peer flush policy 466 */ 467 static enum peer_txq_flush_policy 468 map_flush_policy(enum cdp_peer_txq_flush_policy policy) 469 { 470 switch (policy) { 471 case CDP_PEER_TXQ_FLUSH_POLICY_NONE: 472 return PEER_TXQ_FLUSH_POLICY_NONE; 473 case CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END: 474 return PEER_TXQ_FLUSH_POLICY_TWT_SP_END; 475 default: 476 return PEER_TXQ_FLUSH_POLICY_INVALID; 477 } 478 } 479 480 /** 481 * send_peer_txq_flush_conf() - Send flush config for peers TID queues 482 * @psoc: Opaque handle for posc object manager object 483 * @mac: MAC addr of peer for which the tx queue flush is intended 484 * @vdev_id: VDEV identifier 485 * @tid: TID mask for identifying the tx queues to be flushed 486 * @policy: The peer tid queue flush policy 487 * 488 * Return: 0 for success or error code 489 */ 490 static int send_peer_txq_flush_conf(struct cdp_ctrl_objmgr_psoc *psoc, 491 uint8_t *mac, uint8_t vdev_id, 492 uint32_t tid, 493 enum cdp_peer_txq_flush_policy policy) 494 { 495 struct wlan_objmgr_psoc *obj_soc; 496 struct wmi_unified *wmi_handle; 497 enum peer_txq_flush_policy flush_policy; 498 struct peer_txq_flush_config_params param = {0}; 499 QDF_STATUS status; 500 501 obj_soc = (struct wlan_objmgr_psoc *)psoc; 502 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 503 if (!wmi_handle) { 504 target_if_err("Invalid wmi handle"); 505 return -EINVAL; 506 } 507 508 flush_policy = map_flush_policy(policy); 509 if (flush_policy >= PEER_TXQ_FLUSH_POLICY_INVALID) { 510 target_if_err("Invalid flush policy : %d", policy); 511 return -EINVAL; 512 } 513 514 param.vdev_id = vdev_id; 515 param.tid_mask = tid; 516 param.policy = flush_policy; 517 qdf_mem_copy(param.peer, mac, QDF_MAC_ADDR_SIZE); 518 519 status = wmi_unified_peer_txq_flush_config_send(wmi_handle, ¶m); 520 return qdf_status_to_os_return(status); 521 } 522 523 /** 524 * send_peer_txq_flush_tids() - Send flush command peers TID queues 525 * @psoc: Opaque handle for psoc object manager object 526 * @mac: MAC addr of peer for which the tx queue flush is intended 527 * @vdev_id: VDEV identifier 528 * @tid: TID mask for identifying the tx queues to be flushed 529 * 530 * Return: 0 for success or error code 531 */ 532 static int send_peer_txq_flush_tids(struct cdp_ctrl_objmgr_psoc *psoc, 533 uint8_t *mac, uint8_t vdev_id, 534 uint32_t tid) 535 { 536 struct wlan_objmgr_psoc *obj_soc; 537 struct wmi_unified *wmi_handle; 538 struct peer_flush_params param; 539 QDF_STATUS status; 540 541 if (!psoc || !mac) { 542 target_if_err("Invalid params"); 543 return -EINVAL; 544 } 545 546 obj_soc = (struct wlan_objmgr_psoc *)psoc; 547 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 548 if (!wmi_handle) { 549 target_if_err("Invalid wmi handle"); 550 return -EINVAL; 551 } 552 553 param.vdev_id = vdev_id; 554 param.peer_tid_bitmap = tid; 555 qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE); 556 557 status = wmi_unified_peer_flush_tids_send(wmi_handle, mac, ¶m); 558 return qdf_status_to_os_return(status); 559 } 560 561 int target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc, 562 uint8_t vdev_id, uint8_t *addr, 563 uint8_t ac, uint32_t tid, 564 enum cdp_peer_txq_flush_policy policy) 565 { 566 static uint8_t ac_to_tid[4][2] = { {0, 3}, {1, 2}, {4, 5}, {6, 7} }; 567 struct wlan_objmgr_psoc *obj_soc; 568 struct wlan_objmgr_peer *peer; 569 int i, rc; 570 571 if (!psoc || !addr) { 572 target_if_err("Invalid params"); 573 return -EINVAL; 574 } 575 576 if (!tid && !ac) { 577 target_if_err("no ac/tid mask setting"); 578 return -EINVAL; 579 } 580 581 if (tid && policy == CDP_PEER_TXQ_FLUSH_POLICY_INVALID) { 582 target_if_err("Invalid flush policy"); 583 return -EINVAL; 584 } 585 obj_soc = (struct wlan_objmgr_psoc *)psoc; 586 587 peer = wlan_objmgr_get_peer_by_mac(obj_soc, addr, WLAN_DP_ID); 588 if (!peer) { 589 target_if_err("Peer not found in the list"); 590 return -EINVAL; 591 } 592 /* If tid mask is provided and policy is immediate use legacy WMI. 593 * If tid mask is provided and policy is other than immediate use 594 * the new WMI command for flush config. 595 * If tid mask is not provided and ac mask is provided, convert to tid, 596 * use the legacy WMI cmd for flushing the queues immediately. 597 */ 598 if (tid) { 599 if (policy == CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE) { 600 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 601 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 602 return rc; 603 } 604 rc = send_peer_txq_flush_conf(psoc, addr, vdev_id, tid, policy); 605 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 606 return rc; 607 } 608 609 if (ac) { 610 tid = 0; 611 for (i = 0; i < 4; ++i) { 612 if (((ac & 0x0f) >> i) & 0x01) { 613 tid |= (1 << ac_to_tid[i][0]) | 614 (1 << ac_to_tid[i][1]); 615 } 616 } 617 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 618 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 619 return rc; 620 } 621 /* should not hit this line */ 622 return 0; 623 } 624 #endif 625