diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-14 02:23:32 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-14 02:23:32 -0800 |
| commit | 4ee69dfb15bb00a85cd9f18951995f9bf4691374 (patch) | |
| tree | 3fae897a260847a537c2288662ffc3b6e385cecc | |
| parent | e85a05376e3c09a8f958295f07acce09e78715eb (diff) | |
| parent | 8cf139e51d55121dbc4bff518ba975567d35c308 (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.c | 70 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/adf_nbuf.c | 102 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/adf_nbuf.h | 32 |
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 */ |
