1 /* 2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <qdf_mem.h> /* qdf_mem_malloc,free, etc. */ 21 #include <qdf_types.h> /* qdf_print, bool */ 22 #include <qdf_nbuf.h> /* qdf_nbuf_t, etc. */ 23 #include <qdf_timer.h> /* qdf_timer_free */ 24 25 #include <htt.h> /* HTT_HL_RX_DESC_SIZE */ 26 #include <ol_cfg.h> 27 #include <ol_rx.h> 28 #include <ol_htt_rx_api.h> 29 #include <htt_internal.h> /* HTT_ASSERT, htt_pdev_t, HTT_RX_BUF_SIZE */ 30 #include "regtable.h" 31 32 #include <cds_ieee80211_common.h> /* ieee80211_frame, ieee80211_qoscntl */ 33 #include <cds_utils.h> 34 #include <wlan_policy_mgr_api.h> 35 #include "ol_txrx_types.h" 36 #ifdef DEBUG_DMA_DONE 37 #include <asm/barrier.h> 38 #include <wma_api.h> 39 #endif 40 #include <pktlog_ac_fmt.h> 41 42 #define HTT_FCS_LEN (4) 43 44 enum { 45 HW_RX_DECAP_FORMAT_RAW = 0, 46 HW_RX_DECAP_FORMAT_NWIFI, 47 HW_RX_DECAP_FORMAT_8023, 48 HW_RX_DECAP_FORMAT_ETH2, 49 }; 50 51 struct mon_rx_status g_ppdu_rx_status; 52 53 /** 54 * htt_rx_mon_note_capture_channel() - Make note of channel to update in 55 * radiotap 56 * @pdev: handle to htt_pdev 57 * @mon_ch: capture channel number. 58 * 59 * Return: None 60 */ htt_rx_mon_note_capture_channel(htt_pdev_handle pdev,int mon_ch)61 void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch) 62 { 63 struct mon_channel *ch_info = &pdev->mon_ch_info; 64 65 ch_info->ch_num = mon_ch; 66 ch_info->ch_freq = cds_chan_to_freq(mon_ch); 67 } 68 69 #ifndef CONFIG_HL_SUPPORT 70 /** 71 * htt_mon_rx_handle_amsdu_packet() - Handle consecutive fragments of amsdu 72 * @msdu: pointer to first msdu of amsdu 73 * @pdev: Handle to htt_pdev_handle 74 * @msg_word: Input and output variable, so pointer to HTT msg pointer 75 * @amsdu_len: remaining length of all N-1 msdu msdu's 76 * @frag_cnt: number of frags handled 77 * 78 * This function handles the (N-1) msdu's of amsdu, N'th msdu is already 79 * handled by calling function. N-1 msdu's are tied using frags_list. 80 * msdu_info field updated by FW indicates if this is last msdu. All the 81 * msdu's before last msdu will be of MAX payload. 82 * 83 * Return: 1 on success and 0 on failure. 84 */ 85 static htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu,htt_pdev_handle pdev,uint32_t ** msg_word,uint32_t amsdu_len,uint32_t * frag_cnt)86 int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev, 87 uint32_t **msg_word, uint32_t amsdu_len, 88 uint32_t *frag_cnt) 89 { 90 qdf_nbuf_t frag_nbuf; 91 qdf_nbuf_t prev_frag_nbuf; 92 uint32_t len; 93 uint32_t last_frag; 94 qdf_dma_addr_t paddr; 95 96 *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; 97 paddr = htt_rx_in_ord_paddr_get(*msg_word); 98 frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); 99 if (qdf_unlikely(!frag_nbuf)) { 100 qdf_print("netbuf pop failed!"); 101 return 0; 102 } 103 *frag_cnt = *frag_cnt + 1; 104 last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)*msg_word)-> 105 msdu_info; 106 qdf_nbuf_append_ext_list(msdu, frag_nbuf, amsdu_len); 107 qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); 108 qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); 109 /* For msdu's other than parent will not have htt_host_rx_desc_base */ 110 len = QDF_MIN(amsdu_len, HTT_RX_BUF_SIZE); 111 amsdu_len -= len; 112 qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); 113 114 HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, 115 QDF_TRACE_LEVEL_INFO_HIGH, 116 qdf_nbuf_data(frag_nbuf), 117 qdf_nbuf_len(frag_nbuf))); 118 prev_frag_nbuf = frag_nbuf; 119 while (!last_frag) { 120 *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; 121 paddr = htt_rx_in_ord_paddr_get(*msg_word); 122 frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); 123 last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) 124 *msg_word)->msdu_info; 125 126 if (qdf_unlikely(!frag_nbuf)) { 127 qdf_print("netbuf pop failed!"); 128 prev_frag_nbuf->next = NULL; 129 return 0; 130 } 131 *frag_cnt = *frag_cnt + 1; 132 qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); 133 qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); 134 135 len = QDF_MIN(amsdu_len, HTT_RX_BUF_SIZE); 136 amsdu_len -= len; 137 qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); 138 HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, 139 QDF_TRACE_LEVEL_INFO_HIGH, 140 qdf_nbuf_data(frag_nbuf), 141 qdf_nbuf_len(frag_nbuf))); 142 143 qdf_nbuf_set_next(prev_frag_nbuf, frag_nbuf); 144 prev_frag_nbuf = frag_nbuf; 145 } 146 qdf_nbuf_set_next(prev_frag_nbuf, NULL); 147 return 1; 148 } 149 150 #define SHORT_PREAMBLE 1 151 #define LONG_PREAMBLE 0 152 #ifdef HELIUMPLUS 153 /** 154 * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc 155 * @l_sig_rate_select: OFDM or CCK rate 156 * @l_sig_rate: 157 * 158 * If l_sig_rate_select is 0: 159 * 0x8: OFDM 48 Mbps 160 * 0x9: OFDM 24 Mbps 161 * 0xA: OFDM 12 Mbps 162 * 0xB: OFDM 6 Mbps 163 * 0xC: OFDM 54 Mbps 164 * 0xD: OFDM 36 Mbps 165 * 0xE: OFDM 18 Mbps 166 * 0xF: OFDM 9 Mbps 167 * If l_sig_rate_select is 1: 168 * 0x1: DSSS 1 Mbps long preamble 169 * 0x2: DSSS 2 Mbps long preamble 170 * 0x3: CCK 5.5 Mbps long preamble 171 * 0x4: CCK 11 Mbps long preamble 172 * 0x5: DSSS 2 Mbps short preamble 173 * 0x6: CCK 5.5 Mbps 174 * 0x7: CCK 11 Mbps short preamble 175 * 176 * Return: rate interms of 500Kbps. 177 */ htt_rx_get_rate(uint32_t l_sig_rate_select,uint32_t l_sig_rate,uint8_t * preamble)178 static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, 179 uint32_t l_sig_rate, uint8_t *preamble) 180 { 181 char ret = 0x0; 182 *preamble = SHORT_PREAMBLE; 183 if (l_sig_rate_select == 0) { 184 switch (l_sig_rate) { 185 case 0x8: 186 ret = 0x60; 187 break; 188 case 0x9: 189 ret = 0x30; 190 break; 191 case 0xA: 192 ret = 0x18; 193 break; 194 case 0xB: 195 ret = 0x0c; 196 break; 197 case 0xC: 198 ret = 0x6c; 199 break; 200 case 0xD: 201 ret = 0x48; 202 break; 203 case 0xE: 204 ret = 0x24; 205 break; 206 case 0xF: 207 ret = 0x12; 208 break; 209 default: 210 break; 211 } 212 } else if (l_sig_rate_select == 1) { 213 switch (l_sig_rate) { 214 case 0x1: 215 ret = 0x2; 216 *preamble = LONG_PREAMBLE; 217 break; 218 case 0x2: 219 ret = 0x4; 220 *preamble = LONG_PREAMBLE; 221 break; 222 case 0x3: 223 ret = 0xB; 224 *preamble = LONG_PREAMBLE; 225 break; 226 case 0x4: 227 ret = 0x16; 228 *preamble = LONG_PREAMBLE; 229 break; 230 case 0x5: 231 ret = 0x4; 232 break; 233 case 0x6: 234 ret = 0xB; 235 break; 236 case 0x7: 237 ret = 0x16; 238 break; 239 default: 240 break; 241 } 242 } else { 243 qdf_print("Invalid rate info\n"); 244 } 245 return ret; 246 } 247 #else 248 /** 249 * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc 250 * @l_sig_rate_select: OFDM or CCK rate 251 * @l_sig_rate: 252 * 253 * If l_sig_rate_select is 0: 254 * 0x8: OFDM 48 Mbps 255 * 0x9: OFDM 24 Mbps 256 * 0xA: OFDM 12 Mbps 257 * 0xB: OFDM 6 Mbps 258 * 0xC: OFDM 54 Mbps 259 * 0xD: OFDM 36 Mbps 260 * 0xE: OFDM 18 Mbps 261 * 0xF: OFDM 9 Mbps 262 * If l_sig_rate_select is 1: 263 * 0x8: CCK 11 Mbps long preamble 264 * 0x9: CCK 5.5 Mbps long preamble 265 * 0xA: CCK 2 Mbps long preamble 266 * 0xB: CCK 1 Mbps long preamble 267 * 0xC: CCK 11 Mbps short preamble 268 * 0xD: CCK 5.5 Mbps short preamble 269 * 0xE: CCK 2 Mbps short preamble 270 * 271 * Return: rate interms of 500Kbps. 272 */ htt_rx_get_rate(uint32_t l_sig_rate_select,uint32_t l_sig_rate,uint8_t * preamble)273 static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, 274 uint32_t l_sig_rate, uint8_t *preamble) 275 { 276 char ret = 0x0; 277 *preamble = SHORT_PREAMBLE; 278 if (l_sig_rate_select == 0) { 279 switch (l_sig_rate) { 280 case 0x8: 281 ret = 0x60; 282 break; 283 case 0x9: 284 ret = 0x30; 285 break; 286 case 0xA: 287 ret = 0x18; 288 break; 289 case 0xB: 290 ret = 0x0c; 291 break; 292 case 0xC: 293 ret = 0x6c; 294 break; 295 case 0xD: 296 ret = 0x48; 297 break; 298 case 0xE: 299 ret = 0x24; 300 break; 301 case 0xF: 302 ret = 0x12; 303 break; 304 default: 305 break; 306 } 307 } else if (l_sig_rate_select == 1) { 308 switch (l_sig_rate) { 309 case 0x8: 310 ret = 0x16; 311 *preamble = LONG_PREAMBLE; 312 break; 313 case 0x9: 314 ret = 0x0B; 315 *preamble = LONG_PREAMBLE; 316 break; 317 case 0xA: 318 ret = 0x4; 319 *preamble = LONG_PREAMBLE; 320 break; 321 case 0xB: 322 ret = 0x02; 323 *preamble = LONG_PREAMBLE; 324 break; 325 case 0xC: 326 ret = 0x16; 327 break; 328 case 0xD: 329 ret = 0x0B; 330 break; 331 case 0xE: 332 ret = 0x04; 333 break; 334 default: 335 break; 336 } 337 } else { 338 qdf_print("Invalid rate info\n"); 339 } 340 return ret; 341 } 342 #endif /* HELIUMPLUS */ 343 344 /** 345 * htt_mon_rx_get_phy_info() - Get phy info 346 * @rx_desc: Pointer to struct htt_host_rx_desc_base 347 * @rx_status: Return variable updated with phy_info in rx_status 348 * 349 * Return: None 350 */ htt_mon_rx_get_phy_info(struct htt_host_rx_desc_base * rx_desc,struct mon_rx_status * rx_status)351 static void htt_mon_rx_get_phy_info(struct htt_host_rx_desc_base *rx_desc, 352 struct mon_rx_status *rx_status) 353 { 354 uint8_t preamble = 0; 355 uint8_t preamble_type = rx_desc->ppdu_start.preamble_type; 356 uint8_t mcs = 0, nss = 0, sgi = 0, bw = 0, beamformed = 0; 357 uint16_t vht_flags = 0, ht_flags = 0; 358 uint32_t l_sig_rate_select = rx_desc->ppdu_start.l_sig_rate_select; 359 uint32_t l_sig_rate = rx_desc->ppdu_start.l_sig_rate; 360 bool is_stbc = 0, ldpc = 0; 361 362 switch (preamble_type) { 363 case 4: 364 /* legacy */ 365 rx_status->rate = htt_rx_get_rate(l_sig_rate_select, l_sig_rate, 366 &preamble); 367 break; 368 case 8: 369 is_stbc = ((VHT_SIG_A_2(rx_desc) >> 4) & 3); 370 fallthrough; 371 case 9: 372 ht_flags = 1; 373 sgi = (VHT_SIG_A_2(rx_desc) >> 7) & 0x01; 374 bw = (VHT_SIG_A_1(rx_desc) >> 7) & 0x01; 375 mcs = (VHT_SIG_A_1(rx_desc) & 0x7f); 376 nss = mcs >> 3; 377 beamformed = 378 (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; 379 break; 380 case 0x0c: 381 is_stbc = (VHT_SIG_A_2(rx_desc) >> 3) & 1; 382 ldpc = (VHT_SIG_A_2(rx_desc) >> 2) & 1; 383 fallthrough; 384 case 0x0d: 385 { 386 uint8_t gid_in_sig = ((VHT_SIG_A_1(rx_desc) >> 4) & 0x3f); 387 388 vht_flags = 1; 389 sgi = VHT_SIG_A_2(rx_desc) & 0x01; 390 bw = (VHT_SIG_A_1(rx_desc) & 0x03); 391 if (gid_in_sig == 0 || gid_in_sig == 63) { 392 /* SU case */ 393 mcs = (VHT_SIG_A_2(rx_desc) >> 4) & 394 0xf; 395 nss = (VHT_SIG_A_1(rx_desc) >> 10) & 396 0x7; 397 } else { 398 /* MU case */ 399 uint8_t sta_user_pos = 400 (uint8_t)((rx_desc->ppdu_start.reserved_4a >> 8) 401 & 0x3); 402 mcs = (rx_desc->ppdu_start.vht_sig_b >> 16); 403 if (bw >= 2) 404 mcs >>= 3; 405 else if (bw > 0) 406 mcs >>= 1; 407 mcs &= 0xf; 408 nss = (((VHT_SIG_A_1(rx_desc) >> 10) + 409 sta_user_pos * 3) & 0x7); 410 } 411 beamformed = (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; 412 } 413 fallthrough; 414 default: 415 break; 416 } 417 418 rx_status->mcs = mcs; 419 rx_status->bw = bw; 420 rx_status->nr_ant = nss; 421 rx_status->is_stbc = is_stbc; 422 rx_status->sgi = sgi; 423 rx_status->ldpc = ldpc; 424 rx_status->beamformed = beamformed; 425 rx_status->vht_flag_values3[0] = mcs << 0x4 | (nss + 1); 426 if (ht_flags) 427 rx_status->ht_mcs = mcs; 428 rx_status->ht_flags = ht_flags; 429 rx_status->vht_flags = vht_flags; 430 rx_status->rtap_flags |= ((preamble == SHORT_PREAMBLE) ? BIT(1) : 0); 431 rx_status->vht_flag_values2 = bw; 432 } 433 434 /** 435 * htt_mon_rx_get_rtap_flags() - Get radiotap flags 436 * @rx_desc: Pointer to struct htt_host_rx_desc_base 437 * 438 * Return: Bitmapped radiotap flags. 439 */ htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base * rx_desc)440 static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) 441 { 442 uint8_t rtap_flags = 0; 443 444 /* WEP40 || WEP104 || WEP128 */ 445 if (rx_desc->mpdu_start.encrypt_type == 0 || 446 rx_desc->mpdu_start.encrypt_type == 1 || 447 rx_desc->mpdu_start.encrypt_type == 3) 448 rtap_flags |= BIT(2); 449 450 /* IEEE80211_RADIOTAP_F_FRAG */ 451 if (rx_desc->attention.fragment) 452 rtap_flags |= BIT(3); 453 454 /* IEEE80211_RADIOTAP_F_FCS */ 455 rtap_flags |= BIT(4); 456 457 /* IEEE80211_RADIOTAP_F_BADFCS */ 458 if (rx_desc->mpdu_end.fcs_err) 459 rtap_flags |= BIT(6); 460 461 return rtap_flags; 462 } 463 htt_rx_mon_get_rx_status(htt_pdev_handle pdev,struct htt_host_rx_desc_base * rx_desc,struct mon_rx_status * rx_status)464 void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, 465 struct htt_host_rx_desc_base *rx_desc, 466 struct mon_rx_status *rx_status) 467 { 468 struct mon_channel *ch_info = &pdev->mon_ch_info; 469 470 rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); 471 rx_status->chan_freq = ch_info->ch_freq; 472 rx_status->chan_num = ch_info->ch_num; 473 htt_mon_rx_get_phy_info(rx_desc, rx_status); 474 rx_status->rtap_flags |= htt_mon_rx_get_rtap_flags(rx_desc); 475 476 if (rx_desc->ppdu_start.l_sig_rate_select) 477 rx_status->cck_flag = 1; 478 else 479 rx_status->ofdm_flag = 1; 480 481 rx_status->ant_signal_db = rx_desc->ppdu_start.rssi_comb; 482 rx_status->rssi_comb = rx_desc->ppdu_start.rssi_comb; 483 rx_status->chan_noise_floor = pdev->txrx_pdev->chan_noise_floor; 484 } 485 486 /** 487 * htt_rx_mon_amsdu_rx_in_order_pop_ll() - Monitor mode HTT Rx in order pop 488 * function 489 * @pdev: Handle to htt_pdev_handle 490 * @rx_ind_msg: In order indication message. 491 * @head_msdu: Return variable pointing to head msdu. 492 * @tail_msdu: Return variable pointing to tail msdu. 493 * 494 * This function pops the msdu based on paddr:length of inorder indication 495 * message. 496 * 497 * Return: 1 for success, 0 on failure. 498 */ htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,qdf_nbuf_t rx_ind_msg,qdf_nbuf_t * head_msdu,qdf_nbuf_t * tail_msdu,uint32_t * replenish_cnt)499 int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, 500 qdf_nbuf_t rx_ind_msg, 501 qdf_nbuf_t *head_msdu, 502 qdf_nbuf_t *tail_msdu, 503 uint32_t *replenish_cnt) 504 { 505 qdf_nbuf_t msdu, next, prev = NULL; 506 uint8_t *rx_ind_data; 507 uint32_t *msg_word; 508 uint32_t msdu_count; 509 struct htt_host_rx_desc_base *rx_desc; 510 uint32_t amsdu_len; 511 uint32_t len; 512 uint32_t last_frag; 513 qdf_dma_addr_t paddr; 514 static uint8_t preamble_type; 515 static uint32_t vht_sig_a_1; 516 static uint32_t vht_sig_a_2; 517 518 HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); 519 520 rx_ind_data = qdf_nbuf_data(rx_ind_msg); 521 msg_word = (uint32_t *)rx_ind_data; 522 523 *replenish_cnt = 0; 524 HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, 525 QDF_TRACE_LEVEL_INFO_HIGH, 526 (void *)rx_ind_data, 527 (int)qdf_nbuf_len(rx_ind_msg))); 528 529 /* Get the total number of MSDUs */ 530 msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); 531 HTT_RX_CHECK_MSDU_COUNT(msdu_count); 532 533 msg_word = (uint32_t *)(rx_ind_data + 534 HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); 535 paddr = htt_rx_in_ord_paddr_get(msg_word); 536 msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); 537 538 if (qdf_unlikely(!msdu)) { 539 qdf_print("netbuf pop failed!"); 540 *tail_msdu = NULL; 541 return 0; 542 } 543 *replenish_cnt = *replenish_cnt + 1; 544 545 while (msdu_count > 0) { 546 msdu_count--; 547 /* 548 * Set the netbuf length to be the entire buffer length 549 * initially, so the unmap will unmap the entire buffer. 550 */ 551 qdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); 552 qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); 553 554 /* 555 * cache consistency has been taken care of by the 556 * qdf_nbuf_unmap 557 */ 558 rx_desc = htt_rx_desc(msdu); 559 if ((unsigned int)(*(uint32_t *)&rx_desc->attention) & 560 RX_DESC_ATTN_MPDU_LEN_ERR_BIT) { 561 qdf_nbuf_free(msdu); 562 last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) 563 msg_word)->msdu_info; 564 while (!last_frag) { 565 msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; 566 paddr = htt_rx_in_ord_paddr_get(msg_word); 567 msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); 568 last_frag = ((struct 569 htt_rx_in_ord_paddr_ind_msdu_t *) 570 msg_word)->msdu_info; 571 if (qdf_unlikely(!msdu)) { 572 qdf_print("netbuf pop failed!"); 573 return 0; 574 } 575 *replenish_cnt = *replenish_cnt + 1; 576 qdf_nbuf_unmap(pdev->osdev, msdu, 577 QDF_DMA_FROM_DEVICE); 578 qdf_nbuf_free(msdu); 579 } 580 msdu = prev; 581 goto next_pop; 582 } 583 584 if (!prev) 585 (*head_msdu) = msdu; 586 prev = msdu; 587 588 HTT_PKT_DUMP(htt_print_rx_desc(rx_desc)); 589 590 /* 591 * Only the first mpdu has valid preamble type, so use it 592 * till the last mpdu is reached 593 */ 594 if (rx_desc->attention.first_mpdu) { 595 preamble_type = rx_desc->ppdu_start.preamble_type; 596 if (preamble_type == 8 || preamble_type == 9 || 597 preamble_type == 0x0c || preamble_type == 0x0d) { 598 vht_sig_a_1 = VHT_SIG_A_1(rx_desc); 599 vht_sig_a_2 = VHT_SIG_A_2(rx_desc); 600 } 601 } else { 602 rx_desc->ppdu_start.preamble_type = preamble_type; 603 if (preamble_type == 8 || preamble_type == 9 || 604 preamble_type == 0x0c || preamble_type == 0x0d) { 605 VHT_SIG_A_1(rx_desc) = vht_sig_a_1; 606 VHT_SIG_A_2(rx_desc) = vht_sig_a_2; 607 } 608 } 609 610 if (rx_desc->attention.last_mpdu) { 611 preamble_type = 0; 612 vht_sig_a_1 = 0; 613 vht_sig_a_2 = 0; 614 } 615 616 /* 617 * Make the netbuf's data pointer point to the payload rather 618 * than the descriptor. 619 */ 620 if (rx_desc->attention.first_mpdu) { 621 memset(&g_ppdu_rx_status, 0, 622 sizeof(struct mon_rx_status)); 623 htt_rx_mon_get_rx_status(pdev, rx_desc, 624 &g_ppdu_rx_status); 625 } 626 /* 627 * For certain platform, 350 bytes of headroom is already 628 * appended to accommodate radiotap header but 629 * qdf_nbuf_update_radiotap() API again will try to create 630 * a room for radiotap header. To make our design simple 631 * let qdf_nbuf_update_radiotap() API create a room for radiotap 632 * header and update it, do qdf_nbuf_pull_head() operation and 633 * pull 350 bytes of headroom. 634 * 635 * 636 * 637 * (SKB buffer) 638 * skb->head --> +-----------+ <-- skb->data 639 * | | (Before pulling headroom) 640 * | | 641 * | HEAD | 350 bytes of headroom 642 * | | 643 * | | 644 * +-----------+ <-- skb->data 645 * | | (After pulling headroom) 646 * | | 647 * | DATA | 648 * | | 649 * | | 650 * +-----------+ 651 * | | 652 * | | 653 * | TAIL | 654 * | | 655 * | | 656 * +-----------+ 657 * 658 */ 659 if (qdf_nbuf_head(msdu) == qdf_nbuf_data(msdu)) 660 qdf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); 661 qdf_nbuf_update_radiotap(&g_ppdu_rx_status, msdu, 662 HTT_RX_STD_DESC_RESERVATION); 663 amsdu_len = HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(*(msg_word + 664 NEXT_FIELD_OFFSET_IN32)); 665 666 /* 667 * MAX_RX_PAYLOAD_SZ when we have AMSDU packet. amsdu_len in 668 * which case is the total length of sum of all AMSDU's 669 */ 670 len = QDF_MIN(amsdu_len, MAX_RX_PAYLOAD_SZ); 671 amsdu_len -= len; 672 qdf_nbuf_trim_tail(msdu, HTT_RX_BUF_SIZE - 673 (RX_STD_DESC_SIZE + len)); 674 675 HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, 676 QDF_TRACE_LEVEL_INFO_HIGH, 677 qdf_nbuf_data(msdu), 678 qdf_nbuf_len(msdu))); 679 last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) 680 msg_word)->msdu_info; 681 682 /* Handle amsdu packet */ 683 if (!last_frag) { 684 /* 685 * For AMSDU packet msdu->len is sum of all the msdu's 686 * length, msdu->data_len is sum of length's of 687 * remaining msdu's other than parent. 688 */ 689 if (!htt_mon_rx_handle_amsdu_packet(msdu, pdev, 690 &msg_word, 691 amsdu_len, 692 replenish_cnt)) { 693 qdf_print("failed to handle amsdu packet"); 694 return 0; 695 } 696 } 697 698 next_pop: 699 /* check if this is the last msdu */ 700 if (msdu_count) { 701 msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; 702 paddr = htt_rx_in_ord_paddr_get(msg_word); 703 next = htt_rx_in_order_netbuf_pop(pdev, paddr); 704 if (qdf_unlikely(!next)) { 705 qdf_print("netbuf pop failed!"); 706 *tail_msdu = NULL; 707 return 0; 708 } 709 *replenish_cnt = *replenish_cnt + 1; 710 if (msdu) 711 qdf_nbuf_set_next(msdu, next); 712 msdu = next; 713 } else { 714 *tail_msdu = msdu; 715 if (msdu) 716 qdf_nbuf_set_next(msdu, NULL); 717 } 718 } 719 720 return 1; 721 } 722 #endif /* CONFIG_HL_SUPPORT */ 723 724 #if defined(FEATURE_MONITOR_MODE_SUPPORT) 725 #if !defined(QCA6290_HEADERS_DEF) && !defined(QCA6390_HEADERS_DEF) && \ 726 !defined(QCA6490_HEADERS_DEF) && !defined(QCA6750_HEADERS_DEF) && \ 727 !defined(KIWI_HEADERS_DEF) 728 static void htt_rx_parse_ppdu_start_status(struct htt_host_rx_desc_base * rx_desc,struct ieee80211_rx_status * rs)729 htt_rx_parse_ppdu_start_status(struct htt_host_rx_desc_base *rx_desc, 730 struct ieee80211_rx_status *rs) 731 { 732 struct rx_ppdu_start *ppdu_start = &rx_desc->ppdu_start; 733 734 /* RSSI */ 735 rs->rs_rssi = ppdu_start->rssi_comb; 736 737 /* PHY rate */ 738 /* 739 * rs_ratephy coding 740 * [b3 - b0] 741 * 0 -> OFDM 742 * 1 -> CCK 743 * 2 -> HT 744 * 3 -> VHT 745 * OFDM / CCK 746 * [b7 - b4 ] => LSIG rate 747 * [b23 - b8 ] => service field 748 * (b'12 static/dynamic, 749 * b'14..b'13 BW for VHT) 750 * [b31 - b24 ] => Reserved 751 * HT / VHT 752 * [b15 - b4 ] => SIG A_2 12 LSBs 753 * [b31 - b16] => SIG A_1 16 LSBs 754 */ 755 if (ppdu_start->preamble_type == 0x4) { 756 rs->rs_ratephy = ppdu_start->l_sig_rate_select; 757 rs->rs_ratephy |= ppdu_start->l_sig_rate << 4; 758 rs->rs_ratephy |= ppdu_start->service << 8; 759 } else { 760 rs->rs_ratephy = (ppdu_start->preamble_type & 0x4) ? 3 : 2; 761 #ifdef HELIUMPLUS 762 rs->rs_ratephy |= 763 (ppdu_start->ht_sig_vht_sig_ah_sig_a_2 & 0xFFF) << 4; 764 rs->rs_ratephy |= 765 (ppdu_start->ht_sig_vht_sig_ah_sig_a_1 & 0xFFFF) << 16; 766 #else 767 rs->rs_ratephy |= (ppdu_start->ht_sig_vht_sig_a_2 & 0xFFF) << 4; 768 rs->rs_ratephy |= 769 (ppdu_start->ht_sig_vht_sig_a_1 & 0xFFFF) << 16; 770 #endif 771 } 772 } 773 774 /* Util fake function that has same prototype as qdf_nbuf_clone that just 775 * returns the same nbuf 776 */ htt_rx_qdf_noclone_buf(qdf_nbuf_t buf)777 static qdf_nbuf_t htt_rx_qdf_noclone_buf(qdf_nbuf_t buf) 778 { 779 return buf; 780 } 781 782 /* This function is used by montior mode code to restitch an MSDU list 783 * corresponding to an MPDU back into an MPDU by linking up the skbs. 784 */ 785 qdf_nbuf_t htt_rx_restitch_mpdu_from_msdus(htt_pdev_handle pdev,qdf_nbuf_t head_msdu,struct ieee80211_rx_status * rx_status,unsigned int clone_not_reqd)786 htt_rx_restitch_mpdu_from_msdus(htt_pdev_handle pdev, 787 qdf_nbuf_t head_msdu, 788 struct ieee80211_rx_status *rx_status, 789 unsigned int clone_not_reqd) 790 { 791 qdf_nbuf_t msdu, mpdu_buf, prev_buf, msdu_orig, head_frag_list_cloned; 792 unsigned int decap_format, wifi_hdr_len, sec_hdr_len, msdu_llc_len, 793 mpdu_buf_len, decap_hdr_pull_bytes, frag_list_sum_len, dir, 794 is_amsdu, is_first_frag, amsdu_pad, msdu_len; 795 struct htt_host_rx_desc_base *rx_desc; 796 char *hdr_desc; 797 unsigned char *dest; 798 struct ieee80211_frame *wh; 799 struct ieee80211_qoscntl *qos; 800 801 /* The nbuf has been pulled just beyond the status and points to the 802 * payload 803 */ 804 msdu_orig = head_msdu; 805 rx_desc = htt_rx_desc(msdu_orig); 806 807 /* Fill out the rx_status from the PPDU start and end fields */ 808 if (rx_desc->attention.first_mpdu) { 809 htt_rx_parse_ppdu_start_status(rx_desc, rx_status); 810 811 /* The timestamp is no longer valid - It will be valid only for 812 * the last MPDU 813 */ 814 rx_status->rs_tstamp.tsf = ~0; 815 } 816 817 decap_format = 818 GET_FIELD(&rx_desc->msdu_start, RX_MSDU_START_2_DECAP_FORMAT); 819 820 head_frag_list_cloned = NULL; 821 822 /* Easy case - The MSDU status indicates that this is a non-decapped 823 * packet in RAW mode. 824 * return 825 */ 826 if (decap_format == HW_RX_DECAP_FORMAT_RAW) { 827 /* Note that this path might suffer from headroom unavailabilty, 828 * but the RX status is usually enough 829 */ 830 if (clone_not_reqd) 831 mpdu_buf = htt_rx_qdf_noclone_buf(head_msdu); 832 else 833 mpdu_buf = qdf_nbuf_clone(head_msdu); 834 835 if (!mpdu_buf) 836 goto mpdu_stitch_fail; 837 838 prev_buf = mpdu_buf; 839 840 frag_list_sum_len = 0; 841 is_first_frag = 1; 842 msdu_len = qdf_nbuf_len(mpdu_buf); 843 844 /* Drop the zero-length msdu */ 845 if (!msdu_len) 846 goto mpdu_stitch_fail; 847 848 msdu_orig = qdf_nbuf_next(head_msdu); 849 850 while (msdu_orig) { 851 /* TODO: intra AMSDU padding - do we need it ??? */ 852 if (clone_not_reqd) 853 msdu = htt_rx_qdf_noclone_buf(msdu_orig); 854 else 855 msdu = qdf_nbuf_clone(msdu_orig); 856 857 if (!msdu) 858 goto mpdu_stitch_fail; 859 860 if (is_first_frag) { 861 is_first_frag = 0; 862 head_frag_list_cloned = msdu; 863 } 864 865 msdu_len = qdf_nbuf_len(msdu); 866 /* Drop the zero-length msdu */ 867 if (!msdu_len) 868 goto mpdu_stitch_fail; 869 870 frag_list_sum_len += msdu_len; 871 872 /* Maintain the linking of the cloned MSDUS */ 873 qdf_nbuf_set_next_ext(prev_buf, msdu); 874 875 /* Move to the next */ 876 prev_buf = msdu; 877 msdu_orig = qdf_nbuf_next(msdu_orig); 878 } 879 880 /* The last msdu length need be larger than HTT_FCS_LEN */ 881 if (msdu_len < HTT_FCS_LEN) 882 goto mpdu_stitch_fail; 883 884 qdf_nbuf_trim_tail(prev_buf, HTT_FCS_LEN); 885 886 /* If there were more fragments to this RAW frame */ 887 if (head_frag_list_cloned) { 888 qdf_nbuf_append_ext_list(mpdu_buf, 889 head_frag_list_cloned, 890 frag_list_sum_len); 891 } 892 893 goto mpdu_stitch_done; 894 } 895 896 /* Decap mode: 897 * Calculate the amount of header in decapped packet to knock off based 898 * on the decap type and the corresponding number of raw bytes to copy 899 * status header 900 */ 901 902 hdr_desc = &rx_desc->rx_hdr_status[0]; 903 904 /* Base size */ 905 wifi_hdr_len = sizeof(struct ieee80211_frame); 906 wh = (struct ieee80211_frame *)hdr_desc; 907 908 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 909 if (dir == IEEE80211_FC1_DIR_DSTODS) 910 wifi_hdr_len += 6; 911 912 is_amsdu = 0; 913 if (wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) { 914 qos = (struct ieee80211_qoscntl *) 915 (hdr_desc + wifi_hdr_len); 916 wifi_hdr_len += 2; 917 918 is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU); 919 } 920 921 /* TODO: Any security headers associated with MPDU */ 922 sec_hdr_len = 0; 923 924 /* MSDU related stuff LLC - AMSDU subframe header etc */ 925 msdu_llc_len = is_amsdu ? (14 + 8) : 8; 926 927 mpdu_buf_len = wifi_hdr_len + sec_hdr_len + msdu_llc_len; 928 929 /* "Decap" header to remove from MSDU buffer */ 930 decap_hdr_pull_bytes = 14; 931 932 /* Allocate a new nbuf for holding the 802.11 header retrieved from the 933 * status of the now decapped first msdu. Leave enough headroom for 934 * accommodating any radio-tap /prism like PHY header 935 */ 936 #define HTT_MAX_MONITOR_HEADER (512) 937 mpdu_buf = qdf_nbuf_alloc(pdev->osdev, 938 HTT_MAX_MONITOR_HEADER + mpdu_buf_len, 939 HTT_MAX_MONITOR_HEADER, 4, false); 940 941 if (!mpdu_buf) 942 goto mpdu_stitch_fail; 943 944 /* Copy the MPDU related header and enc headers into the first buffer 945 * - Note that there can be a 2 byte pad between heaader and enc header 946 */ 947 948 prev_buf = mpdu_buf; 949 dest = qdf_nbuf_put_tail(prev_buf, wifi_hdr_len); 950 if (!dest) 951 goto mpdu_stitch_fail; 952 qdf_mem_copy(dest, hdr_desc, wifi_hdr_len); 953 hdr_desc += wifi_hdr_len; 954 955 /* NOTE - This padding is present only in the RAW header status - not 956 * when the MSDU data payload is in RAW format. 957 */ 958 /* Skip the "IV pad" */ 959 if (wifi_hdr_len & 0x3) 960 hdr_desc += 2; 961 962 /* The first LLC len is copied into the MPDU buffer */ 963 frag_list_sum_len = 0; 964 frag_list_sum_len -= msdu_llc_len; 965 966 msdu_orig = head_msdu; 967 is_first_frag = 1; 968 amsdu_pad = 0; 969 970 while (msdu_orig) { 971 /* TODO: intra AMSDU padding - do we need it ??? */ 972 if (clone_not_reqd) 973 msdu = htt_rx_qdf_noclone_buf(msdu_orig); 974 else 975 msdu = qdf_nbuf_clone(msdu_orig); 976 977 if (!msdu) 978 goto mpdu_stitch_fail; 979 980 if (is_first_frag) { 981 is_first_frag = 0; 982 head_frag_list_cloned = msdu; 983 } else { 984 /* Maintain the linking of the cloned MSDUS */ 985 qdf_nbuf_set_next_ext(prev_buf, msdu); 986 987 /* Reload the hdr ptr only on non-first MSDUs */ 988 rx_desc = htt_rx_desc(msdu_orig); 989 hdr_desc = &rx_desc->rx_hdr_status[0]; 990 } 991 992 /* Copy this buffers MSDU related status into the prev buffer */ 993 dest = qdf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); 994 dest += amsdu_pad; 995 qdf_mem_copy(dest, hdr_desc, msdu_llc_len); 996 997 /* Push the MSDU buffer beyond the decap header */ 998 qdf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); 999 frag_list_sum_len += 1000 msdu_llc_len + qdf_nbuf_len(msdu) + amsdu_pad; 1001 1002 /* 1003 * Set up intra-AMSDU pad to be added to start of next buffer - 1004 * AMSDU pad is 4 byte pad on AMSDU subframe 1005 */ 1006 amsdu_pad = (msdu_llc_len + qdf_nbuf_len(msdu)) & 0x3; 1007 amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0; 1008 1009 /* 1010 * TODO FIXME How do we handle MSDUs that have fraglist - Should 1011 * probably iterate all the frags cloning them along the way and 1012 * and also updating the prev_buf pointer 1013 */ 1014 1015 /* Move to the next */ 1016 prev_buf = msdu; 1017 msdu_orig = qdf_nbuf_next(msdu_orig); 1018 } 1019 1020 /* TODO: Convert this to suitable qdf routines */ 1021 qdf_nbuf_append_ext_list(mpdu_buf, head_frag_list_cloned, 1022 frag_list_sum_len); 1023 1024 mpdu_stitch_done: 1025 /* Check if this buffer contains the PPDU end status for TSF */ 1026 if (rx_desc->attention.last_mpdu) 1027 #ifdef HELIUMPLUS 1028 rx_status->rs_tstamp.tsf = 1029 rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; 1030 #else 1031 rx_status->rs_tstamp.tsf = rx_desc->ppdu_end.tsf_timestamp; 1032 #endif 1033 /* All the nbufs have been linked into the ext list 1034 * and then unlink the nbuf list 1035 */ 1036 if (clone_not_reqd) { 1037 msdu = head_msdu; 1038 while (msdu) { 1039 msdu_orig = msdu; 1040 msdu = qdf_nbuf_next(msdu); 1041 qdf_nbuf_set_next(msdu_orig, NULL); 1042 } 1043 } 1044 1045 return mpdu_buf; 1046 1047 mpdu_stitch_fail: 1048 /* Free these alloced buffers and the orig buffers in non-clone case */ 1049 if (!clone_not_reqd) { 1050 /* Free the head buffer */ 1051 if (mpdu_buf) 1052 qdf_nbuf_free(mpdu_buf); 1053 1054 /* Free the partial list */ 1055 while (head_frag_list_cloned) { 1056 msdu = head_frag_list_cloned; 1057 head_frag_list_cloned = 1058 qdf_nbuf_next_ext(head_frag_list_cloned); 1059 qdf_nbuf_free(msdu); 1060 } 1061 } else { 1062 /* Free the alloced head buffer */ 1063 if (decap_format != HW_RX_DECAP_FORMAT_RAW) 1064 if (mpdu_buf) 1065 qdf_nbuf_free(mpdu_buf); 1066 1067 /* Free the orig buffers */ 1068 msdu = head_msdu; 1069 while (msdu) { 1070 msdu_orig = msdu; 1071 msdu = qdf_nbuf_next(msdu); 1072 qdf_nbuf_free(msdu_orig); 1073 } 1074 } 1075 1076 return NULL; 1077 } 1078 #endif 1079 #endif 1080