diff --git a/Kbuild b/Kbuild index 50ee1ce8ee73..9b4de21d1009 100644 --- a/Kbuild +++ b/Kbuild @@ -946,6 +946,9 @@ HTT_OBJS := $(HTT_DIR)/htt_tx.o \ $(HTT_DIR)/htt_fw_stats.o \ $(HTT_DIR)/htt_rx.o +ifeq ($(CONFIG_FEATURE_MONITOR_MODE_SUPPORT), y) +HTT_OBJS += $(HTT_DIR)/htt_monitor_rx.o +endif ############## INIT-DEINIT ########### INIT_DEINIT_DIR := init_deinit/dispatcher @@ -1487,6 +1490,7 @@ cppflags-$(CONFIG_HDD_INIT_WITH_RTNL_LOCK) += -DCONFIG_HDD_INIT_WITH_RTNL_LOCK cppflags-$(CONFIG_CONVERGED_TDLS_ENABLE) += -DCONVERGED_TDLS_ENABLE cppflags-$(CONFIG_WLAN_CONV_SPECTRAL_ENABLE) += -DWLAN_CONV_SPECTRAL_ENABLE cppflags-$(CONFIG_WMI_CMD_STRINGS) += -DWMI_CMD_STRINGS +cppflags-$(CONFIG_FEATURE_MONITOR_MODE_SUPPORT) += -DFEATURE_MONITOR_MODE_SUPPORT cppflags-$(CONFIG_WLAN_DISABLE_EXPORT_SYMBOL) += -DWLAN_DISABLE_EXPORT_SYMBOL cppflags-$(CONFIG_WIFI_POS_CONVERGED) += -DWIFI_POS_CONVERGED diff --git a/configs/default_defconfig b/configs/default_defconfig index 22394ac1e9c9..3b23a00c967c 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -507,6 +507,7 @@ CONFIG_CONVERGED_TDLS_ENABLE := y CONFIG_WLAN_CONV_SPECTRAL_ENABLE := y CONFIG_WLAN_SPECTRAL_ENABLE := y CONFIG_WMI_CMD_STRINGS := y +CONFIG_FEATURE_MONITOR_MODE_SUPPORT := y ifeq ($(CONFIG_HELIUMPLUS), y) ifneq ($(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE), y) diff --git a/configs/genoa.snoc.debug_defconfig b/configs/genoa.snoc.debug_defconfig index 814799e60913..4d06e87c713c 100644 --- a/configs/genoa.snoc.debug_defconfig +++ b/configs/genoa.snoc.debug_defconfig @@ -60,6 +60,7 @@ CONFIG_TX_CREDIT_RECLAIM_SUPPORT := n CONFIG_CHECKSUM_OFFLOAD := y CONFIG_QCA_SUPPORT_TX_THROTTLE := y CONFIG_RX_OL := y +CONFIG_FEATURE_MONITOR_MODE_SUPPORT := y ifeq ($(CONFIG_INET_LRO), y) CONFIG_WLAN_LRO := y diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index 1d7ee758ce37..290ced7d0f35 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -896,4 +896,141 @@ void htt_rx_dbg_rxbuf_deinit(struct htt_pdev_t *pdev) return; } #endif + +#ifndef CONFIG_HL_SUPPORT + +#ifdef HTT_DEBUG_DATA +#define HTT_PKT_DUMP(x) x +#else +#define HTT_PKT_DUMP(x) /* no-op */ +#endif + +#ifdef RX_HASH_DEBUG +#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) HTT_ASSERT_ALWAYS(msdu_count) +#else +#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) /* no-op */ +#endif + +#if HTT_PADDR64 +#define NEXT_FIELD_OFFSET_IN32 2 +#else /* ! HTT_PADDR64 */ +#define NEXT_FIELD_OFFSET_IN32 1 +#endif /* HTT_PADDR64 */ + +#define RX_PADDR_MAGIC_PATTERN 0xDEAD0000 + +#if HTT_PADDR64 +static inline qdf_dma_addr_t htt_paddr_trim_to_37(qdf_dma_addr_t paddr) +{ + qdf_dma_addr_t ret = paddr; + + if (sizeof(paddr) > 4) + ret &= 0x1fffffffff; + return ret; +} +#else /* not 64 bits */ +static inline qdf_dma_addr_t htt_paddr_trim_to_37(qdf_dma_addr_t paddr) +{ + return paddr; +} +#endif /* HTT_PADDR64 */ + +#ifdef ENABLE_DEBUG_ADDRESS_MARKING +static inline qdf_dma_addr_t +htt_rx_paddr_unmark_high_bits(qdf_dma_addr_t paddr) +{ + uint32_t markings; + + if (sizeof(qdf_dma_addr_t) > 4) { + markings = (uint32_t)((paddr >> 16) >> 16); + /* + * check if it is marked correctly: + * See the mark_high_bits function above for the expected + * pattern. + * the LS 5 bits are the high bits of physical address + * padded (with 0b0) to 8 bits + */ + if ((markings & 0xFFFF0000) != RX_PADDR_MAGIC_PATTERN) { + qdf_print("%s: paddr not marked correctly: 0x%pK!\n", + __func__, (void *)paddr); + HTT_ASSERT_ALWAYS(0); + } + + /* clear markings for further use */ + paddr = htt_paddr_trim_to_37(paddr); + } + return paddr; +} + +static inline +qdf_dma_addr_t htt_rx_in_ord_paddr_get(uint32_t *u32p) +{ + qdf_dma_addr_t paddr = 0; + + paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); + if (sizeof(qdf_dma_addr_t) > 4) { + u32p++; + /* 32 bit architectures dont like <<32 */ + paddr |= (((qdf_dma_addr_t) + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p)) + << 16 << 16); + } + paddr = htt_rx_paddr_unmark_high_bits(paddr); + + return paddr; +} +#else +#if HTT_PADDR64 +static inline +qdf_dma_addr_t htt_rx_in_ord_paddr_get(uint32_t *u32p) +{ + qdf_dma_addr_t paddr = 0; + + paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); + if (sizeof(qdf_dma_addr_t) > 4) { + u32p++; + /* 32 bit architectures dont like <<32 */ + paddr |= (((qdf_dma_addr_t) + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p)) + << 16 << 16); + } + return paddr; +} +#else +static inline +qdf_dma_addr_t htt_rx_in_ord_paddr_get(uint32_t *u32p) +{ + return HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); +} +#endif +#endif /* ENABLE_DEBUG_ADDRESS_MARKING */ + +static inline qdf_nbuf_t +htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, qdf_dma_addr_t paddr) +{ + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + pdev->rx_ring.fill_cnt--; + paddr = htt_paddr_trim_to_37(paddr); + return htt_rx_hash_list_lookup(pdev, paddr); +} + +#ifdef FEATURE_MONITOR_MODE_SUPPORT +int 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); +#else +static inline +int 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) +{ + return 0; +} +#endif +#endif + #endif /* _HTT_INTERNAL__H_ */ diff --git a/core/dp/htt/htt_monitor_rx.c b/core/dp/htt/htt_monitor_rx.c new file mode 100644 index 000000000000..f8cd4ec0fccf --- /dev/null +++ b/core/dp/htt/htt_monitor_rx.c @@ -0,0 +1,1055 @@ +/* + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include /* qdf_mem_malloc,free, etc. */ +#include /* qdf_print, bool */ +#include /* qdf_nbuf_t, etc. */ +#include /* qdf_timer_free */ + +#include /* HTT_HL_RX_DESC_SIZE */ +#include +#include +#include +#include /* HTT_ASSERT, htt_pdev_t, HTT_RX_BUF_SIZE */ +#include "regtable.h" + +#include /* ieee80211_frame, ieee80211_qoscntl */ +#include /* ieee80211_rx_status */ +#include +#include +#include "ol_txrx_types.h" +#ifdef DEBUG_DMA_DONE +#include +#include +#endif +#include + +#define HTT_FCS_LEN (4) + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +enum { + HW_RX_DECAP_FORMAT_RAW = 0, + HW_RX_DECAP_FORMAT_NWIFI, + HW_RX_DECAP_FORMAT_8023, + HW_RX_DECAP_FORMAT_ETH2, +}; + +/** + * htt_rx_mon_note_capture_channel() - Make note of channel to update in + * radiotap + * @pdev: handle to htt_pdev + * @mon_ch: capture channel number. + * + * Return: None + */ +void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch) +{ + struct mon_channel *ch_info = &pdev->mon_ch_info; + + ch_info->ch_num = mon_ch; + ch_info->ch_freq = cds_chan_to_freq(mon_ch); +} + +#ifndef CONFIG_HL_SUPPORT +/** + * htt_mon_rx_handle_amsdu_packet() - Handle consecutive fragments of amsdu + * @msdu: pointer to first msdu of amsdu + * @pdev: Handle to htt_pdev_handle + * @msg_word: Input and output variable, so pointer to HTT msg pointer + * @amsdu_len: remaining length of all N-1 msdu msdu's + * @frag_cnt: number of frags handled + * + * This function handles the (N-1) msdu's of amsdu, N'th msdu is already + * handled by calling function. N-1 msdu's are tied using frags_list. + * msdu_info field updated by FW indicates if this is last msdu. All the + * msdu's before last msdu will be of MAX payload. + * + * Return: 1 on success and 0 on failure. + */ +static +int 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) +{ + qdf_nbuf_t frag_nbuf; + qdf_nbuf_t prev_frag_nbuf; + uint32_t len; + uint32_t last_frag; + qdf_dma_addr_t paddr; + + *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + paddr = htt_rx_in_ord_paddr_get(*msg_word); + frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); + if (qdf_unlikely(!frag_nbuf)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + return 0; + } + *frag_cnt = *frag_cnt + 1; + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)*msg_word)-> + msdu_info; + qdf_nbuf_append_ext_list(msdu, frag_nbuf, amsdu_len); + qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); + /* For msdu's other than parent will not have htt_host_rx_desc_base */ + len = MIN(amsdu_len, HTT_RX_BUF_SIZE); + amsdu_len -= len; + qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); + + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO_HIGH, + qdf_nbuf_data(frag_nbuf), + qdf_nbuf_len(frag_nbuf))); + prev_frag_nbuf = frag_nbuf; + while (!last_frag) { + *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + paddr = htt_rx_in_ord_paddr_get(*msg_word); + frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) + *msg_word)->msdu_info; + + if (qdf_unlikely(!frag_nbuf)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + prev_frag_nbuf->next = NULL; + return 0; + } + *frag_cnt = *frag_cnt + 1; + qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); + + len = MIN(amsdu_len, HTT_RX_BUF_SIZE); + amsdu_len -= len; + qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO_HIGH, + qdf_nbuf_data(frag_nbuf), + qdf_nbuf_len(frag_nbuf))); + + qdf_nbuf_set_next(prev_frag_nbuf, frag_nbuf); + prev_frag_nbuf = frag_nbuf; + } + qdf_nbuf_set_next(prev_frag_nbuf, NULL); + return 1; +} + +#define SHORT_PREAMBLE 1 +#define LONG_PREAMBLE 0 +#ifdef HELIUMPLUS +/** + * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc + * @l_sig_rate_select: OFDM or CCK rate + * @l_sig_rate: + * + * If l_sig_rate_select is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If l_sig_rate_select is 1: + * 0x1: DSSS 1 Mbps long preamble + * 0x2: DSSS 2 Mbps long preamble + * 0x3: CCK 5.5 Mbps long preamble + * 0x4: CCK 11 Mbps long preamble + * 0x5: DSSS 2 Mbps short preamble + * 0x6: CCK 5.5 Mbps + * 0x7: CCK 11 Mbps short preamble + * + * Return: rate interms of 500Kbps. + */ +static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, + uint32_t l_sig_rate, uint8_t *preamble) +{ + char ret = 0x0; + *preamble = SHORT_PREAMBLE; + if (l_sig_rate_select == 0) { + switch (l_sig_rate) { + case 0x8: + ret = 0x60; + break; + case 0x9: + ret = 0x30; + break; + case 0xA: + ret = 0x18; + break; + case 0xB: + ret = 0x0c; + break; + case 0xC: + ret = 0x6c; + break; + case 0xD: + ret = 0x48; + break; + case 0xE: + ret = 0x24; + break; + case 0xF: + ret = 0x12; + break; + default: + break; + } + } else if (l_sig_rate_select == 1) { + switch (l_sig_rate) { + case 0x1: + ret = 0x2; + *preamble = LONG_PREAMBLE; + break; + case 0x2: + ret = 0x4; + *preamble = LONG_PREAMBLE; + break; + case 0x3: + ret = 0xB; + *preamble = LONG_PREAMBLE; + break; + case 0x4: + ret = 0x16; + *preamble = LONG_PREAMBLE; + break; + case 0x5: + ret = 0x4; + break; + case 0x6: + ret = 0xB; + break; + case 0x7: + ret = 0x16; + break; + default: + break; + } + } else { + qdf_print("Invalid rate info\n"); + } + return ret; +} +#else +/** + * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc + * @l_sig_rate_select: OFDM or CCK rate + * @l_sig_rate: + * + * If l_sig_rate_select is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If l_sig_rate_select is 1: + * 0x8: CCK 11 Mbps long preamble + * 0x9: CCK 5.5 Mbps long preamble + * 0xA: CCK 2 Mbps long preamble + * 0xB: CCK 1 Mbps long preamble + * 0xC: CCK 11 Mbps short preamble + * 0xD: CCK 5.5 Mbps short preamble + * 0xE: CCK 2 Mbps short preamble + * + * Return: rate interms of 500Kbps. + */ +static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, + uint32_t l_sig_rate, uint8_t *preamble) +{ + char ret = 0x0; + *preamble = SHORT_PREAMBLE; + if (l_sig_rate_select == 0) { + switch (l_sig_rate) { + case 0x8: + ret = 0x60; + break; + case 0x9: + ret = 0x30; + break; + case 0xA: + ret = 0x18; + break; + case 0xB: + ret = 0x0c; + break; + case 0xC: + ret = 0x6c; + break; + case 0xD: + ret = 0x48; + break; + case 0xE: + ret = 0x24; + break; + case 0xF: + ret = 0x12; + break; + default: + break; + } + } else if (l_sig_rate_select == 1) { + switch (l_sig_rate) { + case 0x8: + ret = 0x16; + *preamble = LONG_PREAMBLE; + break; + case 0x9: + ret = 0x0B; + *preamble = LONG_PREAMBLE; + break; + case 0xA: + ret = 0x4; + *preamble = LONG_PREAMBLE; + break; + case 0xB: + ret = 0x02; + *preamble = LONG_PREAMBLE; + break; + case 0xC: + ret = 0x16; + break; + case 0xD: + ret = 0x0B; + break; + case 0xE: + ret = 0x04; + break; + default: + break; + } + } else { + qdf_print("Invalid rate info\n"); + } + return ret; +} +#endif /* HELIUMPLUS */ + +/** + * htt_mon_rx_get_phy_info() - Get phy info + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * @rx_status: Return variable updated with phy_info in rx_status + * + * Return: None + */ +static void htt_mon_rx_get_phy_info(struct htt_host_rx_desc_base *rx_desc, + struct mon_rx_status *rx_status) +{ + uint8_t preamble = 0; + uint8_t preamble_type = rx_desc->ppdu_start.preamble_type; + uint8_t mcs = 0, nss = 0, sgi = 0, bw = 0, beamformed = 0; + uint16_t vht_flags = 0, ht_flags = 0; + uint32_t l_sig_rate_select = rx_desc->ppdu_start.l_sig_rate_select; + uint32_t l_sig_rate = rx_desc->ppdu_start.l_sig_rate; + bool is_stbc = 0, ldpc = 0; + + switch (preamble_type) { + case 4: + /* legacy */ + rx_status->rate = htt_rx_get_rate(l_sig_rate_select, l_sig_rate, + &preamble); + break; + case 8: + is_stbc = ((VHT_SIG_A_2(rx_desc) >> 4) & 3); + /* fallthrough */ + case 9: + ht_flags = 1; + sgi = (VHT_SIG_A_2(rx_desc) >> 7) & 0x01; + bw = (VHT_SIG_A_1(rx_desc) >> 7) & 0x01; + mcs = (VHT_SIG_A_1(rx_desc) & 0x7f); + nss = mcs >> 3; + beamformed = + (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; + break; + case 0x0c: + is_stbc = (VHT_SIG_A_2(rx_desc) >> 3) & 1; + ldpc = (VHT_SIG_A_2(rx_desc) >> 2) & 1; + /* fallthrough */ + case 0x0d: + { + uint8_t gid_in_sig = ((VHT_SIG_A_1(rx_desc) >> 4) & 0x3f); + + vht_flags = 1; + sgi = VHT_SIG_A_2(rx_desc) & 0x01; + bw = (VHT_SIG_A_1(rx_desc) & 0x03); + if (gid_in_sig == 0 || gid_in_sig == 63) { + /* SU case */ + mcs = (VHT_SIG_A_2(rx_desc) >> 4) & + 0xf; + nss = (VHT_SIG_A_1(rx_desc) >> 10) & + 0x7; + } else { + /* MU case */ + uint8_t sta_user_pos = + (uint8_t)((rx_desc->ppdu_start.reserved_4a >> 8) + & 0x3); + mcs = (rx_desc->ppdu_start.vht_sig_b >> 16); + if (bw >= 2) + mcs >>= 3; + else if (bw > 0) + mcs >>= 1; + mcs &= 0xf; + nss = (((VHT_SIG_A_1(rx_desc) >> 10) + + sta_user_pos * 3) & 0x7); + } + beamformed = (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; + } + /* fallthrough */ + default: + break; + } + + rx_status->mcs = mcs; + rx_status->bw = bw; + rx_status->nr_ant = nss; + rx_status->is_stbc = is_stbc; + rx_status->sgi = sgi; + rx_status->ldpc = ldpc; + rx_status->beamformed = beamformed; + rx_status->vht_flag_values3[0] = mcs << 0x4 | (nss + 1); + rx_status->ht_flags = ht_flags; + rx_status->vht_flags = vht_flags; + rx_status->rtap_flags |= ((preamble == SHORT_PREAMBLE) ? BIT(1) : 0); + if (bw == 0) + rx_status->vht_flag_values2 = 0; + else if (bw == 1) + rx_status->vht_flag_values2 = 1; + else if (bw == 2) + rx_status->vht_flag_values2 = 4; +} + +/** + * htt_mon_rx_get_rtap_flags() - Get radiotap flags + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * + * Return: Bitmapped radiotap flags. + */ +static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) +{ + uint8_t rtap_flags = 0; + + /* WEP40 || WEP104 || WEP128 */ + if (rx_desc->mpdu_start.encrypt_type == 0 || + rx_desc->mpdu_start.encrypt_type == 1 || + rx_desc->mpdu_start.encrypt_type == 3) + rtap_flags |= BIT(2); + + /* IEEE80211_RADIOTAP_F_FRAG */ + if (rx_desc->attention.fragment) + rtap_flags |= BIT(3); + + /* IEEE80211_RADIOTAP_F_FCS */ + rtap_flags |= BIT(4); + + /* IEEE80211_RADIOTAP_F_BADFCS */ + if (rx_desc->mpdu_end.fcs_err) + rtap_flags |= BIT(6); + + return rtap_flags; +} + +/** + * htt_rx_mon_get_rx_status() - Update information about the rx status, + * which is used later for radiotap updation. + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * @rx_status: Return variable updated with rx_status + * + * Return: None + */ +static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, + struct htt_host_rx_desc_base *rx_desc, + struct mon_rx_status *rx_status) +{ + uint16_t channel_flags = 0; + struct mon_channel *ch_info = &pdev->mon_ch_info; + + rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); + rx_status->chan_freq = ch_info->ch_freq; + rx_status->chan_num = ch_info->ch_num; + htt_mon_rx_get_phy_info(rx_desc, rx_status); + rx_status->rtap_flags |= htt_mon_rx_get_rtap_flags(rx_desc); + channel_flags |= rx_desc->ppdu_start.l_sig_rate_select ? + IEEE80211_CHAN_CCK : IEEE80211_CHAN_OFDM; + channel_flags |= + (cds_chan_to_band(ch_info->ch_num) == CDS_BAND_2GHZ ? + IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); + + rx_status->chan_flags = channel_flags; + rx_status->ant_signal_db = rx_desc->ppdu_start.rssi_comb; +} + +/** + * htt_rx_mon_amsdu_rx_in_order_pop_ll() - Monitor mode HTT Rx in order pop + * function + * @pdev: Handle to htt_pdev_handle + * @rx_ind_msg: In order indication message. + * @head_msdu: Return variable pointing to head msdu. + * @tail_msdu: Return variable pointing to tail msdu. + * + * This function pops the msdu based on paddr:length of inorder indication + * message. + * + * Return: 1 for success, 0 on failure. + */ +int 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) +{ + qdf_nbuf_t msdu, next, prev = NULL; + uint8_t *rx_ind_data; + uint32_t *msg_word; + uint32_t msdu_count; + struct htt_host_rx_desc_base *rx_desc; + struct mon_rx_status rx_status = {0}; + uint32_t amsdu_len; + uint32_t len; + uint32_t last_frag; + qdf_dma_addr_t paddr; + + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + + rx_ind_data = qdf_nbuf_data(rx_ind_msg); + msg_word = (uint32_t *)rx_ind_data; + + *replenish_cnt = 0; + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO_HIGH, + (void *)rx_ind_data, + (int)qdf_nbuf_len(rx_ind_msg))); + + /* Get the total number of MSDUs */ + msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); + HTT_RX_CHECK_MSDU_COUNT(msdu_count); + + msg_word = (uint32_t *)(rx_ind_data + + HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); + paddr = htt_rx_in_ord_paddr_get(msg_word); + msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); + + if (qdf_unlikely(!msdu)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + *tail_msdu = NULL; + return 0; + } + *replenish_cnt = *replenish_cnt + 1; + + while (msdu_count > 0) { + msdu_count--; + /* + * Set the netbuf length to be the entire buffer length + * initially, so the unmap will unmap the entire buffer. + */ + qdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); + + /* + * cache consistency has been taken care of by the + * qdf_nbuf_unmap + */ + rx_desc = htt_rx_desc(msdu); + if ((unsigned int)(*(uint32_t *)&rx_desc->attention) & + RX_DESC_ATTN_MPDU_LEN_ERR_BIT) { + qdf_nbuf_free(msdu); + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) + msg_word)->msdu_info; + while (!last_frag) { + msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + paddr = htt_rx_in_ord_paddr_get(msg_word); + msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); + last_frag = ((struct + htt_rx_in_ord_paddr_ind_msdu_t *) + msg_word)->msdu_info; + if (qdf_unlikely(!msdu)) { + qdf_print("%s: netbuf pop failed!\n", + __func__); + return 0; + } + *replenish_cnt = *replenish_cnt + 1; + qdf_nbuf_unmap(pdev->osdev, msdu, + QDF_DMA_FROM_DEVICE); + qdf_nbuf_free(msdu); + } + msdu = prev; + goto next_pop; + } + + if (!prev) + (*head_msdu) = msdu; + prev = msdu; + + HTT_PKT_DUMP(htt_print_rx_desc(rx_desc)); + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + htt_rx_mon_get_rx_status(pdev, rx_desc, &rx_status); + /* + * For certain platform, 350 bytes of headroom is already + * appended to accommodate radiotap header but + * qdf_nbuf_update_radiotap() API again will try to create + * a room for radiotap header. To make our design simple + * let qdf_nbuf_update_radiotap() API create a room for radiotap + * header and update it, do qdf_nbuf_pull_head() operation and + * pull 350 bytes of headroom. + * + * + * + * (SKB buffer) + * skb->head --> +-----------+ <-- skb->data + * | | (Before pulling headroom) + * | | + * | HEAD | 350 bytes of headroom + * | | + * | | + * +-----------+ <-- skb->data + * | | (After pulling headroom) + * | | + * | DATA | + * | | + * | | + * +-----------+ + * | | + * | | + * | TAIL | + * | | + * | | + * +-----------+ + * + */ + if (qdf_nbuf_head(msdu) == qdf_nbuf_data(msdu)) + qdf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); + qdf_nbuf_update_radiotap(&rx_status, msdu, + HTT_RX_STD_DESC_RESERVATION); + amsdu_len = HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(*(msg_word + + NEXT_FIELD_OFFSET_IN32)); + + /* + * MAX_RX_PAYLOAD_SZ when we have AMSDU packet. amsdu_len in + * which case is the total length of sum of all AMSDU's + */ + len = MIN(amsdu_len, MAX_RX_PAYLOAD_SZ); + amsdu_len -= len; + qdf_nbuf_trim_tail(msdu, HTT_RX_BUF_SIZE - + (RX_STD_DESC_SIZE + len)); + + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO_HIGH, + qdf_nbuf_data(msdu), + qdf_nbuf_len(msdu))); + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) + msg_word)->msdu_info; + + /* Handle amsdu packet */ + if (!last_frag) { + /* + * For AMSDU packet msdu->len is sum of all the msdu's + * length, msdu->data_len is sum of length's of + * remaining msdu's other than parent. + */ + if (!htt_mon_rx_handle_amsdu_packet(msdu, pdev, + &msg_word, + amsdu_len, + replenish_cnt)) { + qdf_print("%s: failed to handle amsdu packet\n", + __func__); + return 0; + } + } + +next_pop: + /* check if this is the last msdu */ + if (msdu_count) { + msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + paddr = htt_rx_in_ord_paddr_get(msg_word); + next = htt_rx_in_order_netbuf_pop(pdev, paddr); + if (qdf_unlikely(!next)) { + qdf_print("%s: netbuf pop failed!\n", + __func__); + *tail_msdu = NULL; + return 0; + } + *replenish_cnt = *replenish_cnt + 1; + if (msdu) + qdf_nbuf_set_next(msdu, next); + msdu = next; + } else { + *tail_msdu = msdu; + if (msdu) + qdf_nbuf_set_next(msdu, NULL); + } + } + + return 1; +} +#endif /* CONFIG_HL_SUPPORT */ + +#if !defined(QCA6290_HEADERS_DEF) +static void +htt_rx_parse_ppdu_start_status(struct htt_host_rx_desc_base *rx_desc, + struct ieee80211_rx_status *rs) +{ + struct rx_ppdu_start *ppdu_start = &rx_desc->ppdu_start; + + /* RSSI */ + rs->rs_rssi = ppdu_start->rssi_comb; + + /* PHY rate */ + /* + * rs_ratephy coding + * [b3 - b0] + * 0 -> OFDM + * 1 -> CCK + * 2 -> HT + * 3 -> VHT + * OFDM / CCK + * [b7 - b4 ] => LSIG rate + * [b23 - b8 ] => service field + * (b'12 static/dynamic, + * b'14..b'13 BW for VHT) + * [b31 - b24 ] => Reserved + * HT / VHT + * [b15 - b4 ] => SIG A_2 12 LSBs + * [b31 - b16] => SIG A_1 16 LSBs + */ + if (ppdu_start->preamble_type == 0x4) { + rs->rs_ratephy = ppdu_start->l_sig_rate_select; + rs->rs_ratephy |= ppdu_start->l_sig_rate << 4; + rs->rs_ratephy |= ppdu_start->service << 8; + } else { + rs->rs_ratephy = (ppdu_start->preamble_type & 0x4) ? 3 : 2; +#ifdef HELIUMPLUS + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_ah_sig_a_2 & 0xFFF) << 4; + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_ah_sig_a_1 & 0xFFFF) << 16; +#else + rs->rs_ratephy |= (ppdu_start->ht_sig_vht_sig_a_2 & 0xFFF) << 4; + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_a_1 & 0xFFFF) << 16; +#endif + } +} + +/* Util fake function that has same prototype as qdf_nbuf_clone that just + * returns the same nbuf + */ +static qdf_nbuf_t htt_rx_qdf_noclone_buf(qdf_nbuf_t buf) +{ + return buf; +} + +/* This function is used by montior mode code to restitch an MSDU list + * corresponding to an MPDU back into an MPDU by linking up the skbs. + */ +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) +{ + qdf_nbuf_t msdu, mpdu_buf, prev_buf, msdu_orig, head_frag_list_cloned; + unsigned int decap_format, wifi_hdr_len, sec_hdr_len, msdu_llc_len, + mpdu_buf_len, decap_hdr_pull_bytes, frag_list_sum_len, dir, + is_amsdu, is_first_frag, amsdu_pad, msdu_len; + struct htt_host_rx_desc_base *rx_desc; + char *hdr_desc; + unsigned char *dest; + struct ieee80211_frame *wh; + struct ieee80211_qoscntl *qos; + + /* The nbuf has been pulled just beyond the status and points to the + * payload + */ + msdu_orig = head_msdu; + rx_desc = htt_rx_desc(msdu_orig); + + /* Fill out the rx_status from the PPDU start and end fields */ + if (rx_desc->attention.first_mpdu) { + htt_rx_parse_ppdu_start_status(rx_desc, rx_status); + + /* The timestamp is no longer valid - It will be valid only for + * the last MPDU + */ + rx_status->rs_tstamp.tsf = ~0; + } + + decap_format = + GET_FIELD(&rx_desc->msdu_start, RX_MSDU_START_2_DECAP_FORMAT); + + head_frag_list_cloned = NULL; + + /* Easy case - The MSDU status indicates that this is a non-decapped + * packet in RAW mode. + * return + */ + if (decap_format == HW_RX_DECAP_FORMAT_RAW) { + /* Note that this path might suffer from headroom unavailabilty, + * but the RX status is usually enough + */ + if (clone_not_reqd) + mpdu_buf = htt_rx_qdf_noclone_buf(head_msdu); + else + mpdu_buf = qdf_nbuf_clone(head_msdu); + + if (!mpdu_buf) + goto mpdu_stitch_fail; + + prev_buf = mpdu_buf; + + frag_list_sum_len = 0; + is_first_frag = 1; + msdu_len = qdf_nbuf_len(mpdu_buf); + + /* Drop the zero-length msdu */ + if (!msdu_len) + goto mpdu_stitch_fail; + + msdu_orig = qdf_nbuf_next(head_msdu); + + while (msdu_orig) { + /* TODO: intra AMSDU padding - do we need it ??? */ + if (clone_not_reqd) + msdu = htt_rx_qdf_noclone_buf(msdu_orig); + else + msdu = qdf_nbuf_clone(msdu_orig); + + if (!msdu) + goto mpdu_stitch_fail; + + if (is_first_frag) { + is_first_frag = 0; + head_frag_list_cloned = msdu; + } + + msdu_len = qdf_nbuf_len(msdu); + /* Drop the zero-length msdu */ + if (!msdu_len) + goto mpdu_stitch_fail; + + frag_list_sum_len += msdu_len; + + /* Maintain the linking of the cloned MSDUS */ + qdf_nbuf_set_next_ext(prev_buf, msdu); + + /* Move to the next */ + prev_buf = msdu; + msdu_orig = qdf_nbuf_next(msdu_orig); + } + + /* The last msdu length need be larger than HTT_FCS_LEN */ + if (msdu_len < HTT_FCS_LEN) + goto mpdu_stitch_fail; + + qdf_nbuf_trim_tail(prev_buf, HTT_FCS_LEN); + + /* If there were more fragments to this RAW frame */ + if (head_frag_list_cloned) { + qdf_nbuf_append_ext_list(mpdu_buf, + head_frag_list_cloned, + frag_list_sum_len); + } + + goto mpdu_stitch_done; + } + + /* Decap mode: + * Calculate the amount of header in decapped packet to knock off based + * on the decap type and the corresponding number of raw bytes to copy + * status header + */ + + hdr_desc = &rx_desc->rx_hdr_status[0]; + + /* Base size */ + wifi_hdr_len = sizeof(struct ieee80211_frame); + wh = (struct ieee80211_frame *)hdr_desc; + + dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; + if (dir == IEEE80211_FC1_DIR_DSTODS) + wifi_hdr_len += 6; + + is_amsdu = 0; + if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { + qos = (struct ieee80211_qoscntl *) + (hdr_desc + wifi_hdr_len); + wifi_hdr_len += 2; + + is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU); + } + + /* TODO: Any security headers associated with MPDU */ + sec_hdr_len = 0; + + /* MSDU related stuff LLC - AMSDU subframe header etc */ + msdu_llc_len = is_amsdu ? (14 + 8) : 8; + + mpdu_buf_len = wifi_hdr_len + sec_hdr_len + msdu_llc_len; + + /* "Decap" header to remove from MSDU buffer */ + decap_hdr_pull_bytes = 14; + + /* Allocate a new nbuf for holding the 802.11 header retrieved from the + * status of the now decapped first msdu. Leave enough headroom for + * accomodating any radio-tap /prism like PHY header + */ +#define HTT_MAX_MONITOR_HEADER (512) + mpdu_buf = qdf_nbuf_alloc(pdev->osdev, + HTT_MAX_MONITOR_HEADER + mpdu_buf_len, + HTT_MAX_MONITOR_HEADER, 4, false); + + if (!mpdu_buf) + goto mpdu_stitch_fail; + + /* Copy the MPDU related header and enc headers into the first buffer + * - Note that there can be a 2 byte pad between heaader and enc header + */ + + prev_buf = mpdu_buf; + dest = qdf_nbuf_put_tail(prev_buf, wifi_hdr_len); + if (!dest) + goto mpdu_stitch_fail; + qdf_mem_copy(dest, hdr_desc, wifi_hdr_len); + hdr_desc += wifi_hdr_len; + + /* NOTE - This padding is present only in the RAW header status - not + * when the MSDU data payload is in RAW format. + */ + /* Skip the "IV pad" */ + if (wifi_hdr_len & 0x3) + hdr_desc += 2; + + /* The first LLC len is copied into the MPDU buffer */ + frag_list_sum_len = 0; + frag_list_sum_len -= msdu_llc_len; + + msdu_orig = head_msdu; + is_first_frag = 1; + amsdu_pad = 0; + + while (msdu_orig) { + /* TODO: intra AMSDU padding - do we need it ??? */ + if (clone_not_reqd) + msdu = htt_rx_qdf_noclone_buf(msdu_orig); + else + msdu = qdf_nbuf_clone(msdu_orig); + + if (!msdu) + goto mpdu_stitch_fail; + + if (is_first_frag) { + is_first_frag = 0; + head_frag_list_cloned = msdu; + } else { + /* Maintain the linking of the cloned MSDUS */ + qdf_nbuf_set_next_ext(prev_buf, msdu); + + /* Reload the hdr ptr only on non-first MSDUs */ + rx_desc = htt_rx_desc(msdu_orig); + hdr_desc = &rx_desc->rx_hdr_status[0]; + } + + /* Copy this buffers MSDU related status into the prev buffer */ + dest = qdf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); + dest += amsdu_pad; + qdf_mem_copy(dest, hdr_desc, msdu_llc_len); + + /* Push the MSDU buffer beyond the decap header */ + qdf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); + frag_list_sum_len += + msdu_llc_len + qdf_nbuf_len(msdu) + amsdu_pad; + + /* + * Set up intra-AMSDU pad to be added to start of next buffer - + * AMSDU pad is 4 byte pad on AMSDU subframe + */ + amsdu_pad = (msdu_llc_len + qdf_nbuf_len(msdu)) & 0x3; + amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0; + + /* + * TODO FIXME How do we handle MSDUs that have fraglist - Should + * probably iterate all the frags cloning them along the way and + * and also updating the prev_buf pointer + */ + + /* Move to the next */ + prev_buf = msdu; + msdu_orig = qdf_nbuf_next(msdu_orig); + } + + /* TODO: Convert this to suitable qdf routines */ + qdf_nbuf_append_ext_list(mpdu_buf, head_frag_list_cloned, + frag_list_sum_len); + +mpdu_stitch_done: + /* Check if this buffer contains the PPDU end status for TSF */ + if (rx_desc->attention.last_mpdu) +#ifdef HELIUMPLUS + rx_status->rs_tstamp.tsf = + rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; +#else + rx_status->rs_tstamp.tsf = rx_desc->ppdu_end.tsf_timestamp; +#endif + /* All the nbufs have been linked into the ext list + * and then unlink the nbuf list + */ + if (clone_not_reqd) { + msdu = head_msdu; + while (msdu) { + msdu_orig = msdu; + msdu = qdf_nbuf_next(msdu); + qdf_nbuf_set_next(msdu_orig, NULL); + } + } + + return mpdu_buf; + +mpdu_stitch_fail: + /* Free these alloced buffers and the orig buffers in non-clone case */ + if (!clone_not_reqd) { + /* Free the head buffer */ + if (mpdu_buf) + qdf_nbuf_free(mpdu_buf); + + /* Free the partial list */ + while (head_frag_list_cloned) { + msdu = head_frag_list_cloned; + head_frag_list_cloned = + qdf_nbuf_next_ext(head_frag_list_cloned); + qdf_nbuf_free(msdu); + } + } else { + /* Free the alloced head buffer */ + if (decap_format != HW_RX_DECAP_FORMAT_RAW) + if (mpdu_buf) + qdf_nbuf_free(mpdu_buf); + + /* Free the orig buffers */ + msdu = head_msdu; + while (msdu) { + msdu_orig = msdu; + msdu = qdf_nbuf_next(msdu); + qdf_nbuf_free(msdu_orig); + } + } + + return NULL; +} +#endif diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 934f2663840a..28b57933c03e 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -53,12 +53,6 @@ #endif #include -#ifdef HTT_DEBUG_DATA -#define HTT_PKT_DUMP(x) x -#else -#define HTT_PKT_DUMP(x) /* no-op */ -#endif - /* AR9888v1 WORKAROUND for EV#112367 */ /* FIX THIS - remove this WAR when the bug is fixed */ #define PEREGRINE_1_0_ZERO_LEN_PHY_ERR_WAR @@ -111,12 +105,6 @@ #define RX_HASH_LOG(x) /* no-op */ #endif -#if HTT_PADDR64 -#define NEXT_FIELD_OFFSET_IN32 2 -#else /* ! HTT_PADDR64 */ -#define NEXT_FIELD_OFFSET_IN32 1 -#endif /* HTT_PADDR64 */ - #ifndef CONFIG_HL_SUPPORT /** * htt_get_first_packet_after_wow_wakeup() - get first packet after wow wakeup @@ -382,36 +370,25 @@ htt_rx_msdu_is_frag_hl(htt_pdev_handle pdev, void *msdu_desc) HTT_WORD_GET(*(u_int32_t *)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST); } -#define RX_PADDR_MAGIC_PATTERN 0xDEAD0000 +#ifdef ENABLE_DEBUG_ADDRESS_MARKING static qdf_dma_addr_t htt_rx_paddr_mark_high_bits(qdf_dma_addr_t paddr) { -#ifdef ENABLE_DEBUG_ADDRESS_MARKING if (sizeof(qdf_dma_addr_t) > 4) { /* clear high bits, leave lower 37 bits (paddr) */ paddr &= 0x01FFFFFFFFF; /* mark upper 16 bits of paddr */ paddr |= (((uint64_t)RX_PADDR_MAGIC_PATTERN) << 32); } + return paddr; +} +#else +static qdf_dma_addr_t +htt_rx_paddr_mark_high_bits(qdf_dma_addr_t paddr) +{ + return 0; +} #endif - return paddr; -} - -#if HTT_PADDR64 -static inline qdf_dma_addr_t htt_paddr_trim_to_37(qdf_dma_addr_t paddr) -{ - qdf_dma_addr_t ret = paddr; - - if (sizeof(paddr) > 4) - ret &= 0x1fffffffff; - return ret; -} -#else /* not 64 bits */ -static inline qdf_dma_addr_t htt_paddr_trim_to_37(qdf_dma_addr_t paddr) -{ - return paddr; -} -#endif /* HTT_PADDR64 */ #ifndef CONFIG_HL_SUPPORT static bool @@ -425,76 +402,6 @@ htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc) RX_MSDU_END_4_FIRST_MSDU_LSB); } -#ifdef ENABLE_DEBUG_ADDRESS_MARKING -static qdf_dma_addr_t -htt_rx_paddr_unmark_high_bits(qdf_dma_addr_t paddr) -{ - uint32_t markings; - - if (sizeof(qdf_dma_addr_t) > 4) { - markings = (uint32_t)((paddr >> 16) >> 16); - /* - * check if it is marked correctly: - * See the mark_high_bits function above for the expected - * pattern. - * the LS 5 bits are the high bits of physical address - * padded (with 0b0) to 8 bits - */ - if ((markings & 0xFFFF0000) != RX_PADDR_MAGIC_PATTERN) { - qdf_print("%s: paddr not marked correctly: 0x%pK!\n", - __func__, (void *)paddr); - HTT_ASSERT_ALWAYS(0); - } - - /* clear markings for further use */ - paddr = htt_paddr_trim_to_37(paddr); - } - return paddr; -} - -static qdf_dma_addr_t -htt_rx_in_ord_paddr_get(uint32_t *u32p) -{ - qdf_dma_addr_t paddr = 0; - - paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); - if (sizeof(qdf_dma_addr_t) > 4) { - u32p++; - /* 32 bit architectures dont like <<32 */ - paddr |= (((qdf_dma_addr_t) - HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p)) - << 16 << 16); - } - paddr = htt_rx_paddr_unmark_high_bits(paddr); - - return paddr; -} -#else -#if HTT_PADDR64 -static qdf_dma_addr_t -htt_rx_in_ord_paddr_get(uint32_t *u32p) -{ - qdf_dma_addr_t paddr = 0; - - paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); - if (sizeof(qdf_dma_addr_t) > 4) { - u32p++; - /* 32 bit architectures dont like <<32 */ - paddr |= (((qdf_dma_addr_t) - HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p)) - << 16 << 16); - } - return paddr; -} -#else -static inline qdf_dma_addr_t -htt_rx_in_ord_paddr_get(uint32_t *u32p) -{ - return HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p); -} - -#endif -#endif /* ENABLE_DEBUG_ADDRESS_MARKING */ #endif /* CONFIG_HL_SUPPORT*/ /* full_reorder_offload case: this function is called with lock held */ @@ -1099,17 +1006,6 @@ static inline qdf_nbuf_t htt_rx_netbuf_pop(htt_pdev_handle pdev) return msdu; } -#ifndef CONFIG_HL_SUPPORT -static inline qdf_nbuf_t -htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, qdf_dma_addr_t paddr) -{ - HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); - pdev->rx_ring.fill_cnt--; - paddr = htt_paddr_trim_to_37(paddr); - return htt_rx_hash_list_lookup(pdev, paddr); -} -#endif - /* * FIX ME: this function applies only to LL rx descs. * An equivalent for HL rx descs is needed. @@ -1734,669 +1630,6 @@ htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev, } #endif -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#ifndef CONFIG_HL_SUPPORT -/** - * htt_mon_rx_handle_amsdu_packet() - Handle consecutive fragments of amsdu - * @msdu: pointer to first msdu of amsdu - * @pdev: Handle to htt_pdev_handle - * @msg_word: Input and output variable, so pointer to HTT msg pointer - * @amsdu_len: remaining length of all N-1 msdu msdu's - * @frag_cnt: number of frags handled - * - * This function handles the (N-1) msdu's of amsdu, N'th msdu is already - * handled by calling function. N-1 msdu's are tied using frags_list. - * msdu_info field updated by FW indicates if this is last msdu. All the - * msdu's before last msdu will be of MAX payload. - * - * Return: 1 on success and 0 on failure. - */ -static -int 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) -{ - qdf_nbuf_t frag_nbuf; - qdf_nbuf_t prev_frag_nbuf; - uint32_t len; - uint32_t last_frag; - qdf_dma_addr_t paddr; - - *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; - paddr = htt_rx_in_ord_paddr_get(*msg_word); - frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); - if (qdf_unlikely(NULL == frag_nbuf)) { - qdf_print("%s: netbuf pop failed!\n", __func__); - return 0; - } - *frag_cnt = *frag_cnt + 1; - last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)*msg_word)-> - msdu_info; - qdf_nbuf_append_ext_list(msdu, frag_nbuf, amsdu_len); - qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); - qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); - /* For msdu's other than parent will not have htt_host_rx_desc_base */ - len = MIN(amsdu_len, HTT_RX_BUF_SIZE); - amsdu_len -= len; - qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); - - HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_INFO_HIGH, - qdf_nbuf_data(frag_nbuf), - qdf_nbuf_len(frag_nbuf))); - prev_frag_nbuf = frag_nbuf; - while (!last_frag) { - *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; - paddr = htt_rx_in_ord_paddr_get(*msg_word); - frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr); - last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) - *msg_word)->msdu_info; - - if (qdf_unlikely(NULL == frag_nbuf)) { - qdf_print("%s: netbuf pop failed!\n", __func__); - prev_frag_nbuf->next = NULL; - return 0; - } - *frag_cnt = *frag_cnt + 1; - qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); - qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); - - len = MIN(amsdu_len, HTT_RX_BUF_SIZE); - amsdu_len -= len; - qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); - HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_INFO_HIGH, - qdf_nbuf_data(frag_nbuf), - qdf_nbuf_len(frag_nbuf))); - - qdf_nbuf_set_next(prev_frag_nbuf, frag_nbuf); - prev_frag_nbuf = frag_nbuf; - } - qdf_nbuf_set_next(prev_frag_nbuf, NULL); - return 1; -} - -#define SHORT_PREAMBLE 1 -#define LONG_PREAMBLE 0 -#ifdef HELIUMPLUS -/** - * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc - * @l_sig_rate_select: OFDM or CCK rate - * @l_sig_rate: - * - * If l_sig_rate_select is 0: - * 0x8: OFDM 48 Mbps - * 0x9: OFDM 24 Mbps - * 0xA: OFDM 12 Mbps - * 0xB: OFDM 6 Mbps - * 0xC: OFDM 54 Mbps - * 0xD: OFDM 36 Mbps - * 0xE: OFDM 18 Mbps - * 0xF: OFDM 9 Mbps - * If l_sig_rate_select is 1: - * 0x1: DSSS 1 Mbps long preamble - * 0x2: DSSS 2 Mbps long preamble - * 0x3: CCK 5.5 Mbps long preamble - * 0x4: CCK 11 Mbps long preamble - * 0x5: DSSS 2 Mbps short preamble - * 0x6: CCK 5.5 Mbps - * 0x7: CCK 11 Mbps short preamble - * - * Return: rate interms of 500Kbps. - */ -static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, - uint32_t l_sig_rate, uint8_t *preamble) -{ - char ret = 0x0; - *preamble = SHORT_PREAMBLE; - if (l_sig_rate_select == 0) { - switch (l_sig_rate) { - case 0x8: - ret = 0x60; - break; - case 0x9: - ret = 0x30; - break; - case 0xA: - ret = 0x18; - break; - case 0xB: - ret = 0x0c; - break; - case 0xC: - ret = 0x6c; - break; - case 0xD: - ret = 0x48; - break; - case 0xE: - ret = 0x24; - break; - case 0xF: - ret = 0x12; - break; - default: - break; - } - } else if (l_sig_rate_select == 1) { - switch (l_sig_rate) { - case 0x1: - ret = 0x2; - *preamble = LONG_PREAMBLE; - break; - case 0x2: - ret = 0x4; - *preamble = LONG_PREAMBLE; - break; - case 0x3: - ret = 0xB; - *preamble = LONG_PREAMBLE; - break; - case 0x4: - ret = 0x16; - *preamble = LONG_PREAMBLE; - break; - case 0x5: - ret = 0x4; - break; - case 0x6: - ret = 0xB; - break; - case 0x7: - ret = 0x16; - break; - default: - break; - } - } else { - qdf_print("Invalid rate info\n"); - } - return ret; -} -#else -/** - * htt_rx_get_rate() - get rate info in terms of 500Kbps from htt_rx_desc - * @l_sig_rate_select: OFDM or CCK rate - * @l_sig_rate: - * - * If l_sig_rate_select is 0: - * 0x8: OFDM 48 Mbps - * 0x9: OFDM 24 Mbps - * 0xA: OFDM 12 Mbps - * 0xB: OFDM 6 Mbps - * 0xC: OFDM 54 Mbps - * 0xD: OFDM 36 Mbps - * 0xE: OFDM 18 Mbps - * 0xF: OFDM 9 Mbps - * If l_sig_rate_select is 1: - * 0x8: CCK 11 Mbps long preamble - * 0x9: CCK 5.5 Mbps long preamble - * 0xA: CCK 2 Mbps long preamble - * 0xB: CCK 1 Mbps long preamble - * 0xC: CCK 11 Mbps short preamble - * 0xD: CCK 5.5 Mbps short preamble - * 0xE: CCK 2 Mbps short preamble - * - * Return: rate interms of 500Kbps. - */ -static unsigned char htt_rx_get_rate(uint32_t l_sig_rate_select, - uint32_t l_sig_rate, uint8_t *preamble) -{ - char ret = 0x0; - *preamble = SHORT_PREAMBLE; - if (l_sig_rate_select == 0) { - switch (l_sig_rate) { - case 0x8: - ret = 0x60; - break; - case 0x9: - ret = 0x30; - break; - case 0xA: - ret = 0x18; - break; - case 0xB: - ret = 0x0c; - break; - case 0xC: - ret = 0x6c; - break; - case 0xD: - ret = 0x48; - break; - case 0xE: - ret = 0x24; - break; - case 0xF: - ret = 0x12; - break; - default: - break; - } - } else if (l_sig_rate_select == 1) { - switch (l_sig_rate) { - case 0x8: - ret = 0x16; - *preamble = LONG_PREAMBLE; - break; - case 0x9: - ret = 0x0B; - *preamble = LONG_PREAMBLE; - break; - case 0xA: - ret = 0x4; - *preamble = LONG_PREAMBLE; - break; - case 0xB: - ret = 0x02; - *preamble = LONG_PREAMBLE; - break; - case 0xC: - ret = 0x16; - break; - case 0xD: - ret = 0x0B; - break; - case 0xE: - ret = 0x04; - break; - default: - break; - } - } else { - qdf_print("Invalid rate info\n"); - } - return ret; -} -#endif /* HELIUMPLUS */ -/** - * htt_mon_rx_get_phy_info() - Get phy info - * @rx_desc: Pointer to struct htt_host_rx_desc_base - * @rx_status: Return variable updated with phy_info in rx_status - * - * Return: None - */ -static void htt_mon_rx_get_phy_info(struct htt_host_rx_desc_base *rx_desc, - struct mon_rx_status *rx_status) -{ - uint8_t preamble = 0; - uint8_t preamble_type = rx_desc->ppdu_start.preamble_type; - uint8_t mcs = 0, nss = 0, sgi = 0, bw = 0, beamformed = 0; - uint16_t vht_flags = 0, ht_flags = 0; - uint32_t l_sig_rate_select = rx_desc->ppdu_start.l_sig_rate_select; - uint32_t l_sig_rate = rx_desc->ppdu_start.l_sig_rate; - bool is_stbc = 0, ldpc = 0; - - switch (preamble_type) { - case 4: - /* legacy */ - rx_status->rate = htt_rx_get_rate(l_sig_rate_select, l_sig_rate, - &preamble); - break; - case 8: - is_stbc = ((VHT_SIG_A_2(rx_desc) >> 4) & 3); - /* fallthrough */ - case 9: - ht_flags = 1; - sgi = (VHT_SIG_A_2(rx_desc) >> 7) & 0x01; - bw = (VHT_SIG_A_1(rx_desc) >> 7) & 0x01; - mcs = (VHT_SIG_A_1(rx_desc) & 0x7f); - nss = mcs>>3; - beamformed = - (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; - break; - case 0x0c: - is_stbc = (VHT_SIG_A_2(rx_desc) >> 3) & 1; - ldpc = (VHT_SIG_A_2(rx_desc) >> 2) & 1; - /* fallthrough */ - case 0x0d: - { - uint8_t gid_in_sig = ((VHT_SIG_A_1(rx_desc) >> 4) & 0x3f); - - vht_flags = 1; - sgi = VHT_SIG_A_2(rx_desc) & 0x01; - bw = (VHT_SIG_A_1(rx_desc) & 0x03); - if (gid_in_sig == 0 || gid_in_sig == 63) { - /* SU case */ - mcs = (VHT_SIG_A_2(rx_desc) >> 4) & - 0xf; - nss = (VHT_SIG_A_1(rx_desc) >> 10) & - 0x7; - } else { - /* MU case */ - uint8_t sta_user_pos = - (uint8_t)((rx_desc->ppdu_start.reserved_4a >> 8) - & 0x3); - mcs = (rx_desc->ppdu_start.vht_sig_b >> 16); - if (bw >= 2) - mcs >>= 3; - else if (bw > 0) - mcs >>= 1; - mcs &= 0xf; - nss = (((VHT_SIG_A_1(rx_desc) >> 10) + - sta_user_pos * 3) & 0x7); - } - beamformed = (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; - } - /* fallthrough */ - default: - break; - } - - rx_status->mcs = mcs; - rx_status->bw = bw; - rx_status->nr_ant = nss; - rx_status->is_stbc = is_stbc; - rx_status->sgi = sgi; - rx_status->ldpc = ldpc; - rx_status->beamformed = beamformed; - rx_status->vht_flag_values3[0] = mcs << 0x4 | (nss + 1); - rx_status->ht_flags = ht_flags; - rx_status->vht_flags = vht_flags; - rx_status->rtap_flags |= ((preamble == SHORT_PREAMBLE) ? BIT(1) : 0); - if (bw == 0) - rx_status->vht_flag_values2 = 0; - else if (bw == 1) - rx_status->vht_flag_values2 = 1; - else if (bw == 2) - rx_status->vht_flag_values2 = 4; -} - -/** - * htt_mon_rx_get_rtap_flags() - Get radiotap flags - * @rx_desc: Pointer to struct htt_host_rx_desc_base - * - * Return: Bitmapped radiotap flags. - */ -static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) -{ - uint8_t rtap_flags = 0; - - /* WEP40 || WEP104 || WEP128 */ - if (rx_desc->mpdu_start.encrypt_type == 0 || - rx_desc->mpdu_start.encrypt_type == 1 || - rx_desc->mpdu_start.encrypt_type == 3) - rtap_flags |= BIT(2); - - /* IEEE80211_RADIOTAP_F_FRAG */ - if (rx_desc->attention.fragment) - rtap_flags |= BIT(3); - - /* IEEE80211_RADIOTAP_F_FCS */ - rtap_flags |= BIT(4); - - /* IEEE80211_RADIOTAP_F_BADFCS */ - if (rx_desc->mpdu_end.fcs_err) - rtap_flags |= BIT(6); - - return rtap_flags; -} - -/** - * htt_rx_mon_get_rx_status() - Update information about the rx status, - * which is used later for radiotap updation. - * @rx_desc: Pointer to struct htt_host_rx_desc_base - * @rx_status: Return variable updated with rx_status - * - * Return: None - */ -static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, - struct htt_host_rx_desc_base *rx_desc, - struct mon_rx_status *rx_status) -{ - uint16_t channel_flags = 0; - struct mon_channel *ch_info = &pdev->mon_ch_info; - - rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); - rx_status->chan_freq = ch_info->ch_freq; - rx_status->chan_num = ch_info->ch_num; - htt_mon_rx_get_phy_info(rx_desc, rx_status); - rx_status->rtap_flags |= htt_mon_rx_get_rtap_flags(rx_desc); - channel_flags |= rx_desc->ppdu_start.l_sig_rate_select ? - IEEE80211_CHAN_CCK : IEEE80211_CHAN_OFDM; - channel_flags |= - (cds_chan_to_band(ch_info->ch_num) == CDS_BAND_2GHZ ? - IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); - - rx_status->chan_flags = channel_flags; - rx_status->ant_signal_db = rx_desc->ppdu_start.rssi_comb; -} -#endif - -#ifdef RX_HASH_DEBUG -#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) HTT_ASSERT_ALWAYS(msdu_count) -#else -#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) /* no-op */ -#endif - -#ifndef CONFIG_HL_SUPPORT -/** - * htt_rx_mon_amsdu_rx_in_order_pop_ll() - Monitor mode HTT Rx in order pop - * function - * @pdev: Handle to htt_pdev_handle - * @rx_ind_msg: In order indication message. - * @head_msdu: Return variable pointing to head msdu. - * @tail_msdu: Return variable pointing to tail msdu. - * - * This function pops the msdu based on paddr:length of inorder indication - * message. - * - * Return: 1 for success, 0 on failure. - */ -static int 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) -{ - qdf_nbuf_t msdu, next, prev = NULL; - uint8_t *rx_ind_data; - uint32_t *msg_word; - uint32_t msdu_count; - struct htt_host_rx_desc_base *rx_desc; - struct mon_rx_status rx_status = {0}; - uint32_t amsdu_len; - uint32_t len; - uint32_t last_frag; - qdf_dma_addr_t paddr; - - HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); - - rx_ind_data = qdf_nbuf_data(rx_ind_msg); - msg_word = (uint32_t *)rx_ind_data; - - *replenish_cnt = 0; - HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_INFO_HIGH, - (void *)rx_ind_data, - (int)qdf_nbuf_len(rx_ind_msg))); - - /* Get the total number of MSDUs */ - msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); - HTT_RX_CHECK_MSDU_COUNT(msdu_count); - - msg_word = (uint32_t *)(rx_ind_data + - HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); - paddr = htt_rx_in_ord_paddr_get(msg_word); - msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); - - if (qdf_unlikely(NULL == msdu)) { - qdf_print("%s: netbuf pop failed!\n", __func__); - *tail_msdu = NULL; - return 0; - } - *replenish_cnt = *replenish_cnt + 1; - - while (msdu_count > 0) { - - msdu_count--; - /* - * Set the netbuf length to be the entire buffer length - * initially, so the unmap will unmap the entire buffer. - */ - qdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); - qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); - - /* - * cache consistency has been taken care of by the - * qdf_nbuf_unmap - */ - rx_desc = htt_rx_desc(msdu); - if ((unsigned int)(*(uint32_t *)&rx_desc->attention) & - RX_DESC_ATTN_MPDU_LEN_ERR_BIT) { - qdf_nbuf_free(msdu); - last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) - msg_word)->msdu_info; - while (!last_frag) { - msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; - paddr = htt_rx_in_ord_paddr_get(msg_word); - msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); - last_frag = ((struct - htt_rx_in_ord_paddr_ind_msdu_t *) - msg_word)->msdu_info; - if (qdf_unlikely(!msdu)) { - qdf_print("%s: netbuf pop failed!\n", - __func__); - return 0; - } - *replenish_cnt = *replenish_cnt + 1; - qdf_nbuf_unmap(pdev->osdev, msdu, - QDF_DMA_FROM_DEVICE); - qdf_nbuf_free(msdu); - } - msdu = prev; - goto next_pop; - } - - if (!prev) - (*head_msdu) = msdu; - prev = msdu; - - HTT_PKT_DUMP(htt_print_rx_desc(rx_desc)); - /* - * Make the netbuf's data pointer point to the payload rather - * than the descriptor. - */ - htt_rx_mon_get_rx_status(pdev, rx_desc, &rx_status); - /* - * For certain platform, 350 bytes of headroom is already - * appended to accommodate radiotap header but - * qdf_nbuf_update_radiotap() API again will try to create - * a room for radiotap header. To make our design simple - * let qdf_nbuf_update_radiotap() API create a room for radiotap - * header and update it, do qdf_nbuf_pull_head() operation and - * pull 350 bytes of headroom. - * - * - * - * (SKB buffer) - * skb->head --> +-----------+ <-- skb->data - * | | (Before pulling headroom) - * | | - * | HEAD | 350 bytes of headroom - * | | - * | | - * +-----------+ <-- skb->data - * | | (After pulling headroom) - * | | - * | DATA | - * | | - * | | - * +-----------+ - * | | - * | | - * | TAIL | - * | | - * | | - * +-----------+ - * - */ - if (qdf_nbuf_head(msdu) == qdf_nbuf_data(msdu)) - qdf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); - qdf_nbuf_update_radiotap(&rx_status, msdu, - HTT_RX_STD_DESC_RESERVATION); - amsdu_len = HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(*(msg_word + - NEXT_FIELD_OFFSET_IN32)); - - /* - * MAX_RX_PAYLOAD_SZ when we have AMSDU packet. amsdu_len in - * which case is the total length of sum of all AMSDU's - */ - len = MIN(amsdu_len, MAX_RX_PAYLOAD_SZ); - amsdu_len -= len; - qdf_nbuf_trim_tail(msdu, - HTT_RX_BUF_SIZE - - (RX_STD_DESC_SIZE + len)); - - - HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_INFO_HIGH, - qdf_nbuf_data(msdu), - qdf_nbuf_len(msdu))); - last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) - msg_word)->msdu_info; - - /* Handle amsdu packet */ - if (!last_frag) { - /* - * For AMSDU packet msdu->len is sum of all the msdu's - * length, msdu->data_len is sum of length's of - * remaining msdu's other than parent. - */ - if (!htt_mon_rx_handle_amsdu_packet(msdu, pdev, - &msg_word, - amsdu_len, - replenish_cnt)) { - qdf_print("%s: failed to handle amsdu packet\n", - __func__); - return 0; - } - } - -next_pop: - /* check if this is the last msdu */ - if (msdu_count) { - msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; - paddr = htt_rx_in_ord_paddr_get(msg_word); - next = htt_rx_in_order_netbuf_pop(pdev, paddr); - if (qdf_unlikely(NULL == next)) { - qdf_print("%s: netbuf pop failed!\n", - __func__); - *tail_msdu = NULL; - return 0; - } - *replenish_cnt = *replenish_cnt + 1; - if (msdu) - qdf_nbuf_set_next(msdu, next); - msdu = next; - } else { - *tail_msdu = msdu; - if (msdu) - qdf_nbuf_set_next(msdu, NULL); - } - } - - return 1; -} -#endif - -/** - * htt_rx_mon_note_capture_channel() - Make note of channel to update in - * radiotap - * @pdev: handle to htt_pdev - * @mon_ch: capture channel number. - * - * Return: None - */ -void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch) -{ - struct mon_channel *ch_info = &pdev->mon_ch_info; - - ch_info->ch_num = mon_ch; - ch_info->ch_freq = cds_chan_to_freq(mon_ch); -} - uint32_t htt_rx_amsdu_rx_in_order_get_pktlog(qdf_nbuf_t rx_ind_msg) { uint32_t *msg_word; @@ -2635,384 +1868,6 @@ free_mem_map_table: } #endif -/* FIXME: This is a HW definition not provded by HW, where does it go ? */ -enum { - HW_RX_DECAP_FORMAT_RAW = 0, - HW_RX_DECAP_FORMAT_NWIFI, - HW_RX_DECAP_FORMAT_8023, - HW_RX_DECAP_FORMAT_ETH2, -}; - -#define HTT_FCS_LEN (4) - -#if !defined(QCA6290_HEADERS_DEF) -static void -htt_rx_parse_ppdu_start_status(struct htt_host_rx_desc_base *rx_desc, - struct ieee80211_rx_status *rs) -{ - - struct rx_ppdu_start *ppdu_start = &rx_desc->ppdu_start; - - /* RSSI */ - rs->rs_rssi = ppdu_start->rssi_comb; - - /* PHY rate */ - /* - * rs_ratephy coding - * [b3 - b0] - * 0 -> OFDM - * 1 -> CCK - * 2 -> HT - * 3 -> VHT - * OFDM / CCK - * [b7 - b4 ] => LSIG rate - * [b23 - b8 ] => service field - * (b'12 static/dynamic, - * b'14..b'13 BW for VHT) - * [b31 - b24 ] => Reserved - * HT / VHT - * [b15 - b4 ] => SIG A_2 12 LSBs - * [b31 - b16] => SIG A_1 16 LSBs - */ - if (ppdu_start->preamble_type == 0x4) { - rs->rs_ratephy = ppdu_start->l_sig_rate_select; - rs->rs_ratephy |= ppdu_start->l_sig_rate << 4; - rs->rs_ratephy |= ppdu_start->service << 8; - } else { - rs->rs_ratephy = (ppdu_start->preamble_type & 0x4) ? 3 : 2; -#ifdef HELIUMPLUS - rs->rs_ratephy |= - (ppdu_start->ht_sig_vht_sig_ah_sig_a_2 & 0xFFF) << 4; - rs->rs_ratephy |= - (ppdu_start->ht_sig_vht_sig_ah_sig_a_1 & 0xFFFF) << 16; -#else - rs->rs_ratephy |= (ppdu_start->ht_sig_vht_sig_a_2 & 0xFFF) << 4; - rs->rs_ratephy |= - (ppdu_start->ht_sig_vht_sig_a_1 & 0xFFFF) << 16; -#endif - } -} - -/* Util fake function that has same prototype as qdf_nbuf_clone that just - * returns the same nbuf - */ -static qdf_nbuf_t htt_rx_qdf_noclone_buf(qdf_nbuf_t buf) -{ - return buf; -} - -/* This function is used by montior mode code to restitch an MSDU list - * corresponding to an MPDU back into an MPDU by linking up the skbs. - */ -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) -{ - - qdf_nbuf_t msdu, mpdu_buf, prev_buf, msdu_orig, head_frag_list_cloned; - unsigned int decap_format, wifi_hdr_len, sec_hdr_len, msdu_llc_len, - mpdu_buf_len, decap_hdr_pull_bytes, frag_list_sum_len, dir, - is_amsdu, is_first_frag, amsdu_pad, msdu_len; - struct htt_host_rx_desc_base *rx_desc; - char *hdr_desc; - unsigned char *dest; - struct ieee80211_frame *wh; - struct ieee80211_qoscntl *qos; - - /* The nbuf has been pulled just beyond the status and points to the - * payload - */ - msdu_orig = head_msdu; - rx_desc = htt_rx_desc(msdu_orig); - - /* Fill out the rx_status from the PPDU start and end fields */ - if (rx_desc->attention.first_mpdu) { - htt_rx_parse_ppdu_start_status(rx_desc, rx_status); - - /* The timestamp is no longer valid - It will be valid only for - * the last MPDU - */ - rx_status->rs_tstamp.tsf = ~0; - } - - decap_format = - GET_FIELD(&rx_desc->msdu_start, RX_MSDU_START_2_DECAP_FORMAT); - - head_frag_list_cloned = NULL; - - /* Easy case - The MSDU status indicates that this is a non-decapped - * packet in RAW mode. - * return - */ - if (decap_format == HW_RX_DECAP_FORMAT_RAW) { - /* Note that this path might suffer from headroom unavailabilty, - * but the RX status is usually enough - */ - if (clone_not_reqd) - mpdu_buf = htt_rx_qdf_noclone_buf(head_msdu); - else - mpdu_buf = qdf_nbuf_clone(head_msdu); - - if (!mpdu_buf) - goto mpdu_stitch_fail; - - prev_buf = mpdu_buf; - - frag_list_sum_len = 0; - is_first_frag = 1; - msdu_len = qdf_nbuf_len(mpdu_buf); - - /* Drop the zero-length msdu */ - if (!msdu_len) - goto mpdu_stitch_fail; - - msdu_orig = qdf_nbuf_next(head_msdu); - - while (msdu_orig) { - - /* TODO: intra AMSDU padding - do we need it ??? */ - if (clone_not_reqd) - msdu = htt_rx_qdf_noclone_buf(msdu_orig); - else - msdu = qdf_nbuf_clone(msdu_orig); - - if (!msdu) - goto mpdu_stitch_fail; - - if (is_first_frag) { - is_first_frag = 0; - head_frag_list_cloned = msdu; - } - - msdu_len = qdf_nbuf_len(msdu); - /* Drop the zero-length msdu */ - if (!msdu_len) - goto mpdu_stitch_fail; - - frag_list_sum_len += msdu_len; - - /* Maintain the linking of the cloned MSDUS */ - qdf_nbuf_set_next_ext(prev_buf, msdu); - - /* Move to the next */ - prev_buf = msdu; - msdu_orig = qdf_nbuf_next(msdu_orig); - } - - /* The last msdu length need be larger than HTT_FCS_LEN */ - if (msdu_len < HTT_FCS_LEN) - goto mpdu_stitch_fail; - - qdf_nbuf_trim_tail(prev_buf, HTT_FCS_LEN); - - /* If there were more fragments to this RAW frame */ - if (head_frag_list_cloned) { - qdf_nbuf_append_ext_list(mpdu_buf, - head_frag_list_cloned, - frag_list_sum_len); - } - - goto mpdu_stitch_done; - } - - /* Decap mode: - * Calculate the amount of header in decapped packet to knock off based - * on the decap type and the corresponding number of raw bytes to copy - * status header - */ - - hdr_desc = &rx_desc->rx_hdr_status[0]; - - /* Base size */ - wifi_hdr_len = sizeof(struct ieee80211_frame); - wh = (struct ieee80211_frame *)hdr_desc; - - dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; - if (dir == IEEE80211_FC1_DIR_DSTODS) - wifi_hdr_len += 6; - - is_amsdu = 0; - if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { - qos = (struct ieee80211_qoscntl *) - (hdr_desc + wifi_hdr_len); - wifi_hdr_len += 2; - - is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU); - } - - /* TODO: Any security headers associated with MPDU */ - sec_hdr_len = 0; - - /* MSDU related stuff LLC - AMSDU subframe header etc */ - msdu_llc_len = is_amsdu ? (14 + 8) : 8; - - mpdu_buf_len = wifi_hdr_len + sec_hdr_len + msdu_llc_len; - - /* "Decap" header to remove from MSDU buffer */ - decap_hdr_pull_bytes = 14; - - /* Allocate a new nbuf for holding the 802.11 header retrieved from the - * status of the now decapped first msdu. Leave enough headroom for - * accomodating any radio-tap /prism like PHY header - */ -#define HTT_MAX_MONITOR_HEADER (512) - mpdu_buf = qdf_nbuf_alloc(pdev->osdev, - HTT_MAX_MONITOR_HEADER + mpdu_buf_len, - HTT_MAX_MONITOR_HEADER, 4, false); - - if (!mpdu_buf) - goto mpdu_stitch_fail; - - /* Copy the MPDU related header and enc headers into the first buffer - * - Note that there can be a 2 byte pad between heaader and enc header - */ - - prev_buf = mpdu_buf; - dest = qdf_nbuf_put_tail(prev_buf, wifi_hdr_len); - if (!dest) - goto mpdu_stitch_fail; - qdf_mem_copy(dest, hdr_desc, wifi_hdr_len); - hdr_desc += wifi_hdr_len; - - /* NOTE - This padding is present only in the RAW header status - not - * when the MSDU data payload is in RAW format. - */ - /* Skip the "IV pad" */ - if (wifi_hdr_len & 0x3) - hdr_desc += 2; - - /* The first LLC len is copied into the MPDU buffer */ - frag_list_sum_len = 0; - frag_list_sum_len -= msdu_llc_len; - - msdu_orig = head_msdu; - is_first_frag = 1; - amsdu_pad = 0; - - while (msdu_orig) { - - /* TODO: intra AMSDU padding - do we need it ??? */ - - if (clone_not_reqd) - msdu = htt_rx_qdf_noclone_buf(msdu_orig); - else - msdu = qdf_nbuf_clone(msdu_orig); - - if (!msdu) - goto mpdu_stitch_fail; - - if (is_first_frag) { - is_first_frag = 0; - head_frag_list_cloned = msdu; - } else { - - /* Maintain the linking of the cloned MSDUS */ - qdf_nbuf_set_next_ext(prev_buf, msdu); - - /* Reload the hdr ptr only on non-first MSDUs */ - rx_desc = htt_rx_desc(msdu_orig); - hdr_desc = &rx_desc->rx_hdr_status[0]; - - } - - /* Copy this buffers MSDU related status into the prev buffer */ - dest = qdf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); - dest += amsdu_pad; - qdf_mem_copy(dest, hdr_desc, msdu_llc_len); - - /* Push the MSDU buffer beyond the decap header */ - qdf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); - frag_list_sum_len += - msdu_llc_len + qdf_nbuf_len(msdu) + amsdu_pad; - - /* - * Set up intra-AMSDU pad to be added to start of next buffer - - * AMSDU pad is 4 byte pad on AMSDU subframe - */ - amsdu_pad = (msdu_llc_len + qdf_nbuf_len(msdu)) & 0x3; - amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0; - - /* - * TODO FIXME How do we handle MSDUs that have fraglist - Should - * probably iterate all the frags cloning them along the way and - * and also updating the prev_buf pointer - */ - - /* Move to the next */ - prev_buf = msdu; - msdu_orig = qdf_nbuf_next(msdu_orig); - - } - - /* TODO: Convert this to suitable qdf routines */ - qdf_nbuf_append_ext_list(mpdu_buf, head_frag_list_cloned, - frag_list_sum_len); - -mpdu_stitch_done: - /* Check if this buffer contains the PPDU end status for TSF */ - if (rx_desc->attention.last_mpdu) -#ifdef HELIUMPLUS - rx_status->rs_tstamp.tsf = - rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; -#else - rx_status->rs_tstamp.tsf = rx_desc->ppdu_end.tsf_timestamp; -#endif - /* All the nbufs have been linked into the ext list and - then unlink the nbuf list */ - if (clone_not_reqd) { - msdu = head_msdu; - while (msdu) { - msdu_orig = msdu; - msdu = qdf_nbuf_next(msdu); - qdf_nbuf_set_next(msdu_orig, NULL); - } - } - - return mpdu_buf; - -mpdu_stitch_fail: - /* Free these alloced buffers and the orig buffers in non-clone case */ - if (!clone_not_reqd) { - /* Free the head buffer */ - if (mpdu_buf) - qdf_nbuf_free(mpdu_buf); - - /* Free the partial list */ - while (head_frag_list_cloned) { - msdu = head_frag_list_cloned; - head_frag_list_cloned = - qdf_nbuf_next_ext(head_frag_list_cloned); - qdf_nbuf_free(msdu); - } - } else { - /* Free the alloced head buffer */ - if (decap_format != HW_RX_DECAP_FORMAT_RAW) - if (mpdu_buf) - qdf_nbuf_free(mpdu_buf); - - /* Free the orig buffers */ - msdu = head_msdu; - while (msdu) { - msdu_orig = msdu; - msdu = qdf_nbuf_next(msdu); - qdf_nbuf_free(msdu_orig); - } - } - - return NULL; -} -#else -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 clone_not_reqd) -{ - return NULL; -} -#endif int16_t htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc) { /* diff --git a/core/dp/ol/inc/ol_htt_api.h b/core/dp/ol/inc/ol_htt_api.h index 3ba7fd5f0f6c..cb51c8f5e17c 100644 --- a/core/dp/ol/inc/ol_htt_api.h +++ b/core/dp/ol/inc/ol_htt_api.h @@ -360,9 +360,17 @@ static inline void htt_ipa_uc_detach(struct htt_pdev_t *pdev) } #endif /* IPA_OFFLOAD */ +#ifdef FEATURE_MONITOR_MODE_SUPPORT void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch); void ol_htt_mon_note_chan(struct cdp_pdev *ppdev, int mon_ch); +#else +static inline +void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch) {} + +static inline +void ol_htt_mon_note_chan(struct cdp_pdev *ppdev, int mon_ch) {} +#endif #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) diff --git a/core/dp/ol/inc/ol_htt_rx_api.h b/core/dp/ol/inc/ol_htt_rx_api.h index 191ab4614a34..fab4291dc5a4 100644 --- a/core/dp/ol/inc/ol_htt_rx_api.h +++ b/core/dp/ol/inc/ol_htt_rx_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -824,11 +824,22 @@ int htt_rx_msdu_buff_in_order_replenish(htt_pdev_handle pdev, uint32_t num); * list, else operates on a cloned nbuf * @return network buffer handle to the MPDU */ +#if !defined(QCA6290_HEADERS_DEF) && defined(FEATURE_MONITOR_MODE_SUPPORT) 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 clone_not_reqd); +#else +static inline 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 clone_not_reqd) +{ + return NULL; +} +#endif /** * @brief Return the sequence number of MPDUs to flush. diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index f8218fa71a73..6b1da8f4b4b0 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -1718,6 +1718,7 @@ ol_rx_offload_paddr_deliver_ind_handler(htt_pdev_handle htt_pdev, } #endif +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * ol_htt_mon_note_chan() - Update monitor channel information * @pdev: handle to the physical device @@ -1731,6 +1732,7 @@ void ol_htt_mon_note_chan(struct cdp_pdev *ppdev, int mon_ch) htt_rx_mon_note_capture_channel(pdev->htt_pdev, mon_ch); } +#endif #ifdef NEVERDEFINED /** diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 8bcffb47123f..a44339ccfd46 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -3176,6 +3176,7 @@ bool hdd_is_cli_iface_up(struct hdd_context *hdd_ctx); */ void hdd_set_disconnect_status(struct hdd_adapter *adapter, bool disconnecting); +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * wlan_hdd_set_mon_chan() - Set capture channel on the monitor mode interface. * @adapter: Handle to adapter @@ -3186,6 +3187,14 @@ void hdd_set_disconnect_status(struct hdd_adapter *adapter, bool disconnecting); */ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, uint32_t chan, uint32_t bandwidth); +#else +static inline +int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, uint32_t chan, + uint32_t bandwidth) +{ + return 0; +} +#endif /** * hdd_wlan_get_version() - Get version information diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index ba842d058a2a..193cb158f1ed 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -181,7 +181,17 @@ const char *hdd_reason_type_to_string(enum netif_reason_type reason); const char *hdd_action_type_to_string(enum netif_action_type action); void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, enum netif_action_type action, enum netif_reason_type reason); + +#ifdef FEATURE_MONITOR_MODE_SUPPORT int hdd_set_mon_rx_cb(struct net_device *dev); +#else +static inline +int hdd_set_mon_rx_cb(struct net_device *dev) +{ + return 0; +} +#endif + void hdd_send_rps_ind(struct hdd_adapter *adapter); void hdd_send_rps_disable_ind(struct hdd_adapter *adapter); void wlan_hdd_classify_pkt(struct sk_buff *skb); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index bf22e21250c0..d00c04e2756a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -17541,6 +17541,64 @@ wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter, } #endif +#ifdef FEATURE_MONITOR_MODE_SUPPORT +static +void hdd_mon_select_cbmode(struct hdd_adapter *adapter, + uint8_t operationChannel, + struct ch_params *ch_params) +{ + struct hdd_station_ctx *station_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info; + enum hdd_dot11_mode hdd_dot11_mode; + uint8_t ini_dot11_mode = + (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode; + + hdd_debug("Dot11Mode is %u", ini_dot11_mode); + switch (ini_dot11_mode) { + case eHDD_DOT11_MODE_AUTO: + case eHDD_DOT11_MODE_11ax: + case eHDD_DOT11_MODE_11ax_ONLY: + if (sme_is_feature_supported_by_fw(DOT11AX)) + hdd_dot11_mode = eHDD_DOT11_MODE_11ax; + else if (sme_is_feature_supported_by_fw(DOT11AC)) + hdd_dot11_mode = eHDD_DOT11_MODE_11ac; + else + hdd_dot11_mode = eHDD_DOT11_MODE_11n; + break; + case eHDD_DOT11_MODE_11ac: + case eHDD_DOT11_MODE_11ac_ONLY: + if (sme_is_feature_supported_by_fw(DOT11AC)) + hdd_dot11_mode = eHDD_DOT11_MODE_11ac; + else + hdd_dot11_mode = eHDD_DOT11_MODE_11n; + break; + case eHDD_DOT11_MODE_11n: + case eHDD_DOT11_MODE_11n_ONLY: + hdd_dot11_mode = eHDD_DOT11_MODE_11n; + break; + default: + hdd_dot11_mode = ini_dot11_mode; + break; + } + ch_info->channel_width = ch_params->ch_width; + ch_info->phy_mode = + hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode); + ch_info->channel = operationChannel; + ch_info->cb_mode = ch_params->ch_width; + hdd_debug("ch_info width %d, phymode %d channel %d", + ch_info->channel_width, ch_info->phy_mode, + ch_info->channel); +} +#else +static +void hdd_mon_select_cbmode(struct hdd_adapter *adapter, + uint8_t operationChannel, + struct ch_params *ch_params) +{ +} +#endif + /** * hdd_select_cbmode() - select channel bonding mode * @adapter: Pointer to adapter @@ -17552,8 +17610,6 @@ wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter, void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel, struct ch_params *ch_params) { - struct hdd_station_ctx *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info; uint8_t sec_ch = 0; struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -17573,47 +17629,8 @@ void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel, wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel, sec_ch, ch_params); - if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) { - enum hdd_dot11_mode hdd_dot11_mode; - uint8_t iniDot11Mode = - (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode; - - hdd_debug("Dot11Mode is %u", iniDot11Mode); - switch (iniDot11Mode) { - case eHDD_DOT11_MODE_AUTO: - case eHDD_DOT11_MODE_11ax: - case eHDD_DOT11_MODE_11ax_ONLY: - if (sme_is_feature_supported_by_fw(DOT11AX)) - hdd_dot11_mode = eHDD_DOT11_MODE_11ax; - else if (sme_is_feature_supported_by_fw(DOT11AC)) - hdd_dot11_mode = eHDD_DOT11_MODE_11ac; - else - hdd_dot11_mode = eHDD_DOT11_MODE_11n; - break; - case eHDD_DOT11_MODE_11ac: - case eHDD_DOT11_MODE_11ac_ONLY: - if (sme_is_feature_supported_by_fw(DOT11AC)) - hdd_dot11_mode = eHDD_DOT11_MODE_11ac; - else - hdd_dot11_mode = eHDD_DOT11_MODE_11n; - break; - case eHDD_DOT11_MODE_11n: - case eHDD_DOT11_MODE_11n_ONLY: - hdd_dot11_mode = eHDD_DOT11_MODE_11n; - break; - default: - hdd_dot11_mode = iniDot11Mode; - break; - } - ch_info->channel_width = ch_params->ch_width; - ch_info->phy_mode = - hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode); - ch_info->channel = operationChannel; - ch_info->cb_mode = ch_params->ch_width; - hdd_debug("ch_info width %d, phymode %d channel %d", - ch_info->channel_width, ch_info->phy_mode, - ch_info->channel); - } + if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) + hdd_mon_select_cbmode(adapter, operationChannel, ch_params); } /** @@ -22013,6 +22030,7 @@ int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter, return 0; } +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel * @wiphy: Handle to struct wiphy to get handle to module context. @@ -22117,6 +22135,7 @@ static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy, cds_ssr_unprotect(__func__); return ret; } +#endif /** * wlan_hdd_clear_link_layer_stats() - clear link layer stats @@ -22677,7 +22696,9 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { #ifdef CHANNEL_SWITCH_SUPPORTED .channel_switch = wlan_hdd_cfg80211_channel_switch, #endif +#ifdef FEATURE_MONITOR_MODE_SUPPORT .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch, +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \ defined(CFG80211_ABORT_SCAN) .abort_scan = wlan_hdd_cfg80211_abort_scan, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 09256a1db78d..bf78a78eb8bd 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2133,6 +2133,7 @@ static void hdd_mon_mode_ether_setup(struct net_device *dev) memset(dev->broadcast, 0xFF, ETH_ALEN); } +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * __hdd__mon_open() - HDD Open function * @dev: Pointer to net_device structure @@ -2201,6 +2202,7 @@ static int hdd_mon_open(struct net_device *dev) return ret; } +#endif static QDF_STATUS wlan_hdd_update_dbs_scan_and_fw_mode_config(void) @@ -3525,6 +3527,7 @@ static const struct net_device_ops wlan_drv_ops = { #endif }; +#ifdef FEATURE_MONITOR_MODE_SUPPORT /* Monitor mode net_device_ops, doesnot Tx and most of operations. */ static const struct net_device_ops wlan_mon_drv_ops = { .ndo_open = hdd_mon_open, @@ -3544,6 +3547,12 @@ void hdd_set_station_ops(struct net_device *dev) else dev->netdev_ops = &wlan_drv_ops; } +#else +void hdd_set_station_ops(struct net_device *dev) +{ + dev->netdev_ops = &wlan_drv_ops; +} +#endif /** * hdd_alloc_station_adapter() - allocate the station hdd adapter @@ -5875,6 +5884,7 @@ void hdd_connect_result(struct net_device *dev, const u8 *bssid, } #endif +#ifdef FEATURE_MONITOR_MODE_SUPPORT int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, uint32_t chan, uint32_t bandwidth) { @@ -5952,6 +5962,7 @@ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, uint32_t chan, adapter->mon_bandwidth = bandwidth; return qdf_status_to_os_return(status); } +#endif #ifdef MSM_PLATFORM /** @@ -12447,6 +12458,32 @@ static int fwpath_changed_handler(const char *kmessage, return param_set_copystring(kmessage, kp); } +#ifdef FEATURE_MONITOR_MODE_SUPPORT +static bool is_monitor_mode_supported(void) +{ + return true; +} +#else +static bool is_monitor_mode_supported(void) +{ + pr_err("Monitor mode not supported!"); + return false; +} +#endif + +#ifdef WLAN_FEATURE_EPPING +static bool is_epping_mode_supported(void) +{ + return true; +} +#else +static bool is_epping_mode_supported(void) +{ + pr_err("Epping mode not supported!"); + return false; +} +#endif + /** * is_con_mode_valid() check con mode is valid or not * @mode: global con mode @@ -12457,8 +12494,10 @@ static bool is_con_mode_valid(enum QDF_GLOBAL_MODE mode) { switch (mode) { case QDF_GLOBAL_MONITOR_MODE: - case QDF_GLOBAL_FTM_MODE: + return is_monitor_mode_supported(); case QDF_GLOBAL_EPPING_MODE: + return is_epping_mode_supported(); + case QDF_GLOBAL_FTM_MODE: case QDF_GLOBAL_MISSION_MODE: return true; default: @@ -12752,6 +12791,7 @@ static int con_mode_handler_ftm(const char *kmessage, return ret; } +#ifdef FEATURE_MONITOR_MODE_SUPPORT static int con_mode_handler_monitor(const char *kmessage, const struct kernel_param *kp) { @@ -12769,6 +12809,7 @@ static int con_mode_handler_monitor(const char *kmessage, return ret; } +#endif /** * hdd_get_conparam() - driver exit point @@ -14026,10 +14067,12 @@ static const struct kernel_param_ops con_mode_ftm_ops = { .get = param_get_int, }; +#ifdef FEATURE_MONITOR_MODE_SUPPORT static const struct kernel_param_ops con_mode_monitor_ops = { .set = con_mode_handler_monitor, .get = param_get_int, }; +#endif static const struct kernel_param_ops fwpath_ops = { .set = fwpath_changed_handler, @@ -14042,8 +14085,10 @@ module_param_cb(con_mode, &con_mode_ops, &con_mode, module_param_cb(con_mode_ftm, &con_mode_ftm_ops, &con_mode_ftm, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#ifdef FEATURE_MONITOR_MODE_SUPPORT module_param_cb(con_mode_monitor, &con_mode_monitor_ops, &con_mode_monitor, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif module_param_cb(fwpath, &fwpath_ops, &fwpath, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 9fda667b1515..cfa3c66e4eb2 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -1304,6 +1304,7 @@ QDF_STATUS hdd_deinit_tx_rx(struct hdd_adapter *adapter) return status; } +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * hdd_mon_rx_packet_cbk() - Receive callback registered with OL layer. * @context: [in] pointer to qdf context @@ -1379,6 +1380,7 @@ static QDF_STATUS hdd_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf) return QDF_STATUS_SUCCESS; } +#endif /** * hdd_get_peer_idx() - Get the idx for given address in peer table @@ -2338,6 +2340,7 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, adapter->history_index = 0; } +#ifdef FEATURE_MONITOR_MODE_SUPPORT /** * hdd_set_mon_rx_cb() - Set Monitor mode Rx callback * @dev: Pointer to net_device structure @@ -2381,6 +2384,7 @@ exit: ret = qdf_status_to_os_return(qdf_status); return ret; } +#endif /** * hdd_send_rps_ind() - send rps indication to daemon diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index b246aec89e04..9b182dc95462 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -10126,11 +10126,12 @@ static const struct iw_priv_args we_private_args[] = { 0, "dump_dp_trace"} , #endif +#ifdef FEATURE_MONITOR_MODE_SUPPORT {WE_SET_MON_MODE_CHAN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setMonChan"} , - +#endif {WE_GET_ROAM_SYNCH_DELAY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,