From e809904f9bd2db92c1c7e403aa77ab49b8a9b266 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 28 Feb 2022 20:39:28 +0100 Subject: mt76: mt7615: honor ret from mt7615_mcu_restart in mt7663u_mcu_init Check return value of mt7615_mcu_restart routine in mt7663u_mcu_init(). Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index 0ebb4c3c336a..b560d0db6a92 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -57,7 +57,10 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) { - mt7615_mcu_restart(&dev->mt76); + ret = mt7615_mcu_restart(&dev->mt76); + if (ret) + return ret; + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, 0, 500)) return -EIO; -- cgit v1.2.3 From 4dd4ad44b7da1008616c79dd2c925be71021c315 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 28 Feb 2022 20:43:23 +0100 Subject: mt76: mt7663u: introduce mt7663u_mcu_power_on routine Introduce mt7663u_mcu_power_on utility routine since the code is shared between mt7663u_mcu_init() and mt7663u_probe(). Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 + drivers/net/wireless/mediatek/mt76/mt7615/usb.c | 22 ++++----------- .../net/wireless/mediatek/mt76/mt7615/usb_mcu.c | 31 +++++++++++++++------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 600fa2be4da0..2e91f6a27d0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -559,6 +559,7 @@ void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); int mt7663_usb_sdio_register_device(struct mt7615_dev *dev); int mt7663u_mcu_init(struct mt7615_dev *dev); +int mt7663u_mcu_power_on(struct mt7615_dev *dev); /* sdio */ int mt7663s_mcu_init(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index 5cad398abf63..aeeba7c72f14 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -100,27 +100,15 @@ static int mt7663u_probe(struct usb_interface *usb_intf, (mt76_rr(dev, MT_HW_REV) & 0xff); dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - if (mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, - FW_STATE_PWR_ON << 1, 500)) { - dev_dbg(dev->mt76.dev, "Usb device already powered on\n"); - set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state); - goto alloc_queues; - } - - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); - if (ret) - goto error; - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, FW_STATE_PWR_ON << 1, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - ret = -EIO; - goto error; + ret = mt7663u_mcu_power_on(dev); + if (ret) + goto error; + } else { + set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state); } -alloc_queues: ret = mt76u_alloc_mcu_queue(&dev->mt76); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index b560d0db6a92..98bf2f6ae936 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -42,6 +42,26 @@ out: return ret; } +int mt7663u_mcu_power_on(struct mt7615_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, + MT_TOP_MISC2_FW_PWR_ON, + FW_STATE_PWR_ON << 1, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return 0; +} + int mt7663u_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7663u_mcu_ops = { @@ -65,18 +85,9 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) MT_TOP_MISC2_FW_PWR_ON, 0, 500)) return -EIO; - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); + ret = mt7663u_mcu_power_on(dev); if (ret) return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, - MT_TOP_MISC2_FW_PWR_ON, - FW_STATE_PWR_ON << 1, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - return -EIO; - } } ret = __mt7663_load_firmware(dev); -- cgit v1.2.3 From cbaa0a404f8dd528a668450753c789cb9e178c13 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 1 Mar 2022 09:17:51 +0800 Subject: mt76: mt7921: fix up the monitor mode Properly set up the monitor mode the firmware can support to fix up RTS/CTS and beacon frames cannot be captured and forwarded to the host. Tested-by: Deren Wu Tested-by: Sven Eckelmann Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 24 +++++++++-------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 30 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 ++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 384c3eab1c8a..e5857d2cf78c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -993,6 +993,7 @@ enum { MCU_UNI_CMD_SUSPEND = 0x05, MCU_UNI_CMD_OFFLOAD = 0x06, MCU_UNI_CMD_HIF_CTRL = 0x07, + MCU_UNI_CMD_SNIFFER = 0x24, }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index b6e836a4fad7..ce4c38b436ec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -479,6 +479,16 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable); } +static void +mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt7921_dev *dev = priv; + struct ieee80211_hw *hw = mt76_hw(dev); + bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + mt7921_mcu_set_sniffer(dev, vif, enabled); +} + void mt7921_set_runtime_pm(struct mt7921_dev *dev) { struct ieee80211_hw *hw = dev->mphy.hw; @@ -516,16 +526,10 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); - - if (!enabled) - phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; - else - phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - - mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN, - enabled); - mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_sniffer_interface_iter, dev); + dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0)); mt7921_set_runtime_pm(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index e7adcba7a8bf..5ef8b24f0ab3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1135,3 +1135,33 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) return 0; } + +int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct { + struct { + u8 band_idx; + u8 pad[3]; + } __packed hdr; + struct sniffer_enable_tlv { + __le16 tag; + __le16 len; + u8 enable; + u8 pad[3]; + } __packed enable; + } req = { + .hdr = { + .band_idx = mvif->band_idx, + }, + .enable = { + .tag = cpu_to_le16(0), + .len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)), + .enable = enable, + }, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), + true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 9edc83f06139..9575d571b425 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -452,4 +452,6 @@ void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); void mt7921_set_runtime_pm(struct mt7921_dev *dev); +int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool enable); #endif -- cgit v1.2.3 From 07241519b35794a66fcc429042240424ddf35f3d Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 1 Mar 2022 09:17:52 +0800 Subject: mt76: mt7921: use mt76_hw instead of open coding it use mt76_hw instead of open coding it Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index ce4c38b436ec..e5dcf1615f17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -491,7 +491,7 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) void mt7921_set_runtime_pm(struct mt7921_dev *dev) { - struct ieee80211_hw *hw = dev->mphy.hw; + struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); -- cgit v1.2.3 From 233e39d1ed2c1ad26a24447cb60745ce586e7753 Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Tue, 1 Mar 2022 13:29:10 +0800 Subject: mt76: mt7915: fix DFS no radar detection event Driver needs to carry region definition when radar detection starts. Need to remap nl80211 DFS regions to chip region definition. Signed-off-by: Evelyn Tsai Signed-off-by: Rubio Lu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 1da551f0b389..a99079313ac2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -2364,10 +2364,23 @@ static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy) static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) { - int err; + int err, region; + + switch (dev->mt76.region) { + case NL80211_DFS_ETSI: + region = 0; + break; + case NL80211_DFS_JP: + region = 2; + break; + case NL80211_DFS_FCC: + default: + region = 1; + break; + } err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain, - MT_RX_SEL0, 0); + MT_RX_SEL0, region); if (err < 0) return err; -- cgit v1.2.3 From 499da7200f35a3bf531640c8b27af5aff840f0e0 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Wed, 2 Mar 2022 14:14:06 +0800 Subject: mt76: split single ldpc cap bit into bits The original single LDPC cap bit cannot be used to differentiate LDPC cap in each PHY mode. This modification split the single bit into 3 bits, ht_ldpc, vht_ldpc, and he_ldpc. Reviewed-by: Ryder Lee Suggested-by: Money Wang Signed-off-by: MeiChia Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 9 +++++---- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 20 ++++++++++++-------- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 4 +++- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index e98c6076a633..390add3144c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -880,7 +880,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, NULL, wtbl_hdr); if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta, - NULL, wtbl_hdr, true); + NULL, wtbl_hdr, true, true); mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid, NULL, wtbl_hdr); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 0a646ae51c8d..6c762fbf9aaa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -899,7 +899,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_smps_tlv); void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv, bool ldpc) + void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc) { struct wtbl_ht *ht = NULL; struct tlv *tlv; @@ -909,7 +909,7 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), wtbl_tlv, sta_wtbl); ht = (struct wtbl_ht *)tlv; - ht->ldpc = ldpc && + ht->ldpc = ht_ldpc && !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); ht->af = sta->ht_cap.ampdu_factor; ht->mm = sta->ht_cap.ampdu_density; @@ -924,7 +924,7 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, sizeof(*vht), wtbl_tlv, sta_wtbl); vht = (struct wtbl_vht *)tlv; - vht->ldpc = ldpc && + vht->ldpc = vht_ldpc && !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); vht->vht = true; @@ -1004,7 +1004,8 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy, sta_wtbl, wtbl_hdr); if (info->sta) mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, - sta_wtbl, wtbl_hdr, true); + sta_wtbl, wtbl_hdr, + true, true); } return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index e5857d2cf78c..c3c93338d56a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1562,7 +1562,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, u8 rcpi, u8 state); void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv, bool ldpc); + void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc); void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_ampdu_params *params, bool enable, bool tx, void *sta_wtbl, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 119f9358162f..cc7d8e7e8d8a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -821,8 +821,9 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G)) cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT; - if (mvif->cap.ldpc && (elem->phy_cap_info[1] & - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) + if (mvif->cap.he_ldpc && + (elem->phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) cap |= STA_REC_HE_CAP_LDPC; if (elem->phy_cap_info[1] & @@ -1073,7 +1074,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb, mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr); if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv, - wtbl_hdr, mvif->cap.ldpc); + wtbl_hdr, mvif->cap.ht_ldpc, + mvif->cap.vht_ldpc); return 0; } @@ -1582,7 +1584,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_TX_STBC; if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (mvif->cap.ldpc && + if (mvif->cap.ht_ldpc && (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; @@ -1608,7 +1610,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_VHT_TX_STBC; if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (mvif->cap.ldpc && + if (mvif->cap.vht_ldpc && (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; @@ -1872,8 +1874,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, len); if (ie && ie[1] >= sizeof(*ht)) { ht = (void *)(ie + 2); - vc->ldpc |= !!(le16_to_cpu(ht->cap_info) & - IEEE80211_HT_CAP_LDPC_CODING); + vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) & + IEEE80211_HT_CAP_LDPC_CODING); } ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable, @@ -1884,7 +1886,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, vht = (void *)(ie + 2); bc = le32_to_cpu(vht->vht_cap_info); - vc->ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC); + vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC); vc->vht_su_ebfer = (bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) && (pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); @@ -1908,6 +1910,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, he = (void *)(ie + 3); + vc->he_ldpc = + HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]); vc->he_su_ebfer = HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 52b848dd4b66..2fe737f2f844 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -138,7 +138,9 @@ struct mt7915_sta { }; struct mt7915_vif_cap { - bool ldpc:1; + bool ht_ldpc:1; + bool vht_ldpc:1; + bool he_ldpc:1; bool vht_su_ebfer:1; bool vht_su_ebfee:1; bool vht_mu_ebfer:1; -- cgit v1.2.3 From 11a72265928f679c3ffabd15c97b3ef8e910e205 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 2 Mar 2022 16:32:57 +0100 Subject: mt76: mt7921: make mt7921_init_tx_queues static mt7921 is only used in mt7921_dma_init routine. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 39d6ce4ecddd..ca7e20fb5fc0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -5,7 +5,7 @@ #include "../dma.h" #include "mac.h" -int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc) +static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc) { int i, err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 9575d571b425..ca24036e50b9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -384,7 +384,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, void mt7921_tx_worker(struct mt76_worker *w); void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); -int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc); void mt7921_tx_token_put(struct mt7921_dev *dev); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); -- cgit v1.2.3 From e907341dab1bf4eb3c6cbdf79d125b2eee51058c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 2 Mar 2022 16:46:06 +0100 Subject: mt76: mt7921: fix xmit-queue dump for usb and sdio Use proper xmit queue handler to dump queue stats. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index dd04909d980a..1bb388ecc334 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -429,8 +429,13 @@ int mt7921_init_debugfs(struct mt7921_dev *dev) if (!dir) return -ENOMEM; - debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, - mt7921_queues_read); + if (mt76_is_mmio(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt7921_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt76_queues_read); + debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7921_queues_acq); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, -- cgit v1.2.3 From 849ee6ac9dd3efd0a57cbc98b9a9d6ae87374aff Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 3 Mar 2022 09:46:41 +0100 Subject: mt76: mt7921: fix mt7921_queues_acq implementation Fix mt7921_queues_acq implementation according to the vendor sdk. Fixes: 474a9f21e2e20 ("mt76: mt7921: add debugfs support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 13 ++++++------- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 11 +++++------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 1bb388ecc334..32004b55a360 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -129,23 +129,22 @@ mt7921_queues_acq(struct seq_file *s, void *data) mt7921_mutex_acquire(dev); - for (i = 0; i < 16; i++) { - int j, acs = i / 4, index = i % 4; + for (i = 0; i < 4; i++) { u32 ctrl, val, qlen = 0; + int j; - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); - ctrl = BIT(31) | BIT(15) | (acs << 8); + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); + ctrl = BIT(31) | BIT(11) | (i << 24); for (j = 0; j < 32; j++) { if (val & BIT(j)) continue; - mt76_wr(dev, MT_PLE_FL_Q0_CTRL, - ctrl | (j + (index << 5))); + mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, GENMASK(11, 0)); } - seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); + seq_printf(s, "AC%d: queued=%d\n", i, qlen); } mt7921_mutex_release(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 411695f273cd..33578e0dfde3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -17,13 +17,12 @@ #define MT_PLE_BASE 0x820c0000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) -#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0) -#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4) -#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8) -#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc) +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) +#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) +#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) +#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) -#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \ - ((n) << 2)) +#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) #define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) #define MT_MDP_BASE 0x820cd000 -- cgit v1.2.3 From 123bc712b1de0805f9d683687e17b1ec2aba0b68 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Fri, 4 Mar 2022 22:54:05 +0800 Subject: mt76: fix monitor mode crash with sdio driver mt7921s driver may receive frames with fragment buffers. If there is a CTS packet received in monitor mode, the payload is 10 bytes only and need 6 bytes header padding after RXD buffer. However, only RXD in the first linear buffer, if we pull buffer size RXD-size+6 bytes with skb_pull(), that would trigger "BUG_ON(skb->len < skb->data_len)" in __skb_pull(). To avoid the nonlinear buffer issue, enlarge the RXD size from 128 to 256 to make sure all MCU operation in linear buffer. [ 52.007562] kernel BUG at include/linux/skbuff.h:2313! [ 52.007578] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 52.007987] pc : skb_pull+0x48/0x4c [ 52.008015] lr : mt7921_queue_rx_skb+0x494/0x890 [mt7921_common] [ 52.008361] Call trace: [ 52.008377] skb_pull+0x48/0x4c [ 52.008400] mt76s_net_worker+0x134/0x1b0 [mt76_sdio 35339a92c6eb7d4bbcc806a1d22f56365565135c] [ 52.008431] __mt76_worker_fn+0xe8/0x170 [mt76 ef716597d11a77150bc07e3fdd68eeb0f9b56917] [ 52.008449] kthread+0x148/0x3ac [ 52.008466] ret_from_fork+0x10/0x30 Signed-off-by: Lorenzo Bianconi Signed-off-by: Sean Wang Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5e10fe156926..81078be3bd07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -19,7 +19,7 @@ #define MT_MCU_RING_SIZE 32 #define MT_RX_BUF_SIZE 2048 -#define MT_SKB_HEAD_LEN 128 +#define MT_SKB_HEAD_LEN 256 #define MT_MAX_NON_AQL_PKT 16 #define MT_TXQ_FREE_THR 32 -- cgit v1.2.3 From 3f71ff0868e616b11a24cd0428f3d1df5d0acffc Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 5 Mar 2022 07:42:24 +0800 Subject: mt76: mt7915: allow beaconing on all chains This improves rate reach performance on units with polarized antennas. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index a99079313ac2..34742f244797 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1101,6 +1101,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi, if (ieee80211_is_beacon(fc)) { txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); + txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, 0x18)); } if (info->flags & IEEE80211_TX_CTL_INJECTED) { -- cgit v1.2.3 From 37b5e57b0c76e26e4bec0dd4f8b40cfb29c36838 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Mon, 7 Mar 2022 15:10:25 +0800 Subject: mt76: connac: add 6 GHz support for wtbl and starec configuration Since there are no HT & VHT IEs being sent in 6ghz, some capabilities judgement and parsing for wtbl & starec configuration should be modified to reflect such changes. Reviewed-by: Ryder Lee Signed-off-by: Money Wang Signed-off-by: MeiChia Chiu Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 6c762fbf9aaa..5e65fa3f3cba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -905,18 +905,27 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct tlv *tlv; u32 flags = 0; - if (sta->ht_cap.ht_supported) { + if (sta->ht_cap.ht_supported || sta->he_6ghz_capa.capa) { tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), wtbl_tlv, sta_wtbl); ht = (struct wtbl_ht *)tlv; ht->ldpc = ht_ldpc && !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); - ht->af = sta->ht_cap.ampdu_factor; - ht->mm = sta->ht_cap.ampdu_density; + + if (sta->ht_cap.ht_supported) { + ht->af = sta->ht_cap.ampdu_factor; + ht->mm = sta->ht_cap.ampdu_density; + } else { + ht->af = le16_get_bits(sta->he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); + ht->mm = le16_get_bits(sta->he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); + } + ht->ht = true; } - if (sta->vht_cap.vht_supported) { + if (sta->vht_cap.vht_supported || sta->he_6ghz_capa.capa) { struct wtbl_vht *vht; u8 af; @@ -1242,7 +1251,7 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, if (he_cap && he_cap->has_he) mode |= PHY_MODE_AX_24G; - } else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) { + } else if (band == NL80211_BAND_5GHZ) { mode |= PHY_MODE_A; if (ht_cap->ht_supported) @@ -1251,8 +1260,11 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, if (vht_cap->vht_supported) mode |= PHY_MODE_AC; - if (he_cap && he_cap->has_he && band == NL80211_BAND_5GHZ) + if (he_cap && he_cap->has_he) mode |= PHY_MODE_AX_5G; + } else if (band == NL80211_BAND_6GHZ) { + mode |= PHY_MODE_A | PHY_MODE_AN | + PHY_MODE_AC | PHY_MODE_AX_5G; } return mode; -- cgit v1.2.3 From b4d093e321bd158af2a94d84e5d5b99023100d92 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Mon, 7 Mar 2022 15:10:26 +0800 Subject: mt76: mt7915: add 6 GHz support Basic 6 GHz support is added to mt76. Modification includes: 1. Add 6 GHz E2P definition 2. Register 6 GHz HE cap 3. Refactor existing code of adding a STA This adds support for Wi-Fi 6E on MT7986/MT7916. Detailed link: https://www.mediatek.com/products/mediatek-filogic-830 Detailed link: https://www.mediatek.com/products/products/broadband-wifi/mediatek-filogic-630 Reviewed-by: Ryder Lee Signed-off-by: Shayne Chen Signed-off-by: Peter Chiu Signed-off-by: Money Wang Signed-off-by: MeiChia Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 21 +++++++++++++--- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h | 7 ++++++ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 28 ++++++++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 12 ++++++---- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 28 ++++++++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2 +- .../net/wireless/mediatek/mt76/mt7915/testmode.c | 4 ++++ 7 files changed, 88 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 0fa539479aa7..136a6adab3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -135,9 +135,24 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) val = eeprom[MT_EE_WIFI_CONF + phy->band_idx]; val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); - if (val == MT_EE_BAND_SEL_DEFAULT && - (!is_mt7915(&dev->mt76) || dev->dbdc_support)) - val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; + + if (!is_mt7915(&dev->mt76)) { + switch (val) { + case MT_EE_V2_BAND_SEL_5GHZ: + phy->mt76->cap.has_5ghz = true; + return; + case MT_EE_V2_BAND_SEL_6GHZ: + phy->mt76->cap.has_6ghz = true; + return; + case MT_EE_V2_BAND_SEL_5GHZ_6GHZ: + phy->mt76->cap.has_5ghz = true; + phy->mt76->cap.has_6ghz = true; + return; + default: + phy->mt76->cap.has_2ghz = true; + return; + } + } switch (val) { case MT_EE_BAND_SEL_5GHZ: diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 5ffc56bb5c51..5dad5b0b5ac6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -76,6 +76,13 @@ enum mt7915_eeprom_band { MT_EE_BAND_SEL_DUAL, }; +enum { + MT_EE_V2_BAND_SEL_2GHZ, + MT_EE_V2_BAND_SEL_5GHZ, + MT_EE_V2_BAND_SEL_6GHZ, + MT_EE_V2_BAND_SEL_5GHZ_6GHZ, +}; + enum mt7915_sku_rate_group { SKU_CCK, SKU_OFDM, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index fd16d777f2e4..9a696687d61c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -872,7 +872,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, if (band == NL80211_BAND_2GHZ) he_cap_elem->phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; - else if (band == NL80211_BAND_5GHZ) + else he_cap_elem->phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | @@ -911,7 +911,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, if (band == NL80211_BAND_2GHZ) he_cap_elem->phy_cap_info[0] |= IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; - else if (band == NL80211_BAND_5GHZ) + else he_cap_elem->phy_cap_info[0] |= IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; @@ -961,6 +961,21 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); } + + if (band == NL80211_BAND_6GHZ) { + u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | + IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; + + cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_8, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | + u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | + u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); + + data[idx].he_6ghz_capa.capa = cpu_to_le16(cap); + } + idx++; } @@ -990,6 +1005,15 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) band->iftype_data = data; band->n_iftype_data = n; } + + if (phy->mt76->cap.has_6ghz) { + data = phy->iftype[NL80211_BAND_6GHZ]; + n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data); + + band = &phy->mt76->sband_6g.sband; + band->iftype_data = data; + band->n_iftype_data = n; + } } static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 34742f244797..b02451c775c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -638,6 +638,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->band = mphy->chandef.chan->band; if (status->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (status->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; @@ -1351,7 +1353,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) u16 fc, tid; u32 val; - if (!sta || !sta->ht_cap.ht_supported) + if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he)) return; tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1])); @@ -1559,6 +1561,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; @@ -1804,7 +1808,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); int offset; - bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ; + bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; @@ -1824,7 +1828,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset); mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset); mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx), - FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) | + FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | FIELD_PREP(MT_IFS_RIFS, 2) | FIELD_PREP(MT_IFS_SIFS, 10) | FIELD_PREP(MT_IFS_SLOT, phy->slottime)); @@ -1832,7 +1836,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx), FIELD_PREP(MT_IFS_EIFS_CCK, 314)); - if (phy->slottime < 20 || is_5ghz) + if (phy->slottime < 20 || a_band) val = MT7915_CFEND_RATE_DEFAULT; else val = MT7915_CFEND_RATE_11B; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index cc7d8e7e8d8a..10dc4bf5adec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -987,6 +987,9 @@ mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) struct sta_rec_ht *ht; struct tlv *tlv; + if (!sta->ht_cap.ht_supported) + return; + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; @@ -1267,6 +1270,9 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, }; bool ebf; + if (!(sta->ht_cap.ht_supported || sta->he_cap.has_he)) + return; + ebf = mt7915_is_ebf_supported(phy, vif, sta, false); if (!ebf && !dev->ibf) return; @@ -1327,6 +1333,9 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct tlv *tlv; u8 nrow = 0; + if (!(sta->vht_cap.vht_supported || sta->he_cap.has_he)) + return; + if (!mt7915_is_ebf_supported(phy, vif, sta, true)) return; @@ -1621,6 +1630,10 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, if (sta->he_cap.has_he) { ra->supp_mode |= MODE_HE; cap |= STA_CAP_HE; + + if (sta->he_6ghz_capa.capa) + ra->af = le16_get_bits(sta->he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); } ra->sta_cap = cpu_to_le32(cap); @@ -1643,7 +1656,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, * once dev->rc_work changes the settings driver should also * update sta_rec_he here. */ - if (sta->he_cap.has_he && changed) + if (changed) mt7915_mcu_sta_he_tlv(skb, sta, vif); /* sta_rec_ra accommodates BW, NSS and only MCS range format @@ -1712,7 +1725,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, goto out; /* tag order is in accordance with firmware dependency. */ - if (sta && sta->ht_cap.ht_supported) { + if (sta) { /* starec bfer */ mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta); /* starec ht */ @@ -1729,7 +1742,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, return ret; } - if (sta && sta->ht_cap.ht_supported) { + if (sta) { /* starec amsdu */ mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta); /* starec he */ @@ -2772,6 +2785,11 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) { + static const u8 ch_band[] = { + [NL80211_BAND_2GHZ] = 0, + [NL80211_BAND_5GHZ] = 1, + [NL80211_BAND_6GHZ] = 2, + }; struct mt7915_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1; @@ -2799,7 +2817,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) .tx_streams_num = hweight8(phy->mt76->antenna_mask), .rx_streams = phy->mt76->antenna_mask, .band_idx = phy->band_idx, - .channel_band = chandef->chan->band, + .channel_band = ch_band[chandef->chan->band], }; #ifdef CONFIG_NL80211_TESTMODE @@ -3461,6 +3479,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, case MT_PHY_TYPE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 2fe737f2f844..6efa0a2e2345 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -227,7 +227,7 @@ struct mt7915_phy { struct mt76_phy *mt76; struct mt7915_dev *dev; - struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES]; + struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; struct ieee80211_vif *monitor_vif; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c index 6605e24c4593..20f63644e929 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -271,6 +271,8 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time) case MT76_TM_TX_MODE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; @@ -572,6 +574,8 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en) if (chandef->chan->band == NL80211_BAND_5GHZ) sband = &phy->mt76->sband_5g.sband; + else if (chandef->chan->band == NL80211_BAND_6GHZ) + sband = &phy->mt76->sband_6g.sband; else sband = &phy->mt76->sband_2g.sband; -- cgit v1.2.3 From 1c2d366ecb4108adcf28d36aa6266eaf5b310955 Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Mon, 7 Mar 2022 15:10:27 +0800 Subject: mt76: mt7915: fix eeprom fields of txpower init values A-die 7976 has different offset and uses different channel group definition on txpower init values. Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986") Signed-off-by: Shayne Chen Signed-off-by: MeiChia Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 52 +++++++++++----------- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h | 14 +++++- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 136a6adab3df..317c3bc2db44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -263,32 +263,38 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, { u8 *eeprom = dev->mt76.eeprom.data; int index, target_power; - bool tssi_on; + bool tssi_on, is_7976; if (chain_idx > 3) return -EINVAL; tssi_on = mt7915_tssi_enabled(dev, chan->band); + is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76); if (chan->band == NL80211_BAND_2GHZ) { - u32 power = is_mt7915(&dev->mt76) ? - MT_EE_TX0_POWER_2G : MT_EE_TX0_POWER_2G_V2; - - index = power + chain_idx * 3; - target_power = eeprom[index]; + if (is_7976) { + index = MT_EE_TX0_POWER_2G_V2 + chain_idx; + target_power = eeprom[index]; + } else { + index = MT_EE_TX0_POWER_2G + chain_idx * 3; + target_power = eeprom[index]; - if (!tssi_on) - target_power += eeprom[index + 1]; + if (!tssi_on) + target_power += eeprom[index + 1]; + } } else { - int group = mt7915_get_channel_group(chan->hw_value); - u32 power = is_mt7915(&dev->mt76) ? - MT_EE_TX0_POWER_5G : MT_EE_TX0_POWER_5G_V2; + int group = mt7915_get_channel_group(chan->hw_value, is_7976); - index = power + chain_idx * 12; - target_power = eeprom[index + group]; + if (is_7976) { + index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5; + target_power = eeprom[index + group]; + } else { + index = MT_EE_TX0_POWER_5G + chain_idx * 12; + target_power = eeprom[index + group]; - if (!tssi_on) - target_power += eeprom[index + 8]; + if (!tssi_on) + target_power += eeprom[index + 8]; + } } return target_power; @@ -297,20 +303,16 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band) { u8 *eeprom = dev->mt76.eeprom.data; - u32 val; + u32 val, offs; s8 delta; - u32 rate_2g, rate_5g; - - rate_2g = is_mt7915(&dev->mt76) ? - MT_EE_RATE_DELTA_2G : MT_EE_RATE_DELTA_2G_V2; - - rate_5g = is_mt7915(&dev->mt76) ? - MT_EE_RATE_DELTA_5G : MT_EE_RATE_DELTA_5G_V2; + bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76); if (band == NL80211_BAND_2GHZ) - val = eeprom[rate_2g]; + offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G; else - val = eeprom[rate_5g]; + offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G; + + val = eeprom[offs]; if (!(val & MT_EE_RATE_DELTA_EN)) return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 5dad5b0b5ac6..45760917c54d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -103,8 +103,20 @@ enum mt7915_sku_rate_group { }; static inline int -mt7915_get_channel_group(int channel) +mt7915_get_channel_group(int channel, bool is_7976) { + if (is_7976) { + if (channel <= 64) + return 0; + if (channel <= 96) + return 1; + if (channel <= 128) + return 2; + if (channel <= 144) + return 3; + return 4; + } + if (channel >= 184 && channel <= 196) return 0; if (channel <= 48) -- cgit v1.2.3 From ae146683001a5b5e3f4cd8c86ae27f9e4a7bb917 Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Mon, 7 Mar 2022 15:10:28 +0800 Subject: mt76: mt7915: add txpower init for 6GHz Add support to init txpower values of 6GHz band. Signed-off-by: Shayne Chen Signed-off-by: MeiChia Chiu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 15 +++++++++++---- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h | 13 ++++++++++++- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 ++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 317c3bc2db44..5b133bcdab17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -282,8 +282,8 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, if (!tssi_on) target_power += eeprom[index + 1]; } - } else { - int group = mt7915_get_channel_group(chan->hw_value, is_7976); + } else if (chan->band == NL80211_BAND_5GHZ) { + int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976); if (is_7976) { index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5; @@ -295,6 +295,11 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, if (!tssi_on) target_power += eeprom[index + 8]; } + } else { + int group = mt7915_get_channel_group_6g(chan->hw_value); + + index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8; + target_power = is_7976 ? eeprom[index + group] : 0; } return target_power; @@ -309,12 +314,14 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band) if (band == NL80211_BAND_2GHZ) offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G; - else + else if (band == NL80211_BAND_5GHZ) offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G; + else + offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0; val = eeprom[offs]; - if (!(val & MT_EE_RATE_DELTA_EN)) + if (!offs || !(val & MT_EE_RATE_DELTA_EN)) return 0; delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 45760917c54d..7578ac6d0be6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -25,8 +25,10 @@ enum mt7915_eeprom_field { MT_EE_TX0_POWER_5G = 0x34b, MT_EE_RATE_DELTA_2G_V2 = 0x7d3, MT_EE_RATE_DELTA_5G_V2 = 0x81e, + MT_EE_RATE_DELTA_6G_V2 = 0x884, /* 6g fields only appear in eeprom v2 */ MT_EE_TX0_POWER_2G_V2 = 0x441, MT_EE_TX0_POWER_5G_V2 = 0x445, + MT_EE_TX0_POWER_6G_V2 = 0x465, MT_EE_ADIE_FT_VERSION = 0x9a0, __MT_EE_MAX = 0xe00, @@ -103,7 +105,7 @@ enum mt7915_sku_rate_group { }; static inline int -mt7915_get_channel_group(int channel, bool is_7976) +mt7915_get_channel_group_5g(int channel, bool is_7976) { if (is_7976) { if (channel <= 64) @@ -134,6 +136,15 @@ mt7915_get_channel_group(int channel, bool is_7976) return 7; } +static inline int +mt7915_get_channel_group_6g(int channel) +{ + if (channel <= 29) + return 0; + + return DIV_ROUND_UP(channel - 29, 32); +} + static inline bool mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 9a696687d61c..668244e0d11e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -312,6 +312,7 @@ mt7915_regd_notifier(struct wiphy *wiphy, mt7915_init_txpower(dev, &mphy->sband_2g.sband); mt7915_init_txpower(dev, &mphy->sband_5g.sband); + mt7915_init_txpower(dev, &mphy->sband_6g.sband); mphy->dfs_state = MT_DFS_STATE_UNKNOWN; mt7915_dfs_init_radar_detector(phy); @@ -558,6 +559,7 @@ static void mt7915_init_work(struct work_struct *work) mt7915_mac_init(dev); mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband); + mt7915_init_txpower(dev, &dev->mphy.sband_6g.sband); mt7915_txbf_init(dev); } -- cgit v1.2.3 From 9a657684158f44d04845c770c1cfa57989fc2400 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 7 Mar 2022 12:35:21 +0100 Subject: mt76: mt7921: get rid of mt7921_wait_for_mcu_init declaration mt7921_wait_for_mcu_init is no longer used. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index ca24036e50b9..3952247659fa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -408,7 +408,6 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev); void mt7921_pm_wake_work(struct work_struct *work); void mt7921_pm_power_save_work(struct work_struct *work); -bool mt7921_wait_for_mcu_init(struct mt7921_dev *dev); void mt7921_coredump_work(struct work_struct *work); int mt7921_wfsys_reset(struct mt7921_dev *dev); int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr); -- cgit v1.2.3 From 01318bc00d16947715e8f65a629806e5953a36ff Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Mar 2022 17:13:49 +0300 Subject: mt76: mt7915: check for devm_pinctrl_get() failure If devm_pinctrl_get() fails then it leads to an error pointer dereference. Add a check to prevent that. Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986") Signed-off-by: Dan Carpenter Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 769874820f9b..3028c02cb840 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -196,6 +196,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev) type = mt7986_wmac_check_adie_type(dev); pinctrl = devm_pinctrl_get(dev->mt76.dev); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); switch (type) { case ADIE_SB: -- cgit v1.2.3 From c00e13726b6c728370686b6d6e0e71b0a9f37f03 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Mar 2022 22:24:29 +0000 Subject: mt76: connac: make read-only array ba_range static const Don't populate the read-only array ba_range on the stack but instead make it static const. Also makes the object code a little smaller. Signed-off-by: Colin Ian King Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 5e65fa3f3cba..eeb73d14552b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1054,7 +1054,7 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb, } if (enable && tx) { - u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; + static const u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; int i; for (i = 7; i > 0; i--) { -- cgit v1.2.3 From f1fe8eefd2dd383beaf1748d8246a421c43865c5 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 9 Mar 2022 14:29:24 +0800 Subject: mt76: use le32/16_get_bits() whenever possible Switch to use le32/16_get_bits() to simplfy codes and specify the size explicitly to avoid potential issues. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 9 ++---- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 20 ++++++------- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 35 ++++++++-------------- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 31 ++++++++----------- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 13 ++++---- .../net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/sdio_txrx.c | 2 +- 8 files changed, 46 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 415ea17b9be6..37b092e3ea51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -76,7 +76,7 @@ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); if (q == MT_RXQ_MCU) { if (type == PKT_TYPE_RX_EVENT) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 2e5d26616bc2..17713c821d80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1130,7 +1130,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, } rate_set_tsf = READ_ONCE(sta->rate_set_tsf); - rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) - + rs_idx = !((u32)(le32_get_bits(txs_data[1], MT_TXS1_F0_TIMESTAMP) - rate_set_tsf) < 1000000); rs_idx ^= rate_set_tsf & BIT(0); rs = &sta->rateset[rs_idx]; @@ -1244,14 +1244,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) struct mt7603_sta *msta = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; - u32 txs; u8 wcidx; u8 pid; - txs = le32_to_cpu(txs_data[4]); - pid = FIELD_GET(MT_TXS4_PID, txs); - txs = le32_to_cpu(txs_data[3]); - wcidx = FIELD_GET(MT_TXS3_WCID, txs); + pid = le32_get_bits(txs_data[4], MT_TXS4_PID); + wcidx = le32_get_bits(txs_data[3], MT_TXS3_WCID); if (pid == MT_PACKET_ID_NO_ACK) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index d1d87240f24f..bd687f7de628 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -261,7 +261,7 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) struct ieee80211_hdr hdr; u16 frame_control; - if (FIELD_GET(MT_RXD1_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[1])) != + if (le32_get_bits(rxd[1], MT_RXD1_NORMAL_ADDR_TYPE) != MT_RXD1_NORMAL_U2M) return -EINVAL; @@ -1427,7 +1427,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, } rate_set_tsf = READ_ONCE(sta->rate_set_tsf); - rs_idx = !((u32)(FIELD_GET(MT_TXS4_F0_TIMESTAMP, le32_to_cpu(txs_data[4])) - + rs_idx = !((u32)(le32_get_bits(txs_data[4], MT_TXS4_F0_TIMESTAMP) - rate_set_tsf) < 1000000); rs_idx ^= rate_set_tsf & BIT(0); rs = &sta->rateset[rs_idx]; @@ -1558,14 +1558,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) struct mt76_wcid *wcid; struct mt76_phy *mphy = &dev->mt76.phy; __le32 *txs_data = data; - u32 txs; u8 wcidx; u8 pid; - txs = le32_to_cpu(txs_data[0]); - pid = FIELD_GET(MT_TXS0_PID, txs); - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); + pid = le32_get_bits(txs_data[0], MT_TXS0_PID); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); if (pid == MT_PACKET_ID_NO_ACK) return; @@ -1653,7 +1650,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len) mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); } - count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); + count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT); if (is_mt7615(&dev->mt76)) { __le16 *token = &free->token[0]; @@ -1686,7 +1683,8 @@ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len) __le32 *end = (__le32 *)&rxd[len / 4]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + switch (type) { case PKT_TYPE_TXRX_NOTIFY: mt7615_mac_tx_free(dev, data, len); @@ -1710,8 +1708,8 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, enum rx_pkt_type type; u16 flag; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); - flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG); if (type == PKT_TYPE_RX_EVENT && flag == 0x1) type = PKT_TYPE_NORMAL_MCU; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index b02451c775c0..44866d4dab97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -226,8 +226,8 @@ mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, u32 ru_h, ru_l; u8 ru, offs = 0; - ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0])); - ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1])); + ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L); + ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H); ru = (u8)(ru_l | ru_h << 4); status->bw = RATE_INFO_BW_HE_RU; @@ -400,7 +400,7 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) struct ieee80211_hdr hdr; u16 frame_control; - if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) != + if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != MT_RXD3_NORMAL_U2M) return -EINVAL; @@ -861,7 +861,7 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) u8 snr; int i; - band_idx = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1])); + band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX); if (band_idx && !phy->band_idx) phy = mt7915_ext_phy(dev); @@ -1356,7 +1356,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he)) return; - tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1])); + tid = le32_get_bits(txwi[1], MT_TXD1_TID); if (tid >= 6) /* skip VO queue */ return; @@ -1404,7 +1404,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) mt7915_tx_check_aggr(sta, txwi); } else { - wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); } __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); @@ -1438,12 +1438,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); } - /* - * TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, - * to the time ack is received or dropped by hw (air + hw queue time). - * Should avoid accessing WTBL to get Tx airtime, and use it instead. - */ - total = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl)); + total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4); if (WARN_ON_ONCE((void *)&free->info[total >> v3] > end)) return; @@ -1636,18 +1631,13 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; - u32 txs; u8 pid; - txs = le32_to_cpu(txs_data[0]); - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) return; - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); - - txs = le32_to_cpu(txs_data[3]); - pid = FIELD_GET(MT_TXS3_PID, txs); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); + pid = le32_get_bits(txs_data[3], MT_TXS3_PID); if (pid < MT_PACKET_ID_FIRST) return; @@ -1684,7 +1674,8 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len) __le32 *end = (__le32 *)&rxd[len / 4]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + switch (type) { case PKT_TYPE_TXRX_NOTIFY: mt7915_mac_tx_free(dev, data, len); @@ -1709,7 +1700,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); switch (type) { case PKT_TYPE_TXRX_NOTIFY: diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index ea2a655acc6a..8bd8b4fe1047 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -176,8 +176,8 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, u32 ru_h, ru_l; u8 ru, offs = 0; - ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0])); - ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1])); + ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L); + ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H); ru = (u8)(ru_l | ru_h << 4); status->bw = RATE_INFO_BW_HE_RU; @@ -247,19 +247,19 @@ mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) MU_PREP(FLAGS2_SIG_B_SYMS_USERS, le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); - he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, le32_to_cpu(rxv[3])); + he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0); if (status->bw >= RATE_INFO_BW_40) { he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); he_mu->ru_ch2[0] = - FIELD_GET(MT_CRXV_HE_RU1, le32_to_cpu(rxv[3])); + le32_get_bits(rxv[3], MT_CRXV_HE_RU1); } if (status->bw >= RATE_INFO_BW_80) { he_mu->ru_ch1[1] = - FIELD_GET(MT_CRXV_HE_RU2, le32_to_cpu(rxv[3])); + le32_get_bits(rxv[3], MT_CRXV_HE_RU2); he_mu->ru_ch2[1] = - FIELD_GET(MT_CRXV_HE_RU3, le32_to_cpu(rxv[3])); + le32_get_bits(rxv[3], MT_CRXV_HE_RU3); } } @@ -409,7 +409,7 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) struct ieee80211_hdr hdr; u16 frame_control; - if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) != + if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != MT_RXD3_NORMAL_U2M) return -EINVAL; @@ -1024,7 +1024,7 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he)) return; - tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1])); + tid = le32_get_bits(txwi[1], MT_TXD1_TID); if (tid >= 6) /* skip VO queue */ return; @@ -1163,18 +1163,13 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; - u32 txs; u8 pid; - txs = le32_to_cpu(txs_data[0]); - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) return; - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); - - txs = le32_to_cpu(txs_data[3]); - pid = FIELD_GET(MT_TXS3_PID, txs); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); + pid = le32_get_bits(txs_data[3], MT_TXS3_PID); if (pid < MT_PACKET_ID_FIRST) return; @@ -1213,8 +1208,8 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, enum rx_pkt_type type; u16 flag; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); - flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG); if (type == PKT_TYPE_RX_EVENT && flag == 0x1) type = PKT_TYPE_NORMAL_MCU; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 8ca58293ddf1..5ca14dbbdd26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -137,7 +137,7 @@ mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, wcid_idx = wcid->idx; } else { - wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); } __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); @@ -164,11 +164,7 @@ mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len) mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); - /* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, - * to the time ack is received or dropped by hw (air + hw queue time). - * Should avoid accessing WTBL to get Tx airtime, and use it instead. - */ - count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl)); + count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); if (WARN_ON_ONCE((void *)&free->info[count] > end)) return; @@ -231,7 +227,8 @@ bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len) __le32 *end = (__le32 *)&rxd[len / 4]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + switch (type) { case PKT_TYPE_TXRX_NOTIFY: mt7921e_mac_tx_free(dev, data, len); @@ -252,7 +249,7 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *rxd = (__le32 *)skb->data; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); switch (type) { case PKT_TYPE_TXRX_NOTIFY: diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 4fd1d4765b04..09bcabd6cb8a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -202,7 +202,7 @@ void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) struct mt76_wcid *wcid; u16 idx; - idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); + idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); wcid = rcu_dereference(mdev->wcid[idx]); sta = wcid_to_sta(wcid); diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c index 9fcf507e09bd..a2601aa9e7b1 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c @@ -118,7 +118,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid, __le32 *rxd = (__le32 *)buf; /* parse rxd to get the actual packet length */ - len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0])); + len = le32_get_bits(rxd[0], GENMASK(15, 0)); e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4)); if (!e->skb) break; -- cgit v1.2.3 From 6450b1335f5101f0700fdc67593d355588ebc312 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Fri, 11 Mar 2022 00:42:36 +0800 Subject: mt76: fix invalid rssi report Drop invalid rssi value to calculate a reasonable report Fixes: 4550fb9e9810 ("mt76: improve signal strength reporting") Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 372b94a665ec..5b53d008eb66 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -942,10 +942,11 @@ mt76_rx_signal(struct mt76_rx_status *status) for (chains = status->chains; chains; chains >>= 1, chain_signal++) { int cur, diff; - if (!(chains & BIT(0))) + cur = *chain_signal; + if (!(chains & BIT(0)) || + cur > 0) continue; - cur = *chain_signal; if (cur > signal) swap(cur, signal); -- cgit v1.2.3 From 70493b8692495adc5735f498db4f7fe71be24b3c Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Fri, 11 Mar 2022 22:44:25 +0800 Subject: mt76: mt7915: set band1 TGID field in tx descriptor Set proper group index of tx descriptor for band1. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 44866d4dab97..fdfdded9613d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1218,8 +1218,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); - if ((ext_phy || band_idx) && - q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) + if (ext_phy || band_idx) val |= MT_TXD1_TGID; txwi[1] = cpu_to_le32(val); -- cgit v1.2.3 From bd1407ed22ed56d054dc51b53a39d272ae259e4d Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Fri, 11 Mar 2022 22:44:26 +0800 Subject: mt76: mt7915: fix beamforming mib stats Some of beamforming mib counters are moved to different offsets or registers in newer chipsets. Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986") Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 73 +++++++++++++++--------- drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 2 + drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 28 ++++++--- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index fdfdded9613d..47d5a993c9c7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -2185,15 +2185,6 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) cnt = mt76_rr(dev, MT_MIB_SDR31(phy->band_idx)); mib->rx_ba_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx)); - mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt); - - if (is_mt7915(&dev->mt76)) - cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx)); - mib->tx_pkt_ibf_cnt += is_mt7915(&dev->mt76) ? - FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK, cnt) : - FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDRMUBF(phy->band_idx)); mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt); @@ -2206,24 +2197,10 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) cnt = mt76_rr(dev, MT_MIB_DR11(phy->band_idx)); mib->tx_su_acked_mpdu_cnt += cnt; - cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx)); - mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt); - mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt); - - cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx)); - mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt); - mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt); - mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt); - mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt); - - cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(phy->band_idx)); - mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt); - mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt); - mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt); - - cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx)); - mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt); - mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt); + cnt = mt76_rr(dev, MT_ETBF_PAR_RPT0(phy->band_idx)); + mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_PAR_RPT0_FB_BW, cnt); + mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NC, cnt); + mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NR, cnt); for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); @@ -2252,6 +2229,26 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) dev->mt76.aggr_stats[aggr1++] += val & 0xffff; dev->mt76.aggr_stats[aggr1++] += val >> 16; } + + cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx)); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx)); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx)); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx)); + mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt); + mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt); + + cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx)); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt); } else { for (i = 0; i < 2; i++) { /* rts count */ @@ -2280,6 +2277,28 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val); dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val); } + + cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx)); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR7(phy->band_idx)); + mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_MIB_BFCR7_BFEE_TX_FB_CPL, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR2(phy->band_idx)); + mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_MIB_BFCR2_BFEE_TX_FB_TRIG, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR0(phy->band_idx)); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR1(phy->band_idx)); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 1b14bba7ec89..5062e0d8cae4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -122,6 +122,7 @@ static const u32 mt7915_offs[] = { [PLE_PG_HIF_GROUP] = 0x110, [PLE_HIF_PG_INFO] = 0x114, [AC_OFFSET] = 0x040, + [ETBF_PAR_RPT0] = 0x068, }; static const u32 mt7916_offs[] = { @@ -194,6 +195,7 @@ static const u32 mt7916_offs[] = { [PLE_PG_HIF_GROUP] = 0x00c, [PLE_HIF_PG_INFO] = 0x388, [AC_OFFSET] = 0x080, + [ETBF_PAR_RPT0] = 0x100, }; static const struct __map mt7915_reg_map[] = { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 8fe24ab49143..e5f93c40591c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -103,6 +103,7 @@ enum offs_rev { PLE_PG_HIF_GROUP, PLE_HIF_PG_INFO, AC_OFFSET, + ETBF_PAR_RPT0, __MT_OFFS_MAX, }; @@ -223,10 +224,10 @@ enum offs_rev { #define MT_ETBF_TX_FB_CPL GENMASK(31, 16) #define MT_ETBF_TX_FB_TRI GENMASK(15, 0) -#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x068) -#define MT_ETBF_RX_FB_BW GENMASK(7, 6) -#define MT_ETBF_RX_FB_NC GENMASK(5, 3) -#define MT_ETBF_RX_FB_NR GENMASK(2, 0) +#define MT_ETBF_PAR_RPT0(_band) MT_WF_ETBF(_band, __OFFS(ETBF_PAR_RPT0)) +#define MT_ETBF_PAR_RPT0_FB_BW GENMASK(7, 6) +#define MT_ETBF_PAR_RPT0_FB_NC GENMASK(5, 3) +#define MT_ETBF_PAR_RPT0_FB_NR GENMASK(2, 0) #define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x0f0) #define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) @@ -367,11 +368,11 @@ enum offs_rev { #define MT_MIB_SDR31(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR31)) #define MT_MIB_SDR32(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR32)) -#define MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK GENMASK(15, 0) +#define MT_MIB_SDR32_TX_PKT_EBF_CNT GENMASK(15, 0) +#define MT_MIB_SDR32_TX_PKT_IBF_CNT GENMASK(31, 16) #define MT_MIB_SDR33(_band) MT_WF_MIB(_band, 0x088) -#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916 GENMASK(31, 16) +#define MT_MIB_SDR33_TX_PKT_IBF_CNT GENMASK(15, 0) #define MT_MIB_SDRMUBF(_band) MT_WF_MIB(_band, __OFFS(MIB_SDRMUBF)) #define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) @@ -401,6 +402,19 @@ enum offs_rev { ((n) << 2)) #define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) +#define MT_MIB_BFCR0(_band) MT_WF_MIB(_band, 0x7b0) +#define MT_MIB_BFCR0_RX_FB_HT GENMASK(15, 0) +#define MT_MIB_BFCR0_RX_FB_VHT GENMASK(31, 16) + +#define MT_MIB_BFCR1(_band) MT_WF_MIB(_band, 0x7b4) +#define MT_MIB_BFCR1_RX_FB_HE GENMASK(15, 0) + +#define MT_MIB_BFCR2(_band) MT_WF_MIB(_band, 0x7b8) +#define MT_MIB_BFCR2_BFEE_TX_FB_TRIG GENMASK(15, 0) + +#define MT_MIB_BFCR7(_band) MT_WF_MIB(_band, 0x7cc) +#define MT_MIB_BFCR7_BFEE_TX_FB_CPL GENMASK(15, 0) + /* WTBLON TOP */ #define MT_WTBLON_TOP_BASE 0x820d4000 #define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -- cgit v1.2.3 From 381d9de774d4fb6262eaf489e0f193001e6e5299 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Fri, 11 Mar 2022 22:44:27 +0800 Subject: mt76: mt7915: fix phy cap in mt7915_set_stream_he_txbf_caps() This patch fixes performance issue of beamforming tx on bandwidth 160MHz. Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986") Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 25 +++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 668244e0d11e..5534df00617d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -726,11 +726,18 @@ void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy) } static void -mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, +mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev, + struct ieee80211_sta_he_cap *he_cap, int vif, int nss) { struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem; - u8 c; + u8 c, nss_160; + + /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */ + if (is_mt7915(&dev->mt76) && !dev->dbdc_support) + nss_160 = nss / 2; + else + nss_160 = nss; #ifdef CONFIG_MAC80211_MESH if (vif == NL80211_IFTYPE_MESH_POINT) @@ -784,13 +791,21 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, /* num_snd_dim * for mt7915, max supported nss is 2 for bw > 80MHz */ - c = (nss - 1) | - IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2; + c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, + nss - 1) | + FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK, + nss_160 - 1); elem->phy_cap_info[5] |= c; c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; + + if (!is_mt7915(&dev->mt76)) { + c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ | + IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; + elem->phy_cap_info[7] |= c; + } } static void @@ -952,7 +967,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160); he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160); - mt7915_set_stream_he_txbf_caps(he_cap, i, nss); + mt7915_set_stream_he_txbf_caps(dev, he_cap, i, nss); memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & -- cgit v1.2.3 From 51f9325c7b43c604cec8885c8e0d0352b811f1a6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 14 Mar 2022 12:53:34 +0100 Subject: mt76: mt7915: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 5534df00617d..9a8df1282f8d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -581,7 +581,7 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev) val &= ~MT_TOP_PWR_SW_RST; mt76_wr(dev, MT_TOP_PWR_CTRL, val); - /* release wfsys then mcu re-excutes romcode */ + /* release wfsys then mcu re-executes romcode */ val |= MT_TOP_PWR_SW_RST; mt76_wr(dev, MT_TOP_PWR_CTRL, val); -- cgit v1.2.3 From 84bba93ac46ee8d5d6eca57769f8dfbfa8bea1f0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:23 +0100 Subject: mt76: usb: add req_type to ___mt76u_rr signature This is a preliminary patch to add usb support to mt7921 driver. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 0a7006c8959b..1b0435e0ea33 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -62,16 +62,15 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, } EXPORT_SYMBOL_GPL(mt76u_vendor_request); -static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr) +static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, + u32 addr) { struct mt76_usb *usb = &dev->usb; u32 data = ~0; int ret; - ret = __mt76u_vendor_request(dev, req, - USB_DIR_IN | USB_TYPE_VENDOR, - addr >> 16, addr, usb->data, - sizeof(__le32)); + ret = __mt76u_vendor_request(dev, req, req_type, addr >> 16, + addr, usb->data, sizeof(__le32)); if (ret == sizeof(__le32)) data = get_unaligned_le32(usb->data); trace_usb_reg_rr(dev, addr, data); @@ -95,7 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) break; } - return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK); + return ___mt76u_rr(dev, req, USB_DIR_IN | USB_TYPE_VENDOR, + addr & ~MT_VEND_TYPE_MASK); } static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) @@ -114,7 +114,8 @@ static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) u32 ret; mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr); mutex_unlock(&dev->usb.usb_ctrl_mtx); return ret; @@ -177,7 +178,8 @@ static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) { mutex_lock(&dev->usb.usb_ctrl_mtx); - val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask; + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask; ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); mutex_unlock(&dev->usb.usb_ctrl_mtx); -- cgit v1.2.3 From e0daf14d9f4e5fe445700fed287a16318f89d56e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:24 +0100 Subject: mt76: usb: add req_type to ___mt76u_wr signature This is a preliminary patch to add usb support to mt7921 driver. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 1b0435e0ea33..4b7a816f1b93 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -121,16 +121,14 @@ static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) return ret; } -static void ___mt76u_wr(struct mt76_dev *dev, u8 req, +static void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr, u32 val) { struct mt76_usb *usb = &dev->usb; put_unaligned_le32(val, usb->data); - __mt76u_vendor_request(dev, req, - USB_DIR_OUT | USB_TYPE_VENDOR, - addr >> 16, addr, usb->data, - sizeof(__le32)); + __mt76u_vendor_request(dev, req, req_type, addr >> 16, + addr, usb->data, sizeof(__le32)); trace_usb_reg_wr(dev, addr, val); } @@ -146,7 +144,8 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) req = MT_VEND_MULTI_WRITE; break; } - ___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val); + ___mt76u_wr(dev, req, USB_DIR_OUT | USB_TYPE_VENDOR, + addr & ~MT_VEND_TYPE_MASK, val); } static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) @@ -159,7 +158,8 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val) { mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); mutex_unlock(&dev->usb.usb_ctrl_mtx); } @@ -180,7 +180,8 @@ static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, mutex_lock(&dev->usb.usb_ctrl_mtx); val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask; - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); mutex_unlock(&dev->usb.usb_ctrl_mtx); return val; -- cgit v1.2.3 From 6cb596ba84e307930836e9533a48792095f0dd42 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:25 +0100 Subject: mt76: usb: introduce __mt76u_init utility routine Introduce __mt76u_init unitility routine and move mt7615 usb bus ops into mt7615 module in order to allow specifying driver specific parameter. This is a preliminary patch to add usb support to mt7921 driver. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 12 ++- drivers/net/wireless/mediatek/mt76/mt7615/usb.c | 68 +++++++++++++- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 112 +++++++----------------- 5 files changed, 110 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 81078be3bd07..882fb5d2517f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1274,13 +1274,21 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, struct mt76_sta_stats *stats); int mt76_skb_adjust_pad(struct sk_buff *skb, int pad); +int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, + u16 val, u16 offset, void *buf, size_t len); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); -int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, - bool ext); +void mt76u_read_copy(struct mt76_dev *dev, u32 offset, + void *data, int len); +u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr); +void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, + u32 addr, u32 val); +int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + struct mt76_bus_ops *ops); +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); int mt76u_alloc_mcu_queue(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_tx(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index aeeba7c72f14..967641aebf5f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -21,6 +21,64 @@ static const struct usb_device_id mt7615_device_table[] = { { }, }; +static u32 mt7663u_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7663u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static u32 mt7663u_rmw(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + +static void mt7663u_copy(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + static void mt7663u_stop(struct ieee80211_hw *hw) { struct mt7615_phy *phy = mt7615_hw_phy(hw); @@ -66,6 +124,14 @@ static int mt7663u_probe(struct usb_interface *usb_intf, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, }; + static struct mt76_bus_ops bus_ops = { + .rr = mt7663u_rr, + .wr = mt7663u_wr, + .rmw = mt7663u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt7663u_copy, + .type = MT76_BUS_USB, + }; struct usb_device *udev = interface_to_usbdev(usb_intf); struct ieee80211_ops *ops; struct mt7615_dev *dev; @@ -92,7 +158,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf, INIT_WORK(&dev->mcu_work, mt7663u_init_work); dev->reg_map = mt7663_usb_sdio_reg_map; dev->ops = ops; - ret = mt76u_init(mdev, usb_intf, true); + ret = __mt76u_init(mdev, usb_intf, &bus_ops); if (ret < 0) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 436daf6d6d86..0422c332354a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -245,7 +245,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); mt76x02u_init_mcu(mdev); - ret = mt76u_init(mdev, usb_intf, false); + ret = mt76u_init(mdev, usb_intf); if (ret) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 2575369e44e2..55068f3252ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -57,7 +57,7 @@ static int mt76x2u_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); mt76x02u_init_mcu(mdev); - err = mt76u_init(mdev, intf, false); + err = mt76u_init(mdev, intf); if (err < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 4b7a816f1b93..a85e192c9d59 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -15,9 +15,8 @@ static bool disable_usb_sg; module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644); MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support"); -static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, - u8 req_type, u16 val, u16 offset, - void *buf, size_t len) +int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, + u16 val, u16 offset, void *buf, size_t len) { struct usb_interface *uintf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(uintf); @@ -45,6 +44,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, req, offset, ret); return ret; } +EXPORT_SYMBOL_GPL(__mt76u_vendor_request); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, @@ -62,8 +62,7 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, } EXPORT_SYMBOL_GPL(mt76u_vendor_request); -static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, - u32 addr) +u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr) { struct mt76_usb *usb = &dev->usb; u32 data = ~0; @@ -77,6 +76,7 @@ static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, return data; } +EXPORT_SYMBOL_GPL(___mt76u_rr); static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) { @@ -109,20 +109,8 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) return ret; } -static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | USB_TYPE_VENDOR, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, - u32 addr, u32 val) +void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, + u32 addr, u32 val) { struct mt76_usb *usb = &dev->usb; @@ -131,6 +119,7 @@ static void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, addr, usb->data, sizeof(__le32)); trace_usb_reg_wr(dev, addr, val); } +EXPORT_SYMBOL_GPL(___mt76u_wr); static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) { @@ -155,14 +144,6 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) mutex_unlock(&dev->usb.usb_ctrl_mtx); } -static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) { @@ -174,19 +155,6 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, return val; } -static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, - u32 mask, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask; - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return val; -} - static void mt76u_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) { @@ -219,33 +187,8 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset, mutex_unlock(&usb->usb_ctrl_mtx); } -static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset, - const void *data, int len) -{ - struct mt76_usb *usb = &dev->usb; - int ret, i = 0, batch_len; - const u8 *val = data; - - len = round_up(len, 4); - mutex_lock(&usb->usb_ctrl_mtx); - while (i < len) { - batch_len = min_t(int, usb->data_len, len - i); - memcpy(usb->data, val + i, batch_len); - ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | USB_TYPE_VENDOR, - (offset + i) >> 16, offset + i, - usb->data, batch_len); - if (ret < 0) - break; - - i += batch_len; - } - mutex_unlock(&usb->usb_ctrl_mtx); -} - -static void -mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, - void *data, int len) +void mt76u_read_copy(struct mt76_dev *dev, u32 offset, + void *data, int len) { struct mt76_usb *usb = &dev->usb; int i = 0, batch_len, ret; @@ -267,6 +210,7 @@ mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, } mutex_unlock(&usb->usb_ctrl_mtx); } +EXPORT_SYMBOL_GPL(mt76u_read_copy); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val) @@ -1115,24 +1059,13 @@ static const struct mt76_queue_ops usb_queue_ops = { .kick = mt76u_tx_kick, }; -int mt76u_init(struct mt76_dev *dev, - struct usb_interface *intf, bool ext) +int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + struct mt76_bus_ops *ops) { - static struct mt76_bus_ops mt76u_ops = { - .read_copy = mt76u_read_copy_ext, - .wr_rp = mt76u_wr_rp, - .rd_rp = mt76u_rd_rp, - .type = MT76_BUS_USB, - }; struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; int err; - mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; - mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; - mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw; - mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; - INIT_WORK(&usb->stat_work, mt76u_tx_status_data); usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); @@ -1144,7 +1077,7 @@ int mt76u_init(struct mt76_dev *dev, return -ENOMEM; mutex_init(&usb->usb_ctrl_mtx); - dev->bus = &mt76u_ops; + dev->bus = ops; dev->queue_ops = &usb_queue_ops; dev_set_drvdata(&udev->dev, dev); @@ -1170,6 +1103,23 @@ int mt76u_init(struct mt76_dev *dev, return 0; } +EXPORT_SYMBOL_GPL(__mt76u_init); + +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf) +{ + static struct mt76_bus_ops bus_ops = { + .rr = mt76u_rr, + .wr = mt76u_wr, + .rmw = mt76u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt76u_copy, + .wr_rp = mt76u_wr_rp, + .rd_rp = mt76u_rd_rp, + .type = MT76_BUS_USB, + }; + + return __mt76u_init(dev, intf, &bus_ops); +} EXPORT_SYMBOL_GPL(mt76u_init); MODULE_AUTHOR("Lorenzo Bianconi "); -- cgit v1.2.3 From eafe031fd6646072021da8860366c4bf567927a4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:26 +0100 Subject: mt76: mt7921: disable runtime pm for usb Runtime-pm is not currently supported by usb driver Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7921/init.c | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 32004b55a360..bce76417f95d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -267,6 +267,9 @@ mt7921_pm_set(void *data, u64 val) struct mt7921_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + mutex_lock(&dev->mt76.mutex); if (val == pm->enable_user) @@ -311,6 +314,9 @@ mt7921_deep_sleep_set(void *data, u64 val) bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); bool enable = !!val; + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + mt7921_mutex_acquire(dev); if (pm->ds_enable_user == enable) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index fa6af85bba7b..54f51e7b48a0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -226,10 +226,12 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->pm.idle_timeout = MT7921_PM_TIMEOUT; dev->pm.stats.last_wake_event = jiffies; dev->pm.stats.last_doze_event = jiffies; - dev->pm.enable_user = true; - dev->pm.enable = true; - dev->pm.ds_enable_user = true; - dev->pm.ds_enable = true; + if (!mt76_is_usb(&dev->mt76)) { + dev->pm.enable_user = true; + dev->pm.enable = true; + dev->pm.ds_enable_user = true; + dev->pm.ds_enable = true; + } if (mt76_is_sdio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; -- cgit v1.2.3 From b72fd217934d70c30a4793256aa92b0127962d70 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:27 +0100 Subject: mt76: mt7921: update mt7921_skb_add_usb_sdio_hdr to support usb This is a preliminary patch to add mt7921u driver support. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 10 ++++++---- drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 3952247659fa..39ad75af988c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -352,12 +352,14 @@ static inline void mt7921_mcu_tx_cleanup(struct mt7921_dev *dev) mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false); } -static inline void mt7921_skb_add_sdio_hdr(struct sk_buff *skb, - enum mt7921_sdio_pkt_type type) +static inline void +mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, + int type) { - u32 hdr; + u32 hdr, len; - hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, skb->len + sizeof(hdr)) | + len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr); + hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) | FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type); put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr))); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 09bcabd6cb8a..248d3f3cdb08 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -183,7 +183,7 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb); - mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA); + mt7921_skb_add_usb_sdio_hdr(dev, skb, MT7921_SDIO_DATA); pad = round_up(skb->len, 4) - skb->len; err = mt76_skb_adjust_pad(skb, pad); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 5d8af18c7026..54a5c712a3c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -36,7 +36,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, if (cmd == MCU_CMD(FW_SCATTER)) type = MT7921_SDIO_FWDL; - mt7921_skb_add_sdio_hdr(skb, type); + mt7921_skb_add_usb_sdio_hdr(dev, skb, type); pad = round_up(skb->len, 4) - skb->len; __skb_put_zero(skb, pad); -- cgit v1.2.3 From 5b834b0d4d6b8179e8859b6161c6ab4a8076e882 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:28 +0100 Subject: mt76: mt7921: move mt7921_usb_sdio_tx_prepare_skb in common mac code This is a preliminary patch to add mt7921u driver support. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 58 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 9 ++-- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 53 -------------------- 4 files changed, 64 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 8bd8b4fe1047..dd1a241c45d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1622,3 +1622,61 @@ void mt7921_coredump_work(struct work_struct *work) mt7921_reset(&dev->mt76); } + +/* usb_sdio */ +static void +mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, + enum mt76_txq_id qid, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, int pid, + struct sk_buff *skb) +{ + __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); + + memset(txwi, 0, MT_SDIO_TXD_SIZE); + mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false); + skb_push(skb, MT_SDIO_TXD_SIZE); +} + +int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct sk_buff *skb = tx_info->skb; + int err, pad, pktid, type; + + if (unlikely(tx_info->skb->len <= ETH_HLEN)) + return -EINVAL; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + if (sta) { + struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + + if (time_after(jiffies, msta->last_txs + HZ / 4)) { + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + msta->last_txs = jiffies; + } + } + + pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); + mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb); + + type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0; + mt7921_skb_add_usb_sdio_hdr(dev, skb, type); + pad = round_up(skb->len, 4) - skb->len; + if (mt76_is_usb(mdev)) + pad += 4; + + err = mt76_skb_adjust_pad(skb, pad); + if (err) + /* Release pktid in case of error. */ + idr_remove(&wcid->pktid, pktid); + + return err; +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_prepare_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 39ad75af988c..06db3e1f39a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -444,14 +444,15 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_init(struct mt7921_dev *dev); int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - enum mt76_txq_id qid, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, - struct mt76_tx_info *tx_info); void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); void mt7921_set_runtime_pm(struct mt7921_dev *dev); int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); + +int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index a6ae29c97e0e..fc6499640a1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -91,7 +91,7 @@ static int mt7921s_probe(struct sdio_func *func, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, - .tx_prepare_skb = mt7921s_tx_prepare_skb, + .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, .tx_complete_skb = mt7921s_tx_complete_skb, .tx_status_data = mt7921s_tx_status_data, .rx_skb = mt7921_queue_rx_skb, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 248d3f3cdb08..d741a58c1260 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -141,59 +141,6 @@ out: return err; } -static void -mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, - enum mt76_txq_id qid, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key, int pid, - struct sk_buff *skb) -{ - __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); - - memset(txwi, 0, MT_SDIO_TXD_SIZE); - mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false); - skb_push(skb, MT_SDIO_TXD_SIZE); -} - -int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - enum mt76_txq_id qid, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, - struct mt76_tx_info *tx_info) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); - struct ieee80211_key_conf *key = info->control.hw_key; - struct sk_buff *skb = tx_info->skb; - int err, pad, pktid; - - if (unlikely(tx_info->skb->len <= ETH_HLEN)) - return -EINVAL; - - if (!wcid) - wcid = &dev->mt76.global_wcid; - - if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - - if (time_after(jiffies, msta->last_txs + HZ / 4)) { - info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; - } - } - - pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); - mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb); - - mt7921_skb_add_usb_sdio_hdr(dev, skb, MT7921_SDIO_DATA); - pad = round_up(skb->len, 4) - skb->len; - - err = mt76_skb_adjust_pad(skb, pad); - if (err) - /* Release pktid in case of error. */ - idr_remove(&wcid->pktid, pktid); - - return err; -} - void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) { __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); -- cgit v1.2.3 From 9da47b504c5b294b3d3df3665a05a80caf54c192 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:29 +0100 Subject: mt76: mt7921: move mt7921_usb_sdio_tx_complete_skb in common mac code. This is a preliminary patch to add mt7921u driver support. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 21 +++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 ++- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 19 ------------------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index dd1a241c45d6..0c1b65653102 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1680,3 +1680,24 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return err; } EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_prepare_skb); + +void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e) +{ + __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); + unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; + struct ieee80211_sta *sta; + struct mt76_wcid *wcid; + u16 idx; + + idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(mdev->wcid[idx]); + sta = wcid_to_sta(wcid); + + if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7921_tx_check_aggr(sta, txwi); + + skb_pull(e->skb, headroom); + mt76_tx_complete_skb(mdev, e->wcid, e->skb); +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 06db3e1f39a2..32b77fe49abd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -444,7 +444,6 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_init(struct mt7921_dev *dev); int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); void mt7921_set_runtime_pm(struct mt7921_dev *dev); @@ -455,4 +454,6 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); +void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index fc6499640a1c..507bd550b063 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -92,7 +92,7 @@ static int mt7921s_probe(struct sdio_func *func, SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, - .tx_complete_skb = mt7921s_tx_complete_skb, + .tx_complete_skb = mt7921_usb_sdio_tx_complete_skb, .tx_status_data = mt7921s_tx_status_data, .rx_skb = mt7921_queue_rx_skb, .sta_ps = mt7921_sta_ps, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index d741a58c1260..fa9db21bb3e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -141,25 +141,6 @@ out: return err; } -void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); - unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - struct ieee80211_sta *sta; - struct mt76_wcid *wcid; - u16 idx; - - idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - wcid = rcu_dereference(mdev->wcid[idx]); - sta = wcid_to_sta(wcid); - - if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); - - skb_pull(e->skb, headroom); - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); -- cgit v1.2.3 From 8b7a56d5c0c90032e579595a9d31d22217e62b87 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:30 +0100 Subject: mt76: mt7921: move mt7921_usb_sdio_tx_status_data in mac common code. This is a preliminary patch to add mt7921u driver support. Tested-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 12 ++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 11 ----------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 0c1b65653102..263ac62d88b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1701,3 +1701,15 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, mt76_tx_complete_skb(mdev, e->wcid, e->skb); } EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb); + +bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + + mt7921_mutex_acquire(dev); + mt7921_mac_sta_poll(dev); + mt7921_mutex_release(dev); + + return false; +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 32b77fe49abd..e0d67756673f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -444,7 +444,6 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_init(struct mt7921_dev *dev); int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); void mt7921_set_runtime_pm(struct mt7921_dev *dev); int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, @@ -456,4 +455,5 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info); void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); +bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 507bd550b063..9b2bc0b11492 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -93,7 +93,7 @@ static int mt7921s_probe(struct sdio_func *func, SURVEY_INFO_TIME_BSS_RX, .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, .tx_complete_skb = mt7921_usb_sdio_tx_complete_skb, - .tx_status_data = mt7921s_tx_status_data, + .tx_status_data = mt7921_usb_sdio_tx_status_data, .rx_skb = mt7921_queue_rx_skb, .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index fa9db21bb3e8..1b3adb3d91e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -140,14 +140,3 @@ out: return err; } - -bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - - mt7921_mutex_acquire(dev); - mt7921_mac_sta_poll(dev); - mt7921_mutex_release(dev); - - return false; -} -- cgit v1.2.3 From 0d2afe09fad5f8c59e21630f10b66b08cf5c529a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 16:10:31 +0100 Subject: mt76: mt7921: add mt7921u driver Introduce support for MT7921U 802.11ax 2x2:2SS wireless devices. Tested-by: Sean Wang Tested-by: Deren Wu Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/Kconfig | 11 + drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 2 + drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.h | 1 + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 +- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 12 + drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 50 +++- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 305 +++++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/usb_mac.c | 252 +++++++++++++++++ 9 files changed, 635 insertions(+), 3 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/usb.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig index 71154fc2a87c..adff2d7350b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig @@ -24,3 +24,14 @@ config MT7921S This adds support for MT7921S 802.11ax 2x2:2SS wireless devices. To compile this driver as a module, choose M here. + +config MT7921U + tristate "MediaTek MT7921U (USB) support" + select MT76_USB + select MT7921_COMMON + depends on MAC80211 + depends on USB + help + This adds support for MT7921U 802.11ax 2x2:2SS wireless devices. + + To compile this driver as a module, choose M here. diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index 1187acedfeda..0a146818c623 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o obj-$(CONFIG_MT7921E) += mt7921e.o obj-$(CONFIG_MT7921S) += mt7921s.o +obj-$(CONFIG_MT7921U) += mt7921u.o CFLAGS_trace.o := -I$(src) @@ -10,3 +11,4 @@ mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o +mt7921u-y := usb.o usb_mac.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 54f51e7b48a0..ceb22653e4bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -233,7 +233,7 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->pm.ds_enable = true; } - if (mt76_is_sdio(&dev->mt76)) + if (!mt76_is_mmio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; ret = mt7921_init_hardware(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h index 12e1cf8abe6e..79447e2d0143 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h @@ -202,6 +202,7 @@ enum tx_mcu_port_q_idx { #define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4) #define MT_SDIO_TAIL_SIZE 8 #define MT_SDIO_HDR_SIZE 4 +#define MT_USB_TAIL_SIZE 4 #define MT_TXD0_Q_IDX GENMASK(31, 25) #define MT_TXD0_PKT_FMT GENMASK(24, 23) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index e5dcf1615f17..3a16a966d9d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -264,7 +264,7 @@ static int mt7921_start(struct ieee80211_hw *hw) return err; } -static void mt7921_stop(struct ieee80211_hw *hw) +void mt7921_stop(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); @@ -281,6 +281,7 @@ static void mt7921_stop(struct ieee80211_hw *hw) mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); mt7921_mutex_release(dev); } +EXPORT_SYMBOL_GPL(mt7921_stop); static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index e0d67756673f..1ea781429d49 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -30,6 +30,7 @@ #define MT7921_DRV_OWN_RETRY_COUNT 10 #define MT7921_MCU_INIT_RETRY_COUNT 10 +#define MT7921_WFSYS_INIT_RETRY_COUNT 2 #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" @@ -365,6 +366,7 @@ mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr))); } +void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt7921_dev *dev); bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); void mt7921_mac_reset_counters(struct mt7921_phy *phy); @@ -456,4 +458,14 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); + +/* usb */ +#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) +#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) + +int mt7921u_mcu_power_on(struct mt7921_dev *dev); +int mt7921u_wfsys_reset(struct mt7921_dev *dev); +int mt7921u_dma_init(struct mt7921_dev *dev); +int mt7921u_init_reset(struct mt7921_dev *dev); +int mt7921u_mac_reset(struct mt7921_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 33578e0dfde3..6712ff60c722 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -353,6 +353,7 @@ #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) #define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) #define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) +#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) #define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) #define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) @@ -377,6 +378,9 @@ #define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) #define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) +#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) +#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) + #define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) #define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) #define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) @@ -425,6 +429,10 @@ #define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) #define MT_WFDMA_NEED_REINIT BIT(1) +#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) +#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) +#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) + #define MT_HW_BOUND 0x70010020 #define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 @@ -433,12 +441,14 @@ #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) -#define MT_DMA_SHDL(ofs) (0xd6000 + (ofs)) +#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) #define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) #define MT_DMASHDL_DMASHDL_BYPASS BIT(28) #define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) #define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) +#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) #define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) +#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) #define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) #define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) #define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) @@ -453,6 +463,43 @@ #define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) +#define MT_WFDMA_HOST_CONFIG 0x7c027030 +#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) + +#define MT_UMAC(ofs) (0x74000000 + (ofs)) +#define MT_UDMA_TX_QSEL MT_UMAC(0x008) +#define MT_FW_DL_EN BIT(3) + +#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) +#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) +#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) + +#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) +#define MT_WL_RX_AGG_TO GENMASK(7, 0) +#define MT_WL_RX_AGG_LMT GENMASK(15, 8) +#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) +#define MT_WL_TX_DPH_CHK_EN BIT(17) +#define MT_WL_RX_MPSZ_PAD0 BIT(18) +#define MT_WL_RX_FLUSH BIT(19) +#define MT_TICK_1US_EN BIT(20) +#define MT_WL_RX_AGG_EN BIT(21) +#define MT_WL_RX_EN BIT(22) +#define MT_WL_TX_EN BIT(23) +#define MT_WL_RX_BUSY BIT(30) +#define MT_WL_TX_BUSY BIT(31) + +#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) +#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) +#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) + +#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) +#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) + +#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) +#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) +#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) +#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) + #define MT_CONN_STATUS 0x7c053c10 #define MT_WIFI_PATCH_DL_STATE BIT(0) @@ -466,6 +513,7 @@ #define WFSYS_SW_INIT_DONE BIT(4) #define MT_CONN_ON_MISC 0x7c0600f0 +#define MT_TOP_MISC2_FW_PWR_ON BIT(0) #define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c new file mode 100644 index 000000000000..0f99d059d319 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. + * + * Author: Lorenzo Bianconi + */ + +#include +#include +#include + +#include "mt7921.h" +#include "mcu.h" +#include "mac.h" + +static const struct usb_device_id mt7921u_device_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff) }, + { }, +}; + +static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + +static void mt7921u_copy(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + +int mt7921u_mcu_power_on(struct mt7921_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, + MT_TOP_MISC2_FW_PWR_ON, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return ret; +} + +static int +mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *seq) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + u32 pad, ep; + int ret; + + ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq); + if (ret) + return ret; + + if (cmd != MCU_CMD(FW_SCATTER)) + ep = MT_EP_OUT_INBAND_CMD; + else + ep = MT_EP_OUT_AC_BE; + + mt7921_skb_add_usb_sdio_hdr(dev, skb, 0); + pad = round_up(skb->len, 4) + 4 - skb->len; + __skb_put_zero(skb, pad); + + ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL, + 1000, ep); + dev_kfree_skb(skb); + + return ret; +} + +static int mt7921u_mcu_init(struct mt7921_dev *dev) +{ + static const struct mt76_mcu_ops mcu_ops = { + .headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd), + .tailroom = MT_USB_TAIL_SIZE, + .mcu_skb_send_msg = mt7921u_mcu_send_message, + .mcu_parse_response = mt7921_mcu_parse_response, + .mcu_restart = mt76_connac_mcu_restart, + }; + int ret; + + dev->mt76.mcu_ops = &mcu_ops; + + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + ret = mt7921_run_firmware(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + return 0; +} + +static void mt7921u_stop(struct ieee80211_hw *hw) +{ + struct mt7921_dev *dev = mt7921_hw_dev(hw); + + mt76u_stop_tx(&dev->mt76); + mt7921_stop(hw); +} + +static void mt7921u_cleanup(struct mt7921_dev *dev) +{ + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + mt7921u_wfsys_reset(dev); + mt7921_mcu_exit(dev); + mt76u_queues_deinit(&dev->mt76); +} + +static int mt7921u_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + .txwi_size = MT_SDIO_TXD_SIZE, + .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, + .tx_complete_skb = mt7921_usb_sdio_tx_complete_skb, + .tx_status_data = mt7921_usb_sdio_tx_status_data, + .rx_skb = mt7921_queue_rx_skb, + .sta_ps = mt7921_sta_ps, + .sta_add = mt7921_mac_sta_add, + .sta_assoc = mt7921_mac_sta_assoc, + .sta_remove = mt7921_mac_sta_remove, + .update_survey = mt7921_update_channel, + }; + static const struct mt7921_hif_ops hif_ops = { + .mcu_init = mt7921u_mcu_init, + .init_reset = mt7921u_init_reset, + .reset = mt7921u_mac_reset, + }; + static struct mt76_bus_ops bus_ops = { + .rr = mt7921u_rr, + .wr = mt7921u_wr, + .rmw = mt7921u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt7921u_copy, + .type = MT76_BUS_USB, + }; + struct usb_device *udev = interface_to_usbdev(usb_intf); + struct ieee80211_ops *ops; + struct ieee80211_hw *hw; + struct mt7921_dev *dev; + struct mt76_dev *mdev; + int ret; + + ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops), + GFP_KERNEL); + if (!ops) + return -ENOMEM; + + ops->stop = mt7921u_stop; + + mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7921_dev, mt76); + dev->hif_ops = &hif_ops; + + udev = usb_get_dev(udev); + usb_reset_device(udev); + + usb_set_intfdata(usb_intf, dev); + + ret = __mt76u_init(mdev, usb_intf, &bus_ops); + if (ret < 0) + goto error; + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) { + ret = mt7921u_wfsys_reset(dev); + if (ret) + goto error; + } + + ret = mt7921u_mcu_power_on(dev); + if (ret) + goto error; + + ret = mt76u_alloc_mcu_queue(&dev->mt76); + if (ret) + goto error; + + ret = mt76u_alloc_queues(&dev->mt76); + if (ret) + goto error; + + ret = mt7921u_dma_init(dev); + if (ret) + return ret; + + hw = mt76_hw(dev); + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1; + + ret = mt7921_register_device(dev); + if (ret) + goto error; + + return 0; + +error: + mt76u_queues_deinit(&dev->mt76); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); + + return ret; +} + +static void mt7921u_disconnect(struct usb_interface *usb_intf) +{ + struct mt7921_dev *dev = usb_get_intfdata(usb_intf); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return; + + mt76_unregister_device(&dev->mt76); + mt7921u_cleanup(dev); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); +} + +MODULE_DEVICE_TABLE(usb, mt7921u_device_table); +MODULE_FIRMWARE(MT7921_FIRMWARE_WM); +MODULE_FIRMWARE(MT7921_ROM_PATCH); + +static struct usb_driver mt7921u_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7921u_device_table, + .probe = mt7921u_probe, + .disconnect = mt7921u_disconnect, + .soft_unbind = 1, + .disable_hub_initiated_lpm = 1, +}; +module_usb_driver(mt7921u_driver); + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c new file mode 100644 index 000000000000..99bcbd858b65 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. + * + * Author: Lorenzo Bianconi + */ + +#include +#include +#include + +#include "mt7921.h" +#include "mcu.h" +#include "mac.h" + +static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, + USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE, + USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static void mt7921u_dma_prefetch(struct mt7921_dev *dev) +{ + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_BASE_PTR_MASK, 0x80); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_BASE_PTR_MASK, 0xc0); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_BASE_PTR_MASK, 0x100); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_BASE_PTR_MASK, 0x140); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_BASE_PTR_MASK, 0x180); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_BASE_PTR_MASK, 0x280); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_BASE_PTR_MASK, 0x2c0); +} + +static void mt7921u_wfdma_init(struct mt7921_dev *dev) +{ + mt7921u_dma_prefetch(dev); + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | + MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + /* disable dmashdl */ + mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + +static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev) +{ + if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) + return -ETIMEDOUT; + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + return 0; +} + +static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) +{ + u32 val; + + /* usb endpoint reset opt + * bits[4,9]: out blk ep 4-9 + * bits[20,21]: in blk ep 4-5 + * bits[22]: in int ep 6 + */ + val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); + if (reset) + val |= GENMASK(9, 4) | GENMASK(22, 20); + else + val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); + mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); +} + +int mt7921u_dma_init(struct mt7921_dev *dev) +{ + int err; + + mt7921u_wfdma_init(dev); + + mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); + + mt76_set(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_EN | MT_WL_TX_EN | + MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); + mt76_clear(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); + mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); + + err = mt7921u_dma_rx_evt_ep4(dev); + if (err) + return err; + + mt7921u_epctl_rst_opt(dev, false); + + return 0; +} + +int mt7921u_wfsys_reset(struct mt7921_dev *dev) +{ + u32 val; + int i; + + mt7921u_epctl_rst_opt(dev, false); + + val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + usleep_range(10, 20); + + val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); + for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) { + val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); + if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) + break; + + msleep(100); + } + + if (i == MT7921_WFSYS_INIT_RETRY_COUNT) + return -ETIMEDOUT; + + return 0; +} + +int mt7921u_init_reset(struct mt7921_dev *dev) +{ + set_bit(MT76_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + mt7921_mcu_exit(dev); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt7921u_wfsys_reset(dev); + + clear_bit(MT76_RESET, &dev->mphy.state); + + return mt76u_resume_rx(&dev->mt76); +} + +int mt7921u_mac_reset(struct mt7921_dev *dev) +{ + int err; + + mt76_txq_schedule_all(&dev->mphy); + mt76_worker_disable(&dev->mt76.tx_worker); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + mt7921_mcu_exit(dev); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt7921u_wfsys_reset(dev); + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + err = mt76u_resume_rx(&dev->mt76); + if (err) + goto out; + + err = mt7921u_mcu_power_on(dev); + if (err) + goto out; + + err = mt7921u_dma_init(dev); + if (err) + goto out; + + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_run_firmware(dev); + if (err) + goto out; + + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7921_mac_init(dev); + if (err) + goto out; + + err = __mt7921_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; +} -- cgit v1.2.3 From 1c71e03afe4b457a15e50de40006b927dfc00755 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 14 Mar 2022 17:29:13 +0100 Subject: mt76: mt7921: move mt7921_init_hw in a dedicated work Firmware initialization can take a while. Move mt7921_init_hw routine in a dedicated work in order to not slow down bootstrap process. Tested-by: Deren Wu Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 62 +++++++++++++++------- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 + drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 1 + 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index ceb22653e4bb..91fc41922d95 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -165,7 +165,7 @@ out: static int mt7921_init_hardware(struct mt7921_dev *dev) { - int ret, idx, i; + int ret, i; set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); @@ -182,6 +182,13 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return ret; } + return 0; +} + +static int mt7921_init_wcid(struct mt7921_dev *dev) +{ + int idx; + /* Beacon and mgmt frames should occupy wcid 0 */ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); if (idx) @@ -195,6 +202,38 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return 0; } +static void mt7921_init_work(struct work_struct *work) +{ + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + init_work); + int ret; + + ret = mt7921_init_hardware(dev); + if (ret) + return; + + mt76_set_stream_caps(&dev->mphy, true); + mt7921_set_stream_he_caps(&dev->phy); + + ret = mt76_register_device(&dev->mt76, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); + if (ret) { + dev_err(dev->mt76.dev, "register device failed\n"); + return; + } + + ret = mt7921_init_debugfs(dev); + if (ret) { + dev_err(dev->mt76.dev, "register debugfs failed\n"); + return; + } + + /* we support chip reset now */ + dev->hw_init_done = true; + + mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); +} + int mt7921_register_device(struct mt7921_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -222,6 +261,7 @@ int mt7921_register_device(struct mt7921_dev *dev) spin_lock_init(&dev->sta_poll_lock); INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); + INIT_WORK(&dev->init_work, mt7921_init_work); dev->pm.idle_timeout = MT7921_PM_TIMEOUT; dev->pm.stats.last_wake_event = jiffies; @@ -236,7 +276,7 @@ int mt7921_register_device(struct mt7921_dev *dev) if (!mt76_is_mmio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - ret = mt7921_init_hardware(dev); + ret = mt7921_init_wcid(dev); if (ret) return ret; @@ -264,23 +304,7 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; - mt76_set_stream_caps(&dev->mphy, true); - mt7921_set_stream_he_caps(&dev->phy); - - ret = mt76_register_device(&dev->mt76, true, mt76_rates, - ARRAY_SIZE(mt76_rates)); - if (ret) - return ret; - - ret = mt7921_init_debugfs(dev); - if (ret) - return ret; - - ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); - if (ret) - return ret; - - dev->hw_init_done = true; + queue_work(system_wq, &dev->init_work); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 1ea781429d49..7690364bc079 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -205,6 +205,8 @@ struct mt7921_dev { struct list_head sta_poll_list; spinlock_t sta_poll_lock; + struct work_struct init_work; + u8 fw_debug; struct mt76_connac_pm pm; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index a0c82d19c4d9..1a01d025bbe5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -105,6 +105,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) int i; struct mt76_connac_pm *pm = &dev->pm; + cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 9b2bc0b11492..af26d59fa2f0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -41,6 +41,7 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; + cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 0f99d059d319..b7771e9f1fcd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -275,6 +275,7 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf) { struct mt7921_dev *dev = usb_get_intfdata(usb_intf); + cancel_work_sync(&dev->init_work); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return; -- cgit v1.2.3 From 6b7f9aff7c673989c6adf601c7e3f3684d5acd44 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 15 Mar 2022 13:19:12 +0100 Subject: mt76: mt7915: introduce 802.11ax multi-bss support Introduce mbss mcu APIs to enable 802.11ax multi-bss AP support for mt7915 devices Tested-by: Money Wang Co-developed-by: Ryder Lee Signed-off-by: Ryder Lee Co-developed-by: Money Wang Signed-off-by: Money Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 19 ++++++-- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 + drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 54 +++++++++++++++++++++- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index eeb73d14552b..7cb17bf40e35 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -2675,11 +2675,25 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, struct bss_info_basic *bss; struct tlv *tlv; + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); + bss = (struct bss_info_basic *)tlv; + switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MONITOR: break; + case NL80211_IFTYPE_AP: + if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) { + u8 bssid_id = vif->bss_conf.bssid_indicator; + struct wiphy *wiphy = phy->hw->wiphy; + + if (bssid_id > ilog2(wiphy->mbssid_max_interfaces)) + return -EINVAL; + + bss->non_tx_bssid = vif->bss_conf.bssid_index; + bss->max_bssid = bssid_id; + } + break; case NL80211_IFTYPE_STATION: if (enable) { rcu_read_lock(); @@ -2704,9 +2718,6 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, break; } - tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); - - bss = (struct bss_info_basic *)tlv; bss->network_type = cpu_to_le32(type); bss->bmc_wcid_lo = to_wcid_lo(wlan_idx); bss->bmc_wcid_hi = to_wcid_hi(wlan_idx); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 9a8df1282f8d..6d29366c5139 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -343,6 +343,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7915_regd_notifier; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy->mbssid_max_interfaces = 16; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); @@ -360,6 +361,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); hw->max_tx_fragments = 4; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 10dc4bf5adec..9cd458223b00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1825,6 +1825,55 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, info->cnt = skb->data[offs->cntdwn_counter_offs[0]]; } +static void +mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, + struct ieee80211_vif *vif, struct bss_info_bcn *bcn, + struct ieee80211_mutable_offsets *offs) +{ + struct bss_info_bcn_mbss *mbss; + const struct element *elem; + struct tlv *tlv; + + if (!vif->bss_conf.bssid_indicator) + return; + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID, + sizeof(*mbss), &bcn->sub_ntlv, + &bcn->len); + + mbss = (struct bss_info_bcn_mbss *)tlv; + mbss->offset[0] = cpu_to_le16(offs->tim_offset); + mbss->bitmap = cpu_to_le32(1); + + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, + &skb->data[offs->mbssid_off], + skb->len - offs->mbssid_off) { + const struct element *sub_elem; + + if (elem->datalen < 2) + continue; + + for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) { + const u8 *data; + + if (sub_elem->id || sub_elem->datalen < 4) + continue; /* not a valid BSS profile */ + + /* Find WLAN_EID_MULTI_BSSID_IDX + * in the merged nontransmitted profile + */ + data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, + sub_elem->data, + sub_elem->datalen); + if (!data || data[1] < 1 || !data[2]) + continue; + + mbss->offset[data[2]] = cpu_to_le16(data - skb->data); + mbss->bitmap |= cpu_to_le32(BIT(data[2])); + } + } +} + static void mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *rskb, struct sk_buff *skb, @@ -1952,6 +2001,9 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE; bool ext_phy = phy != &dev->phy; + if (vif->bss_conf.nontransmitted) + return 0; + rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL, len); if (IS_ERR(rskb)) @@ -1981,8 +2033,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, mt7915_mcu_beacon_check_caps(phy, vif, skb); - /* TODO: subtag - 11v MBSSID */ mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs); + mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs); mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); dev_kfree_skb(skb); -- cgit v1.2.3 From 32bfd774626d8e1051fe78ae37f0906421a8bd84 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Wed, 16 Mar 2022 00:24:34 +0800 Subject: mt76: fix wrong HE data rate in sniffer tool Due to the missing IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN in status report, the HE rate in wirehsark/tcpdump always shows wrong value. Applications will refer to IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC when the flag is set and shows the correct data rate. Reviewed-by: Ryder Lee Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 6 ++++-- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 47d5a993c9c7..e9e7efbf350d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -349,14 +349,16 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode) 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_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); break; case MT_PHY_TYPE_HE_EXT_SU: he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN); + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 263ac62d88b7..233998ca4857 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -304,14 +304,16 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode) 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_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); break; case MT_PHY_TYPE_HE_EXT_SU: he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN); + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); break; -- cgit v1.2.3 From 1f12fa34e5dc57433e63e7137d11afa0df4c5b8f Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 16 Mar 2022 03:25:03 +0800 Subject: mt76: mt7921: don't enable beacon filter when IEEE80211_CONF_CHANGE_MONITOR is set IEEE80211_CONF_CHANGE_MONITOR would be set every time even when vif runs as sta mode. If vif runs as sta mode, the beacon filter would be falsely enabled earlier than the associated state. That is not the behavior the firmware expects and also breaks the original logic of sta mode. Thus, we only limit the operation to set the beacon filter only for monitor mode when IEEE80211_CONF_CHANGE_MONITOR is set. Fixes: 4ad65a54617c ("mt76: mt7921: toggle runtime-pm adding a monitor vif") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 3a16a966d9d3..fdaf2451bc1d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -485,9 +485,17 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7921_dev *dev = priv; struct ieee80211_hw *hw = mt76_hw(dev); - bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + mt7921_mcu_set_sniffer(dev, vif, monitor); + pm->enable = !monitor; + pm->ds_enable = !monitor; + + mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); - mt7921_mcu_set_sniffer(dev, vif, enabled); + if (monitor) + mt7921_mcu_set_beacon_filter(dev, vif, false); } void mt7921_set_runtime_pm(struct mt7921_dev *dev) @@ -531,7 +539,6 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) IEEE80211_IFACE_ITER_RESUME_ALL, mt7921_sniffer_interface_iter, dev); dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0)); - mt7921_set_runtime_pm(dev); } out: -- cgit v1.2.3 From 24e69f6bc3ca4a1696158b68a6fbf14252a8bd28 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Wed, 16 Mar 2022 17:51:52 +0800 Subject: mt76: fix monitor rx FCS error in DFS channel When setup monitor mode in DFS channel, mt76 send CH_SWITCH_DFS to fw for channel config. This would cause rx performance bad while monitoring frames. Settings CH_SWITCH_NORMAL in monitor mode would get the same performance as normal channels. Reviewed-by: Shayne Chen Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 390add3144c2..97e2a85cb728 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -2151,7 +2151,8 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - if (cmd == MCU_EXT_CMD(SET_RX_PATH)) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 9cd458223b00..e7a6f80e7755 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2885,7 +2885,8 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) } #endif - if (cmd == MCU_EXT_CMD(SET_RX_PATH)) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 5ef8b24f0ab3..da2be050ed7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -863,7 +863,8 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) else req.channel_band = chandef->chan->band; - if (cmd == MCU_EXT_CMD(SET_RX_PATH)) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; -- cgit v1.2.3