summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-14 02:23:32 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-14 02:23:32 -0800
commit4ee69dfb15bb00a85cd9f18951995f9bf4691374 (patch)
tree3fae897a260847a537c2288662ffc3b6e385cecc
parente85a05376e3c09a8f958295f07acce09e78715eb (diff)
parent8cf139e51d55121dbc4bff518ba975567d35c308 (diff)
Merge "qcacld-2.0: Add MCS/VHT info to radiotap header" into wlan-cld2.driver.lnx.1.0-dev
-rw-r--r--CORE/CLD_TXRX/HTT/htt_rx.c70
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_nbuf.c102
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_nbuf.h32
3 files changed, 187 insertions, 17 deletions
diff --git a/CORE/CLD_TXRX/HTT/htt_rx.c b/CORE/CLD_TXRX/HTT/htt_rx.c
index baa627e7dae2..69afa95b137f 100644
--- a/CORE/CLD_TXRX/HTT/htt_rx.c
+++ b/CORE/CLD_TXRX/HTT/htt_rx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1746,34 +1746,71 @@ htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
}
/**
- * get_num_antenna_hl() - get number of antenna
+ * get_ht_vht_info() - get ht/vht information
* @rx_desc: pointer to htt_host_rx_desc_base.
+ * @rx_status: pointer to mon_rx_status.
*
- * Return: number of antenna.
+ * This function retrieve MCS/VHT info by parsing preamble,
+ * vht_sig_a1 and vht_sig_a2, which follows ieee80211 spec.
+ * Since high latency path doesn't config PPDU/MPDU start/end,
+ * it only uses the info which htt_rx_ppdu_desc_t has.
+ *
+ * Return: None.
*/
-static uint8_t get_num_antenna_hl(struct htt_rx_ppdu_desc_t *rx_desc)
+static void get_ht_vht_info_hl(struct htt_rx_ppdu_desc_t *rx_desc,
+ struct mon_rx_status *rx_status)
{
uint8_t preamble_type =
(uint8_t)rx_desc->preamble_type;
- uint8_t mcs, nss = 1;
switch (preamble_type) {
case 8:
case 9:
- mcs = (uint8_t)(rx_desc->vht_sig_a1 & 0x7f);
- nss = mcs >> 3;
+ rx_status->mcs_info.valid = 1;
+ rx_status->vht_info.valid = 0;
+ rx_status->mcs_info.mcs = rx_desc->vht_sig_a1 & 0x7f;
+ rx_status->nr_ant = rx_status->mcs_info.mcs >> 3;
+ rx_status->mcs_info.bw = (rx_desc->vht_sig_a1 >> 7) & 0x1;
+ rx_status->mcs_info.smoothing = rx_desc->vht_sig_a2 & 0x1;
+ rx_status->mcs_info.not_sounding =
+ (rx_desc->vht_sig_a2 >> 1) & 0x1;
+ rx_status->mcs_info.aggregation =
+ (rx_desc->vht_sig_a2 >> 3) & 0x1;
+ rx_status->mcs_info.stbc = (rx_desc->vht_sig_a2 >> 4) & 0x3;
+ rx_status->mcs_info.fec = (rx_desc->vht_sig_a2 >> 6) & 0x1;
+ rx_status->mcs_info.sgi = (rx_desc->vht_sig_a2 >> 7) & 0x1;
+ rx_status->mcs_info.ness = (rx_desc->vht_sig_a2 >> 8) & 0x3;
break;
case 0x0c: /* VHT w/o TxBF */
case 0x0d: /* VHT w/ TxBF */
- mcs = (uint8_t)((rx_desc->vht_sig_a2
- >> 4) & 0xf);
- nss = (uint8_t)((rx_desc->vht_sig_a1
- >> 10) & 0x7);
+ rx_status->vht_info.valid = 1;
+ rx_status->mcs_info.valid = 0;
+ rx_status->vht_info.bw = rx_desc->vht_sig_a1 & 0x3;
+ rx_status->vht_info.stbc = (rx_desc->vht_sig_a1 >> 3) & 0x1;
+ /* Currently only handle SU case */
+ rx_status->vht_info.gid = (rx_desc->vht_sig_a1 >> 4) & 0x3f;
+ rx_status->vht_info.nss = (rx_desc->vht_sig_a1 >> 10) & 0x7;
+ rx_status->nr_ant = (rx_desc->vht_sig_a1 >> 10) & 0x7;
+ rx_status->vht_info.paid = (rx_desc->vht_sig_a1 >> 13) & 0x1ff;
+ rx_status->vht_info.txps_forbidden =
+ (rx_desc->vht_sig_a1 >> 22) & 0x1;
+ rx_status->vht_info.sgi = rx_desc->vht_sig_a2 & 0x1;
+ rx_status->vht_info.sgi_disambiguation =
+ (rx_desc->vht_sig_a2 >> 1) & 0x1;
+ rx_status->vht_info.coding = (rx_desc->vht_sig_a2 >> 2) & 0x1;
+ rx_status->vht_info.ldpc_extra_symbol =
+ (rx_desc->vht_sig_a2 >> 3) & 0x1;
+ rx_status->vht_info.mcs = (rx_desc->vht_sig_a2
+ >> 4) & 0xf;
+ rx_status->vht_info.beamformed = (rx_desc->vht_sig_a2
+ >> 8) & 0x1;
break;
default:
+ rx_status->mcs_info.valid = 0;
+ rx_status->vht_info.valid = 0;
+ rx_status->nr_ant = 1;
break;
}
- return nss;
}
/**
@@ -1796,9 +1833,14 @@ void htt_get_radiotap_rx_status_hl(struct htt_rx_ppdu_desc_t *rx_desc,
rx_desc->legacy_rate);
channel_flags |= rx_desc->legacy_rate_sel ?
IEEE80211_CHAN_CCK : IEEE80211_CHAN_OFDM;
+ if (rx_status->chan)
+ channel_flags |=
+ (vos_chan_to_band(vos_freq_to_chan(rx_status->chan))
+ == VOS_BAND_2GHZ ?
+ IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ);
rx_status->chan_flags = channel_flags;
rx_status->ant_signal_db = rx_desc->rssi_cmb;
- rx_status->nr_ant = get_num_antenna_hl(rx_desc);
+ get_ht_vht_info_hl(rx_desc, rx_status);
}
/**
@@ -1840,7 +1882,6 @@ htt_rx_mon_amsdu_pop_hl(
rx_desc = htt_rx_msdu_desc_retrieve(pdev, *head_msdu);
rx_ppdu_desc = (struct htt_rx_ppdu_desc_t *)((uint8_t *)(rx_desc) -
HTT_RX_IND_HL_BYTES + HTT_RX_IND_HDR_PREFIX_BYTES);
- htt_get_radiotap_rx_status_hl(rx_ppdu_desc, &rx_status);
rx_mpdu_desc =
htt_rx_mpdu_desc_list_next(pdev, rx_ind_msg);
@@ -1852,6 +1893,7 @@ htt_rx_mon_amsdu_pop_hl(
else
rx_status.chan = 0;
+ htt_get_radiotap_rx_status_hl(rx_ppdu_desc, &rx_status);
/*
* set headroom size to 0 to append to tail of skb. For HL path,
* rx desc size is variable and will be used later in ol_rx_deliver
diff --git a/CORE/SERVICES/COMMON/adf/adf_nbuf.c b/CORE/SERVICES/COMMON/adf/adf_nbuf.c
index ab38e62afbd4..bb8fd7be1234 100644
--- a/CORE/SERVICES/COMMON/adf/adf_nbuf.c
+++ b/CORE/SERVICES/COMMON/adf/adf_nbuf.c
@@ -1708,12 +1708,20 @@ int adf_nbuf_update_radiotap(struct mon_rx_status *rx_status, adf_nbuf_t nbuf,
rtap_len += 1;
/* IEEE80211_RADIOTAP_RATE u8 500kb/s*/
- rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
- rtap_buf[rtap_len] = rx_status->rate;
- rtap_len += 1;
+ if (!(rx_status->mcs_info.valid || rx_status->vht_info.valid)) {
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+ rtap_buf[rtap_len] = rx_status->rate;
+ rtap_len += 1;
+ }
/* IEEE80211_RADIOTAP_CHANNEL */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL);
+ /* padding */
+ if (rx_status->mcs_info.valid || rx_status->vht_info.valid) {
+ rtap_buf[rtap_len] = 0;
+ rtap_len += 1;
+ }
/* Channel frequency in Mhz */
put_unaligned_le16(rx_status->chan, (void *)&rtap_buf[rtap_len]);
rtap_len += 2;
@@ -1742,6 +1750,94 @@ int adf_nbuf_update_radiotap(struct mon_rx_status *rx_status, adf_nbuf_t nbuf,
rtap_buf[rtap_len] = rx_status->nr_ant;
rtap_len += 1;
+ /* IEEE80211_RADIOTAP_MCS: u8 known, u8 flags, u8 mcs */
+ if (rx_status->mcs_info.valid) {
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
+ /*
+ * known fields: band width, mcs index, short GI, FEC type,
+ * STBC streams, ness.
+ */
+ rtap_buf[rtap_len] = 0x77;
+ rtap_len += 1;
+ /* band width */
+ rtap_buf[rtap_len] = 0;
+ rtap_buf[rtap_len] |= (rx_status->mcs_info.bw & 0x3);
+ /* short GI */
+ rtap_buf[rtap_len] |= ((rx_status->mcs_info.sgi << 2) & 0x4);
+ /* FEC type */
+ rtap_buf[rtap_len] |= ((rx_status->mcs_info.fec << 4) & 0x10);
+ /* STBC streams */
+ rtap_buf[rtap_len] |= ((rx_status->mcs_info.stbc << 5) & 0x60);
+ /* ness */
+ rtap_buf[rtap_len] |= ((rx_status->mcs_info.ness << 7) & 0x80);
+ rtap_len += 1;
+ /* mcs index */
+ rtap_buf[rtap_len] = rx_status->mcs_info.mcs;
+ rtap_len += 1;
+ }
+
+ /* IEEE80211_RADIOTAP_VHT: u16, u8, u8, u8[4], u8, u8, u16 */
+ if (rx_status->vht_info.valid) {
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
+ /* padding */
+ rtap_buf[rtap_len] = 0;
+ rtap_len += 1;
+ /*
+ * known fields: STBC, TXOP_PS_NOT_ALLOWED,
+ * Short GI NSYM disambiguation, short GI,
+ * LDPC extra OFDM symbol, Beamformed ,
+ * bandwidth, gid, Partial AID
+ */
+ put_unaligned_le16(0x1ff, (void *)&rtap_buf[rtap_len]);
+ rtap_len += 2;
+ /* STBC */
+ rtap_buf[rtap_len] = 0;
+ rtap_buf[rtap_len] |= (rx_status->vht_info.stbc & 0x1);
+ /* TXOP_PS_NOT_ALLOWED */
+ rtap_buf[rtap_len] |=
+ ((rx_status->vht_info.txps_forbidden << 1) & 0x2);
+ /* short GI */
+ rtap_buf[rtap_len] |=
+ ((rx_status->vht_info.sgi << 2) & 0x4);
+ /* short GI NSYM disambiguation */
+ rtap_buf[rtap_len] |=
+ ((rx_status->vht_info.sgi_disambiguation << 3) & 0x8);
+ /* LDPC Extra OFDM symbol */
+ rtap_buf[rtap_len] |=
+ ((rx_status->vht_info.ldpc_extra_symbol << 4) & 0x10);
+ /* Beamformed */
+ rtap_buf[rtap_len] |=
+ ((rx_status->vht_info.beamformed << 5) & 0x20);
+ rtap_len += 1;
+ /* band width, transform to radiotap format */
+ rtap_buf[rtap_len] =
+ ((rx_status->vht_info.bw == 2) ?
+ 4 : rx_status->vht_info.bw) & 0x1f;
+ rtap_len += 1;
+ /* nss */
+ rtap_buf[rtap_len] |= ((1 + rx_status->vht_info.nss) & 0x0f);
+ /* mcs */
+ rtap_buf[rtap_len] |= ((rx_status->vht_info.mcs << 4) & 0xf0);
+ rtap_len += 1;
+ /* only support SG, so set 0 other 3 users */
+ rtap_buf[rtap_len] = 0;
+ rtap_len += 1;
+ rtap_buf[rtap_len] = 0;
+ rtap_len += 1;
+ rtap_buf[rtap_len] = 0;
+ rtap_len += 1;
+ /* LDPC */
+ rtap_buf[rtap_len] = rx_status->vht_info.coding;
+ rtap_len += 1;
+ /* gid */
+ rtap_buf[rtap_len] = rx_status->vht_info.gid;
+ rtap_len += 1;
+ /* pid */
+ put_unaligned_le16((uint16_t)(rx_status->vht_info.paid),
+ (void *)&rtap_buf[rtap_len]);
+ rtap_len += 2;
+ }
+
rthdr->it_len = cpu_to_le16(rtap_len);
if (headroom_sz >= rtap_len) {
diff --git a/CORE/SERVICES/COMMON/adf/adf_nbuf.h b/CORE/SERVICES/COMMON/adf/adf_nbuf.h
index 1a5c20ecc0a6..747d4209fd64 100644
--- a/CORE/SERVICES/COMMON/adf/adf_nbuf.h
+++ b/CORE/SERVICES/COMMON/adf/adf_nbuf.h
@@ -121,6 +121,8 @@
* @rate: Rate in terms 500Kbps
* @ant_signal_db: Rx packet RSSI
* @nr_ant: Number of Antennas used for streaming
+ * @mcs_info: Parsed ht sig info
+ * @vht_info: Parsed vht sig info
*/
struct mon_rx_status {
@@ -131,6 +133,36 @@ struct mon_rx_status {
uint8_t rate;
uint8_t ant_signal_db;
uint8_t nr_ant;
+ struct mon_rx_mcs_info {
+ uint8_t valid;
+ uint32_t mcs: 7,
+ bw: 1,
+ smoothing: 1,
+ not_sounding: 1,
+ aggregation: 1,
+ stbc: 2,
+ fec: 1,
+ sgi: 1,
+ ness: 2,
+ reserved: 15;
+ } mcs_info;
+
+ struct mon_rx_vht_info {
+ uint8_t valid;
+ uint32_t bw: 2,
+ stbc: 1,
+ gid: 6,
+ nss: 3,
+ paid: 9,
+ txps_forbidden: 1,
+ sgi: 1,
+ sgi_disambiguation: 1,
+ coding: 1,
+ ldpc_extra_symbol: 1,
+ mcs: 4,
+ beamformed: 1,
+ reserved: 1;
+ } vht_info;
};
/* DHCP Related Mask */