1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #include "qdf_util.h" 30 #include "qdf_types.h" 31 #include "qdf_lock.h" 32 #include "qdf_mem.h" 33 #include "qdf_nbuf.h" 34 #include "tcl_data_cmd.h" 35 #include "mac_tcl_reg_seq_hwioreg.h" 36 #include "phyrx_rssi_legacy.h" 37 #include "rx_msdu_start.h" 38 #include "tlv_tag_def.h" 39 #include "hal_hw_headers.h" 40 #include "hal_internal.h" 41 #include "cdp_txrx_mon_struct.h" 42 #include "qdf_trace.h" 43 #include "hal_rx.h" 44 #include "hal_tx.h" 45 #include "dp_types.h" 46 #include "hal_api_mon.h" 47 #include "phyrx_other_receive_info_ru_details.h" 48 49 #if defined(QCA_WIFI_QCA6290_11AX) 50 #define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ 51 (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ 52 RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ 53 RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ 54 RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) 55 56 /* 57 * hal_rx_msdu_start_nss_get_6290(): API to get the NSS 58 * Interval from rx_msdu_start 59 * 60 * @buf: pointer to the start of RX PKT TLV header 61 * Return: uint32_t(nss) 62 */ 63 static uint32_t 64 hal_rx_msdu_start_nss_get_6290(uint8_t *buf) 65 { 66 struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; 67 struct rx_msdu_start *msdu_start = 68 &pkt_tlvs->msdu_start_tlv.rx_msdu_start; 69 uint8_t mimo_ss_bitmap; 70 71 mimo_ss_bitmap = HAL_RX_MSDU_START_MIMO_SS_BITMAP(msdu_start); 72 73 return qdf_get_hweight8(mimo_ss_bitmap); 74 } 75 #else 76 static uint32_t 77 hal_rx_msdu_start_nss_get_6290(uint8_t *buf) 78 { 79 struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; 80 struct rx_msdu_start *msdu_start = 81 &pkt_tlvs->msdu_start_tlv.rx_msdu_start; 82 uint32_t nss; 83 84 nss = HAL_RX_MSDU_START_NSS_GET(msdu_start); 85 return nss; 86 } 87 #endif 88 89 /** 90 * hal_rx_mon_hw_desc_get_mpdu_status_6290(): Retrieve MPDU status 91 * 92 * @ hw_desc_addr: Start address of Rx HW TLVs 93 * @ rs: Status for monitor mode 94 * 95 * Return: void 96 */ 97 static void hal_rx_mon_hw_desc_get_mpdu_status_6290(void *hw_desc_addr, 98 struct mon_rx_status *rs) 99 { 100 struct rx_msdu_start *rx_msdu_start; 101 struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; 102 uint32_t reg_value; 103 const uint32_t sgi_hw_to_cdp[] = { 104 CDP_SGI_0_8_US, 105 CDP_SGI_0_4_US, 106 CDP_SGI_1_6_US, 107 CDP_SGI_3_2_US, 108 }; 109 110 rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; 111 112 HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs); 113 114 rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, 115 RX_MSDU_START_5, USER_RSSI); 116 rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); 117 118 reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); 119 rs->sgi = sgi_hw_to_cdp[reg_value]; 120 #if !defined(QCA_WIFI_QCA6290_11AX) 121 rs->nr_ant = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS); 122 #endif 123 reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE); 124 switch (reg_value) { 125 case HAL_RX_PKT_TYPE_11N: 126 rs->ht_flags = 1; 127 break; 128 case HAL_RX_PKT_TYPE_11AC: 129 rs->vht_flags = 1; 130 reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, 131 RECEIVE_BANDWIDTH); 132 rs->vht_flag_values2 = reg_value; 133 break; 134 case HAL_RX_PKT_TYPE_11AX: 135 rs->he_flags = 1; 136 break; 137 default: 138 break; 139 } 140 reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); 141 rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; 142 /* TODO: rs->beamformed should be set for SU beamforming also */ 143 } 144 145 #define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) 146 147 static uint32_t hal_get_link_desc_size_6290(void) 148 { 149 return LINK_DESC_SIZE; 150 } 151 152 153 #ifdef QCA_WIFI_QCA6290_11AX 154 /* 155 * hal_rx_get_tlv_6290(): API to get the tlv 156 * 157 * @rx_tlv: TLV data extracted from the rx packet 158 * Return: uint8_t 159 */ 160 static uint8_t hal_rx_get_tlv_6290(void *rx_tlv) 161 { 162 return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); 163 } 164 #else 165 static uint8_t hal_rx_get_tlv_6290(void *rx_tlv) 166 { 167 return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_35, RECEIVE_BANDWIDTH); 168 } 169 #endif 170 171 #ifdef QCA_WIFI_QCA6290_11AX 172 /** 173 * hal_rx_proc_phyrx_other_receive_info_tlv_6290() 174 * - process other receive info TLV 175 * @rx_tlv_hdr: pointer to TLV header 176 * @ppdu_info: pointer to ppdu_info 177 * 178 * Return: None 179 */ 180 static 181 void hal_rx_proc_phyrx_other_receive_info_tlv_6290(void *rx_tlv_hdr, 182 void *ppdu_info_handle) 183 { 184 uint32_t tlv_tag, tlv_len; 185 uint32_t temp_len, other_tlv_len, other_tlv_tag; 186 void *rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; 187 void *other_tlv_hdr = NULL; 188 void *other_tlv = NULL; 189 uint32_t ru_details_channel_0; 190 struct hal_rx_ppdu_info *ppdu_info = 191 (struct hal_rx_ppdu_info *)ppdu_info_handle; 192 193 tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv_hdr); 194 tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv_hdr); 195 temp_len = 0; 196 197 other_tlv_hdr = rx_tlv + HAL_RX_TLV32_HDR_SIZE; 198 199 other_tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(other_tlv_hdr); 200 other_tlv_len = HAL_RX_GET_USER_TLV32_LEN(other_tlv_hdr); 201 temp_len += other_tlv_len; 202 other_tlv = other_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; 203 204 switch (other_tlv_tag) { 205 case WIFIPHYRX_OTHER_RECEIVE_INFO_RU_DETAILS_E: 206 ru_details_channel_0 = 207 HAL_RX_GET(other_tlv, 208 PHYRX_OTHER_RECEIVE_INFO_RU_DETAILS_0, 209 RU_DETAILS_CHANNEL_0); 210 211 qdf_mem_copy(ppdu_info->rx_status.he_RU, 212 &ru_details_channel_0, 213 sizeof(ppdu_info->rx_status.he_RU)); 214 215 if (ppdu_info->rx_status.bw >= HAL_FULL_RX_BW_20) 216 ppdu_info->rx_status.he_sig_b_common_known |= 217 QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0; 218 219 if (ppdu_info->rx_status.bw >= HAL_FULL_RX_BW_40) 220 ppdu_info->rx_status.he_sig_b_common_known |= 221 QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU1; 222 223 if (ppdu_info->rx_status.bw >= HAL_FULL_RX_BW_80) 224 ppdu_info->rx_status.he_sig_b_common_known |= 225 QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU2; 226 227 if (ppdu_info->rx_status.bw >= HAL_FULL_RX_BW_160) 228 ppdu_info->rx_status.he_sig_b_common_known |= 229 QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU3; 230 break; 231 default: 232 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 233 "%s unhandled TLV type: %d, TLV len:%d", 234 __func__, other_tlv_tag, other_tlv_len); 235 break; 236 } 237 } 238 #else 239 static 240 void hal_rx_proc_phyrx_other_receive_info_tlv_6290(void *rx_tlv_hdr, 241 void *ppdu_info_handle) 242 { 243 } 244 #endif /* QCA_WIFI_QCA6290_11AX */ 245 246 /** 247 * hal_rx_dump_msdu_start_tlv_6290() : dump RX msdu_start TLV in structured 248 * human readable format. 249 * @ msdu_start: pointer the msdu_start TLV in pkt. 250 * @ dbg_level: log level. 251 * 252 * Return: void 253 */ 254 static void hal_rx_dump_msdu_start_tlv_6290(void *msdustart, 255 uint8_t dbg_level) 256 { 257 struct rx_msdu_start *msdu_start = (struct rx_msdu_start *)msdustart; 258 259 QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, 260 "rx_msdu_start tlv - " 261 "rxpcu_mpdu_filter_in_category: %d " 262 "sw_frame_group_id: %d " 263 "phy_ppdu_id: %d " 264 "msdu_length: %d " 265 "ipsec_esp: %d " 266 "l3_offset: %d " 267 "ipsec_ah: %d " 268 "l4_offset: %d " 269 "msdu_number: %d " 270 "decap_format: %d " 271 "ipv4_proto: %d " 272 "ipv6_proto: %d " 273 "tcp_proto: %d " 274 "udp_proto: %d " 275 "ip_frag: %d " 276 "tcp_only_ack: %d " 277 "da_is_bcast_mcast: %d " 278 "ip4_protocol_ip6_next_header: %d " 279 "toeplitz_hash_2_or_4: %d " 280 "flow_id_toeplitz: %d " 281 "user_rssi: %d " 282 "pkt_type: %d " 283 "stbc: %d " 284 "sgi: %d " 285 "rate_mcs: %d " 286 "receive_bandwidth: %d " 287 "reception_type: %d " 288 #if !defined(QCA_WIFI_QCA6290_11AX) 289 "toeplitz_hash: %d " 290 "nss: %d " 291 #endif 292 "ppdu_start_timestamp: %d " 293 "sw_phy_meta_data: %d ", 294 msdu_start->rxpcu_mpdu_filter_in_category, 295 msdu_start->sw_frame_group_id, 296 msdu_start->phy_ppdu_id, 297 msdu_start->msdu_length, 298 msdu_start->ipsec_esp, 299 msdu_start->l3_offset, 300 msdu_start->ipsec_ah, 301 msdu_start->l4_offset, 302 msdu_start->msdu_number, 303 msdu_start->decap_format, 304 msdu_start->ipv4_proto, 305 msdu_start->ipv6_proto, 306 msdu_start->tcp_proto, 307 msdu_start->udp_proto, 308 msdu_start->ip_frag, 309 msdu_start->tcp_only_ack, 310 msdu_start->da_is_bcast_mcast, 311 msdu_start->ip4_protocol_ip6_next_header, 312 msdu_start->toeplitz_hash_2_or_4, 313 msdu_start->flow_id_toeplitz, 314 msdu_start->user_rssi, 315 msdu_start->pkt_type, 316 msdu_start->stbc, 317 msdu_start->sgi, 318 msdu_start->rate_mcs, 319 msdu_start->receive_bandwidth, 320 msdu_start->reception_type, 321 #if !defined(QCA_WIFI_QCA6290_11AX) 322 msdu_start->toeplitz_hash, 323 msdu_start->nss, 324 #endif 325 msdu_start->ppdu_start_timestamp, 326 msdu_start->sw_phy_meta_data); 327 } 328 329 /** 330 * hal_rx_dump_msdu_end_tlv_6290: dump RX msdu_end TLV in structured 331 * human readable format. 332 * @ msdu_end: pointer the msdu_end TLV in pkt. 333 * @ dbg_level: log level. 334 * 335 * Return: void 336 */ 337 static void hal_rx_dump_msdu_end_tlv_6290(void *msduend, 338 uint8_t dbg_level) 339 { 340 struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; 341 342 QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, 343 "rx_msdu_end tlv - " 344 "rxpcu_mpdu_filter_in_category: %d " 345 "sw_frame_group_id: %d " 346 "phy_ppdu_id: %d " 347 "ip_hdr_chksum: %d " 348 "tcp_udp_chksum: %d " 349 "key_id_octet: %d " 350 "cce_super_rule: %d " 351 "cce_classify_not_done_truncat: %d " 352 "cce_classify_not_done_cce_dis: %d " 353 "ext_wapi_pn_63_48: %d " 354 "ext_wapi_pn_95_64: %d " 355 "ext_wapi_pn_127_96: %d " 356 "reported_mpdu_length: %d " 357 "first_msdu: %d " 358 "last_msdu: %d " 359 "sa_idx_timeout: %d " 360 "da_idx_timeout: %d " 361 "msdu_limit_error: %d " 362 "flow_idx_timeout: %d " 363 "flow_idx_invalid: %d " 364 "wifi_parser_error: %d " 365 "amsdu_parser_error: %d " 366 "sa_is_valid: %d " 367 "da_is_valid: %d " 368 "da_is_mcbc: %d " 369 "l3_header_padding: %d " 370 "ipv6_options_crc: %d " 371 "tcp_seq_number: %d " 372 "tcp_ack_number: %d " 373 "tcp_flag: %d " 374 "lro_eligible: %d " 375 "window_size: %d " 376 "da_offset: %d " 377 "sa_offset: %d " 378 "da_offset_valid: %d " 379 "sa_offset_valid: %d " 380 "rule_indication_31_0: %d " 381 "rule_indication_63_32: %d " 382 "sa_idx: %d " 383 "da_idx: %d " 384 "msdu_drop: %d " 385 "reo_destination_indication: %d " 386 "flow_idx: %d " 387 "fse_metadata: %d " 388 "cce_metadata: %d " 389 "sa_sw_peer_id: %d ", 390 msdu_end->rxpcu_mpdu_filter_in_category, 391 msdu_end->sw_frame_group_id, 392 msdu_end->phy_ppdu_id, 393 msdu_end->ip_hdr_chksum, 394 msdu_end->tcp_udp_chksum, 395 msdu_end->key_id_octet, 396 msdu_end->cce_super_rule, 397 msdu_end->cce_classify_not_done_truncate, 398 msdu_end->cce_classify_not_done_cce_dis, 399 msdu_end->ext_wapi_pn_63_48, 400 msdu_end->ext_wapi_pn_95_64, 401 msdu_end->ext_wapi_pn_127_96, 402 msdu_end->reported_mpdu_length, 403 msdu_end->first_msdu, 404 msdu_end->last_msdu, 405 msdu_end->sa_idx_timeout, 406 msdu_end->da_idx_timeout, 407 msdu_end->msdu_limit_error, 408 msdu_end->flow_idx_timeout, 409 msdu_end->flow_idx_invalid, 410 msdu_end->wifi_parser_error, 411 msdu_end->amsdu_parser_error, 412 msdu_end->sa_is_valid, 413 msdu_end->da_is_valid, 414 msdu_end->da_is_mcbc, 415 msdu_end->l3_header_padding, 416 msdu_end->ipv6_options_crc, 417 msdu_end->tcp_seq_number, 418 msdu_end->tcp_ack_number, 419 msdu_end->tcp_flag, 420 msdu_end->lro_eligible, 421 msdu_end->window_size, 422 msdu_end->da_offset, 423 msdu_end->sa_offset, 424 msdu_end->da_offset_valid, 425 msdu_end->sa_offset_valid, 426 msdu_end->rule_indication_31_0, 427 msdu_end->rule_indication_63_32, 428 msdu_end->sa_idx, 429 msdu_end->da_idx, 430 msdu_end->msdu_drop, 431 msdu_end->reo_destination_indication, 432 msdu_end->flow_idx, 433 msdu_end->fse_metadata, 434 msdu_end->cce_metadata, 435 msdu_end->sa_sw_peer_id); 436 } 437 438 439 /* 440 * Get tid from RX_MPDU_START 441 */ 442 #define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ 443 (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ 444 RX_MPDU_INFO_3_TID_OFFSET)), \ 445 RX_MPDU_INFO_3_TID_MASK, \ 446 RX_MPDU_INFO_3_TID_LSB)) 447 448 static uint32_t hal_rx_mpdu_start_tid_get_6290(uint8_t *buf) 449 { 450 struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; 451 struct rx_mpdu_start *mpdu_start = 452 &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; 453 uint32_t tid; 454 455 tid = HAL_RX_MPDU_INFO_TID_GET(&mpdu_start->rx_mpdu_info_details); 456 457 return tid; 458 } 459 460 #define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \ 461 (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start), \ 462 RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)), \ 463 RX_MSDU_START_5_RECEPTION_TYPE_MASK, \ 464 RX_MSDU_START_5_RECEPTION_TYPE_LSB)) 465 466 /* 467 * hal_rx_msdu_start_reception_type_get(): API to get the reception type 468 * Interval from rx_msdu_start 469 * 470 * @buf: pointer to the start of RX PKT TLV header 471 * Return: uint32_t(reception_type) 472 */ 473 static uint32_t hal_rx_msdu_start_reception_type_get_6290(uint8_t *buf) 474 { 475 struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; 476 struct rx_msdu_start *msdu_start = 477 &pkt_tlvs->msdu_start_tlv.rx_msdu_start; 478 uint32_t reception_type; 479 480 reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start); 481 482 return reception_type; 483 } 484 485 #define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ 486 (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ 487 RX_MSDU_END_13_DA_IDX_OFFSET)), \ 488 RX_MSDU_END_13_DA_IDX_MASK, \ 489 RX_MSDU_END_13_DA_IDX_LSB)) 490 491 /** 492 * hal_rx_msdu_end_da_idx_get_6290: API to get da_idx 493 * from rx_msdu_end TLV 494 * 495 * @ buf: pointer to the start of RX PKT TLV headers 496 * Return: da index 497 */ 498 static uint16_t hal_rx_msdu_end_da_idx_get_6290(uint8_t *buf) 499 { 500 struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; 501 struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; 502 uint16_t da_idx; 503 504 da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); 505 506 return da_idx; 507 } 508 509