From 532f0482fc577a78c0086893ab39acb406ac3e65 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Sat, 4 Feb 2023 14:53:04 +0800 Subject: wifi: mt76: remove redundent MCU_UNI_CMD_* definitions clear redundent definitions only Fixes: 5b55b6da982c ("wifi: mt76: mt7921: add unified ROC cmd/event support") Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index a5e6ee4daf92..40a99e0caded 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -967,9 +967,6 @@ enum { DEV_INFO_MAX_NUM }; -#define MCU_UNI_CMD_EVENT BIT(1) -#define MCU_UNI_CMD_UNSOLICITED_EVENT BIT(2) - /* event table */ enum { MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, -- cgit From 64822bdba456a145f7cb4c66d9939bf42c64ae62 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 7 Feb 2023 14:35:04 +0100 Subject: dt-bindings: mt76: add active-low property for led LEDs can be in low-active mode, driver already supports it, but documentation is missing. Add documentation for the dt property. Signed-off-by: Frank Wunderlich Acked-by: Krzysztof Kozlowski Signed-off-by: Felix Fietkau --- Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml index 7d526ff53fb7..67b63f119f64 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml @@ -111,6 +111,11 @@ properties: $ref: /schemas/leds/common.yaml# additionalProperties: false properties: + led-active-low: + description: + LED is enabled with ground signal. + type: boolean + led-sources: maxItems: 1 -- cgit From fcc51acfebb85dbc3ab1bea3ce4997d7c0a3a38d Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Sat, 11 Feb 2023 09:01:58 +0800 Subject: wifi: mt76: mt7921: fix wrong command to set STA channel Should not use AND operator to check vif type NL80211_IFTYPE_MONITOR, and that will cause we go into sniffer command for both STA and MONITOR mode. However, the sniffer command would set channel properly (with some extra options), the STA mode still works even if using the wrong command. Fix vif type check to make sure we using the right command to update channel. Fixes: 914189af23b8 ("wifi: mt76: mt7921: fix channel switch fail in monitor mode") Signed-off-by: Deren Wu 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 75eaf86c6a78..a72964e7a807 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1695,7 +1695,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac, if (ctx != mvif->ctx) return; - if (vif->type & NL80211_IFTYPE_MONITOR) + if (vif->type == NL80211_IFTYPE_MONITOR) mt7921_mcu_config_sniffer(mvif, ctx); else mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx); -- cgit From 9270270d62191b7549296721e8d5f3dc0df01563 Mon Sep 17 00:00:00 2001 From: Deren Wu Date: Tue, 14 Feb 2023 10:49:57 +0800 Subject: wifi: mt76: mt7921: fix PCI DMA hang after reboot mt7921 just stop some workers and clean up chip status before reboot. In stress test, there are working activities still running at the period of .shutdown callback and that would cause some hosts cannot recover DMA after reboot. To avoid the floating state in reboot, we use mt7921_pci_remove() to fully deinit all resources. Fixes: f23a0cea8bd6 ("wifi: mt76: mt7921e: add pci .shutdown() support") Signed-off-by: Deren Wu Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index cb72ded37256..1a8a54a46dcc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -509,17 +509,7 @@ failed: static void mt7921_pci_shutdown(struct pci_dev *pdev) { - struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt76_connac_pm *pm = &dev->pm; - - cancel_delayed_work_sync(&pm->ps_work); - cancel_work_sync(&pm->wake_work); - - /* chip cleanup before reboot */ - mt7921_mcu_drv_pmctrl(dev); - mt7921_dma_cleanup(dev); - mt7921_wfsys_reset(dev); + mt7921_pci_remove(pdev); } static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume); -- cgit From df5e5bfdb1d52c5524f21e34488a37f3fe2badad Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Feb 2023 13:56:50 +0800 Subject: wifi: mt76: mt7996: Remove unneeded semicolon ./drivers/net/wireless/mediatek/mt76/mt7996/mcu.c:3136:3-4: Unneeded semicolon Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4059 Signed-off-by: Yang Li Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index dbe30832fd88..8ad51cbfdbe8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -3133,7 +3133,7 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) break; default: break; - }; + } buf += le16_to_cpu(tlv->len); } -- cgit From cdc215c2c8d74b3c8886650e979b47f16c1f7f92 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Feb 2023 15:15:05 +0300 Subject: wifi: mt76: mt7915: unlock on error in mt7915_thermal_temp_store() Drop the lock before returning -EINVAL. Fixes: ecaccdae7a7e ("wifi: mt76: mt7915: rework mt7915_thermal_temp_store()") Signed-off-by: Dan Carpenter Acked-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 5e288116b1b0..4f3efc942a4d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -89,6 +89,7 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev, val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) { dev_err(phy->dev->mt76.dev, "temp1_max shall be greater than temp1_crit."); + mutex_unlock(&phy->dev->mt76.mutex); return -EINVAL; } -- cgit From 63a3724632464559d1e98d90d2c63d43ec6ef6f5 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 18 Feb 2023 01:46:54 +0800 Subject: wifi: mt76: mt7996: fix radiotap bitfield The 11be generation's radiotap bitfields were wrongly copy-and-pasted from 11ax driver, so fix them accordingly. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 54 +++++++++++++------------ drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 41 +++++++++---------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index c9a9f0e31771..3c3506c7c87a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -260,12 +260,9 @@ mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, struct ieee80211_radiotap_he *he, __le32 *rxv) { - u32 ru_h, ru_l; - u8 ru, offs = 0; + u32 ru, offs = 0; - 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); + ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC); status->bw = RATE_INFO_BW_HE_RU; @@ -330,18 +327,23 @@ mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | MU_PREP(FLAGS2_SIG_B_SYMS_USERS, - le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); + le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); - he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0); + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; if (status->bw >= RATE_INFO_BW_40) { he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); - he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1); + he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; } if (status->bw >= RATE_INFO_BW_80) { - he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2); - he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3); + u32 ru_h, ru_l; + + he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; + + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); } } @@ -364,23 +366,23 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) HE_BITS(DATA2_TXOP_KNOWN), }; struct ieee80211_radiotap_he *he = NULL; - u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1; + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; status->flag |= RX_FLAG_RADIOTAP_HE; he = skb_push(skb, sizeof(known)); memcpy(he, &known, sizeof(known)); - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); - he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | le16_encode_bits(ltf_size, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); switch (mode) { case MT_PHY_TYPE_HE_SU: @@ -389,22 +391,22 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) 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]); + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 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_BW_RU_ALLOC_KNOWN); - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); break; case MT_PHY_TYPE_HE_MU: he->data1 |= HE_BITS(DATA1_FORMAT_MU) | HE_BITS(DATA1_UL_DL_KNOWN); - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); mt7996_mac_decode_he_radiotap_ru(status, he, rxv); mt7996_mac_decode_he_mu_radiotap(skb, rxv); @@ -415,10 +417,10 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]); + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); mt7996_mac_decode_he_radiotap_ru(status, he, rxv); break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index 27184cbac619..2cc218f735d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -102,8 +102,7 @@ enum rx_pkt_type { #define MT_PRXV_NSTS GENMASK(10, 7) #define MT_PRXV_TXBF BIT(11) #define MT_PRXV_HT_AD_CODE BIT(12) -#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28) -#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) +#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22) #define MT_PRXV_RCPI3 GENMASK(31, 24) #define MT_PRXV_RCPI2 GENMASK(23, 16) #define MT_PRXV_RCPI1 GENMASK(15, 8) @@ -113,34 +112,32 @@ enum rx_pkt_type { #define MT_PRXV_TX_MODE GENMASK(14, 11) #define MT_PRXV_FRAME_MODE GENMASK(2, 0) #define MT_PRXV_DCM BIT(5) -#define MT_PRXV_NUM_RX BIT(8, 6) /* C-RXV */ -#define MT_CRXV_HT_STBC GENMASK(1, 0) -#define MT_CRXV_TX_MODE GENMASK(7, 4) -#define MT_CRXV_FRAME_MODE GENMASK(10, 8) -#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) -#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) -#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) -#define MT_CRXV_HE_PE_DISAMBIG BIT(23) -#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) -#define MT_CRXV_HE_UPLINK BIT(31) -#define MT_CRXV_HE_RU0 GENMASK(7, 0) -#define MT_CRXV_HE_RU1 GENMASK(15, 8) -#define MT_CRXV_HE_RU2 GENMASK(23, 16) -#define MT_CRXV_HE_RU3 GENMASK(31, 24) - -#define MT_CRXV_HE_MU_AID GENMASK(30, 20) +#define MT_CRXV_HE_NUM_USER GENMASK(26, 20) +#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27) +#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30) + +#define MT_CRXV_HE_PE_DISAMBIG BIT(1) +#define MT_CRXV_HE_UPLINK BIT(2) + +#define MT_CRXV_HE_MU_AID GENMASK(27, 17) +#define MT_CRXV_HE_BEAM_CHNG BIT(29) + +#define MT_CRXV_HE_DOPPLER BIT(0) +#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10) +#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17) #define MT_CRXV_HE_SR_MASK GENMASK(11, 8) #define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) #define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) #define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) -#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0) -#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6) -#define MT_CRXV_HE_BEAM_CHNG BIT(13) -#define MT_CRXV_HE_DOPPLER BIT(16) +#define MT_CRXV_HE_RU0 GENMASK(8, 0) +#define MT_CRXV_HE_RU1 GENMASK(17, 9) +#define MT_CRXV_HE_RU2 GENMASK(26, 18) +#define MT_CRXV_HE_RU3_L GENMASK(31, 27) +#define MT_CRXV_HE_RU3_H GENMASK(3, 0) enum tx_header_format { MT_HDR_FORMAT_802_3, -- cgit From c278a64a9375b5410a25d3e17317c36ee9e2fd02 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 18 Feb 2023 01:47:32 +0800 Subject: wifi: mt76: dynamic channel bandwidth changes in AP mode Allow AP to change channel width for 40Mhz intolerant STA on the 2.4 GHz band. Signed-off-by: Himanshu Goyal Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 34abf70f44af..87902f4b8e12 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -418,7 +418,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, phy->macaddr); - wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_AP_UAPSD; -- cgit From 90fb69212c60e26ef70ed0e8532b116c7649ac88 Mon Sep 17 00:00:00 2001 From: Lorenz Brun Date: Sat, 18 Feb 2023 12:29:45 +0100 Subject: wifi: mt76: mt7915: expose device tree match table On MT7986 the WiFi driver currently does not get automatically loaded, requiring manual modprobing because the device tree compatibles are not exported into metadata. Add the missing MODULE_DEVICE_TABLE macro to fix this. Fixes: 99ad32a4ca3a2 ("mt76: mt7915: add support for MT7986") Signed-off-by: Lorenz Brun Reviewed-by: AngeloGioacchino Del Regno 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 2ac0a0f2859c..32c137066e7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -1239,6 +1239,8 @@ static const struct of_device_id mt7986_wmac_of_match[] = { {}, }; +MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match); + struct platform_driver mt7986_wmac_driver = { .driver = { .name = "mt7986-wmac", -- cgit From db1a5a6c69e3f2dc05984f5472195bf011254d92 Mon Sep 17 00:00:00 2001 From: Sujuan Chen Date: Wed, 22 Feb 2023 21:01:35 +0800 Subject: wifi: mt76: mt7915: add dev->hif2 support for mt7916 WED device Enable two PCIe interfaces (dev->hif2) support for mt7916 when WED is enabled. Signed-off-by: Sujuan Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 10 ++++++++-- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 10 +++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index abe17dac9996..43a5456d4b97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -87,8 +87,14 @@ static void mt7915_dma_config(struct mt7915_dev *dev) MT7916_RXQ_BAND0); RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916, MT7916_RXQ_MCU_WA); - RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916, - MT7916_RXQ_BAND1); + if (dev->hif2) + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, + MT_INT_RX_DONE_BAND1_MT7916, + MT7916_RXQ_BAND1); + else + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, + MT_INT_WED_RX_DONE_BAND1_MT7916, + MT7916_RXQ_BAND1); RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN); TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 5545a8bdf1d0..16f09ead307d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2370,7 +2370,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) if (ret) return ret; - if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76)) + if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && + is_mt7915(&dev->mt76)) || + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); ret = mt7915_mcu_set_mwds(dev, 1); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 225a19604d3e..6f0c0e2ae045 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -989,13 +989,13 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) struct mt7915_dev *dev = dev_instance; struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - if (mtk_wed_device_active(wed)) { + if (mtk_wed_device_active(wed)) mtk_wed_device_irq_set_mask(wed, 0); - } else { + else mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); - } + + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; -- cgit From 9c97df11dfe68b548a47744ba9fa6beddcfba2bc Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Thu, 23 Feb 2023 14:24:57 +0800 Subject: wifi: mt76: mt7915: rework init flow in mt7915_thermal_init() If kernel do not enable CONFIG_HWMON, it may cause thermal initialization to be done with temperature value 0 and then can not transmit. This commit fixes it by setting trigger/restore temperature before checking CONFIG_HWMON. Fixes: 7d12b38ab6f6 ("wifi: mt76: mt7915: call mt7915_mcu_set_thermal_throttling() only after init_work") Signed-off-by: Howard Hsu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 4f3efc942a4d..71ccefd39cb2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -203,6 +203,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) phy->cdev = cdev; } + /* initialize critical/maximum high temperature */ + phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP; + phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP; + if (!IS_REACHABLE(CONFIG_HWMON)) return 0; @@ -211,10 +215,6 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) if (IS_ERR(hwmon)) return PTR_ERR(hwmon); - /* initialize critical/maximum high temperature */ - phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP; - phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP; - return 0; } -- cgit From e4d2b8bcac11c23536771ff38e536c7462b213f5 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Wed, 22 Feb 2023 14:27:29 +0800 Subject: wifi: mt76: drop the incorrect scatter and gather frame The scatter and gather frame may be incorrect because WED and WO may send frames to host driver interleaved. Signed-off-by: Peter Chiu Signed-off-by: Sujuan Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 6 ++++-- drivers/net/wireless/mediatek/mt76/dma.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index da281cd1d36f..738d7e1569bf 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -402,8 +402,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, *info = le32_to_cpu(desc->info); if (mt76_queue_is_wed_rx(q)) { - u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, - le32_to_cpu(desc->buf1)); + u32 buf1 = le32_to_cpu(desc->buf1); + u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1); struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token); if (!t) @@ -424,6 +424,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP)); + + *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP); } } else { buf = e->buf; diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index 4b9bc7f462b8..1b090d78cd05 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -19,6 +19,7 @@ #define MT_DMA_CTL_TO_HOST_A BIT(12) #define MT_DMA_CTL_DROP BIT(14) #define MT_DMA_CTL_TOKEN GENMASK(31, 16) +#define MT_DMA_CTL_WO_DROP BIT(8) #define MT_DMA_PPE_CPU_REASON GENMASK(15, 11) #define MT_DMA_PPE_ENTRY GENMASK(30, 16) -- cgit From 9e47dd9f64a47ae00ca0123017584c37209ee900 Mon Sep 17 00:00:00 2001 From: Kang Chen Date: Mon, 27 Feb 2023 22:48:23 +0800 Subject: wifi: mt76: handle failure of vzalloc in mt7615_coredump_work vzalloc may fails, dump might be null and will cause illegal address access later. Link: https://lore.kernel.org/all/Y%2Fy5Asxw3T3m4jCw@lore-desk Fixes: d2bf7959d9c0 ("mt76: mt7663: introduce coredump support") Signed-off-by: Kang Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index a95602473359..6d6b46d7bd1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -2380,7 +2380,7 @@ void mt7615_coredump_work(struct work_struct *work) break; skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); - if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { + if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { dev_kfree_skb(skb); continue; } @@ -2390,6 +2390,8 @@ void mt7615_coredump_work(struct work_struct *work) dev_kfree_skb(skb); } - dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, - GFP_KERNEL); + + if (dump) + dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, + GFP_KERNEL); } -- cgit From 5b8ccdfb943f6a03c676d2ea816dd38c149e920b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 14 Apr 2023 14:10:54 +0200 Subject: wifi: mt76: add missing locking to protect against concurrent rx/status calls According to the documentation, ieee80211_rx_list must not run concurrently with ieee80211_tx_status (or its variants). Cc: stable@vger.kernel.org Fixes: 88046b2c9f6d ("mt76: add support for reporting tx status with skb") Reported-by: Brian Coverstone Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 5 ++++- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 5 ++++- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 5 ++++- drivers/net/wireless/mediatek/mt76/tx.c | 4 ++++ 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 738d7e1569bf..6c0174313d09 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -578,7 +578,9 @@ free: free_skb: status.skb = tx_info.skb; hw = mt76_tx_status_get_hw(dev, tx_info.skb); + spin_lock_bh(&dev->rx_lock); ieee80211_tx_status_ext(hw, &status); + spin_unlock_bh(&dev->rx_lock); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 70a7f84af028..12e0af52082a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1279,8 +1279,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) if (wcidx >= MT7603_WTBL_STA || !sta) goto out; - if (mt7603_fill_txs(dev, msta, &info, txs_data)) + if (mt7603_fill_txs(dev, msta, &info, txs_data)) { + spin_lock_bh(&dev->mt76.rx_lock); ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + spin_unlock_bh(&dev->mt76.rx_lock); + } out: rcu_read_unlock(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 6d6b46d7bd1a..ce216bad3b73 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1558,8 +1558,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (wcid->phy_idx && dev->mt76.phys[MT_BAND1]) mphy = dev->mt76.phys[MT_BAND1]; - if (mt7615_fill_txs(dev, msta, &info, txs_data)) + if (mt7615_fill_txs(dev, msta, &info, txs_data)) { + spin_lock_bh(&dev->mt76.rx_lock); ieee80211_tx_status_noskb(mphy->hw, sta, &info); + spin_unlock_bh(&dev->mt76.rx_lock); + } out: rcu_read_unlock(); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index d3f74473e6fb..3e41d809ade3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -631,8 +631,11 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, mt76_tx_status_unlock(mdev, &list); - if (!status.skb) + if (!status.skb) { + spin_lock_bh(&dev->mt76.rx_lock); ieee80211_tx_status_ext(mt76_hw(dev), &status); + spin_unlock_bh(&dev->mt76.rx_lock); + } if (!len) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 3ad9742364ba..72b3ec715e47 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -77,7 +77,9 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list) } hw = mt76_tx_status_get_hw(dev, skb); + spin_lock_bh(&dev->rx_lock); ieee80211_tx_status_ext(hw, &status); + spin_unlock_bh(&dev->rx_lock); } rcu_read_unlock(); } @@ -263,7 +265,9 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff * if (cb->pktid < MT_PACKET_ID_FIRST) { hw = mt76_tx_status_get_hw(dev, skb); status.sta = wcid_to_sta(wcid); + spin_lock_bh(&dev->rx_lock); ieee80211_tx_status_ext(hw, &status); + spin_unlock_bh(&dev->rx_lock); goto out; } -- cgit From 1a1ff6c3b338a6e9ef8d187fbae3d8f823a300ce Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 18 Feb 2023 01:50:38 +0800 Subject: wifi: mt76: connac: refresh tx session timer for WED device There's no keep-alive packet being received by mac80211 stack when WED is enabled, which leads to tx BA session timeout. This patch calls ieee80211_refresh_tx_agg_session_timer() to refresh timer according to tx status reporting. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index aed4ee95fb2e..8d316d3aab8f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -582,6 +582,17 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); stats->tx_retries += le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT); + + if (wcid->sta) { + struct ieee80211_sta *sta; + u8 tid; + + sta = container_of((void *)wcid, struct ieee80211_sta, + drv_priv); + tid = FIELD_GET(MT_TXS0_TID, txs); + + ieee80211_refresh_tx_agg_session_timer(sta, tid); + } } txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); -- cgit From 885f7af7e54498e7168fa9e7c2f029f81988f933 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 9 Feb 2023 10:22:59 +0800 Subject: wifi: mt76: mt7915: remove mt7915_mcu_beacon_check_caps() Those capabilities have been added into ieee80211_bss_conf. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 1 - drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 107 +++------------------ drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 14 --- 3 files changed, 12 insertions(+), 110 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 3bbccbdfc5eb..2ada2806de66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -269,7 +269,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; mt7915_init_bitrate_mask(vif); - memset(&mvif->cap, -1, sizeof(mvif->cap)); mt7915_mcu_add_bss_info(phy, vif, true); mt7915_mcu_add_sta(dev, vif, NULL, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 16f09ead307d..7432b1eb396d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -706,7 +706,6 @@ static void mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he *he; @@ -740,7 +739,7 @@ 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.he_ldpc && + if (vif->bss_conf.he_ldpc && (elem->phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) cap |= STA_REC_HE_CAP_LDPC; @@ -849,7 +848,6 @@ static void mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct sta_rec_muru *muru; struct tlv *tlv; @@ -862,9 +860,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, muru = (struct sta_rec_muru *)tlv; - muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || - mvif->cap.vht_mu_ebfer || - mvif->cap.vht_mu_ebfee; + muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer || + vif->bss_conf.vht_mu_beamformer || + vif->bss_conf.vht_mu_beamformee; if (!is_mt7915(&dev->mt76)) muru->cfg.mimo_ul_en = true; muru->cfg.ofdma_dl_en = true; @@ -997,8 +995,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.ht_ldpc, - mvif->cap.vht_ldpc); + wtbl_hdr, vif->bss_conf.ht_ldpc, + vif->bss_conf.vht_ldpc); return 0; } @@ -1007,7 +1005,6 @@ static inline bool mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; int tx_ant = hweight8(phy->mt76->chainmask) - 1; if (vif->type != NL80211_IFTYPE_STATION && @@ -1021,10 +1018,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; if (bfee) - return mvif->cap.he_su_ebfee && + return vif->bss_conf.he_su_beamformee && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); else - return mvif->cap.he_su_ebfer && + return vif->bss_conf.he_su_beamformer && HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } @@ -1032,10 +1029,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, u32 cap = sta->deflink.vht_cap.cap; if (bfee) - return mvif->cap.vht_su_ebfee && + return vif->bss_conf.vht_su_beamformee && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); else - return mvif->cap.vht_su_ebfer && + return vif->bss_conf.vht_su_beamformer && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); } @@ -1530,7 +1527,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_TX_STBC; if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (mvif->cap.ht_ldpc && + if (vif->bss_conf.ht_ldpc && (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; @@ -1556,7 +1553,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_VHT_TX_STBC; if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (mvif->cap.vht_ldpc && + if (vif->bss_conf.vht_ldpc && (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; @@ -1875,84 +1872,6 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } -static void -mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, - struct sk_buff *skb) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_vif_cap *vc = &mvif->cap; - const struct ieee80211_he_cap_elem *he; - const struct ieee80211_vht_cap *vht; - const struct ieee80211_ht_cap *ht; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - const u8 *ie; - u32 len, bc; - - /* Check missing configuration options to allow AP mode in mac80211 - * to remain in sync with hostapd settings, and get a subset of - * beacon and hardware capabilities. - */ - if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data))) - return; - - memset(vc, 0, sizeof(*vc)); - - len = skb->len - (mgmt->u.beacon.variable - skb->data); - - ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable, - len); - if (ie && ie[1] >= sizeof(*ht)) { - ht = (void *)(ie + 2); - 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, - len); - if (ie && ie[1] >= sizeof(*vht)) { - u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap; - - vht = (void *)(ie + 2); - bc = le32_to_cpu(vht->vht_cap_info); - - 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); - vc->vht_su_ebfee = - (bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) && - (pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); - vc->vht_mu_ebfer = - (bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) && - (pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE); - vc->vht_mu_ebfee = - (bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && - (pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); - } - - ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, - mgmt->u.beacon.variable, len); - if (ie && ie[1] >= sizeof(*he) + 1) { - const struct ieee80211_sta_he_cap *pc = - mt76_connac_get_he_phy_cap(phy->mt76, vif); - const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; - - 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]); - vc->he_su_ebfee = - HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) && - HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); - vc->he_mu_ebfer = - HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) && - HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]); - } -} - static void mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *rskb, struct bss_info_bcn *bcn, @@ -2063,8 +1982,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, info = IEEE80211_SKB_CB(skb); info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy); - mt7915_mcu_beacon_check_caps(phy, vif, skb); - 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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 3cbfb9b6a305..e4016cef9447 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -147,23 +147,9 @@ struct mt7915_sta { } twt; }; -struct mt7915_vif_cap { - 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; - bool vht_mu_ebfee:1; - bool he_su_ebfer:1; - bool he_su_ebfee:1; - bool he_mu_ebfer:1; -}; - struct mt7915_vif { struct mt76_vif mt76; /* must be first */ - struct mt7915_vif_cap cap; struct mt7915_sta sta; struct mt7915_phy *phy; -- cgit From dda423dd65c3e977e545306de3f51031103ce610 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 9 Feb 2023 10:23:00 +0800 Subject: wifi: mt76: mt7996: remove mt7996_mcu_beacon_check_caps() Those capabilities have been added into ieee80211_bss_conf. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 1 - drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 115 ++------------------- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 16 --- 3 files changed, 8 insertions(+), 124 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 3e4da0350d96..9d67fcaf2428 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -220,7 +220,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; mt7996_init_bitrate_mask(vif); - memset(&mvif->cap, -1, sizeof(mvif->cap)); mt7996_mcu_add_bss_info(phy, vif, true); mt7996_mcu_add_sta(dev, vif, NULL, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 8ad51cbfdbe8..c1e6f7d1660c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1053,7 +1053,6 @@ static inline bool mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; int sts = hweight16(phy->mt76->chainmask); if (vif->type != NL80211_IFTYPE_STATION && @@ -1068,10 +1067,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; if (bfee) - return mvif->cap.eht_su_ebfee && + return vif->bss_conf.eht_su_beamformee && EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); else - return mvif->cap.eht_su_ebfer && + return vif->bss_conf.eht_su_beamformer && EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); } @@ -1079,10 +1078,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; if (bfee) - return mvif->cap.he_su_ebfee && + return vif->bss_conf.he_su_beamformee && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); else - return mvif->cap.he_su_ebfer && + return vif->bss_conf.he_su_beamformer && HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } @@ -1090,10 +1089,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, u32 cap = sta->deflink.vht_cap.cap; if (bfee) - return mvif->cap.vht_su_ebfee && + return vif->bss_conf.vht_su_beamformee && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); else - return mvif->cap.vht_su_ebfer && + return vif->bss_conf.vht_su_beamformer && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); } @@ -1572,7 +1571,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, cap |= STA_CAP_TX_STBC; if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (mvif->cap.ht_ldpc && + if (vif->bss_conf.ht_ldpc && (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; @@ -1598,7 +1597,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, cap |= STA_CAP_VHT_TX_STBC; if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (mvif->cap.vht_ldpc && + if (vif->bss_conf.vht_ldpc && (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; @@ -1911,102 +1910,6 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } -static void -mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif, - struct sk_buff *skb) -{ - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_vif_cap *vc = &mvif->cap; - const struct ieee80211_eht_cap_elem_fixed *eht; - const struct ieee80211_he_cap_elem *he; - const struct ieee80211_vht_cap *vht; - const struct ieee80211_ht_cap *ht; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - const u8 *ie; - u32 len, bc; - - /* Check missing configuration options to allow AP mode in mac80211 - * to remain in sync with hostapd settings, and get a subset of - * beacon and hardware capabilities. - */ - if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data))) - return; - - memset(vc, 0, sizeof(*vc)); - - len = skb->len - (mgmt->u.beacon.variable - skb->data); - - ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable, - len); - if (ie && ie[1] >= sizeof(*ht)) { - ht = (void *)(ie + 2); - 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, - len); - if (ie && ie[1] >= sizeof(*vht)) { - u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap; - - vht = (void *)(ie + 2); - bc = le32_to_cpu(vht->vht_cap_info); - - 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); - vc->vht_su_ebfee = - (bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) && - (pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); - vc->vht_mu_ebfer = - (bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) && - (pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE); - vc->vht_mu_ebfee = - (bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && - (pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); - } - - ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, - mgmt->u.beacon.variable, len); - if (ie && ie[1] >= sizeof(*he) + 1) { - const struct ieee80211_sta_he_cap *pc = - mt76_connac_get_he_phy_cap(phy->mt76, vif); - const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; - - 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]); - vc->he_su_ebfee = - HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) && - HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); - vc->he_mu_ebfer = - HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) && - HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]); - } - - ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY, - mgmt->u.beacon.variable, len); - if (ie && ie[1] >= sizeof(*eht) + 1) { - const struct ieee80211_sta_eht_cap *pc = - mt76_connac_get_eht_phy_cap(phy->mt76, vif); - const struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; - - eht = (void *)(ie + 3); - - vc->eht_su_ebfer = - EHT_PHY(CAP0_SU_BEAMFORMER, eht->phy_cap_info[0]) && - EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); - vc->eht_su_ebfee = - EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) && - EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); - } -} - int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en) { @@ -2045,8 +1948,6 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); - mt7996_mcu_beacon_check_caps(phy, vif, skb); - mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); /* TODO: subtag - 11v MBSSID */ mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 018dfd2b36b0..24572dd55fe0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -112,25 +112,9 @@ struct mt7996_sta { } twt; }; -struct mt7996_vif_cap { - 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; - bool vht_mu_ebfee:1; - bool he_su_ebfer:1; - bool he_su_ebfee:1; - bool he_mu_ebfer:1; - bool eht_su_ebfer:1; - bool eht_su_ebfee:1; -}; - struct mt7996_vif { struct mt76_vif mt76; /* must be first */ - struct mt7996_vif_cap cap; struct mt7996_sta sta; struct mt7996_phy *phy; -- cgit From 021af945997ffaeaa37c9673d71afad7cde6bdef Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Fri, 3 Mar 2023 16:35:52 +0800 Subject: wifi: mt76: mt7996: add eht rx rate support Add support to report eht rx rate. Note that extended fields for eht in mt76_rx_status will make the struct size exceed the cb size, so make nss and band share the same u8. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 11 ++++++++--- drivers/net/wireless/mediatek/mt76/mt76.h | 18 ++++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 9 +++++---- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 87902f4b8e12..e53166fcdc9d 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1067,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, status->enc_flags = mstat.enc_flags; status->encoding = mstat.encoding; status->bw = mstat.bw; - status->he_ru = mstat.he_ru; - status->he_gi = mstat.he_gi; - status->he_dcm = mstat.he_dcm; + if (status->encoding == RX_ENC_EHT) { + status->eht.ru = mstat.eht.ru; + status->eht.gi = mstat.eht.gi; + } else { + status->he_ru = mstat.he_ru; + status->he_gi = mstat.he_gi; + status->he_dcm = mstat.he_dcm; + } status->rate_idx = mstat.rate_idx; status->nss = mstat.nss; status->band = mstat.band; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 183b0fc5a2d4..c3d1313e2f20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -621,12 +621,22 @@ struct mt76_rx_status { u16 freq; u32 flag; u8 enc_flags; - u8 encoding:2, bw:3, he_ru:3; - u8 he_gi:2, he_dcm:1; + u8 encoding:3, bw:4; + union { + struct { + u8 he_ru:3; + u8 he_gi:2; + u8 he_dcm:1; + }; + struct { + u8 ru:4; + u8 gi:2; + } eht; + }; + u8 amsdu:1, first_amsdu:1, last_amsdu:1; u8 rate_idx; - u8 nss; - u8 band; + u8 nss:5, band:3; s8 signal; u8 chains; s8 chain_signal[IEEE80211_MAX_CHAINS]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 3c3506c7c87a..d811b4e01800 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -572,11 +572,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, case MT_PHY_TYPE_EHT_SU: case MT_PHY_TYPE_EHT_TRIG: case MT_PHY_TYPE_EHT_MU: - /* TODO: currently report rx rate with HE rate */ status->nss = nss; - status->encoding = RX_ENC_HE; - bw = min_t(int, bw, IEEE80211_STA_RX_BW_160); - i = min_t(int, i & 0xf, 11); + status->encoding = RX_ENC_EHT; + i &= GENMASK(3, 0); + + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2) + status->eht.gi = gi; break; default: return -EINVAL; -- cgit From d0b6f86fdbefa62fd4ad2acd1aea6c45f9b518ba Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Fri, 3 Mar 2023 16:35:53 +0800 Subject: wifi: mt76: mt7996: let non-bufferable MMPDUs use correct hw queue Pass qid into mt7996_mac_write_txwi() to let the tx descriptor of non-bufferable MMPDUs be filled with correct hw queue index. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 11 ++++++----- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 5 +++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index d811b4e01800..f1414a448023 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -982,8 +982,9 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, } void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, u32 changed) + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; @@ -1014,7 +1015,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, } else if (beacon) { p_fmt = MT_TX_TYPE_FW; q_idx = MT_LMAC_BCN0; - } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { + } else if (qid >= MT_TXQ_PSD) { p_fmt = MT_TX_TYPE_CT; q_idx = MT_LMAC_ALTX0; } else { @@ -1123,8 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, memset(txwi_ptr, 0, MT_TXD_SIZE); /* Transmit non qos data by 802.11 header and need to fill txd by host*/ if (!is_8023 || pid >= MT_PACKET_ID_FIRST) - mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, - key, 0); + mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, + pid, qid, 0); txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index c1e6f7d1660c..bb95fdda0eba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1905,8 +1905,9 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, } buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE; - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON); + memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } @@ -2016,8 +2017,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE; - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, - changed); + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed); memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 24572dd55fe0..569d9f6ee1d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -471,8 +471,9 @@ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band); void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, struct ieee80211_vif *vif, bool enable); void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, u32 changed); + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed); void mt7996_mac_set_timing(struct mt7996_phy *phy); int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -- cgit From c04ab57dab559c519bb882995beeb6d95a0a21d3 Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Fri, 3 Mar 2023 16:35:54 +0800 Subject: wifi: mt76: mt7996: remove unused eeprom band selection Tri-band chipsets support one band on each a-die, so remove the unused definition of eeprom band selection. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c | 4 ---- drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c index 2e48c5a40f81..544b6c6f1ea3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c @@ -138,10 +138,6 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy) case MT_EE_BAND_SEL_6GHZ: phy->mt76->cap.has_6ghz = true; break; - case MT_EE_BAND_SEL_5GHZ_6GHZ: - phy->mt76->cap.has_5ghz = true; - phy->mt76->cap.has_6ghz = true; - break; default: ret = -EINVAL; break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h index 8da599e0abea..5571881f639b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h @@ -46,7 +46,6 @@ enum mt7996_eeprom_band { MT_EE_BAND_SEL_2GHZ, MT_EE_BAND_SEL_5GHZ, MT_EE_BAND_SEL_6GHZ, - MT_EE_BAND_SEL_5GHZ_6GHZ, }; static inline int -- cgit From 8b14ce24a0297175bc4ebdf26d45a22b5a33847f Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Fri, 3 Mar 2023 16:35:55 +0800 Subject: wifi: mt76: mt7996: fix pointer calculation in ie countdown event Fix the tail and data pointers. The rxd->len in mt7996_mcu_rxd does not include the length of general rxd. It only includes the length of firmware event rxd. Use skb->length to get the correct length. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index bb95fdda0eba..29ff4c191a3c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -422,7 +422,8 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb) if (hdr->band && dev->mt76.phys[hdr->band]) mphy = dev->mt76.phys[hdr->band]; - tail = skb->data + le16_to_cpu(rxd->len); + tail = skb->data + skb->len; + data += sizeof(struct header); while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) { switch (le16_to_cpu(tlv->tag)) { case UNI_EVENT_IE_COUNTDOWN_CSA: -- cgit From 4e029000fc9f503f01fb91f19d341e65bcc6c3c2 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Fri, 3 Mar 2023 16:35:56 +0800 Subject: wifi: mt76: mt7996: init mpdu density cap Init mpdu density based on the hardware capability to prevent rx drop. Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 946da93eed32..de94e151c47b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -196,10 +196,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) hw->max_tx_fragments = 4; - if (phy->mt76->cap.has_2ghz) + if (phy->mt76->cap.has_2ghz) { phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; + phy->mt76->sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_2; + } if (phy->mt76->cap.has_5ghz) { phy->mt76->sband_5g.sband.ht_cap.cap |= @@ -211,6 +214,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + phy->mt76->sband_5g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_1; } mt76_set_stream_caps(phy->mt76, true); @@ -689,7 +694,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; - cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2, + cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5, IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | -- cgit From 6784b1785e214b0df43a6c9c37495b39c7473223 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Fri, 3 Mar 2023 16:35:57 +0800 Subject: wifi: mt76: mt7996: remove mt7996_mcu_set_pm() Currently using BSS_INFO_PS command will sometimes cause packet drop in hw rx queue. Temporarily remove this function until finding the cause. Signed-off-by: Peter Chiu Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 8 ------- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 26 ---------------------- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 - 3 files changed, 35 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 9d67fcaf2428..33e76a97f46b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -52,10 +52,6 @@ static int mt7996_start(struct ieee80211_hw *hw) set_bit(MT76_STATE_RUNNING, &phy->mt76->state); - ieee80211_iterate_interfaces(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7996_mcu_set_pm, dev->mt76.hw); - ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, MT7996_WATCHDOG_TIME); @@ -79,10 +75,6 @@ static void mt7996_stop(struct ieee80211_hw *hw) clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); - ieee80211_iterate_interfaces(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7996_mcu_set_pm, dev->mt76.hw); - mutex_unlock(&dev->mt76.mutex); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 29ff4c191a3c..2a66ac546513 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -3478,32 +3478,6 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, &req, sizeof(req), true); } -void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ -#define EXIT_PM_STATE 0 -#define ENTER_PM_STATE 1 - struct ieee80211_hw *hw = priv; - struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct bss_power_save *ps; - struct sk_buff *skb; - struct tlv *tlv; - bool running = test_bit(MT76_STATE_RUNNING, &phy->mt76->state); - - skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, - MT7996_BSS_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return; - - tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PS, sizeof(*ps)); - ps = (struct bss_power_save *)tlv; - ps->profile = running ? EXIT_PM_STATE : ENTER_PM_STATE; - - mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); -} - int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 569d9f6ee1d0..5463ce77a1a0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -416,7 +416,6 @@ int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev, int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, const struct mt7996_dfs_pattern *pattern); int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable); -void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif); int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val); int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch); int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, -- cgit From 72fc0df3006ce5c109f9c68f0724e44c47b4ec7b Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Fri, 3 Mar 2023 16:35:58 +0800 Subject: wifi: mt76: mt7996: fix eeprom tx path bitfields Swap the tx path bitfields of band1 and band2 to read correct setting. Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") Signed-off-by: StanleyYP Wang Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h index 5571881f639b..0c749774f6b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h @@ -31,11 +31,11 @@ enum mt7996_eeprom_field { #define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0) #define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3) -#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(5, 3) -#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(2, 0) +#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0) +#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3) #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3) -#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(5, 3) -#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(2, 0) +#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0) +#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3) #define MT_EE_RATE_DELTA_MASK GENMASK(5, 0) #define MT_EE_RATE_DELTA_SIGN BIT(6) -- cgit From a1ec7e6237c58c887e34ce4c02a9ec88ebe1c766 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 6 Mar 2023 18:50:29 +0100 Subject: wifi: mt76: mt7921: introduce mt7921_get_mac80211_ops utility routine Since the fw offload capability check is shared between pci,usb and sdio devices, move it in common init code and reduce code duplication. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 29 ++++++++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 ++- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 19 ++------------ drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 20 ++------------- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 19 ++------------ 5 files changed, 35 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 80c71acfe159..33681fbb2fe8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -169,7 +169,8 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); } -u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm) +static u8 +mt7921_get_offload_capability(struct device *dev, const char *fw_wm) { struct mt7921_fw_features *features = NULL; const struct mt76_connac2_fw_trailer *hdr; @@ -220,7 +221,31 @@ out: return features ? features->data : 0; } -EXPORT_SYMBOL_GPL(mt7921_check_offload_capability); + +struct ieee80211_ops * +mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features) +{ + struct ieee80211_ops *ops; + + ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL); + if (!ops) + return NULL; + + *fw_features = mt7921_get_offload_capability(dev, drv_data); + if (!(*fw_features & MT7921_FW_CAP_CNM)) { + ops->remain_on_channel = NULL; + ops->cancel_remain_on_channel = NULL; + ops->add_chanctx = NULL; + ops->remove_chanctx = NULL; + ops->change_chanctx = NULL; + ops->assign_vif_chanctx = NULL; + ops->unassign_vif_chanctx = NULL; + ops->mgd_prepare_tx = NULL; + ops->mgd_complete_tx = NULL; + } + return ops; +} +EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops); int mt7921_mac_init(struct mt7921_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 1af70dac723b..b1dceeafa54e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -593,5 +593,6 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, enum mt7921_roc_req type, u8 token_id); int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, u8 token_id); -u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm); +struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev, + void *drv_data, u8 *fw_features); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 1a8a54a46dcc..b520cd258170 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -256,7 +256,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .drv_own = mt7921e_mcu_drv_pmctrl, .fw_own = mt7921e_mcu_fw_pmctrl, }; - struct ieee80211_ops *ops; struct mt76_bus_ops *bus_ops; struct mt7921_dev *dev; @@ -285,27 +284,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (mt7921_disable_aspm) mt76_pci_disable_aspm(pdev); - features = mt7921_check_offload_capability(&pdev->dev, (const char *) - id->driver_data); - ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops), - GFP_KERNEL); + ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data, + &features); if (!ops) { ret = -ENOMEM; goto err_free_pci_vec; } - if (!(features & MT7921_FW_CAP_CNM)) { - ops->remain_on_channel = NULL; - ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; - ops->assign_vif_chanctx = NULL; - ops->unassign_vif_chanctx = NULL; - ops->mgd_prepare_tx = NULL; - ops->mgd_complete_tx = NULL; - } - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops); if (!mdev) { ret = -ENOMEM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 8ce4252b8ae7..584921fb25b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -122,33 +122,17 @@ static int mt7921s_probe(struct sdio_func *func, .drv_own = mt7921s_mcu_drv_pmctrl, .fw_own = mt7921s_mcu_fw_pmctrl, }; - struct ieee80211_ops *ops; struct mt7921_dev *dev; struct mt76_dev *mdev; u8 features; int ret; - features = mt7921_check_offload_capability(&func->dev, (const char *) - id->driver_data); - - ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops), - GFP_KERNEL); + ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data, + &features); if (!ops) return -ENOMEM; - if (!(features & MT7921_FW_CAP_CNM)) { - ops->remain_on_channel = NULL; - ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; - ops->assign_vif_chanctx = NULL; - ops->unassign_vif_chanctx = NULL; - ops->mgd_prepare_tx = NULL; - ops->mgd_complete_tx = NULL; - } - mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops); if (!mdev) return -ENOMEM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 8fef09ed29c9..376bf89a70d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -210,27 +210,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf, u8 features; int ret; - features = mt7921_check_offload_capability(&usb_intf->dev, (const char *) - id->driver_info); - ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops), - GFP_KERNEL); + ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info, + &features); if (!ops) return -ENOMEM; - if (!(features & MT7921_FW_CAP_CNM)) { - ops->remain_on_channel = NULL; - ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; - ops->assign_vif_chanctx = NULL; - ops->unassign_vif_chanctx = NULL; - ops->mgd_prepare_tx = NULL; - ops->mgd_complete_tx = NULL; - } - ops->stop = mt7921u_stop; - mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); if (!mdev) return -ENOMEM; -- cgit From a5af1481a85679a9812f728ee5cf64ee7edbe669 Mon Sep 17 00:00:00 2001 From: Neil Chen Date: Tue, 7 Mar 2023 19:22:49 +0800 Subject: wifi: mt76: mt7921: use driver flags rather than mac80211 flags to mcu FIF_* flags from mac80211 is not ABI. mt7921 should not pass it into mcu directly. Remap FIF_* to driver defined flags as mcu command input. Fixes: c222f77fd421 ("wifi: mt76: mt7921: fix rx filter incorrect by drv/fw inconsistent") Signed-off-by: Neil Chen Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index a72964e7a807..f1d537a7705a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -703,10 +703,25 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { +#define MT7921_FILTER_FCSFAIL BIT(2) +#define MT7921_FILTER_CONTROL BIT(5) +#define MT7921_FILTER_OTHER_BSS BIT(6) +#define MT7921_FILTER_ENABLE BIT(31) + struct mt7921_dev *dev = mt7921_hw_dev(hw); + u32 flags = MT7921_FILTER_ENABLE; + +#define MT7921_FILTER(_fif, _type) do { \ + if (*total_flags & (_fif)) \ + flags |= MT7921_FILTER_##_type; \ + } while (0) + + MT7921_FILTER(FIF_FCSFAIL, FCSFAIL); + MT7921_FILTER(FIF_CONTROL, CONTROL); + MT7921_FILTER(FIF_OTHER_BSS, OTHER_BSS); mt7921_mutex_acquire(dev); - mt7921_mcu_set_rxfilter(dev, *total_flags, 0, 0); + mt7921_mcu_set_rxfilter(dev, flags, 0, 0); mt7921_mutex_release(dev); *total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL); -- cgit From 09d4d6da1b65d09414e7bce61459593f3c80ead1 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 29 Mar 2023 14:57:58 -0500 Subject: wifi: mt76: mt7921e: Set memory space enable in PCI_COMMAND if unset When the BIOS has been configured for Fast Boot, systems with mt7921e have non-functional wifi. Turning on Fast boot caused both bus master enable and memory space enable bits in PCI_COMMAND not to get configured. The mt7921 driver already sets bus master enable, but explicitly check and set memory access enable as well to fix this problem. Tested-by: Anson Tsao Signed-off-by: Mario Limonciello Acked-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index b520cd258170..974412b6f76a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -262,6 +262,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, struct mt76_dev *mdev; u8 features; int ret; + u16 cmd; ret = pcim_enable_device(pdev); if (ret) @@ -271,6 +272,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (ret) return ret; + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY)) { + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + } pci_set_master(pdev); ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); -- cgit From ec193b41cc56077e481af4abca2e00e298fcf798 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:33:55 +0200 Subject: wifi: mt76: move irq_tasklet in mt76_dev struct irq_tasklet struct is used by most of the drivers (e.g. mt7915, mt7921, mt7615, mt7663 and mt7996) so move it in common code. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt7615/mmio.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 4 +--- drivers/net/wireless/mediatek/mt76/mt7615/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 3 +-- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 3 +-- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 +-- 15 files changed, 24 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index c3d1313e2f20..6b07b8fafec2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -788,6 +788,7 @@ struct mt76_dev { spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; + struct tasklet_struct irq_tasklet; struct list_head txwi_cache; struct list_head rxwi_cache; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 83173efb56dc..e703400aa551 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -80,14 +80,14 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); return IRQ_HANDLED; } static void mt7615_irq_tasklet(struct tasklet_struct *t) { - struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet); + struct mt7615_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev); u32 mcu_int; @@ -202,7 +202,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, dev = container_of(mdev, struct mt7615_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); - tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet); + tasklet_setup(&mdev->irq_tasklet, mt7615_irq_tasklet); dev->reg_map = map; dev->ops = ops; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 43591b4c1d9a..fbf73f8fda1b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -245,8 +245,6 @@ struct mt7615_dev { }; const struct mt76_bus_ops *bus_ops; - struct tasklet_struct irq_tasklet; - struct mt7615_phy phy; u64 omac_mask; @@ -416,7 +414,7 @@ static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); } static inline bool mt7615_firmware_offload(struct mt7615_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index b808248943ea..9f43e673518b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -94,7 +94,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) mt76_for_each_q_rx(mdev, i) { napi_disable(&mdev->napi[i]); } - tasklet_kill(&dev->irq_tasklet); + tasklet_kill(&mdev->irq_tasklet); mt7615_dma_reset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 0680e002b981..f607eee3fb47 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -122,7 +122,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev) mt7615_tx_token_put(dev); mt7615_dma_cleanup(dev); - tasklet_disable(&dev->irq_tasklet); + tasklet_disable(&dev->mt76.irq_tasklet); mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 71ccefd39cb2..0d52c30ff8fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -1180,7 +1180,7 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev) mt7915_mcu_exit(dev); mt7915_tx_token_put(dev); mt7915_dma_cleanup(dev); - tasklet_disable(&dev->irq_tasklet); + tasklet_disable(&dev->mt76.irq_tasklet); if (is_mt7986(&dev->mt76)) mt7986_wmac_disable(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 97ca55d283fb..3c156c1d589b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1627,7 +1627,7 @@ void mt7915_mac_reset_work(struct work_struct *work) } local_bh_enable(); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 6f0c0e2ae045..49f0410384c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -916,7 +916,7 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev, /* TODO: support 2/4/6/8 MSI-X vectors */ static void mt7915_irq_tasklet(struct tasklet_struct *t) { - struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet); + struct mt7915_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); struct mtk_wed_device *wed = &dev->mt76.mmio.wed; u32 intr, intr1, mask; @@ -1000,7 +1000,7 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); return IRQ_HANDLED; } @@ -1041,7 +1041,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, if (ret) goto error; - tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet); + tasklet_setup(&mdev->irq_tasklet, mt7915_irq_tasklet); return dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index e4016cef9447..530cdcef13c9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -294,7 +294,6 @@ struct mt7915_dev { u32 wfdma_mask; const struct mt76_bus_ops *bus_ops; - struct tasklet_struct irq_tasklet; struct mt7915_phy phy; /* monitor rx chain configured channel */ @@ -567,7 +566,7 @@ static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask) else mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); } static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index b1dceeafa54e..aeb58ad169e6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -287,7 +287,6 @@ struct mt7921_dev { const struct mt76_bus_ops *bus_ops; struct mt7921_phy phy; - struct tasklet_struct irq_tasklet; struct work_struct reset_work; bool hw_full_reset:1; @@ -395,7 +394,7 @@ static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); } static inline u32 diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 974412b6f76a..020ee0e49f78 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -50,7 +50,7 @@ static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); return IRQ_HANDLED; } @@ -122,7 +122,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) mt7921_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); - tasklet_disable(&dev->irq_tasklet); + tasklet_disable(&dev->mt76.irq_tasklet); } static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) @@ -309,7 +309,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, dev->fw_features = features; dev->hif_ops = &mt7921_pcie_ops; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); + tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; @@ -421,7 +421,7 @@ static int mt7921_pci_suspend(struct device *device) mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); synchronize_irq(pdev->irq); - tasklet_kill(&dev->irq_tasklet); + tasklet_kill(&mdev->irq_tasklet); err = mt7921_mcu_fw_pmctrl(dev); if (err) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index de94e151c47b..539e5cc4aa2b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -902,7 +902,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev) mt7996_mcu_exit(dev); mt7996_tx_token_put(dev); mt7996_dma_cleanup(dev); - tasklet_disable(&dev->irq_tasklet); + tasklet_disable(&dev->mt76.irq_tasklet); mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index f1414a448023..18a997a79526 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1883,7 +1883,7 @@ void mt7996_mac_reset_work(struct work_struct *work) } local_bh_enable(); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 902370a2a639..65fa1260e80b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -251,7 +251,7 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev, /* TODO: support 2/4/6/8 MSI-X vectors */ static void mt7996_irq_tasklet(struct tasklet_struct *t) { - struct mt7996_dev *dev = from_tasklet(dev, t, irq_tasklet); + struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); u32 i, intr, mask, intr1; mt76_wr(dev, MT_INT_MASK_CSR, 0); @@ -308,7 +308,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); return IRQ_HANDLED; } @@ -349,7 +349,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, if (ret) goto error; - tasklet_setup(&dev->irq_tasklet, mt7996_irq_tasklet); + tasklet_setup(&mdev->irq_tasklet, mt7996_irq_tasklet); mt76_wr(dev, MT_INT_MASK_CSR, 0); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 5463ce77a1a0..4cdc3cc6102d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -222,7 +222,6 @@ struct mt7996_dev { u32 q_wfdma_mask; const struct mt76_bus_ops *bus_ops; - struct tasklet_struct irq_tasklet; struct mt7996_phy phy; /* monitor rx chain configured channel */ @@ -451,7 +450,7 @@ static inline void mt7996_irq_enable(struct mt7996_dev *dev, u32 mask) else mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - tasklet_schedule(&dev->irq_tasklet); + tasklet_schedule(&dev->mt76.irq_tasklet); } static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask) -- cgit From 4fc441569c9b18eb87d8cd20f197d9d31a84d453 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:33:56 +0200 Subject: wifi: mt76: add mt76_connac_irq_enable utility routine Most of connac based drivers (mt7921, mt7615, mt7663) share the same code to enable interrupts. Move it in mt76_connac module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 5 +++-- drivers/net/wireless/mediatek/mt76/mt7615/mmio.c | 4 +--- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 7 ------- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 7 ------- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 13 ++++++------- 7 files changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index f1914431ff7f..0ce01ccc5dce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -76,7 +76,8 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); if (napi_complete(napi)) - mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev)); + mt76_connac_irq_enable(&dev->mt76, + mt7615_tx_mcu_int_mask(dev)); mt76_connac_pm_unref(&dev->mphy, &dev->pm); @@ -297,7 +298,7 @@ int mt7615_dma_init(struct mt7615_dev *dev) else mask |= MT_INT_MCU_CMD; - mt7615_irq_enable(dev, mask); + mt76_connac_irq_enable(&dev->mt76, mask); mt7615_dma_start(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index e703400aa551..cb10878dac7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -66,9 +66,7 @@ const u32 mt7663e_reg_map[] = { static void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); + mt76_connac_irq_enable(mdev, MT_INT_RX_DONE(q)); } static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index fbf73f8fda1b..ff910a80a6b4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -410,13 +410,6 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl); -static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) -{ - mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - - tasklet_schedule(&dev->mt76.irq_tasklet); -} - static inline bool mt7615_firmware_offload(struct mt7615_dev *dev) { return dev->fw_ver > MT7615_FIRMWARE_V2; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index b339c50bff20..84974dfe1953 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -279,6 +279,12 @@ static inline u8 mt76_connac_spe_idx(u8 antenna_mask) return ant_to_spe[antenna_mask]; } +static inline void mt76_connac_irq_enable(struct mt76_dev *dev, u32 mask) +{ + mt76_set_irq_mask(dev, 0, 0, mask); + tasklet_schedule(&dev->irq_tasklet); +} + int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm); void mt76_connac_power_save_sched(struct mt76_phy *phy, struct mt76_connac_pm *pm); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index d1f10f6d9adc..7b33881a4b54 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -19,7 +19,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) mt76_connac_tx_cleanup(&dev->mt76); if (napi_complete(napi)) - mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL); + mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL); mt76_connac_pm_unref(&dev->mphy, &dev->pm); return 0; @@ -123,9 +123,9 @@ static int mt7921_dma_enable(struct mt7921_dev *dev) mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); /* enable interrupts for TX/RX rings */ - mt7921_irq_enable(dev, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + mt76_connac_irq_enable(&dev->mt76, + MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index aeb58ad169e6..098230039e9a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -390,13 +390,6 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb); int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, u8 bit_op, u32 bit_map); -static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask) -{ - mt76_set_irq_mask(&dev->mt76, 0, 0, mask); - - tasklet_schedule(&dev->mt76.irq_tasklet); -} - static inline u32 mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 020ee0e49f78..17ba2b4ffec7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -31,14 +31,12 @@ MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support"); static void mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - if (q == MT_RXQ_MAIN) - mt7921_irq_enable(dev, MT_INT_RX_DONE_DATA); + mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA); else if (q == MT_RXQ_MCU_WA) - mt7921_irq_enable(dev, MT_INT_RX_DONE_WM2); + mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2); else - mt7921_irq_enable(dev, MT_INT_RX_DONE_WM); + mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM); } static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) @@ -465,8 +463,9 @@ static int mt7921_pci_resume(struct device *device) /* enable interrupt */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + mt76_connac_irq_enable(&dev->mt76, + MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); /* put dma enabled */ -- cgit From f28c3139a9073a0f3161c4f144440b455124041c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:33:57 +0200 Subject: wifi: mt76: get rid of unused sta_ps callbacks sta_ps callback is just an empty stub for most of the drivers, so get rid of them. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 5 ----- drivers/net/wireless/mediatek/mt76/mt7615/mmio.c | 1 - drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 - drivers/net/wireless/mediatek/mt76/mt7615/sdio.c | 1 - drivers/net/wireless/mediatek/mt76/mt7615/usb.c | 1 - drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 ---- drivers/net/wireless/mediatek/mt76/mt7915/mmio.c | 1 - drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 - drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 ----- drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 - 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 - drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ---- drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 1 - drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 - 17 files changed, 2 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index e53166fcdc9d..467afef98ba2 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1309,7 +1309,8 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) if (ps) set_bit(MT_WCID_FLAG_PS, &wcid->flags); - dev->drv->sta_ps(dev, sta, ps); + if (dev->drv->sta_ps) + dev->drv->sta_ps(dev, sta, ps); if (!ps) clear_bit(MT_WCID_FLAG_PS, &wcid->flags); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index ce216bad3b73..d90378a30d15 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -655,11 +655,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) return 0; } -void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) -{ -} -EXPORT_SYMBOL_GPL(mt7615_sta_ps); - static u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, struct mt76_phy *mphy, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index cb10878dac7e..ac036a072439 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -179,7 +179,6 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, .rx_check = mt7615_rx_check, .rx_skb = mt7615_queue_rx_skb, .rx_poll_complete = mt7615_rx_poll_complete, - .sta_ps = mt7615_sta_ps, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index ff910a80a6b4..932cdad7e7d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -511,7 +511,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev); bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); -void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 304212f5f8da..fc547a0031ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -84,7 +84,6 @@ static int mt7663s_probe(struct sdio_func *func, .tx_status_data = mt7663_usb_sdio_tx_status_data, .rx_skb = mt7615_queue_rx_skb, .rx_check = mt7615_rx_check, - .sta_ps = mt7615_sta_ps, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index f2d651d7adff..04963b9f7498 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -120,7 +120,6 @@ static int mt7663u_probe(struct usb_interface *usb_intf, .tx_status_data = mt7663_usb_sdio_tx_status_data, .rx_skb = mt7615_queue_rx_skb, .rx_check = mt7615_rx_check, - .sta_ps = mt7615_sta_ps, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 3c156c1d589b..7df8d95fc3fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -73,10 +73,6 @@ static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev, return &sta->vif->sta.wcid; } -void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) -{ -} - bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 49f0410384c0..45f3558bf31c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -1022,7 +1022,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, .rx_skb = mt7915_queue_rx_skb, .rx_check = mt7915_rx_check, .rx_poll_complete = mt7915_rx_poll_complete, - .sta_ps = mt7915_sta_ps, .sta_add = mt7915_mac_sta_add, .sta_remove = mt7915_mac_sta_remove, .update_survey = mt7915_update_channel, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 530cdcef13c9..b3ead3530740 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -616,7 +616,6 @@ void mt7915_tx_token_put(struct mt7915_dev *dev); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len); -void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); void mt7915_stats_work(struct work_struct *work); int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force); int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 557c20190c2b..2eeea43f6bf6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -32,11 +32,6 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, return &sta->vif->sta.wcid; } -void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) -{ -} -EXPORT_SYMBOL_GPL(mt7921_sta_ps); - bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 098230039e9a..f3155d45a774 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -470,7 +470,6 @@ void mt7921_tx_token_put(struct mt7921_dev *dev); bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); -void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); void mt7921_stats_work(struct work_struct *work); void mt7921_set_stream_he_caps(struct mt7921_phy *phy); void mt7921_update_channel(struct mt76_phy *mphy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 17ba2b4ffec7..35ea76c796a3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -241,7 +241,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .rx_check = mt7921_rx_check, .rx_skb = mt7921_queue_rx_skb, .rx_poll_complete = mt7921_rx_poll_complete, - .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index 584921fb25b5..fe396f195dd7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -99,7 +99,6 @@ static int mt7921s_probe(struct sdio_func *func, .tx_status_data = mt7921_usb_sdio_tx_status_data, .rx_skb = mt7921_queue_rx_skb, .rx_check = mt7921_rx_check, - .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 376bf89a70d8..014476f8ad53 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -183,7 +183,6 @@ static int mt7921u_probe(struct usb_interface *usb_intf, .tx_status_data = mt7921_usb_sdio_tx_status_data, .rx_skb = mt7921_queue_rx_skb, .rx_check = mt7921_rx_check, - .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 18a997a79526..6ce75243e40d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -78,10 +78,6 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, return &sta->vif->sta.wcid; } -void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) -{ -} - bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 65fa1260e80b..fc77641ce7bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -330,7 +330,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, .rx_skb = mt7996_queue_rx_skb, .rx_check = mt7996_rx_check, .rx_poll_complete = mt7996_rx_poll_complete, - .sta_ps = mt7996_sta_ps, .sta_add = mt7996_mac_sta_add, .sta_remove = mt7996_mac_sta_remove, .update_survey = mt7996_update_channel, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 4cdc3cc6102d..dc77fa4e351e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -495,7 +495,6 @@ void mt7996_tx_token_put(struct mt7996_dev *dev); void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len); -void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); void mt7996_stats_work(struct work_struct *work); int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force); int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy); -- cgit From 6a8b899df1562a46a8c55cebc7d35508a24300d3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:33:58 +0200 Subject: wifi: mt76: add mt76_connac_gen_ppe_thresh utility routine gen_ppe_thresh routine is shared between mt7615, mt7915, mt7921 and mt7996 so move it in mt76_connac module. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 1 + .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 21 ++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 23 +--------------------- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 23 +--------------------- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 23 +--------------------- 5 files changed, 25 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 84974dfe1953..fc8e999a431a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -359,6 +359,7 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm) mutex_unlock(&dev->mutex); } +void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss); int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, int ring_base, u32 flags); void mt76_connac_write_hw_txp(struct mt76_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index 8d316d3aab8f..bd4ce2c7742d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -9,6 +9,27 @@ #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ IEEE80211_RADIOTAP_HE_##f) +void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss) +{ + static const u8 ppet16_ppet8_ru3_ru0[] = { 0x1c, 0xc7, 0x71 }; + u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ + + he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | + FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, + ru_bit_mask); + + ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * + nss * hweight8(ru_bit_mask) * 2; + ppet_size = DIV_ROUND_UP(ppet_bits, 8); + + for (i = 0; i < ppet_size - 1; i++) + he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; + + he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & + (0xff >> (8 - (ppet_bits - 1) % 8)); +} +EXPORT_SYMBOL_GPL(mt76_connac_gen_ppe_thresh); + int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm) { struct mt76_dev *dev = phy->dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 0d52c30ff8fd..538ec0f8e630 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -931,27 +931,6 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy, } } -static void -mt7915_gen_ppe_thresh(u8 *he_ppet, int nss) -{ - u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; - - he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | - FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, - ru_bit_mask); - - ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * - nss * hweight8(ru_bit_mask) * 2; - ppet_size = DIV_ROUND_UP(ppet_bits, 8); - - for (i = 0; i < ppet_size - 1; i++) - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; - - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & - (0xff >> (8 - (ppet_bits - 1) % 8)); -} - static int mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) @@ -1101,7 +1080,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index f1d537a7705a..0c9a472bc81a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -9,27 +9,6 @@ #include "mt7921.h" #include "mcu.h" -static void -mt7921_gen_ppe_thresh(u8 *he_ppet, int nss) -{ - u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; - - he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | - FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, - ru_bit_mask); - - ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * - nss * hweight8(ru_bit_mask) * 2; - ppet_size = DIV_ROUND_UP(ppet_bits, 8); - - for (i = 0; i < ppet_size - 1; i++) - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; - - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & - (0xff >> (8 - (ppet_bits - 1) % 8)); -} - static int mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) @@ -168,7 +147,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt7921_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 539e5cc4aa2b..ddea5f48816d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -557,27 +557,6 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, elem->phy_cap_info[7] |= c; } -static void -mt7996_gen_ppe_thresh(u8 *he_ppet, int nss) -{ - u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; - - he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | - FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, - ru_bit_mask); - - ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * - nss * hweight8(ru_bit_mask) * 2; - ppet_size = DIV_ROUND_UP(ppet_bits, 8); - - for (i = 0; i < ppet_size - 1; i++) - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; - - he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & - (0xff >> (8 - (ppet_bits - 1) % 8)); -} - static void mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data, @@ -683,7 +662,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, -- cgit From 50cc972dde9647e43e3c1e64a41e0553e92e6a37 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:33:59 +0200 Subject: wifi: mt76: mt7921: get rid of eeprom.h eeprom.h is mostly empty for mt7921, so get rid of it. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7921/debugfs.c | 1 - drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h | 30 ---------------------- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 1 - drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 1 - drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 11 ++++++++ 5 files changed, 11 insertions(+), 33 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 29d8883268f6..d6b6edba2fec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -2,7 +2,6 @@ /* Copyright (C) 2020 MediaTek Inc. */ #include "mt7921.h" -#include "eeprom.h" static int mt7921_reg_set(void *data, u64 val) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h deleted file mode 100644 index 4b647278eb30..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* Copyright (C) 2020 MediaTek Inc. */ - -#ifndef __MT7921_EEPROM_H -#define __MT7921_EEPROM_H - -#include "mt7921.h" - -enum mt7921_eeprom_field { - MT_EE_CHIP_ID = 0x000, - MT_EE_VERSION = 0x002, - MT_EE_MAC_ADDR = 0x004, - MT_EE_WIFI_CONF = 0x07c, - MT_EE_HW_TYPE = 0x55b, - __MT_EE_MAX = 0x9ff -}; - -#define MT_EE_WIFI_CONF_TX_MASK BIT(0) -#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2) - -#define MT_EE_HW_TYPE_ENCAP BIT(0) - -enum mt7921_eeprom_band { - MT_EE_NA, - MT_EE_5GHZ, - MT_EE_2GHZ, - MT_EE_DUAL_BAND, -}; - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 33681fbb2fe8..f419f908dda2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -6,7 +6,6 @@ #include "mt7921.h" #include "mac.h" #include "mcu.h" -#include "eeprom.h" static const struct ieee80211_iface_limit if_limits[] = { { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index c5e7ad06f877..601d5aadb4f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -5,7 +5,6 @@ #include #include "mt7921.h" #include "mt7921_trace.h" -#include "eeprom.h" #include "mcu.h" #include "mac.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index f3155d45a774..149acb1662d5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -266,6 +266,17 @@ struct mt7921_phy { bool roc_grant; }; +enum mt7921_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, + MT_EE_WIFI_CONF = 0x07c, + MT_EE_HW_TYPE = 0x55b, + __MT_EE_MAX = 0x9ff +}; + +#define MT_EE_HW_TYPE_ENCAP BIT(0) + #define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) #define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev)) #define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) -- cgit From 140efef36a91c1d7fad7f89c375fba8df1e4459f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Apr 2023 12:34:00 +0200 Subject: wifi: mt76: move shared mac definitions in mt76_connac2_mac.h Move some mac shared definitions between mt7996, mt7921 and mt7915 in mt76_connac2_mac.h. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.h | 12 ----- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 14 ++++++ .../net/wireless/mediatek/mt76/mt76_connac2_mac.h | 22 +++++++++ drivers/net/wireless/mediatek/mt76/mt7915/mac.h | 33 +------------- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 13 +++++- drivers/net/wireless/mediatek/mt76/mt7921/mac.h | 53 ---------------------- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/pci_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/sdio_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/sdio_mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/usb_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 12 ----- 17 files changed, 59 insertions(+), 120 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mac.h diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 880c9f74a7f1..d08fbe64c262 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -19,18 +19,6 @@ #define MT_RXD0_NORMAL_GROUP_3 BIT(27) #define MT_RXD0_NORMAL_GROUP_4 BIT(28) -enum rx_pkt_type { - PKT_TYPE_TXS, - PKT_TYPE_TXRXV, - PKT_TYPE_NORMAL, - PKT_TYPE_RX_DUP_RFB, - PKT_TYPE_RX_TMR, - PKT_TYPE_RETRIEVE, - PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT, - PKT_TYPE_NORMAL_MCU, -}; - #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) #define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) #define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index fc8e999a431a..15653b274f83 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -6,6 +6,20 @@ #include "mt76.h" +enum rx_pkt_type { + PKT_TYPE_TXS, + PKT_TYPE_TXRXV, + PKT_TYPE_NORMAL, + PKT_TYPE_RX_DUP_RFB, + PKT_TYPE_RX_TMR, + PKT_TYPE_RETRIEVE, + PKT_TYPE_TXRX_NOTIFY, + PKT_TYPE_RX_EVENT, + PKT_TYPE_NORMAL_MCU, + PKT_TYPE_RX_FW_MONITOR = 0x0c, + PKT_TYPE_TXRX_NOTIFY_V0 = 0x18, +}; + #define MT76_CONNAC_SCAN_IE_LEN 600 #define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL 10 #define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h index f33171bcd343..a5ec0f631385 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h @@ -32,6 +32,16 @@ enum { MT_LMAC_PSMP0, }; +#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) +#define MT_TX_FREE_WLAN_ID GENMASK(23, 14) +#define MT_TX_FREE_LATENCY GENMASK(12, 0) +/* 0: success, others: dropped */ +#define MT_TX_FREE_STATUS GENMASK(14, 13) +#define MT_TX_FREE_MSDU_ID GENMASK(30, 16) +#define MT_TX_FREE_PAIR BIT(31) +/* will support this field in further revision */ +#define MT_TX_FREE_RATE GENMASK(13, 0) + #define MT_TXD0_Q_IDX GENMASK(31, 25) #define MT_TXD0_PKT_FMT GENMASK(24, 23) #define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) @@ -166,6 +176,15 @@ enum { #define MT_TXS7_MPDU_RETRY_CNT GENMASK(31, 23) +/* RXD DW0 */ +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_FLAG GENMASK(19, 16) +#define MT_RXD0_PKT_TYPE GENMASK(31, 27) + +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) + /* RXD DW1 */ #define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0) #define MT_RXD1_NORMAL_GROUP_1 BIT(11) @@ -308,6 +327,9 @@ enum { #define MT_CRXV_FOE_HI GENMASK(6, 0) #define MT_CRXV_FOE_SHIFT 13 +#define MT_CT_PARSE_LEN 72 +#define MT_CT_DMA_BUF_NUM 2 + #define MT_CT_INFO_APPLY_TXD BIT(0) #define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) #define MT_CT_INFO_MGMT_FRAME BIT(2) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 6fa9c79f3e5f..ce94f87e2042 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -6,43 +6,12 @@ #include "../mt76_connac2_mac.h" -#define MT_CT_PARSE_LEN 72 -#define MT_CT_DMA_BUF_NUM 2 - -#define MT_RXD0_LENGTH GENMASK(15, 0) -#define MT_RXD0_PKT_TYPE GENMASK(31, 27) - -#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) -#define MT_RXD0_NORMAL_IP_SUM BIT(23) -#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) - -enum rx_pkt_type { - PKT_TYPE_TXS, - PKT_TYPE_TXRXV, - PKT_TYPE_NORMAL, - PKT_TYPE_RX_DUP_RFB, - PKT_TYPE_RX_TMR, - PKT_TYPE_RETRIEVE, - PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT, - PKT_TYPE_RX_FW_MONITOR = 0x0c, - PKT_TYPE_TXRX_NOTIFY_V0 = 0x18, -}; - #define MT_TX_FREE_VER GENMASK(18, 16) -#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) -#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) -#define MT_TX_FREE_WLAN_ID GENMASK(23, 14) -#define MT_TX_FREE_LATENCY GENMASK(12, 0) +#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) /* 0: success, others: dropped */ -#define MT_TX_FREE_MSDU_ID GENMASK(30, 16) -#define MT_TX_FREE_PAIR BIT(31) #define MT_TX_FREE_MPDU_HEADER BIT(30) #define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0) -/* will support this field in further revision */ -#define MT_TX_FREE_RATE GENMASK(13, 0) - #define MT_TXS5_F0_FINAL_MPDU BIT(31) #define MT_TXS5_F0_QOS BIT(30) #define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 7b33881a4b54..1d85c0c10049 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -3,7 +3,7 @@ #include "mt7921.h" #include "../dma.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" static int mt7921_poll_tx(struct napi_struct *napi, int budget) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index f419f908dda2..e5fdf2df8c36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -4,7 +4,7 @@ #include #include #include "mt7921.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "mcu.h" static const struct ieee80211_iface_limit if_limits[] = { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 2eeea43f6bf6..1675bf520481 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -6,9 +6,20 @@ #include #include "mt7921.h" #include "../dma.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "mcu.h" +#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7 +#define MT_WTBL_TXRX_RATE_G2_HE 24 +#define MT_WTBL_TXRX_RATE_G2 12 + +#define MT_WTBL_AC0_CTT_OFFSET 20 + +static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) +{ + return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; +} + static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, u16 idx, bool unicast) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h deleted file mode 100644 index 8afec600364f..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* Copyright (C) 2020 MediaTek Inc. */ - -#ifndef __MT7921_MAC_H -#define __MT7921_MAC_H - -#include "../mt76_connac2_mac.h" - -#define MT_CT_PARSE_LEN 72 -#define MT_CT_DMA_BUF_NUM 2 - -#define MT_RXD0_LENGTH GENMASK(15, 0) -#define MT_RXD0_PKT_FLAG GENMASK(19, 16) -#define MT_RXD0_PKT_TYPE GENMASK(31, 27) - -#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) -#define MT_RXD0_NORMAL_IP_SUM BIT(23) -#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) - -enum rx_pkt_type { - PKT_TYPE_TXS, - PKT_TYPE_TXRXV, - PKT_TYPE_NORMAL, - PKT_TYPE_RX_DUP_RFB, - PKT_TYPE_RX_TMR, - PKT_TYPE_RETRIEVE, - PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT, - PKT_TYPE_NORMAL_MCU, -}; - -#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) -#define MT_TX_FREE_WLAN_ID GENMASK(23, 14) -#define MT_TX_FREE_LATENCY GENMASK(12, 0) -/* 0: success, others: dropped */ -#define MT_TX_FREE_STATUS GENMASK(14, 13) -#define MT_TX_FREE_MSDU_ID GENMASK(30, 16) -#define MT_TX_FREE_PAIR BIT(31) -/* will support this field in further revision */ -#define MT_TX_FREE_RATE GENMASK(13, 0) - -#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7 -#define MT_WTBL_TXRX_RATE_G2_HE 24 -#define MT_WTBL_TXRX_RATE_G2 12 - -#define MT_WTBL_AC0_CTT_OFFSET 20 - -static inline u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) -{ - return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; -} - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 601d5aadb4f4..04925e66f15b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -6,7 +6,7 @@ #include "mt7921.h" #include "mt7921_trace.h" #include "mcu.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #define MT_STA_BFER BIT(0) #define MT_STA_BFEE BIT(1) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 35ea76c796a3..40bea17cc440 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -8,7 +8,7 @@ #include #include "mt7921.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "mcu.h" #include "../trace.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 8dd60408b117..6053a2556c20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -3,7 +3,7 @@ #include "mt7921.h" #include "../dma.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index fe396f195dd7..a77a309c0d60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -13,7 +13,7 @@ #include "mt7921.h" #include "../sdio.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "mcu.h" static const struct sdio_device_id mt7921s_table[] = { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 1b3adb3d91e8..cff9925c41ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -4,7 +4,7 @@ #include #include #include "mt7921.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "../sdio.h" static void mt7921s_enable_irq(struct mt76_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 5c1489766d9f..177679ce1c80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -8,7 +8,7 @@ #include "mt7921.h" #include "../sdio.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" #include "mcu.h" #include "regs.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 014476f8ad53..46118421ef28 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -10,7 +10,7 @@ #include "mt7921.h" #include "mcu.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" static const struct usb_device_id mt7921u_device_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c index efbd3954c883..50eb6e7fd6b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -10,7 +10,7 @@ #include "mt7921.h" #include "mcu.h" -#include "mac.h" +#include "../mt76_connac2_mac.h" static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index 2cc218f735d8..0318e16fcfab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -20,18 +20,6 @@ #define MT_RXD0_SW_PKT_TYPE_MAP 0x380F #define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801 -enum rx_pkt_type { - PKT_TYPE_TXS, - PKT_TYPE_TXRXV, - PKT_TYPE_NORMAL, - PKT_TYPE_RX_DUP_RFB, - PKT_TYPE_RX_TMR, - PKT_TYPE_RETRIEVE, - PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT, - PKT_TYPE_RX_FW_MONITOR = 0x0c, -}; - /* RXD DW1 */ #define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0) #define MT_RXD1_NORMAL_GROUP_1 BIT(16) -- cgit From c397fc1e6365a2a9e5540a85b2c1d4ea412aa0e2 Mon Sep 17 00:00:00 2001 From: Quan Zhou Date: Sat, 18 Mar 2023 15:41:12 +0800 Subject: wifi: mt76: mt7921e: fix probe timeout after reboot In system warm reboot scene, due to the polling timeout(now 1000us) is too short to wait dma idle in time, it may make driver probe fail with error code -ETIMEDOUT. Meanwhile, we also found the dma may take around 70ms to enter idle state. Change the polling idle timeout to 100ms to avoid the probabilistic probe fail. Tested pass with 5000 times warm reboot on x86 platform. [4.477496] pci 0000:01:00.0: attach allowed to drvr mt7921e [internal device] [4.478306] mt7921e 0000:01:00.0: ASIC revision: 79610010 [4.480063] mt7921e: probe of 0000:01:00.0 failed with error -110 Fixes: 0a1059d0f060 ("mt76: mt7921: move mt7921_dma_reset in dma.c") Signed-off-by: Quan Zhou Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 1d85c0c10049..28207172c4ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -90,9 +90,9 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - if (!mt76_poll(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) + if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) return -ETIMEDOUT; return 0; -- cgit From 23792cedaff02351b57bddd8957fc917fa88f2e0 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Thu, 23 Mar 2023 21:26:12 +0800 Subject: wifi: mt76: fix 6GHz high channel not be scanned mt76 scan command only support 64 channels currently. If the channel count is larger than 64(for 2+5+6GHz), some channels will not be scanned. Hence change the scan type to full channel scan in case of the command cannot include proper list for chip. Fixes: 399090ef9605 ("mt76: mt76_connac: move hw_scan and sched_scan routine in mt76_connac_mcu module") Reported-by: Ben Greear Tested-by: Isaac Konikoff Signed-off-by: Ming Yen Hsieh Signed-off-by: Deren Wu Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 008ece1b16f8..cb27885b5da7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1678,8 +1678,16 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req->channel_min_dwell_time = cpu_to_le16(duration); req->channel_dwell_time = cpu_to_le16(duration); - req->channels_num = min_t(u8, sreq->n_channels, 32); - req->ext_channels_num = min_t(u8, ext_channels_num, 32); + if (sreq->n_channels == 0 || sreq->n_channels > 64) { + req->channel_type = 0; + req->channels_num = 0; + req->ext_channels_num = 0; + } else { + req->channel_type = 4; + req->channels_num = min_t(u8, sreq->n_channels, 32); + req->ext_channels_num = min_t(u8, ext_channels_num, 32); + } + for (i = 0; i < req->channels_num + req->ext_channels_num; i++) { if (i >= 32) chan = &req->ext_channels[i - 32]; @@ -1699,7 +1707,6 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, } chan->channel_num = scan_list[i]->hw_value; } - req->channel_type = sreq->n_channels ? 4 : 0; if (sreq->ie_len > 0) { memcpy(req->ies, sreq->ie, sreq->ie_len); -- cgit From 268079896060b224cb0a42eb6ca0d0a0836c46bb Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 31 Mar 2023 06:10:17 +0800 Subject: wifi: mt76: mt7915: drop redundant prefix of mt7915_txpower_puts() Just a cosmetic patch to drop redundant prefix for txpower ouput text. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7915/debugfs.c | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 5a46813a59ea..879884ead660 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -958,10 +958,10 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data) DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues); -#define mt7915_txpower_puts(prefix, rate) \ +#define mt7915_txpower_puts(rate) \ ({ \ - len += scnprintf(buf + len, sz - len, "%-16s:", #prefix " (tmac)"); \ - for (i = 0; i < mt7915_sku_group_len[rate]; i++, offs++) \ + len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \ + for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \ len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \ len += scnprintf(buf + len, sz - len, "\n"); \ }) @@ -1004,41 +1004,41 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, phy != &dev->phy, phy->mt76->chandef.chan->hw_value); len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n", " ", "1m", "2m", "5m", "11m"); - mt7915_txpower_puts(CCK, SKU_CCK); + mt7915_txpower_puts(CCK); len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m", "54m"); - mt7915_txpower_puts(OFDM, SKU_OFDM); + mt7915_txpower_puts(OFDM); len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7"); - mt7915_txpower_puts(HT20, SKU_HT_BW20); + mt7915_txpower_puts(HT_BW20); len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7", "mcs32"); - mt7915_txpower_puts(HT40, SKU_HT_BW40); + mt7915_txpower_puts(HT_BW40); len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); - mt7915_txpower_puts(VHT20, SKU_VHT_BW20); - mt7915_txpower_puts(VHT40, SKU_VHT_BW40); - mt7915_txpower_puts(VHT80, SKU_VHT_BW80); - mt7915_txpower_puts(VHT160, SKU_VHT_BW160); - mt7915_txpower_puts(HE26, SKU_HE_RU26); - mt7915_txpower_puts(HE52, SKU_HE_RU52); - mt7915_txpower_puts(HE106, SKU_HE_RU106); - mt7915_txpower_puts(HE242, SKU_HE_RU242); - mt7915_txpower_puts(HE484, SKU_HE_RU484); - mt7915_txpower_puts(HE996, SKU_HE_RU996); - mt7915_txpower_puts(HE996x2, SKU_HE_RU2x996); + mt7915_txpower_puts(VHT_BW20); + mt7915_txpower_puts(VHT_BW40); + mt7915_txpower_puts(VHT_BW80); + mt7915_txpower_puts(VHT_BW160); + mt7915_txpower_puts(HE_RU26); + mt7915_txpower_puts(HE_RU52); + mt7915_txpower_puts(HE_RU106); + mt7915_txpower_puts(HE_RU242); + mt7915_txpower_puts(HE_RU484); + mt7915_txpower_puts(HE_RU996); + mt7915_txpower_puts(HE_RU2x996); reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) : MT_WF_PHY_TPC_CTRL_STAT_MT7916(band); -- cgit From 03eb52dd78cab08f13925aeec8315fbdbcba3253 Mon Sep 17 00:00:00 2001 From: Reese Russell Date: Tue, 4 Apr 2023 00:35:12 -0700 Subject: wifi: mt76: mt7921: add Netgear AXE3000 (A8000) support Issue: Though the Netgear AXE3000 (A8000) is based on the mt7921 chipset because of the unique USB VID:PID combination this device does not initialize/register. Thus making it not plug and play. Fix: Adds support for the Netgear AXE3000 (A8000) based on the Mediatek mt7921au chipset. The method of action is adding the USD VID/PID pair to the mt7921u_device_table[] array. Notes: A retail sample of the Netgear AXE3000 (A8000) yeilds the following from lsusb D 0846:9060 NetGear, Inc. Wireless_Device. This pair 0846:9060 VID:PID has been reported by other users on Github. Signed-off-by: Reese Russell Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 46118421ef28..9b05e4577cdf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -18,6 +18,9 @@ static const struct usb_device_id mt7921u_device_table[] = { /* Comfast CF-952AX */ { USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM }, + /* Netgear, Inc. [A8000,AXE3000] */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM }, { }, }; -- cgit From 2631c5b6ef9d7c6707e020def6947464c8aa6f92 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 6 Apr 2023 08:32:12 -0600 Subject: wifi: mt76: Replace zero-length array with flexible-array member Zero-length arrays are deprecated [1] and have to be replaced by C99 flexible-array members. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help to make progress towards globally enabling -fstrict-flex-arrays=3 [2] Link: https://github.com/KSPP/linux/issues/78 [1] Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [2] Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 40a99e0caded..9dbfe26e87e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -127,7 +127,7 @@ struct mt76_connac2_mcu_rxd { u8 rsv1[2]; u8 s2d_index; - u8 tlv[0]; + u8 tlv[]; }; struct mt76_connac2_patch_hdr { -- cgit From 6d6793cef6a491b8f6db5f40ef3334411293da32 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 17 Mar 2023 14:56:39 -0600 Subject: wifi: mt76: mt7921: Replace fake flex-arrays with flexible-array members MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero-length arrays as fake flexible arrays are deprecated and we are moving towards adopting C99 flexible-array members instead. Address the following warnings found with GCC-13 and -fstrict-flex-arrays=3 enabled: drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c:266:25: warning: array subscript 0 is outside array bounds of ‘struct mt7921_asar_dyn_limit_v2[0]’ [-Warray-bounds=] drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c:263:25: warning: array subscript 0 is outside array bounds of ‘struct mt7921_asar_dyn_limit[0]’ [-Warray-bounds=] drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c:223:28: warning: array subscript is outside array bounds of ‘struct mt7921_asar_geo_limit_v2[0]’ [-Warray-bounds=] drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c:220:28: warning: array subscript is outside array bounds of ‘struct mt7921_asar_geo_limit[0]’ [-Warray-bounds=] drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c:334:37: warning: array subscript i is outside array bounds of ‘u8[0]’ {aka ‘unsigned char[]’} [-Warray-bounds=] Notice that the DECLARE_FLEX_ARRAY() helper allows for flexible-array members in unions. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/21 Link: https://github.com/KSPP/linux/issues/272 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h index 35268b0890ad..6f2c4a572572 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h @@ -24,7 +24,7 @@ struct mt7921_asar_dyn { u8 names[4]; u8 enable; u8 nr_tbl; - struct mt7921_asar_dyn_limit tbl[0]; + DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl); } __packed; struct mt7921_asar_dyn_limit_v2 { @@ -37,7 +37,7 @@ struct mt7921_asar_dyn_v2 { u8 enable; u8 rsvd; u8 nr_tbl; - struct mt7921_asar_dyn_limit_v2 tbl[0]; + DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl); } __packed; struct mt7921_asar_geo_band { @@ -55,7 +55,7 @@ struct mt7921_asar_geo { u8 names[4]; u8 version; u8 nr_tbl; - struct mt7921_asar_geo_limit tbl[0]; + DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl); } __packed; struct mt7921_asar_geo_limit_v2 { @@ -69,7 +69,7 @@ struct mt7921_asar_geo_v2 { u8 version; u8 rsvd; u8 nr_tbl; - struct mt7921_asar_geo_limit_v2 tbl[0]; + DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl); } __packed; struct mt7921_asar_cl { @@ -85,7 +85,7 @@ struct mt7921_asar_fg { u8 rsvd; u8 nr_flag; u8 rsvd1; - u8 flag[0]; + u8 flag[]; } __packed; struct mt7921_acpi_sar { -- cgit From 1b83d17ccece7db5e0ad4602969c1146f1381c3d Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 8 Mar 2023 05:50:59 +0800 Subject: wifi: mt76: mt7921: enable p2p support Introduce p2p-go/p2p-client support to mt7921 driver CONNECTION_P2P_GC/GO is not supported with the current firmware so we added mt76_dev to mt76_connac_mcu_sta_basic_tlv signature to use CONNECTION_INFRA_STA/AP instead for p2p-client and p2p-go respectively to make it work. Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 10 +++++++--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index eea398c79a98..195fe1094d9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -861,7 +861,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, else mvif->sta_added = true; } - mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry); + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, vif, sta, enable, + new_entry); if (enable && sta) mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0, MT76_STA_INFO_STATE_ASSOC); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index cb27885b5da7..0f0a519f956f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -363,7 +363,7 @@ void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv); -void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, +void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable, bool newly) @@ -394,7 +394,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: - if (vif->p2p) + if (vif->p2p && !is_mt7921(dev)) conn_type = CONNECTION_P2P_GC; else conn_type = CONNECTION_INFRA_STA; @@ -402,7 +402,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, basic->aid = cpu_to_le16(sta->aid); break; case NL80211_IFTYPE_STATION: - if (vif->p2p) + if (vif->p2p && !is_mt7921(dev)) conn_type = CONNECTION_P2P_GO; else conn_type = CONNECTION_INFRA_AP; @@ -1029,7 +1029,7 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy, return PTR_ERR(skb); if (info->sta || !info->offload_fw) - mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, + mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta, info->enable, info->newly); if (info->sta && info->enable) mt76_connac_mcu_sta_tlv(phy, skb, info->sta, diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 9dbfe26e87e0..ac7d5817f345 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1776,7 +1776,7 @@ mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len) int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy); int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif); -void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, +void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable, bool newly); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 7432b1eb396d..9fcb22fa1f97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1654,8 +1654,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, return PTR_ERR(skb); /* starec basic */ - mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, - !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable, + !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); if (!enable) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index e5fdf2df8c36..5955c7c5b91a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -31,11 +31,13 @@ static const struct ieee80211_iface_combination if_comb[] = { static const struct ieee80211_iface_limit if_limits_chanctx[] = { { .max = 2, - .types = BIT(NL80211_IFTYPE_STATION), + .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT) }, { .max = 1, - .types = BIT(NL80211_IFTYPE_AP), + .types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) } }; @@ -99,7 +101,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | WIPHY_FLAG_4ADDR_STATION); wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); wiphy->max_remain_on_channel_duration = 5000; wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_scan_ssids = 4; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 2a66ac546513..016853033c1f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1694,8 +1694,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, return PTR_ERR(skb); /* starec basic */ - mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, - !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable, + !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); if (!enable) goto out; -- cgit From 27015b6fbcca836c6dbf196afc266e068af4aeec Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Wed, 5 Apr 2023 07:24:37 +0800 Subject: wifi: mt76: mt7996: enable full system reset support Add mt7996_reset() and refactor mt7996_mac_reset_work() to support full system recovery. Signed-off-by: Bo Jiao Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/dma.c | 64 +++++ drivers/net/wireless/mediatek/mt76/mt7996/init.c | 11 +- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 284 +++++++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 18 +- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 22 +- drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 7 +- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 17 +- drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 13 +- 8 files changed, 365 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index c09fe4274935..534143465d9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -352,6 +352,70 @@ int mt7996_dma_init(struct mt7996_dev *dev) return 0; } +void mt7996_dma_reset(struct mt7996_dev *dev, bool force) +{ + struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1]; + struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2]; + u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + int i; + + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + if (dev->hif2) + mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + usleep_range(1000, 2000); + + for (i = 0; i < __MT_TXQ_MAX; i++) { + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); + if (phy2) + mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true); + if (phy3) + mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true); + } + + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); + + mt76_tx_status_check(&dev->mt76, true); + + /* reset wfsys */ + if (force) + mt7996_wfsys_reset(dev); + + mt7996_dma_disable(dev, force); + + /* reset hw queues */ + for (i = 0; i < __MT_TXQ_MAX; i++) { + mt76_queue_reset(dev, dev->mphy.q_tx[i]); + if (phy2) + mt76_queue_reset(dev, phy2->q_tx[i]); + if (phy3) + mt76_queue_reset(dev, phy3->q_tx[i]); + } + + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_reset(dev, dev->mt76.q_mcu[i]); + + mt76_for_each_q_rx(&dev->mt76, i) { + mt76_queue_reset(dev, &dev->mt76.q_rx[i]); + } + + mt76_tx_status_check(&dev->mt76, true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_reset(dev, i); + + mt7996_dma_enable(dev); +} + void mt7996_dma_cleanup(struct mt7996_dev *dev) { mt7996_dma_disable(dev, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index ddea5f48816d..6de9a0405b74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -99,9 +99,8 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev, mt7996_led_set_config(led_cdev, 0xff, 0); } -static void -mt7996_init_txpower(struct mt7996_dev *dev, - struct ieee80211_supported_band *sband) +void mt7996_init_txpower(struct mt7996_dev *dev, + struct ieee80211_supported_band *sband) { int i, nss = hweight8(dev->mphy.antenna_mask); int nss_delta = mt76_tx_power_nss_delta(nss); @@ -255,7 +254,7 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band) mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set); } -static void mt7996_mac_init(struct mt7996_dev *dev) +void mt7996_mac_init(struct mt7996_dev *dev) { #define HIF_TXD_V2_1 4 int i; @@ -289,7 +288,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev) mt7996_mac_init_band(dev, i); } -static int mt7996_txbf_init(struct mt7996_dev *dev) +int mt7996_txbf_init(struct mt7996_dev *dev) { int ret; @@ -870,6 +869,8 @@ int mt7996_register_device(struct mt7996_dev *dev) if (ret) return ret; + dev->recovery.hw_init_done = true; + return mt7996_init_debugfs(&dev->phy); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 6ce75243e40d..d526d6f53ace 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1704,7 +1704,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state) bool ret; ret = wait_event_timeout(dev->reset_wait, - (READ_ONCE(dev->reset_state) & state), + (READ_ONCE(dev->recovery.state) & state), MT7996_RESET_TIMEOUT); WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); @@ -1753,68 +1753,207 @@ mt7996_update_beacons(struct mt7996_dev *dev) mt7996_update_vif_beacon, phy3->hw); } -static void -mt7996_dma_reset(struct mt7996_dev *dev) +void mt7996_tx_token_put(struct mt7996_dev *dev) { - struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1]; - struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2]; - u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); - int i; + struct mt76_txwi_cache *txwi; + int id; + + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { + mt7996_txwi_free(dev, txwi, NULL, NULL); + dev->mt76.token_count--; + } + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); +} + +static int +mt7996_mac_restart(struct mt7996_dev *dev) +{ + struct mt7996_phy *phy2, *phy3; + struct mt76_dev *mdev = &dev->mt76; + int i, ret; - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); + phy2 = mt7996_phy2(dev); + phy3 = mt7996_phy3(dev); - if (dev->hif2) - mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); + if (dev->hif2) { + mt76_wr(dev, MT_INT1_MASK_CSR, 0x0); + mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); + } - usleep_range(1000, 2000); + if (dev_is_pci(mdev->dev)) { + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); + if (dev->hif2) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); + } - for (i = 0; i < __MT_TXQ_MAX; i++) { - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - if (phy2) - mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true); - if (phy3) - mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true); + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); + set_bit(MT76_MCU_RESET, &phy2->mt76->state); + } + if (phy3) { + set_bit(MT76_RESET, &phy3->mt76->state); + set_bit(MT76_MCU_RESET, &phy3->mt76->state); } - for (i = 0; i < __MT_MCUQ_MAX; i++) - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (phy2) + mt76_txq_schedule_all(phy2->mt76); + if (phy3) + mt76_txq_schedule_all(phy3->mt76); - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_rx_reset(dev, i); + /* disable all tx/rx napi */ + mt76_worker_disable(&dev->mt76.tx_worker); + mt76_for_each_q_rx(mdev, i) { + if (mdev->q_rx[i].ndesc) + napi_disable(&dev->mt76.napi[i]); + } + napi_disable(&dev->mt76.tx_napi); + + /* token reinit */ + mt7996_tx_token_put(dev); + idr_init(&dev->mt76.token); + + mt7996_dma_reset(dev, true); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + if (mdev->q_rx[i].ndesc) { + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); + } + } + local_bh_enable(); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + + mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); + mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + if (dev->hif2) { + mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask); + mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); + } + if (dev_is_pci(mdev->dev)) { + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + if (dev->hif2) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + } + + /* load firmware */ + ret = mt7996_mcu_init_firmware(dev); + if (ret) + goto out; + + /* set the necessary init items */ + ret = mt7996_mcu_set_eeprom(dev); + if (ret) + goto out; + + mt7996_mac_init(dev); + mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband); + mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband); + ret = mt7996_txbf_init(dev); + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { + ret = mt7996_run(dev->mphy.hw); + if (ret) + goto out; + } - mt76_tx_status_check(&dev->mt76, true); + if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) { + ret = mt7996_run(phy2->mt76->hw); + if (ret) + goto out; + } - /* re-init prefetch settings after reset */ - mt7996_dma_prefetch(dev); + if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) { + ret = mt7996_run(phy3->mt76->hw); + if (ret) + goto out; + } + +out: + /* reset done */ + clear_bit(MT76_RESET, &dev->mphy.state); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); + if (phy3) + clear_bit(MT76_RESET, &phy3->mt76->state); - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + local_bh_disable(); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); + local_bh_enable(); - if (dev->hif2) - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_worker_enable(&dev->mt76.tx_worker); + return ret; } -void mt7996_tx_token_put(struct mt7996_dev *dev) +static void +mt7996_mac_full_reset(struct mt7996_dev *dev) { - struct mt76_txwi_cache *txwi; - int id; + struct mt7996_phy *phy2, *phy3; + int i; - spin_lock_bh(&dev->mt76.token_lock); - idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7996_txwi_free(dev, txwi, NULL, NULL); - dev->mt76.token_count--; + phy2 = mt7996_phy2(dev); + phy3 = mt7996_phy3(dev); + dev->recovery.hw_full_reset = true; + + wake_up(&dev->mt76.mcu.wait); + ieee80211_stop_queues(mt76_hw(dev)); + if (phy2) + ieee80211_stop_queues(phy2->mt76->hw); + if (phy3) + ieee80211_stop_queues(phy3->mt76->hw); + + cancel_delayed_work_sync(&dev->mphy.mac_work); + if (phy2) + cancel_delayed_work_sync(&phy2->mt76->mac_work); + if (phy3) + cancel_delayed_work_sync(&phy3->mt76->mac_work); + + mutex_lock(&dev->mt76.mutex); + for (i = 0; i < 10; i++) { + if (!mt7996_mac_restart(dev)) + break; } - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); + mutex_unlock(&dev->mt76.mutex); + + if (i == 10) + dev_err(dev->mt76.dev, "chip full reset failed\n"); + + ieee80211_restart_hw(mt76_hw(dev)); + if (phy2) + ieee80211_restart_hw(phy2->mt76->hw); + if (phy3) + ieee80211_restart_hw(phy3->mt76->hw); + + ieee80211_wake_queues(mt76_hw(dev)); + if (phy2) + ieee80211_wake_queues(phy2->mt76->hw); + if (phy3) + ieee80211_wake_queues(phy3->mt76->hw); + + dev->recovery.hw_full_reset = false; + ieee80211_queue_delayed_work(mt76_hw(dev), + &dev->mphy.mac_work, + MT7996_WATCHDOG_TIME); + if (phy2) + ieee80211_queue_delayed_work(phy2->mt76->hw, + &phy2->mt76->mac_work, + MT7996_WATCHDOG_TIME); + if (phy3) + ieee80211_queue_delayed_work(phy3->mt76->hw, + &phy3->mt76->mac_work, + MT7996_WATCHDOG_TIME); } -/* system error recovery */ void mt7996_mac_reset_work(struct work_struct *work) { struct mt7996_phy *phy2, *phy3; @@ -1825,9 +1964,36 @@ void mt7996_mac_reset_work(struct work_struct *work) phy2 = mt7996_phy2(dev); phy3 = mt7996_phy3(dev); - if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) + /* chip full reset */ + if (dev->recovery.restart) { + /* disable WA/WM WDT */ + mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA, + MT_MCU_CMD_WDT_MASK); + + if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT) + dev->recovery.wa_reset_count++; + else + dev->recovery.wm_reset_count++; + + mt7996_mac_full_reset(dev); + + /* enable mcu irq */ + mt7996_irq_enable(dev, MT_INT_MCU_CMD); + mt7996_irq_disable(dev, 0); + + /* enable WA/WM WDT */ + mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK); + + dev->recovery.state = MT_MCU_CMD_NORMAL_STATE; + dev->recovery.restart = false; return; + } + if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) + return; + + dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", + wiphy_name(dev->mt76.hw->wiphy)); ieee80211_stop_queues(mt76_hw(dev)); if (phy2) ieee80211_stop_queues(phy2->mt76->hw); @@ -1856,7 +2022,7 @@ void mt7996_mac_reset_work(struct work_struct *work) mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7996_dma_reset(dev); + mt7996_dma_reset(dev, false); mt7996_tx_token_put(dev); idr_init(&dev->mt76.token); @@ -1911,6 +2077,32 @@ void mt7996_mac_reset_work(struct work_struct *work) ieee80211_queue_delayed_work(phy3->mt76->hw, &phy3->mt76->mac_work, MT7996_WATCHDOG_TIME); + dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.", + wiphy_name(dev->mt76.hw->wiphy)); +} + +void mt7996_reset(struct mt7996_dev *dev) +{ + if (!dev->recovery.hw_init_done) + return; + + if (dev->recovery.hw_full_reset) + return; + + /* wm/wa exception: do full recovery */ + if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) { + dev->recovery.restart = true; + dev_info(dev->mt76.dev, + "%s indicated firmware crash, attempting recovery\n", + wiphy_name(dev->mt76.hw->wiphy)); + + mt7996_irq_disable(dev, MT_INT_MCU_CMD); + queue_work(dev->mt76.wq, &dev->reset_work); + return; + } + + queue_work(dev->mt76.wq, &dev->reset_work); + wake_up(&dev->reset_wait); } void mt7996_mac_update_stats(struct mt7996_phy *phy) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 33e76a97f46b..7ddfcf68ebd1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -22,17 +22,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev) return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); } -static int mt7996_start(struct ieee80211_hw *hw) +int mt7996_run(struct ieee80211_hw *hw) { struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_phy *phy = mt7996_hw_phy(hw); bool running; int ret; - flush_work(&dev->init_work); - - mutex_lock(&dev->mt76.mutex); - running = mt7996_dev_running(dev); if (!running) { ret = mt7996_mcu_set_hdr_trans(dev, true); @@ -59,6 +55,18 @@ static int mt7996_start(struct ieee80211_hw *hw) mt7996_mac_reset_counters(phy); out: + return ret; +} + +static int mt7996_start(struct ieee80211_hw *hw) +{ + struct mt7996_dev *dev = mt7996_hw_dev(hw); + int ret; + + flush_work(&dev->init_work); + + mutex_lock(&dev->mt76.mutex); + ret = mt7996_run(hw); mutex_unlock(&dev->mt76.mutex); return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 016853033c1f..7a73f1a474fa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -2425,17 +2425,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev) MCU_WM_UNI_CMD(VOW), true); } -int mt7996_mcu_init(struct mt7996_dev *dev) +int mt7996_mcu_init_firmware(struct mt7996_dev *dev) { - static const struct mt76_mcu_ops mt7996_mcu_ops = { - .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */ - .mcu_skb_send_msg = mt7996_mcu_send_message, - .mcu_parse_response = mt7996_mcu_parse_response, - }; int ret; - dev->mt76.mcu_ops = &mt7996_mcu_ops; - /* force firmware operation mode into normal state, * which should be set before firmware download stage. */ @@ -2476,6 +2469,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev) MCU_WA_PARAM_RED, 0, 0); } +int mt7996_mcu_init(struct mt7996_dev *dev) +{ + static const struct mt76_mcu_ops mt7996_mcu_ops = { + .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */ + .mcu_skb_send_msg = mt7996_mcu_send_message, + .mcu_parse_response = mt7996_mcu_parse_response, + }; + + dev->mt76.mcu_ops = &mt7996_mcu_ops; + + return mt7996_mcu_init_firmware(dev); +} + void mt7996_mcu_exit(struct mt7996_dev *dev) { mt7996_mcu_restart(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index fc77641ce7bf..8d6ab919d086 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -289,10 +289,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) u32 val = mt76_rr(dev, MT_MCU_CMD); mt76_wr(dev, MT_MCU_CMD, val); - if (val & MT_MCU_CMD_ERROR_MASK) { - dev->reset_state = val; - ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); - wake_up(&dev->reset_wait); + if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) { + dev->recovery.state = val; + mt7996_reset(dev); } } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index dc77fa4e351e..1a780167efd0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -236,7 +236,14 @@ struct mt7996_dev { struct work_struct rc_work; struct work_struct reset_work; wait_queue_head_t reset_wait; - u32 reset_state; + struct { + u32 state; + u32 wa_reset_count; + u32 wm_reset_count; + bool hw_full_reset:1; + bool hw_init_done:1; + bool restart:1; + } recovery; struct list_head sta_rc_list; struct list_head sta_poll_list; @@ -369,9 +376,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev, struct ieee80211_channel *chan); s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band); int mt7996_dma_init(struct mt7996_dev *dev); +void mt7996_dma_reset(struct mt7996_dev *dev, bool force); void mt7996_dma_prefetch(struct mt7996_dev *dev); void mt7996_dma_cleanup(struct mt7996_dev *dev); +void mt7996_init_txpower(struct mt7996_dev *dev, + struct ieee80211_supported_band *sband); +int mt7996_txbf_init(struct mt7996_dev *dev); +void mt7996_reset(struct mt7996_dev *dev); +int mt7996_run(struct ieee80211_hw *hw); int mt7996_mcu_init(struct mt7996_dev *dev); +int mt7996_mcu_init_firmware(struct mt7996_dev *dev); int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, struct mt7996_vif *mvif, struct mt7996_twt_flow *flow, @@ -461,6 +475,7 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask) mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } +void mt7996_mac_init(struct mt7996_dev *dev); u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw); bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask); void mt7996_mac_reset_counters(struct mt7996_phy *phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 7a28cae34e34..5ba74b49d65d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -317,6 +317,8 @@ enum base_rev { #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154) #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3) +#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4) + #define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) #define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) @@ -444,6 +446,10 @@ enum base_rev { #define MT_MCU_CMD_NORMAL_STATE BIT(5) #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) +#define MT_MCU_CMD_WA_WDT BIT(31) +#define MT_MCU_CMD_WM_WDT BIT(30) +#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30) + /* l1/l2 remap */ #define MT_HIF_REMAP_L1 0x155024 #define MT_HIF_REMAP_L1_MASK GENMASK(31, 16) @@ -468,7 +474,10 @@ enum base_rev { #define MT_INFRA_MCU_END 0x7c3fffff /* FW MODE SYNC */ -#define MT_SWDEF_MODE 0x9143c +#define MT_SWDEF_BASE 0x00401400 + +#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) +#define MT_SWDEF_MODE MT_SWDEF(0x3c) #define MT_SWDEF_NORMAL_MODE 0 /* LED */ @@ -506,7 +515,7 @@ enum base_rev { #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) #define MT_HW_REV 0x70010204 -#define MT_WF_SUBSYS_RST 0x70002600 +#define MT_WF_SUBSYS_RST 0x70028600 /* PCIE MAC */ #define MT_PCIE_MAC_BASE 0x74030000 -- cgit From 672662f0742bf51584b871939703e3deb4beec27 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 5 Apr 2023 07:24:38 +0800 Subject: wifi: mt76: mt7996: add full system reset knobs into debugfs Add testing points into debugfs to trigger firmware assert and enable full system recovery. Also rename knob "fw_ser" to a clear-cut name "sys_recovery". Co-developed-by: Bo Jiao Signed-off-by: Bo Jiao Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + .../net/wireless/mediatek/mt76/mt7996/debugfs.c | 149 ++++++++++++++++++--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 16 +++ drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 28 ++-- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 + drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 13 ++ 6 files changed, 178 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index ac7d5817f345..08b031def3ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1221,6 +1221,7 @@ enum { MCU_UNI_CMD_VOW = 0x37, MCU_UNI_CMD_RRO = 0x57, MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58, + MCU_UNI_CMD_ASSERT_DUMP = 0x6f, }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 9c5e9ac1c335..513ab4ba41c9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get, /* test knob of system error recovery */ static ssize_t -mt7996_fw_ser_set(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) +mt7996_sys_recovery_set(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) { struct mt7996_phy *phy = file->private_data; struct mt7996_dev *dev = phy->dev; - u8 band_idx = phy->mt76->band_idx; + bool band = phy->mt76->band_idx; char buf[16]; int ret = 0; u16 val; @@ -73,17 +73,47 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf, return -EINVAL; switch (val) { - case SER_SET_RECOVER_L1: - case SER_SET_RECOVER_L2: - case SER_SET_RECOVER_L3_RX_ABORT: - case SER_SET_RECOVER_L3_TX_ABORT: - case SER_SET_RECOVER_L3_TX_DISABLE: - case SER_SET_RECOVER_L3_BF: - ret = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx); + /* + * 0: grab firmware current SER state. + * 1: trigger & enable system error L1 recovery. + * 2: trigger & enable system error L2 recovery. + * 3: trigger & enable system error L3 rx abort. + * 4: trigger & enable system error L3 tx abort + * 5: trigger & enable system error L3 tx disable. + * 6: trigger & enable system error L3 bf recovery. + * 7: trigger & enable system error L4 mdp recovery. + * 8: trigger & enable system error full recovery. + * 9: trigger firmware crash. + */ + case UNI_CMD_SER_QUERY: + ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band); + break; + case UNI_CMD_SER_SET_RECOVER_L1: + case UNI_CMD_SER_SET_RECOVER_L2: + case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT: + case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT: + case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE: + case UNI_CMD_SER_SET_RECOVER_L3_BF: + case UNI_CMD_SER_SET_RECOVER_L4_MDP: + ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band); if (ret) return ret; - ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx); + ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band); + break; + + /* enable full chip reset */ + case UNI_CMD_SER_SET_RECOVER_FULL: + mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK); + dev->recovery.state |= MT_MCU_CMD_WDT_MASK; + mt7996_reset(dev); + break; + + /* WARNING: trigger firmware crash */ + case UNI_CMD_SER_SET_SYSTEM_ASSERT: + ret = mt7996_mcu_trigger_assert(dev); + if (ret) + return ret; break; default: break; @@ -92,9 +122,97 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf, return ret ? ret : count; } -static const struct file_operations mt7996_fw_ser_ops = { - .write = mt7996_fw_ser_set, - /* TODO: ser read */ +static ssize_t +mt7996_sys_recovery_get(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct mt7996_phy *phy = file->private_data; + struct mt7996_dev *dev = phy->dev; + char *buff; + int desc = 0; + ssize_t ret; + static const size_t bufsz = 1024; + + buff = kmalloc(bufsz, GFP_KERNEL); + if (!buff) + return -ENOMEM; + + /* HELP */ + desc += scnprintf(buff + desc, bufsz - desc, + "Please echo the correct value ...\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "0: grab firmware transient SER state\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "1: trigger system error L1 recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "2: trigger system error L2 recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "3: trigger system error L3 rx abort\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "4: trigger system error L3 tx abort\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "5: trigger system error L3 tx disable\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "6: trigger system error L3 bf recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "7: trigger system error L4 mdp recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "8: trigger system error full recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "9: trigger firmware crash\n"); + + /* SER statistics */ + desc += scnprintf(buff + desc, bufsz - desc, + "\nlet's dump firmware SER statistics...\n"); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_STATUS = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_SER_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B2 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B2 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "\nSYS_RESET_COUNT: WM %d, WA %d\n", + dev->recovery.wm_reset_count, + dev->recovery.wa_reset_count); + + ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); + kfree(buff); + return ret; +} + +static const struct file_operations mt7996_sys_recovery_ops = { + .write = mt7996_sys_recovery_set, + .read = mt7996_sys_recovery_get, .open = simple_open, .llseek = default_llseek, }; @@ -674,6 +792,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy) debugfs_create_file("xmit-queues", 0400, dir, phy, &mt7996_xmit_queues_fops); debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops); + debugfs_create_file("sys_recovery", 0600, dir, phy, + &mt7996_sys_recovery_ops); debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm); debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa); debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin); @@ -684,7 +804,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy) &fops_implicit_txbf); debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, mt7996_twt_stats); - debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops); debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); if (phy->mt76->cap.has_5ghz) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 7a73f1a474fa..c99605a1ee6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -3615,6 +3615,22 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set) return 0; } +int mt7996_mcu_trigger_assert(struct mt7996_dev *dev) +{ + struct { + __le16 tag; + __le16 len; + u8 enable; + u8 rsv[3]; + } __packed req = { + .len = cpu_to_le16(sizeof(req) - 4), + .enable = true, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ASSERT_DUMP), + &req, sizeof(req), false); +} + int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index dd0c5ac52703..6f92b9a7d86d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -648,23 +648,21 @@ enum { }; enum { - UNI_CMD_SER_QUERY = 0x0, - UNI_CMD_SER_SET = 0x2, - UNI_CMD_SER_TRIGGER = 0x3, -}; - -enum { - SER_QUERY, + UNI_CMD_SER_QUERY, /* recovery */ - SER_SET_RECOVER_L1, - SER_SET_RECOVER_L2, - SER_SET_RECOVER_L3_RX_ABORT, - SER_SET_RECOVER_L3_TX_ABORT, - SER_SET_RECOVER_L3_TX_DISABLE, - SER_SET_RECOVER_L3_BF, + UNI_CMD_SER_SET_RECOVER_L1, + UNI_CMD_SER_SET_RECOVER_L2, + UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT, + UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT, + UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE, + UNI_CMD_SER_SET_RECOVER_L3_BF, + UNI_CMD_SER_SET_RECOVER_L4_MDP, + UNI_CMD_SER_SET_RECOVER_FULL, + UNI_CMD_SER_SET_SYSTEM_ASSERT, /* action */ - SER_ENABLE = 2, - SER_RECOVER + UNI_CMD_SER_ENABLE = 1, + UNI_CMD_SER_SET, + UNI_CMD_SER_TRIGGER }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 1a780167efd0..bc399e8d0dd3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -441,6 +441,7 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val); int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl); int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level); +int mt7996_mcu_trigger_assert(struct mt7996_dev *dev); void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb); void mt7996_mcu_exit(struct mt7996_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 5ba74b49d65d..fb9b8dec9189 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -480,6 +480,19 @@ enum base_rev { #define MT_SWDEF_MODE MT_SWDEF(0x3c) #define MT_SWDEF_NORMAL_MODE 0 +#define MT_SWDEF_SER_STATS MT_SWDEF(0x040) +#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044) +#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048) +#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04c) +#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050) +#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054) +#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058) +#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05c) +#define MT_SWDEF_LAMC_WISR6_BN2_STATS MT_SWDEF(0x060) +#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064) +#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068) +#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06c) + /* LED */ #define MT_LED_TOP_BASE 0x18013000 #define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n)) -- cgit From 878161d5d4a469a6ef7f3fb4fe9f676bc508ee99 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 5 Apr 2023 07:24:39 +0800 Subject: wifi: mt76: mt7996: enable coredump support Host triggered and catastrophic event triggered firmware core dumping for basic firmware issues triage, including state reporting, function calltrace and MCU memory dump. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/mt7996/Makefile | 2 + .../net/wireless/mediatek/mt76/mt7996/coredump.c | 268 +++++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7996/coredump.h | 97 ++++++++ drivers/net/wireless/mediatek/mt76/mt7996/init.c | 10 +- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 72 +++++- drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 8 + drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 22 ++ drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 18 ++ 9 files changed, 496 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7996/coredump.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7996/coredump.h diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig index 79fb47a73c91..1afa2f662e47 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig @@ -2,6 +2,7 @@ config MT7996E tristate "MediaTek MT7996 (PCIe) support" select MT76_CONNAC_LIB + select WANT_DEV_COREDUMP select RELAY depends on MAC80211 depends on PCI diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Makefile b/drivers/net/wireless/mediatek/mt76/mt7996/Makefile index bcb9a3c53149..07c8b555c1ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7996/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_MT7996E) += mt7996e.o mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ debugfs.o mmio.o + +mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c new file mode 100644 index 000000000000..ccab0d7b9be4 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include +#include +#include +#include +#include "coredump.h" + +static bool coredump_memdump; +module_param(coredump_memdump, bool, 0644); +MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory"); + +static const struct mt7996_mem_region mt7996_mem_regions[] = { + { + .start = 0x00800000, + .len = 0x0004ffff, + .name = "ULM0", + }, + { + .start = 0x00900000, + .len = 0x00037fff, + .name = "ULM1", + }, + { + .start = 0x02200000, + .len = 0x0003ffff, + .name = "ULM2", + }, + { + .start = 0x00400000, + .len = 0x00067fff, + .name = "SRAM", + }, + { + .start = 0xe0000000, + .len = 0x0015ffff, + .name = "CRAM0", + }, + { + .start = 0xe0160000, + .len = 0x0011bfff, + .name = "CRAM1", + }, +}; + +const struct mt7996_mem_region* +mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7990: + case 0x7991: + *num = ARRAY_SIZE(mt7996_mem_regions); + return &mt7996_mem_regions[0]; + default: + return NULL; + } +} + +static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev) +{ + const struct mt7996_mem_region *mem_region; + size_t size = 0; + u32 num; + int i; + + mem_region = mt7996_coredump_get_mem_layout(dev, &num); + if (!mem_region) + return 0; + + for (i = 0; i < num; i++) { + size += mem_region->len; + mem_region++; + } + + /* reserve space for the headers */ + size += num * sizeof(struct mt7996_mem_hdr); + /* make sure it is aligned 4 bytes for debug message print out */ + size = ALIGN(size, 4); + + return size; +} + +struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev) +{ + struct mt7996_crash_data *crash_data = dev->coredump.crash_data; + + lockdep_assert_held(&dev->dump_mutex); + + if (coredump_memdump && + !mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500)) + return NULL; + + guid_gen(&crash_data->guid); + ktime_get_real_ts64(&crash_data->timestamp); + + return crash_data; +} + +static void +mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump, + bool *exception) +{ + u32 count; + + count = mt76_rr(dev, MT_FW_ASSERT_CNT); + + /* normal mode: driver can manually trigger assert for detail info */ + if (!count) + strscpy(dump->fw_state, "normal", sizeof(dump->fw_state)); + else + strscpy(dump->fw_state, "exception", sizeof(dump->fw_state)); + + *exception = !!count; +} + +static void +mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump, + bool exception) +{ + u32 oldest, i, idx; + + strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current)); + + /* 0: WM PC log output */ + mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0); + /* choose 33th PC log buffer to read current PC index */ + mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f); + + /* read current PC */ + dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG); + + /* stop call stack record */ + if (!exception) { + mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); + mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); + } + + oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL, + GENMASK(20, 16)) + 2; + for (i = 0; i < 16; i++) { + idx = ((oldest + 2 * i + 1) % 32); + dump->pc_stack[i + 1] = + mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4); + } + + oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL, + GENMASK(20, 16)) + 2; + for (i = 0; i < 16; i++) { + idx = ((oldest + 2 * i + 1) % 32); + dump->lr_stack[i] = + mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4); + } + + /* start call stack record */ + if (!exception) { + mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); + mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); + } +} + +static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev) +{ + struct mt7996_crash_data *crash_data = dev->coredump.crash_data; + struct mt7996_coredump *dump; + struct mt7996_coredump_mem *dump_mem; + size_t len, sofar = 0, hdr_len = sizeof(*dump); + unsigned char *buf; + bool exception; + + len = hdr_len; + + if (coredump_memdump && crash_data->memdump_buf_len) + len += sizeof(*dump_mem) + crash_data->memdump_buf_len; + + sofar += hdr_len; + + /* this is going to get big when we start dumping memory and such, + * so go ahead and use vmalloc. + */ + buf = vzalloc(len); + if (!buf) + return NULL; + + mutex_lock(&dev->dump_mutex); + + dump = (struct mt7996_coredump *)(buf); + dump->len = len; + + /* plain text */ + strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic)); + strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel)); + strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version, + sizeof(dump->fw_ver)); + + guid_copy(&dump->guid, &crash_data->guid); + dump->tv_sec = crash_data->timestamp.tv_sec; + dump->tv_nsec = crash_data->timestamp.tv_nsec; + dump->device_id = mt76_chip(&dev->mt76); + + mt7996_coredump_fw_state(dev, dump, &exception); + mt7996_coredump_fw_stack(dev, dump, exception); + + /* gather memory content */ + dump_mem = (struct mt7996_coredump_mem *)(buf + sofar); + dump_mem->len = crash_data->memdump_buf_len; + if (coredump_memdump && crash_data->memdump_buf_len) + memcpy(dump_mem->data, crash_data->memdump_buf, + crash_data->memdump_buf_len); + + mutex_unlock(&dev->dump_mutex); + + return dump; +} + +int mt7996_coredump_submit(struct mt7996_dev *dev) +{ + struct mt7996_coredump *dump; + + dump = mt7996_coredump_build(dev); + if (!dump) { + dev_warn(dev->mt76.dev, "no crash dump data found\n"); + return -ENODATA; + } + + dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL); + + return 0; +} + +int mt7996_coredump_register(struct mt7996_dev *dev) +{ + struct mt7996_crash_data *crash_data; + + crash_data = vzalloc(sizeof(*dev->coredump.crash_data)); + if (!crash_data) + return -ENOMEM; + + dev->coredump.crash_data = crash_data; + + if (coredump_memdump) { + crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev); + if (!crash_data->memdump_buf_len) + /* no memory content */ + return 0; + + crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len); + if (!crash_data->memdump_buf) { + vfree(crash_data); + return -ENOMEM; + } + } + + return 0; +} + +void mt7996_coredump_unregister(struct mt7996_dev *dev) +{ + if (dev->coredump.crash_data->memdump_buf) { + vfree(dev->coredump.crash_data->memdump_buf); + dev->coredump.crash_data->memdump_buf = NULL; + dev->coredump.crash_data->memdump_buf_len = 0; + } + + vfree(dev->coredump.crash_data); + dev->coredump.crash_data = NULL; +} + diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h new file mode 100644 index 000000000000..af2ba219b1b5 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef _COREDUMP_H_ +#define _COREDUMP_H_ + +#include "mt7996.h" + +struct mt7996_coredump { + char magic[16]; + + u32 len; + + guid_t guid; + + /* time-of-day stamp */ + u64 tv_sec; + /* time-of-day stamp, nano-seconds */ + u64 tv_nsec; + /* kernel version */ + char kernel[64]; + /* firmware version */ + char fw_ver[ETHTOOL_FWVERS_LEN]; + + u32 device_id; + + /* exception state */ + char fw_state[12]; + + /* program counters */ + char pc_current[16]; + u32 pc_stack[17]; + /* link registers */ + u32 lr_stack[16]; + + /* memory content */ + u8 data[]; +} __packed; + +struct mt7996_coredump_mem { + u32 len; + u8 data[]; +} __packed; + +struct mt7996_mem_hdr { + u32 start; + u32 len; + u8 data[]; +}; + +struct mt7996_mem_region { + u32 start; + size_t len; + + const char *name; +}; + +#ifdef CONFIG_DEV_COREDUMP + +const struct mt7996_mem_region * +mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num); +struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev); +int mt7996_coredump_submit(struct mt7996_dev *dev); +int mt7996_coredump_register(struct mt7996_dev *dev); +void mt7996_coredump_unregister(struct mt7996_dev *dev); + +#else /* CONFIG_DEV_COREDUMP */ + +static inline const struct mt7996_mem_region * +mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num) +{ + return NULL; +} + +static inline int mt7996_coredump_submit(struct mt7996_dev *dev) +{ + return 0; +} + +static inline struct +mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev) +{ + return NULL; +} + +static inline int mt7996_coredump_register(struct mt7996_dev *dev) +{ + return 0; +} + +static inline void mt7996_coredump_unregister(struct mt7996_dev *dev) +{ +} + +#endif /* CONFIG_DEV_COREDUMP */ + +#endif /* _COREDUMP_H_ */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 6de9a0405b74..19cdd0625c40 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -8,6 +8,7 @@ #include "mt7996.h" #include "mac.h" #include "mcu.h" +#include "coredump.h" #include "eeprom.h" static const struct ieee80211_iface_limit if_limits[] = { @@ -841,6 +842,8 @@ int mt7996_register_device(struct mt7996_dev *dev) init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7996_mac_reset_work); + INIT_WORK(&dev->dump_work, mt7996_mac_dump_work); + mutex_init(&dev->dump_mutex); ret = mt7996_init_hardware(dev); if (ret) @@ -871,13 +874,18 @@ int mt7996_register_device(struct mt7996_dev *dev) dev->recovery.hw_init_done = true; - return mt7996_init_debugfs(&dev->phy); + ret = mt7996_init_debugfs(&dev->phy); + if (ret) + return ret; + + return mt7996_coredump_register(dev); } void mt7996_unregister_device(struct mt7996_dev *dev) { mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2); mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1); + mt7996_coredump_unregister(dev); mt76_unregister_device(&dev->mt76); mt7996_mcu_exit(dev); mt7996_tx_token_put(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index d526d6f53ace..1e9452c33e47 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -5,6 +5,7 @@ #include #include +#include "coredump.h" #include "mt7996.h" #include "../dma.h" #include "mac.h" @@ -2081,6 +2082,75 @@ void mt7996_mac_reset_work(struct work_struct *work) wiphy_name(dev->mt76.hw->wiphy)); } +/* firmware coredump */ +void mt7996_mac_dump_work(struct work_struct *work) +{ + const struct mt7996_mem_region *mem_region; + struct mt7996_crash_data *crash_data; + struct mt7996_dev *dev; + struct mt7996_mem_hdr *hdr; + size_t buf_len; + int i; + u32 num; + u8 *buf; + + dev = container_of(work, struct mt7996_dev, dump_work); + + mutex_lock(&dev->dump_mutex); + + crash_data = mt7996_coredump_new(dev); + if (!crash_data) { + mutex_unlock(&dev->dump_mutex); + goto skip_coredump; + } + + mem_region = mt7996_coredump_get_mem_layout(dev, &num); + if (!mem_region || !crash_data->memdump_buf_len) { + mutex_unlock(&dev->dump_mutex); + goto skip_memdump; + } + + buf = crash_data->memdump_buf; + buf_len = crash_data->memdump_buf_len; + + /* dumping memory content... */ + memset(buf, 0, buf_len); + for (i = 0; i < num; i++) { + if (mem_region->len > buf_len) { + dev_warn(dev->mt76.dev, "%s len %zu is too large\n", + mem_region->name, mem_region->len); + break; + } + + /* reserve space for the header */ + hdr = (void *)buf; + buf += sizeof(*hdr); + buf_len -= sizeof(*hdr); + + mt7996_memcpy_fromio(dev, buf, mem_region->start, + mem_region->len); + + hdr->start = mem_region->start; + hdr->len = mem_region->len; + + if (!mem_region->len) + /* note: the header remains, just with zero length */ + break; + + buf += mem_region->len; + buf_len -= mem_region->len; + + mem_region++; + } + + mutex_unlock(&dev->dump_mutex); + +skip_memdump: + mt7996_coredump_submit(dev); +skip_coredump: + queue_work(dev->mt76.wq, &dev->reset_work); +} + void mt7996_reset(struct mt7996_dev *dev) { if (!dev->recovery.hw_init_done) @@ -2097,7 +2167,7 @@ void mt7996_reset(struct mt7996_dev *dev) wiphy_name(dev->mt76.hw->wiphy)); mt7996_irq_disable(dev, MT_INT_MCU_CMD); - queue_work(dev->mt76.wq, &dev->reset_work); + queue_work(dev->mt76.wq, &dev->dump_work); return; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 8d6ab919d086..879b0e90b52e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -162,6 +162,14 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr) return mt7996_reg_map_l2(dev, addr); } +void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset, + size_t len) +{ + u32 addr = __mt7996_reg_addr(dev, offset); + + memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len); +} + static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset) { struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index bc399e8d0dd3..4001cf12b671 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -176,6 +176,15 @@ struct mib_stats { u32 tx_amsdu_cnt; }; +/* crash-dump */ +struct mt7996_crash_data { + guid_t guid; + struct timespec64 timestamp; + + u8 *memdump_buf; + size_t memdump_buf_len; +}; + struct mt7996_hif { struct list_head list; @@ -234,6 +243,7 @@ struct mt7996_dev { struct work_struct init_work; struct work_struct rc_work; + struct work_struct dump_work; struct work_struct reset_work; wait_queue_head_t reset_wait; struct { @@ -245,6 +255,14 @@ struct mt7996_dev { bool restart:1; } recovery; + /* protects coredump data */ + struct mutex dump_mutex; +#ifdef CONFIG_DEV_COREDUMP + struct { + struct mt7996_crash_data *crash_data; + } coredump; +#endif + struct list_head sta_rc_list; struct list_head sta_poll_list; struct list_head twt_list; @@ -476,6 +494,9 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask) mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } +void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset, + size_t len); + void mt7996_mac_init(struct mt7996_dev *dev); u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw); bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask); @@ -495,6 +516,7 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7996_mac_work(struct work_struct *work); void mt7996_mac_reset_work(struct work_struct *work); +void mt7996_mac_dump_work(struct work_struct *work); void mt7996_mac_sta_rc_work(struct work_struct *work); void mt7996_mac_update_stats(struct mt7996_phy *phy); void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index fb9b8dec9189..75f856205559 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -474,6 +474,9 @@ enum base_rev { #define MT_INFRA_MCU_END 0x7c3fffff /* FW MODE SYNC */ +#define MT_FW_ASSERT_CNT 0x02208274 +#define MT_FW_DUMP_STATE 0x02209e90 + #define MT_SWDEF_BASE 0x00401400 #define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) @@ -508,6 +511,13 @@ enum base_rev { #define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4)) +/* CONN DBG */ +#define MT_CONN_DBG_CTL_BASE 0x18023000 +#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs)) +#define MT_CONN_DBG_CTL_OUT_SEL MT_CONN_DBG_CTL(0x604) +#define MT_CONN_DBG_CTL_PC_LOG_SEL MT_CONN_DBG_CTL(0x60c) +#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x610) + #define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */ #define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */ #define MT_LED_GPIO_SEL_MASK GENMASK(11, 8) @@ -561,4 +571,12 @@ enum base_rev { #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18) #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29) +/* CONN MCU EXCP CON */ +#define MT_MCU_WM_EXCP_BASE 0x89050000 +#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs)) +#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100) +#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104) +#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200) +#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204) + #endif -- cgit From 61d1f54533496711e06fcfd42b93c5ded9e27c7a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 5 Apr 2023 12:38:53 +0200 Subject: wifi: mt76: move mcu_uni_event and mcu_reg_event in common code mcu_uni_event and mcu_reg_event structs are shared between mt7921 and mt7615 drivers, so move them in connac lib. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7615/mcu.h | 11 ----------- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 11 +++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7921/mcu.h | 11 ----------- 5 files changed, 19 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 195fe1094d9b..8d745c9730c7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -163,16 +163,16 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, cmd == MCU_UNI_CMD(HIF_CTRL) || cmd == MCU_UNI_CMD(OFFLOAD) || cmd == MCU_UNI_CMD(SUSPEND)) { - struct mt7615_mcu_uni_event *event; + struct mt76_connac_mcu_uni_event *event; skb_pull(skb, sizeof(*rxd)); - event = (struct mt7615_mcu_uni_event *)skb->data; + event = (struct mt76_connac_mcu_uni_event *)skb->data; ret = le32_to_cpu(event->status); } else if (cmd == MCU_CE_QUERY(REG_READ)) { - struct mt7615_mcu_reg_event *event; + struct mt76_connac_mcu_reg_event *event; skb_pull(skb, sizeof(*rxd)); - event = (struct mt7615_mcu_reg_event *)skb->data; + event = (struct mt76_connac_mcu_reg_event *)skb->data; ret = (int)le32_to_cpu(event->val); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 615956acc6b5..8e9604be0792 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -206,17 +206,6 @@ enum { MCU_ATE_SET_TX_POWER_CONTROL = 0x15, }; -struct mt7615_mcu_uni_event { - u8 cid; - u8 pad[3]; - __le32 status; /* 0: success, others: fail */ -} __packed; - -struct mt7615_mcu_reg_event { - __le32 reg; - __le32 val; -} __packed; - struct mt7615_roc_tlv { u8 bss_idx; u8 token; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 08b031def3ef..ca1ce97a6d2f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -1690,6 +1690,17 @@ struct mt76_connac_config { u8 data[320]; } __packed; +struct mt76_connac_mcu_uni_event { + u8 cid; + u8 pad[3]; + __le32 status; /* 0: success, others: fail */ +} __packed; + +struct mt76_connac_mcu_reg_event { + __le32 reg; + __le32 val; +} __packed; + static inline enum mcu_cipher_type mt76_connac_mcu_get_cipher(int cipher) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 04925e66f15b..259b6ea88be4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -67,19 +67,19 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, cmd == MCU_UNI_CMD(HIF_CTRL) || cmd == MCU_UNI_CMD(OFFLOAD) || cmd == MCU_UNI_CMD(SUSPEND)) { - struct mt7921_mcu_uni_event *event; + struct mt76_connac_mcu_uni_event *event; skb_pull(skb, sizeof(*rxd)); - event = (struct mt7921_mcu_uni_event *)skb->data; + event = (struct mt76_connac_mcu_uni_event *)skb->data; ret = le32_to_cpu(event->status); /* skip invalid event */ if (mcu_cmd != event->cid) ret = -EAGAIN; } else if (cmd == MCU_CE_QUERY(REG_READ)) { - struct mt7921_mcu_reg_event *event; + struct mt76_connac_mcu_reg_event *event; skb_pull(skb, sizeof(*rxd)); - event = (struct mt7921_mcu_reg_event *)skb->data; + event = (struct mt76_connac_mcu_reg_event *)skb->data; ret = (int)le32_to_cpu(event->val); } else { skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index 96dc870fd35e..9b0aa3b70f0e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -50,22 +50,11 @@ struct mt7921_mcu_eeprom_info { #define MT_RA_RATE_DCM_EN BIT(4) #define MT_RA_RATE_BW GENMASK(14, 13) -struct mt7921_mcu_uni_event { - u8 cid; - u8 pad[3]; - __le32 status; /* 0: success, others: fail */ -} __packed; - enum { MT_EBF = BIT(0), /* explicit beamforming */ MT_IBF = BIT(1) /* implicit beamforming */ }; -struct mt7921_mcu_reg_event { - __le32 reg; - __le32 val; -} __packed; - struct mt7921_mcu_ant_id_config { u8 ant_id[4]; } __packed; -- cgit From 12db28c3ef31f719bd18fa186a40bb152e6a527c Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 12 Apr 2023 05:23:11 +0800 Subject: mt76: mt7921: fix kernel panic by accessing unallocated eeprom.data The MT7921 driver no longer uses eeprom.data, but the relevant code has not been removed completely since commit 16d98b548365 ("mt76: mt7921: rely on mcu_get_nic_capability"). This could result in potential invalid memory access. To fix the kernel panic issue in mt7921, it is necessary to avoid accessing unallocated eeprom.data which can lead to invalid memory access. Furthermore, it is possible to entirely eliminate the mt7921_mcu_parse_eeprom function and solely depend on mt7921_mcu_parse_response to divide the RxD header. [2.702735] BUG: kernel NULL pointer dereference, address: 0000000000000550 [2.702740] #PF: supervisor write access in kernel mode [2.702741] #PF: error_code(0x0002) - not-present page [2.702743] PGD 0 P4D 0 [2.702747] Oops: 0002 [#1] PREEMPT SMP NOPTI [2.702755] RIP: 0010:mt7921_mcu_parse_response+0x147/0x170 [mt7921_common] [2.702758] RSP: 0018:ffffae7c00fef828 EFLAGS: 00010286 [2.702760] RAX: ffffa367f57be024 RBX: ffffa367cc7bf500 RCX: 0000000000000000 [2.702762] RDX: 0000000000000550 RSI: 0000000000000000 RDI: ffffa367cc7bf500 [2.702763] RBP: ffffae7c00fef840 R08: ffffa367cb167000 R09: 0000000000000005 [2.702764] R10: 0000000000000000 R11: ffffffffc04702e4 R12: ffffa367e8329f40 [2.702766] R13: 0000000000000000 R14: 0000000000000001 R15: ffffa367e8329f40 [2.702768] FS: 000079ee6cf20c40(0000) GS:ffffa36b2f940000(0000) knlGS:0000000000000000 [2.702769] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [2.702775] CR2: 0000000000000550 CR3: 00000001233c6004 CR4: 0000000000770ee0 [2.702776] PKRU: 55555554 [2.702777] Call Trace: [2.702782] mt76_mcu_skb_send_and_get_msg+0xc3/0x11e [mt76 ] [2.702785] mt7921_run_firmware+0x241/0x853 [mt7921_common ] [2.702789] mt7921e_mcu_init+0x2b/0x56 [mt7921e ] [2.702792] mt7921_register_device+0x2eb/0x5a5 [mt7921_common ] [2.702795] ? mt7921_irq_tasklet+0x1d4/0x1d4 [mt7921e ] [2.702797] mt7921_pci_probe+0x2d6/0x319 [mt7921e ] [2.702799] pci_device_probe+0x9f/0x12a Fixes: 16d98b548365 ("mt76: mt7921: rely on mcu_get_nic_capability") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 259b6ea88be4..c69ce6df4956 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -15,24 +15,6 @@ static bool mt7921_disable_clc; module_param_named(disable_clc, mt7921_disable_clc, bool, 0644); MODULE_PARM_DESC(disable_clc, "disable CLC support"); -static int -mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb) -{ - struct mt7921_mcu_eeprom_info *res; - u8 *buf; - - if (!skb) - return -EINVAL; - - skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); - - res = (struct mt7921_mcu_eeprom_info *)skb->data; - buf = dev->eeprom.data + le32_to_cpu(res->addr); - memcpy(buf, res->data, 16); - - return 0; -} - int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq) { @@ -59,8 +41,6 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, } else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) { skb_pull(skb, sizeof(*rxd) + 4); ret = le32_to_cpu(*(__le32 *)skb->data); - } else if (cmd == MCU_EXT_CMD(EFUSE_ACCESS)) { - ret = mt7921_mcu_parse_eeprom(mdev, skb); } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) || cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) || cmd == MCU_UNI_CMD(STA_REC_UPDATE) || -- cgit From 5c47cdebbaeb7724df6f9f46917c93e53f791547 Mon Sep 17 00:00:00 2001 From: Jiefeng Li Date: Wed, 12 Apr 2023 14:22:34 +0800 Subject: wifi: mt76: mt7921: fix missing unwind goto in `mt7921u_probe` `mt7921u_dma_init` can only return zero or negative number according to its definition. When it returns non-zero number, there exists an error and this function should handle this error rather than return directly. Fixes: 0d2afe09fad5 ("mt76: mt7921: add mt7921u driver") Signed-off-by: Jiefeng Li Reviewed-by: Dongliang Mu Reviewed-by: Sridhar Samudrala Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 9b05e4577cdf..1f302c430339 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -259,7 +259,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, ret = mt7921u_dma_init(dev, false); if (ret) - return ret; + goto error; hw = mt76_hw(dev); /* check hw sg support in order to enable AMSDU */ -- cgit From 87714bf6ed1589813e473db5471e6e9857755764 Mon Sep 17 00:00:00 2001 From: Quan Zhou Date: Thu, 13 Apr 2023 05:11:13 +0800 Subject: wifi: mt76: mt7921e: improve reliability of dma reset The hardware team has advised the driver that it is necessary to first put WFDMA into an idle state before resetting the WFDMA. Otherwise, the WFDMA may enter an unknown state where it cannot be polled with the right state successfully. To ensure that the DMA can work properly while a stressful cold reboot test was being made, we have reordered the programming sequence in the driver based on the hardware team's guidance. The patch would modify the WFDMA disabling flow from "DMA reset -> disabling DMASHDL -> disabling WFDMA -> polling and waiting until DMA idle" to "disabling WFDMA -> polling and waiting for DMA idle -> disabling DMASHDL -> DMA reset. Where he polling and waiting until WFDMA is idle is coordinated with the operation of disabling WFDMA. Even while WFDMA is being disabled, it can still handle Tx/Rx requests. The additional polling allows sufficient time for WFDMA to process the last T/Rx request. When the idle state of WFDMA is reached, it is a reliable indication that DMASHDL is also idle to ensure it is safe to disable it and perform the DMA reset. Fixes: 0a1059d0f060 ("mt76: mt7921: move mt7921_dma_reset in dma.c") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Co-developed-by: Deren Wu Signed-off-by: Deren Wu Co-developed-by: Wang Zhao Signed-off-by: Wang Zhao Signed-off-by: Quan Zhou Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 36 ++++++++++++++----------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 28207172c4ef..f0a80c2b476a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -66,22 +66,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev) static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) { - if (force) { - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - } - - /* disable dmashdl */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - /* disable WFDMA0 */ mt76_clear(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | @@ -95,6 +79,22 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) return -ETIMEDOUT; + /* disable dmashdl */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + if (force) { + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + } + return 0; } @@ -301,6 +301,10 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev) MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1); + /* reset */ mt76_clear(dev, MT_WFDMA0_RST, MT_WFDMA0_RST_DMASHDL_ALL_RST | -- cgit From 3d78c46423c6567ed25ca033e086865b1b4d5ae1 Mon Sep 17 00:00:00 2001 From: Quan Zhou Date: Thu, 13 Apr 2023 05:11:14 +0800 Subject: wifi: mt76: mt7921e: stop chip reset worker in unregister hook If the chip reset worker is triggered during the remove process, the chip DMA may not be properly pushed back to the idle state. This can lead to corruption of the DMA flow due to the chip reset. Therefore, it is necessary to stop the chip reset before the DMA is finalized. To avoid resetting the chip after the reset worker is cancelled, use __mt7921_mcu_drv_pmctrl() instead of mt7921_mcu_drv_pmctrl(). It is safe to ignore the pm mutex because the pm worker and wake worker have already been cancelled. Fixes: 033ae79b3830 ("mt76: mt7921: refactor init.c to be bus independent") Co-developed-by: Sean Wang Signed-off-by: Sean Wang Co-developed-by: Deren Wu Signed-off-by: Deren Wu Co-developed-by: Wang Zhao Signed-off-by: Wang Zhao Signed-off-by: Quan Zhou Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 40bea17cc440..1c727870bbdb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -113,9 +113,10 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) napi_disable(&dev->mt76.napi[i]); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); + cancel_work_sync(&dev->reset_work); mt7921_tx_token_put(dev); - mt7921_mcu_drv_pmctrl(dev); + __mt7921_mcu_drv_pmctrl(dev); mt7921_dma_cleanup(dev); mt7921_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); -- cgit From 3d2892e05086d09aecf14ea64b2debbf495e313c Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 14 Apr 2023 04:23:29 +0800 Subject: wifi: mt76: connac: fix txd multicast rate setting The vif->bss_conf.mcast_rate should be applied to multicast data frame only. Fixes: 182071cdd594 ("mt76: connac: move connac2_mac_write_txwi in mt76_connac module") Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index bd4ce2c7742d..a51a2d4ff2f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -558,7 +558,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { /* Fixed rata is available just for 802.11 txd */ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - bool multicast = is_multicast_ether_addr(hdr->addr1); + bool multicast = ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1); u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, multicast); u32 val = MT_TXD6_FIXED_BW; -- cgit From 9c54548bc9e46217c551ed69fd2f14f4cb5155eb Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 14 Apr 2023 04:23:30 +0800 Subject: wifi: mt76: connac: add nss calculation into mt76_connac2_mac_tx_rate_val() Take nss calculation into account since this function always wrongly returns 0. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 43 ++++++++++++++-------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index a51a2d4ff2f8..ee0fbfcd07d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -288,11 +288,29 @@ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, } EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues); +#define __bitrate_mask_check(_mcs, _mode) \ +({ \ + u8 i = 0; \ + for (nss = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \ + if (!mask->control[band]._mcs[i]) \ + continue; \ + if (hweight16(mask->control[band]._mcs[i]) == 1) { \ + mode = MT_PHY_TYPE_##_mode; \ + rateidx = ffs(mask->control[band]._mcs[i]) - 1; \ + if (mode == MT_PHY_TYPE_HT) \ + rateidx += 8 * i; \ + else \ + nss = i + 1; \ + goto out; \ + } \ + } \ +}) + u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, bool beacon, bool mcast) { - u8 mode = 0, band = mphy->chandef.chan->band; + u8 nss = 0, mode = 0, band = mphy->chandef.chan->band; int rateidx = 0, mcast_rate; if (!vif) @@ -307,19 +325,12 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct cfg80211_bitrate_mask *mask; mask = &vif->bss_conf.beacon_tx_rate; - if (hweight16(mask->control[band].he_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].he_mcs[0]) - 1; - mode = MT_PHY_TYPE_HE_SU; - goto out; - } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].vht_mcs[0]) - 1; - mode = MT_PHY_TYPE_VHT; - goto out; - } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].ht_mcs[0]) - 1; - mode = MT_PHY_TYPE_HT; - goto out; - } else if (hweight32(mask->control[band].legacy) == 1) { + + __bitrate_mask_check(he_mcs, HE_SU); + __bitrate_mask_check(vht_mcs, VHT); + __bitrate_mask_check(ht_mcs, HT); + + if (hweight32(mask->control[band].legacy) == 1) { rateidx = ffs(mask->control[band].legacy) - 1; goto legacy; } @@ -335,9 +346,9 @@ legacy: rateidx = mt76_calculate_default_rate(mphy, rateidx); mode = rateidx >> 8; rateidx &= GENMASK(7, 0); - out: - return FIELD_PREP(MT_TX_RATE_IDX, rateidx) | + return FIELD_PREP(MT_TX_RATE_NSS, nss) | + FIELD_PREP(MT_TX_RATE_IDX, rateidx) | FIELD_PREP(MT_TX_RATE_MODE, mode); } EXPORT_SYMBOL_GPL(mt76_connac2_mac_tx_rate_val); -- cgit From 15ee62e73705df447971613de4fa660dd71ed40e Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 14 Apr 2023 04:23:31 +0800 Subject: wifi: mt76: mt7996: enable BSS_CHANGED_BASIC_RATES support The connac3 removes fixed rate fields to reduce txd size and introduces global rate tables (64 entries) for rate setting. Driver needs to fill the corresponding idx in MT_TXD6_TX_RATE while tx, and push mt76_rate into predifined table at bootup stage so that mvif->basic_rates_idx can immediately switch out once setting changes. spe_idx is also needed for fixed rate frames, and will be updated by future patches. Note that all table entries are shared across driver and firmware (i.e.TxBF), hence adding MT7996_BASIC_RATES_TBL to reflect mapping status. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 16 +++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 32 ++++++++++------------ drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 7 ++--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 29 ++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 20 ++++++-------- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 7 +++++ drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 7 +++++ 7 files changed, 85 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 19cdd0625c40..90a92c1611f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -255,6 +255,20 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band) mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set); } +static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) { + u16 rate = mt76_rates[i].hw_value; + u16 idx = MT7996_BASIC_RATES_TBL + i; + + rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) | + FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0)); + mt7996_mac_set_fixed_rate_table(dev, idx, rate); + } +} + void mt7996_mac_init(struct mt7996_dev *dev) { #define HIF_TXD_V2_1 4 @@ -287,6 +301,8 @@ void mt7996_mac_init(struct mt7996_dev *dev) for (i = MT_BAND0; i <= MT_BAND2; i++) mt7996_mac_init_band(dev, i); + + mt7996_mac_init_basic_rates(dev); } int mt7996_txbf_init(struct mt7996_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 1e9452c33e47..c8ada309d73f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -252,6 +252,17 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, mt76_clear(dev, addr, BIT(5)); } +void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, + u8 tbl_idx, u16 rate_idx) +{ + u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx; + + mt76_wr(dev, MT_WTBL_ITDR0, rate_idx); + /* use wtbl spe idx */ + mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL); + mt76_wr(dev, MT_WTBL_ITCR, ctrl); +} + static void mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, struct ieee80211_radiotap_he *he, @@ -985,7 +996,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct mt76_phy *mphy = &dev->mphy; + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; @@ -997,15 +1008,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, BSS_CHANGED_FILS_DISCOVERY)); if (vif) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - omac_idx = mvif->mt76.omac_idx; wmm_idx = mvif->mt76.wmm_idx; band_idx = mvif->mt76.band_idx; } - mphy = mt76_dev_phy(&dev->mt76, band_idx); - if (inband_disc) { p_fmt = MT_TX_TYPE_FW; q_idx = MT_LMAC_ALTX0; @@ -1063,18 +1070,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, mt7996_mac_write_txwi_80211(dev, txwi, skb, key); if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { - /* Fixed rata is available just for 802.11 txd */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - bool multicast = is_multicast_ether_addr(hdr->addr1); - u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, - multicast); - - /* fix to bw 20 */ - val = MT_TXD6_FIXED_BW | - FIELD_PREP(MT_TXD6_BW, 0) | - FIELD_PREP(MT_TXD6_TX_RATE, rate); - - txwi[6] |= cpu_to_le32(val); + u8 idx = mvif->basic_rates_idx; + + txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx); txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index 0318e16fcfab..b2bbe0e09e26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -224,14 +224,11 @@ enum tx_mgnt_type { #define MT_TXD6_TX_SRC GENMASK(31, 30) #define MT_TXD6_VTA BIT(28) -#define MT_TXD6_FIXED_BW BIT(25) -#define MT_TXD6_BW GENMASK(24, 22) +#define MT_TXD6_BW GENMASK(25, 22) #define MT_TXD6_TX_RATE GENMASK(21, 16) #define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) #define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) #define MT_TXD6_MSDU_CNT GENMASK(9, 4) -#define MT_TXD6_SPE_ID_IDX BIT(10) -#define MT_TXD6_ANT_ID GENMASK(7, 4) #define MT_TXD6_DIS_MAT BIT(3) #define MT_TXD6_DAS BIT(2) #define MT_TXD6_AMSDU_CAP BIT(1) @@ -245,7 +242,7 @@ enum tx_mgnt_type { #define MT_TXD7_UDP_TCP_SUM BIT(15) #define MT_TXD7_TX_TIME GENMASK(9, 0) -#define MT_TX_RATE_STBC BIT(13) +#define MT_TX_RATE_STBC BIT(14) #define MT_TX_RATE_NSS GENMASK(13, 10) #define MT_TX_RATE_MODE GENMASK(9, 6) #define MT_TX_RATE_SU_EXT_TONE BIT(5) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 7ddfcf68ebd1..1243e5f925ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -5,6 +5,7 @@ #include "mt7996.h" #include "mcu.h" +#include "mac.h" static bool mt7996_dev_running(struct mt7996_dev *dev) { @@ -219,6 +220,11 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, vif->offload_flags = 0; vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; + if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) + mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; + else + mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL; + mt7996_init_bitrate_mask(vif); mt7996_mcu_add_bss_info(phy, vif, true); @@ -496,11 +502,30 @@ mt7996_update_bss_color(struct ieee80211_hw *hw, } } +static u8 +mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_phy *mphy = hw->priv; + u16 rate; + u8 i, idx; + + rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, false); + + idx = FIELD_GET(MT_TX_RATE_IDX, rate); + for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) + if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx) + return MT7996_BASIC_RATES_TBL + i; + + return mvif->basic_rates_idx; +} + static void mt7996_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u64 changed) { + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); @@ -532,6 +557,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, } } + if (changed & BSS_CHANGED_BASIC_RATES) + mvif->basic_rates_idx = mt7996_get_rates_table(hw, vif); + if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { mt7996_mcu_add_bss_info(phy, vif, true); mt7996_mcu_add_sta(dev, vif, NULL, true); @@ -891,6 +919,7 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) mt7996_set_stream_vht_txbf_caps(phy); mt7996_set_stream_he_eht_caps(phy); + /* TODO: update bmc_wtbl spe_idx when antenna changes */ mutex_unlock(&dev->mt76.mutex); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index c99605a1ee6b..3db74ae109dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -597,25 +597,23 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void -mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7996_phy *phy) +mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7996_phy *phy) { + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct bss_rate_tlv *bmc; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; struct tlv *tlv; + u8 idx = mvif->basic_rates_idx; tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc)); bmc = (struct bss_rate_tlv *)tlv; - if (band == NL80211_BAND_2GHZ) { - bmc->short_preamble = true; - } else { - bmc->bc_trans = cpu_to_le16(0x8080); - bmc->mc_trans = cpu_to_le16(0x8080); - bmc->bc_fixed_rate = 1; - bmc->mc_fixed_rate = 1; - bmc->short_preamble = 1; - } + + bmc->short_preamble = (band == NL80211_BAND_2GHZ); + bmc->bc_fixed_rate = idx; + bmc->mc_fixed_rate = idx; } static void @@ -823,7 +821,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, if (enable) { mt7996_mcu_bss_rfch_tlv(skb, vif, phy); - mt7996_mcu_bss_bmc_tlv(skb, phy); + mt7996_mcu_bss_bmc_tlv(skb, vif, phy); mt7996_mcu_bss_ra_tlv(skb, vif, phy); mt7996_mcu_bss_txcmd_tlv(skb, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 4001cf12b671..5cf5ea8cece9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -43,6 +43,9 @@ #define MT7996_MAX_STA_TWT_AGRT 8 #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3) +/* NOTE: used to map mt76_rates. idx may change if firmware expands table */ +#define MT7996_BASIC_RATES_TBL 11 + struct mt7996_vif; struct mt7996_sta; struct mt7996_dfs_pulse; @@ -120,6 +123,8 @@ struct mt7996_vif { struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; struct cfg80211_bitrate_mask bitrate_mask; + + u8 basic_rates_idx; }; /* per-phy stats. */ @@ -505,6 +510,8 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy); void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band); void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, struct ieee80211_vif *vif, bool enable); +void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, + u8 tbl_idx, u16 rate_idx); void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, int pid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 75f856205559..d1d3d154195d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -228,6 +228,13 @@ enum base_rev { #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14) #define MT_WTBL_UPDATE_BUSY BIT(31) +#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0) +#define MT_WTBL_ITCR_WR BIT(16) +#define MT_WTBL_ITCR_EXEC BIT(31) +#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8) +#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc) +#define MT_WTBL_SPE_IDX_SEL BIT(6) + /* WTBL */ #define MT_WTBL_BASE 0x820d8000 #define MT_WTBL_LMAC_ID GENMASK(14, 8) -- cgit From ab0eec4bf225c5e78fd10d764d536300376f8445 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 14 Apr 2023 04:23:32 +0800 Subject: wifi: mt76: mt7996: enable BSS_CHANGED_MCAST_RATE support Similar to BSS_CHANGED_BASIC_RATES, this enables mcast rate configuration through fixed rate tables. Signed-off-by: Ryder Lee Change-Id: Ifc305e8c7de9a7df4ad5f856e2097d721a886aaa Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 +++++++++--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 3 ++- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 + 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index c8ada309d73f..fbb92c39beee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1070,8 +1070,14 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, mt7996_mac_write_txwi_80211(dev, txwi, skb, key); if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool mcast = ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1); u8 idx = mvif->basic_rates_idx; + if (mcast && mvif->mcast_rates_idx) + idx = mvif->mcast_rates_idx; + txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx); txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 1243e5f925ad..f861fbb7de47 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -503,14 +503,15 @@ mt7996_update_bss_color(struct ieee80211_hw *hw, } static u8 -mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + bool mcast) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt76_phy *mphy = hw->priv; u16 rate; u8 i, idx; - rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, false); + rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, mcast); idx = FIELD_GET(MT_TX_RATE_IDX, rate); for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) @@ -557,8 +558,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, } } + if (changed & BSS_CHANGED_MCAST_RATE) + mvif->mcast_rates_idx = + mt7996_get_rates_table(hw, vif, true); + if (changed & BSS_CHANGED_BASIC_RATES) - mvif->basic_rates_idx = mt7996_get_rates_table(hw, vif); + mvif->basic_rates_idx = + mt7996_get_rates_table(hw, vif, false); if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { mt7996_mcu_add_bss_info(phy, vif, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 3db74ae109dc..f96992b55c7a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -605,7 +605,8 @@ mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; struct tlv *tlv; - u8 idx = mvif->basic_rates_idx; + u8 idx = mvif->mcast_rates_idx ? + mvif->mcast_rates_idx : mvif->basic_rates_idx; tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 5cf5ea8cece9..a1a6ee0de2ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -125,6 +125,7 @@ struct mt7996_vif { struct cfg80211_bitrate_mask bitrate_mask; u8 basic_rates_idx; + u8 mcast_rates_idx; }; /* per-phy stats. */ -- cgit From c2171b068beea766311e4c2858ef8497504c6e6d Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Fri, 14 Apr 2023 04:23:33 +0800 Subject: wifi: mt76: mt7996: enable configured beacon tx rate The user is allowed to change beacon tx rate (HT/VHT/HE) from hostapd. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt7996/main.c | 26 +++++++++++++++++----- drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 ++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index fbb92c39beee..1ae2c85e66ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1077,6 +1077,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, if (mcast && mvif->mcast_rates_idx) idx = mvif->mcast_rates_idx; + else if (beacon && mvif->beacon_rates_idx) + idx = mvif->beacon_rates_idx; txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx); txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index f861fbb7de47..0975774fe244 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -504,14 +504,24 @@ mt7996_update_bss_color(struct ieee80211_hw *hw, static u8 mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - bool mcast) + bool beacon, bool mcast) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt76_phy *mphy = hw->priv; u16 rate; - u8 i, idx; + u8 i, idx, ht; - rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, mcast); + rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); + ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM; + + if (beacon && ht) { + struct mt7996_dev *dev = mt7996_hw_dev(hw); + + /* must odd index */ + idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20); + mt7996_mac_set_fixed_rate_table(dev, idx, rate); + return idx; + } idx = FIELD_GET(MT_TX_RATE_IDX, rate); for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) @@ -560,11 +570,11 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_MCAST_RATE) mvif->mcast_rates_idx = - mt7996_get_rates_table(hw, vif, true); + mt7996_get_rates_table(hw, vif, false, true); if (changed & BSS_CHANGED_BASIC_RATES) mvif->basic_rates_idx = - mt7996_get_rates_table(hw, vif, false); + mt7996_get_rates_table(hw, vif, false, false); if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { mt7996_mcu_add_bss_info(phy, vif, true); @@ -582,8 +592,12 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, mt7996_update_bss_color(hw, vif, &info->he_bss_color); if (changed & (BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_ENABLED)) + BSS_CHANGED_BEACON_ENABLED)) { + mvif->beacon_rates_idx = + mt7996_get_rates_table(hw, vif, true, false); + mt7996_mcu_add_beacon(hw, vif, info->enable_beacon); + } if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || changed & BSS_CHANGED_FILS_DISCOVERY) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index a1a6ee0de2ff..4d7dcb95a620 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -45,6 +45,7 @@ /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ #define MT7996_BASIC_RATES_TBL 11 +#define MT7996_BEACON_RATES_TBL 25 struct mt7996_vif; struct mt7996_sta; @@ -126,6 +127,7 @@ struct mt7996_vif { u8 basic_rates_idx; u8 mcast_rates_idx; + u8 beacon_rates_idx; }; /* per-phy stats. */ -- cgit From 27db47ab1f47906c2392f9d246e244e412b19278 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sun, 12 Mar 2023 14:11:25 +0800 Subject: wifi: mt76: mt7996: enable mesh HW amsdu/de-amsdu support This enables HW offloading amsdu/de-amsdu support for 802.11s mesh interface. Co-developed-by: Bo Jiao Signed-off-by: Bo Jiao Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 24 ++++++++++++++++-------- drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 7 +++++++ drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 1 + 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 1ae2c85e66ac..0639bd3808c6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -641,6 +641,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) u32 rxd4 = le32_to_cpu(rxd[4]); u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; u32 csum_status = *(u32 *)skb->cb; + u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP; + bool is_mesh = (rxd0 & mesh_mask) == mesh_mask; bool unicast, insert_ccmp_hdr = false; u8 remove_pad, amsdu_info, band_idx; u8 mode = 0, qos_ctl = 0; @@ -832,19 +834,16 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) int pad_start = 0; skb_pull(skb, hdr_gap); - if (!hdr_trans && status->amsdu) { + if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) { pad_start = ieee80211_get_hdrlen_from_skb(skb); - } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) && + get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) { /* When header translation failure is indicated, * the hardware will insert an extra 2-byte field * containing the data length after the protocol * type field. */ - pad_start = 12; - if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) - pad_start += 4; - else - pad_start = 0; + pad_start = 16; } if (pad_start) { @@ -865,8 +864,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) hdr = mt76_skb_get_hdr(skb); fc = hdr->frame_control; if (ieee80211_is_data_qos(fc)) { + u8 *qos = ieee80211_get_qos_ctl(hdr); + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); - qos_ctl = *ieee80211_get_qos_ctl(hdr); + qos_ctl = *qos; + + /* Mesh DA/SA/Length will be stripped after hardware + * de-amsdu, so here needs to clear amsdu present bit + * to mark it as a normal mesh frame. + */ + if (ieee80211_has_a4(fc) && is_mesh && status->amsdu) + *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; } } else { status->flag |= RX_FLAG_8023; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index b2bbe0e09e26..bc4e6c55373e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -12,6 +12,8 @@ #define MT_RXD0_LENGTH GENMASK(15, 0) #define MT_RXD0_PKT_TYPE GENMASK(31, 27) +#define MT_RXD0_MESH BIT(18) +#define MT_RXD0_MHCP BIT(19) #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) #define MT_RXD0_NORMAL_IP_SUM BIT(23) #define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index f96992b55c7a..88e2f9d0e513 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1022,6 +1022,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, struct tlv *tlv; if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_MESH_POINT && vif->type != NL80211_IFTYPE_AP) return; @@ -1470,6 +1471,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb, hdr_trans->to_ds = true; hdr_trans->from_ds = true; } + + if (vif->type == NL80211_IFTYPE_MESH_POINT) { + hdr_trans->to_ds = true; + hdr_trans->from_ds = true; + hdr_trans->mesh = true; + } } static enum mcu_mmps_mode diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index 6f92b9a7d86d..d7075a4d0667 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -396,7 +396,7 @@ struct sta_rec_hdr_trans { u8 from_ds; u8 to_ds; u8 dis_rx_hdr_tran; - u8 rsv; + u8 mesh; } __packed; struct hdr_trans_en { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 879b0e90b52e..3a591a7b47ae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -327,6 +327,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, /* txwi_size = txd size + txp size */ .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp), .drv_flags = MT_DRV_TXWI_NO_FREE | + MT_DRV_AMSDU_OFFLOAD | MT_DRV_HW_MGMT_TXQ, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | -- cgit From e12b2e99b8799f26432528934edc8677888ad72f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Nov 2022 19:50:46 +0100 Subject: wifi: mt76: mt7615: increase eeprom size for mt7663 mt7663 efuse has 0x600 bytes instead of 0x400. Increase the size in order to fix issues with incomplete calibration data Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 7 ++++++- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 6dbaaf95ee38..68e88224b8b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -47,6 +47,9 @@ static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base) void *buf; u32 val; + if (is_mt7663(&dev->mt76)) + len = MT7663_EEPROM_SIZE; + val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); if (val & MT_EFUSE_BASE_CTRL_EMPTY) return 0; @@ -72,6 +75,8 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr) { int ret; + BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE); + ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE); if (ret < 0) return ret; @@ -336,7 +341,7 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr) ret = mt7615_check_eeprom(&dev->mt76); if (ret && dev->mt76.otp.data) { memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, - MT7615_EEPROM_SIZE); + dev->mt76.otp.size); } else { dev->flash_eeprom = true; mt7615_cal_free_data(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index a024dee10362..a67fbb90f5b3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -46,7 +46,7 @@ enum mt7615_eeprom_field { MT7615_EE_MAX = 0x3bf, MT7622_EE_MAX = 0x3db, - MT7663_EE_MAX = 0x400, + MT7663_EE_MAX = 0x600, }; #define MT_EE_RATE_POWER_MASK GENMASK(5, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 932cdad7e7d4..0381c53bc96a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -51,6 +51,7 @@ #define MT7663_FIRMWARE_N9 "mediatek/mt7663_n9_rebb.bin" #define MT7615_EEPROM_SIZE 1024 +#define MT7663_EEPROM_SIZE 1536 #define MT7615_TOKEN_SIZE 4096 #define MT_FRAC_SCALE 12 -- cgit From f4d63a87b527de258eec5bd6e9547f063d472b79 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 31 Dec 2022 08:44:33 +0100 Subject: wifi: mt76: dma: use napi_build_skb Improves performance by using bulk allocation Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6c0174313d09..465190ebaf1c 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -853,7 +853,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) !(dev->drv->rx_check(dev, data, len))) goto free_frag; - skb = build_skb(data, q->buf_size); + skb = napi_build_skb(data, q->buf_size); if (!skb) goto free_frag; -- cgit From 230a167e094770fdcc104481719ef7b1a706fb27 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 30 Mar 2023 11:07:52 +0200 Subject: wifi: mt76: set NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 on supported drivers Drivers that do not generate IV/PN in software can safely rekey PTK0 Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 5fa6f097ec30..621e69f07e3c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -396,6 +396,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 538ec0f8e630..ac2049f49bb3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -369,6 +369,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); if (!is_mt7915(&dev->mt76)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 5955c7c5b91a..e929f6eb65ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -124,6 +124,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, HAS_RATE_CONTROL); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 90a92c1611f3..f1b48cdda58f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -182,6 +182,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); if (!mdev->dev->of_node || !of_property_read_bool(mdev->dev->of_node, -- cgit From 3b522cadedfe6e9e0e8193d7d4ab5aa8d0c73209 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 19 Apr 2023 13:58:40 +0800 Subject: wifi: mt76: mt7996: fill txd by host driver The hardware SDO has issue to fill txd for the moment, so fallback to driver filling method. Fixes: 98686cd21624 (wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices) Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 0639bd3808c6..130eb7b4fd91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1132,11 +1132,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - memset(txwi_ptr, 0, MT_TXD_SIZE); - /* Transmit non qos data by 802.11 header and need to fill txd by host*/ - if (!is_8023 || pid >= MT_PACKET_ID_FIRST) - mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, - pid, qid, 0); + mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, + pid, qid, 0); txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { @@ -1145,10 +1142,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, } txp->fw.nbuf = nbuf; - txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST); - - if (!is_8023 || pid >= MT_PACKET_ID_FIRST) - txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD); + txp->fw.flags = + cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD); if (!key) txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); -- cgit