From patchwork Fri Apr 10 08:54:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryder Lee X-Patchwork-Id: 11482977 X-Patchwork-Delegate: nbd@nbd.name Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2112992C for ; Fri, 10 Apr 2020 08:55:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ED80F207FF for ; Fri, 10 Apr 2020 08:55:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="X69j7rl5" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726676AbgDJIzR (ORCPT ); Fri, 10 Apr 2020 04:55:17 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:49894 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726598AbgDJIzQ (ORCPT ); Fri, 10 Apr 2020 04:55:16 -0400 X-UUID: f6adb5a0dbee48b687b528318d90585b-20200410 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=6Iap4yQ4RgTsNNmL0VeTnIEU1y8N17XPHCJ/cCLAsj8=; b=X69j7rl5ufg/KyIQg6SFDHTmBEridUQjI+Ov4xvomb71p4J07Kgaubqs/FCxaLAf5Nt1RCO4Sy8+7Bren4RZau74+iBQQFPwOOGhkj0TcIeIl7KklcreH3x74V1XDfJoYkflSiRzMbT5bsztj6JWlp6lAtOUtvdPyWMXYzpTz3o=; X-UUID: f6adb5a0dbee48b687b528318d90585b-20200410 Received: from mtkexhb02.mediatek.inc [(172.21.101.103)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 1884961516; Fri, 10 Apr 2020 16:55:06 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs02n1.mediatek.inc (172.21.101.77) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 10 Apr 2020 16:55:02 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 10 Apr 2020 16:55:02 +0800 From: Ryder Lee To: Felix Fietkau , Lorenzo Bianconi CC: Shayne Chen , YF Luo , Yiwei Chung , Chih-Min Chen , Evelyn Tsai , Sean Wang , , , Ryder Lee Subject: [PATCH 12/16] mt76: mt7915: add Rx radiotap header support Date: Fri, 10 Apr 2020 16:54:49 +0800 Message-ID: <616fb2d447ab3612ce43c00b938d42c7bf71b373.1586507878.git.ryder.lee@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org mac80211 expects the definition of what HE rate info is available inside astruct prepended to the skb. Signed-off-by: Ryder Lee --- .../net/wireless/mediatek/mt76/mt7915/mac.c | 141 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mac.h | 16 ++ 2 files changed, 157 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index f0604bb6d644..61d2d90637f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -9,6 +9,10 @@ #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ + IEEE80211_RADIOTAP_HE_##f) + static const struct mt7915_dfs_radar_spec etsi_radar_specs = { .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, .radar_pattern = { @@ -171,6 +175,138 @@ void mt7915_mac_sta_poll(struct mt7915_dev *dev) rcu_read_unlock(); } +static void +mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, + struct mt7915_rxv *rxv, + struct ieee80211_radiotap_he *he) +{ + u32 ru_h, ru_l; + u8 ru, offs = 0; + + ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv->v[0])); + ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv->v[1])); + ru = (u8)(ru_l | ru_h << 4); + + status->bw = RATE_INFO_BW_HE_RU; + + switch (ru) { + case 0 ... 36: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; + offs = ru; + break; + case 37 ... 52: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; + offs = ru - 37; + break; + case 53 ... 60: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; + offs = ru - 53; + break; + case 61 ... 64: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; + offs = ru - 61; + break; + case 65 ... 66: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; + offs = ru - 65; + break; + case 67: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 68: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; + break; + } + + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | + le16_encode_bits(offs, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); +} + +static void +mt7915_mac_decode_he_radiotap(struct sk_buff *skb, + struct mt76_rx_status *status, + struct mt7915_rxv *rxv) +{ + /* TODO: struct ieee80211_radiotap_he_mu */ + static const struct ieee80211_radiotap_he known = { + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | + HE_BITS(DATA1_DATA_DCM_KNOWN) | + HE_BITS(DATA1_STBC_KNOWN) | + HE_BITS(DATA1_CODING_KNOWN), + .data2 = HE_BITS(DATA2_GI_KNOWN) | + HE_BITS(DATA2_TXBF_KNOWN), + }; + struct ieee80211_radiotap_he *he = NULL; + __le32 v2 = rxv->v[2]; + __le32 v11 = rxv->v[11]; + __le32 v14 = rxv->v[14]; + u32 ltf_size = le32_get_bits(v2, MT_CRXV_HE_LTF_SIZE) + 1; + + he = skb_push(skb, sizeof(known)); + memcpy(he, &known, sizeof(known)); + + he->data1 = HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN); + he->data2 = HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN); + + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) | + le16_encode_bits(ltf_size, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, v14) | + HE_PREP(DATA6_DOPPLER, DOPPLER, v14); + + switch (rxv->phy) { + case MT_PHY_TYPE_HE_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN); + + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, v14) | + HE_PREP(DATA3_UL_DL, UPLINK, v2); + he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, v11); + break; + case MT_PHY_TYPE_HE_EXT_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, v2); + break; + case MT_PHY_TYPE_HE_MU: + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, v2); + he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, v11); + + mt7915_mac_decode_he_radiotap_ru(status, rxv, he); + break; + case MT_PHY_TYPE_HE_TB: + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); + + he->data4 = HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); + + mt7915_mac_decode_he_radiotap_ru(status, rxv, he); + break; + default: + break; + } +} + int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -347,6 +483,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) return -EINVAL; break; case MT_PHY_TYPE_HE_MU: + status->flag |= RX_FLAG_RADIOTAP_HE_MU; /* fall through */ case MT_PHY_TYPE_HE_SU: case MT_PHY_TYPE_HE_EXT_SU: @@ -354,6 +491,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->nss = FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; status->encoding = RX_ENC_HE; + status->flag |= RX_FLAG_RADIOTAP_HE; i &= GENMASK(3, 0); if (gi <= NL80211_RATE_INFO_HE_GI_3_2) @@ -404,6 +542,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) mt76_insert_ccmp_hdr(skb, key_id); } + if (status->flag & RX_FLAG_RADIOTAP_HE) + mt7915_mac_decode_he_radiotap(skb, status, &rxv); + hdr = mt76_skb_get_hdr(skb); if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 712753484aee..b9bc8b25b031 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -101,6 +101,8 @@ enum rx_pkt_type { #define MT_PRXV_TX_ER_SU_106T BIT(5) #define MT_PRXV_NSTS GENMASK(9, 7) #define MT_PRXV_HT_AD_CODE BIT(11) +#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28) +#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) #define MT_PRXV_RCPI3 GENMASK(31, 24) #define MT_PRXV_RCPI2 GENMASK(23, 16) #define MT_PRXV_RCPI1 GENMASK(15, 8) @@ -111,6 +113,20 @@ enum rx_pkt_type { #define MT_CRXV_TX_MODE GENMASK(7, 4) #define MT_CRXV_FRAME_MODE GENMASK(10, 8) #define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) +#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) +#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) +#define MT_CRXV_HE_PE_DISAMBIG BIT(23) +#define MT_CRXV_HE_UPLINK BIT(31) + +#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) +#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) +#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) +#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) + +#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0) +#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6) +#define MT_CRXV_HE_BEAM_CHNG BIT(13) +#define MT_CRXV_HE_DOPPLER BIT(16) struct mt7915_rxv { u32 phy;