summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/mt7921
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/Makefile4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/init.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.c470
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.h10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c208
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c164
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.h43
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h29
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h51
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c24
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/regs.h37
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/trace.c12
14 files changed, 686 insertions, 390 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
index 09d1446ad933..e531666f9fb4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
@@ -2,4 +2,6 @@
obj-$(CONFIG_MT7921E) += mt7921e.o
-mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o
+CFLAGS_trace.o := -I$(src)
+
+mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o trace.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
index c1a64ff6a197..94f0320ab2d4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -44,14 +44,13 @@ mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
for (i = 0; i < ARRAY_SIZE(bound); i++)
- bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1;
+ bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
seq_printf(file, "\nPhy0\n");
seq_printf(file, "Length: %8d | ", bound[0]);
for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
- seq_printf(file, "%3d -%3d | ",
- bound[i] + 1, bound[i + 1]);
+ seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]);
seq_puts(file, "\nCount: ");
for (i = 0; i < ARRAY_SIZE(bound); i++)
@@ -152,7 +151,6 @@ mt7921_pm_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt76_phy *mphy = dev->phy.mt76;
- int ret = 0;
mt7921_mutex_acquire(dev);
@@ -163,7 +161,7 @@ mt7921_pm_set(void *data, u64 val)
mt7921_pm_interface_iter, mphy->priv);
mt7921_mutex_release(dev);
- return ret;
+ return 0;
}
static int
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index cd9665610284..992faf82ad09 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -299,7 +299,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
if (ret < 0)
return ret;
- netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
+ netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt7921_poll_tx, NAPI_POLL_WEIGHT);
napi_enable(&dev->mt76.tx_napi);
@@ -323,7 +323,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
- mt76_set(dev, 0x54000120, BIT(1));
+ 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 |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 89a13b4a74a4..5bb0a7b9e9e5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -77,6 +77,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
+ hw->radiotap_timestamp.units_pos =
+ IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
+
phy->slottime = 9;
hw->sta_data_size = sizeof(struct mt7921_sta);
@@ -95,6 +98,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy->reg_notifier = mt7921_regd_notifier;
+ wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
@@ -142,7 +146,7 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
}
-static void mt7921_mac_init(struct mt7921_dev *dev)
+void mt7921_mac_init(struct mt7921_dev *dev)
{
int i;
@@ -232,7 +236,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
- init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
ret = mt7921_init_hardware(dev);
@@ -250,9 +253,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
- dev->mphy.sband_5g.sband.vht_cap.cap |=
- IEEE80211_VHT_CAP_SHORT_GI_160 |
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
@@ -273,8 +273,6 @@ void mt7921_unregister_device(struct mt7921_dev *dev)
{
mt76_unregister_device(&dev->mt76);
mt7921_mcu_exit(dev);
- mt7921_dma_cleanup(dev);
-
mt7921_tx_token_put(dev);
tasklet_disable(&dev->irq_tasklet);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 3f9097481a5e..b507f3917830 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -9,8 +9,6 @@
#include "mac.h"
#include "mcu.h"
-#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
-
#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
IEEE80211_RADIOTAP_HE_##f)
@@ -51,14 +49,6 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
0, 5000);
}
-static u32 mt7921_mac_wtbl_lmac_addr(struct mt7921_dev *dev, u16 wcid)
-{
- mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
- FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
-
- return MT_WTBL_LMAC_OFFS(wcid, 0);
-}
-
static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
{
static const u8 ac_to_tid[] = {
@@ -95,7 +85,7 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
spin_unlock_bh(&dev->sta_poll_lock);
idx = msta->wcid.idx;
- addr = mt7921_mac_wtbl_lmac_addr(dev, idx) + 20 * 4;
+ addr = MT_WTBL_LMAC_OFFS(idx, 0) + 20 * 4;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u32 tx_last = msta->airtime_ac[i];
@@ -285,6 +275,37 @@ mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy,
status->freq = ieee80211_channel_to_frequency(chfreq, status->band);
}
+static void
+mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct sk_buff *skb = priv;
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
+
+ if (status->signal > 0)
+ return;
+
+ if (!ether_addr_equal(vif->addr, hdr->addr1))
+ return;
+
+ ewma_rssi_add(&mvif->rssi, -status->signal);
+}
+
+static void
+mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
+
+ if (!ieee80211_is_assoc_resp(hdr->frame_control) &&
+ !ieee80211_is_auth(hdr->frame_control))
+ return;
+
+ ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7921_mac_rssi_iter, skb);
+}
+
int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
@@ -349,19 +370,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
}
- if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
- status->flag |= RX_FLAG_AMPDU_DETAILS;
-
- /* all subframes of an A-MPDU have the same timestamp */
- if (phy->rx_ampdu_ts != rxd[14]) {
- if (!++phy->ampdu_ref)
- phy->ampdu_ref++;
- }
- phy->rx_ampdu_ts = rxd[14];
-
- status->ampdu_ref = phy->ampdu_ref;
- }
-
remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2);
if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
@@ -393,6 +401,22 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
}
if (rxd1 & MT_RXD1_NORMAL_GROUP_2) {
+ status->timestamp = le32_to_cpu(rxd[0]);
+ status->flag |= RX_FLAG_MACTIME_START;
+
+ if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) {
+ status->flag |= RX_FLAG_AMPDU_DETAILS;
+
+ /* all subframes of an A-MPDU have the same timestamp */
+ if (phy->rx_ampdu_ts != status->timestamp) {
+ if (!++phy->ampdu_ref)
+ phy->ampdu_ref++;
+ }
+ phy->rx_ampdu_ts = status->timestamp;
+
+ status->ampdu_ref = phy->ampdu_ref;
+ }
+
rxd += 2;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
@@ -400,7 +424,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
/* RXD Group 3 - P-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
- u32 v0, v1, v2;
+ u8 stbc, gi;
+ u32 v0, v1;
+ bool cck;
rxv = rxd;
rxd += 2;
@@ -409,7 +435,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
v0 = le32_to_cpu(rxv[0]);
v1 = le32_to_cpu(rxv[1]);
- v2 = le32_to_cpu(rxv[2]);
if (v0 & MT_PRXV_HT_AD_CODE)
status->enc_flags |= RX_ENC_FLAG_LDPC;
@@ -429,87 +454,87 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->chain_signal[i]);
}
- /* RXD Group 5 - C-RXV */
- if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
- u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
- u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
- bool cck = false;
+ stbc = FIELD_GET(MT_PRXV_STBC, v0);
+ gi = FIELD_GET(MT_PRXV_SGI, v0);
+ cck = false;
- rxd += 18;
- if ((u8 *)rxd - skb->data >= skb->len)
- return -EINVAL;
+ idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
+ mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
- idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
- mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
-
- switch (mode) {
- case MT_PHY_TYPE_CCK:
- cck = true;
- fallthrough;
- case MT_PHY_TYPE_OFDM:
- i = mt76_get_rate(&dev->mt76, sband, i, cck);
- break;
- case MT_PHY_TYPE_HT_GF:
- case MT_PHY_TYPE_HT:
- status->encoding = RX_ENC_HT;
- if (i > 31)
- return -EINVAL;
- break;
- case MT_PHY_TYPE_VHT:
- status->nss =
- FIELD_GET(MT_PRXV_NSTS, v0) + 1;
- status->encoding = RX_ENC_VHT;
- if (i > 9)
- return -EINVAL;
- break;
- case MT_PHY_TYPE_HE_MU:
- status->flag |= RX_FLAG_RADIOTAP_HE_MU;
- fallthrough;
- case MT_PHY_TYPE_HE_SU:
- case MT_PHY_TYPE_HE_EXT_SU:
- case MT_PHY_TYPE_HE_TB:
- status->nss =
- FIELD_GET(MT_PRXV_NSTS, v0) + 1;
- status->encoding = RX_ENC_HE;
- status->flag |= RX_FLAG_RADIOTAP_HE;
- i &= GENMASK(3, 0);
-
- if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
- status->he_gi = gi;
-
- status->he_dcm = !!(idx & MT_PRXV_TX_DCM);
- break;
- default:
+ switch (mode) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ fallthrough;
+ case MT_PHY_TYPE_OFDM:
+ i = mt76_get_rate(&dev->mt76, sband, i, cck);
+ break;
+ case MT_PHY_TYPE_HT_GF:
+ case MT_PHY_TYPE_HT:
+ status->encoding = RX_ENC_HT;
+ if (i > 31)
return -EINVAL;
- }
- status->rate_idx = i;
-
- switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) {
- case IEEE80211_STA_RX_BW_20:
- break;
- case IEEE80211_STA_RX_BW_40:
- if (mode & MT_PHY_TYPE_HE_EXT_SU &&
- (idx & MT_PRXV_TX_ER_SU_106T)) {
- status->bw = RATE_INFO_BW_HE_RU;
- status->he_ru =
- NL80211_RATE_INFO_HE_RU_ALLOC_106;
- } else {
- status->bw = RATE_INFO_BW_40;
- }
- break;
- case IEEE80211_STA_RX_BW_80:
- status->bw = RATE_INFO_BW_80;
- break;
- case IEEE80211_STA_RX_BW_160:
- status->bw = RATE_INFO_BW_160;
- break;
- default:
+ break;
+ case MT_PHY_TYPE_VHT:
+ status->nss =
+ FIELD_GET(MT_PRXV_NSTS, v0) + 1;
+ status->encoding = RX_ENC_VHT;
+ if (i > 9)
return -EINVAL;
+ break;
+ case MT_PHY_TYPE_HE_MU:
+ status->flag |= RX_FLAG_RADIOTAP_HE_MU;
+ fallthrough;
+ case MT_PHY_TYPE_HE_SU:
+ case MT_PHY_TYPE_HE_EXT_SU:
+ case MT_PHY_TYPE_HE_TB:
+ status->nss =
+ FIELD_GET(MT_PRXV_NSTS, v0) + 1;
+ status->encoding = RX_ENC_HE;
+ status->flag |= RX_FLAG_RADIOTAP_HE;
+ i &= GENMASK(3, 0);
+
+ if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
+ status->he_gi = gi;
+
+ status->he_dcm = !!(idx & MT_PRXV_TX_DCM);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ status->rate_idx = i;
+
+ switch (FIELD_GET(MT_PRXV_FRAME_MODE, v0)) {
+ case IEEE80211_STA_RX_BW_20:
+ break;
+ case IEEE80211_STA_RX_BW_40:
+ if (mode & MT_PHY_TYPE_HE_EXT_SU &&
+ (idx & MT_PRXV_TX_ER_SU_106T)) {
+ status->bw = RATE_INFO_BW_HE_RU;
+ status->he_ru =
+ NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ } else {
+ status->bw = RATE_INFO_BW_40;
}
+ break;
+ case IEEE80211_STA_RX_BW_80:
+ status->bw = RATE_INFO_BW_80;
+ break;
+ case IEEE80211_STA_RX_BW_160:
+ status->bw = RATE_INFO_BW_160;
+ break;
+ default:
+ return -EINVAL;
+ }
- status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
- if (mode < MT_PHY_TYPE_HE_SU && gi)
- status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
+ if (mode < MT_PHY_TYPE_HE_SU && gi)
+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+
+ if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
+ rxd += 18;
+ if ((u8 *)rxd - skb->data >= skb->len)
+ return -EINVAL;
}
}
@@ -521,6 +546,8 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
mt76_insert_ccmp_hdr(skb, key_id);
}
+ mt7921_mac_assoc_rssi(dev, skb);
+
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
@@ -530,7 +557,7 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
- status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
return 0;
@@ -1183,43 +1210,76 @@ void mt7921_update_channel(struct mt76_dev *mdev)
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
}
-static bool
-mt7921_wait_reset_state(struct mt7921_dev *dev, u32 state)
+int mt7921_wfsys_reset(struct mt7921_dev *dev)
{
- bool ret;
+ mt76_set(dev, 0x70002600, BIT(0));
+ msleep(200);
+ mt76_clear(dev, 0x70002600, BIT(0));
- ret = wait_event_timeout(dev->reset_wait,
- (READ_ONCE(dev->reset_state) & state),
- MT7921_RESET_TIMEOUT);
-
- WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
- return ret;
+ return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B,
+ WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500);
}
static void
-mt7921_dma_reset(struct mt7921_phy *phy)
+mt7921_dma_reset(struct mt7921_dev *dev)
{
- struct mt7921_dev *dev = phy->dev;
int i;
+ /* 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 WFDMA0 */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
- usleep_range(1000, 2000);
+ mt76_poll(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
+ MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
+ /* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++)
- mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true);
+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
- mt76_for_each_q_rx(&dev->mt76, i) {
- mt76_queue_rx_reset(dev, 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]);
- /* re-init prefetch settings after reset */
+ /* configure perfetch settings */
mt7921_dma_prefetch(dev);
+ /* reset dma idx */
+ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
+
+ /* configure delay interrupt */
+ mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
+
+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
+ MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+
+ 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);
}
void mt7921_tx_token_put(struct mt7921_dev *dev)
@@ -1243,71 +1303,125 @@ void mt7921_tx_token_put(struct mt7921_dev *dev)
idr_destroy(&dev->token);
}
-/* system error recovery */
-void mt7921_mac_reset_work(struct work_struct *work)
+static void
+mt7921_vif_connect_iter(void *priv, u8 *mac,
+ struct ieee80211_vif *vif)
{
- struct mt7921_dev *dev;
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct mt7921_dev *dev = mvif->phy->dev;
- dev = container_of(work, struct mt7921_dev, reset_work);
+ ieee80211_disconnect(vif, true);
- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
- return;
+ mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
+ mt7921_mcu_set_tx(dev, vif);
+}
- ieee80211_stop_queues(mt76_hw(dev));
+static int
+mt7921_mac_reset(struct mt7921_dev *dev)
+{
+ int i, err;
+
+ mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
+
+ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
- set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
- cancel_delayed_work_sync(&dev->mphy.mac_work);
+ skb_queue_purge(&dev->mt76.mcu.res_q);
- /* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
- napi_disable(&dev->mt76.napi[0]);
- napi_disable(&dev->mt76.napi[1]);
- napi_disable(&dev->mt76.napi[2]);
+ napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
+ napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
+ napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
napi_disable(&dev->mt76.tx_napi);
- mt7921_mutex_acquire(dev);
-
- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
-
mt7921_tx_token_put(dev);
idr_init(&dev->token);
- if (mt7921_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
- mt7921_dma_reset(&dev->phy);
+ /* clean up hw queues */
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++)
+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
- mt7921_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
- }
+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
- clear_bit(MT76_MCU_RESET, &dev->mphy.state);
- clear_bit(MT76_RESET, &dev->mphy.state);
+ mt76_for_each_q_rx(&dev->mt76, i)
+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
+
+ mt7921_wfsys_reset(dev);
+ mt7921_dma_reset(dev);
+
+ mt76_for_each_q_rx(&dev->mt76, i) {
+ mt76_queue_rx_reset(dev, i);
+ napi_enable(&dev->mt76.napi[i]);
+ napi_schedule(&dev->mt76.napi[i]);
+ }
- mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
+ mt76_worker_enable(&dev->mt76.tx_worker);
+
+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+
+ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
+ 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);
+
+ err = mt7921_run_firmware(dev);
+ if (err)
+ return err;
- napi_enable(&dev->mt76.napi[0]);
- napi_schedule(&dev->mt76.napi[0]);
+ err = mt7921_mcu_set_eeprom(dev);
+ if (err)
+ return err;
- napi_enable(&dev->mt76.napi[1]);
- napi_schedule(&dev->mt76.napi[1]);
+ mt7921_mac_init(dev);
+ return __mt7921_start(&dev->phy);
+}
- napi_enable(&dev->mt76.napi[2]);
- napi_schedule(&dev->mt76.napi[2]);
+/* system error recovery */
+void mt7921_mac_reset_work(struct work_struct *work)
+{
+ struct ieee80211_hw *hw;
+ struct mt7921_dev *dev;
+ int i;
- ieee80211_wake_queues(mt76_hw(dev));
+ dev = container_of(work, struct mt7921_dev, reset_work);
+ hw = mt76_hw(dev);
- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
- mt7921_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
+ dev_err(dev->mt76.dev, "chip reset\n");
+ ieee80211_stop_queues(hw);
- mt7921_mutex_release(dev);
+ cancel_delayed_work_sync(&dev->mphy.mac_work);
+ cancel_delayed_work_sync(&dev->pm.ps_work);
+ cancel_work_sync(&dev->pm.wake_work);
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
- MT7921_WATCHDOG_TIME);
+ mutex_lock(&dev->mt76.mutex);
+ for (i = 0; i < 10; i++) {
+ if (!mt7921_mac_reset(dev))
+ break;
+ }
+ mutex_unlock(&dev->mt76.mutex);
+
+ if (i == 10)
+ dev_err(dev->mt76.dev, "chip reset failed\n");
+
+ ieee80211_wake_queues(hw);
+ ieee80211_iterate_active_interfaces(hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7921_vif_connect_iter, 0);
+}
+
+void mt7921_reset(struct mt76_dev *mdev)
+{
+ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+
+ queue_work(dev->mt76.wq, &dev->reset_work);
}
static void
@@ -1317,31 +1431,20 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
struct mib_stats *mib = &phy->mib;
int i, aggr0 = 0, aggr1;
- memset(mib, 0, sizeof(*mib));
-
- mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(0),
- MT_MIB_SDR3_FCS_ERR_MASK);
+ mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0),
+ MT_MIB_SDR3_FCS_ERR_MASK);
+ mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0),
+ MT_MIB_ACK_FAIL_COUNT_MASK);
+ mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0),
+ MT_MIB_BA_FAIL_COUNT_MASK);
+ mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0),
+ MT_MIB_RTS_COUNT_MASK);
+ mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0),
+ MT_MIB_RTS_FAIL_COUNT_MASK);
for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {
u32 val, val2;
- val = mt76_rr(dev, MT_MIB_MB_SDR1(0, i));
-
- val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
- if (val2 > mib->ack_fail_cnt)
- mib->ack_fail_cnt = val2;
-
- val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
- if (val2 > mib->ba_miss_cnt)
- mib->ba_miss_cnt = val2;
-
- val = mt76_rr(dev, MT_MIB_MB_SDR0(0, i));
- val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
- if (val2 > mib->rts_retries_cnt) {
- mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
- mib->rts_retries_cnt = val2;
- }
-
val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
@@ -1399,7 +1502,7 @@ void mt7921_mac_work(struct work_struct *work)
if (++phy->sta_work_count == 10) {
phy->sta_work_count = 0;
mt7921_mac_sta_stats_work(phy);
- };
+ }
mt7921_mutex_release(phy->dev);
@@ -1503,8 +1606,10 @@ void mt7921_coredump_work(struct work_struct *work)
break;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
- if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ)
- break;
+ if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
+ dev_kfree_skb(skb);
+ continue;
+ }
memcpy(data, skb->data, skb->len);
data += skb->len;
@@ -1513,4 +1618,5 @@ void mt7921_coredump_work(struct work_struct *work)
}
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
GFP_KERNEL);
+ mt7921_reset(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
index a0c1fa0f20e4..109c8849d106 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
@@ -97,18 +97,24 @@ enum rx_pkt_type {
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
-/* P-RXV */
+/* P-RXV DW0 */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)
#define MT_PRXV_TX_ER_SU_106T BIT(5)
#define MT_PRXV_NSTS GENMASK(9, 7)
#define MT_PRXV_HT_AD_CODE BIT(11)
+#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
+#define MT_PRXV_SGI GENMASK(16, 15)
+#define MT_PRXV_STBC GENMASK(23, 22)
+#define MT_PRXV_TX_MODE GENMASK(27, 24)
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
-#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
+
+/* P-RXV DW1 */
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
+#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
/* C-RXV */
#define MT_CRXV_HT_STBC GENMASK(1, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 729f6c42cdde..d9ec7d9bb1c4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -125,10 +125,6 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
- he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
- he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
- he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
- he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
@@ -169,28 +165,44 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy)
}
}
-static int mt7921_start(struct ieee80211_hw *hw)
+int __mt7921_start(struct mt7921_phy *phy)
{
- struct mt7921_dev *dev = mt7921_hw_dev(hw);
- struct mt7921_phy *phy = mt7921_hw_phy(hw);
+ struct mt76_phy *mphy = phy->mt76;
+ int err;
- mt7921_mutex_acquire(dev);
+ err = mt76_connac_mcu_set_mac_enable(mphy->dev, 0, true, false);
+ if (err)
+ return err;
- mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
- mt76_connac_mcu_set_channel_domain(phy->mt76);
+ err = mt76_connac_mcu_set_channel_domain(mphy);
+ if (err)
+ return err;
+
+ err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+ if (err)
+ return err;
- mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
mt7921_mac_reset_counters(phy);
- set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ set_bit(MT76_STATE_RUNNING, &mphy->state);
- ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+ ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7921_WATCHDOG_TIME);
- mt7921_mutex_release(dev);
-
return 0;
}
+static int mt7921_start(struct ieee80211_hw *hw)
+{
+ struct mt7921_phy *phy = mt7921_hw_phy(hw);
+ int err;
+
+ mt7921_mutex_acquire(phy->dev);
+ err = __mt7921_start(phy);
+ mt7921_mutex_release(phy->dev);
+
+ return err;
+}
+
static void mt7921_stop(struct ieee80211_hw *hw)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
@@ -224,9 +236,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
if (i)
return i - 1;
- if (type != NL80211_IFTYPE_STATION)
- break;
-
/* next, try to find a free repeater entry for the sta */
i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
REPEATER_BSSID_MAX - REPEATER_BSSID_START);
@@ -295,15 +304,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out;
- if (dev->pm.enable) {
- ret = mt7921_mcu_set_bss_pm(dev, vif, true);
- if (ret)
- goto out;
-
- vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
- mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
- }
-
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
@@ -318,6 +318,8 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
mt7921_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+ ewma_rssi_init(&mvif->rssi);
+
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
@@ -348,19 +350,12 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
if (vif == phy->monitor_vif)
phy->monitor_vif = NULL;
+ mt7921_mutex_acquire(dev);
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
-
- if (dev->pm.enable) {
- mt7921_mcu_set_bss_pm(dev, vif, false);
- mt76_clear(dev, MT_WF_RFCR(0),
- MT_WF_RFCR_DROP_OTHER_BEACON);
- }
-
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
- mt7921_mutex_acquire(dev);
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mt7921_mutex_release(dev);
@@ -413,7 +408,8 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv :
&mvif->sta;
struct mt76_wcid *wcid = &msta->wcid;
- int idx = key->keyidx;
+ u8 *wcid_keyidx = &wcid->hw_key_idx;
+ int idx = key->keyidx, err = 0;
/* The hardware does not support per-STA RX GTK, fallback
* to software mode for these.
@@ -429,6 +425,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_AES_CMAC:
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+ wcid_keyidx = &wcid->hw_key_idx2;
break;
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
@@ -443,23 +440,29 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
- if (cmd == SET_KEY) {
- key->hw_key_idx = wcid->idx;
- wcid->hw_key_idx = idx;
- } else if (idx == wcid->hw_key_idx) {
- wcid->hw_key_idx = -1;
- }
+ mt7921_mutex_acquire(dev);
+
+ if (cmd == SET_KEY)
+ *wcid_keyidx = idx;
+ else if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
+ else
+ goto out;
+
mt76_wcid_key_setup(&dev->mt76, wcid,
cmd == SET_KEY ? key : NULL);
- return mt7921_mcu_add_key(dev, vif, msta, key, cmd);
+ err = mt7921_mcu_add_key(dev, vif, msta, key, cmd);
+out:
+ mt7921_mutex_release(dev);
+
+ return err;
}
static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt7921_phy *phy = mt7921_hw_phy(hw);
- bool band = phy != &dev->phy;
int ret;
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -480,9 +483,9 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
else
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
- mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
+ mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN,
enabled);
- mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
+ mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
}
mt7921_mutex_release(dev);
@@ -511,7 +514,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt7921_phy *phy = mt7921_hw_phy(hw);
- bool band = phy != &dev->phy;
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
MT_WF_RFCR1_DROP_BF_POLL |
MT_WF_RFCR1_DROP_BA |
@@ -551,16 +553,46 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
MT_WF_RFCR_DROP_NDPA);
*total_flags = flags;
- mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
+ mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
if (*total_flags & FIF_CONTROL)
- mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
+ mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags);
else
- mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);
+ mt76_set(dev, MT_WF_RFCR1(0), ctl_flags);
mt7921_mutex_release(dev);
}
+static int
+mt7921_bss_bcnft_apply(struct mt7921_dev *dev, struct ieee80211_vif *vif,
+ bool assoc)
+{
+ int ret;
+
+ if (!dev->pm.enable)
+ return 0;
+
+ if (assoc) {
+ ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true);
+ if (ret)
+ return ret;
+
+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+ mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
+
+ return 0;
+ }
+
+ ret = mt7921_mcu_set_bss_pm(dev, vif, false);
+ if (ret)
+ return ret;
+
+ vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
+ mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
+
+ return 0;
+}
+
static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@@ -587,6 +619,12 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_PS)
mt7921_mcu_uni_bss_ps(dev, vif);
+ if (changed & BSS_CHANGED_ASSOC)
+ mt7921_bss_bcnft_apply(dev, vif, info->assoc);
+
+ if (changed & BSS_CHANGED_ARP_FILTER)
+ mt7921_mcu_update_arp_filter(hw, vif, info);
+
mt7921_mutex_release(dev);
}
@@ -596,6 +634,15 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ int rssi = -ewma_rssi_read(&mvif->rssi);
+ struct mt76_sta_cmd_info info = {
+ .sta = sta,
+ .vif = vif,
+ .enable = true,
+ .cmd = MCU_UNI_CMD_STA_REC_UPDATE,
+ .wcid = &msta->wcid,
+ .rcpi = to_rcpi(rssi),
+ };
int ret, idx;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
@@ -622,8 +669,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7921_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
- ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid,
- true, MCU_UNI_CMD_STA_REC_UPDATE);
+ ret = mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
if (ret)
return ret;
@@ -637,21 +683,28 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
+ struct mt76_sta_cmd_info info = {
+ .sta = sta,
+ .vif = vif,
+ .cmd = MCU_UNI_CMD_STA_REC_UPDATE,
+ .wcid = &msta->wcid,
+ };
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
mt76_connac_pm_wake(&dev->mphy, &dev->pm);
- mt76_connac_mcu_add_sta_cmd(&dev->mphy, vif, sta, &msta->wcid, false,
- MCU_UNI_CMD_STA_REC_UPDATE);
+ mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
mt7921_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
- mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
- false);
+ ewma_rssi_init(&mvif->rssi);
+ if (!sta->tdls)
+ mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
+ &mvif->sta.wcid, false);
}
spin_lock_bh(&dev->sta_poll_lock);
@@ -814,11 +867,17 @@ mt7921_get_stats(struct ieee80211_hw *hw,
struct mt7921_phy *phy = mt7921_hw_phy(hw);
struct mib_stats *mib = &phy->mib;
+ mt7921_mutex_acquire(phy->dev);
+
stats->dot11RTSSuccessCount = mib->rts_cnt;
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
+ memset(mib, 0, sizeof(*mib));
+
+ mt7921_mutex_release(phy->dev);
+
return 0;
}
@@ -827,9 +886,7 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_dev *dev = mt7921_hw_dev(hw);
- struct mt7921_phy *phy = mt7921_hw_phy(hw);
u8 omac_idx = mvif->mt76.omac_idx;
- bool band = phy != &dev->phy;
union {
u64 t64;
u32 t32[2];
@@ -840,9 +897,9 @@ mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
/* TSF software read */
- mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE);
- tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
- tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
+ mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE);
+ tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0));
+ tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0));
mt7921_mutex_release(dev);
@@ -855,9 +912,7 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_dev *dev = mt7921_hw_dev(hw);
- struct mt7921_phy *phy = mt7921_hw_phy(hw);
u8 omac_idx = mvif->mt76.omac_idx;
- bool band = phy != &dev->phy;
union {
u64 t64;
u32 t32[2];
@@ -867,10 +922,10 @@ mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt7921_mutex_acquire(dev);
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
- mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
- mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
+ mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]);
+ mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]);
/* TSF software overwrite */
- mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE);
+ mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE);
mt7921_mutex_release(dev);
}
@@ -1008,14 +1063,6 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
return 0;
}
-static void
-mt7921_sta_rc_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- u32 changed)
-{
-}
-
static void mt7921_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1120,6 +1167,15 @@ static void mt7921_set_rekey_data(struct ieee80211_hw *hw,
}
#endif /* CONFIG_PM */
+static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+ struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+ wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy),
+ HZ / 2);
+}
+
const struct ieee80211_ops mt7921_ops = {
.tx = mt7921_tx,
.start = mt7921_start,
@@ -1133,7 +1189,6 @@ const struct ieee80211_ops mt7921_ops = {
.sta_add = mt7921_sta_add,
.sta_remove = mt7921_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
- .sta_rc_update = mt7921_sta_rc_update,
.set_key = mt7921_set_key,
.ampdu_action = mt7921_ampdu_action,
.set_rts_threshold = mt7921_set_rts_threshold,
@@ -1158,4 +1213,5 @@ const struct ieee80211_ops mt7921_ops = {
.set_wakeup = mt7921_set_wakeup,
.set_rekey_data = mt7921_set_rekey_data,
#endif /* CONFIG_PM */
+ .flush = mt7921_flush,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index b5cc72e7e81c..aa55667b6ed7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -4,6 +4,7 @@
#include <linux/firmware.h>
#include <linux/fs.h>
#include "mt7921.h"
+#include "mt7921_trace.h"
#include "mcu.h"
#include "mac.h"
@@ -222,8 +223,16 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
u32 val;
u8 seq;
- /* TODO: make dynamic based on msg type */
- mdev->mcu.timeout = 20 * HZ;
+ switch (cmd) {
+ case MCU_UNI_CMD_HIF_CTRL:
+ case MCU_UNI_CMD_SUSPEND:
+ case MCU_UNI_CMD_OFFLOAD:
+ mdev->mcu.timeout = HZ / 3;
+ break;
+ default:
+ mdev->mcu.timeout = 3 * HZ;
+ break;
+ }
seq = ++dev->mt76.mcu.msg_seq & 0xf;
if (!seq)
@@ -404,9 +413,12 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
if (wlan_idx >= MT76_N_WCIDS)
return;
+
+ rcu_read_lock();
+
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
- return;
+ goto out;
msta = container_of(wcid, struct mt7921_sta, wcid);
stats = &msta->stats;
@@ -414,6 +426,8 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
/* current rate */
mt7921_mcu_tx_rate_parse(mphy, &peer, &rate, curr);
stats->tx_rate = rate;
+out:
+ rcu_read_unlock();
}
static void
@@ -466,33 +480,45 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
static void
mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
- struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data;
- struct debug_msg {
+ struct mt7921_debug_msg {
__le16 id;
u8 type;
u8 flag;
__le32 value;
__le16 len;
u8 content[512];
- } __packed * debug_msg;
- u16 cur_len;
- int i;
-
- skb_pull(skb, sizeof(*rxd));
- debug_msg = (struct debug_msg *)skb->data;
+ } __packed * msg;
- cur_len = min_t(u16, le16_to_cpu(debug_msg->len), 512);
+ skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
+ msg = (struct mt7921_debug_msg *)skb->data;
- if (debug_msg->type == 0x3) {
- for (i = 0 ; i < cur_len; i++)
- if (!debug_msg->content[i])
- debug_msg->content[i] = ' ';
+ if (msg->type == 3) { /* fw log */
+ u16 len = min_t(u16, le16_to_cpu(msg->len), 512);
+ int i;
- dev_dbg(dev->mt76.dev, "%s", debug_msg->content);
+ for (i = 0 ; i < len; i++) {
+ if (!msg->content[i])
+ msg->content[i] = ' ';
+ }
+ wiphy_info(mt76_hw(dev)->wiphy, "%*s", len, msg->content);
}
}
static void
+mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
+{
+ struct mt7921_mcu_lp_event {
+ u8 state;
+ u8 reserved[3];
+ } __packed * event;
+
+ skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
+ event = (struct mt7921_mcu_lp_event *)skb->data;
+
+ trace_lp_event(dev, event->state);
+}
+
+static void
mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data;
@@ -515,6 +541,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt76_connac_mcu_coredump_event(&dev->mt76, skb,
&dev->coredump);
return;
+ case MCU_EVENT_LP_INFO:
+ mt7921_mcu_low_power_event(dev, skb);
+ break;
default:
break;
}
@@ -537,6 +566,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
rxd->eid == MCU_EVENT_SCAN_DONE ||
rxd->eid == MCU_EVENT_DBG_MSG ||
rxd->eid == MCU_EVENT_COREDUMP ||
+ rxd->eid == MCU_EVENT_LP_INFO ||
!rxd->seq)
mt7921_mcu_rx_unsolicited_event(dev, skb);
else
@@ -919,6 +949,24 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl)
sizeof(data), false);
}
+int mt7921_run_firmware(struct mt7921_dev *dev)
+{
+ int err;
+
+ err = mt7921_driver_own(dev);
+ if (err)
+ return err;
+
+ err = mt7921_load_firmware(dev);
+ if (err)
+ return err;
+
+ set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
+ mt7921_mcu_fw_log_2_host(dev, 1);
+
+ return 0;
+}
+
int mt7921_mcu_init(struct mt7921_dev *dev)
{
static const struct mt76_mcu_ops mt7921_mcu_ops = {
@@ -926,39 +974,17 @@ int mt7921_mcu_init(struct mt7921_dev *dev)
.mcu_skb_send_msg = mt7921_mcu_send_message,
.mcu_parse_response = mt7921_mcu_parse_response,
.mcu_restart = mt7921_mcu_restart,
+ .mcu_reset = mt7921_reset,
};
- int ret;
dev->mt76.mcu_ops = &mt7921_mcu_ops;
- ret = mt7921_driver_own(dev);
- if (ret)
- return ret;
-
- ret = mt7921_load_firmware(dev);
- if (ret)
- return ret;
-
- set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
- mt7921_mcu_fw_log_2_host(dev, 1);
-
- return 0;
+ return mt7921_run_firmware(dev);
}
void mt7921_mcu_exit(struct mt7921_dev *dev)
{
- u32 reg = mt7921_reg_map_l1(dev, MT_TOP_MISC);
-
- __mt76_mcu_restart(&dev->mt76);
- if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
- FIELD_PREP(MT_TOP_MISC_FW_STATE,
- FW_STATE_FW_DOWNLOAD), 1000)) {
- dev_err(dev->mt76.dev, "Failed to exit mcu\n");
- return;
- }
-
- reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0);
- mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN);
+ mt7921_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
}
@@ -1255,6 +1281,7 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "driver own failed\n");
+ mt7921_reset(&dev->mt76);
return -EIO;
}
@@ -1281,6 +1308,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "firmware own failed\n");
+ mt7921_reset(&dev->mt76);
return -EIO;
}
@@ -1292,8 +1320,14 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt7921_phy *phy = priv;
struct mt7921_dev *dev = phy->dev;
+ int ret;
+
+ if (dev->pm.enable)
+ ret = mt7921_mcu_uni_bss_bcnft(dev, vif, true);
+ else
+ ret = mt7921_mcu_set_bss_pm(dev, vif, false);
- if (mt7921_mcu_set_bss_pm(dev, vif, dev->pm.enable))
+ if (ret)
return;
if (dev->pm.enable) {
@@ -1304,3 +1338,47 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
}
}
+
+int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info)
+{
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct mt7921_dev *dev = mt7921_hw_dev(hw);
+ struct sk_buff *skb;
+ int i, len = min_t(int, info->arp_addr_cnt,
+ IEEE80211_BSS_ARP_ADDR_LIST_LEN);
+ struct {
+ struct {
+ u8 bss_idx;
+ u8 pad[3];
+ } __packed hdr;
+ struct mt76_connac_arpns_tlv arp;
+ } req_hdr = {
+ .hdr = {
+ .bss_idx = mvif->mt76.idx,
+ },
+ .arp = {
+ .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP),
+ .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),
+ .ips_num = len,
+ .mode = 2, /* update */
+ .option = 1,
+ },
+ };
+
+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
+ sizeof(req_hdr) + len * sizeof(__be32));
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put_data(skb, &req_hdr, sizeof(req_hdr));
+ for (i = 0; i < len; i++) {
+ u8 *addr = (u8 *)skb_put(skb, sizeof(__be32));
+
+ memcpy(addr, &info->arp_addr_list[i], sizeof(__be32));
+ }
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD,
+ true);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
index 2fdc62367b3f..13e125f32283 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
@@ -79,6 +79,7 @@ struct mt7921_uni_txd {
/* event table */
enum {
MCU_EVENT_REG_ACCESS = 0x05,
+ MCU_EVENT_LP_INFO = 0x07,
MCU_EVENT_SCAN_DONE = 0x0d,
MCU_EVENT_BSS_ABSENCE = 0x11,
MCU_EVENT_BSS_BEACON_LOSS = 0x13,
@@ -177,25 +178,6 @@ enum {
MCU_PHY_STATE_OFDMLQ_CNINFO,
};
-#define STA_TYPE_STA BIT(0)
-#define STA_TYPE_AP BIT(1)
-#define STA_TYPE_ADHOC BIT(2)
-#define STA_TYPE_WDS BIT(4)
-#define STA_TYPE_BC BIT(5)
-
-#define NETWORK_INFRA BIT(16)
-#define NETWORK_P2P BIT(17)
-#define NETWORK_IBSS BIT(18)
-#define NETWORK_WDS BIT(21)
-
-#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
-#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
-#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
-#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P)
-#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS)
-#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS)
-#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA)
-
struct sec_key {
u8 cipher_id;
u8 cipher_len;
@@ -251,29 +233,6 @@ enum {
MT_IBF = BIT(1) /* implicit beamforming */
};
-#define MT7921_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
- sizeof(struct wtbl_generic) + \
- sizeof(struct wtbl_rx) + \
- sizeof(struct wtbl_ht) + \
- sizeof(struct wtbl_vht) + \
- sizeof(struct wtbl_hdr_trans) +\
- sizeof(struct wtbl_ba) + \
- sizeof(struct wtbl_smps))
-
-#define MT7921_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
- sizeof(struct sta_rec_basic) + \
- sizeof(struct sta_rec_ht) + \
- sizeof(struct sta_rec_he) + \
- sizeof(struct sta_rec_ba) + \
- sizeof(struct sta_rec_vht) + \
- sizeof(struct sta_rec_uapsd) + \
- sizeof(struct sta_rec_amsdu) + \
- sizeof(struct tlv) + \
- MT7921_WTBL_UPDATE_MAX_SIZE)
-
-#define MT7921_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
- sizeof(struct wtbl_ba))
-
#define STA_CAP_WMM BIT(0)
#define STA_CAP_SGI_20 BIT(4)
#define STA_CAP_SGI_40 BIT(5)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 46e6aeec35ae..e3d83d3d954c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -46,6 +46,9 @@
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
+#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
+#define to_rcpi(rssi) (2 * (rssi) + 220)
+
struct mt7921_vif;
struct mt7921_sta;
@@ -92,21 +95,25 @@ struct mt7921_sta {
struct mt7921_sta_key_conf bip;
};
+DECLARE_EWMA(rssi, 10, 8);
+
struct mt7921_vif {
struct mt76_vif mt76; /* must be first */
struct mt7921_sta sta;
struct mt7921_phy *phy;
+ struct ewma_rssi rssi;
+
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
};
struct mib_stats {
- u16 ack_fail_cnt;
- u16 fcs_err_cnt;
- u16 rts_cnt;
- u16 rts_retries_cnt;
- u16 ba_miss_cnt;
+ u32 ack_fail_cnt;
+ u32 fcs_err_cnt;
+ u32 rts_cnt;
+ u32 rts_retries_cnt;
+ u32 ba_miss_cnt;
};
struct mt7921_phy {
@@ -125,7 +132,7 @@ struct mt7921_phy {
s16 coverage_class;
u8 slottime;
- __le32 rx_ampdu_ts;
+ u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
@@ -151,8 +158,6 @@ struct mt7921_dev {
struct work_struct init_work;
struct work_struct reset_work;
- wait_queue_head_t reset_wait;
- u32 reset_state;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
@@ -209,6 +214,7 @@ extern struct pci_driver mt7921_pci_driver;
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
+int __mt7921_start(struct mt7921_phy *phy);
int mt7921_register_device(struct mt7921_dev *dev);
void mt7921_unregister_device(struct mt7921_dev *dev);
int mt7921_eeprom_init(struct mt7921_dev *dev);
@@ -220,6 +226,7 @@ void mt7921_eeprom_init_sku(struct mt7921_dev *dev);
int mt7921_dma_init(struct mt7921_dev *dev);
void mt7921_dma_prefetch(struct mt7921_dev *dev);
void mt7921_dma_cleanup(struct mt7921_dev *dev);
+int mt7921_run_firmware(struct mt7921_dev *dev);
int mt7921_mcu_init(struct mt7921_dev *dev);
int mt7921_mcu_add_bss_info(struct mt7921_phy *phy,
struct ieee80211_vif *vif, int enable);
@@ -281,6 +288,7 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val)
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
+void mt7921_mac_init(struct mt7921_dev *dev);
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
@@ -296,6 +304,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7921_mac_work(struct work_struct *work);
void mt7921_mac_reset_work(struct work_struct *work);
+void mt7921_reset(struct mt76_dev *mdev);
int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
@@ -339,4 +348,8 @@ int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy,
bool enable);
void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
void mt7921_coredump_work(struct work_struct *work);
+int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info);
+int mt7921_wfsys_reset(struct mt7921_dev *dev);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h
new file mode 100644
index 000000000000..9bc4db67f352
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __MT7921_TRACE_H
+
+#include <linux/tracepoint.h>
+#include "mt7921.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mt7921
+
+#define MAXNAME 32
+#define DEV_ENTRY __array(char, wiphy_name, 32)
+#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
+ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME)
+#define DEV_PR_FMT "%s"
+#define DEV_PR_ARG __entry->wiphy_name
+#define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready"
+
+TRACE_EVENT(lp_event,
+ TP_PROTO(struct mt7921_dev *dev, u8 lp_state),
+
+ TP_ARGS(dev, lp_state),
+
+ TP_STRUCT__entry(
+ DEV_ENTRY
+ __field(u8, lp_state)
+ ),
+
+ TP_fast_assign(
+ DEV_ASSIGN;
+ __entry->lp_state = lp_state;
+ ),
+
+ TP_printk(
+ DEV_PR_FMT " %s",
+ DEV_PR_ARG, LP_STATE_PR_ARG
+ )
+);
+
+#endif
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE mt7921_trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 5570b4a50531..40e2086d075c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -13,7 +13,7 @@
#include "../trace.h"
static const struct pci_device_id mt7921_pci_device_table[] = {
- { PCI_DEVICE(0x14c3, 0x7961) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961) },
{ },
};
@@ -137,7 +137,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
- mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
@@ -146,10 +146,12 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
ret = mt7921_register_device(dev);
if (ret)
- goto err_free_dev;
+ goto err_free_irq;
return 0;
+err_free_irq:
+ devm_free_irq(&pdev->dev, pdev->irq, dev);
err_free_dev:
mt76_free_device(&dev->mt76);
err_free_pci_vec:
@@ -209,12 +211,12 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
/* disable interrupt */
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
- pci_save_state(pdev);
- err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ err = mt7921_mcu_fw_pmctrl(dev);
if (err)
goto restore;
- err = mt7921_mcu_drv_pmctrl(dev);
+ pci_save_state(pdev);
+ err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err)
goto restore;
@@ -237,18 +239,18 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
int i, err;
- err = mt7921_mcu_fw_pmctrl(dev);
- if (err < 0)
- return err;
-
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
+ err = mt7921_mcu_drv_pmctrl(dev);
+ if (err < 0)
+ return err;
+
/* enable interrupt */
- mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ 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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
index 6dad7f6ab09d..76ecfea21dce 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
@@ -96,8 +96,8 @@
#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800)
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
-#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014)
-#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0)
+#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698)
+#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16)
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
@@ -121,16 +121,21 @@
#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16)
#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
-#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4))
-#define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0)
-#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16)
+#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688)
+#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
+#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690)
+#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0)
+#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518)
+#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0)
+#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520)
+#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0)
#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4))
#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0)
-#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2))
-#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2))
-#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2))
+#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2))
+#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2))
+#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2))
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0))
#define MT_WTBLON_TOP_BASE 0x34000
@@ -357,11 +362,11 @@
#define MT_INFRA_CFG_BASE 0xfe000
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
-#define MT_HIF_REMAP_L1 MT_INFRA(0x260)
+#define MT_HIF_REMAP_L1 MT_INFRA(0x24c)
#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0)
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
-#define MT_HIF_REMAP_BASE_L1 0xe0000
+#define MT_HIF_REMAP_BASE_L1 0x40000
#define MT_SWDEF_BASE 0x41f200
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
@@ -380,11 +385,17 @@
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
+#define MT_MCU_WPDMA0_BASE 0x54000000
+#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs))
+
+#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120)
+#define MT_WFDMA_NEED_REINIT BIT(1)
+
#define MT_HW_BOUND 0x70010020
#define MT_HW_CHIPID 0x70010200
#define MT_HW_REV 0x70010204
-#define MT_PCIE_MAC_BASE 0x74030000
+#define MT_PCIE_MAC_BASE 0x10000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
@@ -413,6 +424,10 @@
#define PCIE_LPCR_HOST_CLR_OWN BIT(1)
#define PCIE_LPCR_HOST_SET_OWN BIT(0)
+#define MT_WFSYS_SW_RST_B 0x18000140
+#define WFSYS_SW_RST_B BIT(0)
+#define WFSYS_SW_INIT_DONE BIT(4)
+
#define MT_CONN_ON_MISC 0x7c0600f0
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c
new file mode 100644
index 000000000000..4dc3c7b89ebd
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "mt7921_trace.h"
+
+#endif