1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <htt.h> 20 #include <hal_api.h> 21 #include "dp_htt.h" 22 #include "dp_peer.h" 23 #include "dp_types.h" 24 #include "dp_internal.h" 25 #include "dp_rx_mon.h" 26 #include "htt_stats.h" 27 #include "htt_ppdu_stats.h" 28 #include "qdf_mem.h" /* qdf_mem_malloc,free */ 29 #include "cdp_txrx_cmn_struct.h" 30 31 #define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE 32 33 #define HTT_HTC_PKT_POOL_INIT_SIZE 64 34 #define HTT_T2H_MAX_MSG_SIZE 2048 35 36 #define HTT_MSG_BUF_SIZE(msg_bytes) \ 37 ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING) 38 39 #define HTT_PID_BIT_MASK 0x3 40 41 #define DP_EXT_MSG_LENGTH 2048 42 #define DP_HTT_SEND_HTC_PKT(soc, pkt) \ 43 do { \ 44 if (htc_send_pkt(soc->htc_soc, &pkt->htc_pkt) == \ 45 QDF_STATUS_SUCCESS) \ 46 htt_htc_misc_pkt_list_add(soc, pkt); \ 47 } while (0) 48 49 #define HTT_MGMT_CTRL_TLV_RESERVERD_LEN 12 50 /** 51 * Bitmap of HTT PPDU TLV types for Default mode 52 */ 53 #define HTT_PPDU_DEFAULT_TLV_BITMAP \ 54 (1 << HTT_PPDU_STATS_COMMON_TLV) | \ 55 (1 << HTT_PPDU_STATS_USR_COMMON_TLV) | \ 56 (1 << HTT_PPDU_STATS_USR_RATE_TLV) | \ 57 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV) | \ 58 (1 << HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV) | \ 59 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) 60 61 /** 62 * Bitmap of HTT PPDU TLV types for Sniffer mode 63 */ 64 #define HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP \ 65 (1 << HTT_PPDU_STATS_COMMON_TLV) | \ 66 (1 << HTT_PPDU_STATS_USR_COMMON_TLV) | \ 67 (1 << HTT_PPDU_STATS_USR_RATE_TLV) | \ 68 (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV) | \ 69 (1 << HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV) | \ 70 (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) | \ 71 (1 << HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV) | \ 72 (1 << HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV) | \ 73 (1 << HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV) 74 75 #define HTT_FRAMECTRL_DATATYPE 0x08 76 #define HTT_PPDU_DESC_MAX_DEPTH 16 77 78 /* 79 * dp_tx_stats_update() - Update per-peer statistics 80 * @soc: Datapath soc handle 81 * @peer: Datapath peer handle 82 * @ppdu: PPDU Descriptor 83 * @ack_rssi: RSSI of last ack received 84 * 85 * Return: None 86 */ 87 #ifdef FEATURE_PERPKT_INFO 88 static void dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, 89 struct cdp_tx_completion_ppdu_user *ppdu, uint32_t ack_rssi) 90 { 91 struct dp_pdev *pdev = peer->vdev->pdev; 92 uint8_t preamble, mcs; 93 uint16_t num_msdu; 94 95 preamble = ppdu->preamble; 96 mcs = ppdu->mcs; 97 num_msdu = ppdu->num_msdu; 98 99 /* If the peer statistics are already processed as part of 100 * per-MSDU completion handler, do not process these again in per-PPDU 101 * indications */ 102 if (soc->process_tx_status) 103 return; 104 105 DP_STATS_INC_PKT(peer, tx.comp_pkt, 106 num_msdu, (ppdu->success_bytes + 107 ppdu->retry_bytes + ppdu->failed_bytes)); 108 DP_STATS_INC(peer, tx.tx_failed, ppdu->failed_msdus); 109 DP_STATS_UPD(peer, tx.tx_rate, ppdu->tx_rate); 110 DP_STATS_INC(peer, tx.sgi_count[ppdu->gi], num_msdu); 111 DP_STATS_INC(peer, tx.bw[ppdu->bw], num_msdu); 112 DP_STATS_INC(peer, tx.nss[ppdu->nss], num_msdu); 113 DP_STATS_INC(peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], num_msdu); 114 DP_STATS_INCC(peer, tx.stbc, num_msdu, ppdu->stbc); 115 DP_STATS_INCC(peer, tx.ldpc, num_msdu, ppdu->ldpc); 116 if (!(ppdu->is_mcast)) 117 DP_STATS_UPD(peer, tx.last_ack_rssi, ack_rssi); 118 119 DP_STATS_INC(peer, tx.retries, 120 (ppdu->long_retries + ppdu->short_retries)); 121 DP_STATS_INCC(peer, 122 tx.pkt_type[preamble].mcs_count[MAX_MCS-1], num_msdu, 123 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_A))); 124 DP_STATS_INCC(peer, 125 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 126 ((mcs < MAX_MCS_11A) && (preamble == DOT11_A))); 127 DP_STATS_INCC(peer, 128 tx.pkt_type[preamble].mcs_count[MAX_MCS-1], num_msdu, 129 ((mcs >= MAX_MCS_11B) && (preamble == DOT11_B))); 130 DP_STATS_INCC(peer, 131 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 132 ((mcs < (MAX_MCS_11B)) && (preamble == DOT11_B))); 133 DP_STATS_INCC(peer, 134 tx.pkt_type[preamble].mcs_count[MAX_MCS-1], num_msdu, 135 ((mcs >= MAX_MCS_11A) && (preamble == DOT11_N))); 136 DP_STATS_INCC(peer, 137 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 138 ((mcs < MAX_MCS_11A) && (preamble == DOT11_N))); 139 DP_STATS_INCC(peer, 140 tx.pkt_type[preamble].mcs_count[MAX_MCS-1], num_msdu, 141 ((mcs >= MAX_MCS_11AC) && (preamble == DOT11_AC))); 142 DP_STATS_INCC(peer, 143 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 144 ((mcs < MAX_MCS_11AC) && (preamble == DOT11_AC))); 145 DP_STATS_INCC(peer, 146 tx.pkt_type[preamble].mcs_count[MAX_MCS-1], num_msdu, 147 ((mcs >= (MAX_MCS - 1)) && (preamble == DOT11_AX))); 148 DP_STATS_INCC(peer, 149 tx.pkt_type[preamble].mcs_count[mcs], num_msdu, 150 ((mcs < (MAX_MCS - 1)) && (preamble == DOT11_AX))); 151 152 if (soc->cdp_soc.ol_ops->update_dp_stats) { 153 soc->cdp_soc.ol_ops->update_dp_stats(pdev->osif_pdev, 154 &peer->stats, ppdu->peer_id, 155 UPDATE_PEER_STATS); 156 157 dp_aggregate_vdev_stats(peer->vdev); 158 } 159 } 160 #endif 161 162 /* 163 * htt_htc_pkt_alloc() - Allocate HTC packet buffer 164 * @htt_soc: HTT SOC handle 165 * 166 * Return: Pointer to htc packet buffer 167 */ 168 static struct dp_htt_htc_pkt * 169 htt_htc_pkt_alloc(struct htt_soc *soc) 170 { 171 struct dp_htt_htc_pkt_union *pkt = NULL; 172 173 HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex); 174 if (soc->htt_htc_pkt_freelist) { 175 pkt = soc->htt_htc_pkt_freelist; 176 soc->htt_htc_pkt_freelist = soc->htt_htc_pkt_freelist->u.next; 177 } 178 HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex); 179 180 if (pkt == NULL) 181 pkt = qdf_mem_malloc(sizeof(*pkt)); 182 return &pkt->u.pkt; /* not actually a dereference */ 183 } 184 185 /* 186 * htt_htc_pkt_free() - Free HTC packet buffer 187 * @htt_soc: HTT SOC handle 188 */ 189 static void 190 htt_htc_pkt_free(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt) 191 { 192 struct dp_htt_htc_pkt_union *u_pkt = 193 (struct dp_htt_htc_pkt_union *)pkt; 194 195 HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex); 196 u_pkt->u.next = soc->htt_htc_pkt_freelist; 197 soc->htt_htc_pkt_freelist = u_pkt; 198 HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex); 199 } 200 201 /* 202 * htt_htc_pkt_pool_free() - Free HTC packet pool 203 * @htt_soc: HTT SOC handle 204 */ 205 static void 206 htt_htc_pkt_pool_free(struct htt_soc *soc) 207 { 208 struct dp_htt_htc_pkt_union *pkt, *next; 209 pkt = soc->htt_htc_pkt_freelist; 210 while (pkt) { 211 next = pkt->u.next; 212 qdf_mem_free(pkt); 213 pkt = next; 214 } 215 soc->htt_htc_pkt_freelist = NULL; 216 } 217 218 /* 219 * htt_htc_misc_pkt_list_trim() - trim misc list 220 * @htt_soc: HTT SOC handle 221 * @level: max no. of pkts in list 222 */ 223 static void 224 htt_htc_misc_pkt_list_trim(struct htt_soc *soc, int level) 225 { 226 struct dp_htt_htc_pkt_union *pkt, *next, *prev = NULL; 227 int i = 0; 228 qdf_nbuf_t netbuf; 229 230 HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex); 231 pkt = soc->htt_htc_pkt_misclist; 232 while (pkt) { 233 next = pkt->u.next; 234 /* trim the out grown list*/ 235 if (++i > level) { 236 netbuf = 237 (qdf_nbuf_t)(pkt->u.pkt.htc_pkt.pNetBufContext); 238 qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE); 239 qdf_nbuf_free(netbuf); 240 qdf_mem_free(pkt); 241 pkt = NULL; 242 if (prev) 243 prev->u.next = NULL; 244 } 245 prev = pkt; 246 pkt = next; 247 } 248 HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex); 249 } 250 251 /* 252 * htt_htc_misc_pkt_list_add() - Add pkt to misc list 253 * @htt_soc: HTT SOC handle 254 * @dp_htt_htc_pkt: pkt to be added to list 255 */ 256 static void 257 htt_htc_misc_pkt_list_add(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt) 258 { 259 struct dp_htt_htc_pkt_union *u_pkt = 260 (struct dp_htt_htc_pkt_union *)pkt; 261 int misclist_trim_level = htc_get_tx_queue_depth(soc->htc_soc, 262 pkt->htc_pkt.Endpoint) 263 + DP_HTT_HTC_PKT_MISCLIST_SIZE; 264 265 HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex); 266 if (soc->htt_htc_pkt_misclist) { 267 u_pkt->u.next = soc->htt_htc_pkt_misclist; 268 soc->htt_htc_pkt_misclist = u_pkt; 269 } else { 270 soc->htt_htc_pkt_misclist = u_pkt; 271 } 272 HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex); 273 274 /* only ce pipe size + tx_queue_depth could possibly be in use 275 * free older packets in the misclist 276 */ 277 htt_htc_misc_pkt_list_trim(soc, misclist_trim_level); 278 } 279 280 /* 281 * htt_htc_misc_pkt_pool_free() - free pkts in misc list 282 * @htt_soc: HTT SOC handle 283 */ 284 static void 285 htt_htc_misc_pkt_pool_free(struct htt_soc *soc) 286 { 287 struct dp_htt_htc_pkt_union *pkt, *next; 288 qdf_nbuf_t netbuf; 289 290 pkt = soc->htt_htc_pkt_misclist; 291 292 while (pkt) { 293 next = pkt->u.next; 294 netbuf = (qdf_nbuf_t) (pkt->u.pkt.htc_pkt.pNetBufContext); 295 qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE); 296 297 soc->stats.htc_pkt_free++; 298 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, 299 "%s: Pkt free count %d\n", 300 __func__, soc->stats.htc_pkt_free); 301 302 qdf_nbuf_free(netbuf); 303 qdf_mem_free(pkt); 304 pkt = next; 305 } 306 soc->htt_htc_pkt_misclist = NULL; 307 } 308 309 /* 310 * htt_t2h_mac_addr_deswizzle() - Swap MAC addr bytes if FW endianess differ 311 * @tgt_mac_addr: Target MAC 312 * @buffer: Output buffer 313 */ 314 static u_int8_t * 315 htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer) 316 { 317 #ifdef BIG_ENDIAN_HOST 318 /* 319 * The host endianness is opposite of the target endianness. 320 * To make u_int32_t elements come out correctly, the target->host 321 * upload has swizzled the bytes in each u_int32_t element of the 322 * message. 323 * For byte-array message fields like the MAC address, this 324 * upload swizzling puts the bytes in the wrong order, and needs 325 * to be undone. 326 */ 327 buffer[0] = tgt_mac_addr[3]; 328 buffer[1] = tgt_mac_addr[2]; 329 buffer[2] = tgt_mac_addr[1]; 330 buffer[3] = tgt_mac_addr[0]; 331 buffer[4] = tgt_mac_addr[7]; 332 buffer[5] = tgt_mac_addr[6]; 333 return buffer; 334 #else 335 /* 336 * The host endianness matches the target endianness - 337 * we can use the mac addr directly from the message buffer. 338 */ 339 return tgt_mac_addr; 340 #endif 341 } 342 343 /* 344 * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer 345 * @soc: SOC handle 346 * @status: Completion status 347 * @netbuf: HTT buffer 348 */ 349 static void 350 dp_htt_h2t_send_complete_free_netbuf( 351 void *soc, A_STATUS status, qdf_nbuf_t netbuf) 352 { 353 qdf_nbuf_free(netbuf); 354 } 355 356 /* 357 * dp_htt_h2t_send_complete() - H2T completion handler 358 * @context: Opaque context (HTT SOC handle) 359 * @htc_pkt: HTC packet 360 */ 361 static void 362 dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt) 363 { 364 void (*send_complete_part2)( 365 void *soc, A_STATUS status, qdf_nbuf_t msdu); 366 struct htt_soc *soc = (struct htt_soc *) context; 367 struct dp_htt_htc_pkt *htt_pkt; 368 qdf_nbuf_t netbuf; 369 370 send_complete_part2 = htc_pkt->pPktContext; 371 372 htt_pkt = container_of(htc_pkt, struct dp_htt_htc_pkt, htc_pkt); 373 374 /* process (free or keep) the netbuf that held the message */ 375 netbuf = (qdf_nbuf_t) htc_pkt->pNetBufContext; 376 /* 377 * adf sendcomplete is required for windows only 378 */ 379 /* qdf_nbuf_set_sendcompleteflag(netbuf, TRUE); */ 380 if (send_complete_part2 != NULL) { 381 send_complete_part2( 382 htt_pkt->soc_ctxt, htc_pkt->Status, netbuf); 383 } 384 /* free the htt_htc_pkt / HTC_PACKET object */ 385 htt_htc_pkt_free(soc, htt_pkt); 386 } 387 388 /* 389 * htt_h2t_ver_req_msg() - Send HTT version request message to target 390 * @htt_soc: HTT SOC handle 391 * 392 * Return: 0 on success; error code on failure 393 */ 394 static int htt_h2t_ver_req_msg(struct htt_soc *soc) 395 { 396 struct dp_htt_htc_pkt *pkt; 397 qdf_nbuf_t msg; 398 uint32_t *msg_word; 399 400 msg = qdf_nbuf_alloc( 401 soc->osdev, 402 HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES), 403 /* reserve room for the HTC header */ 404 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); 405 if (!msg) 406 return QDF_STATUS_E_NOMEM; 407 408 /* 409 * Set the length of the message. 410 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added 411 * separately during the below call to qdf_nbuf_push_head. 412 * The contribution from the HTC header is added separately inside HTC. 413 */ 414 if (qdf_nbuf_put_tail(msg, HTT_VER_REQ_BYTES) == NULL) { 415 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 416 "%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg\n", 417 __func__); 418 return QDF_STATUS_E_FAILURE; 419 } 420 421 /* fill in the message contents */ 422 msg_word = (u_int32_t *) qdf_nbuf_data(msg); 423 424 /* rewind beyond alignment pad to get to the HTC header reserved area */ 425 qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); 426 427 *msg_word = 0; 428 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ); 429 430 pkt = htt_htc_pkt_alloc(soc); 431 if (!pkt) { 432 qdf_nbuf_free(msg); 433 return QDF_STATUS_E_FAILURE; 434 } 435 pkt->soc_ctxt = NULL; /* not used during send-done callback */ 436 437 SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, 438 dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg), 439 qdf_nbuf_len(msg), soc->htc_endpoint, 440 1); /* tag - not relevant here */ 441 442 SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); 443 DP_HTT_SEND_HTC_PKT(soc, pkt); 444 return 0; 445 } 446 447 /* 448 * htt_srng_setup() - Send SRNG setup message to target 449 * @htt_soc: HTT SOC handle 450 * @mac_id: MAC Id 451 * @hal_srng: Opaque HAL SRNG pointer 452 * @hal_ring_type: SRNG ring type 453 * 454 * Return: 0 on success; error code on failure 455 */ 456 int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, 457 int hal_ring_type) 458 { 459 struct htt_soc *soc = (struct htt_soc *)htt_soc; 460 struct dp_htt_htc_pkt *pkt; 461 qdf_nbuf_t htt_msg; 462 uint32_t *msg_word; 463 struct hal_srng_params srng_params; 464 qdf_dma_addr_t hp_addr, tp_addr; 465 uint32_t ring_entry_size = 466 hal_srng_get_entrysize(soc->hal_soc, hal_ring_type); 467 int htt_ring_type, htt_ring_id; 468 469 /* Sizes should be set in 4-byte words */ 470 ring_entry_size = ring_entry_size >> 2; 471 472 htt_msg = qdf_nbuf_alloc(soc->osdev, 473 HTT_MSG_BUF_SIZE(HTT_SRING_SETUP_SZ), 474 /* reserve room for the HTC header */ 475 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); 476 if (!htt_msg) 477 goto fail0; 478 479 hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); 480 hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng); 481 tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng); 482 483 switch (hal_ring_type) { 484 case RXDMA_BUF: 485 #ifdef QCA_HOST2FW_RXBUF_RING 486 if (srng_params.ring_id == 487 (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0)) { 488 htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING; 489 htt_ring_type = HTT_SW_TO_SW_RING; 490 #ifdef IPA_OFFLOAD 491 } else if (srng_params.ring_id == 492 (HAL_SRNG_WMAC1_SW2RXDMA0_BUF2)) { 493 htt_ring_id = HTT_HOST2_TO_FW_RXBUF_RING; 494 htt_ring_type = HTT_SW_TO_SW_RING; 495 #endif 496 #else 497 if (srng_params.ring_id == 498 (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 + 499 (mac_id * HAL_MAX_RINGS_PER_LMAC))) { 500 htt_ring_id = HTT_RXDMA_HOST_BUF_RING; 501 htt_ring_type = HTT_SW_TO_HW_RING; 502 #endif 503 } else if (srng_params.ring_id == 504 #ifdef IPA_OFFLOAD 505 (HAL_SRNG_WMAC1_SW2RXDMA0_BUF1 + 506 #else 507 (HAL_SRNG_WMAC1_SW2RXDMA1_BUF + 508 #endif 509 (mac_id * HAL_MAX_RINGS_PER_LMAC))) { 510 htt_ring_id = HTT_RXDMA_HOST_BUF_RING; 511 htt_ring_type = HTT_SW_TO_HW_RING; 512 } else { 513 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 514 "%s: Ring %d currently not supported\n", 515 __func__, srng_params.ring_id); 516 goto fail1; 517 } 518 519 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 520 "%s: ring_type %d ring_id %d\n", 521 __func__, hal_ring_type, srng_params.ring_id); 522 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 523 "%s: hp_addr 0x%llx tp_addr 0x%llx\n", 524 __func__, (uint64_t)hp_addr, (uint64_t)tp_addr); 525 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 526 "%s: htt_ring_id %d\n", __func__, htt_ring_id); 527 break; 528 case RXDMA_MONITOR_BUF: 529 htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING; 530 htt_ring_type = HTT_SW_TO_HW_RING; 531 break; 532 case RXDMA_MONITOR_STATUS: 533 htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING; 534 htt_ring_type = HTT_SW_TO_HW_RING; 535 break; 536 case RXDMA_MONITOR_DST: 537 htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING; 538 htt_ring_type = HTT_HW_TO_SW_RING; 539 break; 540 case RXDMA_MONITOR_DESC: 541 htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING; 542 htt_ring_type = HTT_SW_TO_HW_RING; 543 break; 544 case RXDMA_DST: 545 htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; 546 htt_ring_type = HTT_HW_TO_SW_RING; 547 break; 548 549 default: 550 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 551 "%s: Ring currently not supported\n", __func__); 552 goto fail1; 553 } 554 555 /* 556 * Set the length of the message. 557 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added 558 * separately during the below call to qdf_nbuf_push_head. 559 * The contribution from the HTC header is added separately inside HTC. 560 */ 561 if (qdf_nbuf_put_tail(htt_msg, HTT_SRING_SETUP_SZ) == NULL) { 562 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 563 "%s: Failed to expand head for SRING_SETUP msg\n", 564 __func__); 565 return QDF_STATUS_E_FAILURE; 566 } 567 568 msg_word = (uint32_t *)qdf_nbuf_data(htt_msg); 569 570 /* rewind beyond alignment pad to get to the HTC header reserved area */ 571 qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING); 572 573 /* word 0 */ 574 *msg_word = 0; 575 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP); 576 577 if ((htt_ring_type == HTT_SW_TO_HW_RING) || 578 (htt_ring_type == HTT_HW_TO_SW_RING)) 579 HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, 580 DP_SW2HW_MACID(mac_id)); 581 else 582 HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id); 583 584 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 585 "%s: mac_id %d\n", __func__, mac_id); 586 HTT_SRING_SETUP_RING_TYPE_SET(*msg_word, htt_ring_type); 587 /* TODO: Discuss with FW on changing this to unique ID and using 588 * htt_ring_type to send the type of ring 589 */ 590 HTT_SRING_SETUP_RING_ID_SET(*msg_word, htt_ring_id); 591 592 /* word 1 */ 593 msg_word++; 594 *msg_word = 0; 595 HTT_SRING_SETUP_RING_BASE_ADDR_LO_SET(*msg_word, 596 srng_params.ring_base_paddr & 0xffffffff); 597 598 /* word 2 */ 599 msg_word++; 600 *msg_word = 0; 601 HTT_SRING_SETUP_RING_BASE_ADDR_HI_SET(*msg_word, 602 (uint64_t)srng_params.ring_base_paddr >> 32); 603 604 /* word 3 */ 605 msg_word++; 606 *msg_word = 0; 607 HTT_SRING_SETUP_ENTRY_SIZE_SET(*msg_word, ring_entry_size); 608 HTT_SRING_SETUP_RING_SIZE_SET(*msg_word, 609 (ring_entry_size * srng_params.num_entries)); 610 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 611 "%s: entry_size %d\n", __func__, 612 ring_entry_size); 613 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 614 "%s: num_entries %d\n", __func__, 615 srng_params.num_entries); 616 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 617 "%s: ring_size %d\n", __func__, 618 (ring_entry_size * srng_params.num_entries)); 619 if (htt_ring_type == HTT_SW_TO_HW_RING) 620 HTT_SRING_SETUP_RING_MISC_CFG_FLAG_LOOPCOUNT_DISABLE_SET( 621 *msg_word, 1); 622 HTT_SRING_SETUP_RING_MISC_CFG_FLAG_MSI_SWAP_SET(*msg_word, 623 !!(srng_params.flags & HAL_SRNG_MSI_SWAP)); 624 HTT_SRING_SETUP_RING_MISC_CFG_FLAG_TLV_SWAP_SET(*msg_word, 625 !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP)); 626 HTT_SRING_SETUP_RING_MISC_CFG_FLAG_HOST_FW_SWAP_SET(*msg_word, 627 !!(srng_params.flags & HAL_SRNG_RING_PTR_SWAP)); 628 629 /* word 4 */ 630 msg_word++; 631 *msg_word = 0; 632 HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word, 633 hp_addr & 0xffffffff); 634 635 /* word 5 */ 636 msg_word++; 637 *msg_word = 0; 638 HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word, 639 (uint64_t)hp_addr >> 32); 640 641 /* word 6 */ 642 msg_word++; 643 *msg_word = 0; 644 HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word, 645 tp_addr & 0xffffffff); 646 647 /* word 7 */ 648 msg_word++; 649 *msg_word = 0; 650 HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word, 651 (uint64_t)tp_addr >> 32); 652 653 /* word 8 */ 654 msg_word++; 655 *msg_word = 0; 656 HTT_SRING_SETUP_RING_MSI_ADDR_LO_SET(*msg_word, 657 srng_params.msi_addr & 0xffffffff); 658 659 /* word 9 */ 660 msg_word++; 661 *msg_word = 0; 662 HTT_SRING_SETUP_RING_MSI_ADDR_HI_SET(*msg_word, 663 (uint64_t)(srng_params.msi_addr) >> 32); 664 665 /* word 10 */ 666 msg_word++; 667 *msg_word = 0; 668 HTT_SRING_SETUP_RING_MSI_DATA_SET(*msg_word, 669 srng_params.msi_data); 670 671 /* word 11 */ 672 msg_word++; 673 *msg_word = 0; 674 HTT_SRING_SETUP_INTR_BATCH_COUNTER_TH_SET(*msg_word, 675 srng_params.intr_batch_cntr_thres_entries * 676 ring_entry_size); 677 HTT_SRING_SETUP_INTR_TIMER_TH_SET(*msg_word, 678 srng_params.intr_timer_thres_us >> 3); 679 680 /* word 12 */ 681 msg_word++; 682 *msg_word = 0; 683 if (srng_params.flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) { 684 /* TODO: Setting low threshold to 1/8th of ring size - see 685 * if this needs to be configurable 686 */ 687 HTT_SRING_SETUP_INTR_LOW_TH_SET(*msg_word, 688 srng_params.low_threshold); 689 } 690 /* "response_required" field should be set if a HTT response message is 691 * required after setting up the ring. 692 */ 693 pkt = htt_htc_pkt_alloc(soc); 694 if (!pkt) 695 goto fail1; 696 697 pkt->soc_ctxt = NULL; /* not used during send-done callback */ 698 699 SET_HTC_PACKET_INFO_TX( 700 &pkt->htc_pkt, 701 dp_htt_h2t_send_complete_free_netbuf, 702 qdf_nbuf_data(htt_msg), 703 qdf_nbuf_len(htt_msg), 704 soc->htc_endpoint, 705 HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */ 706 707 SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg); 708 DP_HTT_SEND_HTC_PKT(soc, pkt); 709 710 return QDF_STATUS_SUCCESS; 711 712 fail1: 713 qdf_nbuf_free(htt_msg); 714 fail0: 715 return QDF_STATUS_E_FAILURE; 716 } 717 718 /* 719 * htt_h2t_rx_ring_cfg() - Send SRNG packet and TLV filter 720 * config message to target 721 * @htt_soc: HTT SOC handle 722 * @pdev_id: PDEV Id 723 * @hal_srng: Opaque HAL SRNG pointer 724 * @hal_ring_type: SRNG ring type 725 * @ring_buf_size: SRNG buffer size 726 * @htt_tlv_filter: Rx SRNG TLV and filter setting 727 * Return: 0 on success; error code on failure 728 */ 729 int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, 730 int hal_ring_type, int ring_buf_size, 731 struct htt_rx_ring_tlv_filter *htt_tlv_filter) 732 { 733 struct htt_soc *soc = (struct htt_soc *)htt_soc; 734 struct dp_htt_htc_pkt *pkt; 735 qdf_nbuf_t htt_msg; 736 uint32_t *msg_word; 737 struct hal_srng_params srng_params; 738 uint32_t htt_ring_type, htt_ring_id; 739 uint32_t tlv_filter; 740 741 htt_msg = qdf_nbuf_alloc(soc->osdev, 742 HTT_MSG_BUF_SIZE(HTT_RX_RING_SELECTION_CFG_SZ), 743 /* reserve room for the HTC header */ 744 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); 745 if (!htt_msg) 746 goto fail0; 747 748 hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); 749 750 switch (hal_ring_type) { 751 case RXDMA_BUF: 752 #if QCA_HOST2FW_RXBUF_RING 753 htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING; 754 htt_ring_type = HTT_SW_TO_SW_RING; 755 #else 756 htt_ring_id = HTT_RXDMA_HOST_BUF_RING; 757 htt_ring_type = HTT_SW_TO_HW_RING; 758 #endif 759 break; 760 case RXDMA_MONITOR_BUF: 761 htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING; 762 htt_ring_type = HTT_SW_TO_HW_RING; 763 break; 764 case RXDMA_MONITOR_STATUS: 765 htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING; 766 htt_ring_type = HTT_SW_TO_HW_RING; 767 break; 768 case RXDMA_MONITOR_DST: 769 htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING; 770 htt_ring_type = HTT_HW_TO_SW_RING; 771 break; 772 case RXDMA_MONITOR_DESC: 773 htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING; 774 htt_ring_type = HTT_SW_TO_HW_RING; 775 break; 776 case RXDMA_DST: 777 htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; 778 htt_ring_type = HTT_HW_TO_SW_RING; 779 break; 780 781 default: 782 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 783 "%s: Ring currently not supported\n", __func__); 784 goto fail1; 785 } 786 787 /* 788 * Set the length of the message. 789 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added 790 * separately during the below call to qdf_nbuf_push_head. 791 * The contribution from the HTC header is added separately inside HTC. 792 */ 793 if (qdf_nbuf_put_tail(htt_msg, HTT_RX_RING_SELECTION_CFG_SZ) == NULL) { 794 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 795 "%s: Failed to expand head for RX Ring Cfg msg\n", 796 __func__); 797 goto fail1; /* failure */ 798 } 799 800 msg_word = (uint32_t *)qdf_nbuf_data(htt_msg); 801 802 /* rewind beyond alignment pad to get to the HTC header reserved area */ 803 qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING); 804 805 /* word 0 */ 806 *msg_word = 0; 807 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG); 808 809 /* 810 * pdev_id is indexed from 0 whereas mac_id is indexed from 1 811 * SW_TO_SW and SW_TO_HW rings are unaffected by this 812 */ 813 if (htt_ring_type == HTT_SW_TO_SW_RING || 814 htt_ring_type == HTT_SW_TO_HW_RING) 815 HTT_RX_RING_SELECTION_CFG_PDEV_ID_SET(*msg_word, 816 DP_SW2HW_MACID(pdev_id)); 817 818 /* TODO: Discuss with FW on changing this to unique ID and using 819 * htt_ring_type to send the type of ring 820 */ 821 HTT_RX_RING_SELECTION_CFG_RING_ID_SET(*msg_word, htt_ring_id); 822 823 HTT_RX_RING_SELECTION_CFG_STATUS_TLV_SET(*msg_word, 824 !!(srng_params.flags & HAL_SRNG_MSI_SWAP)); 825 826 HTT_RX_RING_SELECTION_CFG_PKT_TLV_SET(*msg_word, 827 !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP)); 828 829 /* word 1 */ 830 msg_word++; 831 *msg_word = 0; 832 HTT_RX_RING_SELECTION_CFG_RING_BUFFER_SIZE_SET(*msg_word, 833 ring_buf_size); 834 835 /* word 2 */ 836 msg_word++; 837 *msg_word = 0; 838 839 if (htt_tlv_filter->enable_fp) { 840 /* TYPE: MGMT */ 841 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 842 FP, MGMT, 0000, 843 (htt_tlv_filter->fp_mgmt_filter & 844 FILTER_MGMT_ASSOC_REQ) ? 1 : 0); 845 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 846 FP, MGMT, 0001, 847 (htt_tlv_filter->fp_mgmt_filter & 848 FILTER_MGMT_ASSOC_RES) ? 1 : 0); 849 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 850 FP, MGMT, 0010, 851 (htt_tlv_filter->fp_mgmt_filter & 852 FILTER_MGMT_REASSOC_REQ) ? 1 : 0); 853 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 854 FP, MGMT, 0011, 855 (htt_tlv_filter->fp_mgmt_filter & 856 FILTER_MGMT_REASSOC_RES) ? 1 : 0); 857 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 858 FP, MGMT, 0100, 859 (htt_tlv_filter->fp_mgmt_filter & 860 FILTER_MGMT_PROBE_REQ) ? 1 : 0); 861 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 862 FP, MGMT, 0101, 863 (htt_tlv_filter->fp_mgmt_filter & 864 FILTER_MGMT_PROBE_RES) ? 1 : 0); 865 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 866 FP, MGMT, 0110, 867 (htt_tlv_filter->fp_mgmt_filter & 868 FILTER_MGMT_TIM_ADVT) ? 1 : 0); 869 /* reserved */ 870 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP, 871 MGMT, 0111, 872 (htt_tlv_filter->fp_mgmt_filter & 873 FILTER_MGMT_RESERVED_7) ? 1 : 0); 874 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 875 FP, MGMT, 1000, 876 (htt_tlv_filter->fp_mgmt_filter & 877 FILTER_MGMT_BEACON) ? 1 : 0); 878 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 879 FP, MGMT, 1001, 880 (htt_tlv_filter->fp_mgmt_filter & 881 FILTER_MGMT_ATIM) ? 1 : 0); 882 } 883 884 if (htt_tlv_filter->enable_md) { 885 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 886 MGMT, 0000, 1); 887 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 888 MGMT, 0001, 1); 889 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 890 MGMT, 0010, 1); 891 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 892 MGMT, 0011, 1); 893 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 894 MGMT, 0100, 1); 895 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 896 MGMT, 0101, 1); 897 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 898 MGMT, 0110, 1); 899 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 900 MGMT, 0111, 1); 901 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 902 MGMT, 1000, 1); 903 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD, 904 MGMT, 1001, 1); 905 } 906 907 if (htt_tlv_filter->enable_mo) { 908 /* TYPE: MGMT */ 909 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 910 MO, MGMT, 0000, 911 (htt_tlv_filter->mo_mgmt_filter & 912 FILTER_MGMT_ASSOC_REQ) ? 1 : 0); 913 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 914 MO, MGMT, 0001, 915 (htt_tlv_filter->mo_mgmt_filter & 916 FILTER_MGMT_ASSOC_RES) ? 1 : 0); 917 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 918 MO, MGMT, 0010, 919 (htt_tlv_filter->mo_mgmt_filter & 920 FILTER_MGMT_REASSOC_REQ) ? 1 : 0); 921 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 922 MO, MGMT, 0011, 923 (htt_tlv_filter->mo_mgmt_filter & 924 FILTER_MGMT_REASSOC_RES) ? 1 : 0); 925 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 926 MO, MGMT, 0100, 927 (htt_tlv_filter->mo_mgmt_filter & 928 FILTER_MGMT_PROBE_REQ) ? 1 : 0); 929 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 930 MO, MGMT, 0101, 931 (htt_tlv_filter->mo_mgmt_filter & 932 FILTER_MGMT_PROBE_RES) ? 1 : 0); 933 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 934 MO, MGMT, 0110, 935 (htt_tlv_filter->mo_mgmt_filter & 936 FILTER_MGMT_TIM_ADVT) ? 1 : 0); 937 /* reserved */ 938 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO, 939 MGMT, 0111, 940 (htt_tlv_filter->mo_mgmt_filter & 941 FILTER_MGMT_RESERVED_7) ? 1 : 0); 942 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 943 MO, MGMT, 1000, 944 (htt_tlv_filter->mo_mgmt_filter & 945 FILTER_MGMT_BEACON) ? 1 : 0); 946 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, 947 MO, MGMT, 1001, 948 (htt_tlv_filter->mo_mgmt_filter & 949 FILTER_MGMT_ATIM) ? 1 : 0); 950 } 951 952 /* word 3 */ 953 msg_word++; 954 *msg_word = 0; 955 956 if (htt_tlv_filter->enable_fp) { 957 /* TYPE: MGMT */ 958 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 959 FP, MGMT, 1010, 960 (htt_tlv_filter->fp_mgmt_filter & 961 FILTER_MGMT_DISASSOC) ? 1 : 0); 962 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 963 FP, MGMT, 1011, 964 (htt_tlv_filter->fp_mgmt_filter & 965 FILTER_MGMT_AUTH) ? 1 : 0); 966 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 967 FP, MGMT, 1100, 968 (htt_tlv_filter->fp_mgmt_filter & 969 FILTER_MGMT_DEAUTH) ? 1 : 0); 970 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 971 FP, MGMT, 1101, 972 (htt_tlv_filter->fp_mgmt_filter & 973 FILTER_MGMT_ACTION) ? 1 : 0); 974 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 975 FP, MGMT, 1110, 976 (htt_tlv_filter->fp_mgmt_filter & 977 FILTER_MGMT_ACT_NO_ACK) ? 1 : 0); 978 /* reserved*/ 979 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP, 980 MGMT, 1111, 981 (htt_tlv_filter->fp_mgmt_filter & 982 FILTER_MGMT_RESERVED_15) ? 1 : 0); 983 } 984 985 if (htt_tlv_filter->enable_md) { 986 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD, 987 MGMT, 1010, 1); 988 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD, 989 MGMT, 1011, 1); 990 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD, 991 MGMT, 1100, 1); 992 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD, 993 MGMT, 1101, 1); 994 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD, 995 MGMT, 1110, 1); 996 } 997 998 if (htt_tlv_filter->enable_mo) { 999 /* TYPE: MGMT */ 1000 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 1001 MO, MGMT, 1010, 1002 (htt_tlv_filter->mo_mgmt_filter & 1003 FILTER_MGMT_DISASSOC) ? 1 : 0); 1004 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 1005 MO, MGMT, 1011, 1006 (htt_tlv_filter->mo_mgmt_filter & 1007 FILTER_MGMT_AUTH) ? 1 : 0); 1008 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 1009 MO, MGMT, 1100, 1010 (htt_tlv_filter->mo_mgmt_filter & 1011 FILTER_MGMT_DEAUTH) ? 1 : 0); 1012 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 1013 MO, MGMT, 1101, 1014 (htt_tlv_filter->mo_mgmt_filter & 1015 FILTER_MGMT_ACTION) ? 1 : 0); 1016 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, 1017 MO, MGMT, 1110, 1018 (htt_tlv_filter->mo_mgmt_filter & 1019 FILTER_MGMT_ACT_NO_ACK) ? 1 : 0); 1020 /* reserved*/ 1021 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO, 1022 MGMT, 1111, 1023 (htt_tlv_filter->mo_mgmt_filter & 1024 FILTER_MGMT_RESERVED_15) ? 1 : 0); 1025 } 1026 1027 /* word 4 */ 1028 msg_word++; 1029 *msg_word = 0; 1030 1031 if (htt_tlv_filter->enable_fp) { 1032 /* TYPE: CTRL */ 1033 /* reserved */ 1034 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1035 CTRL, 0000, 1036 (htt_tlv_filter->fp_ctrl_filter & 1037 FILTER_CTRL_RESERVED_1) ? 1 : 0); 1038 /* reserved */ 1039 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1040 CTRL, 0001, 1041 (htt_tlv_filter->fp_ctrl_filter & 1042 FILTER_CTRL_RESERVED_2) ? 1 : 0); 1043 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1044 CTRL, 0010, 1045 (htt_tlv_filter->fp_ctrl_filter & 1046 FILTER_CTRL_TRIGGER) ? 1 : 0); 1047 /* reserved */ 1048 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1049 CTRL, 0011, 1050 (htt_tlv_filter->fp_ctrl_filter & 1051 FILTER_CTRL_RESERVED_4) ? 1 : 0); 1052 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1053 CTRL, 0100, 1054 (htt_tlv_filter->fp_ctrl_filter & 1055 FILTER_CTRL_BF_REP_POLL) ? 1 : 0); 1056 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1057 CTRL, 0101, 1058 (htt_tlv_filter->fp_ctrl_filter & 1059 FILTER_CTRL_VHT_NDP) ? 1 : 0); 1060 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1061 CTRL, 0110, 1062 (htt_tlv_filter->fp_ctrl_filter & 1063 FILTER_CTRL_FRAME_EXT) ? 1 : 0); 1064 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1065 CTRL, 0111, 1066 (htt_tlv_filter->fp_ctrl_filter & 1067 FILTER_CTRL_CTRLWRAP) ? 1 : 0); 1068 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1069 CTRL, 1000, 1070 (htt_tlv_filter->fp_ctrl_filter & 1071 FILTER_CTRL_BA_REQ) ? 1 : 0); 1072 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP, 1073 CTRL, 1001, 1074 (htt_tlv_filter->fp_ctrl_filter & 1075 FILTER_CTRL_BA) ? 1 : 0); 1076 } 1077 1078 if (htt_tlv_filter->enable_md) { 1079 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1080 CTRL, 0000, 1); 1081 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1082 CTRL, 0001, 1); 1083 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1084 CTRL, 0010, 1); 1085 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1086 CTRL, 0011, 1); 1087 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1088 CTRL, 0100, 1); 1089 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1090 CTRL, 0101, 1); 1091 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1092 CTRL, 0110, 1); 1093 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD, 1094 CTRL, 0111, 1); 1095 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD, 1096 CTRL, 1000, 1); 1097 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD, 1098 CTRL, 1001, 1); 1099 } 1100 1101 if (htt_tlv_filter->enable_mo) { 1102 /* TYPE: CTRL */ 1103 /* reserved */ 1104 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1105 CTRL, 0000, 1106 (htt_tlv_filter->mo_ctrl_filter & 1107 FILTER_CTRL_RESERVED_1) ? 1 : 0); 1108 /* reserved */ 1109 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1110 CTRL, 0001, 1111 (htt_tlv_filter->mo_ctrl_filter & 1112 FILTER_CTRL_RESERVED_2) ? 1 : 0); 1113 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1114 CTRL, 0010, 1115 (htt_tlv_filter->mo_ctrl_filter & 1116 FILTER_CTRL_TRIGGER) ? 1 : 0); 1117 /* reserved */ 1118 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1119 CTRL, 0011, 1120 (htt_tlv_filter->mo_ctrl_filter & 1121 FILTER_CTRL_RESERVED_4) ? 1 : 0); 1122 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1123 CTRL, 0100, 1124 (htt_tlv_filter->mo_ctrl_filter & 1125 FILTER_CTRL_BF_REP_POLL) ? 1 : 0); 1126 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1127 CTRL, 0101, 1128 (htt_tlv_filter->mo_ctrl_filter & 1129 FILTER_CTRL_VHT_NDP) ? 1 : 0); 1130 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1131 CTRL, 0110, 1132 (htt_tlv_filter->mo_ctrl_filter & 1133 FILTER_CTRL_FRAME_EXT) ? 1 : 0); 1134 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1135 CTRL, 0111, 1136 (htt_tlv_filter->mo_ctrl_filter & 1137 FILTER_CTRL_CTRLWRAP) ? 1 : 0); 1138 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1139 CTRL, 1000, 1140 (htt_tlv_filter->mo_ctrl_filter & 1141 FILTER_CTRL_BA_REQ) ? 1 : 0); 1142 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO, 1143 CTRL, 1001, 1144 (htt_tlv_filter->mo_ctrl_filter & 1145 FILTER_CTRL_BA) ? 1 : 0); 1146 } 1147 1148 /* word 5 */ 1149 msg_word++; 1150 *msg_word = 0; 1151 if (htt_tlv_filter->enable_fp) { 1152 /* TYPE: CTRL */ 1153 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1154 CTRL, 1010, 1155 (htt_tlv_filter->fp_ctrl_filter & 1156 FILTER_CTRL_PSPOLL) ? 1 : 0); 1157 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1158 CTRL, 1011, 1159 (htt_tlv_filter->fp_ctrl_filter & 1160 FILTER_CTRL_RTS) ? 1 : 0); 1161 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1162 CTRL, 1100, 1163 (htt_tlv_filter->fp_ctrl_filter & 1164 FILTER_CTRL_CTS) ? 1 : 0); 1165 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1166 CTRL, 1101, 1167 (htt_tlv_filter->fp_ctrl_filter & 1168 FILTER_CTRL_ACK) ? 1 : 0); 1169 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1170 CTRL, 1110, 1171 (htt_tlv_filter->fp_ctrl_filter & 1172 FILTER_CTRL_CFEND) ? 1 : 0); 1173 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1174 CTRL, 1111, 1175 (htt_tlv_filter->fp_ctrl_filter & 1176 FILTER_CTRL_CFEND_CFACK) ? 1 : 0); 1177 /* TYPE: DATA */ 1178 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1179 DATA, MCAST, 1180 (htt_tlv_filter->fp_data_filter & 1181 FILTER_DATA_MCAST) ? 1 : 0); 1182 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1183 DATA, UCAST, 1184 (htt_tlv_filter->fp_data_filter & 1185 FILTER_DATA_UCAST) ? 1 : 0); 1186 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP, 1187 DATA, NULL, 1188 (htt_tlv_filter->fp_data_filter & 1189 FILTER_DATA_NULL) ? 1 : 0); 1190 } 1191 1192 if (htt_tlv_filter->enable_md) { 1193 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1194 CTRL, 1010, 1); 1195 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1196 CTRL, 1011, 1); 1197 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1198 CTRL, 1100, 1); 1199 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1200 CTRL, 1101, 1); 1201 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1202 CTRL, 1110, 1); 1203 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1204 CTRL, 1111, 1); 1205 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1206 DATA, MCAST, 1); 1207 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1208 DATA, UCAST, 1); 1209 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD, 1210 DATA, NULL, 1); 1211 } 1212 1213 if (htt_tlv_filter->enable_mo) { 1214 /* TYPE: CTRL */ 1215 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1216 CTRL, 1010, 1217 (htt_tlv_filter->mo_ctrl_filter & 1218 FILTER_CTRL_PSPOLL) ? 1 : 0); 1219 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1220 CTRL, 1011, 1221 (htt_tlv_filter->mo_ctrl_filter & 1222 FILTER_CTRL_RTS) ? 1 : 0); 1223 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1224 CTRL, 1100, 1225 (htt_tlv_filter->mo_ctrl_filter & 1226 FILTER_CTRL_CTS) ? 1 : 0); 1227 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1228 CTRL, 1101, 1229 (htt_tlv_filter->mo_ctrl_filter & 1230 FILTER_CTRL_ACK) ? 1 : 0); 1231 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1232 CTRL, 1110, 1233 (htt_tlv_filter->mo_ctrl_filter & 1234 FILTER_CTRL_CFEND) ? 1 : 0); 1235 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1236 CTRL, 1111, 1237 (htt_tlv_filter->mo_ctrl_filter & 1238 FILTER_CTRL_CFEND_CFACK) ? 1 : 0); 1239 /* TYPE: DATA */ 1240 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1241 DATA, MCAST, 1242 (htt_tlv_filter->mo_data_filter & 1243 FILTER_DATA_MCAST) ? 1 : 0); 1244 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1245 DATA, UCAST, 1246 (htt_tlv_filter->mo_data_filter & 1247 FILTER_DATA_UCAST) ? 1 : 0); 1248 htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO, 1249 DATA, NULL, 1250 (htt_tlv_filter->mo_data_filter & 1251 FILTER_DATA_NULL) ? 1 : 0); 1252 } 1253 1254 /* word 6 */ 1255 msg_word++; 1256 *msg_word = 0; 1257 tlv_filter = 0; 1258 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_START, 1259 htt_tlv_filter->mpdu_start); 1260 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_START, 1261 htt_tlv_filter->msdu_start); 1262 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET, 1263 htt_tlv_filter->packet); 1264 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_END, 1265 htt_tlv_filter->msdu_end); 1266 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_END, 1267 htt_tlv_filter->mpdu_end); 1268 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET_HEADER, 1269 htt_tlv_filter->packet_header); 1270 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, ATTENTION, 1271 htt_tlv_filter->attention); 1272 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START, 1273 htt_tlv_filter->ppdu_start); 1274 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END, 1275 htt_tlv_filter->ppdu_end); 1276 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_USER_STATS, 1277 htt_tlv_filter->ppdu_end_user_stats); 1278 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, 1279 PPDU_END_USER_STATS_EXT, 1280 htt_tlv_filter->ppdu_end_user_stats_ext); 1281 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_STATUS_DONE, 1282 htt_tlv_filter->ppdu_end_status_done); 1283 /* RESERVED bit maps to header_per_msdu in htt_tlv_filter*/ 1284 htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, RESERVED, 1285 htt_tlv_filter->header_per_msdu); 1286 1287 HTT_RX_RING_SELECTION_CFG_TLV_FILTER_IN_FLAG_SET(*msg_word, tlv_filter); 1288 1289 /* "response_required" field should be set if a HTT response message is 1290 * required after setting up the ring. 1291 */ 1292 pkt = htt_htc_pkt_alloc(soc); 1293 if (!pkt) 1294 goto fail1; 1295 1296 pkt->soc_ctxt = NULL; /* not used during send-done callback */ 1297 1298 SET_HTC_PACKET_INFO_TX( 1299 &pkt->htc_pkt, 1300 dp_htt_h2t_send_complete_free_netbuf, 1301 qdf_nbuf_data(htt_msg), 1302 qdf_nbuf_len(htt_msg), 1303 soc->htc_endpoint, 1304 1); /* tag - not relevant here */ 1305 1306 SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg); 1307 DP_HTT_SEND_HTC_PKT(soc, pkt); 1308 return QDF_STATUS_SUCCESS; 1309 1310 fail1: 1311 qdf_nbuf_free(htt_msg); 1312 fail0: 1313 return QDF_STATUS_E_FAILURE; 1314 } 1315 1316 #if defined(CONFIG_WIN) && WDI_EVENT_ENABLE 1317 static inline QDF_STATUS dp_send_htt_stat_resp(struct htt_stats_context *htt_stats, 1318 struct dp_soc *soc, qdf_nbuf_t htt_msg) 1319 1320 { 1321 uint32_t pdev_id; 1322 uint32_t *msg_word = NULL; 1323 uint32_t msg_remain_len = 0; 1324 1325 msg_word = (uint32_t *) qdf_nbuf_data(htt_msg); 1326 1327 /*COOKIE MSB*/ 1328 pdev_id = *(msg_word + 2) & HTT_PID_BIT_MASK; 1329 1330 /* stats message length + 16 size of HTT header*/ 1331 msg_remain_len = qdf_min(htt_stats->msg_len + 16, 1332 (uint32_t)DP_EXT_MSG_LENGTH); 1333 1334 dp_wdi_event_handler(WDI_EVENT_HTT_STATS, soc, 1335 msg_word, msg_remain_len, 1336 WDI_NO_VAL, pdev_id); 1337 1338 if (htt_stats->msg_len >= DP_EXT_MSG_LENGTH) { 1339 htt_stats->msg_len -= DP_EXT_MSG_LENGTH; 1340 } 1341 /* Need to be freed here as WDI handler will 1342 * make a copy of pkt to send data to application 1343 */ 1344 qdf_nbuf_free(htt_msg); 1345 return QDF_STATUS_SUCCESS; 1346 } 1347 #else 1348 static inline QDF_STATUS dp_send_htt_stat_resp(struct htt_stats_context *htt_stats, 1349 struct dp_soc *soc, qdf_nbuf_t htt_msg) 1350 { 1351 return QDF_STATUS_E_NOSUPPORT; 1352 } 1353 #endif 1354 1355 /** 1356 * dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats 1357 * @htt_stats: htt stats info 1358 * 1359 * The FW sends the HTT EXT STATS as a stream of T2H messages. Each T2H message 1360 * contains sub messages which are identified by a TLV header. 1361 * In this function we will process the stream of T2H messages and read all the 1362 * TLV contained in the message. 1363 * 1364 * THe following cases have been taken care of 1365 * Case 1: When the tlv_remain_length <= msg_remain_length of HTT MSG buffer 1366 * In this case the buffer will contain multiple tlvs. 1367 * Case 2: When the tlv_remain_length > msg_remain_length of HTT MSG buffer. 1368 * Only one tlv will be contained in the HTT message and this tag 1369 * will extend onto the next buffer. 1370 * Case 3: When the buffer is the continuation of the previous message 1371 * Case 4: tlv length is 0. which will indicate the end of message 1372 * 1373 * return: void 1374 */ 1375 static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats, 1376 struct dp_soc *soc) 1377 { 1378 htt_tlv_tag_t tlv_type = 0xff; 1379 qdf_nbuf_t htt_msg = NULL; 1380 uint32_t *msg_word; 1381 uint8_t *tlv_buf_head = NULL; 1382 uint8_t *tlv_buf_tail = NULL; 1383 uint32_t msg_remain_len = 0; 1384 uint32_t tlv_remain_len = 0; 1385 uint32_t *tlv_start; 1386 int cookie_val; 1387 int cookie_msb; 1388 int pdev_id; 1389 bool copy_stats = false; 1390 struct dp_pdev *pdev; 1391 1392 /* Process node in the HTT message queue */ 1393 while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg)) 1394 != NULL) { 1395 msg_word = (uint32_t *) qdf_nbuf_data(htt_msg); 1396 cookie_val = *(msg_word + 1); 1397 if (cookie_val) { 1398 if (dp_send_htt_stat_resp(htt_stats, soc, htt_msg) 1399 == QDF_STATUS_SUCCESS) { 1400 continue; 1401 } 1402 } 1403 cookie_msb = *(msg_word + 2); 1404 pdev_id = *(msg_word + 2) & HTT_PID_BIT_MASK; 1405 pdev = soc->pdev_list[pdev_id]; 1406 1407 if (cookie_msb >> 2) { 1408 copy_stats = true; 1409 } 1410 /* read 5th word */ 1411 msg_word = msg_word + 4; 1412 msg_remain_len = qdf_min(htt_stats->msg_len, 1413 (uint32_t) DP_EXT_MSG_LENGTH); 1414 /* Keep processing the node till node length is 0 */ 1415 while (msg_remain_len) { 1416 /* 1417 * if message is not a continuation of previous message 1418 * read the tlv type and tlv length 1419 */ 1420 if (!tlv_buf_head) { 1421 tlv_type = HTT_STATS_TLV_TAG_GET( 1422 *msg_word); 1423 tlv_remain_len = HTT_STATS_TLV_LENGTH_GET( 1424 *msg_word); 1425 } 1426 1427 if (tlv_remain_len == 0) { 1428 msg_remain_len = 0; 1429 1430 if (tlv_buf_head) { 1431 qdf_mem_free(tlv_buf_head); 1432 tlv_buf_head = NULL; 1433 tlv_buf_tail = NULL; 1434 } 1435 1436 goto error; 1437 } 1438 1439 if (!tlv_buf_head) 1440 tlv_remain_len += HTT_TLV_HDR_LEN; 1441 1442 if ((tlv_remain_len <= msg_remain_len)) { 1443 /* Case 3 */ 1444 if (tlv_buf_head) { 1445 qdf_mem_copy(tlv_buf_tail, 1446 (uint8_t *)msg_word, 1447 tlv_remain_len); 1448 tlv_start = (uint32_t *)tlv_buf_head; 1449 } else { 1450 /* Case 1 */ 1451 tlv_start = msg_word; 1452 } 1453 1454 if (copy_stats) 1455 dp_htt_stats_copy_tag(pdev, tlv_type, tlv_start); 1456 else 1457 dp_htt_stats_print_tag(tlv_type, tlv_start); 1458 1459 msg_remain_len -= tlv_remain_len; 1460 1461 msg_word = (uint32_t *) 1462 (((uint8_t *)msg_word) + 1463 tlv_remain_len); 1464 1465 tlv_remain_len = 0; 1466 1467 if (tlv_buf_head) { 1468 qdf_mem_free(tlv_buf_head); 1469 tlv_buf_head = NULL; 1470 tlv_buf_tail = NULL; 1471 } 1472 1473 } else { /* tlv_remain_len > msg_remain_len */ 1474 /* Case 2 & 3 */ 1475 if (!tlv_buf_head) { 1476 tlv_buf_head = qdf_mem_malloc( 1477 tlv_remain_len); 1478 1479 if (!tlv_buf_head) { 1480 QDF_TRACE(QDF_MODULE_ID_TXRX, 1481 QDF_TRACE_LEVEL_ERROR, 1482 "Alloc failed"); 1483 goto error; 1484 } 1485 1486 tlv_buf_tail = tlv_buf_head; 1487 } 1488 1489 qdf_mem_copy(tlv_buf_tail, (uint8_t *)msg_word, 1490 msg_remain_len); 1491 tlv_remain_len -= msg_remain_len; 1492 tlv_buf_tail += msg_remain_len; 1493 } 1494 } 1495 1496 if (htt_stats->msg_len >= DP_EXT_MSG_LENGTH) { 1497 htt_stats->msg_len -= DP_EXT_MSG_LENGTH; 1498 } 1499 1500 qdf_nbuf_free(htt_msg); 1501 } 1502 return; 1503 1504 error: 1505 qdf_nbuf_free(htt_msg); 1506 while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg)) 1507 != NULL) 1508 qdf_nbuf_free(htt_msg); 1509 } 1510 1511 void htt_t2h_stats_handler(void *context) 1512 { 1513 struct dp_soc *soc = (struct dp_soc *)context; 1514 struct htt_stats_context htt_stats; 1515 uint32_t length; 1516 uint32_t *msg_word; 1517 qdf_nbuf_t htt_msg = NULL; 1518 uint8_t done; 1519 uint8_t rem_stats; 1520 1521 if (!soc || !qdf_atomic_read(&soc->cmn_init_done)) { 1522 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 1523 "soc: 0x%pK, init_done: %d", soc, 1524 qdf_atomic_read(&soc->cmn_init_done)); 1525 return; 1526 } 1527 1528 qdf_mem_zero(&htt_stats, sizeof(htt_stats)); 1529 qdf_nbuf_queue_init(&htt_stats.msg); 1530 1531 /* pull one completed stats from soc->htt_stats_msg and process */ 1532 qdf_spin_lock_bh(&soc->htt_stats.lock); 1533 if (!soc->htt_stats.num_stats) { 1534 qdf_spin_unlock_bh(&soc->htt_stats.lock); 1535 return; 1536 } 1537 while ((htt_msg = qdf_nbuf_queue_remove(&soc->htt_stats.msg)) != NULL) { 1538 msg_word = (uint32_t *) qdf_nbuf_data(htt_msg); 1539 msg_word = msg_word + HTT_T2H_EXT_STATS_TLV_START_OFFSET; 1540 length = HTT_T2H_EXT_STATS_CONF_TLV_LENGTH_GET(*msg_word); 1541 done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word); 1542 qdf_nbuf_queue_add(&htt_stats.msg, htt_msg); 1543 /* 1544 * HTT EXT stats response comes as stream of TLVs which span over 1545 * multiple T2H messages. 1546 * The first message will carry length of the response. 1547 * For rest of the messages length will be zero. 1548 */ 1549 if (length) 1550 htt_stats.msg_len = length; 1551 /* 1552 * Done bit signifies that this is the last T2H buffer in the 1553 * stream of HTT EXT STATS message 1554 */ 1555 if (done) 1556 break; 1557 } 1558 rem_stats = --soc->htt_stats.num_stats; 1559 qdf_spin_unlock_bh(&soc->htt_stats.lock); 1560 1561 dp_process_htt_stat_msg(&htt_stats, soc); 1562 /* If there are more stats to process, schedule stats work again */ 1563 if (rem_stats) 1564 qdf_sched_work(0, &soc->htt_stats.work); 1565 } 1566 1567 /* 1568 * dp_get_ppdu_info_user_index: Find and allocate a per-user descriptor for a PPDU, 1569 * if a new peer id arrives in a PPDU 1570 * pdev: DP pdev handle 1571 * @peer_id : peer unique identifier 1572 * @ppdu_info: per ppdu tlv structure 1573 * 1574 * return:user index to be populated 1575 */ 1576 #ifdef FEATURE_PERPKT_INFO 1577 static uint8_t dp_get_ppdu_info_user_index(struct dp_pdev *pdev, 1578 uint16_t peer_id, 1579 struct ppdu_info *ppdu_info) 1580 { 1581 uint8_t user_index = 0; 1582 struct cdp_tx_completion_ppdu *ppdu_desc; 1583 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1584 1585 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1586 1587 while ((user_index + 1) <= ppdu_info->last_user) { 1588 ppdu_user_desc = &ppdu_desc->user[user_index]; 1589 if (ppdu_user_desc->peer_id != peer_id) { 1590 user_index++; 1591 continue; 1592 } else { 1593 /* Max users possible is 8 so user array index should 1594 * not exceed 7 1595 */ 1596 qdf_assert_always(user_index <= CDP_MU_MAX_USER_INDEX); 1597 return user_index; 1598 } 1599 } 1600 1601 ppdu_info->last_user++; 1602 /* Max users possible is 8 so last user should not exceed 8 */ 1603 qdf_assert_always(ppdu_info->last_user <= CDP_MU_MAX_USERS); 1604 return ppdu_info->last_user - 1; 1605 } 1606 1607 /* 1608 * dp_process_ppdu_stats_common_tlv: Process htt_ppdu_stats_common_tlv 1609 * pdev: DP pdev handle 1610 * @tag_buf: buffer containing the tlv htt_ppdu_stats_common_tlv 1611 * @ppdu_info: per ppdu tlv structure 1612 * 1613 * return:void 1614 */ 1615 static void dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev, 1616 uint32_t *tag_buf, struct ppdu_info *ppdu_info) 1617 { 1618 uint16_t frame_type; 1619 uint16_t freq; 1620 struct dp_soc *soc = NULL; 1621 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 1622 1623 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1624 1625 tag_buf += 2; 1626 ppdu_desc->num_users = 1627 HTT_PPDU_STATS_COMMON_TLV_NUM_USERS_GET(*tag_buf); 1628 tag_buf++; 1629 frame_type = HTT_PPDU_STATS_COMMON_TLV_FRM_TYPE_GET(*tag_buf); 1630 1631 if ((frame_type == HTT_STATS_FTYPE_TIDQ_DATA_SU) || 1632 (frame_type == HTT_STATS_FTYPE_TIDQ_DATA_MU)) 1633 ppdu_desc->frame_type = CDP_PPDU_FTYPE_DATA; 1634 else 1635 ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; 1636 1637 tag_buf += 2; 1638 ppdu_desc->tx_duration = *tag_buf; 1639 tag_buf += 3; 1640 ppdu_desc->ppdu_start_timestamp = *tag_buf; 1641 1642 ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + 1643 ppdu_desc->tx_duration; 1644 1645 tag_buf++; 1646 1647 freq = HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_GET(*tag_buf); 1648 if (freq != ppdu_desc->channel) { 1649 soc = pdev->soc; 1650 ppdu_desc->channel = freq; 1651 if (soc && soc->cdp_soc.ol_ops->freq_to_channel) 1652 pdev->operating_channel = 1653 soc->cdp_soc.ol_ops->freq_to_channel(pdev->osif_pdev, freq); 1654 } 1655 1656 ppdu_desc->phy_mode = HTT_PPDU_STATS_COMMON_TLV_PHY_MODE_GET(*tag_buf); 1657 } 1658 1659 /* 1660 * dp_process_ppdu_stats_user_common_tlv: Process ppdu_stats_user_common 1661 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_common_tlv 1662 * @ppdu_info: per ppdu tlv structure 1663 * 1664 * return:void 1665 */ 1666 static void dp_process_ppdu_stats_user_common_tlv( 1667 struct dp_pdev *pdev, uint32_t *tag_buf, 1668 struct ppdu_info *ppdu_info) 1669 { 1670 uint16_t peer_id; 1671 struct dp_peer *peer; 1672 struct cdp_tx_completion_ppdu *ppdu_desc; 1673 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1674 uint8_t curr_user_index = 0; 1675 1676 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1677 1678 tag_buf++; 1679 peer_id = HTT_PPDU_STATS_USER_COMMON_TLV_SW_PEER_ID_GET(*tag_buf); 1680 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1681 1682 if (!peer) 1683 return; 1684 1685 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1686 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1687 1688 ppdu_user_desc->peer_id = peer_id; 1689 1690 tag_buf++; 1691 1692 if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf)) { 1693 ppdu_user_desc->is_mcast = true; 1694 ppdu_user_desc->mpdu_tried_mcast = 1695 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 1696 } else { 1697 ppdu_user_desc->mpdu_tried_ucast = 1698 HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf); 1699 } 1700 1701 tag_buf++; 1702 1703 ppdu_user_desc->qos_ctrl = 1704 HTT_PPDU_STATS_USER_COMMON_TLV_QOS_CTRL_GET(*tag_buf); 1705 ppdu_user_desc->frame_ctrl = 1706 HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf); 1707 ppdu_desc->frame_ctrl = ppdu_user_desc->frame_ctrl; 1708 } 1709 1710 1711 /** 1712 * dp_process_ppdu_stats_user_rate_tlv() - Process htt_ppdu_stats_user_rate_tlv 1713 * @pdev: DP pdev handle 1714 * @tag_buf: T2H message buffer carrying the user rate TLV 1715 * @ppdu_info: per ppdu tlv structure 1716 * 1717 * return:void 1718 */ 1719 static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev, 1720 uint32_t *tag_buf, 1721 struct ppdu_info *ppdu_info) 1722 { 1723 uint16_t peer_id; 1724 struct dp_peer *peer; 1725 struct cdp_tx_completion_ppdu *ppdu_desc; 1726 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1727 uint8_t curr_user_index = 0; 1728 1729 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1730 1731 tag_buf++; 1732 peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf); 1733 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1734 1735 if (!peer) 1736 return; 1737 1738 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1739 1740 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1741 ppdu_user_desc->peer_id = peer_id; 1742 1743 ppdu_user_desc->tid = 1744 HTT_PPDU_STATS_USER_RATE_TLV_TID_NUM_GET(*tag_buf); 1745 1746 qdf_mem_copy(ppdu_user_desc->mac_addr, peer->mac_addr.raw, 1747 DP_MAC_ADDR_LEN); 1748 1749 tag_buf += 2; 1750 1751 ppdu_user_desc->ru_tones = (HTT_PPDU_STATS_USER_RATE_TLV_RU_END_GET(*tag_buf) - 1752 HTT_PPDU_STATS_USER_RATE_TLV_RU_START_GET(*tag_buf)) + 1; 1753 1754 tag_buf += 2; 1755 1756 ppdu_user_desc->ppdu_type = 1757 HTT_PPDU_STATS_USER_RATE_TLV_PPDU_TYPE_GET(*tag_buf); 1758 1759 tag_buf++; 1760 ppdu_user_desc->tx_rate = *tag_buf; 1761 1762 ppdu_user_desc->ltf_size = 1763 HTT_PPDU_STATS_USER_RATE_TLV_LTF_SIZE_GET(*tag_buf); 1764 ppdu_user_desc->stbc = 1765 HTT_PPDU_STATS_USER_RATE_TLV_STBC_GET(*tag_buf); 1766 ppdu_user_desc->he_re = 1767 HTT_PPDU_STATS_USER_RATE_TLV_HE_RE_GET(*tag_buf); 1768 ppdu_user_desc->txbf = 1769 HTT_PPDU_STATS_USER_RATE_TLV_TXBF_GET(*tag_buf); 1770 ppdu_user_desc->bw = 1771 HTT_PPDU_STATS_USER_RATE_TLV_BW_GET(*tag_buf); 1772 ppdu_user_desc->nss = HTT_PPDU_STATS_USER_RATE_TLV_NSS_GET(*tag_buf); 1773 ppdu_user_desc->mcs = HTT_PPDU_STATS_USER_RATE_TLV_MCS_GET(*tag_buf); 1774 ppdu_user_desc->preamble = 1775 HTT_PPDU_STATS_USER_RATE_TLV_PREAMBLE_GET(*tag_buf); 1776 ppdu_user_desc->gi = HTT_PPDU_STATS_USER_RATE_TLV_GI_GET(*tag_buf); 1777 ppdu_user_desc->dcm = HTT_PPDU_STATS_USER_RATE_TLV_DCM_GET(*tag_buf); 1778 ppdu_user_desc->ldpc = HTT_PPDU_STATS_USER_RATE_TLV_LDPC_GET(*tag_buf); 1779 } 1780 1781 /* 1782 * dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv: Process 1783 * htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 1784 * pdev: DP PDEV handle 1785 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_64_tlv 1786 * @ppdu_info: per ppdu tlv structure 1787 * 1788 * return:void 1789 */ 1790 static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 1791 struct dp_pdev *pdev, uint32_t *tag_buf, 1792 struct ppdu_info *ppdu_info) 1793 { 1794 htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *dp_stats_buf = 1795 (htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *)tag_buf; 1796 1797 struct cdp_tx_completion_ppdu *ppdu_desc; 1798 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1799 uint8_t curr_user_index = 0; 1800 uint16_t peer_id; 1801 struct dp_peer *peer; 1802 1803 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1804 1805 tag_buf++; 1806 1807 peer_id = 1808 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 1809 1810 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1811 1812 if (!peer) 1813 return; 1814 1815 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1816 1817 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1818 ppdu_user_desc->peer_id = peer_id; 1819 1820 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 1821 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 1822 CDP_BA_64_BIT_MAP_SIZE_DWORDS); 1823 } 1824 1825 /* 1826 * dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv: Process 1827 * htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 1828 * soc: DP SOC handle 1829 * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_256_tlv 1830 * @ppdu_info: per ppdu tlv structure 1831 * 1832 * return:void 1833 */ 1834 static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 1835 struct dp_pdev *pdev, uint32_t *tag_buf, 1836 struct ppdu_info *ppdu_info) 1837 { 1838 htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *dp_stats_buf = 1839 (htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *)tag_buf; 1840 1841 struct cdp_tx_completion_ppdu *ppdu_desc; 1842 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1843 uint8_t curr_user_index = 0; 1844 uint16_t peer_id; 1845 struct dp_peer *peer; 1846 1847 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1848 1849 tag_buf++; 1850 1851 peer_id = 1852 HTT_PPDU_STATS_ENQ_MPDU_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 1853 1854 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1855 1856 if (!peer) 1857 return; 1858 1859 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1860 1861 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1862 ppdu_user_desc->peer_id = peer_id; 1863 1864 ppdu_user_desc->start_seq = dp_stats_buf->start_seq; 1865 qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap, 1866 CDP_BA_256_BIT_MAP_SIZE_DWORDS); 1867 } 1868 1869 /* 1870 * dp_process_ppdu_stats_user_cmpltn_common_tlv: Process 1871 * htt_ppdu_stats_user_cmpltn_common_tlv 1872 * soc: DP SOC handle 1873 * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_cmpltn_common_tlv 1874 * @ppdu_info: per ppdu tlv structure 1875 * 1876 * return:void 1877 */ 1878 static void dp_process_ppdu_stats_user_cmpltn_common_tlv( 1879 struct dp_pdev *pdev, uint32_t *tag_buf, 1880 struct ppdu_info *ppdu_info) 1881 { 1882 uint16_t peer_id; 1883 struct dp_peer *peer; 1884 struct cdp_tx_completion_ppdu *ppdu_desc; 1885 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1886 uint8_t curr_user_index = 0; 1887 htt_ppdu_stats_user_cmpltn_common_tlv *dp_stats_buf = 1888 (htt_ppdu_stats_user_cmpltn_common_tlv *)tag_buf; 1889 1890 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1891 1892 tag_buf++; 1893 peer_id = 1894 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf); 1895 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1896 1897 if (!peer) 1898 return; 1899 1900 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1901 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1902 ppdu_user_desc->peer_id = peer_id; 1903 1904 ppdu_user_desc->completion_status = 1905 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_COMPLETION_STATUS_GET( 1906 *tag_buf); 1907 1908 ppdu_user_desc->tid = 1909 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TID_NUM_GET(*tag_buf); 1910 1911 1912 tag_buf++; 1913 ppdu_desc->ack_rssi = dp_stats_buf->ack_rssi; 1914 1915 tag_buf++; 1916 1917 ppdu_user_desc->mpdu_success = 1918 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_SUCCESS_GET(*tag_buf); 1919 1920 tag_buf++; 1921 1922 ppdu_user_desc->long_retries = 1923 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_LONG_RETRY_GET(*tag_buf); 1924 1925 ppdu_user_desc->short_retries = 1926 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SHORT_RETRY_GET(*tag_buf); 1927 ppdu_user_desc->retry_msdus = 1928 ppdu_user_desc->long_retries + ppdu_user_desc->short_retries; 1929 1930 ppdu_user_desc->is_ampdu = 1931 HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf); 1932 ppdu_info->is_ampdu = ppdu_user_desc->is_ampdu; 1933 1934 } 1935 1936 /* 1937 * dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv: Process 1938 * htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 1939 * pdev: DP PDEV handle 1940 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv 1941 * @ppdu_info: per ppdu tlv structure 1942 * 1943 * return:void 1944 */ 1945 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 1946 struct dp_pdev *pdev, uint32_t *tag_buf, 1947 struct ppdu_info *ppdu_info) 1948 { 1949 htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *dp_stats_buf = 1950 (htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *)tag_buf; 1951 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1952 struct cdp_tx_completion_ppdu *ppdu_desc; 1953 uint8_t curr_user_index = 0; 1954 uint16_t peer_id; 1955 struct dp_peer *peer; 1956 1957 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 1958 1959 tag_buf++; 1960 1961 peer_id = 1962 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 1963 1964 peer = dp_peer_find_by_id(pdev->soc, peer_id); 1965 1966 if (!peer) 1967 return; 1968 1969 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 1970 1971 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 1972 ppdu_user_desc->peer_id = peer_id; 1973 1974 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 1975 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 1976 CDP_BA_64_BIT_MAP_SIZE_DWORDS); 1977 } 1978 1979 /* 1980 * dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv: Process 1981 * htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 1982 * pdev: DP PDEV handle 1983 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv 1984 * @ppdu_info: per ppdu tlv structure 1985 * 1986 * return:void 1987 */ 1988 static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 1989 struct dp_pdev *pdev, uint32_t *tag_buf, 1990 struct ppdu_info *ppdu_info) 1991 { 1992 htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *dp_stats_buf = 1993 (htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *)tag_buf; 1994 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 1995 struct cdp_tx_completion_ppdu *ppdu_desc; 1996 uint8_t curr_user_index = 0; 1997 uint16_t peer_id; 1998 struct dp_peer *peer; 1999 2000 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 2001 2002 tag_buf++; 2003 2004 peer_id = 2005 HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf); 2006 2007 peer = dp_peer_find_by_id(pdev->soc, peer_id); 2008 2009 if (!peer) 2010 return; 2011 2012 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 2013 2014 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 2015 ppdu_user_desc->peer_id = peer_id; 2016 2017 ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; 2018 qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, 2019 CDP_BA_256_BIT_MAP_SIZE_DWORDS); 2020 } 2021 2022 /* 2023 * dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv: Process 2024 * htt_ppdu_stats_user_compltn_ack_ba_status_tlv 2025 * pdev: DP PDE handle 2026 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 2027 * @ppdu_info: per ppdu tlv structure 2028 * 2029 * return:void 2030 */ 2031 static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 2032 struct dp_pdev *pdev, uint32_t *tag_buf, 2033 struct ppdu_info *ppdu_info) 2034 { 2035 uint16_t peer_id; 2036 struct dp_peer *peer; 2037 struct cdp_tx_completion_ppdu *ppdu_desc; 2038 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 2039 uint8_t curr_user_index = 0; 2040 2041 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 2042 2043 tag_buf += 2; 2044 peer_id = 2045 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf); 2046 2047 2048 peer = dp_peer_find_by_id(pdev->soc, peer_id); 2049 2050 if (!peer) 2051 return; 2052 2053 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 2054 2055 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 2056 ppdu_user_desc->peer_id = peer_id; 2057 2058 tag_buf++; 2059 ppdu_user_desc->tid = 2060 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_TID_NUM_GET(*tag_buf); 2061 ppdu_user_desc->num_mpdu = 2062 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MPDU_GET(*tag_buf); 2063 2064 ppdu_user_desc->num_msdu = 2065 HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MSDU_GET(*tag_buf); 2066 2067 ppdu_user_desc->success_msdus = ppdu_user_desc->num_msdu; 2068 2069 tag_buf += 2; 2070 ppdu_user_desc->success_bytes = *tag_buf; 2071 2072 } 2073 2074 /* 2075 * dp_process_ppdu_stats_user_common_array_tlv: Process 2076 * htt_ppdu_stats_user_common_array_tlv 2077 * pdev: DP PDEV handle 2078 * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv 2079 * @ppdu_info: per ppdu tlv structure 2080 * 2081 * return:void 2082 */ 2083 static void dp_process_ppdu_stats_user_common_array_tlv( 2084 struct dp_pdev *pdev, uint32_t *tag_buf, 2085 struct ppdu_info *ppdu_info) 2086 { 2087 uint32_t peer_id; 2088 struct dp_peer *peer; 2089 struct cdp_tx_completion_ppdu *ppdu_desc; 2090 struct cdp_tx_completion_ppdu_user *ppdu_user_desc; 2091 uint8_t curr_user_index = 0; 2092 struct htt_tx_ppdu_stats_info *dp_stats_buf; 2093 2094 ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); 2095 2096 tag_buf++; 2097 dp_stats_buf = (struct htt_tx_ppdu_stats_info *)tag_buf; 2098 tag_buf += 3; 2099 peer_id = 2100 HTT_PPDU_STATS_ARRAY_ITEM_TLV_PEERID_GET(*tag_buf); 2101 2102 peer = dp_peer_find_by_id(pdev->soc, peer_id); 2103 2104 if (!peer) { 2105 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2106 "Invalid peer"); 2107 return; 2108 } 2109 2110 curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id, ppdu_info); 2111 2112 ppdu_user_desc = &ppdu_desc->user[curr_user_index]; 2113 2114 ppdu_user_desc->retry_bytes = dp_stats_buf->tx_retry_bytes; 2115 ppdu_user_desc->failed_bytes = dp_stats_buf->tx_failed_bytes; 2116 2117 tag_buf++; 2118 2119 ppdu_user_desc->success_msdus = 2120 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_SUCC_MSDUS_GET(*tag_buf); 2121 ppdu_user_desc->retry_bytes = 2122 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_RETRY_MSDUS_GET(*tag_buf); 2123 tag_buf++; 2124 ppdu_user_desc->failed_msdus = 2125 HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_FAILED_MSDUS_GET(*tag_buf); 2126 } 2127 2128 /* 2129 * dp_process_ppdu_stats_flush_tlv: Process 2130 * htt_ppdu_stats_flush_tlv 2131 * @pdev: DP PDEV handle 2132 * @tag_buf: buffer containing the htt_ppdu_stats_flush_tlv 2133 * 2134 * return:void 2135 */ 2136 static void dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, 2137 uint32_t *tag_buf) 2138 { 2139 uint32_t peer_id; 2140 uint32_t drop_reason; 2141 uint8_t tid; 2142 uint32_t num_msdu; 2143 struct dp_peer *peer; 2144 2145 tag_buf++; 2146 drop_reason = *tag_buf; 2147 2148 tag_buf++; 2149 num_msdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MSDU_GET(*tag_buf); 2150 2151 tag_buf++; 2152 peer_id = 2153 HTT_PPDU_STATS_FLUSH_TLV_SW_PEER_ID_GET(*tag_buf); 2154 2155 peer = dp_peer_find_by_id(pdev->soc, peer_id); 2156 if (!peer) 2157 return; 2158 2159 tid = HTT_PPDU_STATS_FLUSH_TLV_TID_NUM_GET(*tag_buf); 2160 2161 if (drop_reason == HTT_FLUSH_EXCESS_RETRIES) { 2162 DP_STATS_INC(peer, tx.excess_retries_per_ac[TID_TO_WME_AC(tid)], 2163 num_msdu); 2164 } 2165 } 2166 2167 /* 2168 * dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv: Process 2169 * htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2170 * @pdev: DP PDEV handle 2171 * @tag_buf: buffer containing the htt_ppdu_stats_tx_mgmtctrl_payload_tlv 2172 * @length: tlv_length 2173 * 2174 * return:void 2175 */ 2176 static void dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv( 2177 struct dp_pdev *pdev, uint32_t *tag_buf, uint32_t length) 2178 { 2179 htt_ppdu_stats_tx_mgmtctrl_payload_tlv *dp_stats_buf; 2180 qdf_nbuf_t nbuf; 2181 uint32_t payload_size; 2182 2183 if ((!pdev->tx_sniffer_enable) && (!pdev->mcopy_mode)) 2184 return; 2185 2186 payload_size = length - HTT_MGMT_CTRL_TLV_RESERVERD_LEN; 2187 nbuf = NULL; 2188 dp_stats_buf = (htt_ppdu_stats_tx_mgmtctrl_payload_tlv *)tag_buf; 2189 2190 2191 nbuf = qdf_nbuf_alloc(pdev->soc->osdev, payload_size, 0, 4, true); 2192 2193 if (!nbuf) { 2194 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2195 "Nbuf Allocation failed for Mgmt. payload"); 2196 qdf_assert(0); 2197 return; 2198 } 2199 2200 qdf_nbuf_put_tail(nbuf, payload_size); 2201 qdf_mem_copy(qdf_nbuf_data(nbuf), dp_stats_buf->payload, payload_size); 2202 2203 dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc, 2204 nbuf, HTT_INVALID_PEER, 2205 WDI_NO_VAL, pdev->pdev_id); 2206 } 2207 2208 /** 2209 * dp_process_ppdu_tag(): Function to process the PPDU TLVs 2210 * @pdev: DP pdev handle 2211 * @tag_buf: TLV buffer 2212 * @tlv_len: length of tlv 2213 * @ppdu_info: per ppdu tlv structure 2214 * 2215 * return: void 2216 */ 2217 static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf, 2218 uint32_t tlv_len, struct ppdu_info *ppdu_info) 2219 { 2220 uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf); 2221 2222 switch (tlv_type) { 2223 case HTT_PPDU_STATS_COMMON_TLV: 2224 qdf_assert_always(tlv_len == 2225 sizeof(htt_ppdu_stats_common_tlv)); 2226 dp_process_ppdu_stats_common_tlv(pdev, tag_buf, ppdu_info); 2227 break; 2228 case HTT_PPDU_STATS_USR_COMMON_TLV: 2229 qdf_assert_always(tlv_len == 2230 sizeof(htt_ppdu_stats_user_common_tlv)); 2231 dp_process_ppdu_stats_user_common_tlv( 2232 pdev, tag_buf, ppdu_info); 2233 break; 2234 case HTT_PPDU_STATS_USR_RATE_TLV: 2235 qdf_assert_always(tlv_len == 2236 sizeof(htt_ppdu_stats_user_rate_tlv)); 2237 dp_process_ppdu_stats_user_rate_tlv(pdev, tag_buf, ppdu_info); 2238 break; 2239 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV: 2240 qdf_assert_always(tlv_len == 2241 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_64_tlv)); 2242 dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv( 2243 pdev, tag_buf, ppdu_info); 2244 break; 2245 case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_256_TLV: 2246 qdf_assert_always(tlv_len == 2247 sizeof(htt_ppdu_stats_enq_mpdu_bitmap_256_tlv)); 2248 dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv( 2249 pdev, tag_buf, ppdu_info); 2250 break; 2251 case HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV: 2252 qdf_assert_always(tlv_len == 2253 sizeof(htt_ppdu_stats_user_cmpltn_common_tlv)); 2254 dp_process_ppdu_stats_user_cmpltn_common_tlv( 2255 pdev, tag_buf, ppdu_info); 2256 break; 2257 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV: 2258 qdf_assert_always(tlv_len == 2259 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv)); 2260 dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( 2261 pdev, tag_buf, ppdu_info); 2262 break; 2263 case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV: 2264 qdf_assert_always(tlv_len == 2265 sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv)); 2266 dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( 2267 pdev, tag_buf, ppdu_info); 2268 break; 2269 case HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV: 2270 qdf_assert_always(tlv_len == 2271 sizeof(htt_ppdu_stats_user_compltn_ack_ba_status_tlv)); 2272 dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( 2273 pdev, tag_buf, ppdu_info); 2274 break; 2275 case HTT_PPDU_STATS_USR_COMMON_ARRAY_TLV: 2276 qdf_assert_always(tlv_len == 2277 sizeof(htt_ppdu_stats_usr_common_array_tlv_v)); 2278 dp_process_ppdu_stats_user_common_array_tlv( 2279 pdev, tag_buf, ppdu_info); 2280 break; 2281 case HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV: 2282 qdf_assert_always(tlv_len == 2283 sizeof(htt_ppdu_stats_flush_tlv)); 2284 dp_process_ppdu_stats_user_compltn_flush_tlv( 2285 pdev, tag_buf); 2286 break; 2287 case HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV: 2288 dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv( 2289 pdev, tag_buf, tlv_len); 2290 break; 2291 default: 2292 break; 2293 } 2294 } 2295 2296 /** 2297 * dp_ppdu_desc_deliver(): Function to deliver Tx PPDU status descriptor 2298 * to upper layer 2299 * @pdev: DP pdev handle 2300 * @ppdu_info: per PPDU TLV descriptor 2301 * 2302 * return: void 2303 */ 2304 static 2305 void dp_ppdu_desc_deliver(struct dp_pdev *pdev, 2306 struct ppdu_info *ppdu_info) 2307 { 2308 struct cdp_tx_completion_ppdu *ppdu_desc = NULL; 2309 struct dp_peer *peer = NULL; 2310 qdf_nbuf_t nbuf; 2311 uint16_t i; 2312 2313 ppdu_desc = (struct cdp_tx_completion_ppdu *) 2314 qdf_nbuf_data(ppdu_info->nbuf); 2315 2316 ppdu_desc->num_users = ppdu_info->last_user; 2317 ppdu_desc->ppdu_id = ppdu_info->ppdu_id; 2318 2319 for (i = 0; i < ppdu_desc->num_users; i++) { 2320 2321 2322 ppdu_desc->num_mpdu += ppdu_desc->user[i].num_mpdu; 2323 ppdu_desc->num_msdu += ppdu_desc->user[i].num_msdu; 2324 2325 if (ppdu_desc->user[i].tid < CDP_DATA_TID_MAX) { 2326 peer = dp_peer_find_by_id(pdev->soc, 2327 ppdu_desc->user[i].peer_id); 2328 /** 2329 * This check is to make sure peer is not deleted 2330 * after processing the TLVs. 2331 */ 2332 if (!peer) 2333 continue; 2334 2335 dp_tx_stats_update(pdev->soc, peer, 2336 &ppdu_desc->user[i], 2337 ppdu_desc->ack_rssi); 2338 } 2339 } 2340 2341 /* 2342 * Remove from the list 2343 */ 2344 TAILQ_REMOVE(&pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem); 2345 nbuf = ppdu_info->nbuf; 2346 pdev->list_depth--; 2347 qdf_mem_free(ppdu_info); 2348 2349 qdf_assert_always(nbuf); 2350 2351 ppdu_desc = (struct cdp_tx_completion_ppdu *) 2352 qdf_nbuf_data(nbuf); 2353 2354 /** 2355 * Deliver PPDU stats only for valid (acked) data frames if 2356 * sniffer mode is not enabled. 2357 * If sniffer mode is enabled, PPDU stats for all frames 2358 * including mgmt/control frames should be delivered to upper layer 2359 */ 2360 if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { 2361 dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC, pdev->soc, 2362 nbuf, HTT_INVALID_PEER, 2363 WDI_NO_VAL, pdev->pdev_id); 2364 } else { 2365 if (ppdu_desc->num_mpdu != 0 && ppdu_desc->num_users != 0 && 2366 ppdu_desc->frame_ctrl & HTT_FRAMECTRL_DATATYPE) { 2367 2368 dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC, 2369 pdev->soc, nbuf, HTT_INVALID_PEER, 2370 WDI_NO_VAL, pdev->pdev_id); 2371 } else 2372 qdf_nbuf_free(nbuf); 2373 } 2374 return; 2375 } 2376 2377 /** 2378 * dp_get_ppdu_desc(): Function to allocate new PPDU status 2379 * desc for new ppdu id 2380 * @pdev: DP pdev handle 2381 * @ppdu_id: PPDU unique identifier 2382 * @tlv_type: TLV type received 2383 * 2384 * return: ppdu_info per ppdu tlv structure 2385 */ 2386 static 2387 struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, 2388 uint8_t tlv_type) 2389 { 2390 struct ppdu_info *ppdu_info = NULL; 2391 2392 /* 2393 * Find ppdu_id node exists or not 2394 */ 2395 TAILQ_FOREACH(ppdu_info, &pdev->ppdu_info_list, ppdu_info_list_elem) { 2396 2397 if (ppdu_info && (ppdu_info->ppdu_id == ppdu_id)) { 2398 break; 2399 } 2400 } 2401 2402 if (ppdu_info) { 2403 /** 2404 * if we get tlv_type that is already been processed for ppdu, 2405 * that means we got a new ppdu with same ppdu id. 2406 * Hence Flush the older ppdu 2407 */ 2408 if (ppdu_info->tlv_bitmap & (1 << tlv_type)) 2409 dp_ppdu_desc_deliver(pdev, ppdu_info); 2410 else 2411 return ppdu_info; 2412 } 2413 2414 /** 2415 * Flush the head ppdu descriptor if ppdu desc list reaches max 2416 * threshold 2417 */ 2418 if (pdev->list_depth > HTT_PPDU_DESC_MAX_DEPTH) { 2419 ppdu_info = TAILQ_FIRST(&pdev->ppdu_info_list); 2420 dp_ppdu_desc_deliver(pdev, ppdu_info); 2421 } 2422 2423 /* 2424 * Allocate new ppdu_info node 2425 */ 2426 ppdu_info = qdf_mem_malloc(sizeof(struct ppdu_info)); 2427 if (!ppdu_info) 2428 return NULL; 2429 2430 ppdu_info->nbuf = qdf_nbuf_alloc(pdev->soc->osdev, 2431 sizeof(struct cdp_tx_completion_ppdu), 0, 4, 2432 TRUE); 2433 if (!ppdu_info->nbuf) { 2434 qdf_mem_free(ppdu_info); 2435 return NULL; 2436 } 2437 2438 qdf_mem_zero(qdf_nbuf_data(ppdu_info->nbuf), 2439 sizeof(struct cdp_tx_completion_ppdu)); 2440 2441 if (qdf_nbuf_put_tail(ppdu_info->nbuf, 2442 sizeof(struct cdp_tx_completion_ppdu)) == NULL) { 2443 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 2444 "No tailroom for HTT PPDU"); 2445 qdf_nbuf_free(ppdu_info->nbuf); 2446 ppdu_info->nbuf = NULL; 2447 ppdu_info->last_user = 0; 2448 qdf_mem_free(ppdu_info); 2449 return NULL; 2450 } 2451 2452 /** 2453 * No lock is needed because all PPDU TLVs are processed in 2454 * same context and this list is updated in same context 2455 */ 2456 TAILQ_INSERT_TAIL(&pdev->ppdu_info_list, ppdu_info, 2457 ppdu_info_list_elem); 2458 pdev->list_depth++; 2459 return ppdu_info; 2460 } 2461 2462 /** 2463 * dp_htt_process_tlv(): Function to process each PPDU TLVs 2464 * @pdev: DP pdev handle 2465 * @htt_t2h_msg: HTT target to host message 2466 * 2467 * return: ppdu_info per ppdu tlv structure 2468 */ 2469 2470 static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, 2471 qdf_nbuf_t htt_t2h_msg) 2472 { 2473 uint32_t length; 2474 uint32_t ppdu_id; 2475 uint8_t tlv_type; 2476 uint32_t tlv_length, tlv_bitmap_expected; 2477 uint8_t *tlv_buf; 2478 struct ppdu_info *ppdu_info = NULL; 2479 2480 uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); 2481 2482 length = HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_GET(*msg_word); 2483 2484 msg_word = msg_word + 1; 2485 ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word); 2486 2487 2488 msg_word = msg_word + 3; 2489 while (length > 0) { 2490 tlv_buf = (uint8_t *)msg_word; 2491 tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word); 2492 tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word); 2493 if (qdf_likely(tlv_type < CDP_PPDU_STATS_MAX_TAG)) 2494 pdev->stats.ppdu_stats_counter[tlv_type]++; 2495 2496 if (tlv_length == 0) 2497 break; 2498 2499 tlv_length += HTT_TLV_HDR_LEN; 2500 2501 /** 2502 * Not allocating separate ppdu descriptor for MGMT Payload 2503 * TLV as this is sent as separate WDI indication and it 2504 * doesn't contain any ppdu information 2505 */ 2506 if (tlv_type == HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV) { 2507 dp_process_ppdu_tag(pdev, msg_word, tlv_length, NULL); 2508 msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 2509 length -= (tlv_length); 2510 continue; 2511 } 2512 2513 ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type); 2514 if (!ppdu_info) 2515 return NULL; 2516 ppdu_info->ppdu_id = ppdu_id; 2517 ppdu_info->tlv_bitmap |= (1 << tlv_type); 2518 2519 dp_process_ppdu_tag(pdev, msg_word, tlv_length, ppdu_info); 2520 2521 /** 2522 * Increment pdev level tlv count to monitor 2523 * missing TLVs 2524 */ 2525 pdev->tlv_count++; 2526 ppdu_info->last_tlv_cnt = pdev->tlv_count; 2527 2528 msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length); 2529 length -= (tlv_length); 2530 } 2531 2532 pdev->last_ppdu_id = ppdu_id; 2533 2534 tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; 2535 2536 if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { 2537 if (ppdu_info->is_ampdu) 2538 tlv_bitmap_expected = HTT_PPDU_SNIFFER_AMPDU_TLV_BITMAP; 2539 } 2540 2541 /** 2542 * Once all the TLVs for a given PPDU has been processed, 2543 * return PPDU status to be delivered to higher layer 2544 */ 2545 if (ppdu_info->tlv_bitmap == tlv_bitmap_expected) 2546 return ppdu_info; 2547 2548 return NULL; 2549 } 2550 #endif /* FEATURE_PERPKT_INFO */ 2551 2552 /** 2553 * dp_txrx_ppdu_stats_handler() - Function to process HTT PPDU stats from FW 2554 * @soc: DP SOC handle 2555 * @pdev_id: pdev id 2556 * @htt_t2h_msg: HTT message nbuf 2557 * 2558 * return:void 2559 */ 2560 #if defined(WDI_EVENT_ENABLE) 2561 #ifdef FEATURE_PERPKT_INFO 2562 static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 2563 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 2564 { 2565 struct dp_pdev *pdev = soc->pdev_list[pdev_id]; 2566 struct ppdu_info *ppdu_info = NULL; 2567 2568 if (!pdev->enhanced_stats_en && !pdev->tx_sniffer_enable && 2569 !pdev->mcopy_mode) 2570 return; 2571 2572 ppdu_info = dp_htt_process_tlv(pdev, htt_t2h_msg); 2573 if (ppdu_info) 2574 dp_ppdu_desc_deliver(pdev, ppdu_info); 2575 } 2576 #else 2577 static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc, 2578 uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg) 2579 { 2580 2581 } 2582 #endif 2583 #endif 2584 2585 /** 2586 * dp_txrx_fw_stats_handler() - Function to process HTT EXT stats 2587 * @soc: DP SOC handle 2588 * @htt_t2h_msg: HTT message nbuf 2589 * 2590 * return:void 2591 */ 2592 static inline void dp_txrx_fw_stats_handler(struct dp_soc *soc, 2593 qdf_nbuf_t htt_t2h_msg) 2594 { 2595 uint8_t done; 2596 qdf_nbuf_t msg_copy; 2597 uint32_t *msg_word; 2598 2599 msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); 2600 msg_word = msg_word + 3; 2601 done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word); 2602 2603 /* 2604 * HTT EXT stats response comes as stream of TLVs which span over 2605 * multiple T2H messages. 2606 * The first message will carry length of the response. 2607 * For rest of the messages length will be zero. 2608 * 2609 * Clone the T2H message buffer and store it in a list to process 2610 * it later. 2611 * 2612 * The original T2H message buffers gets freed in the T2H HTT event 2613 * handler 2614 */ 2615 msg_copy = qdf_nbuf_clone(htt_t2h_msg); 2616 2617 if (!msg_copy) { 2618 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, 2619 "T2H messge clone failed for HTT EXT STATS"); 2620 goto error; 2621 } 2622 2623 qdf_spin_lock_bh(&soc->htt_stats.lock); 2624 qdf_nbuf_queue_add(&soc->htt_stats.msg, msg_copy); 2625 /* 2626 * Done bit signifies that this is the last T2H buffer in the stream of 2627 * HTT EXT STATS message 2628 */ 2629 if (done) { 2630 soc->htt_stats.num_stats++; 2631 qdf_sched_work(0, &soc->htt_stats.work); 2632 } 2633 qdf_spin_unlock_bh(&soc->htt_stats.lock); 2634 2635 return; 2636 2637 error: 2638 qdf_spin_lock_bh(&soc->htt_stats.lock); 2639 while ((msg_copy = qdf_nbuf_queue_remove(&soc->htt_stats.msg)) 2640 != NULL) { 2641 qdf_nbuf_free(msg_copy); 2642 } 2643 soc->htt_stats.num_stats = 0; 2644 qdf_spin_unlock_bh(&soc->htt_stats.lock); 2645 return; 2646 2647 } 2648 2649 /* 2650 * htt_soc_attach_target() - SOC level HTT setup 2651 * @htt_soc: HTT SOC handle 2652 * 2653 * Return: 0 on success; error code on failure 2654 */ 2655 int htt_soc_attach_target(void *htt_soc) 2656 { 2657 struct htt_soc *soc = (struct htt_soc *)htt_soc; 2658 2659 return htt_h2t_ver_req_msg(soc); 2660 } 2661 2662 2663 #if defined(WDI_EVENT_ENABLE) && !defined(REMOVE_PKT_LOG) 2664 /* 2665 * dp_ppdu_stats_ind_handler() - PPDU stats msg handler 2666 * @htt_soc: HTT SOC handle 2667 * @msg_word: Pointer to payload 2668 * @htt_t2h_msg: HTT msg nbuf 2669 * 2670 * Return: None 2671 */ 2672 static void 2673 dp_ppdu_stats_ind_handler(struct htt_soc *soc, 2674 uint32_t *msg_word, 2675 qdf_nbuf_t htt_t2h_msg) 2676 { 2677 u_int8_t pdev_id; 2678 qdf_nbuf_set_pktlen(htt_t2h_msg, HTT_T2H_MAX_MSG_SIZE); 2679 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, 2680 "received HTT_T2H_MSG_TYPE_PPDU_STATS_IND\n"); 2681 pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word); 2682 pdev_id = DP_HW2SW_MACID(pdev_id); 2683 dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id, 2684 htt_t2h_msg); 2685 dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc, 2686 htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL, 2687 pdev_id); 2688 } 2689 #else 2690 dp_ppdu_stats_ind_handler(struct htt_soc *soc, 2691 qdf_nbuf_t htt_t2h_msg) 2692 { 2693 } 2694 #endif 2695 2696 #if defined(WDI_EVENT_ENABLE) && \ 2697 !defined(REMOVE_PKT_LOG) && defined(CONFIG_WIN) 2698 /* 2699 * dp_pktlog_msg_handler() - Pktlog msg handler 2700 * @htt_soc: HTT SOC handle 2701 * @msg_word: Pointer to payload 2702 * 2703 * Return: None 2704 */ 2705 static void 2706 dp_pktlog_msg_handler(struct htt_soc *soc, 2707 uint32_t *msg_word) 2708 { 2709 uint8_t pdev_id; 2710 uint32_t *pl_hdr; 2711 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, 2712 "received HTT_T2H_MSG_TYPE_PKTLOG\n"); 2713 pdev_id = HTT_T2H_PKTLOG_PDEV_ID_GET(*msg_word); 2714 pdev_id = DP_HW2SW_MACID(pdev_id); 2715 pl_hdr = (msg_word + 1); 2716 dp_wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc, 2717 pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL, 2718 pdev_id); 2719 } 2720 #else 2721 static void 2722 dp_pktlog_msg_handler(struct htt_soc *soc, 2723 uint32_t *msg_word) 2724 { 2725 } 2726 #endif 2727 2728 /* 2729 * dp_htt_t2h_msg_handler() - Generic Target to host Msg/event handler 2730 * @context: Opaque context (HTT SOC handle) 2731 * @pkt: HTC packet 2732 */ 2733 static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) 2734 { 2735 struct htt_soc *soc = (struct htt_soc *) context; 2736 qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext; 2737 u_int32_t *msg_word; 2738 enum htt_t2h_msg_type msg_type; 2739 2740 /* check for successful message reception */ 2741 if (pkt->Status != QDF_STATUS_SUCCESS) { 2742 if (pkt->Status != QDF_STATUS_E_CANCELED) 2743 soc->stats.htc_err_cnt++; 2744 2745 qdf_nbuf_free(htt_t2h_msg); 2746 return; 2747 } 2748 2749 /* TODO: Check if we should pop the HTC/HTT header alignment padding */ 2750 2751 msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg); 2752 msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); 2753 switch (msg_type) { 2754 case HTT_T2H_MSG_TYPE_PEER_MAP: 2755 { 2756 u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; 2757 u_int8_t *peer_mac_addr; 2758 u_int16_t peer_id; 2759 u_int16_t hw_peer_id; 2760 u_int8_t vdev_id; 2761 2762 peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); 2763 hw_peer_id = 2764 HTT_RX_PEER_MAP_HW_PEER_ID_GET(*(msg_word+2)); 2765 vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word); 2766 peer_mac_addr = htt_t2h_mac_addr_deswizzle( 2767 (u_int8_t *) (msg_word+1), 2768 &mac_addr_deswizzle_buf[0]); 2769 QDF_TRACE(QDF_MODULE_ID_TXRX, 2770 QDF_TRACE_LEVEL_INFO, 2771 "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", 2772 peer_id, vdev_id); 2773 2774 dp_rx_peer_map_handler(soc->dp_soc, peer_id, hw_peer_id, 2775 vdev_id, peer_mac_addr); 2776 break; 2777 } 2778 case HTT_T2H_MSG_TYPE_PEER_UNMAP: 2779 { 2780 u_int16_t peer_id; 2781 peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word); 2782 2783 dp_rx_peer_unmap_handler(soc->dp_soc, peer_id); 2784 break; 2785 } 2786 case HTT_T2H_MSG_TYPE_SEC_IND: 2787 { 2788 u_int16_t peer_id; 2789 enum htt_sec_type sec_type; 2790 int is_unicast; 2791 2792 peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word); 2793 sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word); 2794 is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word); 2795 /* point to the first part of the Michael key */ 2796 msg_word++; 2797 dp_rx_sec_ind_handler( 2798 soc->dp_soc, peer_id, sec_type, is_unicast, 2799 msg_word, msg_word + 2); 2800 break; 2801 } 2802 2803 case HTT_T2H_MSG_TYPE_PPDU_STATS_IND: 2804 { 2805 dp_ppdu_stats_ind_handler(soc, msg_word, htt_t2h_msg); 2806 break; 2807 } 2808 2809 case HTT_T2H_MSG_TYPE_PKTLOG: 2810 { 2811 dp_pktlog_msg_handler(soc, msg_word); 2812 break; 2813 } 2814 2815 case HTT_T2H_MSG_TYPE_VERSION_CONF: 2816 { 2817 htc_pm_runtime_put(soc->htc_soc); 2818 soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); 2819 soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); 2820 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, 2821 "target uses HTT version %d.%d; host uses %d.%d\n", 2822 soc->tgt_ver.major, soc->tgt_ver.minor, 2823 HTT_CURRENT_VERSION_MAJOR, 2824 HTT_CURRENT_VERSION_MINOR); 2825 if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) { 2826 QDF_TRACE(QDF_MODULE_ID_TXRX, 2827 QDF_TRACE_LEVEL_ERROR, 2828 "*** Incompatible host/target HTT versions!\n"); 2829 } 2830 /* abort if the target is incompatible with the host */ 2831 qdf_assert(soc->tgt_ver.major == 2832 HTT_CURRENT_VERSION_MAJOR); 2833 if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { 2834 QDF_TRACE(QDF_MODULE_ID_TXRX, 2835 QDF_TRACE_LEVEL_WARN, 2836 "*** Warning: host/target HTT versions" 2837 " are different, though compatible!\n"); 2838 } 2839 break; 2840 } 2841 case HTT_T2H_MSG_TYPE_RX_ADDBA: 2842 { 2843 uint16_t peer_id; 2844 uint8_t tid; 2845 uint8_t win_sz; 2846 uint16_t status; 2847 struct dp_peer *peer; 2848 2849 /* 2850 * Update REO Queue Desc with new values 2851 */ 2852 peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); 2853 tid = HTT_RX_ADDBA_TID_GET(*msg_word); 2854 win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); 2855 peer = dp_peer_find_by_id(soc->dp_soc, peer_id); 2856 2857 /* 2858 * Window size needs to be incremented by 1 2859 * since fw needs to represent a value of 256 2860 * using just 8 bits 2861 */ 2862 if (peer) { 2863 status = dp_addba_requestprocess_wifi3(peer, 2864 0, tid, 0, win_sz + 1, 0xffff); 2865 QDF_TRACE(QDF_MODULE_ID_TXRX, 2866 QDF_TRACE_LEVEL_INFO, 2867 FL("PeerID %d BAW %d TID %d stat %d\n"), 2868 peer_id, win_sz, tid, status); 2869 2870 } else { 2871 QDF_TRACE(QDF_MODULE_ID_TXRX, 2872 QDF_TRACE_LEVEL_ERROR, 2873 FL("Peer not found peer id %d\n"), 2874 peer_id); 2875 } 2876 break; 2877 } 2878 case HTT_T2H_MSG_TYPE_EXT_STATS_CONF: 2879 { 2880 dp_txrx_fw_stats_handler(soc->dp_soc, htt_t2h_msg); 2881 break; 2882 } 2883 default: 2884 break; 2885 }; 2886 2887 /* Free the indication buffer */ 2888 qdf_nbuf_free(htt_t2h_msg); 2889 } 2890 2891 /* 2892 * dp_htt_h2t_full() - Send full handler (called from HTC) 2893 * @context: Opaque context (HTT SOC handle) 2894 * @pkt: HTC packet 2895 * 2896 * Return: enum htc_send_full_action 2897 */ 2898 static enum htc_send_full_action 2899 dp_htt_h2t_full(void *context, HTC_PACKET *pkt) 2900 { 2901 return HTC_SEND_FULL_KEEP; 2902 } 2903 2904 /* 2905 * dp_htt_hif_t2h_hp_callback() - HIF callback for high priority T2H messages 2906 * @context: Opaque context (HTT SOC handle) 2907 * @nbuf: nbuf containing T2H message 2908 * @pipe_id: HIF pipe ID 2909 * 2910 * Return: QDF_STATUS 2911 * 2912 * TODO: Temporary change to bypass HTC connection for this new HIF pipe, which 2913 * will be used for packet log and other high-priority HTT messsages. Proper 2914 * HTC connection to be added later once required FW changes are available 2915 */ 2916 static QDF_STATUS 2917 dp_htt_hif_t2h_hp_callback (void *context, qdf_nbuf_t nbuf, uint8_t pipe_id) 2918 { 2919 A_STATUS rc = QDF_STATUS_SUCCESS; 2920 HTC_PACKET htc_pkt; 2921 2922 qdf_assert_always(pipe_id == DP_HTT_T2H_HP_PIPE); 2923 qdf_mem_zero(&htc_pkt, sizeof(htc_pkt)); 2924 htc_pkt.Status = QDF_STATUS_SUCCESS; 2925 htc_pkt.pPktContext = (void *)nbuf; 2926 dp_htt_t2h_msg_handler(context, &htc_pkt); 2927 2928 return rc; 2929 } 2930 2931 /* 2932 * htt_htc_soc_attach() - Register SOC level HTT instance with HTC 2933 * @htt_soc: HTT SOC handle 2934 * 2935 * Return: 0 on success; error code on failure 2936 */ 2937 static int 2938 htt_htc_soc_attach(struct htt_soc *soc) 2939 { 2940 struct htc_service_connect_req connect; 2941 struct htc_service_connect_resp response; 2942 A_STATUS status; 2943 struct dp_soc *dpsoc = soc->dp_soc; 2944 2945 qdf_mem_set(&connect, sizeof(connect), 0); 2946 qdf_mem_set(&response, sizeof(response), 0); 2947 2948 connect.pMetaData = NULL; 2949 connect.MetaDataLength = 0; 2950 connect.EpCallbacks.pContext = soc; 2951 connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete; 2952 connect.EpCallbacks.EpTxCompleteMultiple = NULL; 2953 connect.EpCallbacks.EpRecv = dp_htt_t2h_msg_handler; 2954 2955 /* rx buffers currently are provided by HIF, not by EpRecvRefill */ 2956 connect.EpCallbacks.EpRecvRefill = NULL; 2957 2958 /* N/A, fill is done by HIF */ 2959 connect.EpCallbacks.RecvRefillWaterMark = 1; 2960 2961 connect.EpCallbacks.EpSendFull = dp_htt_h2t_full; 2962 /* 2963 * Specify how deep to let a queue get before htc_send_pkt will 2964 * call the EpSendFull function due to excessive send queue depth. 2965 */ 2966 connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH; 2967 2968 /* disable flow control for HTT data message service */ 2969 connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; 2970 2971 /* connect to control service */ 2972 connect.service_id = HTT_DATA_MSG_SVC; 2973 2974 status = htc_connect_service(soc->htc_soc, &connect, &response); 2975 2976 if (status != A_OK) 2977 return QDF_STATUS_E_FAILURE; 2978 2979 soc->htc_endpoint = response.Endpoint; 2980 2981 hif_save_htc_htt_config_endpoint(dpsoc->hif_handle, soc->htc_endpoint); 2982 dp_hif_update_pipe_callback(soc->dp_soc, (void *)soc, 2983 dp_htt_hif_t2h_hp_callback, DP_HTT_T2H_HP_PIPE); 2984 2985 return 0; /* success */ 2986 } 2987 2988 /* 2989 * htt_soc_attach() - SOC level HTT initialization 2990 * @dp_soc: Opaque Data path SOC handle 2991 * @ctrl_psoc: Opaque ctrl SOC handle 2992 * @htc_soc: SOC level HTC handle 2993 * @hal_soc: Opaque HAL SOC handle 2994 * @osdev: QDF device 2995 * 2996 * Return: HTT handle on success; NULL on failure 2997 */ 2998 void * 2999 htt_soc_attach(void *dp_soc, void *ctrl_psoc, HTC_HANDLE htc_soc, 3000 void *hal_soc, qdf_device_t osdev) 3001 { 3002 struct htt_soc *soc; 3003 int i; 3004 3005 soc = qdf_mem_malloc(sizeof(*soc)); 3006 3007 if (!soc) 3008 goto fail1; 3009 3010 soc->osdev = osdev; 3011 soc->ctrl_psoc = ctrl_psoc; 3012 soc->dp_soc = dp_soc; 3013 soc->htc_soc = htc_soc; 3014 soc->hal_soc = hal_soc; 3015 3016 /* TODO: See if any NSS related context is requred in htt_soc */ 3017 3018 soc->htt_htc_pkt_freelist = NULL; 3019 3020 if (htt_htc_soc_attach(soc)) 3021 goto fail2; 3022 3023 /* TODO: See if any Rx data specific intialization is required. For 3024 * MCL use cases, the data will be received as single packet and 3025 * should not required any descriptor or reorder handling 3026 */ 3027 3028 HTT_TX_MUTEX_INIT(&soc->htt_tx_mutex); 3029 3030 /* pre-allocate some HTC_PACKET objects */ 3031 for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) { 3032 struct dp_htt_htc_pkt_union *pkt; 3033 pkt = qdf_mem_malloc(sizeof(*pkt)); 3034 if (!pkt) 3035 break; 3036 3037 htt_htc_pkt_free(soc, &pkt->u.pkt); 3038 } 3039 3040 return soc; 3041 3042 fail2: 3043 qdf_mem_free(soc); 3044 3045 fail1: 3046 return NULL; 3047 } 3048 3049 3050 /* 3051 * htt_soc_detach() - Detach SOC level HTT 3052 * @htt_soc: HTT SOC handle 3053 */ 3054 void 3055 htt_soc_detach(void *htt_soc) 3056 { 3057 struct htt_soc *soc = (struct htt_soc *)htt_soc; 3058 3059 htt_htc_misc_pkt_pool_free(soc); 3060 htt_htc_pkt_pool_free(soc); 3061 HTT_TX_MUTEX_DESTROY(&soc->htt_tx_mutex); 3062 qdf_mem_free(soc); 3063 } 3064 3065 /* 3066 * dp_get_pdev_mask_for_channel_id() - Retrieve pdev_id mask based on channel 3067 * information 3068 * @pdev - DP PDEV Handle 3069 * @channel - frequency 3070 * 3071 * Return - Pdev_id mask 3072 */ 3073 static inline 3074 uint8_t dp_get_pdev_mask_for_channel_id(struct dp_pdev *pdev, uint8_t channel) 3075 { 3076 uint8_t pdev_mask = 0; 3077 3078 if (!channel) 3079 return 1 << (pdev->pdev_id + 1); 3080 3081 else if (channel && WLAN_CHAN_IS_5GHZ(channel)) 3082 pdev_mask = 0; 3083 3084 else if (channel && WLAN_CHAN_IS_2GHZ(channel)) 3085 pdev_mask = 1; 3086 3087 return 1 << (pdev_mask + 1); 3088 } 3089 3090 /** 3091 * dp_h2t_ext_stats_msg_send(): function to contruct HTT message to pass to FW 3092 * @pdev: DP PDEV handle 3093 * @stats_type_upload_mask: stats type requested by user 3094 * @config_param_0: extra configuration parameters 3095 * @config_param_1: extra configuration parameters 3096 * @config_param_2: extra configuration parameters 3097 * @config_param_3: extra configuration parameters 3098 * 3099 * return: QDF STATUS 3100 */ 3101 QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, 3102 uint32_t stats_type_upload_mask, uint32_t config_param_0, 3103 uint32_t config_param_1, uint32_t config_param_2, 3104 uint32_t config_param_3, int cookie_val, int cookie_msb, 3105 uint8_t channel) 3106 { 3107 struct htt_soc *soc = pdev->soc->htt_handle; 3108 struct dp_htt_htc_pkt *pkt; 3109 qdf_nbuf_t msg; 3110 uint32_t *msg_word; 3111 uint8_t pdev_mask = 0; 3112 3113 msg = qdf_nbuf_alloc( 3114 soc->osdev, 3115 HTT_MSG_BUF_SIZE(HTT_H2T_EXT_STATS_REQ_MSG_SZ), 3116 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); 3117 3118 if (!msg) 3119 return QDF_STATUS_E_NOMEM; 3120 3121 /*TODO:Add support for SOC stats 3122 * Bit 0: SOC Stats 3123 * Bit 1: Pdev stats for pdev id 0 3124 * Bit 2: Pdev stats for pdev id 1 3125 * Bit 3: Pdev stats for pdev id 2 3126 */ 3127 pdev_mask = dp_get_pdev_mask_for_channel_id(pdev, channel); 3128 3129 /* 3130 * Set the length of the message. 3131 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added 3132 * separately during the below call to qdf_nbuf_push_head. 3133 * The contribution from the HTC header is added separately inside HTC. 3134 */ 3135 if (qdf_nbuf_put_tail(msg, HTT_H2T_EXT_STATS_REQ_MSG_SZ) == NULL) { 3136 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 3137 "Failed to expand head for HTT_EXT_STATS"); 3138 qdf_nbuf_free(msg); 3139 return QDF_STATUS_E_FAILURE; 3140 } 3141 3142 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, 3143 "-----%s:%d----\n cookie <-> %d\n config_param_0 %u\n" 3144 "config_param_1 %u\n config_param_2 %u\n" 3145 "config_param_4 %u\n -------------\n", 3146 __func__, __LINE__, cookie_val, config_param_0, 3147 config_param_1, config_param_2, config_param_3); 3148 3149 msg_word = (uint32_t *) qdf_nbuf_data(msg); 3150 3151 qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); 3152 *msg_word = 0; 3153 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_EXT_STATS_REQ); 3154 HTT_H2T_EXT_STATS_REQ_PDEV_MASK_SET(*msg_word, pdev_mask); 3155 HTT_H2T_EXT_STATS_REQ_STATS_TYPE_SET(*msg_word, stats_type_upload_mask); 3156 3157 /* word 1 */ 3158 msg_word++; 3159 *msg_word = 0; 3160 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_0); 3161 3162 /* word 2 */ 3163 msg_word++; 3164 *msg_word = 0; 3165 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_1); 3166 3167 /* word 3 */ 3168 msg_word++; 3169 *msg_word = 0; 3170 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_2); 3171 3172 /* word 4 */ 3173 msg_word++; 3174 *msg_word = 0; 3175 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_3); 3176 3177 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, 0); 3178 3179 /* word 5 */ 3180 msg_word++; 3181 3182 /* word 6 */ 3183 msg_word++; 3184 *msg_word = 0; 3185 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, cookie_val); 3186 3187 /* word 7 */ 3188 msg_word++; 3189 *msg_word = 0; 3190 /*Using last 2 bits for pdev_id */ 3191 cookie_msb = ((cookie_msb << 2) | pdev->pdev_id); 3192 HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, cookie_msb); 3193 3194 pkt = htt_htc_pkt_alloc(soc); 3195 if (!pkt) { 3196 qdf_nbuf_free(msg); 3197 return QDF_STATUS_E_NOMEM; 3198 } 3199 3200 pkt->soc_ctxt = NULL; /* not used during send-done callback */ 3201 3202 SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, 3203 dp_htt_h2t_send_complete_free_netbuf, 3204 qdf_nbuf_data(msg), qdf_nbuf_len(msg), 3205 soc->htc_endpoint, 3206 1); /* tag - not relevant here */ 3207 3208 SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); 3209 DP_HTT_SEND_HTC_PKT(soc, pkt); 3210 return 0; 3211 } 3212 3213 /* This macro will revert once proper HTT header will define for 3214 * HTT_H2T_MSG_TYPE_PPDU_STATS_CFG in htt.h file 3215 * */ 3216 #if defined(WDI_EVENT_ENABLE) 3217 /** 3218 * dp_h2t_cfg_stats_msg_send(): function to construct HTT message to pass to FW 3219 * @pdev: DP PDEV handle 3220 * @stats_type_upload_mask: stats type requested by user 3221 * @mac_id: Mac id number 3222 * 3223 * return: QDF STATUS 3224 */ 3225 QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, 3226 uint32_t stats_type_upload_mask, uint8_t mac_id) 3227 { 3228 struct htt_soc *soc = pdev->soc->htt_handle; 3229 struct dp_htt_htc_pkt *pkt; 3230 qdf_nbuf_t msg; 3231 uint32_t *msg_word; 3232 uint8_t pdev_mask; 3233 3234 msg = qdf_nbuf_alloc( 3235 soc->osdev, 3236 HTT_MSG_BUF_SIZE(HTT_H2T_PPDU_STATS_CFG_MSG_SZ), 3237 HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, true); 3238 3239 if (!msg) { 3240 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 3241 "Fail to allocate HTT_H2T_PPDU_STATS_CFG_MSG_SZ msg buffer\n"); 3242 qdf_assert(0); 3243 return QDF_STATUS_E_NOMEM; 3244 } 3245 3246 /*TODO:Add support for SOC stats 3247 * Bit 0: SOC Stats 3248 * Bit 1: Pdev stats for pdev id 0 3249 * Bit 2: Pdev stats for pdev id 1 3250 * Bit 3: Pdev stats for pdev id 2 3251 */ 3252 pdev_mask = 1 << DP_SW2HW_MACID(mac_id); 3253 3254 /* 3255 * Set the length of the message. 3256 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added 3257 * separately during the below call to qdf_nbuf_push_head. 3258 * The contribution from the HTC header is added separately inside HTC. 3259 */ 3260 if (qdf_nbuf_put_tail(msg, HTT_H2T_PPDU_STATS_CFG_MSG_SZ) == NULL) { 3261 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 3262 "Failed to expand head for HTT_CFG_STATS\n"); 3263 qdf_nbuf_free(msg); 3264 return QDF_STATUS_E_FAILURE; 3265 } 3266 3267 msg_word = (uint32_t *) qdf_nbuf_data(msg); 3268 3269 qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); 3270 *msg_word = 0; 3271 HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_PPDU_STATS_CFG); 3272 HTT_H2T_PPDU_STATS_CFG_PDEV_MASK_SET(*msg_word, pdev_mask); 3273 HTT_H2T_PPDU_STATS_CFG_TLV_BITMASK_SET(*msg_word, 3274 stats_type_upload_mask); 3275 3276 pkt = htt_htc_pkt_alloc(soc); 3277 if (!pkt) { 3278 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 3279 "Fail to allocate dp_htt_htc_pkt buffer\n"); 3280 qdf_assert(0); 3281 qdf_nbuf_free(msg); 3282 return QDF_STATUS_E_NOMEM; 3283 } 3284 3285 pkt->soc_ctxt = NULL; /* not used during send-done callback */ 3286 3287 SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, 3288 dp_htt_h2t_send_complete_free_netbuf, 3289 qdf_nbuf_data(msg), qdf_nbuf_len(msg), 3290 soc->htc_endpoint, 3291 1); /* tag - not relevant here */ 3292 3293 SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); 3294 DP_HTT_SEND_HTC_PKT(soc, pkt); 3295 return 0; 3296 } 3297 #endif 3298