1 /* 2 * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-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 #include <qdf_atomic.h> /* qdf_atomic_inc, etc. */ 21 #include <qdf_lock.h> /* qdf_os_spinlock */ 22 #include <qdf_time.h> /* qdf_system_ticks, etc. */ 23 #include <qdf_nbuf.h> /* qdf_nbuf_t */ 24 #include <qdf_net_types.h> /* QDF_NBUF_TX_EXT_TID_INVALID */ 25 26 #include "queue.h" /* TAILQ */ 27 #ifdef QCA_COMPUTE_TX_DELAY 28 #include <enet.h> /* ethernet_hdr_t, etc. */ 29 #include <ipv6_defs.h> /* ipv6_traffic_class */ 30 #endif 31 32 #include <ol_txrx_api.h> /* ol_txrx_vdev_handle, etc. */ 33 #include <ol_htt_tx_api.h> /* htt_tx_compl_desc_id */ 34 #include <ol_txrx_htt_api.h> /* htt_tx_status */ 35 36 #include <ol_ctrl_txrx_api.h> 37 #include <cdp_txrx_tx_delay.h> 38 #include <ol_txrx_types.h> /* ol_txrx_vdev_t, etc */ 39 #include <ol_tx_desc.h> /* ol_tx_desc_find, ol_tx_desc_frame_free */ 40 #ifdef QCA_COMPUTE_TX_DELAY 41 #include <ol_tx_classify.h> /* ol_tx_dest_addr_find */ 42 #endif 43 #include <ol_txrx_internal.h> /* OL_TX_DESC_NO_REFS, etc. */ 44 #include <ol_osif_txrx_api.h> 45 #include <ol_tx.h> /* ol_tx_reinject */ 46 #include <ol_tx_send.h> 47 48 #include <ol_cfg.h> /* ol_cfg_is_high_latency */ 49 #include <ol_tx_sched.h> 50 #ifdef QCA_SUPPORT_SW_TXRX_ENCAP 51 #include <ol_txrx_encap.h> /* OL_TX_RESTORE_HDR, etc */ 52 #endif 53 #include <ol_tx_queue.h> 54 #include <ol_txrx.h> 55 #include <pktlog_ac_fmt.h> 56 #include <cdp_txrx_handle.h> 57 #include <wlan_reg_services_api.h> 58 #include "qdf_hrtimer.h" 59 60 /* High/Low tx resource count in percentage */ 61 /* Set default high threshold to 15% */ 62 #ifndef TX_RESOURCE_HIGH_TH_IN_PER 63 #define TX_RESOURCE_HIGH_TH_IN_PER 15 64 #endif 65 66 /* Set default low threshold to 5% */ 67 #ifndef TX_RESOURCE_LOW_TH_IN_PER 68 #define TX_RESOURCE_LOW_TH_IN_PER 5 69 #endif 70 71 #ifdef QCA_HL_NETDEV_FLOW_CONTROL 72 static u16 ol_txrx_tx_desc_alloc_table[TXRX_FC_MAX] = { 73 [TXRX_FC_5GH_80M_2x2] = 2000, 74 [TXRX_FC_2GH_40M_2x2] = 800, 75 }; 76 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */ 77 78 /* tx filtering is handled within the target FW */ 79 #define TX_FILTER_CHECK(tx_msdu_info) 0 /* don't filter */ 80 81 u_int16_t ol_tx_desc_pool_size_hl(struct cdp_cfg * ctrl_pdev)82 ol_tx_desc_pool_size_hl(struct cdp_cfg *ctrl_pdev) 83 { 84 uint16_t desc_pool_size; 85 uint16_t steady_state_tx_lifetime_ms; 86 uint16_t safety_factor; 87 88 /* 89 * Steady-state tx latency: 90 * roughly 1-2 ms flight time 91 * + roughly 1-2 ms prep time, 92 * + roughly 1-2 ms target->host notification time. 93 * = roughly 6 ms total 94 * Thus, steady state number of frames = 95 * steady state max throughput / frame size * tx latency, e.g. 96 * 1 Gbps / 1500 bytes * 6 ms = 500 97 * 98 */ 99 steady_state_tx_lifetime_ms = 6; 100 101 safety_factor = 8; 102 103 desc_pool_size = 104 ol_cfg_max_thruput_mbps(ctrl_pdev) * 105 1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ / 106 (8 * OL_TX_AVG_FRM_BYTES) * 107 steady_state_tx_lifetime_ms * 108 safety_factor; 109 110 /* minimum */ 111 if (desc_pool_size < OL_TX_DESC_POOL_SIZE_MIN_HL) 112 desc_pool_size = OL_TX_DESC_POOL_SIZE_MIN_HL; 113 114 /* maximum */ 115 if (desc_pool_size > OL_TX_DESC_POOL_SIZE_MAX_HL) 116 desc_pool_size = OL_TX_DESC_POOL_SIZE_MAX_HL; 117 118 return desc_pool_size; 119 } 120 121 #ifdef CONFIG_TX_DESC_HI_PRIO_RESERVE 122 123 /** 124 * ol_tx_hl_desc_alloc() - Allocate and initialize a tx descriptor 125 * for a HL system. 126 * @pdev: the data physical device sending the data 127 * @vdev: the virtual device sending the data 128 * @msdu: the tx frame 129 * @msdu_info: the tx meta data 130 * 131 * Return: the tx descriptor 132 */ 133 static inline ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)134 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev, 135 struct ol_txrx_vdev_t *vdev, 136 qdf_nbuf_t msdu, 137 struct ol_txrx_msdu_info_t *msdu_info) 138 { 139 struct ol_tx_desc_t *tx_desc = NULL; 140 141 if (qdf_atomic_read(&pdev->tx_queue.rsrc_cnt) > 142 TXRX_HL_TX_DESC_HI_PRIO_RESERVED) { 143 tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info); 144 } else if (qdf_nbuf_is_ipv4_pkt(msdu) == true) { 145 if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 146 QDF_NBUF_CB_PACKET_TYPE_DHCP) || 147 (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 148 QDF_NBUF_CB_PACKET_TYPE_EAPOL)) { 149 tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info); 150 ol_txrx_info("Got tx desc from resv pool"); 151 } 152 } 153 return tx_desc; 154 } 155 156 #elif defined(QCA_HL_NETDEV_FLOW_CONTROL) ol_tx_desc_is_high_prio(qdf_nbuf_t msdu)157 bool ol_tx_desc_is_high_prio(qdf_nbuf_t msdu) 158 { 159 enum qdf_proto_subtype proto_subtype; 160 bool high_prio = false; 161 162 if (qdf_nbuf_is_ipv4_pkt(msdu) == true) { 163 if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 164 QDF_NBUF_CB_PACKET_TYPE_DHCP) || 165 (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 166 QDF_NBUF_CB_PACKET_TYPE_EAPOL)) 167 high_prio = true; 168 } else if (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 169 QDF_NBUF_CB_PACKET_TYPE_ARP) { 170 high_prio = true; 171 } else if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) == 172 QDF_NBUF_CB_PACKET_TYPE_ICMPv6)) { 173 proto_subtype = qdf_nbuf_get_icmpv6_subtype(msdu); 174 switch (proto_subtype) { 175 case QDF_PROTO_ICMPV6_NA: 176 case QDF_PROTO_ICMPV6_NS: 177 high_prio = true; 178 default: 179 high_prio = false; 180 } 181 } 182 return high_prio; 183 } 184 185 static inline ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)186 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev, 187 struct ol_txrx_vdev_t *vdev, 188 qdf_nbuf_t msdu, 189 struct ol_txrx_msdu_info_t *msdu_info) 190 { 191 struct ol_tx_desc_t *tx_desc = 192 ol_tx_desc_hl(pdev, vdev, msdu, msdu_info); 193 194 if (!tx_desc) 195 return NULL; 196 197 qdf_spin_lock_bh(&pdev->tx_mutex); 198 /* return if TX flow control disabled */ 199 if (vdev->tx_desc_limit == 0) { 200 qdf_spin_unlock_bh(&pdev->tx_mutex); 201 return tx_desc; 202 } 203 204 if (!qdf_atomic_read(&vdev->os_q_paused) && 205 (qdf_atomic_read(&vdev->tx_desc_count) >= vdev->queue_stop_th)) { 206 /* 207 * Pause normal priority 208 * netdev queues if tx desc limit crosses 209 */ 210 pdev->pause_cb(vdev->vdev_id, 211 WLAN_STOP_NON_PRIORITY_QUEUE, 212 WLAN_DATA_FLOW_CONTROL); 213 qdf_atomic_set(&vdev->os_q_paused, 1); 214 } else if (ol_tx_desc_is_high_prio(msdu) && !vdev->prio_q_paused && 215 (qdf_atomic_read(&vdev->tx_desc_count) 216 == vdev->tx_desc_limit)) { 217 /* Pause high priority queue */ 218 pdev->pause_cb(vdev->vdev_id, 219 WLAN_NETIF_PRIORITY_QUEUE_OFF, 220 WLAN_DATA_FLOW_CONTROL_PRIORITY); 221 vdev->prio_q_paused = 1; 222 } 223 qdf_spin_unlock_bh(&pdev->tx_mutex); 224 225 return tx_desc; 226 } 227 228 #else 229 230 static inline ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)231 struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev, 232 struct ol_txrx_vdev_t *vdev, 233 qdf_nbuf_t msdu, 234 struct ol_txrx_msdu_info_t *msdu_info) 235 { 236 struct ol_tx_desc_t *tx_desc = NULL; 237 238 tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info); 239 return tx_desc; 240 } 241 #endif 242 243 static inline uint16_t ol_txrx_rsrc_threshold_lo(int desc_pool_size)244 ol_txrx_rsrc_threshold_lo(int desc_pool_size) 245 { 246 int threshold_low; 247 248 /* always maintain a 5% margin of unallocated descriptors */ 249 threshold_low = ((TX_RESOURCE_LOW_TH_IN_PER) * 250 desc_pool_size) / 100; 251 252 return threshold_low; 253 } 254 255 static inline uint16_t ol_txrx_rsrc_threshold_hi(int desc_pool_size)256 ol_txrx_rsrc_threshold_hi(int desc_pool_size) 257 { 258 int threshold_high; 259 /* when freeing up descriptors, keep going until 260 * there's a 15% margin 261 */ 262 threshold_high = ((TX_RESOURCE_HIGH_TH_IN_PER) * 263 desc_pool_size) / 100; 264 265 return threshold_high; 266 } 267 ol_tx_init_pdev(ol_txrx_pdev_handle pdev)268 void ol_tx_init_pdev(ol_txrx_pdev_handle pdev) 269 { 270 uint16_t desc_pool_size, i; 271 272 desc_pool_size = ol_tx_desc_pool_size_hl(pdev->ctrl_pdev); 273 274 qdf_atomic_init(&pdev->tx_queue.rsrc_cnt); 275 qdf_atomic_add(desc_pool_size, &pdev->tx_queue.rsrc_cnt); 276 277 pdev->tx_queue.rsrc_threshold_lo = 278 ol_txrx_rsrc_threshold_lo(desc_pool_size); 279 pdev->tx_queue.rsrc_threshold_hi = 280 ol_txrx_rsrc_threshold_hi(desc_pool_size); 281 282 for (i = 0 ; i < OL_TX_MAX_TXQ_GROUPS; i++) 283 qdf_atomic_init(&pdev->txq_grps[i].credit); 284 285 ol_tx_target_credit_init(pdev, desc_pool_size); 286 } 287 288 #ifdef QCA_SUPPORT_SW_TXRX_ENCAP ol_tx_encap_wrapper(struct ol_txrx_pdev_t * pdev,ol_txrx_vdev_handle vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * tx_msdu_info)289 static inline int ol_tx_encap_wrapper(struct ol_txrx_pdev_t *pdev, 290 ol_txrx_vdev_handle vdev, 291 struct ol_tx_desc_t *tx_desc, 292 qdf_nbuf_t msdu, 293 struct ol_txrx_msdu_info_t *tx_msdu_info) 294 { 295 if (OL_TX_ENCAP(vdev, tx_desc, msdu, tx_msdu_info) != A_OK) { 296 qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt); 297 ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); 298 if (tx_msdu_info->peer) { 299 /* remove the peer reference added above */ 300 ol_txrx_peer_release_ref(tx_msdu_info->peer, 301 PEER_DEBUG_ID_OL_INTERNAL); 302 } 303 return -EINVAL; 304 } 305 306 return 0; 307 } 308 #else ol_tx_encap_wrapper(struct ol_txrx_pdev_t * pdev,ol_txrx_vdev_handle vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * tx_msdu_info)309 static inline int ol_tx_encap_wrapper(struct ol_txrx_pdev_t *pdev, 310 ol_txrx_vdev_handle vdev, 311 struct ol_tx_desc_t *tx_desc, 312 qdf_nbuf_t msdu, 313 struct ol_txrx_msdu_info_t *tx_msdu_info) 314 { 315 /* no-op */ 316 return 0; 317 } 318 #endif 319 320 /** 321 * parse_ocb_tx_header() - Function to check for OCB 322 * @msdu: Pointer to OS packet (qdf_nbuf_t) 323 * @tx_ctrl: TX control header on a packet and extract it if present 324 * 325 * Return: true if ocb parsing is successful 326 */ 327 #ifdef WLAN_FEATURE_DSRC 328 #define OCB_HEADER_VERSION 1 parse_ocb_tx_header(qdf_nbuf_t msdu,struct ocb_tx_ctrl_hdr_t * tx_ctrl)329 static bool parse_ocb_tx_header(qdf_nbuf_t msdu, 330 struct ocb_tx_ctrl_hdr_t *tx_ctrl) 331 { 332 qdf_ether_header_t *eth_hdr_p; 333 struct ocb_tx_ctrl_hdr_t *tx_ctrl_hdr; 334 335 /* Check if TX control header is present */ 336 eth_hdr_p = (qdf_ether_header_t *)qdf_nbuf_data(msdu); 337 if (eth_hdr_p->ether_type != QDF_SWAP_U16(ETHERTYPE_OCB_TX)) 338 /* TX control header is not present. Nothing to do.. */ 339 return true; 340 341 /* Remove the ethernet header */ 342 qdf_nbuf_pull_head(msdu, sizeof(qdf_ether_header_t)); 343 344 /* Parse the TX control header */ 345 tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t *)qdf_nbuf_data(msdu); 346 347 if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) { 348 if (tx_ctrl) 349 qdf_mem_copy(tx_ctrl, tx_ctrl_hdr, 350 sizeof(*tx_ctrl_hdr)); 351 } else { 352 /* The TX control header is invalid. */ 353 return false; 354 } 355 356 /* Remove the TX control header */ 357 qdf_nbuf_pull_head(msdu, tx_ctrl_hdr->length); 358 return true; 359 } 360 #else parse_ocb_tx_header(qdf_nbuf_t msdu,struct ocb_tx_ctrl_hdr_t * tx_ctrl)361 static bool parse_ocb_tx_header(qdf_nbuf_t msdu, 362 struct ocb_tx_ctrl_hdr_t *tx_ctrl) 363 { 364 return true; 365 } 366 #endif 367 368 /** 369 * ol_txrx_mgmt_tx_desc_alloc() - Allocate and initialize a tx descriptor 370 * for management frame 371 * @pdev: the data physical device sending the data 372 * @vdev: the virtual device sending the data 373 * @tx_mgmt_frm: the tx management frame 374 * @tx_msdu_info: the tx meta data 375 * 376 * Return: the tx descriptor 377 */ 378 struct ol_tx_desc_t * ol_txrx_mgmt_tx_desc_alloc(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,qdf_nbuf_t tx_mgmt_frm,struct ol_txrx_msdu_info_t * tx_msdu_info)379 ol_txrx_mgmt_tx_desc_alloc( 380 struct ol_txrx_pdev_t *pdev, 381 struct ol_txrx_vdev_t *vdev, 382 qdf_nbuf_t tx_mgmt_frm, 383 struct ol_txrx_msdu_info_t *tx_msdu_info) 384 { 385 struct ol_tx_desc_t *tx_desc; 386 387 tx_msdu_info->htt.action.tx_comp_req = 1; 388 tx_desc = ol_tx_desc_hl(pdev, vdev, tx_mgmt_frm, tx_msdu_info); 389 return tx_desc; 390 } 391 392 /** 393 * ol_txrx_mgmt_send_frame() - send a management frame 394 * @vdev: virtual device sending the frame 395 * @tx_desc: tx desc 396 * @tx_mgmt_frm: management frame to send 397 * @tx_msdu_info: the tx meta data 398 * @chanfreq: download change frequency 399 * 400 * Return: 401 * 0 -> the frame is accepted for transmission, -OR- 402 * 1 -> the frame was not accepted 403 */ ol_txrx_mgmt_send_frame(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_mgmt_frm,struct ol_txrx_msdu_info_t * tx_msdu_info,uint16_t chanfreq)404 int ol_txrx_mgmt_send_frame( 405 struct ol_txrx_vdev_t *vdev, 406 struct ol_tx_desc_t *tx_desc, 407 qdf_nbuf_t tx_mgmt_frm, 408 struct ol_txrx_msdu_info_t *tx_msdu_info, 409 uint16_t chanfreq) 410 { 411 struct ol_txrx_pdev_t *pdev = vdev->pdev; 412 struct ol_tx_frms_queue_t *txq; 413 int status = 1; 414 415 /* 416 * 1. Look up the peer and queue the frame in the peer's mgmt queue. 417 * 2. Invoke the download scheduler. 418 */ 419 txq = ol_tx_classify_mgmt(vdev, tx_desc, tx_mgmt_frm, tx_msdu_info); 420 if (!txq) { 421 /* TXRX_STATS_MSDU_LIST_INCR(vdev->pdev, tx.dropped.no_txq, 422 * msdu); 423 */ 424 qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt); 425 ol_tx_desc_frame_free_nonstd(vdev->pdev, tx_desc, 426 1 /* error */); 427 goto out; /* can't accept the tx mgmt frame */ 428 } 429 /* Initialize the HTT tx desc l2 header offset field. 430 * Even though tx encap does not apply to mgmt frames, 431 * htt_tx_desc_mpdu_header still needs to be called, 432 * to specify that there was no L2 header added by tx encap, 433 * so the frame's length does not need to be adjusted to account for 434 * an added L2 header. 435 */ 436 htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0); 437 if (qdf_unlikely(htt_tx_desc_init( 438 pdev->htt_pdev, tx_desc->htt_tx_desc, 439 tx_desc->htt_tx_desc_paddr, 440 ol_tx_desc_id(pdev, tx_desc), 441 tx_mgmt_frm, 442 &tx_msdu_info->htt, &tx_msdu_info->tso_info, NULL, 0))) 443 goto out; 444 htt_tx_desc_display(tx_desc->htt_tx_desc); 445 htt_tx_desc_set_chanfreq(tx_desc->htt_tx_desc, chanfreq); 446 447 ol_tx_enqueue(vdev->pdev, txq, tx_desc, tx_msdu_info); 448 ol_tx_sched(vdev->pdev); 449 status = 0; 450 out: 451 if (tx_msdu_info->peer) { 452 /* remove the peer reference added above */ 453 ol_txrx_peer_release_ref(tx_msdu_info->peer, 454 PEER_DEBUG_ID_OL_INTERNAL); 455 } 456 457 return status; 458 } 459 460 /** 461 * ol_tx_hl_base() - send tx frames for a HL system. 462 * @vdev: the virtual device sending the data 463 * @tx_spec: indicate what non-standard transmission actions to apply 464 * @msdu_list: the tx frames to send 465 * @tx_comp_req: tx completion req 466 * @call_sched: will schedule the tx if true 467 * 468 * Return: NULL if all MSDUs are accepted 469 */ 470 static inline qdf_nbuf_t ol_tx_hl_base(ol_txrx_vdev_handle vdev,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list,int tx_comp_req,bool call_sched)471 ol_tx_hl_base( 472 ol_txrx_vdev_handle vdev, 473 enum ol_tx_spec tx_spec, 474 qdf_nbuf_t msdu_list, 475 int tx_comp_req, 476 bool call_sched) 477 { 478 struct ol_txrx_pdev_t *pdev = vdev->pdev; 479 qdf_nbuf_t msdu = msdu_list; 480 struct ol_txrx_msdu_info_t tx_msdu_info; 481 struct ocb_tx_ctrl_hdr_t tx_ctrl; 482 htt_pdev_handle htt_pdev = pdev->htt_pdev; 483 484 tx_msdu_info.tso_info.is_tso = 0; 485 486 /* 487 * The msdu_list variable could be used instead of the msdu var, 488 * but just to clarify which operations are done on a single MSDU 489 * vs. a list of MSDUs, use a distinct variable for single MSDUs 490 * within the list. 491 */ 492 while (msdu) { 493 qdf_nbuf_t next; 494 struct ol_tx_frms_queue_t *txq; 495 struct ol_tx_desc_t *tx_desc = NULL; 496 497 qdf_mem_zero(&tx_ctrl, sizeof(tx_ctrl)); 498 tx_msdu_info.peer = NULL; 499 /* 500 * The netbuf will get stored into a (peer-TID) tx queue list 501 * inside the ol_tx_classify_store function or else dropped, 502 * so store the next pointer immediately. 503 */ 504 next = qdf_nbuf_next(msdu); 505 506 tx_desc = ol_tx_hl_desc_alloc(pdev, vdev, msdu, &tx_msdu_info); 507 508 if (!tx_desc) { 509 /* 510 * If we're out of tx descs, there's no need to try 511 * to allocate tx descs for the remaining MSDUs. 512 */ 513 TXRX_STATS_MSDU_LIST_INCR(pdev, tx.dropped.host_reject, 514 msdu); 515 return msdu; /* the list of unaccepted MSDUs */ 516 } 517 518 /* OL_TXRX_PROT_AN_LOG(pdev->prot_an_tx_sent, msdu);*/ 519 520 qdf_dp_trace_log_pkt(vdev->vdev_id, msdu, QDF_TX, 521 QDF_TRACE_DEFAULT_PDEV_ID, 522 vdev->qdf_opmode); 523 DPTRACE(qdf_dp_trace_data_pkt(msdu, QDF_TRACE_DEFAULT_PDEV_ID, 524 QDF_DP_TRACE_TX_PACKET_RECORD, 525 tx_desc->id, QDF_TX)); 526 527 if (tx_spec != OL_TX_SPEC_STD) { 528 #if defined(FEATURE_WLAN_TDLS) 529 if (tx_spec & OL_TX_SPEC_NO_FREE) { 530 tx_desc->pkt_type = OL_TX_FRM_NO_FREE; 531 } else if (tx_spec & OL_TX_SPEC_TSO) { 532 #else 533 if (tx_spec & OL_TX_SPEC_TSO) { 534 #endif 535 tx_desc->pkt_type = OL_TX_FRM_TSO; 536 } 537 if (ol_txrx_tx_is_raw(tx_spec)) { 538 /* CHECK THIS: does this need 539 * to happen after htt_tx_desc_init? 540 */ 541 /* different types of raw frames */ 542 u_int8_t sub_type = 543 ol_txrx_tx_raw_subtype( 544 tx_spec); 545 htt_tx_desc_type(htt_pdev, 546 tx_desc->htt_tx_desc, 547 htt_pkt_type_raw, 548 sub_type); 549 } 550 } 551 552 tx_msdu_info.htt.info.ext_tid = qdf_nbuf_get_tid(msdu); 553 tx_msdu_info.htt.info.vdev_id = vdev->vdev_id; 554 tx_msdu_info.htt.info.frame_type = htt_frm_type_data; 555 tx_msdu_info.htt.info.l2_hdr_type = pdev->htt_pkt_type; 556 557 if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(msdu) 558 == 1) { 559 tx_msdu_info.htt.action.tx_comp_req = 1; 560 tx_desc->pkt_type = OL_TX_FRM_NO_FREE; 561 } else { 562 tx_msdu_info.htt.action.tx_comp_req = 563 tx_comp_req; 564 } 565 566 /* If the vdev is in OCB mode, 567 * parse the tx control header. 568 */ 569 if (vdev->opmode == wlan_op_mode_ocb) { 570 if (!parse_ocb_tx_header(msdu, &tx_ctrl)) { 571 /* There was an error parsing 572 * the header.Skip this packet. 573 */ 574 goto MSDU_LOOP_BOTTOM; 575 } 576 } 577 578 txq = ol_tx_classify(vdev, tx_desc, msdu, 579 &tx_msdu_info); 580 581 /* initialize the HW tx descriptor */ 582 htt_tx_desc_init( 583 pdev->htt_pdev, tx_desc->htt_tx_desc, 584 tx_desc->htt_tx_desc_paddr, 585 ol_tx_desc_id(pdev, tx_desc), 586 msdu, 587 &tx_msdu_info.htt, 588 &tx_msdu_info.tso_info, 589 &tx_ctrl, 590 vdev->opmode == wlan_op_mode_ocb); 591 592 if ((!txq) || TX_FILTER_CHECK(&tx_msdu_info)) { 593 /* drop this frame, 594 * but try sending subsequent frames 595 */ 596 /* TXRX_STATS_MSDU_LIST_INCR(pdev, 597 * tx.dropped.no_txq, msdu); 598 */ 599 qdf_atomic_inc(&pdev->tx_queue.rsrc_cnt); 600 ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); 601 if (tx_msdu_info.peer) { 602 /* remove the peer reference 603 * added above 604 */ 605 ol_txrx_peer_release_ref( 606 tx_msdu_info.peer, 607 PEER_DEBUG_ID_OL_INTERNAL); 608 } 609 goto MSDU_LOOP_BOTTOM; 610 } 611 612 if (tx_msdu_info.peer) { 613 /* 614 * If the state is not associated then drop all 615 * the data packets received for that peer 616 */ 617 if (tx_msdu_info.peer->state == 618 OL_TXRX_PEER_STATE_DISC) { 619 qdf_atomic_inc( 620 &pdev->tx_queue.rsrc_cnt); 621 ol_tx_desc_frame_free_nonstd(pdev, 622 tx_desc, 623 1); 624 ol_txrx_peer_release_ref( 625 tx_msdu_info.peer, 626 PEER_DEBUG_ID_OL_INTERNAL); 627 msdu = next; 628 continue; 629 } else if (tx_msdu_info.peer->state != 630 OL_TXRX_PEER_STATE_AUTH) { 631 if (tx_msdu_info.htt.info.ethertype != 632 ETHERTYPE_PAE && 633 tx_msdu_info.htt.info.ethertype 634 != ETHERTYPE_WAI) { 635 qdf_atomic_inc( 636 &pdev->tx_queue. 637 rsrc_cnt); 638 ol_tx_desc_frame_free_nonstd( 639 pdev, 640 tx_desc, 1); 641 ol_txrx_peer_release_ref( 642 tx_msdu_info.peer, 643 PEER_DEBUG_ID_OL_INTERNAL); 644 msdu = next; 645 continue; 646 } 647 } 648 } 649 /* 650 * Initialize the HTT tx desc l2 header offset field. 651 * htt_tx_desc_mpdu_header needs to be called to 652 * make sure, the l2 header size is initialized 653 * correctly to handle cases where TX ENCAP is disabled 654 * or Tx Encap fails to perform Encap 655 */ 656 htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0); 657 658 /* 659 * Note: when the driver is built without support for 660 * SW tx encap,the following macro is a no-op. 661 * When the driver is built with support for SW tx 662 * encap, it performs encap, and if an error is 663 * encountered, jumps to the MSDU_LOOP_BOTTOM label. 664 */ 665 if (ol_tx_encap_wrapper(pdev, vdev, tx_desc, msdu, 666 &tx_msdu_info)) 667 goto MSDU_LOOP_BOTTOM; 668 669 /* 670 * If debug display is enabled, show the meta-data 671 * being downloaded to the target via the 672 * HTT tx descriptor. 673 */ 674 htt_tx_desc_display(tx_desc->htt_tx_desc); 675 676 ol_tx_enqueue(pdev, txq, tx_desc, &tx_msdu_info); 677 if (tx_msdu_info.peer) { 678 OL_TX_PEER_STATS_UPDATE(tx_msdu_info.peer, 679 msdu); 680 /* remove the peer reference added above */ 681 ol_txrx_peer_release_ref 682 (tx_msdu_info.peer, 683 PEER_DEBUG_ID_OL_INTERNAL); 684 } 685 MSDU_LOOP_BOTTOM: 686 msdu = next; 687 } 688 689 if (call_sched) 690 ol_tx_sched(pdev); 691 return NULL; /* all MSDUs were accepted */ 692 } 693 694 #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK 695 696 /** 697 * ol_tx_pdev_reset_driver_del_ack() - reset driver delayed ack enabled flag 698 * @soc_hdl: soc handle 699 * @pdev_id: datapath pdev identifier 700 * 701 * Return: none 702 */ 703 void 704 ol_tx_pdev_reset_driver_del_ack(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 705 { 706 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 707 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id); 708 struct ol_txrx_vdev_t *vdev; 709 710 if (!pdev) 711 return; 712 713 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 714 vdev->driver_del_ack_enabled = false; 715 716 dp_debug("vdev_id %d driver_del_ack_enabled %d", 717 vdev->vdev_id, vdev->driver_del_ack_enabled); 718 } 719 } 720 721 /** 722 * ol_tx_vdev_set_driver_del_ack_enable() - set driver delayed ack enabled flag 723 * @soc_hdl: datapath soc handle 724 * @vdev_id: vdev id 725 * @rx_packets: number of rx packets 726 * @time_in_ms: time in ms 727 * @high_th: high threshold 728 * @low_th: low threshold 729 * 730 * Return: none 731 */ 732 void 733 ol_tx_vdev_set_driver_del_ack_enable(struct cdp_soc_t *soc_hdl, 734 uint8_t vdev_id, 735 unsigned long rx_packets, 736 uint32_t time_in_ms, 737 uint32_t high_th, 738 uint32_t low_th) 739 { 740 struct ol_txrx_vdev_t *vdev = 741 (struct ol_txrx_vdev_t *) 742 ol_txrx_get_vdev_from_vdev_id(vdev_id); 743 bool old_driver_del_ack_enabled; 744 745 if ((!vdev) || (low_th > high_th)) 746 return; 747 748 old_driver_del_ack_enabled = vdev->driver_del_ack_enabled; 749 if (rx_packets > high_th) 750 vdev->driver_del_ack_enabled = true; 751 else if (rx_packets < low_th) 752 vdev->driver_del_ack_enabled = false; 753 754 if (old_driver_del_ack_enabled != vdev->driver_del_ack_enabled) { 755 dp_debug("vdev_id %d driver_del_ack_enabled %d rx_packets %ld time_in_ms %d high_th %d low_th %d", 756 vdev->vdev_id, vdev->driver_del_ack_enabled, 757 rx_packets, time_in_ms, high_th, low_th); 758 } 759 } 760 761 /** 762 * ol_tx_hl_send_all_tcp_ack() - send all queued tcp ack packets 763 * @vdev: vdev handle 764 * 765 * Return: none 766 */ 767 void ol_tx_hl_send_all_tcp_ack(struct ol_txrx_vdev_t *vdev) 768 { 769 int i; 770 struct tcp_stream_node *tcp_node_list; 771 struct tcp_stream_node *temp; 772 struct ol_txrx_pdev_t *pdev = vdev->pdev; 773 774 for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) { 775 tcp_node_list = NULL; 776 qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock); 777 if (vdev->tcp_ack_hash.node[i].no_of_entries) 778 tcp_node_list = vdev->tcp_ack_hash.node[i].head; 779 780 vdev->tcp_ack_hash.node[i].no_of_entries = 0; 781 vdev->tcp_ack_hash.node[i].head = NULL; 782 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock); 783 784 /* Send all packets */ 785 while (tcp_node_list) { 786 int tx_comp_req = pdev->cfg.default_tx_comp_req || 787 pdev->cfg.request_tx_comp; 788 qdf_nbuf_t msdu_list; 789 790 temp = tcp_node_list; 791 tcp_node_list = temp->next; 792 793 msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 794 temp->head, 795 tx_comp_req, false); 796 if (msdu_list) 797 qdf_nbuf_tx_free(msdu_list, 1/*error*/); 798 ol_txrx_vdev_free_tcp_node(vdev, temp); 799 } 800 } 801 ol_tx_sched(vdev->pdev); 802 } 803 804 /** 805 * tcp_del_ack_tasklet() - tasklet function to send ack packets 806 * @data: vdev handle 807 * 808 * Return: none 809 */ 810 void tcp_del_ack_tasklet(void *data) 811 { 812 struct ol_txrx_vdev_t *vdev = data; 813 814 ol_tx_hl_send_all_tcp_ack(vdev); 815 } 816 817 /** 818 * ol_tx_get_stream_id() - get stream_id from packet info 819 * @info: packet info 820 * 821 * Return: stream_id 822 */ 823 uint16_t ol_tx_get_stream_id(struct packet_info *info) 824 { 825 return ((info->dst_port + info->dst_ip + info->src_port + info->src_ip) 826 & (OL_TX_HL_DEL_ACK_HASH_SIZE - 1)); 827 } 828 829 /** 830 * ol_tx_is_tcp_ack() - check whether the packet is tcp ack frame 831 * @msdu: packet 832 * 833 * Return: true if the packet is tcp ack frame 834 */ 835 static bool 836 ol_tx_is_tcp_ack(qdf_nbuf_t msdu) 837 { 838 uint16_t ether_type; 839 uint8_t protocol; 840 uint8_t flag, ip_header_len, tcp_header_len; 841 uint32_t seg_len; 842 uint8_t *skb_data; 843 uint32_t skb_len; 844 bool tcp_acked = false; 845 uint32_t tcp_header_off; 846 847 qdf_nbuf_peek_header(msdu, &skb_data, &skb_len); 848 if (skb_len < (QDF_NBUF_TRAC_IPV4_OFFSET + 849 QDF_NBUF_TRAC_IPV4_HEADER_SIZE + 850 QDF_NBUF_TRAC_TCP_FLAGS_OFFSET)) 851 goto exit; 852 853 ether_type = (uint16_t)(*(uint16_t *) 854 (skb_data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET)); 855 protocol = (uint16_t)(*(uint16_t *) 856 (skb_data + QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET)); 857 858 if ((QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE) == ether_type) && 859 (protocol == QDF_NBUF_TRAC_TCP_TYPE)) { 860 ip_header_len = ((uint8_t)(*(uint8_t *) 861 (skb_data + QDF_NBUF_TRAC_IPV4_OFFSET)) & 862 QDF_NBUF_TRAC_IPV4_HEADER_MASK) << 2; 863 tcp_header_off = QDF_NBUF_TRAC_IPV4_OFFSET + ip_header_len; 864 865 tcp_header_len = ((uint8_t)(*(uint8_t *) 866 (skb_data + tcp_header_off + 867 QDF_NBUF_TRAC_TCP_HEADER_LEN_OFFSET))) >> 2; 868 seg_len = skb_len - tcp_header_len - tcp_header_off; 869 flag = (uint8_t)(*(uint8_t *) 870 (skb_data + tcp_header_off + 871 QDF_NBUF_TRAC_TCP_FLAGS_OFFSET)); 872 873 if ((flag == QDF_NBUF_TRAC_TCP_ACK_MASK) && (seg_len == 0)) 874 tcp_acked = true; 875 } 876 877 exit: 878 879 return tcp_acked; 880 } 881 882 /** 883 * ol_tx_get_packet_info() - update packet info for passed msdu 884 * @msdu: packet 885 * @info: packet info 886 * 887 * Return: none 888 */ 889 void ol_tx_get_packet_info(qdf_nbuf_t msdu, struct packet_info *info) 890 { 891 uint16_t ether_type; 892 uint8_t protocol; 893 uint8_t flag, ip_header_len, tcp_header_len; 894 uint32_t seg_len; 895 uint8_t *skb_data; 896 uint32_t skb_len; 897 uint32_t tcp_header_off; 898 899 info->type = NO_TCP_PKT; 900 901 qdf_nbuf_peek_header(msdu, &skb_data, &skb_len); 902 if (skb_len < (QDF_NBUF_TRAC_IPV4_OFFSET + 903 QDF_NBUF_TRAC_IPV4_HEADER_SIZE + 904 QDF_NBUF_TRAC_TCP_FLAGS_OFFSET)) 905 return; 906 907 ether_type = (uint16_t)(*(uint16_t *) 908 (skb_data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET)); 909 protocol = (uint16_t)(*(uint16_t *) 910 (skb_data + QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET)); 911 912 if ((QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE) == ether_type) && 913 (protocol == QDF_NBUF_TRAC_TCP_TYPE)) { 914 ip_header_len = ((uint8_t)(*(uint8_t *) 915 (skb_data + QDF_NBUF_TRAC_IPV4_OFFSET)) & 916 QDF_NBUF_TRAC_IPV4_HEADER_MASK) << 2; 917 tcp_header_off = QDF_NBUF_TRAC_IPV4_OFFSET + ip_header_len; 918 919 tcp_header_len = ((uint8_t)(*(uint8_t *) 920 (skb_data + tcp_header_off + 921 QDF_NBUF_TRAC_TCP_HEADER_LEN_OFFSET))) >> 2; 922 seg_len = skb_len - tcp_header_len - tcp_header_off; 923 flag = (uint8_t)(*(uint8_t *) 924 (skb_data + tcp_header_off + 925 QDF_NBUF_TRAC_TCP_FLAGS_OFFSET)); 926 927 info->src_ip = QDF_SWAP_U32((uint32_t)(*(uint32_t *) 928 (skb_data + QDF_NBUF_TRAC_IPV4_SRC_ADDR_OFFSET))); 929 info->dst_ip = QDF_SWAP_U32((uint32_t)(*(uint32_t *) 930 (skb_data + QDF_NBUF_TRAC_IPV4_DEST_ADDR_OFFSET))); 931 info->src_port = QDF_SWAP_U16((uint16_t)(*(uint16_t *) 932 (skb_data + tcp_header_off + 933 QDF_NBUF_TRAC_TCP_SPORT_OFFSET))); 934 info->dst_port = QDF_SWAP_U16((uint16_t)(*(uint16_t *) 935 (skb_data + tcp_header_off + 936 QDF_NBUF_TRAC_TCP_DPORT_OFFSET))); 937 info->stream_id = ol_tx_get_stream_id(info); 938 939 if ((flag == QDF_NBUF_TRAC_TCP_ACK_MASK) && (seg_len == 0)) { 940 info->type = TCP_PKT_ACK; 941 info->ack_number = (uint32_t)(*(uint32_t *) 942 (skb_data + tcp_header_off + 943 QDF_NBUF_TRAC_TCP_ACK_OFFSET)); 944 info->ack_number = QDF_SWAP_U32(info->ack_number); 945 } else { 946 info->type = TCP_PKT_NO_ACK; 947 } 948 } 949 } 950 951 /** 952 * ol_tx_hl_find_and_send_tcp_stream() - find and send tcp stream for passed 953 * stream info 954 * @vdev: vdev handle 955 * @info: packet info 956 * 957 * Return: none 958 */ 959 void ol_tx_hl_find_and_send_tcp_stream(struct ol_txrx_vdev_t *vdev, 960 struct packet_info *info) 961 { 962 uint8_t no_of_entries; 963 struct tcp_stream_node *node_to_be_remove = NULL; 964 struct ol_txrx_pdev_t *pdev = vdev->pdev; 965 966 /* remove tcp node from hash */ 967 qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[info->stream_id]. 968 hash_node_lock); 969 970 no_of_entries = vdev->tcp_ack_hash.node[info->stream_id]. 971 no_of_entries; 972 if (no_of_entries > 1) { 973 /* collision case */ 974 struct tcp_stream_node *head = 975 vdev->tcp_ack_hash.node[info->stream_id].head; 976 struct tcp_stream_node *temp; 977 978 if ((head->dst_ip == info->dst_ip) && 979 (head->src_ip == info->src_ip) && 980 (head->src_port == info->src_port) && 981 (head->dst_port == info->dst_port)) { 982 node_to_be_remove = head; 983 vdev->tcp_ack_hash.node[info->stream_id].head = 984 head->next; 985 vdev->tcp_ack_hash.node[info->stream_id]. 986 no_of_entries--; 987 } else { 988 temp = head; 989 while (temp->next) { 990 if ((temp->next->dst_ip == info->dst_ip) && 991 (temp->next->src_ip == info->src_ip) && 992 (temp->next->src_port == info->src_port) && 993 (temp->next->dst_port == info->dst_port)) { 994 node_to_be_remove = temp->next; 995 temp->next = temp->next->next; 996 vdev->tcp_ack_hash. 997 node[info->stream_id]. 998 no_of_entries--; 999 break; 1000 } 1001 temp = temp->next; 1002 } 1003 } 1004 } else if (no_of_entries == 1) { 1005 /* Only one tcp_node */ 1006 node_to_be_remove = 1007 vdev->tcp_ack_hash.node[info->stream_id].head; 1008 vdev->tcp_ack_hash.node[info->stream_id].head = NULL; 1009 vdev->tcp_ack_hash.node[info->stream_id].no_of_entries = 0; 1010 } 1011 qdf_spin_unlock_bh(&vdev->tcp_ack_hash. 1012 node[info->stream_id].hash_node_lock); 1013 1014 /* send packets */ 1015 if (node_to_be_remove) { 1016 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1017 pdev->cfg.request_tx_comp; 1018 qdf_nbuf_t msdu_list; 1019 1020 msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 1021 node_to_be_remove->head, 1022 tx_comp_req, true); 1023 if (msdu_list) 1024 qdf_nbuf_tx_free(msdu_list, 1/*error*/); 1025 ol_txrx_vdev_free_tcp_node(vdev, node_to_be_remove); 1026 } 1027 } 1028 1029 static struct tcp_stream_node * 1030 ol_tx_hl_rep_tcp_ack(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu, 1031 struct packet_info *info, bool *is_found, 1032 bool *start_timer) 1033 { 1034 struct tcp_stream_node *node_to_be_remove = NULL; 1035 struct tcp_stream_node *head = 1036 vdev->tcp_ack_hash.node[info->stream_id].head; 1037 struct tcp_stream_node *temp; 1038 1039 if ((head->dst_ip == info->dst_ip) && 1040 (head->src_ip == info->src_ip) && 1041 (head->src_port == info->src_port) && 1042 (head->dst_port == info->dst_port)) { 1043 *is_found = true; 1044 if ((head->ack_number < info->ack_number) && 1045 (head->no_of_ack_replaced < 1046 ol_cfg_get_del_ack_count_value(vdev->pdev->ctrl_pdev))) { 1047 /* replace ack packet */ 1048 qdf_nbuf_tx_free(head->head, 1); 1049 head->head = msdu; 1050 head->ack_number = info->ack_number; 1051 head->no_of_ack_replaced++; 1052 *start_timer = true; 1053 1054 vdev->no_of_tcpack_replaced++; 1055 1056 if (head->no_of_ack_replaced == 1057 ol_cfg_get_del_ack_count_value( 1058 vdev->pdev->ctrl_pdev)) { 1059 node_to_be_remove = head; 1060 vdev->tcp_ack_hash.node[info->stream_id].head = 1061 head->next; 1062 vdev->tcp_ack_hash.node[info->stream_id]. 1063 no_of_entries--; 1064 } 1065 } else { 1066 /* append and send packets */ 1067 head->head->next = msdu; 1068 node_to_be_remove = head; 1069 vdev->tcp_ack_hash.node[info->stream_id].head = 1070 head->next; 1071 vdev->tcp_ack_hash.node[info->stream_id]. 1072 no_of_entries--; 1073 } 1074 } else { 1075 temp = head; 1076 while (temp->next) { 1077 if ((temp->next->dst_ip == info->dst_ip) && 1078 (temp->next->src_ip == info->src_ip) && 1079 (temp->next->src_port == info->src_port) && 1080 (temp->next->dst_port == info->dst_port)) { 1081 *is_found = true; 1082 if ((temp->next->ack_number < 1083 info->ack_number) && 1084 (temp->next->no_of_ack_replaced < 1085 ol_cfg_get_del_ack_count_value( 1086 vdev->pdev->ctrl_pdev))) { 1087 /* replace ack packet */ 1088 qdf_nbuf_tx_free(temp->next->head, 1); 1089 temp->next->head = msdu; 1090 temp->next->ack_number = 1091 info->ack_number; 1092 temp->next->no_of_ack_replaced++; 1093 *start_timer = true; 1094 1095 vdev->no_of_tcpack_replaced++; 1096 1097 if (temp->next->no_of_ack_replaced == 1098 ol_cfg_get_del_ack_count_value( 1099 vdev->pdev->ctrl_pdev)) { 1100 node_to_be_remove = temp->next; 1101 temp->next = temp->next->next; 1102 vdev->tcp_ack_hash. 1103 node[info->stream_id]. 1104 no_of_entries--; 1105 } 1106 } else { 1107 /* append and send packets */ 1108 temp->next->head->next = msdu; 1109 node_to_be_remove = temp->next; 1110 temp->next = temp->next->next; 1111 vdev->tcp_ack_hash. 1112 node[info->stream_id]. 1113 no_of_entries--; 1114 } 1115 break; 1116 } 1117 temp = temp->next; 1118 } 1119 } 1120 return node_to_be_remove; 1121 } 1122 1123 /** 1124 * ol_tx_hl_find_and_replace_tcp_ack() - find and replace tcp ack packet for 1125 * passed packet info 1126 * @vdev: vdev handle 1127 * @msdu: packet 1128 * @info: packet info 1129 * 1130 * Return: none 1131 */ 1132 void ol_tx_hl_find_and_replace_tcp_ack(struct ol_txrx_vdev_t *vdev, 1133 qdf_nbuf_t msdu, 1134 struct packet_info *info) 1135 { 1136 uint8_t no_of_entries; 1137 struct tcp_stream_node *node_to_be_remove = NULL; 1138 bool is_found = false, start_timer = false; 1139 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1140 1141 /* replace ack if required or send packets */ 1142 qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[info->stream_id]. 1143 hash_node_lock); 1144 1145 no_of_entries = vdev->tcp_ack_hash.node[info->stream_id].no_of_entries; 1146 if (no_of_entries > 0) { 1147 node_to_be_remove = ol_tx_hl_rep_tcp_ack(vdev, msdu, info, 1148 &is_found, 1149 &start_timer); 1150 } 1151 1152 if (no_of_entries == 0 || !is_found) { 1153 /* Alloc new tcp node */ 1154 struct tcp_stream_node *new_node; 1155 1156 new_node = ol_txrx_vdev_alloc_tcp_node(vdev); 1157 if (!new_node) { 1158 qdf_spin_unlock_bh(&vdev->tcp_ack_hash. 1159 node[info->stream_id].hash_node_lock); 1160 dp_alert("Malloc failed"); 1161 return; 1162 } 1163 new_node->stream_id = info->stream_id; 1164 new_node->dst_ip = info->dst_ip; 1165 new_node->src_ip = info->src_ip; 1166 new_node->dst_port = info->dst_port; 1167 new_node->src_port = info->src_port; 1168 new_node->ack_number = info->ack_number; 1169 new_node->head = msdu; 1170 new_node->next = NULL; 1171 new_node->no_of_ack_replaced = 0; 1172 1173 start_timer = true; 1174 /* insert new_node */ 1175 if (!vdev->tcp_ack_hash.node[info->stream_id].head) { 1176 vdev->tcp_ack_hash.node[info->stream_id].head = 1177 new_node; 1178 vdev->tcp_ack_hash.node[info->stream_id]. 1179 no_of_entries = 1; 1180 } else { 1181 struct tcp_stream_node *temp = 1182 vdev->tcp_ack_hash.node[info->stream_id].head; 1183 while (temp->next) 1184 temp = temp->next; 1185 1186 temp->next = new_node; 1187 vdev->tcp_ack_hash.node[info->stream_id]. 1188 no_of_entries++; 1189 } 1190 } 1191 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[info->stream_id]. 1192 hash_node_lock); 1193 1194 /* start timer */ 1195 if (start_timer && 1196 (!qdf_atomic_read(&vdev->tcp_ack_hash.is_timer_running))) { 1197 qdf_hrtimer_start(&vdev->tcp_ack_hash.timer, 1198 qdf_ns_to_ktime(( 1199 ol_cfg_get_del_ack_timer_value( 1200 vdev->pdev->ctrl_pdev) * 1201 1000000)), 1202 __QDF_HRTIMER_MODE_REL); 1203 qdf_atomic_set(&vdev->tcp_ack_hash.is_timer_running, 1); 1204 } 1205 1206 /* send packets */ 1207 if (node_to_be_remove) { 1208 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1209 pdev->cfg.request_tx_comp; 1210 qdf_nbuf_t msdu_list = NULL; 1211 1212 msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 1213 node_to_be_remove->head, 1214 tx_comp_req, true); 1215 if (msdu_list) 1216 qdf_nbuf_tx_free(msdu_list, 1/*error*/); 1217 ol_txrx_vdev_free_tcp_node(vdev, node_to_be_remove); 1218 } 1219 } 1220 1221 /** 1222 * ol_tx_hl_vdev_tcp_del_ack_timer() - delayed ack timer function 1223 * @timer: timer handle 1224 * 1225 * Return: enum 1226 */ 1227 enum qdf_hrtimer_restart_status 1228 ol_tx_hl_vdev_tcp_del_ack_timer(qdf_hrtimer_data_t *timer) 1229 { 1230 struct ol_txrx_vdev_t *vdev = qdf_container_of(timer, 1231 struct ol_txrx_vdev_t, 1232 tcp_ack_hash.timer); 1233 enum qdf_hrtimer_restart_status ret = QDF_HRTIMER_NORESTART; 1234 1235 qdf_sched_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq); 1236 qdf_atomic_set(&vdev->tcp_ack_hash.is_timer_running, 0); 1237 return ret; 1238 } 1239 1240 /** 1241 * ol_tx_hl_del_ack_queue_flush_all() - drop all queued packets 1242 * @vdev: vdev handle 1243 * 1244 * Return: none 1245 */ 1246 void ol_tx_hl_del_ack_queue_flush_all(struct ol_txrx_vdev_t *vdev) 1247 { 1248 int i; 1249 struct tcp_stream_node *tcp_node_list; 1250 struct tcp_stream_node *temp; 1251 1252 qdf_hrtimer_cancel(&vdev->tcp_ack_hash.timer); 1253 for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) { 1254 tcp_node_list = NULL; 1255 qdf_spin_lock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock); 1256 1257 if (vdev->tcp_ack_hash.node[i].no_of_entries) 1258 tcp_node_list = vdev->tcp_ack_hash.node[i].head; 1259 1260 vdev->tcp_ack_hash.node[i].no_of_entries = 0; 1261 vdev->tcp_ack_hash.node[i].head = NULL; 1262 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.node[i].hash_node_lock); 1263 1264 /* free all packets */ 1265 while (tcp_node_list) { 1266 temp = tcp_node_list; 1267 tcp_node_list = temp->next; 1268 1269 qdf_nbuf_tx_free(temp->head, 1/*error*/); 1270 ol_txrx_vdev_free_tcp_node(vdev, temp); 1271 } 1272 } 1273 ol_txrx_vdev_deinit_tcp_del_ack(vdev); 1274 } 1275 1276 /** 1277 * ol_txrx_vdev_init_tcp_del_ack() - initialize tcp delayed ack structure 1278 * @vdev: vdev handle 1279 * 1280 * Return: none 1281 */ 1282 void ol_txrx_vdev_init_tcp_del_ack(struct ol_txrx_vdev_t *vdev) 1283 { 1284 int i; 1285 1286 vdev->driver_del_ack_enabled = false; 1287 1288 dp_debug("vdev-id=%u, driver_del_ack_enabled=%d", 1289 vdev->vdev_id, 1290 vdev->driver_del_ack_enabled); 1291 1292 vdev->no_of_tcpack = 0; 1293 vdev->no_of_tcpack_replaced = 0; 1294 1295 qdf_hrtimer_init(&vdev->tcp_ack_hash.timer, 1296 ol_tx_hl_vdev_tcp_del_ack_timer, 1297 __QDF_CLOCK_MONOTONIC, 1298 __QDF_HRTIMER_MODE_REL, 1299 QDF_CONTEXT_HARDWARE 1300 ); 1301 qdf_create_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq, 1302 tcp_del_ack_tasklet, 1303 vdev); 1304 qdf_atomic_init(&vdev->tcp_ack_hash.is_timer_running); 1305 qdf_atomic_init(&vdev->tcp_ack_hash.tcp_node_in_use_count); 1306 qdf_spinlock_create(&vdev->tcp_ack_hash.tcp_free_list_lock); 1307 vdev->tcp_ack_hash.tcp_free_list = NULL; 1308 for (i = 0; i < OL_TX_HL_DEL_ACK_HASH_SIZE; i++) { 1309 qdf_spinlock_create(&vdev->tcp_ack_hash.node[i].hash_node_lock); 1310 vdev->tcp_ack_hash.node[i].no_of_entries = 0; 1311 vdev->tcp_ack_hash.node[i].head = NULL; 1312 } 1313 } 1314 1315 /** 1316 * ol_txrx_vdev_deinit_tcp_del_ack() - deinitialize tcp delayed ack structure 1317 * @vdev: vdev handle 1318 * 1319 * Return: none 1320 */ 1321 void ol_txrx_vdev_deinit_tcp_del_ack(struct ol_txrx_vdev_t *vdev) 1322 { 1323 struct tcp_stream_node *temp; 1324 1325 qdf_destroy_bh(&vdev->tcp_ack_hash.tcp_del_ack_tq); 1326 1327 qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1328 while (vdev->tcp_ack_hash.tcp_free_list) { 1329 temp = vdev->tcp_ack_hash.tcp_free_list; 1330 vdev->tcp_ack_hash.tcp_free_list = temp->next; 1331 qdf_mem_free(temp); 1332 } 1333 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1334 } 1335 1336 /** 1337 * ol_txrx_vdev_free_tcp_node() - add tcp node in free list 1338 * @vdev: vdev handle 1339 * @node: tcp stream node 1340 * 1341 * Return: none 1342 */ 1343 void ol_txrx_vdev_free_tcp_node(struct ol_txrx_vdev_t *vdev, 1344 struct tcp_stream_node *node) 1345 { 1346 qdf_atomic_dec(&vdev->tcp_ack_hash.tcp_node_in_use_count); 1347 1348 qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1349 if (vdev->tcp_ack_hash.tcp_free_list) { 1350 node->next = vdev->tcp_ack_hash.tcp_free_list; 1351 vdev->tcp_ack_hash.tcp_free_list = node; 1352 } else { 1353 vdev->tcp_ack_hash.tcp_free_list = node; 1354 node->next = NULL; 1355 } 1356 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1357 } 1358 1359 /** 1360 * ol_txrx_vdev_alloc_tcp_node() - allocate tcp node 1361 * @vdev: vdev handle 1362 * 1363 * Return: tcp stream node 1364 */ 1365 struct tcp_stream_node *ol_txrx_vdev_alloc_tcp_node(struct ol_txrx_vdev_t *vdev) 1366 { 1367 struct tcp_stream_node *node = NULL; 1368 1369 qdf_spin_lock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1370 if (vdev->tcp_ack_hash.tcp_free_list) { 1371 node = vdev->tcp_ack_hash.tcp_free_list; 1372 vdev->tcp_ack_hash.tcp_free_list = node->next; 1373 } 1374 qdf_spin_unlock_bh(&vdev->tcp_ack_hash.tcp_free_list_lock); 1375 1376 if (!node) { 1377 node = qdf_mem_malloc(sizeof(struct ol_txrx_vdev_t)); 1378 if (!node) 1379 return NULL; 1380 } 1381 qdf_atomic_inc(&vdev->tcp_ack_hash.tcp_node_in_use_count); 1382 return node; 1383 } 1384 1385 qdf_nbuf_t 1386 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) 1387 { 1388 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1389 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1390 pdev->cfg.request_tx_comp; 1391 struct packet_info pkt_info; 1392 qdf_nbuf_t temp; 1393 1394 if (ol_tx_is_tcp_ack(msdu_list)) 1395 vdev->no_of_tcpack++; 1396 1397 /* check Enable through ini */ 1398 if (!ol_cfg_get_del_ack_enable_value(vdev->pdev->ctrl_pdev) || 1399 (!vdev->driver_del_ack_enabled)) { 1400 if (qdf_atomic_read(&vdev->tcp_ack_hash.tcp_node_in_use_count)) 1401 ol_tx_hl_send_all_tcp_ack(vdev); 1402 1403 return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list, 1404 tx_comp_req, true); 1405 } 1406 1407 ol_tx_get_packet_info(msdu_list, &pkt_info); 1408 1409 if (pkt_info.type == TCP_PKT_NO_ACK) { 1410 ol_tx_hl_find_and_send_tcp_stream(vdev, &pkt_info); 1411 temp = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list, 1412 tx_comp_req, true); 1413 return temp; 1414 } 1415 1416 if (pkt_info.type == TCP_PKT_ACK) { 1417 ol_tx_hl_find_and_replace_tcp_ack(vdev, msdu_list, &pkt_info); 1418 return NULL; 1419 } 1420 1421 temp = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list, 1422 tx_comp_req, true); 1423 return temp; 1424 } 1425 #else 1426 1427 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE 1428 void 1429 ol_tx_pdev_reset_bundle_require(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) 1430 { 1431 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1432 struct ol_txrx_pdev_t *pdev = ol_txrx_get_pdev_from_pdev_id(soc, 1433 pdev_id); 1434 struct ol_txrx_vdev_t *vdev; 1435 1436 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 1437 vdev->bundling_required = false; 1438 ol_txrx_info("vdev_id %d bundle_require %d", 1439 vdev->vdev_id, vdev->bundling_required); 1440 } 1441 } 1442 1443 void 1444 ol_tx_vdev_set_bundle_require(uint8_t vdev_id, unsigned long tx_bytes, 1445 uint32_t time_in_ms, uint32_t high_th, 1446 uint32_t low_th) 1447 { 1448 struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *) 1449 ol_txrx_get_vdev_from_vdev_id(vdev_id); 1450 bool old_bundle_required; 1451 1452 if ((!vdev) || (low_th > high_th)) 1453 return; 1454 1455 old_bundle_required = vdev->bundling_required; 1456 if (tx_bytes > ((high_th * time_in_ms * 1500) / 1000)) 1457 vdev->bundling_required = true; 1458 else if (tx_bytes < ((low_th * time_in_ms * 1500) / 1000)) 1459 vdev->bundling_required = false; 1460 1461 if (old_bundle_required != vdev->bundling_required) 1462 ol_txrx_info("vdev_id %d bundle_require %d tx_bytes %ld time_in_ms %d high_th %d low_th %d", 1463 vdev->vdev_id, vdev->bundling_required, tx_bytes, 1464 time_in_ms, high_th, low_th); 1465 } 1466 1467 /** 1468 * ol_tx_hl_queue_flush_all() - drop all packets in vdev bundle queue 1469 * @vdev: vdev handle 1470 * 1471 * Return: none 1472 */ 1473 void 1474 ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev) 1475 { 1476 qdf_spin_lock_bh(&vdev->bundle_queue.mutex); 1477 if (vdev->bundle_queue.txq.depth != 0) { 1478 qdf_timer_stop(&vdev->bundle_queue.timer); 1479 vdev->pdev->total_bundle_queue_length -= 1480 vdev->bundle_queue.txq.depth; 1481 qdf_nbuf_tx_free(vdev->bundle_queue.txq.head, 1/*error*/); 1482 vdev->bundle_queue.txq.depth = 0; 1483 vdev->bundle_queue.txq.head = NULL; 1484 vdev->bundle_queue.txq.tail = NULL; 1485 } 1486 qdf_spin_unlock_bh(&vdev->bundle_queue.mutex); 1487 } 1488 1489 /** 1490 * ol_tx_hl_vdev_queue_append() - append pkt in tx queue 1491 * @vdev: vdev handle 1492 * @msdu_list: msdu list 1493 * 1494 * Return: none 1495 */ 1496 static void 1497 ol_tx_hl_vdev_queue_append(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu_list) 1498 { 1499 qdf_spin_lock_bh(&vdev->bundle_queue.mutex); 1500 1501 if (!vdev->bundle_queue.txq.head) { 1502 qdf_timer_start( 1503 &vdev->bundle_queue.timer, 1504 ol_cfg_get_bundle_timer_value(vdev->pdev->ctrl_pdev)); 1505 vdev->bundle_queue.txq.head = msdu_list; 1506 vdev->bundle_queue.txq.tail = msdu_list; 1507 } else { 1508 qdf_nbuf_set_next(vdev->bundle_queue.txq.tail, msdu_list); 1509 } 1510 1511 while (qdf_nbuf_next(msdu_list)) { 1512 vdev->bundle_queue.txq.depth++; 1513 vdev->pdev->total_bundle_queue_length++; 1514 msdu_list = qdf_nbuf_next(msdu_list); 1515 } 1516 1517 vdev->bundle_queue.txq.depth++; 1518 vdev->pdev->total_bundle_queue_length++; 1519 vdev->bundle_queue.txq.tail = msdu_list; 1520 qdf_spin_unlock_bh(&vdev->bundle_queue.mutex); 1521 } 1522 1523 /** 1524 * ol_tx_hl_vdev_queue_send_all() - send all packets in vdev bundle queue 1525 * @vdev: vdev handle 1526 * @call_sched: invoke scheduler 1527 * 1528 * Return: NULL for success 1529 */ 1530 static qdf_nbuf_t 1531 ol_tx_hl_vdev_queue_send_all(struct ol_txrx_vdev_t *vdev, bool call_sched, 1532 bool in_timer_context) 1533 { 1534 qdf_nbuf_t msdu_list = NULL; 1535 qdf_nbuf_t skb_list_head, skb_list_tail; 1536 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1537 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1538 pdev->cfg.request_tx_comp; 1539 int pkt_to_sent; 1540 1541 qdf_spin_lock_bh(&vdev->bundle_queue.mutex); 1542 1543 if (!vdev->bundle_queue.txq.depth) { 1544 qdf_spin_unlock_bh(&vdev->bundle_queue.mutex); 1545 return msdu_list; 1546 } 1547 1548 if (likely((qdf_atomic_read(&vdev->tx_desc_count) + 1549 vdev->bundle_queue.txq.depth) < 1550 vdev->queue_stop_th)) { 1551 qdf_timer_stop(&vdev->bundle_queue.timer); 1552 vdev->pdev->total_bundle_queue_length -= 1553 vdev->bundle_queue.txq.depth; 1554 msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 1555 vdev->bundle_queue.txq.head, 1556 tx_comp_req, call_sched); 1557 vdev->bundle_queue.txq.depth = 0; 1558 vdev->bundle_queue.txq.head = NULL; 1559 vdev->bundle_queue.txq.tail = NULL; 1560 } else { 1561 pkt_to_sent = vdev->queue_stop_th - 1562 qdf_atomic_read(&vdev->tx_desc_count); 1563 1564 if (pkt_to_sent) { 1565 skb_list_head = vdev->bundle_queue.txq.head; 1566 1567 while (pkt_to_sent) { 1568 skb_list_tail = 1569 vdev->bundle_queue.txq.head; 1570 vdev->bundle_queue.txq.head = 1571 qdf_nbuf_next(vdev->bundle_queue.txq.head); 1572 vdev->pdev->total_bundle_queue_length--; 1573 vdev->bundle_queue.txq.depth--; 1574 pkt_to_sent--; 1575 if (!vdev->bundle_queue.txq.head) { 1576 qdf_timer_stop( 1577 &vdev->bundle_queue.timer); 1578 break; 1579 } 1580 } 1581 1582 qdf_nbuf_set_next(skb_list_tail, NULL); 1583 msdu_list = ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 1584 skb_list_head, tx_comp_req, 1585 call_sched); 1586 } 1587 1588 if (in_timer_context && vdev->bundle_queue.txq.head) { 1589 qdf_timer_start( 1590 &vdev->bundle_queue.timer, 1591 ol_cfg_get_bundle_timer_value( 1592 vdev->pdev->ctrl_pdev)); 1593 } 1594 } 1595 qdf_spin_unlock_bh(&vdev->bundle_queue.mutex); 1596 1597 return msdu_list; 1598 } 1599 1600 /** 1601 * ol_tx_hl_pdev_queue_send_all() - send all packets from all vdev bundle queue 1602 * @pdev: pdev handle 1603 * 1604 * Return: NULL for success 1605 */ 1606 qdf_nbuf_t 1607 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev) 1608 { 1609 struct ol_txrx_vdev_t *vdev; 1610 qdf_nbuf_t msdu_list; 1611 1612 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 1613 msdu_list = ol_tx_hl_vdev_queue_send_all(vdev, false, false); 1614 if (msdu_list) 1615 qdf_nbuf_tx_free(msdu_list, 1/*error*/); 1616 } 1617 ol_tx_sched(pdev); 1618 return NULL; /* all msdus were accepted */ 1619 } 1620 1621 /** 1622 * ol_tx_hl_vdev_bundle_timer() - bundle timer function 1623 * @vdev: vdev handle 1624 * 1625 * Return: none 1626 */ 1627 void 1628 ol_tx_hl_vdev_bundle_timer(void *ctx) 1629 { 1630 qdf_nbuf_t msdu_list; 1631 struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)ctx; 1632 1633 vdev->no_of_bundle_sent_in_timer++; 1634 msdu_list = ol_tx_hl_vdev_queue_send_all(vdev, true, true); 1635 if (msdu_list) 1636 qdf_nbuf_tx_free(msdu_list, 1/*error*/); 1637 } 1638 1639 qdf_nbuf_t 1640 ol_tx_hl(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu_list) 1641 { 1642 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1643 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1644 pdev->cfg.request_tx_comp; 1645 1646 /* No queuing for high priority packets */ 1647 if (ol_tx_desc_is_high_prio(msdu_list)) { 1648 vdev->no_of_pkt_not_added_in_queue++; 1649 return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list, 1650 tx_comp_req, true); 1651 } else if (vdev->bundling_required && 1652 (ol_cfg_get_bundle_size(vdev->pdev->ctrl_pdev) > 1)) { 1653 ol_tx_hl_vdev_queue_append(vdev, msdu_list); 1654 1655 if (pdev->total_bundle_queue_length >= 1656 ol_cfg_get_bundle_size(vdev->pdev->ctrl_pdev)) { 1657 vdev->no_of_bundle_sent_after_threshold++; 1658 return ol_tx_hl_pdev_queue_send_all(pdev); 1659 } 1660 } else { 1661 if (vdev->bundle_queue.txq.depth != 0) { 1662 ol_tx_hl_vdev_queue_append(vdev, msdu_list); 1663 return ol_tx_hl_vdev_queue_send_all(vdev, true, false); 1664 } else { 1665 vdev->no_of_pkt_not_added_in_queue++; 1666 return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, msdu_list, 1667 tx_comp_req, true); 1668 } 1669 } 1670 1671 return NULL; /* all msdus were accepted */ 1672 } 1673 1674 #else 1675 1676 qdf_nbuf_t 1677 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) 1678 { 1679 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1680 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1681 pdev->cfg.request_tx_comp; 1682 1683 return ol_tx_hl_base(vdev, OL_TX_SPEC_STD, 1684 msdu_list, tx_comp_req, true); 1685 } 1686 #endif 1687 #endif 1688 1689 qdf_nbuf_t ol_tx_non_std_hl(struct ol_txrx_vdev_t *vdev, 1690 enum ol_tx_spec tx_spec, 1691 qdf_nbuf_t msdu_list) 1692 { 1693 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1694 int tx_comp_req = pdev->cfg.default_tx_comp_req || 1695 pdev->cfg.request_tx_comp; 1696 1697 if (!tx_comp_req) { 1698 if ((tx_spec == OL_TX_SPEC_NO_FREE) && 1699 (pdev->tx_data_callback.func)) 1700 tx_comp_req = 1; 1701 } 1702 return ol_tx_hl_base(vdev, tx_spec, msdu_list, tx_comp_req, true); 1703 } 1704 1705 #ifdef FEATURE_WLAN_TDLS 1706 void ol_txrx_copy_mac_addr_raw(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 1707 uint8_t *bss_addr) 1708 { 1709 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1710 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1711 vdev_id); 1712 1713 if (!vdev) 1714 return; 1715 1716 qdf_spin_lock_bh(&vdev->pdev->last_real_peer_mutex); 1717 if (bss_addr && vdev->last_real_peer && 1718 !qdf_mem_cmp((u8 *)bss_addr, 1719 vdev->last_real_peer->mac_addr.raw, 1720 QDF_MAC_ADDR_SIZE)) 1721 qdf_mem_copy(vdev->hl_tdls_ap_mac_addr.raw, 1722 vdev->last_real_peer->mac_addr.raw, 1723 QDF_MAC_ADDR_SIZE); 1724 qdf_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex); 1725 } 1726 1727 void 1728 ol_txrx_add_last_real_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, 1729 uint8_t vdev_id) 1730 { 1731 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1732 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id); 1733 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1734 vdev_id); 1735 ol_txrx_peer_handle peer; 1736 1737 if (!pdev || !vdev) 1738 return; 1739 1740 peer = ol_txrx_find_peer_by_addr( 1741 (struct cdp_pdev *)pdev, 1742 vdev->hl_tdls_ap_mac_addr.raw); 1743 1744 qdf_spin_lock_bh(&pdev->last_real_peer_mutex); 1745 if (!vdev->last_real_peer && peer && 1746 (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) { 1747 vdev->last_real_peer = peer; 1748 qdf_mem_zero(vdev->hl_tdls_ap_mac_addr.raw, 1749 QDF_MAC_ADDR_SIZE); 1750 } 1751 qdf_spin_unlock_bh(&pdev->last_real_peer_mutex); 1752 } 1753 1754 bool is_vdev_restore_last_peer(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 1755 uint8_t *peer_mac) 1756 { 1757 struct ol_txrx_peer_t *peer; 1758 struct ol_txrx_pdev_t *pdev; 1759 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1760 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1761 vdev_id); 1762 1763 if (!vdev) 1764 return false; 1765 1766 pdev = vdev->pdev; 1767 peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac); 1768 1769 return vdev->last_real_peer && (vdev->last_real_peer == peer); 1770 } 1771 1772 void ol_txrx_update_last_real_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, 1773 uint8_t vdev_id, bool restore_last_peer) 1774 { 1775 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1776 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id); 1777 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1778 vdev_id); 1779 struct ol_txrx_peer_t *peer; 1780 1781 if (!restore_last_peer || !pdev || !vdev) 1782 return; 1783 1784 peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, 1785 vdev->hl_tdls_ap_mac_addr.raw); 1786 1787 qdf_spin_lock_bh(&pdev->last_real_peer_mutex); 1788 if (!vdev->last_real_peer && peer && 1789 (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) { 1790 vdev->last_real_peer = peer; 1791 qdf_mem_zero(vdev->hl_tdls_ap_mac_addr.raw, 1792 QDF_MAC_ADDR_SIZE); 1793 } 1794 qdf_spin_unlock_bh(&pdev->last_real_peer_mutex); 1795 } 1796 1797 void ol_txrx_set_peer_as_tdls_peer(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 1798 uint8_t *peer_mac, bool val) 1799 { 1800 ol_txrx_peer_handle peer; 1801 struct ol_txrx_pdev_t *pdev; 1802 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1803 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1804 vdev_id); 1805 1806 if (!vdev) 1807 return; 1808 1809 pdev = vdev->pdev; 1810 peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac); 1811 1812 ol_txrx_info_high("peer %pK, peer->ref_cnt %d", 1813 peer, qdf_atomic_read(&peer->ref_cnt)); 1814 1815 /* Mark peer as tdls */ 1816 if (peer) 1817 peer->is_tdls_peer = val; 1818 } 1819 1820 void ol_txrx_set_tdls_offchan_enabled(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 1821 uint8_t *peer_mac, bool val) 1822 { 1823 ol_txrx_peer_handle peer; 1824 struct ol_txrx_pdev_t *pdev; 1825 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 1826 ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc, 1827 vdev_id); 1828 1829 if (!vdev) 1830 return; 1831 1832 pdev = vdev->pdev; 1833 peer = ol_txrx_find_peer_by_addr((struct cdp_pdev *)pdev, peer_mac); 1834 1835 ol_txrx_info_high("peer %pK, peer->ref_cnt %d", 1836 peer, qdf_atomic_read(&peer->ref_cnt)); 1837 1838 /* Set TDLS Offchan operation enable/disable */ 1839 if (peer && peer->is_tdls_peer) 1840 peer->tdls_offchan_enabled = val; 1841 } 1842 #endif 1843 1844 #if defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) 1845 /** 1846 * ol_txrx_pdev_txq_log_init() - initialise pdev txq logs 1847 * @pdev: the physical device object 1848 * 1849 * Return: None 1850 */ 1851 void ol_txrx_pdev_txq_log_init(struct ol_txrx_pdev_t *pdev) 1852 { 1853 qdf_spinlock_create(&pdev->txq_log_spinlock); 1854 pdev->txq_log.size = OL_TXQ_LOG_SIZE; 1855 pdev->txq_log.oldest_record_offset = 0; 1856 pdev->txq_log.offset = 0; 1857 pdev->txq_log.allow_wrap = 1; 1858 pdev->txq_log.wrapped = 0; 1859 } 1860 1861 /** 1862 * ol_txrx_pdev_txq_log_destroy() - remove txq log spinlock for pdev 1863 * @pdev: the physical device object 1864 * 1865 * Return: None 1866 */ 1867 void ol_txrx_pdev_txq_log_destroy(struct ol_txrx_pdev_t *pdev) 1868 { 1869 qdf_spinlock_destroy(&pdev->txq_log_spinlock); 1870 } 1871 #endif 1872 1873 #if defined(DEBUG_HL_LOGGING) 1874 1875 /** 1876 * ol_txrx_pdev_grp_stats_init() - initialise group stat spinlock for pdev 1877 * @pdev: the physical device object 1878 * 1879 * Return: None 1880 */ 1881 void ol_txrx_pdev_grp_stats_init(struct ol_txrx_pdev_t *pdev) 1882 { 1883 qdf_spinlock_create(&pdev->grp_stat_spinlock); 1884 pdev->grp_stats.last_valid_index = -1; 1885 pdev->grp_stats.wrap_around = 0; 1886 } 1887 1888 /** 1889 * ol_txrx_pdev_grp_stat_destroy() - destroy group stat spinlock for pdev 1890 * @pdev: the physical device object 1891 * 1892 * Return: None 1893 */ 1894 void ol_txrx_pdev_grp_stat_destroy(struct ol_txrx_pdev_t *pdev) 1895 { 1896 qdf_spinlock_destroy(&pdev->grp_stat_spinlock); 1897 } 1898 #endif 1899 1900 #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) 1901 1902 /** 1903 * ol_txrx_hl_tdls_flag_reset() - reset tdls flag for vdev 1904 * @soc_hdl: Datapath soc handle 1905 * @vdev_id: id of vdev 1906 * @flag: flag 1907 * 1908 * Return: None 1909 */ 1910 void 1911 ol_txrx_hl_tdls_flag_reset(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 1912 bool flag) 1913 { 1914 struct ol_txrx_vdev_t *vdev = 1915 (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id); 1916 if (!vdev) { 1917 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 1918 "%s: Invalid vdev_id %d", __func__, vdev_id); 1919 return; 1920 } 1921 1922 vdev->hlTdlsFlag = flag; 1923 } 1924 #endif 1925 1926 /** 1927 * ol_txrx_vdev_txqs_init() - initialise vdev tx queues 1928 * @vdev: the virtual device object 1929 * 1930 * Return: None 1931 */ 1932 void ol_txrx_vdev_txqs_init(struct ol_txrx_vdev_t *vdev) 1933 { 1934 uint8_t i; 1935 1936 for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { 1937 TAILQ_INIT(&vdev->txqs[i].head); 1938 vdev->txqs[i].paused_count.total = 0; 1939 vdev->txqs[i].frms = 0; 1940 vdev->txqs[i].bytes = 0; 1941 vdev->txqs[i].ext_tid = OL_TX_NUM_TIDS + i; 1942 vdev->txqs[i].flag = ol_tx_queue_empty; 1943 /* aggregation is not applicable for vdev tx queues */ 1944 vdev->txqs[i].aggr_state = ol_tx_aggr_disabled; 1945 ol_tx_txq_set_group_ptr(&vdev->txqs[i], NULL); 1946 ol_txrx_set_txq_peer(&vdev->txqs[i], NULL); 1947 } 1948 } 1949 1950 /** 1951 * ol_txrx_vdev_tx_queue_free() - free vdev tx queues 1952 * @vdev: the virtual device object 1953 * 1954 * Return: None 1955 */ 1956 void ol_txrx_vdev_tx_queue_free(struct ol_txrx_vdev_t *vdev) 1957 { 1958 struct ol_txrx_pdev_t *pdev = vdev->pdev; 1959 struct ol_tx_frms_queue_t *txq; 1960 int i; 1961 1962 for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { 1963 txq = &vdev->txqs[i]; 1964 ol_tx_queue_free(pdev, txq, (i + OL_TX_NUM_TIDS), false); 1965 } 1966 } 1967 1968 /** 1969 * ol_txrx_peer_txqs_init() - initialise peer tx queues 1970 * @pdev: the physical device object 1971 * @peer: peer object 1972 * 1973 * Return: None 1974 */ 1975 void ol_txrx_peer_txqs_init(struct ol_txrx_pdev_t *pdev, 1976 struct ol_txrx_peer_t *peer) 1977 { 1978 uint8_t i; 1979 struct ol_txrx_vdev_t *vdev = peer->vdev; 1980 1981 qdf_spin_lock_bh(&pdev->tx_queue_spinlock); 1982 for (i = 0; i < OL_TX_NUM_TIDS; i++) { 1983 TAILQ_INIT(&peer->txqs[i].head); 1984 peer->txqs[i].paused_count.total = 0; 1985 peer->txqs[i].frms = 0; 1986 peer->txqs[i].bytes = 0; 1987 peer->txqs[i].ext_tid = i; 1988 peer->txqs[i].flag = ol_tx_queue_empty; 1989 peer->txqs[i].aggr_state = ol_tx_aggr_untried; 1990 ol_tx_set_peer_group_ptr(pdev, peer, vdev->vdev_id, i); 1991 ol_txrx_set_txq_peer(&peer->txqs[i], peer); 1992 } 1993 qdf_spin_unlock_bh(&pdev->tx_queue_spinlock); 1994 1995 /* aggregation is not applicable for mgmt and non-QoS tx queues */ 1996 for (i = OL_TX_NUM_QOS_TIDS; i < OL_TX_NUM_TIDS; i++) 1997 peer->txqs[i].aggr_state = ol_tx_aggr_disabled; 1998 1999 ol_txrx_peer_pause(peer); 2000 } 2001 2002 /** 2003 * ol_txrx_peer_tx_queue_free() - free peer tx queues 2004 * @pdev: the physical device object 2005 * @peer: peer object 2006 * 2007 * Return: None 2008 */ 2009 void ol_txrx_peer_tx_queue_free(struct ol_txrx_pdev_t *pdev, 2010 struct ol_txrx_peer_t *peer) 2011 { 2012 struct ol_tx_frms_queue_t *txq; 2013 uint8_t i; 2014 2015 for (i = 0; i < OL_TX_NUM_TIDS; i++) { 2016 txq = &peer->txqs[i]; 2017 ol_tx_queue_free(pdev, txq, i, true); 2018 } 2019 } 2020 2021 #ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL 2022 2023 /** 2024 * ol_txrx_update_group_credit() - update group credit for tx queue 2025 * @group: for which credit needs to be updated 2026 * @credit: credits 2027 * @absolute: TXQ group absolute 2028 * 2029 * Return: allocated pool size 2030 */ 2031 void ol_txrx_update_group_credit( 2032 struct ol_tx_queue_group_t *group, 2033 int32_t credit, 2034 u_int8_t absolute) 2035 { 2036 if (absolute) 2037 qdf_atomic_set(&group->credit, credit); 2038 else 2039 qdf_atomic_add(credit, &group->credit); 2040 } 2041 2042 /** 2043 * ol_txrx_update_tx_queue_groups() - update vdev tx queue group if 2044 * vdev id mask and ac mask is not matching 2045 * @pdev: the data physical device 2046 * @group_id: TXQ group id 2047 * @credit: TXQ group credit count 2048 * @absolute: TXQ group absolute 2049 * @vdev_id_mask: TXQ vdev group id mask 2050 * @ac_mask: TQX access category mask 2051 * 2052 * Return: None 2053 */ 2054 void ol_txrx_update_tx_queue_groups( 2055 ol_txrx_pdev_handle pdev, 2056 u_int8_t group_id, 2057 int32_t credit, 2058 u_int8_t absolute, 2059 u_int32_t vdev_id_mask, 2060 u_int32_t ac_mask 2061 ) 2062 { 2063 struct ol_tx_queue_group_t *group; 2064 u_int32_t group_vdev_bit_mask, vdev_bit_mask, group_vdev_id_mask; 2065 u_int32_t membership; 2066 struct ol_txrx_vdev_t *vdev; 2067 2068 if (group_id >= OL_TX_MAX_TXQ_GROUPS) { 2069 ol_txrx_warn("invalid group_id=%u, ignore update", group_id); 2070 return; 2071 } 2072 2073 group = &pdev->txq_grps[group_id]; 2074 2075 membership = OL_TXQ_GROUP_MEMBERSHIP_GET(vdev_id_mask, ac_mask); 2076 2077 qdf_spin_lock_bh(&pdev->tx_queue_spinlock); 2078 /* 2079 * if the membership (vdev id mask and ac mask) 2080 * matches then no need to update tx qeue groups. 2081 */ 2082 if (group->membership == membership) 2083 /* Update Credit Only */ 2084 goto credit_update; 2085 2086 credit += ol_txrx_distribute_group_credits(pdev, group_id, 2087 vdev_id_mask); 2088 /* 2089 * membership (vdev id mask and ac mask) is not matching 2090 * TODO: ignoring ac mask for now 2091 */ 2092 qdf_assert(ac_mask == 0xffff); 2093 group_vdev_id_mask = 2094 OL_TXQ_GROUP_VDEV_ID_MASK_GET(group->membership); 2095 2096 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 2097 group_vdev_bit_mask = 2098 OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET( 2099 group_vdev_id_mask, vdev->vdev_id); 2100 vdev_bit_mask = 2101 OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET( 2102 vdev_id_mask, vdev->vdev_id); 2103 2104 if (group_vdev_bit_mask != vdev_bit_mask) { 2105 /* 2106 * Change in vdev tx queue group 2107 */ 2108 if (!vdev_bit_mask) { 2109 /* Set Group Pointer (vdev and peer) to NULL */ 2110 ol_txrx_info("Group membership removed for vdev_id %d from group_id %d", 2111 vdev->vdev_id, group_id); 2112 ol_tx_set_vdev_group_ptr( 2113 pdev, vdev->vdev_id, NULL); 2114 } else { 2115 /* Set Group Pointer (vdev and peer) */ 2116 ol_txrx_info("Group membership updated for vdev_id %d to group_id %d", 2117 vdev->vdev_id, group_id); 2118 ol_tx_set_vdev_group_ptr( 2119 pdev, vdev->vdev_id, group); 2120 } 2121 } 2122 } 2123 /* Update membership */ 2124 group->membership = membership; 2125 ol_txrx_info("Group membership updated for group_id %d membership 0x%x", 2126 group_id, group->membership); 2127 credit_update: 2128 /* Update Credit */ 2129 ol_txrx_update_group_credit(group, credit, absolute); 2130 qdf_spin_unlock_bh(&pdev->tx_queue_spinlock); 2131 } 2132 #endif 2133 2134 #if defined(FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL) && \ 2135 defined(FEATURE_HL_DBS_GROUP_CREDIT_SHARING) 2136 #define MIN_INIT_GROUP_CREDITS 10 2137 int ol_txrx_distribute_group_credits(struct ol_txrx_pdev_t *pdev, 2138 u8 group_id, 2139 u32 vdevid_mask_new) 2140 { 2141 struct ol_tx_queue_group_t *grp = &pdev->txq_grps[group_id]; 2142 struct ol_tx_queue_group_t *grp_nxt = &pdev->txq_grps[!group_id]; 2143 int creds_nxt = qdf_atomic_read(&grp_nxt->credit); 2144 int vdevid_mask = OL_TXQ_GROUP_VDEV_ID_MASK_GET(grp->membership); 2145 int vdevid_mask_othgrp = 2146 OL_TXQ_GROUP_VDEV_ID_MASK_GET(grp_nxt->membership); 2147 int creds_distribute = 0; 2148 2149 /* if vdev added to the group is the first vdev */ 2150 if ((vdevid_mask == 0) && (vdevid_mask_new != 0)) { 2151 /* if other group has members */ 2152 if (vdevid_mask_othgrp) { 2153 if (creds_nxt < MIN_INIT_GROUP_CREDITS) 2154 creds_distribute = creds_nxt / 2; 2155 else 2156 creds_distribute = MIN_INIT_GROUP_CREDITS; 2157 2158 ol_txrx_update_group_credit(grp_nxt, -creds_distribute, 2159 0); 2160 } else { 2161 /* 2162 * Other grp has no members, give all credits to this 2163 * grp. 2164 */ 2165 creds_distribute = 2166 qdf_atomic_read(&pdev->target_tx_credit); 2167 } 2168 /* if all vdevs are removed from this grp */ 2169 } else if ((vdevid_mask != 0) && (vdevid_mask_new == 0)) { 2170 if (vdevid_mask_othgrp) 2171 /* Transfer credits to other grp */ 2172 ol_txrx_update_group_credit(grp_nxt, 2173 qdf_atomic_read(&grp-> 2174 credit), 2175 0); 2176 /* Set current grp credits to zero */ 2177 ol_txrx_update_group_credit(grp, 0, 1); 2178 } 2179 2180 return creds_distribute; 2181 } 2182 #endif /* 2183 * FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL && 2184 * FEATURE_HL_DBS_GROUP_CREDIT_SHARING 2185 */ 2186 2187 #ifdef QCA_HL_NETDEV_FLOW_CONTROL 2188 int ol_txrx_register_hl_flow_control(struct cdp_soc_t *soc_hdl, 2189 uint8_t pdev_id, 2190 tx_pause_callback flowcontrol) 2191 { 2192 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 2193 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id); 2194 u32 desc_pool_size; 2195 2196 if (!pdev || !flowcontrol) { 2197 ol_txrx_err("pdev or pause_cb is NULL"); 2198 return QDF_STATUS_E_INVAL; 2199 } 2200 2201 desc_pool_size = ol_tx_desc_pool_size_hl(pdev->ctrl_pdev); 2202 /* 2203 * Assert if the tx descriptor pool size meets the requirements 2204 * Maximum 2 sessions are allowed on a band. 2205 */ 2206 QDF_ASSERT((2 * ol_txrx_tx_desc_alloc_table[TXRX_FC_5GH_80M_2x2] + 2207 ol_txrx_tx_desc_alloc_table[TXRX_FC_2GH_40M_2x2]) 2208 <= desc_pool_size); 2209 2210 pdev->pause_cb = flowcontrol; 2211 return 0; 2212 } 2213 2214 int ol_txrx_set_vdev_os_queue_status(struct cdp_soc_t *soc_hdl, u8 vdev_id, 2215 enum netif_action_type action) 2216 { 2217 struct ol_txrx_vdev_t *vdev = 2218 (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id); 2219 2220 if (!vdev) { 2221 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2222 "%s: Invalid vdev_id %d", __func__, vdev_id); 2223 return -EINVAL; 2224 } 2225 2226 switch (action) { 2227 case WLAN_NETIF_PRIORITY_QUEUE_ON: 2228 qdf_spin_lock_bh(&vdev->pdev->tx_mutex); 2229 vdev->prio_q_paused = 0; 2230 qdf_spin_unlock_bh(&vdev->pdev->tx_mutex); 2231 break; 2232 case WLAN_WAKE_NON_PRIORITY_QUEUE: 2233 qdf_atomic_set(&vdev->os_q_paused, 0); 2234 break; 2235 default: 2236 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2237 "%s: Invalid action %d", __func__, action); 2238 return -EINVAL; 2239 } 2240 return 0; 2241 } 2242 2243 int ol_txrx_set_vdev_tx_desc_limit(struct cdp_soc_t *soc_hdl, u8 vdev_id, 2244 u32 chan_freq) 2245 { 2246 struct ol_txrx_vdev_t *vdev = 2247 (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id); 2248 enum ol_txrx_fc_limit_id fc_limit_id; 2249 u32 td_limit; 2250 2251 if (!vdev) { 2252 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2253 "%s: Invalid vdev_id %d", __func__, vdev_id); 2254 return -EINVAL; 2255 } 2256 2257 /* TODO: Handle no of spatial streams and channel BW */ 2258 if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq)) 2259 fc_limit_id = TXRX_FC_5GH_80M_2x2; 2260 else 2261 fc_limit_id = TXRX_FC_2GH_40M_2x2; 2262 2263 qdf_spin_lock_bh(&vdev->pdev->tx_mutex); 2264 td_limit = ol_txrx_tx_desc_alloc_table[fc_limit_id]; 2265 vdev->tx_desc_limit = td_limit; 2266 vdev->queue_stop_th = td_limit - TXRX_HL_TX_DESC_HI_PRIO_RESERVED; 2267 vdev->queue_restart_th = td_limit - TXRX_HL_TX_DESC_QUEUE_RESTART_TH; 2268 qdf_spin_unlock_bh(&vdev->pdev->tx_mutex); 2269 2270 return 0; 2271 } 2272 2273 void ol_tx_dump_flow_pool_info_compact(struct ol_txrx_pdev_t *pdev) 2274 { 2275 char *comb_log_str; 2276 int bytes_written = 0; 2277 uint32_t free_size; 2278 struct ol_txrx_vdev_t *vdev; 2279 int i = 0; 2280 2281 free_size = WLAN_MAX_VDEVS * 100; 2282 comb_log_str = qdf_mem_malloc(free_size); 2283 if (!comb_log_str) 2284 return; 2285 2286 qdf_spin_lock_bh(&pdev->tx_mutex); 2287 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 2288 bytes_written += snprintf(&comb_log_str[bytes_written], 2289 free_size, "%d (%d,%d)(%d,%d)(%d,%d) |", 2290 vdev->vdev_id, vdev->tx_desc_limit, 2291 qdf_atomic_read(&vdev->tx_desc_count), 2292 qdf_atomic_read(&vdev->os_q_paused), 2293 vdev->prio_q_paused, vdev->queue_stop_th, 2294 vdev->queue_restart_th); 2295 free_size -= bytes_written; 2296 } 2297 qdf_spin_unlock_bh(&pdev->tx_mutex); 2298 qdf_nofl_debug("STATS | FC: %s", comb_log_str); 2299 2300 free_size = WLAN_MAX_VDEVS * 100; 2301 bytes_written = 0; 2302 qdf_mem_zero(comb_log_str, free_size); 2303 2304 bytes_written = snprintf(&comb_log_str[bytes_written], free_size, 2305 "%d ", 2306 qdf_atomic_read(&pdev->target_tx_credit)); 2307 for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) { 2308 bytes_written += snprintf(&comb_log_str[bytes_written], 2309 free_size, "|%d, (0x%x, %d)", i, 2310 OL_TXQ_GROUP_VDEV_ID_MASK_GET( 2311 pdev->txq_grps[i].membership), 2312 qdf_atomic_read( 2313 &pdev->txq_grps[i].credit)); 2314 free_size -= bytes_written; 2315 } 2316 qdf_nofl_debug("STATS | CREDIT: %s", comb_log_str); 2317 qdf_mem_free(comb_log_str); 2318 } 2319 2320 void ol_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl) 2321 { 2322 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); 2323 ol_txrx_pdev_handle pdev; 2324 struct ol_txrx_vdev_t *vdev; 2325 2326 pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID); 2327 if (!pdev) { 2328 ol_txrx_err("pdev is NULL"); 2329 return; 2330 } 2331 2332 qdf_spin_lock_bh(&pdev->tx_mutex); 2333 TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { 2334 txrx_nofl_info("vdev_id %d", vdev->vdev_id); 2335 txrx_nofl_info("limit %d available %d stop_threshold %d restart_threshold %d", 2336 vdev->tx_desc_limit, 2337 qdf_atomic_read(&vdev->tx_desc_count), 2338 vdev->queue_stop_th, vdev->queue_restart_th); 2339 txrx_nofl_info("q_paused %d prio_q_paused %d", 2340 qdf_atomic_read(&vdev->os_q_paused), 2341 vdev->prio_q_paused); 2342 txrx_nofl_info("no_of_bundle_sent_after_threshold %lld", 2343 vdev->no_of_bundle_sent_after_threshold); 2344 txrx_nofl_info("no_of_bundle_sent_in_timer %lld", 2345 vdev->no_of_bundle_sent_in_timer); 2346 txrx_nofl_info("no_of_pkt_not_added_in_queue %lld", 2347 vdev->no_of_pkt_not_added_in_queue); 2348 } 2349 qdf_spin_unlock_bh(&pdev->tx_mutex); 2350 } 2351 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */ 2352