Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp1889785pxb; Wed, 20 Oct 2021 13:58:42 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwRiipIVWRMylle95ZCGCSG97JiJBn92EDKmWQElzqdbcRT5iGARTRjg61gQlIF7CBb1Dmh X-Received: by 2002:a05:6402:1d49:: with SMTP id dz9mr1792832edb.17.1634763522089; Wed, 20 Oct 2021 13:58:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634763522; cv=none; d=google.com; s=arc-20160816; b=PZbT42/K+Cn9EMX2iGIzlYC1LZPXuq8vq+PDyy1wc5eJEAoZpMZFoWofCxC/vCZchZ cMJuDFBS+TgF9qswSZl3RRsyeinffrn8vODVIaqHEOuy7O+S9szK1jkFWTv3hggRXKLo T+XiyWmzAJzeru2isuNwFk4OKyXvJDJR8dJ+NodXSjxFcqISyOPEceN6MiMrU+vbBqk/ DFj1fMwYTvBvq0T9WIrIyVoLGuuS5fJ4ohUfYclIa5HMbEZga4boNg1389pIO1ktmq6l 2a05Kmog/q2czL2jxhjyF2MbGkiX0ddOxkwOzsorRizED07Ww/25YhgrPRL/A2k4wPYB Mr0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from; bh=SuNqzWn/p575yFT/6p1K83qMmMWYWPHg/vJAaZCfv8M=; b=KXq7hzvYfdYkkJvLBb7OUSYQFhhCAtkBAHmMPm6+5VeqBZJY9w4SLo076UxBaBNTM/ iCG0aIpYloenBFLEodMINqPFkbW7ZkiujtYN3ZU7HX/jGv6PuaC5LGHmHzgrP8k0IoWF TRDLQgBHidA5PIFVOPztM7mEz99zvmLQzK2m0JXUbm0bWKLk3ElNxMYqZx5F1VvOs+Sz SLu2A3u1aiC3/eOXnW7hrsFTAP0JAU+ZjfcOhgfgz36w8SueClyfki5ibRCez695aMW9 tqryZsYMMmCG0i/rKYEOPYTVrnsHZn9VGAOodvk+Mkm7WWZP2s4W8ZNNgmUG4bRa7UQj G3Pw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-wireless-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-wireless-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s18si4721654ejx.160.2021.10.20.13.58.26; Wed, 20 Oct 2021 13:58:42 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-wireless-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-wireless-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-wireless-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230385AbhJTVAT (ORCPT + 63 others); Wed, 20 Oct 2021 17:00:19 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:39802 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230049AbhJTVAS (ORCPT ); Wed, 20 Oct 2021 17:00:18 -0400 X-UUID: 874e1a32c97b4583a9a165ad39bdafa8-20211021 X-UUID: 874e1a32c97b4583a9a165ad39bdafa8-20211021 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 2043572360; Thu, 21 Oct 2021 04:58:00 +0800 Received: from mtkexhb02.mediatek.inc (172.21.101.103) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 21 Oct 2021 04:57:59 +0800 Received: from mtkcas11.mediatek.inc (172.21.101.40) by mtkexhb02.mediatek.inc (172.21.101.103) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 21 Oct 2021 04:57:59 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 21 Oct 2021 04:57:58 +0800 From: Ryder Lee To: Felix Fietkau CC: Lorenzo Bianconi , Shayne Chen , Evelyn Tsai , , , "Ryder Lee" Subject: [PATCH v4 2/3] mt76: mt7915: rework .set_bitrate_mask() to support more options Date: Thu, 21 Oct 2021 04:57:55 +0800 Message-ID: <5e83e2ba5e00e32529de76bba7831093e900a7db.1634755281.git.ryder.lee@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <142086982cd0a7d701e1b6d8891865113d019349.1634755281.git.ryder.lee@mediatek.com> References: <142086982cd0a7d701e1b6d8891865113d019349.1634755281.git.ryder.lee@mediatek.com> MIME-Version: 1.0 Content-Type: text/plain X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org With this patch, driver can support single rate, (HE)GI and HE_LTF configuration through .set_bitrate_mask(). Tested-by: MeiChia Chiu Signed-off-by: Ryder Lee --- v4: rebase v3: fix a macro naming error v2: fix an enum warning --- .../net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/main.c | 32 ++-- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 147 +++++++++++++++++- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 16 +- .../wireless/mediatek/mt76/mt7915/mt7915.h | 5 + 5 files changed, 175 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 6fc12e45a012..5fcf35f2d9fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -89,7 +89,7 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask) 0, 5000); } -static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw) +u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw) { mt76_wr(dev, MT_WTBLON_TOP_WDUCR, FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index ca44f68c5434..057ab27b7083 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -172,6 +172,9 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) int i; for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { + mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; + mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0); + mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0); mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0), sizeof(mvif->bitrate_mask.control[i].ht_mcs)); @@ -994,7 +997,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) { struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_dev *dev = msta->vif->phy->dev; - struct ieee80211_hw *hw = msta->vif->phy->mt76->hw; u32 *changed = data; spin_lock_bh(&dev->sta_poll_lock); @@ -1002,8 +1004,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) if (list_empty(&msta->rc_list)) list_add_tail(&msta->rc_list, &dev->sta_rc_list); spin_unlock_bh(&dev->sta_poll_lock); - - ieee80211_queue_work(hw, &dev->rc_work); } static void mt7915_sta_rc_update(struct ieee80211_hw *hw, @@ -1011,7 +1011,11 @@ static void mt7915_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 changed) { + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = phy->dev; + mt7915_sta_rc_work(&changed, sta); + ieee80211_queue_work(hw, &dev->rc_work); } static int @@ -1019,22 +1023,22 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - enum nl80211_band band = mvif->phy->mt76->chandef.chan->band; - u32 changed; - - if (mask->control[band].gi == NL80211_TXRATE_FORCE_LGI) - return -EINVAL; + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = phy->dev; + u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; - changed = IEEE80211_RC_SUPP_RATES_CHANGED; mvif->bitrate_mask = *mask; - /* Update firmware rate control to add a boundary on top of table - * to limit the rate selection for each peer, so when set bitrates - * vht-mcs-5 1:9, which actually means nss = 1 mcs = 0~9. This only - * applies to data frames as for the other mgmt, mcast, bcast still - * use legacy rates as it is. + /* if multiple rates across different preambles are given we can + * reconfigure this info with all peers using sta_rec command with + * the below exception cases. + * - single rate : if a rate is passed along with different preambles, + * we select the highest one as fixed rate. i.e VHT MCS for VHT peers. + * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT + * then multiple MCS setting (MCS 4,5,6) is not supported. */ ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed); + ieee80211_queue_work(hw, &dev->rc_work); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 27b741e38920..aa7964788a1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2050,6 +2050,128 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2); } +int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *data, u32 field) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct sta_phy *phy = data; + struct sta_rec_ra_fixed *ra; + struct sk_buff *skb; + struct tlv *tlv; + int len = sizeof(struct sta_req_hdr) + sizeof(*ra); + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); + ra = (struct sta_rec_ra_fixed *)tlv; + + switch (field) { + case RATE_PARAM_AUTO: + break; + case RATE_PARAM_FIXED_MCS: + case RATE_PARAM_FIXED_GI: + case RATE_PARAM_FIXED_HE_LTF: + ra->phy = *phy; + break; + default: + break; + } + ra->field = cpu_to_le32(field); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(STA_REC_UPDATE), true); +} + +static int +mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; + struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask; + enum nl80211_band band = chandef->chan->band; + struct sta_phy phy = {}; + int ret, nrates = 0; + +#define __sta_phy_bitrate_mask_check(_mcs, _gi, _he) \ + do { \ + u8 i, gi = mask->control[band]._gi; \ + gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \ + for (i = 0; i <= sta->bandwidth; i++) { \ + phy.sgi |= gi << (i << (_he)); \ + phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\ + } \ + for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) \ + nrates += hweight16(mask->control[band]._mcs[i]); \ + phy.mcs = ffs(mask->control[band]._mcs[0]) - 1; \ + } while (0) + + if (sta->he_cap.has_he) { + __sta_phy_bitrate_mask_check(he_mcs, he_gi, 1); + } else if (sta->vht_cap.vht_supported) { + __sta_phy_bitrate_mask_check(vht_mcs, gi, 0); + } else if (sta->ht_cap.ht_supported) { + __sta_phy_bitrate_mask_check(ht_mcs, gi, 0); + } else { + nrates = hweight32(mask->control[band].legacy); + phy.mcs = ffs(mask->control[band].legacy) - 1; + } +#undef __sta_phy_bitrate_mask_check + + /* fall back to auto rate control */ + if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI && + mask->control[band].he_gi == GENMASK(7, 0) && + mask->control[band].he_ltf == GENMASK(7, 0) && + nrates != 1) + return 0; + + /* fixed single rate */ + if (nrates == 1) { + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + RATE_PARAM_FIXED_MCS); + if (ret) + return ret; + } + + /* fixed GI */ + if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI || + mask->control[band].he_gi != GENMASK(7, 0)) { + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + u32 addr; + + /* firmware updates only TXCMD but doesn't take WTBL into + * account, so driver should update here to reflect the + * actual txrate hardware sends out. + */ + addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7); + if (sta->he_cap.has_he) + mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi); + else + mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); + + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + RATE_PARAM_FIXED_GI); + if (ret) + return ret; + } + + /* fixed HE_LTF */ + if (mask->control[band].he_ltf != GENMASK(7, 0)) { + ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, + RATE_PARAM_FIXED_HE_LTF); + if (ret) + return ret; + } + + return 0; +} + static void mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -2092,8 +2214,6 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, } if (sta->ht_cap.ht_supported) { - const u8 *mcs_mask = mask->control[band].ht_mcs; - ra->supp_mode |= MODE_HT; ra->af = sta->ht_cap.ampdu_factor; ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); @@ -2111,12 +2231,12 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; - mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, mcs_mask); + mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, + mask->control[band].ht_mcs); ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; } if (sta->vht_cap.vht_supported) { - const u16 *mcs_mask = mask->control[band].vht_mcs; u8 af; ra->supp_mode |= MODE_VHT; @@ -2137,7 +2257,8 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; - mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mcs_mask); + mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, + mask->control[band].vht_mcs); } if (sta->he_cap.has_he) { @@ -2154,6 +2275,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct sk_buff *skb; + int ret; skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, MT7915_STA_UPDATE_MAX_SIZE); @@ -2167,10 +2289,21 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, if (sta->he_cap.has_he && changed) mt7915_mcu_sta_he_tlv(skb, sta, vif); + /* sta_rec_ra accommodates BW, NSS and only MCS range format + * i.e 0-{7,8,9} for VHT. + */ mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(STA_REC_UPDATE), true); + if (ret) + return ret; + + /* sta_rec_ra_fixed accommodates single rate, (HE)GI and HE_LTE, + * and updates as peer fixed rate parameters, which overrides + * sta_rec_ra and firmware rate control algorithm. + */ + return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta); } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index d66918d914da..4821adb793d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -886,7 +886,7 @@ struct sta_rec_sec { struct sec_key key[2]; } __packed; -struct ra_phy { +struct sta_phy { u8 type; u8 flag; u8 stbc; @@ -930,7 +930,7 @@ struct sta_rec_ra { __le32 sta_cap; - struct ra_phy phy; + struct sta_phy phy; } __packed; struct sta_rec_ra_fixed { @@ -943,7 +943,7 @@ struct sta_rec_ra_fixed { u8 op_vht_rx_nss; u8 op_vht_rx_nss_type; - struct ra_phy phy; + struct sta_phy phy; u8 spe_en; u8 short_preamble; @@ -951,8 +951,14 @@ struct sta_rec_ra_fixed { u8 mmps_mode; } __packed; -#define RATE_PARAM_FIXED 3 -#define RATE_PARAM_AUTO 20 +enum { + RATE_PARAM_FIXED = 3, + RATE_PARAM_FIXED_HE_LTF = 7, + RATE_PARAM_FIXED_MCS, + RATE_PARAM_FIXED_GI = 11, + RATE_PARAM_AUTO = 20, +}; + #define RATE_CFG_MCS GENMASK(3, 0) #define RATE_CFG_NSS GENMASK(7, 4) #define RATE_CFG_GI GENMASK(11, 8) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 79a33afc5920..7a328fc774a7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -418,6 +418,10 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif); int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req); int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, struct ieee80211_sta *sta, u32 rate); +int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *data, u32 field); int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, @@ -478,6 +482,7 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask) mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } +u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw); bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask); void mt7915_mac_reset_counters(struct mt7915_phy *phy); void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); -- 2.29.2