|
@@ -53,12 +53,6 @@
|
|
|
#endif
|
|
|
#include <pktlog_ac_fmt.h>
|
|
|
|
|
|
-#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);
|
|
|
}
|
|
|
-#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)
|
|
|
+#else
|
|
|
+static qdf_dma_addr_t
|
|
|
+htt_rx_paddr_mark_high_bits(qdf_dma_addr_t paddr)
|
|
|
{
|
|
|
- return paddr;
|
|
|
+ return 0;
|
|
|
}
|
|
|
-#endif /* HTT_PADDR64 */
|
|
|
+#endif
|
|
|
|
|
|
#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)
|
|
|
{
|
|
|
/*
|