summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt7915
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c90
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c83
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h48
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c51
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c162
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c240
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c308
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.h22
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mmio.c67
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h39
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/pci.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/regs.h7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/soc.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/testmode.c6
15 files changed, 788 insertions, 346 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index 6c3696c8c700..b287b7d9394e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -211,13 +211,28 @@ static const struct file_operations mt7915_sys_recovery_ops = {
static int
mt7915_radar_trigger(void *data, u64 val)
{
- struct mt7915_dev *dev = data;
+#define RADAR_MAIN_CHAIN 1
+#define RADAR_BACKGROUND 2
+ struct mt7915_phy *phy = data;
+ struct mt7915_dev *dev = phy->dev;
+ int rdd_idx;
+
+ if (!val || val > RADAR_BACKGROUND)
+ return -EINVAL;
- if (val > MT_RX_SEL2)
+ if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {
+ dev_err(dev->mt76.dev, "Background radar is not enabled\n");
return -EINVAL;
+ }
+
+ rdd_idx = mt7915_get_rdd_idx(phy, val == RADAR_BACKGROUND);
+ if (rdd_idx < 0) {
+ dev_err(dev->mt76.dev, "No RDD found\n");
+ return -EINVAL;
+ }
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE,
- val, 0, 0);
+ rdd_idx, 0, 0);
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
@@ -303,9 +318,9 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.dl_vht_3mu_cnt,
phy->mib.dl_vht_4mu_cnt);
- sub_total_cnt = phy->mib.dl_vht_2mu_cnt +
- phy->mib.dl_vht_3mu_cnt +
- phy->mib.dl_vht_4mu_cnt;
+ sub_total_cnt = (u64)phy->mib.dl_vht_2mu_cnt +
+ phy->mib.dl_vht_3mu_cnt +
+ phy->mib.dl_vht_4mu_cnt;
seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld",
sub_total_cnt);
@@ -353,26 +368,27 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.dl_he_9to16ru_cnt,
phy->mib.dl_he_gtr16ru_cnt);
- sub_total_cnt = phy->mib.dl_he_2mu_cnt +
- phy->mib.dl_he_3mu_cnt +
- phy->mib.dl_he_4mu_cnt;
+ sub_total_cnt = (u64)phy->mib.dl_he_2mu_cnt +
+ phy->mib.dl_he_3mu_cnt +
+ phy->mib.dl_he_4mu_cnt;
total_ppdu_cnt = sub_total_cnt;
seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld",
sub_total_cnt);
- sub_total_cnt = phy->mib.dl_he_2ru_cnt +
- phy->mib.dl_he_3ru_cnt +
- phy->mib.dl_he_4ru_cnt +
- phy->mib.dl_he_5to8ru_cnt +
- phy->mib.dl_he_9to16ru_cnt +
- phy->mib.dl_he_gtr16ru_cnt;
+ sub_total_cnt = (u64)phy->mib.dl_he_2ru_cnt +
+ phy->mib.dl_he_3ru_cnt +
+ phy->mib.dl_he_4ru_cnt +
+ phy->mib.dl_he_5to8ru_cnt +
+ phy->mib.dl_he_9to16ru_cnt +
+ phy->mib.dl_he_gtr16ru_cnt;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld",
sub_total_cnt);
- total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt;
+ total_ppdu_cnt += (u64)phy->mib.dl_he_su_cnt +
+ phy->mib.dl_he_ext_su_cnt;
seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt);
@@ -404,20 +420,20 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.ul_hetrig_9to16ru_cnt,
phy->mib.ul_hetrig_gtr16ru_cnt);
- sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt +
- phy->mib.ul_hetrig_3mu_cnt +
- phy->mib.ul_hetrig_4mu_cnt;
+ sub_total_cnt = (u64)phy->mib.ul_hetrig_2mu_cnt +
+ phy->mib.ul_hetrig_3mu_cnt +
+ phy->mib.ul_hetrig_4mu_cnt;
total_ppdu_cnt = sub_total_cnt;
seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld",
sub_total_cnt);
- sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt +
- phy->mib.ul_hetrig_3ru_cnt +
- phy->mib.ul_hetrig_4ru_cnt +
- phy->mib.ul_hetrig_5to8ru_cnt +
- phy->mib.ul_hetrig_9to16ru_cnt +
- phy->mib.ul_hetrig_gtr16ru_cnt;
+ sub_total_cnt = (u64)phy->mib.ul_hetrig_2ru_cnt +
+ phy->mib.ul_hetrig_3ru_cnt +
+ phy->mib.ul_hetrig_4ru_cnt +
+ phy->mib.ul_hetrig_5to8ru_cnt +
+ phy->mib.ul_hetrig_9to16ru_cnt +
+ phy->mib.ul_hetrig_gtr16ru_cnt;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld",
@@ -444,6 +460,11 @@ mt7915_rdd_monitor(struct seq_file *s, void *data)
mutex_lock(&dev->mt76.mutex);
+ if (!mt7915_eeprom_has_background_radar(dev)) {
+ seq_puts(s, "no background radar capability\n");
+ goto out;
+ }
+
if (!cfg80211_chandef_valid(chandef)) {
ret = -EINVAL;
goto out;
@@ -523,7 +544,8 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
/* WM CPU info record control */
mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
- mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm);
+ mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) |
+ (dev->fw.debug_wm ? 0 : BIT(0)));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
@@ -1049,6 +1071,7 @@ static ssize_t
mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
+ int i, ret, pwr, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
struct mt7915_phy *phy = file->private_data;
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy = phy->mt76;
@@ -1057,7 +1080,6 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
.band_idx = phy->mt76->band_idx,
};
char buf[100];
- int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
enum mac80211_rx_encoding mode;
u32 offs = 0, len = 0;
@@ -1083,13 +1105,13 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
return -EINVAL;
if (pwr160)
- pwr160 = mt7915_get_power_bound(phy, pwr160);
+ pwr160 = mt76_get_power_bound(mphy, pwr160);
if (pwr80)
- pwr80 = mt7915_get_power_bound(phy, pwr80);
+ pwr80 = mt76_get_power_bound(mphy, pwr80);
if (pwr40)
- pwr40 = mt7915_get_power_bound(phy, pwr40);
+ pwr40 = mt76_get_power_bound(mphy, pwr40);
if (pwr20)
- pwr20 = mt7915_get_power_bound(phy, pwr20);
+ pwr20 = mt76_get_power_bound(mphy, pwr20);
if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0)
return -EINVAL;
@@ -1130,8 +1152,8 @@ skip:
if (ret)
goto out;
- mphy->txpower_cur = max(mphy->txpower_cur,
- max(pwr160, max(pwr80, max(pwr40, pwr20))));
+ pwr = max3(pwr80, pwr40, pwr20);
+ mphy->txpower_cur = max3(mphy->txpower_cur, pwr160, pwr);
out:
mutex_unlock(&dev->mt76.mutex);
@@ -1240,7 +1262,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
if (!dev->dbdc_support || phy->mt76->band_idx) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
&dev->hw_pattern);
- debugfs_create_file("radar_trigger", 0200, dir, dev,
+ debugfs_create_file("radar_trigger", 0200, dir, phy,
&fops_radar_trigger);
debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
mt7915_rdd_monitor);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
index c91a1c54027f..0c62272fe7d0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
@@ -578,7 +578,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (ret < 0)
return ret;
- netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt7915_poll_tx);
napi_enable(&dev->mt76.tx_napi);
@@ -614,7 +614,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
mtk_wed_device_dma_reset(wed);
mt7915_dma_disable(dev, force);
- mt76_dma_wed_reset(&dev->mt76);
+ mt76_wed_dma_reset(&dev->mt76);
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index 3bb2643d1b26..c0f3402d30bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -2,35 +2,46 @@
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/firmware.h>
+#include <linux/moduleparam.h>
#include "mt7915.h"
#include "eeprom.h"
+static bool enable_6ghz;
+module_param(enable_6ghz, bool, 0644);
+MODULE_PARM_DESC(enable_6ghz, "Enable 6 GHz instead of 5 GHz on hardware that supports both");
+
static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
u8 *eeprom = mdev->eeprom.data;
- u32 val = eeprom[MT_EE_DO_PRE_CAL];
- u32 offs;
+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
+ u32 size, val = eeprom[offs];
int ret;
- if (!dev->flash_mode)
+ if (!dev->flash_mode || !val)
return 0;
- if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
- return 0;
+ size = mt7915_get_cal_group_size(dev) + mt7915_get_cal_dpd_size(dev);
- val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
- dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL);
+ dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
if (!dev->cal)
return -ENOMEM;
offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
- ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, val);
+ ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);
if (!ret)
return ret;
- return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", val);
+ ret = mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
+ if (!ret)
+ return ret;
+
+ dev_warn(mdev->dev, "missing precal data, size=%d\n", size);
+ devm_kfree(mdev->dev, dev->cal);
+ dev->cal = NULL;
+
+ return ret;
}
static int mt7915_check_eeprom(struct mt7915_dev *dev)
@@ -136,7 +147,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
/* read eeprom data from efuse */
block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);
for (i = 0; i < block_num; i++) {
- ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size);
+ ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
if (ret < 0)
return ret;
}
@@ -164,8 +175,20 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
phy->mt76->cap.has_6ghz = true;
return;
case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
- phy->mt76->cap.has_5ghz = true;
- phy->mt76->cap.has_6ghz = true;
+ if (enable_6ghz) {
+ phy->mt76->cap.has_6ghz = true;
+ u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],
+ MT_EE_V2_BAND_SEL_6GHZ,
+ MT_EE_WIFI_CONF0_BAND_SEL);
+ } else {
+ phy->mt76->cap.has_5ghz = true;
+ u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],
+ MT_EE_V2_BAND_SEL_5GHZ,
+ MT_EE_WIFI_CONF0_BAND_SEL);
+ }
+ /* force to buffer mode */
+ dev->flash_mode = true;
+
return;
default:
phy->mt76->cap.has_2ghz = true;
@@ -256,10 +279,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
return ret;
}
- ret = mt7915_eeprom_load_precal(dev);
- if (ret)
- return ret;
-
+ mt7915_eeprom_load_precal(dev);
mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
@@ -341,6 +361,37 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
}
+bool
+mt7915_eeprom_has_background_radar(struct mt7915_dev *dev)
+{
+ u8 val, buf[MT7915_EEPROM_BLOCK_SIZE];
+ u8 band_sel, tx_path, rx_path;
+ int offs = MT_EE_WIFI_CONF + 1;
+
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7915:
+ return true;
+ case 0x7906:
+ /* read efuse to check background radar capability */
+ if (mt7915_mcu_get_eeprom(dev, offs, buf))
+ break;
+
+ val = buf[offs % MT7915_EEPROM_BLOCK_SIZE];
+ band_sel = u8_get_bits(val, MT_EE_WIFI_CONF0_BAND_SEL);
+ tx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_TX_PATH);
+ rx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_RX_PATH);
+
+ return (band_sel == MT_EE_V2_BAND_SEL_5GHZ &&
+ tx_path == rx_path && rx_path == 2);
+ case 0x7981:
+ case 0x7986:
+ default:
+ break;
+ }
+
+ return false;
+}
+
const u8 mt7915_sku_group_len[] = {
[SKU_CCK] = 4,
[SKU_OFDM] = 8,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h
index adc26a222823..31aec0f40232 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h
@@ -19,6 +19,7 @@ enum mt7915_eeprom_field {
MT_EE_DDIE_FT_VERSION = 0x050,
MT_EE_DO_PRE_CAL = 0x062,
MT_EE_WIFI_CONF = 0x190,
+ MT_EE_DO_PRE_CAL_V2 = 0x19a,
MT_EE_RATE_DELTA_2G = 0x252,
MT_EE_RATE_DELTA_5G = 0x29d,
MT_EE_TX0_POWER_2G = 0x2fc,
@@ -39,12 +40,22 @@ enum mt7915_eeprom_field {
};
#define MT_EE_WIFI_CAL_GROUP BIT(0)
-#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1)
+#define MT_EE_WIFI_CAL_DPD_2G BIT(2)
+#define MT_EE_WIFI_CAL_DPD_5G BIT(1)
+#define MT_EE_WIFI_CAL_DPD_6G BIT(3)
+#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1)
#define MT_EE_CAL_UNIT 1024
-#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16)
-#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16)
+#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_DPD_SIZE_V2_7981 (102 * MT_EE_CAL_UNIT) /* no 6g dpd data */
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
+#define MT_EE_WIFI_CONF0_RX_PATH GENMASK(5, 3)
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
#define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(7, 6)
#define MT_EE_WIFI_CONF_STREAM_NUM GENMASK(7, 5)
@@ -156,6 +167,37 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
return val & MT_EE_WIFI_CONF7_TSSI0_5G;
}
+static inline u32
+mt7915_get_cal_group_size(struct mt7915_dev *dev)
+{
+ u8 *eep = dev->mt76.eeprom.data;
+ u32 val;
+
+ if (is_mt7915(&dev->mt76)) {
+ return MT_EE_CAL_GROUP_SIZE_7915;
+ } else if (is_mt7916(&dev->mt76)) {
+ val = eep[MT_EE_WIFI_CONF + 1];
+ val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
+ return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G :
+ MT_EE_CAL_GROUP_SIZE_7916;
+ } else if (mt7915_check_adie(dev, false)) {
+ return MT_EE_CAL_GROUP_SIZE_7976;
+ } else {
+ return MT_EE_CAL_GROUP_SIZE_7975;
+ }
+}
+
+static inline u32
+mt7915_get_cal_dpd_size(struct mt7915_dev *dev)
+{
+ if (is_mt7915(&dev->mt76))
+ return MT_EE_CAL_DPD_SIZE_V1;
+ else if (is_mt7981(&dev->mt76))
+ return MT_EE_CAL_DPD_SIZE_V2_7981;
+ else
+ return MT_EE_CAL_DPD_SIZE_V2;
+}
+
extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index cea2f6d9050a..3e30ca5155d2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -53,7 +53,9 @@ static ssize_t mt7915_thermal_temp_show(struct device *dev,
switch (i) {
case 0:
+ mutex_lock(&phy->dev->mt76.mutex);
temperature = mt7915_mcu_get_temperature(phy);
+ mutex_unlock(&phy->dev->mt76.mutex);
if (temperature < 0)
return temperature;
/* display in millidegree celcius */
@@ -82,7 +84,7 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
return ret;
mutex_lock(&phy->dev->mt76.mutex);
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 60, 130);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 60 * 1000, 130 * 1000), 1000);
if ((i - 1 == MT7915_CRIT_TEMP_IDX &&
val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) ||
@@ -95,9 +97,8 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
}
phy->throttle_temp[i - 1] = val;
- mutex_unlock(&phy->dev->mt76.mutex);
-
ret = mt7915_mcu_set_thermal_protect(phy);
+ mutex_unlock(&phy->dev->mt76.mutex);
if (ret)
return ret;
@@ -159,7 +160,9 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
* cooling_device convention: 0 = no cooling, more = more cooling
* mcu convention: 1 = max cooling, more = less cooling
*/
+ mutex_lock(&phy->dev->mt76.mutex);
ret = mt7915_mcu_set_thermal_throttling(phy, throttling);
+ mutex_unlock(&phy->dev->mt76.mutex);
if (ret)
return ret;
@@ -194,6 +197,8 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s",
wiphy_name(wiphy));
+ if (!name)
+ return -ENOMEM;
cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops);
if (!IS_ERR(cdev)) {
@@ -280,7 +285,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy,
{
struct mt7915_dev *dev = phy->dev;
int i, n_chains = hweight16(phy->mt76->chainmask);
- int nss_delta = mt76_tx_power_nss_delta(n_chains);
+ int path_delta = mt76_tx_power_path_delta(n_chains);
int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
struct mt76_power_limits limits;
@@ -300,7 +305,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy,
target_power = mt76_get_rate_power_limits(phy->mt76, chan,
&limits,
target_power);
- target_power += nss_delta;
+ target_power += path_delta;
target_power = DIV_ROUND_UP(target_power, 2);
chan->max_power = min_t(int, chan->max_reg_power,
target_power);
@@ -387,9 +392,10 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
if (!is_mt7915(&dev->mt76))
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
- if (!mdev->dev->of_node ||
- !of_property_read_bool(mdev->dev->of_node,
- "mediatek,disable-radar-background"))
+ if (mt7915_eeprom_has_background_radar(phy->dev) &&
+ (!mdev->dev->of_node ||
+ !of_property_read_bool(mdev->dev->of_node,
+ "mediatek,disable-radar-background")))
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_RADAR_BACKGROUND);
@@ -398,6 +404,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
+ ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);
hw->max_tx_fragments = 4;
@@ -509,6 +516,15 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band),
MT_WF_RMAC_MIB_QOS23_BACKOFF);
+ /* clear backoff time for Tx duration */
+ mt76_clear(dev, MT_WTBLOFF_TOP_ACR(band),
+ MT_WTBLOFF_TOP_ADM_BACKOFFTIME);
+
+ /* exclude estimated backoff time for Tx duration on MT7915 */
+ if (is_mt7915(&dev->mt76))
+ mt76_set(dev, MT_AGG_ATCR0(band),
+ MT_AGG_ATCR_MAC_BFF_TIME_EN);
+
/* clear backoff time and set software compensation for OBSS time */
mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET;
set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) |
@@ -823,7 +839,7 @@ mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (ret < 0)
return ret;
- if (dev->flash_mode) {
+ if (dev->cal) {
ret = mt7915_mcu_apply_group_cal(dev);
if (ret)
return ret;
@@ -909,8 +925,7 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;
if (!is_mt7915(&dev->mt76))
- c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
- IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
+ c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
elem->phy_cap_info[2] |= c;
c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
@@ -934,11 +949,10 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;
- if (vif != NL80211_IFTYPE_AP)
+ if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION)
return;
elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
- elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
sts - 1);
@@ -947,6 +961,11 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
sts_160 - 1);
elem->phy_cap_info[5] |= c;
+ if (vif != NL80211_IFTYPE_AP)
+ return;
+
+ elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+
c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
elem->phy_cap_info[6] |= c;
@@ -1107,7 +1126,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) {
- mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
+ mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band);
} else {
he_cap_elem->phy_cap_info[9] |=
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
@@ -1232,14 +1251,14 @@ int mt7915_register_device(struct mt7915_dev *dev)
if (ret)
goto unreg_dev;
- ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
-
if (phy2) {
ret = mt7915_register_ext_phy(dev, phy2);
if (ret)
goto unreg_thermal;
}
+ ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+
dev->recovery.hw_init_done = true;
ret = mt7915_init_debugfs(&dev->phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index b01edbed969c..9400e4af2a04 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -140,8 +140,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
msta->airtime_ac[i] = mt76_rr(dev, addr);
msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
- tx_time[i] = msta->airtime_ac[i] - tx_last;
- rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
+ if (msta->airtime_ac[i] <= tx_last)
+ tx_time[i] = 0;
+ else
+ tx_time[i] = msta->airtime_ac[i] - tx_last;
+
+ if (msta->airtime_ac[i + 4] <= rx_last)
+ rx_time[i] = 0;
+ else
+ rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
if ((tx_last | rx_last) & BIT(30))
clear = true;
@@ -326,11 +333,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
if (status->wcid) {
msta = container_of(status->wcid, struct mt7915_sta, wcid);
- spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->wcid.poll_list))
- list_add_tail(&msta->wcid.poll_list,
- &dev->mt76.sta_poll_list);
- spin_unlock_bh(&dev->mt76.sta_poll_lock);
+ mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -920,11 +923,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7915_sta, wcid);
- spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->wcid.poll_list))
- list_add_tail(&msta->wcid.poll_list,
- &mdev->sta_poll_list);
- spin_unlock_bh(&mdev->sta_poll_lock);
+ mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
continue;
}
@@ -1033,10 +1032,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
if (!wcid->sta)
goto out;
- spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->wcid.poll_list))
- list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
- spin_unlock_bh(&dev->mt76.sta_poll_lock);
+ mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
out:
rcu_read_unlock();
@@ -1156,7 +1152,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
u8 band = phy->mt76->band_idx;
- int eifs_ofdm = 360, sifs = 10, offset;
+ int eifs_ofdm = 84, sifs = 10, offset;
bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
@@ -1338,10 +1334,8 @@ mt7915_mac_restart(struct mt7915_dev *dev)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
- if (ext_phy) {
+ if (ext_phy)
set_bit(MT76_RESET, &ext_phy->state);
- set_bit(MT76_MCU_RESET, &ext_phy->state);
- }
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
@@ -1362,10 +1356,15 @@ mt7915_mac_restart(struct mt7915_dev *dev)
mt7915_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]);
+ }
+ }
+
+ local_bh_disable();
+ mt76_for_each_q_rx(mdev, i) {
+ if (mdev->q_rx[i].ndesc) {
napi_schedule(&dev->mt76.napi[i]);
}
}
@@ -1383,6 +1382,8 @@ mt7915_mac_restart(struct mt7915_dev *dev)
if (dev_is_pci(mdev->dev)) {
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
if (dev->hif2) {
+ mt76_wr(dev, MT_PCIE_RECOG_ID,
+ dev->hif2->index | MT_PCIE_RECOG_ID_SEM);
if (is_mt7915(mdev))
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
else
@@ -1423,8 +1424,9 @@ out:
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
- local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
+
+ local_bh_disable();
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
@@ -1437,12 +1439,15 @@ static void
mt7915_mac_full_reset(struct mt7915_dev *dev)
{
struct mt76_phy *ext_phy;
+ struct mt7915_phy *phy2;
int i;
ext_phy = dev->mt76.phys[MT_BAND1];
+ phy2 = ext_phy ? ext_phy->priv : NULL;
dev->recovery.hw_full_reset = true;
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
ieee80211_stop_queues(mt76_hw(dev));
if (ext_phy)
@@ -1457,26 +1462,30 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
if (!mt7915_mac_restart(dev))
break;
}
- 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 (ext_phy)
- ieee80211_restart_hw(ext_phy->hw);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ while (!list_empty(&dev->mt76.sta_poll_list))
+ list_del_init(dev->mt76.sta_poll_list.next);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
- ieee80211_wake_queues(mt76_hw(dev));
- if (ext_phy)
- ieee80211_wake_queues(ext_phy->hw);
+ memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
+ dev->mt76.vif_mask = 0;
+ dev->phy.omac_mask = 0;
+ if (phy2)
+ phy2->omac_mask = 0;
+ i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
+ dev->mt76.global_wcid.idx = i;
dev->recovery.hw_full_reset = false;
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
- MT7915_WATCHDOG_TIME);
+
+ mutex_unlock(&dev->mt76.mutex);
+
+ ieee80211_restart_hw(mt76_hw(dev));
if (ext_phy)
- ieee80211_queue_delayed_work(ext_phy->hw,
- &ext_phy->mac_work,
- MT7915_WATCHDOG_TIME);
+ ieee80211_restart_hw(ext_phy->hw);
}
/* system error recovery */
@@ -1520,12 +1529,6 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
return;
- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
- mtk_wed_device_stop(&dev->mt76.mmio.wed);
- if (!is_mt798x(&dev->mt76))
- mt76_wr(dev, MT_INT_WED_MASK_CSR, 0);
- }
-
ieee80211_stop_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_stop_queues(ext_phy->hw);
@@ -1538,12 +1541,17 @@ void mt7915_mac_reset_work(struct work_struct *work)
set_bit(MT76_RESET, &phy2->mt76->state);
cancel_delayed_work_sync(&phy2->mt76->mac_work);
}
+
+ mutex_lock(&dev->mt76.mutex);
+
mt76_worker_disable(&dev->mt76.tx_worker);
mt76_for_each_q_rx(&dev->mt76, i)
napi_disable(&dev->mt76.napi[i]);
napi_disable(&dev->mt76.tx_napi);
- mutex_lock(&dev->mt76.mutex);
+
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ mtk_wed_device_stop(&dev->mt76.mmio.wed);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
@@ -1568,9 +1576,12 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
- local_bh_disable();
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
+ }
+
+ local_bh_disable();
+ mt76_for_each_q_rx(&dev->mt76, i) {
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
@@ -1579,8 +1590,8 @@ void mt7915_mac_reset_work(struct work_struct *work)
mt76_worker_enable(&dev->mt76.tx_worker);
- local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
+ local_bh_disable();
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
@@ -1690,6 +1701,11 @@ void mt7915_reset(struct mt7915_dev *dev)
return;
}
+ if ((READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) {
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ wake_up(&dev->mt76.mcu.wait);
+ }
+
queue_work(dev->mt76.wq, &dev->reset_work);
wake_up(&dev->reset_wait);
}
@@ -2019,16 +2035,15 @@ void mt7915_mac_work(struct work_struct *work)
static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
+ int rdd_idx = mt7915_get_rdd_idx(phy, false);
- if (phy->rdd_state & BIT(0))
- mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0,
- MT_RX_SEL0, 0);
- if (phy->rdd_state & BIT(1))
- mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1,
- MT_RX_SEL0, 0);
+ if (rdd_idx < 0)
+ return;
+
+ mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0);
}
-static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
+static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int rdd_idx)
{
int err, region;
@@ -2045,52 +2060,38 @@ static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
break;
}
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain,
- MT_RX_SEL0, region);
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region);
if (err < 0)
return err;
if (is_mt7915(&dev->mt76)) {
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, chain,
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, rdd_idx,
0, dev->dbdc_support ? 2 : 0);
if (err < 0)
return err;
}
- return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain,
- MT_RX_SEL0, 1);
+ return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, rdd_idx, 0, 1);
}
static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy)
{
- struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
struct mt7915_dev *dev = phy->dev;
- int err;
+ int err, rdd_idx;
+
+ rdd_idx = mt7915_get_rdd_idx(phy, false);
+ if (rdd_idx < 0)
+ return -EINVAL;
/* start CAC */
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START,
- phy->mt76->band_idx, MT_RX_SEL0, 0);
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, rdd_idx, 0, 0);
if (err < 0)
return err;
- err = mt7915_dfs_start_rdd(dev, phy->mt76->band_idx);
+ err = mt7915_dfs_start_rdd(dev, rdd_idx);
if (err < 0)
return err;
- phy->rdd_state |= BIT(phy->mt76->band_idx);
-
- if (!is_mt7915(&dev->mt76))
- return 0;
-
- if (chandef->width == NL80211_CHAN_WIDTH_160 ||
- chandef->width == NL80211_CHAN_WIDTH_80P80) {
- err = mt7915_dfs_start_rdd(dev, 1);
- if (err < 0)
- return err;
-
- phy->rdd_state |= BIT(1);
- }
-
return 0;
}
@@ -2132,12 +2133,12 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
enum mt76_dfs_state dfs_state, prev_state;
- int err;
+ int err, rdd_idx = mt7915_get_rdd_idx(phy, false);
prev_state = phy->mt76->dfs_state;
dfs_state = mt76_phy_dfs_state(phy->mt76);
- if (prev_state == dfs_state)
+ if (prev_state == dfs_state || rdd_idx < 0)
return 0;
if (prev_state == MT_DFS_STATE_UNKNOWN)
@@ -2161,8 +2162,7 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
if (dfs_state == MT_DFS_STATE_CAC)
return 0;
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END,
- phy->mt76->band_idx, MT_RX_SEL0, 0);
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, rdd_idx, 0, 0);
if (err < 0) {
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
return err;
@@ -2172,15 +2172,13 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
return 0;
stop:
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START,
- phy->mt76->band_idx, MT_RX_SEL0, 0);
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, rdd_idx, 0, 0);
if (err < 0)
return err;
if (is_mt7915(&dev->mt76)) {
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT,
- phy->mt76->band_idx, 0,
- dev->dbdc_support ? 2 : 0);
+ rdd_idx, 0, dev->dbdc_support ? 2 : 0);
if (err < 0)
return err;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index df2d4279790d..3aa31c5cefa6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -108,7 +108,7 @@ static int mt7915_start(struct ieee80211_hw *hw)
return ret;
}
-static void mt7915_stop(struct ieee80211_hw *hw)
+static void mt7915_stop(struct ieee80211_hw *hw, bool suspend)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
@@ -233,6 +233,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mvif->mt76.omac_idx = idx;
mvif->phy = phy;
mvif->mt76.band_idx = phy->mt76->band_idx;
+ mvif->mt76.wcid = &mvif->sta.wcid;
mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
if (ext_phy)
@@ -245,15 +246,16 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
- idx = MT7915_WTBL_RESERVED - mvif->mt76.idx;
+ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev));
+ if (idx < 0) {
+ ret = -ENOSPC;
+ goto out;
+ }
INIT_LIST_HEAD(&mvif->sta.rc_list);
- INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
- mvif->sta.wcid.phy_idx = ext_phy;
- mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
- mt76_wcid_init(&mvif->sta.wcid);
+ mt76_wcid_init(&mvif->sta.wcid, phy->mt76->band_idx);
mt7915_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -272,7 +274,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
memset(&mvif->cap, -1, sizeof(mvif->cap));
mt7915_mcu_add_bss_info(phy, vif, true);
- mt7915_mcu_add_sta(dev, vif, NULL, true);
+ mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true);
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
out:
@@ -291,7 +293,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
int idx = msta->wcid.idx;
mt7915_mcu_add_bss_info(phy, vif, false);
- mt7915_mcu_add_sta(dev, vif, NULL, false);
+ mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
+ mt76_wcid_mask_clear(dev->mt76.wcid_mask, mvif->sta.wcid.idx);
mutex_lock(&dev->mt76.mutex);
mt76_testmode_reset(phy->mt76, true);
@@ -317,19 +320,13 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
}
-int mt7915_set_channel(struct mt7915_phy *phy)
+int mt7915_set_channel(struct mt76_phy *mphy)
{
+ struct mt7915_phy *phy = mphy->priv;
struct mt7915_dev *dev = phy->dev;
int ret;
- cancel_delayed_work_sync(&phy->mt76->mac_work);
-
- mutex_lock(&dev->mt76.mutex);
- set_bit(MT76_RESET, &phy->mt76->state);
-
- mt76_set_channel(phy->mt76);
-
- if (dev->flash_mode) {
+ if (dev->cal) {
ret = mt7915_mcu_apply_tx_dpd(phy);
if (ret)
goto out;
@@ -347,11 +344,6 @@ int mt7915_set_channel(struct mt7915_phy *phy)
phy->noise = 0;
out:
- clear_bit(MT76_RESET, &phy->mt76->state);
- mutex_unlock(&dev->mt76.mutex);
-
- mt76_txq_schedule_all(phy->mt76);
-
if (!mt76_testmode_enabled(phy->mt76))
ieee80211_queue_delayed_work(phy->mt76->hw,
&phy->mt76->mac_work,
@@ -374,6 +366,13 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
int idx = key->keyidx;
int err = 0;
+ if (sta && !wcid->sta) {
+ if (cmd != SET_KEY)
+ return 0;
+
+ return -EOPNOTSUPP;
+ }
+
/* The hardware does not support per-STA RX GTK, fallback
* to software mode for these.
*/
@@ -464,11 +463,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
mutex_unlock(&dev->mt76.mutex);
}
#endif
- ieee80211_stop_queues(hw);
- ret = mt7915_set_channel(phy);
+ ret = mt76_update_channel(phy->mt76);
if (ret)
return ret;
- ieee80211_wake_queues(hw);
}
if (changed & (IEEE80211_CONF_CHANGE_POWER |
@@ -564,8 +561,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
MT_WF_RFCR_DROP_RTS |
- MT_WF_RFCR_DROP_CTL_RSV |
- MT_WF_RFCR_DROP_NDPA);
+ MT_WF_RFCR_DROP_CTL_RSV);
*total_flags = flags;
rxfilter = phy->rxfilter;
@@ -627,19 +623,24 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC)
set_bss_info = vif->cfg.assoc;
if (changed & BSS_CHANGED_BEACON_ENABLED &&
+ info->enable_beacon &&
vif->type != NL80211_IFTYPE_AP)
- set_bss_info = set_sta = info->enable_beacon;
+ set_bss_info = set_sta = 1;
if (set_bss_info == 1)
mt7915_mcu_add_bss_info(phy, vif, true);
if (set_sta == 1)
- mt7915_mcu_add_sta(dev, vif, NULL, true);
+ mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
if (changed & BSS_CHANGED_ERP_CTS_PROT)
mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
if (changed & BSS_CHANGED_ERP_SLOT) {
- int slottime = info->use_short_slot ? 9 : 20;
+ int slottime = 9;
+
+ if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ &&
+ !info->use_short_slot)
+ slottime = 20;
if (slottime != phy->slottime) {
phy->slottime = slottime;
@@ -668,7 +669,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
if (set_bss_info == 0)
mt7915_mcu_add_bss_info(phy, vif, false);
if (set_sta == 0)
- mt7915_mcu_add_sta(dev, vif, NULL, false);
+ mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
mutex_unlock(&dev->mt76.mutex);
}
@@ -706,7 +707,7 @@ mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
err = mt7915_mcu_add_bss_info(phy, vif, true);
if (err)
goto out;
- err = mt7915_mcu_add_sta(dev, vif, NULL, true);
+ err = mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
out:
mutex_unlock(&dev->mt76.mutex);
@@ -720,7 +721,7 @@ mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt7915_dev *dev = mt7915_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
- mt7915_mcu_add_sta(dev, vif, NULL, false);
+ mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
mutex_unlock(&dev->mt76.mutex);
}
@@ -743,7 +744,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
bool ext_phy = mvif->phy != &dev->phy;
- int ret, idx;
+ int idx;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
if (idx < 0)
@@ -752,22 +753,113 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
INIT_LIST_HEAD(&msta->rc_list);
INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
- msta->wcid.sta = 1;
+ msta->wcid.sta_disabled = 1;
msta->wcid.idx = idx;
msta->wcid.phy_idx = ext_phy;
- msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->jiffies = jiffies;
ewma_avg_signal_init(&msta->avg_ack_signal);
mt7915_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+ mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, true);
- ret = mt7915_mcu_add_sta(dev, vif, sta, true);
- if (ret)
- return ret;
+ return 0;
+}
+
+struct drop_sta_iter {
+ struct mt7915_dev *dev;
+ struct ieee80211_hw *hw;
+ struct ieee80211_vif *vif;
+ u8 sta_addr[ETH_ALEN];
+};
+
+static void
+__mt7915_drop_sta(void *ptr, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct drop_sta_iter *data = ptr;
+ struct ieee80211_sta *sta;
+ struct mt7915_sta *msta;
+
+ if (vif == data->vif || vif->type != NL80211_IFTYPE_AP)
+ return;
+
+ sta = ieee80211_find_sta_by_ifaddr(data->hw, data->sta_addr, mac);
+ if (!sta)
+ return;
+
+ msta = (struct mt7915_sta *)sta->drv_priv;
+ mt7915_mcu_add_sta(data->dev, vif, sta, CONN_STATE_DISCONNECT, false);
+ msta->wcid.sta_disabled = 1;
+ msta->wcid.sta = 0;
+}
+
+static void
+mt7915_drop_other_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt76_phy *ext_phy = dev->mt76.phys[MT_BAND1];
+ struct drop_sta_iter data = {
+ .dev = dev,
+ .hw = dev->mphy.hw,
+ .vif = vif,
+ };
+
+ if (vif->type != NL80211_IFTYPE_AP)
+ return;
+
+ memcpy(data.sta_addr, sta->addr, ETH_ALEN);
+ ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);
+
+ if (!ext_phy)
+ return;
+
+ data.hw = ext_phy->hw;
+ ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);
+}
+
+int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, enum mt76_sta_event ev)
+{
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+ int i, ret;
+ u32 addr;
- return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);
+ switch (ev) {
+ case MT76_STA_EVENT_ASSOC:
+ ret = mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_CONNECT, true);
+ if (ret)
+ return ret;
+
+ addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30);
+ mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0);
+
+ ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);
+ if (ret)
+ return ret;
+
+ msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+ msta->wcid.sta = 1;
+ msta->wcid.sta_disabled = 0;
+
+ return 0;
+
+ case MT76_STA_EVENT_AUTHORIZE:
+ mt7915_drop_other_sta(dev, vif, sta);
+ return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);
+
+ case MT76_STA_EVENT_DISASSOC:
+ for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
+ mt7915_mac_twt_teardown_flow(dev, msta, i);
+
+ mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
+ msta->wcid.sta_disabled = 1;
+ msta->wcid.sta = 0;
+ return 0;
+ }
+
+ return 0;
}
void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -775,16 +867,10 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
- int i;
-
- mt7915_mcu_add_sta(dev, vif, sta, false);
mt7915_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
- for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
- mt7915_mac_twt_teardown_flow(dev, msta, i);
-
spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
@@ -892,22 +978,6 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
static int
-mt7915_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
- IEEE80211_STA_NONE);
-}
-
-static int
-mt7915_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
- IEEE80211_STA_NOTEXIST);
-}
-
-static int
mt7915_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
@@ -1085,8 +1155,7 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
struct rate_info *txrate = &msta->wcid.rate;
struct rate_info rxrate = {};
- if (is_mt7915(&phy->dev->mt76) &&
- !mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
+ if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
sinfo->rxrate = rxrate;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
}
@@ -1155,11 +1224,16 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = phy->dev;
+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+
+ if (!msta->wcid.sta)
+ return;
mt7915_sta_rc_work(&changed, sta);
ieee80211_queue_work(hw, &dev->rc_work);
@@ -1203,6 +1277,9 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
else
clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+ if (!msta->wcid.sta)
+ return;
+
mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
}
@@ -1219,6 +1296,9 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
else
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
+ if (!msta->wcid.sta)
+ return;
+
mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
}
@@ -1575,6 +1655,12 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
}
static int
+mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val)
+{
+ return 0;
+}
+
+static int
mt7915_set_radar_background(struct ieee80211_hw *hw,
struct cfg80211_chan_def *chandef)
{
@@ -1656,7 +1742,22 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
}
#endif
+static void
+mt7915_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type)
+{
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+
+ ieee80211_wake_queues(hw);
+ ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+ MT7915_WATCHDOG_TIME);
+}
+
const struct ieee80211_ops mt7915_ops = {
+ .add_chanctx = ieee80211_emulate_add_chanctx,
+ .remove_chanctx = ieee80211_emulate_remove_chanctx,
+ .change_chanctx = ieee80211_emulate_change_chanctx,
+ .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = mt7915_tx,
.start = mt7915_start,
.stop = mt7915_stop,
@@ -1668,10 +1769,9 @@ const struct ieee80211_ops mt7915_ops = {
.bss_info_changed = mt7915_bss_info_changed,
.start_ap = mt7915_start_ap,
.stop_ap = mt7915_stop_ap,
- .sta_add = mt7915_sta_add,
- .sta_remove = mt7915_sta_remove,
+ .sta_state = mt76_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
- .sta_rc_update = mt7915_sta_rc_update,
+ .link_sta_rc_update = mt7915_sta_rc_update,
.set_key = mt7915_set_key,
.ampdu_action = mt7915_ampdu_action,
.set_rts_threshold = mt7915_set_rts_threshold,
@@ -1700,6 +1800,7 @@ const struct ieee80211_ops mt7915_ops = {
.sta_set_decap_offload = mt7915_sta_set_decap_offload,
.add_twt_setup = mt7915_mac_add_twt_setup,
.twt_teardown_request = mt7915_twt_teardown_request,
+ .set_frag_threshold = mt7915_set_frag_threshold,
CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
#ifdef CONFIG_MAC80211_DEBUGFS
@@ -1708,6 +1809,7 @@ const struct ieee80211_ops mt7915_ops = {
.set_radar_background = mt7915_set_radar_background,
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
.net_fill_forward_path = mt7915_net_fill_forward_path,
- .net_setup_tc = mt76_net_setup_tc,
+ .net_setup_tc = mt76_wed_net_setup_tc,
#endif
+ .reconfig_complete = mt7915_reconfig_complete,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index c67c4f6ca2aa..427542777abc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -157,12 +157,21 @@ static int
mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq)
{
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt76_connac2_mcu_rxd *rxd;
int ret = 0;
if (!skb) {
dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
cmd, seq);
+
+ if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) {
+ dev->recovery.restart = true;
+ wake_up(&dev->mt76.mcu.wait);
+ queue_work(dev->mt76.wq, &dev->reset_work);
+ wake_up(&dev->reset_wait);
+ }
+
return -ETIMEDOUT;
}
@@ -185,17 +194,31 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
return ret;
}
+static void
+mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
+{
+ if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID)
+ return;
+
+ switch (FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd)) {
+ case MCU_EXT_CMD_THERMAL_CTRL:
+ case MCU_EXT_CMD_GET_MIB_INFO:
+ case MCU_EXT_CMD_PHY_STAT_INFO:
+ case MCU_EXT_CMD_STA_REC_UPDATE:
+ case MCU_EXT_CMD_BSS_INFO_UPDATE:
+ mdev->mcu.timeout = 2 * HZ;
+ return;
+ default:
+ break;
+ }
+}
+
static int
mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
enum mt76_mcuq_id qid;
- int ret;
-
- ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq);
- if (ret)
- return ret;
if (cmd == MCU_CMD(FW_SCATTER))
qid = MT_MCUQ_FWDL;
@@ -204,6 +227,8 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
else
qid = MT_MCUQ_WM;
+ mt7915_mcu_set_timeout(mdev, cmd);
+
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);
}
@@ -228,7 +253,7 @@ mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
return;
- ieee80211_csa_finish(vif);
+ ieee80211_csa_finish(vif, 0);
}
static void
@@ -278,22 +303,40 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7915_mcu_rdd_report *r;
+ u32 sku;
r = (struct mt7915_mcu_rdd_report *)skb->data;
- if (r->band_idx > MT_RX_SEL2)
+ switch (r->rdd_idx) {
+ case MT_RDD_IDX_BAND0:
+ break;
+ case MT_RDD_IDX_BAND1:
+ sku = mt7915_check_adie(dev, true);
+ /* the main phy is bound to band 1 for this sku */
+ if (is_mt7986(&dev->mt76) &&
+ (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE))
+ break;
+ mphy = dev->mt76.phys[MT_BAND1];
+ break;
+ case MT_RDD_IDX_BACKGROUND:
+ if (!dev->rdd2_phy)
+ return;
+ mphy = dev->rdd2_phy->mt76;
+ break;
+ default:
+ dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);
return;
+ }
- if ((r->band_idx && !dev->phy.mt76->band_idx) &&
- dev->mt76.phys[MT_BAND1])
- mphy = dev->mt76.phys[MT_BAND1];
+ if (!mphy)
+ return;
- if (r->band_idx == MT_RX_SEL2)
+ if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)
cfg80211_background_radar_event(mphy->hw->wiphy,
&dev->rdd2_chandef,
GFP_ATOMIC);
else
- ieee80211_radar_detected(mphy->hw);
+ ieee80211_radar_detected(mphy->hw, NULL);
dev->hw_pattern++;
}
@@ -331,7 +374,7 @@ mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;
- ieee80211_color_change_finish(vif);
+ ieee80211_color_change_finish(vif, 0);
}
static void
@@ -424,7 +467,7 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len,
.len = cpu_to_le16(sub_len),
};
- ptlv = skb_put(skb, sub_len);
+ ptlv = skb_put_zero(skb, sub_len);
memcpy(ptlv, &tlv, sizeof(tlv));
le16_add_cpu(sub_ntlv, 1);
@@ -463,10 +506,10 @@ static bool mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
.tolerated = true,
};
- if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR))
+ if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR))
return false;
- cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef,
+ cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper,
mt7915_check_he_obss_narrow_bw_ru_iter,
&iter_data);
@@ -690,13 +733,17 @@ int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,
{
struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;
struct mt7915_vif *mvif = msta->vif;
+ int ret;
+ mt76_worker_disable(&dev->mt76.tx_worker);
if (enable && !params->amsdu)
msta->wcid.amsdu = false;
+ ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+ MCU_EXT_CMD(STA_REC_UPDATE),
+ enable, true);
+ mt76_worker_enable(&dev->mt76.tx_worker);
- return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
- MCU_EXT_CMD(STA_REC_UPDATE),
- enable, true);
+ return ret;
}
int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
@@ -1193,7 +1240,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
- const u8 matrix[4][4] = {
+ static const u8 matrix[4][4] = {
{0, 0, 0, 0},
{1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */
{2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
@@ -1503,7 +1550,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
ra->valid = true;
ra->auto_rate = true;
- ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta);
+ ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink);
ra->channel = chandef->chan->hw_value;
ra->bw = sta->deflink.bandwidth;
ra->phy.bw = sta->deflink.bandwidth;
@@ -1653,14 +1700,16 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,
}
int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, bool enable)
+ struct ieee80211_sta *sta, int conn_state, bool newly)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ struct ieee80211_link_sta *link_sta;
struct mt7915_sta *msta;
struct sk_buff *skb;
int ret;
msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;
+ link_sta = sta ? &sta->deflink : NULL;
skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
&msta->wcid);
@@ -1668,13 +1717,10 @@ 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(&dev->mt76, skb, vif, sta, enable,
- !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
- if (!enable)
- goto out;
-
+ mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, &vif->bss_conf, link_sta,
+ conn_state, newly);
/* tag order is in accordance with firmware dependency. */
- if (sta) {
+ if (sta && conn_state != CONN_STATE_DISCONNECT) {
/* starec bfer */
mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta);
/* starec ht */
@@ -1685,12 +1731,17 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
mt76_connac_mcu_sta_uapsd(skb, vif, sta);
}
- ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta);
- if (ret) {
- dev_kfree_skb(skb);
- return ret;
+ if (newly || conn_state != CONN_STATE_DISCONNECT) {
+ ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta);
+ if (ret) {
+ dev_kfree_skb(skb);
+ return ret;
+ }
}
+ if (conn_state == CONN_STATE_DISCONNECT)
+ goto out;
+
if (sta) {
/* starec amsdu */
mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
@@ -1919,8 +1970,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
bcn = (struct bss_info_bcn *)tlv;
bcn->enable = true;
- if (changed & BSS_CHANGED_FILS_DISCOVERY &&
- vif->bss_conf.fils_discovery.max_interval) {
+ if (changed & BSS_CHANGED_FILS_DISCOVERY) {
interval = vif->bss_conf.fils_discovery.max_interval;
skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
@@ -1957,7 +2007,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
discov->tx_interval = interval;
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
- discov->enable = true;
+ discov->enable = !!interval;
buf = (u8 *)sub_tlv + sizeof(*discov);
@@ -2351,6 +2401,8 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
if (ret)
return ret;
+ mt76_connac_mcu_del_wtbl_all(&dev->mt76);
+
if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
is_mt7915(&dev->mt76)) ||
!mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
@@ -2375,7 +2427,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
int mt7915_mcu_init(struct mt7915_dev *dev)
{
static const struct mt76_mcu_ops mt7915_mcu_ops = {
+ .max_retry = 1,
.headroom = sizeof(struct mt76_connac2_mcu_txd),
+ .mcu_skb_prepare_msg = mt76_connac2_mcu_fill_message,
.mcu_skb_send_msg = mt7915_mcu_send_message,
.mcu_parse_response = mt7915_mcu_parse_response,
};
@@ -2661,11 +2715,14 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
struct cfg80211_chan_def *chandef)
{
struct mt7915_dev *dev = phy->dev;
- int err, region;
+ int err, region, rdd_idx;
+
+ rdd_idx = mt7915_get_rdd_idx(phy, true);
+ if (rdd_idx < 0)
+ return -EINVAL;
if (!chandef) { /* disable offchain */
- err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2,
- 0, 0);
+ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0);
if (err)
return err;
@@ -2691,8 +2748,7 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
break;
}
- return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2,
- 0, region);
+ return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region);
}
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
@@ -2746,7 +2802,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
req.switch_reason = CH_SWITCH_NORMAL;
- else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
+ else if (phy->mt76->offchannel ||
phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
@@ -2823,7 +2879,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
&req, sizeof(req), true);
}
-int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
+int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
{
struct mt7915_mcu_eeprom_info req = {
.addr = cpu_to_le32(round_down(offset,
@@ -2831,8 +2887,8 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
};
struct mt7915_mcu_eeprom_info *res;
struct sk_buff *skb;
+ u8 *buf = read_buf;
int ret;
- u8 *buf;
ret = mt76_mcu_send_and_get_msg(&dev->mt76,
MCU_EXT_QUERY(EFUSE_ACCESS),
@@ -2841,8 +2897,10 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
return ret;
res = (struct mt7915_mcu_eeprom_info *)skb->data;
- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
+ if (!buf)
+ buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
+
dev_kfree_skb(skb);
return 0;
@@ -2904,9 +2962,10 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
{
u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
- u32 total = MT_EE_CAL_GROUP_SIZE;
+ u32 total = mt7915_get_cal_group_size(dev);
+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
- if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP))
+ if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
return 0;
/*
@@ -2942,9 +3001,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
return -1;
}
-static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
+static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw)
{
- static const u16 freq_list[] = {
+ static const u16 freq_list_v1[] = {
5180, 5200, 5220, 5240,
5260, 5280, 5300, 5320,
5500, 5520, 5540, 5560,
@@ -2952,65 +3011,135 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
5660, 5680, 5700, 5745,
5765, 5785, 5805, 5825
};
- int offset_2g = ARRAY_SIZE(freq_list);
+ static const u16 freq_list_v2[] = {
+ /* 6G BW20*/
+ 5955, 5975, 5995, 6015,
+ 6035, 6055, 6075, 6095,
+ 6115, 6135, 6155, 6175,
+ 6195, 6215, 6235, 6255,
+ 6275, 6295, 6315, 6335,
+ 6355, 6375, 6395, 6415,
+ 6435, 6455, 6475, 6495,
+ 6515, 6535, 6555, 6575,
+ 6595, 6615, 6635, 6655,
+ 6675, 6695, 6715, 6735,
+ 6755, 6775, 6795, 6815,
+ 6835, 6855, 6875, 6895,
+ 6915, 6935, 6955, 6975,
+ 6995, 7015, 7035, 7055,
+ 7075, 7095, 7115,
+ /* 6G BW160 */
+ 6025, 6185, 6345, 6505,
+ 6665, 6825, 6985,
+ /* 5G BW20 */
+ 5180, 5200, 5220, 5240,
+ 5260, 5280, 5300, 5320,
+ 5500, 5520, 5540, 5560,
+ 5580, 5600, 5620, 5640,
+ 5660, 5680, 5700, 5720,
+ 5745, 5765, 5785, 5805,
+ 5825, 5845, 5865, 5885,
+ /* 5G BW160 */
+ 5250, 5570, 5815
+ };
+ static const u16 freq_list_v2_7981[] = {
+ /* 5G BW20 */
+ 5180, 5200, 5220, 5240,
+ 5260, 5280, 5300, 5320,
+ 5500, 5520, 5540, 5560,
+ 5580, 5600, 5620, 5640,
+ 5660, 5680, 5700, 5720,
+ 5745, 5765, 5785, 5805,
+ 5825, 5845, 5865, 5885,
+ /* 5G BW160 */
+ 5250, 5570, 5815
+ };
+ const u16 *freq_list = freq_list_v1;
+ int n_freqs = ARRAY_SIZE(freq_list_v1);
int idx;
+ if (!is_mt7915(&dev->mt76)) {
+ if (is_mt7981(&dev->mt76)) {
+ freq_list = freq_list_v2_7981;
+ n_freqs = ARRAY_SIZE(freq_list_v2_7981);
+ } else {
+ freq_list = freq_list_v2;
+ n_freqs = ARRAY_SIZE(freq_list_v2);
+ }
+ }
+
if (freq < 4000) {
if (freq < 2432)
- return offset_2g;
+ return n_freqs;
if (freq < 2457)
- return offset_2g + 1;
+ return n_freqs + 1;
- return offset_2g + 2;
+ return n_freqs + 2;
}
- if (bw == NL80211_CHAN_WIDTH_80P80 || bw == NL80211_CHAN_WIDTH_160)
+ if (bw == NL80211_CHAN_WIDTH_80P80)
return -1;
if (bw != NL80211_CHAN_WIDTH_20) {
- idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
- freq + 10);
+ idx = mt7915_find_freq_idx(freq_list, n_freqs, freq + 10);
if (idx >= 0)
return idx;
- idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
- freq - 10);
+ idx = mt7915_find_freq_idx(freq_list, n_freqs, freq - 10);
if (idx >= 0)
return idx;
}
- return mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);
+ return mt7915_find_freq_idx(freq_list, n_freqs, freq);
}
int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
- u16 total = 2, center_freq = chandef->center_freq1;
+ enum nl80211_band band = chandef->chan->band;
+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
+ u16 center_freq = chandef->center_freq1;
u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
+ u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;
int idx;
- if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD))
+ switch (band) {
+ case NL80211_BAND_2GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
+ break;
+ case NL80211_BAND_5GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
+ break;
+ case NL80211_BAND_6GHZ:
+ dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
+ break;
+ default:
+ dpd_mask = 0;
+ break;
+ }
+
+ if (!(eep[offs] & dpd_mask))
return 0;
- idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
+ idx = mt7915_dpd_freq_idx(dev, center_freq, chandef->width);
if (idx < 0)
return -EINVAL;
/* Items: Tx DPD, Tx Flatness */
- idx = idx * 2;
- cal += MT_EE_CAL_GROUP_SIZE;
+ idx = idx * cal_num;
+ cal += mt7915_get_cal_group_size(dev) + (idx * MT_EE_CAL_UNIT);
- while (total--) {
+ while (cal_num--) {
int ret;
- cal += (idx * MT_EE_CAL_UNIT);
ret = mt7915_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT,
MCU_EXT_CMD(DPD_PRE_CAL_INFO));
if (ret)
return ret;
idx++;
+ cal += MT_EE_CAL_UNIT;
}
return 0;
@@ -3064,8 +3193,13 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
res = (struct mt7915_mcu_mib *)(skb->data + offs_cc);
#define __res_u64(s) le64_to_cpu(res[s].data)
- /* subtract Tx backoff time from Tx duration */
- cc_tx = is_mt7915(&dev->mt76) ? __res_u64(1) - __res_u64(4) : __res_u64(1);
+ /* subtract Tx backoff time from Tx duration for MT7915 */
+ if (is_mt7915(&dev->mt76)) {
+ u64 backoff = (__res_u64(4) & 0xffff) * 79; /* 16us + 9us * 7 */
+ cc_tx = __res_u64(1) - backoff;
+ } else {
+ cc_tx = __res_u64(1);
+ }
if (chan_switch)
goto out;
@@ -3211,7 +3345,7 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
if (ret)
return ret;
- txpower = mt7915_get_power_bound(phy, txpower);
+ txpower = mt76_get_power_bound(mphy, txpower);
if (txpower > mphy->txpower_cur || txpower < 0)
return -EINVAL;
@@ -3261,7 +3395,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
int i, idx;
int tx_power;
- tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
+ tx_power = mt76_get_power_bound(mphy, hw->conf.power_level);
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
&limits_array, tx_power);
mphy->txpower_cur = tx_power;
@@ -3801,30 +3935,38 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
{
struct {
__le32 cmd;
- __le32 num;
- __le32 __rsv;
- __le16 wlan_idx;
- } req = {
+ __le32 arg0;
+ __le32 arg1;
+ __le16 arg2;
+ } __packed req = {
.cmd = cpu_to_le32(0x15),
- .num = cpu_to_le32(1),
- .wlan_idx = cpu_to_le16(wlan_idx),
};
struct mt7915_mcu_wa_tx_stat {
- __le16 wlan_idx;
- u8 __rsv[2];
+ __le16 wcid;
+ u8 __rsv2[2];
/* tx_bytes is deprecated since WA byte counter uses u32,
* which easily leads to overflow.
*/
__le32 tx_bytes;
__le32 tx_packets;
- } *res;
+ } __packed *res;
struct mt76_wcid *wcid;
struct sk_buff *skb;
- int ret;
+ int ret, len;
+ u16 ret_wcid;
+
+ if (is_mt7915(&dev->mt76)) {
+ req.arg0 = cpu_to_le32(wlan_idx);
+ len = sizeof(req) - sizeof(req.arg2);
+ } else {
+ req.arg0 = cpu_to_le32(1);
+ req.arg2 = cpu_to_le16(wlan_idx);
+ len = sizeof(req);
+ }
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
- &req, sizeof(req), true, &skb);
+ &req, len, true, &skb);
if (ret)
return ret;
@@ -3833,7 +3975,11 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
- if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
+ ret_wcid = le16_to_cpu(res->wcid);
+ if (is_mt7915(&dev->mt76))
+ ret_wcid &= 0xff;
+
+ if (ret_wcid != wlan_idx) {
ret = -EINVAL;
goto out;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index b41ac4aaced7..086ad89ecd91 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -29,7 +29,7 @@ struct mt7915_mcu_thermal_ctrl {
} __packed;
struct mt7915_mcu_thermal_notify {
- struct mt76_connac2_mcu_rxd rxd;
+ struct mt76_connac2_mcu_rxd_hdr rxd;
struct mt7915_mcu_thermal_ctrl ctrl;
__le32 temperature;
@@ -37,7 +37,7 @@ struct mt7915_mcu_thermal_notify {
} __packed;
struct mt7915_mcu_csa_notify {
- struct mt76_connac2_mcu_rxd rxd;
+ struct mt76_connac2_mcu_rxd_hdr rxd;
u8 omac_idx;
u8 csa_count;
@@ -46,7 +46,7 @@ struct mt7915_mcu_csa_notify {
} __packed;
struct mt7915_mcu_bcc_notify {
- struct mt76_connac2_mcu_rxd rxd;
+ struct mt76_connac2_mcu_rxd_hdr rxd;
u8 band_idx;
u8 omac_idx;
@@ -55,9 +55,9 @@ struct mt7915_mcu_bcc_notify {
} __packed;
struct mt7915_mcu_rdd_report {
- struct mt76_connac2_mcu_rxd rxd;
+ struct mt76_connac2_mcu_rxd_hdr rxd;
- u8 band_idx;
+ u8 rdd_idx;
u8 long_detected;
u8 constant_prf_detected;
u8 staggered_prf_detected;
@@ -515,16 +515,4 @@ enum {
sizeof(struct bss_info_bmc_rate) +\
sizeof(struct bss_info_ext_bss))
-static inline s8
-mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
-{
- struct mt76_phy *mphy = phy->mt76;
- int n_chains = hweight16(mphy->chainmask);
-
- txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
- txpower -= mt76_tx_power_nss_delta(n_chains);
-
- return txpower;
-}
-
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
index 3039f53e2245..9c4d5cea0c42 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
@@ -138,6 +138,7 @@ static const u32 mt7915_offs[] = {
[AGG_ACR0] = 0x084,
[AGG_ACR4] = 0x08c,
[AGG_MRCR] = 0x098,
+ [AGG_ATCR0] = 0x0ec,
[AGG_ATCR1] = 0x0f0,
[AGG_ATCR3] = 0x0f4,
[LPON_UTTR0] = 0x080,
@@ -212,6 +213,7 @@ static const u32 mt7916_offs[] = {
[AGG_ACR0] = 0x054,
[AGG_ACR4] = 0x05c,
[AGG_MRCR] = 0x068,
+ [AGG_ATCR0] = 0x1a4,
[AGG_ATCR1] = 0x1a8,
[AGG_ATCR3] = 0x080,
[LPON_UTTR0] = 0x360,
@@ -484,12 +486,17 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
continue;
ofs = addr - dev->reg.map[i].phys;
- if (ofs > dev->reg.map[i].size)
+ if (ofs >= dev->reg.map[i].size)
continue;
return dev->reg.map[i].maps + ofs;
}
+ return 0;
+}
+
+static u32 __mt7915_reg_remap_addr(struct mt7915_dev *dev, u32 addr)
+{
if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
(addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
(addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
@@ -514,15 +521,30 @@ void mt7915_memcpy_fromio(struct mt7915_dev *dev, void *buf, u32 offset,
{
u32 addr = __mt7915_reg_addr(dev, offset);
- memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
+ if (addr) {
+ memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
+ return;
+ }
+
+ spin_lock_bh(&dev->reg_lock);
+ memcpy_fromio(buf, dev->mt76.mmio.regs +
+ __mt7915_reg_remap_addr(dev, offset), len);
+ spin_unlock_bh(&dev->reg_lock);
}
static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
- u32 addr = __mt7915_reg_addr(dev, offset);
+ u32 addr = __mt7915_reg_addr(dev, offset), val;
+
+ if (addr)
+ return dev->bus_ops->rr(mdev, addr);
- return dev->bus_ops->rr(mdev, addr);
+ spin_lock_bh(&dev->reg_lock);
+ val = dev->bus_ops->rr(mdev, __mt7915_reg_remap_addr(dev, offset));
+ spin_unlock_bh(&dev->reg_lock);
+
+ return val;
}
static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
@@ -530,7 +552,14 @@ static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
u32 addr = __mt7915_reg_addr(dev, offset);
- dev->bus_ops->wr(mdev, addr, val);
+ if (addr) {
+ dev->bus_ops->wr(mdev, addr, val);
+ return;
+ }
+
+ spin_lock_bh(&dev->reg_lock);
+ dev->bus_ops->wr(mdev, __mt7915_reg_remap_addr(dev, offset), val);
+ spin_unlock_bh(&dev->reg_lock);
}
static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
@@ -538,7 +567,14 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
u32 addr = __mt7915_reg_addr(dev, offset);
- return dev->bus_ops->rmw(mdev, addr, mask, val);
+ if (addr)
+ return dev->bus_ops->rmw(mdev, addr, mask, val);
+
+ spin_lock_bh(&dev->reg_lock);
+ val = dev->bus_ops->rmw(mdev, __mt7915_reg_remap_addr(dev, offset), mask, val);
+ spin_unlock_bh(&dev->reg_lock);
+
+ return val;
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
@@ -615,6 +651,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
wed->wlan.base = devm_ioremap(dev->mt76.dev,
pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
+ if (!wed->wlan.base)
+ return -ENOMEM;
+
wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
wed->wlan.wpdma_int = pci_resource_start(pci_dev, 0) +
MT_INT_WED_SOURCE_CSR;
@@ -642,6 +681,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
wed->wlan.bus_type = MTK_WED_BUS_AXI;
wed->wlan.base = devm_ioremap(dev->mt76.dev, res->start,
resource_size(res));
+ if (!wed->wlan.base)
+ return -ENOMEM;
+
wed->wlan.phy_base = res->start;
wed->wlan.wpdma_int = res->start + MT_INT_SOURCE_CSR;
wed->wlan.wpdma_mask = res->start + MT_INT_MASK_CSR;
@@ -672,13 +714,13 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
}
wed->wlan.init_buf = mt7915_wed_init_buf;
- wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
- wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
- wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
- wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
+ wed->wlan.offload_enable = mt76_wed_offload_enable;
+ wed->wlan.offload_disable = mt76_wed_offload_disable;
+ wed->wlan.init_rx_buf = mt76_wed_init_rx_buf;
+ wed->wlan.release_rx_buf = mt76_wed_release_rx_buf;
wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats;
wed->wlan.reset = mt7915_mmio_wed_reset;
- wed->wlan.reset_complete = mt76_mmio_wed_reset_complete;
+ wed->wlan.reset_complete = mt76_wed_reset_complete;
dev->mt76.rx_token_size = wed->wlan.rx_npkt;
@@ -707,6 +749,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev,
dev = container_of(mdev, struct mt7915_dev, mt76);
mt76_mmio_init(&dev->mt76, mem_base);
+ spin_lock_init(&dev->reg_lock);
switch (device_id) {
case 0x7915:
@@ -892,8 +935,10 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
.rx_check = mt7915_rx_check,
.rx_poll_complete = mt7915_rx_poll_complete,
.sta_add = mt7915_mac_sta_add,
+ .sta_event = mt7915_mac_sta_event,
.sta_remove = mt7915_mac_sta_remove,
.update_survey = mt7915_update_channel,
+ .set_channel = mt7915_set_channel,
};
struct mt7915_dev *dev;
struct mt76_dev *mdev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 4727d9c7b11d..2e94347c46d6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -166,7 +166,7 @@ struct mt7915_vif_cap {
};
struct mt7915_vif {
- struct mt76_vif mt76; /* must be first */
+ struct mt76_vif_link mt76; /* must be first */
struct mt7915_vif_cap cap;
struct mt7915_sta sta;
@@ -191,6 +191,7 @@ struct mt7915_hif {
struct device *dev;
void __iomem *regs;
int irq;
+ u32 index;
};
struct mt7915_phy {
@@ -214,8 +215,6 @@ struct mt7915_phy {
s16 coverage_class;
u8 slottime;
- u8 rdd_state;
-
u32 trb_ts;
u32 rx_ampdu_ts;
@@ -287,6 +286,7 @@ struct mt7915_dev {
struct list_head sta_rc_list;
struct list_head twt_list;
+ spinlock_t reg_lock;
u32 hw_pattern;
@@ -301,6 +301,10 @@ struct mt7915_dev {
struct rchan *relay_fwlog;
void *cal;
+ u32 cur_prek_offset;
+ u8 dpd_chan_num_2g;
+ u8 dpd_chan_num_5g;
+ u8 dpd_chan_num_6g;
struct {
u8 debug_wm;
@@ -325,10 +329,10 @@ enum {
__MT_WFDMA_MAX,
};
-enum {
- MT_RX_SEL0,
- MT_RX_SEL1,
- MT_RX_SEL2, /* monitor chain */
+enum rdd_idx {
+ MT_RDD_IDX_BAND0, /* RDD idx for band idx 0 (single-band) */
+ MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */
+ MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */
};
enum mt7915_rdd_cmd {
@@ -348,6 +352,18 @@ enum mt7915_rdd_cmd {
RDD_IRQ_OFF,
};
+static inline int
+mt7915_get_rdd_idx(struct mt7915_phy *phy, bool is_background)
+{
+ if (!phy->mt76->cap.has_5ghz)
+ return -1;
+
+ if (is_background)
+ return MT_RDD_IDX_BACKGROUND;
+
+ return phy->mt76->band_idx;
+}
+
static inline struct mt7915_phy *
mt7915_hw_phy(struct ieee80211_hw *hw)
{
@@ -419,6 +435,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx);
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
+bool mt7915_eeprom_has_background_radar(struct mt7915_dev *dev);
int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
void mt7915_dma_prefetch(struct mt7915_dev *dev);
void mt7915_dma_cleanup(struct mt7915_dev *dev);
@@ -439,7 +456,7 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,
int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
struct ieee80211_vif *vif, int enable);
int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, bool enable);
+ struct ieee80211_sta *sta, int conn_state, bool newly);
int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,
struct ieee80211_ampdu_params *params,
bool add);
@@ -458,7 +475,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool changed);
int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
-int mt7915_set_channel(struct mt7915_phy *phy);
+int mt7915_set_channel(struct mt76_phy *mphy);
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd);
int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif);
int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req);
@@ -467,7 +484,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
struct ieee80211_sta *sta,
void *data, u32 field);
int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
-int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
+int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf);
int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
bool hdr_trans);
@@ -555,6 +572,8 @@ void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
void mt7915_mac_set_timing(struct mt7915_phy *phy);
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, enum mt76_sta_event ev);
void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7915_mac_work(struct work_struct *work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
index 39132894e8ea..07b0a5766eab 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
@@ -42,6 +42,7 @@ static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx)
continue;
get_device(hif->dev);
+ hif->index = idx;
goto out;
}
hif = NULL;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
index 89ac8e6707b8..c5ec63a25a42 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
@@ -66,6 +66,7 @@ enum offs_rev {
AGG_ACR0,
AGG_ACR4,
AGG_MRCR,
+ AGG_ATCR0,
AGG_ATCR1,
AGG_ATCR3,
LPON_UTTR0,
@@ -254,6 +255,9 @@ enum offs_rev {
#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30)
#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24)
+#define MT_WTBLOFF_TOP_ACR(_band) MT_WTBLOFF_TOP(_band, 0x010)
+#define MT_WTBLOFF_TOP_ADM_BACKOFFTIME BIT(29)
+
/* ETBF: band 0(0x820ea000), band 1(0x820fa000) */
#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000)
#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs))
@@ -505,6 +509,9 @@ enum offs_rev {
#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7)
#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24)
+#define MT_AGG_ATCR0(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR0))
+#define MT_AGG_ATCR_MAC_BFF_TIME_EN BIT(30)
+
#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR1))
#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR3))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
index 8b4809703efc..c823a7554a3a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
@@ -7,7 +7,6 @@
#include <linux/pinctrl/consumer.h>
#include <linux/of.h>
#include <linux/of_reserved_mem.h>
-#include <linux/of_gpio.h>
#include <linux/iopoll.h>
#include <linux/reset.h>
#include <linux/of_net.h>
@@ -516,7 +515,8 @@ static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
if (ret)
return ret;
- if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
+ if (version == 0x8a00 || version == 0x8a10 ||
+ version == 0x8b00 || version == 0x8c10) {
rg_xo_01 = 0x1d59080f;
rg_xo_03 = 0x34c00fe0;
} else {
@@ -1303,7 +1303,7 @@ struct platform_driver mt798x_wmac_driver = {
.of_match_table = mt798x_wmac_of_match,
},
.probe = mt798x_wmac_probe,
- .remove_new = mt798x_wmac_remove,
+ .remove = mt798x_wmac_remove,
};
MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
index 0d76ae31b376..d534fff5c952 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
@@ -404,6 +404,7 @@ static void
mt7915_tm_init(struct mt7915_phy *phy, bool en)
{
struct mt7915_dev *dev = phy->dev;
+ int state;
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
@@ -415,7 +416,8 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
mt7915_tm_set_trx(phy, TM_MAC_TXRX, !en);
mt7915_mcu_add_bss_info(phy, phy->monitor_vif, en);
- mt7915_mcu_add_sta(dev, phy->monitor_vif, NULL, en);
+ state = en ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT;
+ mt7915_mcu_add_sta(dev, phy->monitor_vif, NULL, state, true);
if (!en)
mt7915_tm_set_tam_arb(phy, en, 0);
@@ -425,7 +427,7 @@ static void
mt7915_tm_update_channel(struct mt7915_phy *phy)
{
mutex_unlock(&phy->dev->mt76.mutex);
- mt7915_set_channel(phy);
+ mt76_update_channel(phy->mt76);
mutex_lock(&phy->dev->mt76.mutex);
mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));