Browse Source

qcacmn: Fix Radiotap headers in monitor mode

In monitor mode, code decodes legacy rates and bandwidth information for
HT and VHT. Other changes include populating radiotap header with correct
nss and mcs values for legacy, HT and VHT frames. Mapping of mcs rates in
rx_msdu_start tlv and radiotap header info is done using Lithium data
structure document.

Change-Id: I5f20e5d89329738e3a6c076ee14457c003cab279
CRs-fixed: 2083027
sumedh baikady 7 years ago
parent
commit
86a83e8927
3 changed files with 139 additions and 8 deletions
  1. 106 5
      hal/wifi3.0/hal_api_mon.h
  2. 2 0
      hal/wifi3.0/hal_internal.h
  3. 31 3
      qdf/linux/src/qdf_nbuf.c

+ 106 - 5
hal/wifi3.0/hal_api_mon.h

@@ -86,6 +86,23 @@
 #define HAL_RX_RECEPTION_TYPE_OFDMA	2
 #define HAL_RX_RECEPTION_TYPE_MU_OFDMA	3
 
+#define HAL_11B_RATE_0MCS	11
+#define HAL_11B_RATE_1MCS	5.5
+#define HAL_11B_RATE_2MCS	2
+#define HAL_11B_RATE_3MCS	1
+#define HAL_11B_RATE_4MCS	11
+#define HAL_11B_RATE_5MCS	5.5
+#define HAL_11B_RATE_6MCS	2
+
+#define HAL_11A_RATE_0MCS	48
+#define HAL_11A_RATE_1MCS	24
+#define HAL_11A_RATE_2MCS	12
+#define HAL_11A_RATE_3MCS	6
+#define HAL_11A_RATE_4MCS	54
+#define HAL_11A_RATE_5MCS	36
+#define HAL_11A_RATE_6MCS	18
+#define HAL_11A_RATE_7MCS	9
+
 enum {
 	HAL_HW_RX_DECAP_FORMAT_RAW = 0,
 	HAL_HW_RX_DECAP_FORMAT_NWIFI,
@@ -351,7 +368,7 @@ void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr,
 	struct rx_msdu_start *rx_msdu_start;
 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
 	uint32_t reg_value;
-
+	uint8_t nss = 0;
 	static uint32_t sgi_hw_to_cdp[] = {
 		CDP_SGI_0_8_US,
 		CDP_SGI_0_4_US,
@@ -373,12 +390,19 @@ void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr,
 
 	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE);
 	switch (reg_value) {
+	case HAL_RX_PKT_TYPE_11N:
+		rs->ht_flags = 1;
+		rs->bw = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5,
+			RECEIVE_BANDWIDTH);
+		break;
 	case HAL_RX_PKT_TYPE_11AC:
 		rs->vht_flags = 1;
 		reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5,
-		RECEIVE_BANDWIDTH);
-		rs->vht_flag_values2 = 0x01 << reg_value;
-		rs->vht_flag_values3[0] = rs->mcs << 4;
+			RECEIVE_BANDWIDTH);
+		rs->vht_flag_values2 = reg_value;
+		nss = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS);
+		nss = nss + 1;
+		rs->vht_flag_values3[0] = (rs->mcs << 4) | nss ;
 		break;
 	case HAL_RX_PKT_TYPE_11AX:
 		rs->he_flags = 1;
@@ -386,7 +410,6 @@ void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr,
 	default:
 		break;
 	}
-
 	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE);
 	rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0;
 	/* TODO: rs->beamformed should be set for SU beamforming also */
@@ -436,6 +459,7 @@ static inline uint32_t
 hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 {
 	uint32_t tlv_tag, user_id, tlv_len, value;
+	uint8_t group_id = 0;
 
 	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
 	user_id = HAL_RX_GET_USER_TLV32_USERID(rx_tlv);
@@ -526,15 +550,92 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 			1 : 0;
 		break;
 	}
+
+	case WIFIPHYRX_L_SIG_B_E:
+	{
+		uint8_t *l_sig_b_info = (uint8_t *)rx_tlv +
+				HAL_RX_OFFSET(PHYRX_L_SIG_B_0,
+				L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS);
+
+		value = HAL_RX_GET(l_sig_b_info, L_SIG_B_INFO_0, RATE);
+		switch (value) {
+		case 1:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_3MCS;
+			break;
+		case 2:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_2MCS;
+			break;
+		case 3:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_1MCS;
+			break;
+		case 4:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_0MCS;
+			break;
+		case 5:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_6MCS;
+			break;
+		case 6:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_5MCS;
+			break;
+		case 7:
+			ppdu_info->rx_status.rate = HAL_11B_RATE_4MCS;
+			break;
+		default:
+			break;
+		}
+	break;
+	}
+
+	case WIFIPHYRX_L_SIG_A_E:
+	{
+		uint8_t *l_sig_a_info = (uint8_t *)rx_tlv +
+				HAL_RX_OFFSET(PHYRX_L_SIG_A_0,
+				L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS);
+
+		value = HAL_RX_GET(l_sig_a_info, L_SIG_A_INFO_0, RATE);
+		switch (value) {
+		case 8:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_0MCS;
+			break;
+		case 9:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_1MCS;
+			break;
+		case 10:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_2MCS;
+			break;
+		case 11:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_3MCS;
+			break;
+		case 12:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_4MCS;
+			break;
+		case 13:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_5MCS;
+			break;
+		case 14:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_6MCS;
+			break;
+		case 15:
+			ppdu_info->rx_status.rate = HAL_11A_RATE_7MCS;
+			break;
+		default:
+			break;
+		}
+	break;
+	}
+
 	case WIFIPHYRX_VHT_SIG_A_E:
 	{
 		uint8_t *vht_sig_a_info = (uint8_t *)rx_tlv +
 				HAL_RX_OFFSET(PHYRX_VHT_SIG_A_0,
 				VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS);
+
 		value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_1,
 				SU_MU_CODING);
 		ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ?
 			1 : 0;
+		group_id = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_0, GROUP_ID);
+		ppdu_info->rx_status.vht_flag_values5 = group_id;
 		break;
 	}
 	case WIFIPHYRX_HE_SIG_A_SU_E:

+ 2 - 0
hal/wifi3.0/hal_internal.h

@@ -70,6 +70,8 @@
 #include "phyrx_he_sig_b1_mu.h"
 #include "phyrx_he_sig_b2_mu.h"
 #include "phyrx_he_sig_b2_ofdma.h"
+#include "phyrx_l_sig_a.h"
+#include "phyrx_l_sig_b.h"
 #include "phyrx_vht_sig_a.h"
 #include "phyrx_ht_sig.h"
 #include "tx_msdu_extension.h"

+ 31 - 3
qdf/linux/src/qdf_nbuf.c

@@ -53,6 +53,7 @@
 #endif /* FEATURE_TSO */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+
 #define qdf_nbuf_users_inc atomic_inc
 #define qdf_nbuf_users_dec atomic_dec
 #define qdf_nbuf_users_set atomic_set
@@ -64,6 +65,19 @@
 #define qdf_nbuf_users_read refcount_read
 #endif /* KERNEL_VERSION(4, 13, 0) */
 
+#define RATE_MULTIPLIER		2
+
+#define IEEE80211_RADIOTAP_VHT_BW_20	0
+#define IEEE80211_RADIOTAP_VHT_BW_40	1
+#define IEEE80211_RADIOTAP_VHT_BW_80	2
+#define IEEE80211_RADIOTAP_VHT_BW_160	3
+
+#define RADIOTAP_VHT_BW_20	0
+#define RADIOTAP_VHT_BW_40	1
+#define RADIOTAP_VHT_BW_80	4
+#define RADIOTAP_VHT_BW_160	11
+
+
 /* Packet Counter */
 static uint32_t nbuf_tx_mgmt[QDF_NBUF_TX_PKT_STATE_MAX];
 static uint32_t nbuf_tx_data[QDF_NBUF_TX_PKT_STATE_MAX];
@@ -2674,8 +2688,20 @@ static unsigned int qdf_nbuf_update_radiotap_vht_flags(
 		(rx_status->beamformed ?
 		 IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED : 0);
 	rtap_len += 1;
-
-	rtap_buf[rtap_len] = (rx_status->vht_flag_values2);
+	switch (rx_status->vht_flag_values2) {
+	case IEEE80211_RADIOTAP_VHT_BW_20:
+		rtap_buf[rtap_len] = RADIOTAP_VHT_BW_20;
+		break;
+	case IEEE80211_RADIOTAP_VHT_BW_40:
+		rtap_buf[rtap_len] = RADIOTAP_VHT_BW_40;
+		break;
+	case IEEE80211_RADIOTAP_VHT_BW_80:
+		rtap_buf[rtap_len] = RADIOTAP_VHT_BW_80;
+		break;
+	case IEEE80211_RADIOTAP_VHT_BW_160:
+		rtap_buf[rtap_len] = RADIOTAP_VHT_BW_160;
+		break;
+	}
 	rtap_len += 1;
 	rtap_buf[rtap_len] = (rx_status->vht_flag_values3[0]);
 	rtap_len += 1;
@@ -2810,7 +2836,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
 	/* IEEE80211_RADIOTAP_RATE  u8           500kb/s */
 	if (!rx_status->ht_flags && !rx_status->vht_flags) {
 		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
-		rtap_buf[rtap_len] = rx_status->rate;
+		rtap_buf[rtap_len] = rx_status->rate * RATE_MULTIPLIER;
 	} else
 		rtap_buf[rtap_len] = 0;
 	rtap_len += 1;
@@ -2852,6 +2878,8 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
 			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_SGI;
 		if (rx_status->bw)
 			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_BW_40;
+		else
+			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_BW_20;
 		rtap_len += 1;
 
 		rtap_buf[rtap_len] = rx_status->mcs;