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 WLAN_SUPPORT_PPEDS 322 QDF_STATUS 323 target_if_peer_set_ppe_default_routing(struct cdp_ctrl_objmgr_psoc *psoc, 324 uint8_t *peer_macaddr, 325 uint16_t service_code, 326 uint8_t priority_valid, 327 uint16_t src_info, 328 uint8_t vdev_id, uint8_t use_ppe, 329 uint8_t ppe_routing_enabled) 330 { 331 struct wmi_unified *wmi_handle; 332 struct peer_ppe_ds_param param; 333 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 334 335 if (!psoc) { 336 target_if_err("PSOC is NULL!"); 337 return QDF_STATUS_E_NULL_VALUE; 338 } 339 340 wmi_handle = 341 get_wmi_unified_hdl_from_psoc((struct wlan_objmgr_psoc *)psoc); 342 if (!wmi_handle) { 343 target_if_err("wmi_handle is null"); 344 return QDF_STATUS_E_INVAL; 345 } 346 347 qdf_mem_zero(¶m, sizeof(param)); 348 349 qdf_mem_copy(¶m.peer_macaddr[0], peer_macaddr, QDF_MAC_ADDR_SIZE); 350 param.ppe_routing_enabled = ppe_routing_enabled; 351 param.service_code = service_code; 352 param.priority_valid = priority_valid; 353 param.src_info = src_info; 354 param.vdev_id = vdev_id; 355 param.use_ppe = use_ppe; 356 357 qdf_status = wmi_unified_peer_ppe_ds_param_send(wmi_handle, ¶m); 358 if (qdf_status != QDF_STATUS_SUCCESS) { 359 target_if_err("Unable to set PPE default routing for peer " 360 QDF_MAC_ADDR_FMT, 361 QDF_MAC_ADDR_REF(peer_macaddr)); 362 } 363 364 return qdf_status; 365 } 366 #endif /* WLAN_SUPPORT_PPEDS */ 367 368 #ifdef WDS_CONV_TARGET_IF_OPS_ENABLE 369 QDF_STATUS 370 target_if_add_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 371 uint8_t *peer_mac, const uint8_t *dest_mac, 372 uint32_t flags, uint8_t type) 373 { 374 struct peer_add_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 QDF_STATUS status; 380 381 if (type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) 382 return QDF_STATUS_E_FAILURE; 383 384 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 385 WLAN_WDS_ID); 386 if (!vdev) { 387 target_if_err("vdev with id %d is NULL", vdev_id); 388 return QDF_STATUS_E_INVAL; 389 } 390 391 pdev = wlan_vdev_get_pdev(vdev); 392 if (!pdev) { 393 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 394 target_if_err("pdev is NULL"); 395 return QDF_STATUS_E_INVAL; 396 } 397 398 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 399 if (!pdev_wmi_handle) { 400 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 401 target_if_err("pdev_wmi_handle is NULL"); 402 return QDF_STATUS_E_INVAL; 403 } 404 405 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 406 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 407 wmi_wds_param.vdev_id = vdev_id; 408 wmi_wds_param.flags = flags; 409 410 status = wmi_unified_peer_add_wds_entry_cmd(pdev_wmi_handle, 411 &wmi_wds_param); 412 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 413 414 return status; 415 } 416 417 void 418 target_if_del_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 419 uint8_t *dest_mac, uint8_t type, uint8_t delete_in_fw) 420 { 421 struct peer_del_wds_entry_params wmi_wds_param = {0}; 422 struct wmi_unified *pdev_wmi_handle; 423 struct wlan_objmgr_pdev *pdev; 424 struct wlan_objmgr_vdev *vdev; 425 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 426 427 if (!delete_in_fw || type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) { 428 target_if_err("delete_in_fw: %d type: %d", delete_in_fw, type); 429 return; 430 } 431 432 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 433 WLAN_WDS_ID); 434 if (!vdev) { 435 target_if_err("vdev with id %d is NULL", vdev_id); 436 return; 437 } 438 439 pdev = wlan_vdev_get_pdev(vdev); 440 if (!pdev) { 441 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 442 target_if_err("pdev is NULL"); 443 return; 444 } 445 446 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 447 if (!pdev_wmi_handle) { 448 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 449 target_if_err("pdev_wmi_handle is NULL"); 450 return; 451 } 452 453 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 454 wmi_wds_param.vdev_id = vdev_id; 455 456 wmi_unified_peer_del_wds_entry_cmd(pdev_wmi_handle, 457 &wmi_wds_param); 458 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 459 } 460 461 QDF_STATUS 462 target_if_update_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id, 463 uint8_t *dest_mac, uint8_t *peer_mac, 464 uint32_t flags) 465 { 466 struct peer_update_wds_entry_params wmi_wds_param = {0}; 467 struct wmi_unified *pdev_wmi_handle; 468 struct wlan_objmgr_pdev *pdev; 469 struct wlan_objmgr_vdev *vdev; 470 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; 471 QDF_STATUS status; 472 473 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 474 WLAN_WDS_ID); 475 if (!vdev) { 476 target_if_err("vdev with id %d is NULL", vdev_id); 477 return QDF_STATUS_E_INVAL; 478 } 479 480 pdev = wlan_vdev_get_pdev(vdev); 481 if (!pdev) { 482 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 483 target_if_err("pdev is NULL"); 484 return QDF_STATUS_E_INVAL; 485 } 486 487 pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); 488 if (!pdev_wmi_handle) { 489 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 490 target_if_err("pdev_wmi_handle is NULL"); 491 return QDF_STATUS_E_INVAL; 492 } 493 494 qdf_mem_copy(&wmi_wds_param.dest_addr, dest_mac, QDF_MAC_ADDR_SIZE); 495 qdf_mem_copy(&wmi_wds_param.peer_addr, peer_mac, QDF_MAC_ADDR_SIZE); 496 wmi_wds_param.vdev_id = vdev_id; 497 wmi_wds_param.flags = flags; 498 499 status = wmi_unified_update_wds_entry_cmd(pdev_wmi_handle, 500 &wmi_wds_param); 501 wlan_objmgr_vdev_release_ref(vdev, WLAN_WDS_ID); 502 503 return status; 504 } 505 #endif 506 507 #ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF 508 /** 509 * map_flush_policy() - Map DP layer flush policy values to target i/f layer 510 * @policy: The DP layer flush policy value 511 * 512 * Return: Peer flush policy 513 */ 514 static enum peer_txq_flush_policy 515 map_flush_policy(enum cdp_peer_txq_flush_policy policy) 516 { 517 switch (policy) { 518 case CDP_PEER_TXQ_FLUSH_POLICY_NONE: 519 return PEER_TXQ_FLUSH_POLICY_NONE; 520 case CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END: 521 return PEER_TXQ_FLUSH_POLICY_TWT_SP_END; 522 default: 523 return PEER_TXQ_FLUSH_POLICY_INVALID; 524 } 525 } 526 527 /** 528 * send_peer_txq_flush_conf() - Send flush config for peers TID queues 529 * @psoc: Opaque handle for posc object manager object 530 * @mac: MAC addr of peer for which the tx queue flush is intended 531 * @vdev_id: VDEV identifier 532 * @tid: TID mask for identifying the tx queues to be flushed 533 * @policy: The peer tid queue flush policy 534 * 535 * Return: 0 for success or error code 536 */ 537 static int send_peer_txq_flush_conf(struct cdp_ctrl_objmgr_psoc *psoc, 538 uint8_t *mac, uint8_t vdev_id, 539 uint32_t tid, 540 enum cdp_peer_txq_flush_policy policy) 541 { 542 struct wlan_objmgr_psoc *obj_soc; 543 struct wmi_unified *wmi_handle; 544 enum peer_txq_flush_policy flush_policy; 545 struct peer_txq_flush_config_params param = {0}; 546 QDF_STATUS status; 547 548 obj_soc = (struct wlan_objmgr_psoc *)psoc; 549 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 550 if (!wmi_handle) { 551 target_if_err("Invalid wmi handle"); 552 return -EINVAL; 553 } 554 555 flush_policy = map_flush_policy(policy); 556 if (flush_policy >= PEER_TXQ_FLUSH_POLICY_INVALID) { 557 target_if_err("Invalid flush policy : %d", policy); 558 return -EINVAL; 559 } 560 561 param.vdev_id = vdev_id; 562 param.tid_mask = tid; 563 param.policy = flush_policy; 564 qdf_mem_copy(param.peer, mac, QDF_MAC_ADDR_SIZE); 565 566 status = wmi_unified_peer_txq_flush_config_send(wmi_handle, ¶m); 567 return qdf_status_to_os_return(status); 568 } 569 570 /** 571 * send_peer_txq_flush_tids() - Send flush command peers TID queues 572 * @psoc: Opaque handle for psoc object manager object 573 * @mac: MAC addr of peer for which the tx queue flush is intended 574 * @vdev_id: VDEV identifier 575 * @tid: TID mask for identifying the tx queues to be flushed 576 * 577 * Return: 0 for success or error code 578 */ 579 static int send_peer_txq_flush_tids(struct cdp_ctrl_objmgr_psoc *psoc, 580 uint8_t *mac, uint8_t vdev_id, 581 uint32_t tid) 582 { 583 struct wlan_objmgr_psoc *obj_soc; 584 struct wmi_unified *wmi_handle; 585 struct peer_flush_params param; 586 QDF_STATUS status; 587 588 if (!psoc || !mac) { 589 target_if_err("Invalid params"); 590 return -EINVAL; 591 } 592 593 obj_soc = (struct wlan_objmgr_psoc *)psoc; 594 wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc); 595 if (!wmi_handle) { 596 target_if_err("Invalid wmi handle"); 597 return -EINVAL; 598 } 599 600 param.vdev_id = vdev_id; 601 param.peer_tid_bitmap = tid; 602 qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE); 603 604 status = wmi_unified_peer_flush_tids_send(wmi_handle, mac, ¶m); 605 return qdf_status_to_os_return(status); 606 } 607 608 int target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc, 609 uint8_t vdev_id, uint8_t *addr, 610 uint8_t ac, uint32_t tid, 611 enum cdp_peer_txq_flush_policy policy) 612 { 613 static uint8_t ac_to_tid[4][2] = { {0, 3}, {1, 2}, {4, 5}, {6, 7} }; 614 struct wlan_objmgr_psoc *obj_soc; 615 struct wlan_objmgr_peer *peer; 616 int i, rc; 617 618 if (!psoc || !addr) { 619 target_if_err("Invalid params"); 620 return -EINVAL; 621 } 622 623 if (!tid && !ac) { 624 target_if_err("no ac/tid mask setting"); 625 return -EINVAL; 626 } 627 628 if (tid && policy == CDP_PEER_TXQ_FLUSH_POLICY_INVALID) { 629 target_if_err("Invalid flush policy"); 630 return -EINVAL; 631 } 632 obj_soc = (struct wlan_objmgr_psoc *)psoc; 633 634 peer = wlan_objmgr_get_peer_by_mac(obj_soc, addr, WLAN_DP_ID); 635 if (!peer) { 636 target_if_err("Peer not found in the list"); 637 return -EINVAL; 638 } 639 /* If tid mask is provided and policy is immediate use legacy WMI. 640 * If tid mask is provided and policy is other than immediate use 641 * the new WMI command for flush config. 642 * If tid mask is not provided and ac mask is provided, convert to tid, 643 * use the legacy WMI cmd for flushing the queues immediately. 644 */ 645 if (tid) { 646 if (policy == CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE) { 647 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 648 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 649 return rc; 650 } 651 rc = send_peer_txq_flush_conf(psoc, addr, vdev_id, tid, policy); 652 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 653 return rc; 654 } 655 656 if (ac) { 657 tid = 0; 658 for (i = 0; i < 4; ++i) { 659 if (((ac & 0x0f) >> i) & 0x01) { 660 tid |= (1 << ac_to_tid[i][0]) | 661 (1 << ac_to_tid[i][1]); 662 } 663 } 664 rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid); 665 wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID); 666 return rc; 667 } 668 /* should not hit this line */ 669 return 0; 670 } 671 #endif 672