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