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