Merge tag 'mt76-for-kvalo-2023-07-31' of https://github.com/nbd168/wireless

mt76 patches for 6.6

* fixes
* preparation for mt7925 support
* mt7981 support
This commit is contained in:
Kalle Valo
2023-08-02 12:36:37 +03:00
84 changed files with 5821 additions and 4896 deletions
@@ -28,6 +28,7 @@ properties:
- mediatek,mt76
- mediatek,mt7628-wmac
- mediatek,mt7622-wmac
- mediatek,mt7981-wmac
- mediatek,mt7986-wmac
reg:
@@ -71,6 +72,14 @@ properties:
ieee80211-freq-limit: true
nvmem-cells:
items:
- description: NVMEM cell with EEPROM
nvmem-cell-names:
items:
- const: eeprom
mediatek,eeprom-data:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
@@ -84,6 +93,7 @@ properties:
- description: offset containing EEPROM data
description:
Phandle to a MTD partition + offset containing EEPROM data
deprecated: true
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
@@ -258,7 +268,8 @@ examples:
interrupt-parent = <&cpuintc>;
interrupts = <6>;
mediatek,mtd-eeprom = <&factory 0x0>;
nvmem-cells = <&eeprom>;
nvmem-cell-names = "eeprom";
};
- |
@@ -29,6 +29,14 @@ config MT76_CONNAC_LIB
tristate
select MT76_CORE
config MT792x_LIB
tristate
select MT76_CONNAC_LIB
config MT792x_USB
tristate
select MT76_USB
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig"
+9 -1
View File
@@ -5,6 +5,8 @@ obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o
obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o
obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o
obj-$(CONFIG_MT792x_LIB) += mt792x-lib.o
obj-$(CONFIG_MT792x_USB) += mt792x-usb.o
mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
@@ -19,6 +21,7 @@ mt76-sdio-y := sdio.o sdio_txrx.o
CFLAGS_trace.o := -I$(src)
CFLAGS_usb_trace.o := -I$(src)
CFLAGS_mt76x02_trace.o := -I$(src)
CFLAGS_mt792x_trace.o := -I$(src)
mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \
@@ -27,7 +30,12 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o
mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \
mt792x_debugfs.o mt792x_dma.o
mt792x-lib-$(CONFIG_ACPI) += mt792x_acpi_sar.o
mt792x-usb-y := mt792x_usb.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
+6
View File
@@ -466,6 +466,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf buf = {};
dma_addr_t addr;
if (test_bit(MT76_MCU_RESET, &dev->phy.state))
goto error;
if (q->queued + 1 >= q->ndesc - 1)
goto error;
@@ -507,6 +510,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
dma_addr_t addr;
u8 *txwi;
if (test_bit(MT76_RESET, &dev->phy.state))
goto free_skb;
t = mt76_get_txwi(dev);
if (!t)
goto free_skb;
+72 -17
View File
@@ -6,35 +6,40 @@
#include <linux/of_net.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/nvmem-consumer.h>
#include <linux/etherdevice.h>
#include "mt76.h"
int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
{
#if defined(CONFIG_OF) && defined(CONFIG_MTD)
struct device_node *np = dev->dev->of_node;
const void *data;
int size;
data = of_get_property(np, "mediatek,eeprom-data", &size);
if (!data)
return -ENOENT;
if (size > len)
return -EINVAL;
memcpy(eep, data, size);
return 0;
}
static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len)
{
#ifdef CONFIG_MTD
struct device_node *np = dev->dev->of_node;
struct mtd_info *mtd;
const __be32 *list;
const void *data;
const char *part;
phandle phandle;
int size;
size_t retlen;
int size;
int ret;
if (!np)
return -ENOENT;
data = of_get_property(np, "mediatek,eeprom-data", &size);
if (data) {
if (size > len)
return -EINVAL;
memcpy(eep, data, size);
return 0;
}
list = of_get_property(np, "mediatek,mtd-eeprom", &size);
if (!list)
return -ENOENT;
@@ -100,6 +105,56 @@ out_put_node:
return -ENOENT;
#endif
}
static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int len)
{
struct device_node *np = dev->dev->of_node;
struct nvmem_cell *cell;
const void *data;
size_t retlen;
int ret = 0;
cell = of_nvmem_cell_get(np, "eeprom");
if (IS_ERR(cell))
return PTR_ERR(cell);
data = nvmem_cell_read(cell, &retlen);
nvmem_cell_put(cell);
if (IS_ERR(data))
return PTR_ERR(data);
if (retlen < len) {
ret = -EINVAL;
goto exit;
}
memcpy(eep, data, len);
exit:
kfree(data);
return ret;
}
int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
{
struct device_node *np = dev->dev->of_node;
int ret;
if (!np)
return -ENOENT;
ret = mt76_get_of_eeprom_data(dev, eep, len);
if (!ret)
return 0;
ret = mt76_get_of_epprom_from_mtd(dev, eep, offset, len);
if (!ret)
return 0;
return mt76_get_of_epprom_from_nvmem(dev, eep, len);
}
EXPORT_SYMBOL_GPL(mt76_get_of_eeprom);
void
@@ -76,6 +76,7 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
CHAN5G(165, 5825),
CHAN5G(169, 5845),
CHAN5G(173, 5865),
CHAN5G(177, 5885),
};
static const struct ieee80211_channel mt76_channels_6ghz[] = {
@@ -660,6 +661,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
idr_init(&dev->rx_token);
INIT_LIST_HEAD(&dev->wcid_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
INIT_LIST_HEAD(&dev->txwi_cache);
INIT_LIST_HEAD(&dev->rxwi_cache);
@@ -1743,6 +1746,9 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
for (i = 0; i < (eht ? 14 : 12); i++)
data[ei++] += stats->tx_mcs[i];
for (i = 0; i < 4; i++)
data[ei++] += stats->tx_nss[i];
wi->worker_stat_count = ei - wi->initial_stat_idx;
}
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
+105 -1
View File
@@ -277,7 +277,7 @@ struct mt76_sta_stats {
u64 tx_mcs[16]; /* mcs idx */
u64 tx_bytes;
/* WED TX */
u32 tx_packets;
u32 tx_packets; /* unit: MSDU */
u32 tx_retries;
u32 tx_failed;
/* WED RX */
@@ -316,6 +316,7 @@ struct mt76_wcid {
int inactive_count;
struct rate_info rate;
unsigned long ampdu_state;
u16 idx;
u8 hw_key_idx;
@@ -336,6 +337,8 @@ struct mt76_wcid {
struct idr pktid;
struct mt76_sta_stats stats;
struct list_head poll_list;
};
struct mt76_txq {
@@ -702,6 +705,9 @@ struct mt76_vif {
u8 wmm_idx;
u8 scan_seq_num;
u8 cipher;
u8 basic_rates_idx;
u8 mcast_rates_idx;
u8 beacon_rates_idx;
};
struct mt76_phy {
@@ -823,6 +829,9 @@ struct mt76_dev {
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
struct list_head wcid_list;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
u32 rev;
struct tasklet_struct pre_tbtt_tasklet;
@@ -857,6 +866,101 @@ struct mt76_dev {
};
};
/* per-phy stats. */
struct mt76_mib_stats {
u32 ack_fail_cnt;
u32 fcs_err_cnt;
u32 rts_cnt;
u32 rts_retries_cnt;
u32 ba_miss_cnt;
u32 tx_bf_cnt;
u32 tx_mu_bf_cnt;
u32 tx_mu_mpdu_cnt;
u32 tx_mu_acked_mpdu_cnt;
u32 tx_su_acked_mpdu_cnt;
u32 tx_bf_ibf_ppdu_cnt;
u32 tx_bf_ebf_ppdu_cnt;
u32 tx_bf_rx_fb_all_cnt;
u32 tx_bf_rx_fb_eht_cnt;
u32 tx_bf_rx_fb_he_cnt;
u32 tx_bf_rx_fb_vht_cnt;
u32 tx_bf_rx_fb_ht_cnt;
u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */
u32 tx_bf_rx_fb_nc_cnt;
u32 tx_bf_rx_fb_nr_cnt;
u32 tx_bf_fb_cpl_cnt;
u32 tx_bf_fb_trig_cnt;
u32 tx_ampdu_cnt;
u32 tx_stop_q_empty_cnt;
u32 tx_mpdu_attempts_cnt;
u32 tx_mpdu_success_cnt;
u32 tx_pkt_ebf_cnt;
u32 tx_pkt_ibf_cnt;
u32 tx_rwp_fail_cnt;
u32 tx_rwp_need_cnt;
/* rx stats */
u32 rx_fifo_full_cnt;
u32 channel_idle_cnt;
u32 primary_cca_busy_time;
u32 secondary_cca_busy_time;
u32 primary_energy_detect_time;
u32 cck_mdrdy_time;
u32 ofdm_mdrdy_time;
u32 green_mdrdy_time;
u32 rx_vector_mismatch_cnt;
u32 rx_delimiter_fail_cnt;
u32 rx_mrdy_cnt;
u32 rx_len_mismatch_cnt;
u32 rx_mpdu_cnt;
u32 rx_ampdu_cnt;
u32 rx_ampdu_bytes_cnt;
u32 rx_ampdu_valid_subframe_cnt;
u32 rx_ampdu_valid_subframe_bytes_cnt;
u32 rx_pfdrop_cnt;
u32 rx_vec_queue_overflow_drop_cnt;
u32 rx_ba_cnt;
u32 tx_amsdu[8];
u32 tx_amsdu_cnt;
/* mcu_muru_stats */
u32 dl_cck_cnt;
u32 dl_ofdm_cnt;
u32 dl_htmix_cnt;
u32 dl_htgf_cnt;
u32 dl_vht_su_cnt;
u32 dl_vht_2mu_cnt;
u32 dl_vht_3mu_cnt;
u32 dl_vht_4mu_cnt;
u32 dl_he_su_cnt;
u32 dl_he_ext_su_cnt;
u32 dl_he_2ru_cnt;
u32 dl_he_2mu_cnt;
u32 dl_he_3ru_cnt;
u32 dl_he_3mu_cnt;
u32 dl_he_4ru_cnt;
u32 dl_he_4mu_cnt;
u32 dl_he_5to8ru_cnt;
u32 dl_he_9to16ru_cnt;
u32 dl_he_gtr16ru_cnt;
u32 ul_hetrig_su_cnt;
u32 ul_hetrig_2ru_cnt;
u32 ul_hetrig_3ru_cnt;
u32 ul_hetrig_4ru_cnt;
u32 ul_hetrig_5to8ru_cnt;
u32 ul_hetrig_9to16ru_cnt;
u32 ul_hetrig_gtr16ru_cnt;
u32 ul_hetrig_2mu_cnt;
u32 ul_hetrig_3mu_cnt;
u32 ul_hetrig_4mu_cnt;
};
struct mt76_power_limits {
s8 cck[4];
s8 ofdm[8];
@@ -161,7 +161,8 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
return;
}
dev->mt76.beacon_int = intval;
if (intval)
dev->mt76.beacon_int = intval;
mt76_wr(dev, MT_TBTT,
FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
@@ -500,8 +500,6 @@ int mt7603_register_device(struct mt7603_dev *dev)
bus_ops->rmw = mt7603_rmw;
dev->mt76.bus = bus_ops;
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
spin_lock_init(&dev->ps_lock);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work);
+27 -16
View File
@@ -178,8 +178,9 @@ mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled)
mt76_wr(dev, addr + 3 * 4, val);
}
void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort)
{
u32 flush_mask;
int i, port, queue;
if (abort) {
@@ -195,6 +196,18 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN |
FIELD_PREP(MT_TX_ABORT_WCID, idx));
flush_mask = MT_WF_ARB_TX_FLUSH_AC0 |
MT_WF_ARB_TX_FLUSH_AC1 |
MT_WF_ARB_TX_FLUSH_AC2 |
MT_WF_ARB_TX_FLUSH_AC3;
flush_mask <<= mac_idx;
mt76_wr(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask);
mt76_poll(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask, 0, 20000);
mt76_wr(dev, MT_WF_ARB_TX_START_0, flush_mask);
mt76_wr(dev, MT_TX_ABORT, 0);
for (i = 0; i < 4; i++) {
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) |
@@ -202,13 +215,11 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) |
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue));
mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000);
mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000);
}
WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY);
mt76_wr(dev, MT_TX_ABORT, 0);
mt7603_wtbl_set_skip_tx(dev, idx, false);
}
@@ -245,7 +256,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
if (enabled)
mt7603_filter_tx(dev, idx, false);
mt7603_filter_tx(dev, sta->vif->idx, idx, false);
addr = mt7603_wtbl1_addr(idx);
mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
@@ -412,16 +423,16 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev)
while (1) {
bool clear = false;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&dev->sta_poll_list)) {
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&dev->mt76.sta_poll_list)) {
spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&dev->sta_poll_list, struct mt7603_sta,
poll_list);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
msta = list_first_entry(&dev->mt76.sta_poll_list,
struct mt7603_sta, wcid.poll_list);
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7603_wtbl4_addr(msta->wcid.idx);
for (i = 0; i < 4; i++) {
@@ -1267,10 +1278,10 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
msta = container_of(wcid, struct mt7603_sta, wcid);
sta = wcid_to_sta(wcid);
if (list_empty(&msta->poll_list)) {
spin_lock_bh(&dev->sta_poll_lock);
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->wcid.poll_list)) {
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data))
@@ -66,9 +66,10 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
dev->mt76.vif_mask |= BIT_ULL(mvif->idx);
INIT_LIST_HEAD(&mvif->sta.poll_list);
INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.vif = mvif;
mt76_packet_id_init(&mvif->sta.wcid);
eth_broadcast_addr(bc_addr);
@@ -100,10 +101,10 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mutex_lock(&dev->mt76.mutex);
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
@@ -351,12 +352,13 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
INIT_LIST_HEAD(&msta->poll_list);
INIT_LIST_HEAD(&msta->wcid.poll_list);
__skb_queue_head_init(&msta->psq);
msta->ps = ~0;
msta->smps = ~0;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->vif = mvif;
mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr);
mt7603_wtbl_set_ps(dev, msta, false);
@@ -380,18 +382,19 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
spin_lock_bh(&dev->ps_lock);
__skb_queue_purge(&msta->psq);
mt7603_filter_tx(dev, wcid->idx, true);
mt7603_filter_tx(dev, mvif->idx, wcid->idx, true);
spin_unlock_bh(&dev->ps_lock);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
mt7603_wtbl_clear(dev, wcid->idx);
}
@@ -64,7 +64,6 @@ struct mt7603_sta {
struct mt7603_vif *vif;
struct list_head poll_list;
u32 tx_airtime_ac[4];
struct sk_buff_head psq;
@@ -110,9 +109,6 @@ struct mt7603_dev {
u32 rxfilter;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
struct mt7603_sta global_sta;
u32 agc0, agc3;
@@ -234,7 +230,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
bool enabled);
void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
bool enabled);
void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort);
void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort);
int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
@@ -309,6 +309,13 @@ enum {
#define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110)
#define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114)
#define MT_WF_ARB_TX_FLUSH_AC0 BIT(0)
#define MT_WF_ARB_TX_FLUSH_AC1 BIT(5)
#define MT_WF_ARB_TX_FLUSH_AC2 BIT(10)
#define MT_WF_ARB_TX_FLUSH_AC3 BIT(16)
#define MT_WF_ARB_TX_FLUSH_AC4 BIT(21)
#define MT_WF_ARB_TX_FLUSH_AC5 BIT(26)
#define MT_WF_ARB_BCN_START MT_WF_ARB(0x118)
#define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n))
#define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10)
@@ -397,6 +397,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
if (!is_mt7622(&phy->dev->mt76))
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
@@ -626,8 +628,6 @@ void mt7615_init_device(struct mt7615_dev *dev)
INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work);
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
init_waitqueue_head(&dev->phy.roc_wait);
+16 -15
View File
@@ -387,10 +387,11 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
struct mt7615_sta *msta;
msta = container_of(status->wcid, struct mt7615_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
}
if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask &&
@@ -905,19 +906,19 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev)
int i;
INIT_LIST_HEAD(&sta_poll_list);
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
while (!list_empty(&sta_poll_list)) {
bool clear = false;
msta = list_first_entry(&sta_poll_list, struct mt7615_sta,
poll_list);
wcid.poll_list);
spin_lock_bh(&dev->sta_poll_lock);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4;
@@ -1514,10 +1515,10 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
msta = container_of(wcid, struct mt7615_sta, wcid);
sta = wcid_to_sta(wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data))
goto out;
@@ -222,7 +222,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
idx = MT7615_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.poll_list);
INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -274,10 +274,10 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt7615_mutex_release(dev);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
}
@@ -552,6 +552,32 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw,
mt7615_mutex_release(dev);
}
static void
mt7615_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
u8 i, band = mvif->mt76.band_idx;
u32 *mu;
mu = (u32 *)info->mu_group.membership;
for (i = 0; i < WLAN_MEMBERSHIP_LEN / sizeof(*mu); i++) {
if (is_mt7663(&dev->mt76))
mt76_wr(dev, MT7663_WF_PHY_GID_TAB_VLD(band, i), mu[i]);
else
mt76_wr(dev, MT_WF_PHY_GID_TAB_VLD(band, i), mu[i]);
}
mu = (u32 *)info->mu_group.position;
for (i = 0; i < WLAN_USER_POSITION_LEN / sizeof(*mu); i++) {
if (is_mt7663(&dev->mt76))
mt76_wr(dev, MT7663_WF_PHY_GID_TAB_POS(band, i), mu[i]);
else
mt76_wr(dev, MT_WF_PHY_GID_TAB_POS(band, i), mu[i]);
}
}
static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@@ -600,6 +626,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC)
mt7615_mac_set_beacon_filter(phy, vif, vif->cfg.assoc);
if (changed & BSS_CHANGED_MU_GROUPS)
mt7615_update_mu_group(hw, vif, info);
mt7615_mutex_release(dev);
}
@@ -628,7 +657,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
INIT_LIST_HEAD(&msta->poll_list);
INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -676,10 +705,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt7615_mcu_add_bss_info(phy, vif, sta, false);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
}
@@ -125,7 +125,6 @@ struct mt7615_sta {
struct mt7615_vif *vif;
struct list_head poll_list;
u32 airtime_ac[8];
struct ieee80211_tx_rate rates[4];
@@ -262,9 +261,6 @@ struct mt7615_dev {
wait_queue_head_t reset_wait;
u32 reset_state;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
struct {
u8 n_pulses;
u32 period;
@@ -212,6 +212,15 @@ enum mt7615_reg_base {
#define MT7663_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0224 + ((_phy) << 12))
#define MT_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \
((_phy) << 9))
#define MT7663_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \
((_phy) << 12))
#define MT_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \
((_phy) << 9))
#define MT7663_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \
((_phy) << 12))
#define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c)
#define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \
GENMASK(28, 20))
@@ -197,11 +197,21 @@ static inline bool is_mt7916(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7906;
}
static inline bool is_mt7981(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7981;
}
static inline bool is_mt7986(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7986;
}
static inline bool is_mt798x(struct mt76_dev *dev)
{
return is_mt7981(dev) || is_mt7986(dev);
}
static inline bool is_mt7996(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7990;
@@ -409,5 +419,13 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
__le32 *rxv, u8 *mode);
void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta,
struct list_head *free_list);
void mt76_connac2_tx_token_put(struct mt76_dev *dev);
/* connac3 */
void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
u8 mode);
#endif /* __MT76_CONNAC_H */
@@ -34,7 +34,7 @@ enum {
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
#define MT_TX_FREE_COUNT GENMASK(12, 0)
/* 0: success, others: dropped */
#define MT_TX_FREE_STATUS GENMASK(14, 13)
#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt76_connac.h"
#include "mt76_connac3_mac.h"
#include "dma.h"
#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)
static void
mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
struct ieee80211_radiotap_he *he,
__le32 *rxv)
{
u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
status->bw = RATE_INFO_BW_HE_RU;
switch (ru) {
case 0 ... 36:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
offs = ru;
break;
case 37 ... 52:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
offs = ru - 37;
break;
case 53 ... 60:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
offs = ru - 53;
break;
case 61 ... 64:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
offs = ru - 61;
break;
case 65 ... 66:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
offs = ru - 65;
break;
case 67:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
break;
case 68:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
break;
}
he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
le16_encode_bits(offs,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
}
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
static void
mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he_mu mu_known = {
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
struct ieee80211_radiotap_he_mu *he_mu;
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
he_mu = skb_push(skb, sizeof(mu_known));
memcpy(he_mu, &mu_known, sizeof(mu_known));
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
if (status->he_dcm)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
if (status->bw >= RATE_INFO_BW_40) {
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
}
if (status->bw >= RATE_INFO_BW_80) {
u32 ru_h, ru_l;
he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
}
}
void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
u8 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he known = {
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
HE_BITS(DATA1_DATA_DCM_KNOWN) |
HE_BITS(DATA1_STBC_KNOWN) |
HE_BITS(DATA1_CODING_KNOWN) |
HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
HE_BITS(DATA1_DOPPLER_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
HE_BITS(DATA1_BSS_COLOR_KNOWN),
.data2 = HE_BITS(DATA2_GI_KNOWN) |
HE_BITS(DATA2_TXBF_KNOWN) |
HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
HE_BITS(DATA2_TXOP_KNOWN),
};
u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
struct ieee80211_radiotap_he *he;
status->flag |= RX_FLAG_RADIOTAP_HE;
he = skb_push(skb, sizeof(known));
memcpy(he, &known, sizeof(known));
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
le16_encode_bits(ltf_size,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
he->data5 |= HE_BITS(DATA5_TXBF);
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
switch (mode) {
case MT_PHY_TYPE_HE_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_MU:
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
HE_BITS(DATA1_UL_DL_KNOWN);
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
break;
case MT_PHY_TYPE_HE_TB:
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
break;
default:
break;
}
}
EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
@@ -0,0 +1,339 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT76_CONNAC3_MAC_H
#define __MT76_CONNAC3_MAC_H
enum {
MT_CTX0,
MT_HIF0 = 0x0,
MT_LMAC_AC00 = 0x0,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
MT_LMAC_PSMP0,
};
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
#define MT_RXD0_LENGTH GENMASK(15, 0)
#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
#define MT_RXD0_MESH BIT(18)
#define MT_RXD0_MHCP BIT(19)
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16)
#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
#define MT_RXD1_NORMAL_GROUP_2 BIT(17)
#define MT_RXD1_NORMAL_GROUP_3 BIT(18)
#define MT_RXD1_NORMAL_GROUP_4 BIT(19)
#define MT_RXD1_NORMAL_GROUP_5 BIT(20)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(7)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13)
#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(18)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_CO_ANT BIT(22)
#define MT_RXD3_NORMAL_FCS_ERR BIT(24)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
#define MT_RXV_HDR_BAND_IDX BIT(24)
/* RXD GROUP4 */
#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD10_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD10_QOS_CTL GENMASK(31, 16)
#define MT_RXD11_HT_CONTROL GENMASK(31, 0)
/* P-RXV */
#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(10, 7)
#define MT_PRXV_TXBF BIT(11)
#define MT_PRXV_HT_AD_CODE BIT(12)
#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3)
#define MT_PRXV_HT_STBC GENMASK(10, 9)
#define MT_PRXV_TX_MODE GENMASK(14, 11)
#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
#define MT_PRXV_DCM BIT(5)
/* C-RXV */
#define MT_CRXV_HE_NUM_USER GENMASK(26, 20)
#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30)
#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
#define MT_CRXV_HE_UPLINK BIT(2)
#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
#define MT_CRXV_HE_BEAM_CHNG BIT(29)
#define MT_CRXV_HE_DOPPLER BIT(0)
#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_RU0 GENMASK(8, 0)
#define MT_CRXV_HE_RU1 GENMASK(17, 9)
#define MT_CRXV_HE_RU2 GENMASK(26, 18)
#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
enum tx_mgnt_type {
MT_TX_NORMAL,
MT_TX_TIMING,
MT_TX_ADDBA,
};
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
#define MT_TXD_SIZE (8 * 4)
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_FIXED_RATE BIT(31)
#define MT_TXD1_OWN_MAC GENMASK(30, 25)
#define MT_TXD1_TID GENMASK(24, 21)
#define MT_TXD1_BIP BIT(24)
#define MT_TXD1_ETH_802_3 BIT(20)
#define MT_TXD1_HDR_INFO GENMASK(20, 16)
#define MT_TXD1_HDR_FORMAT GENMASK(15, 14)
#define MT_TXD1_TGID GENMASK(13, 12)
#define MT_TXD1_WLAN_IDX GENMASK(11, 0)
#define MT_TXD2_POWER_OFFSET GENMASK(31, 26)
#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_HDR_PAD GENMASK(11, 10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_OWN_MAC_MAP BIT(8)
#define MT_TXD2_BF_TYPE GENMASK(6, 7)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_HW_AMSDU BIT(5)
#define MT_TXD3_BCM BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_FL BIT(15)
#define MT_TXD5_BYPASS_TBB BIT(14)
#define MT_TXD5_BYPASS_RBB BIT(13)
#define MT_TXD5_BSS_COLOR_ZERO BIT(12)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_SRC GENMASK(31, 30)
#define MT_TXD6_VTA BIT(28)
#define MT_TXD6_BW GENMASK(25, 22)
#define MT_TXD6_TX_RATE GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
#define MT_TXD6_DIS_MAT BIT(3)
#define MT_TXD6_DAS BIT(2)
#define MT_TXD6_AMSDU_CAP BIT(1)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_IP_SUM BIT(29)
#define MT_TXD7_DROP_BY_SDO BIT(28)
#define MT_TXD7_MAC_TXD BIT(27)
#define MT_TXD7_CTXD BIT(26)
#define MT_TXD7_CTXD_CNT GENMASK(25, 22)
#define MT_TXD7_UDP_TCP_SUM BIT(15)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TX_RATE_STBC BIT(14)
#define MT_TX_RATE_NSS GENMASK(13, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
/* VHT/HE only use bits 0-3 */
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
#define MT_TXFREE1_VER GENMASK(18, 16)
#define MT_TXFREE_INFO_PAIR BIT(31)
#define MT_TXFREE_INFO_HEADER BIT(30)
#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
#define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
#define MT_TXFREE_INFO_STAT GENMASK(29, 28)
#define MT_TXS0_BW GENMASK(31, 29)
#define MT_TXS0_TID GENMASK(28, 26)
#define MT_TXS0_AMPDU BIT(25)
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
#define MT_TXS0_BA_ERROR BIT(22)
#define MT_TXS0_PS_FLAG BIT(21)
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
#define MT_TXS0_BIP_ERROR BIT(19)
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
#define MT_TXS0_RTS_TIMEOUT BIT(17)
#define MT_TXS0_ACK_TIMEOUT BIT(16)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_STATUS_HOST BIT(15)
#define MT_TXS0_TX_STATUS_MCU BIT(14)
#define MT_TXS0_TX_RATE GENMASK(13, 0)
#define MT_TXS1_SEQNO GENMASK(31, 20)
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
#define MT_TXS2_BAND GENMASK(29, 28)
#define MT_TXS2_WCID GENMASK(27, 16)
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
#define MT_TXS3_PID GENMASK(31, 24)
#define MT_TXS3_RATE_STBC BIT(7)
#define MT_TXS3_FIXED_RATE BIT(6)
#define MT_TXS3_SRC GENMASK(5, 4)
#define MT_TXS3_SHARED_ANTENNA BIT(3)
#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0)
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
#define MT_TXS5_F0_QOS BIT(30)
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0)
#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24)
#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0)
#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24)
#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16)
#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8)
#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0)
#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24)
#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0)
#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24)
#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16)
#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8)
#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0)
#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
#endif /* __MT76_CONNAC3_MAC_H */
@@ -495,6 +495,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
BSS_CHANGED_BEACON_ENABLED));
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
bool amsdu_en = wcid->amsdu;
if (vif) {
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
@@ -521,9 +522,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
/* counting non-offloading skbs */
wcid->stats.tx_bytes += skb->len;
wcid->stats.tx_packets++;
/* mt7915 WA only counts WED path */
if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed))
wcid->stats.tx_packets++;
}
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
@@ -554,12 +555,14 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
txwi[4] = 0;
val = FIELD_PREP(MT_TXD5_PID, pid);
if (pid >= MT_PACKET_ID_FIRST)
if (pid >= MT_PACKET_ID_FIRST) {
val |= MT_TXD5_TX_STATUS_HOST;
amsdu_en = amsdu_en && !is_mt7921(dev);
}
txwi[5] = cpu_to_le32(val);
txwi[6] = 0;
txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
txwi[7] = amsdu_en ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
if (is_8023)
mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid);
@@ -606,12 +609,11 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
txs = le32_to_cpu(txs_data[0]);
/* PPDU based reporting */
if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
if (mtk_wed_device_active(&dev->mmio.wed) &&
FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
stats->tx_bytes +=
le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) -
le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE);
stats->tx_packets +=
le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT);
stats->tx_failed +=
le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
stats->tx_retries +=
@@ -729,17 +731,15 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
if (skb) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool noacked = !(info->flags & IEEE80211_TX_STAT_ACK);
if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ampdu_len = 1;
info->status.ampdu_ack_len = !noacked;
info->status.ampdu_ack_len =
!!(info->flags & IEEE80211_TX_STAT_ACK);
info->status.rates[0].idx = -1;
wcid->stats.tx_failed += noacked;
mt76_connac2_mac_fill_txs(dev, wcid, txs_data);
mt76_tx_status_skb_done(dev, skb, &list);
}
@@ -1112,3 +1112,85 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);
void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
struct mt76_wcid *wcid;
u16 fc, tid;
u32 val;
if (!sta ||
!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
return;
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
if (tid >= 6) /* skip VO queue */
return;
val = le32_to_cpu(txwi[2]);
fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
wcid = (struct mt76_wcid *)sta->drv_priv;
if (!test_and_set_bit(tid, &wcid->ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta,
struct list_head *free_list)
{
struct mt76_wcid *wcid;
__le32 *txwi;
u16 wcid_idx;
mt76_connac_txp_skb_unmap(dev, t);
if (!t->skb)
goto out;
txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
if (sta) {
wcid = (struct mt76_wcid *)sta->drv_priv;
wcid_idx = wcid->idx;
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid = rcu_dereference(dev->wcid[wcid_idx]);
if (wcid && wcid->sta) {
sta = container_of((void *)wcid, struct ieee80211_sta,
drv_priv);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&wcid->poll_list))
list_add_tail(&wcid->poll_list,
&dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
}
}
if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt76_connac2_tx_check_aggr(sta, txwi);
__mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
out:
t->skb = NULL;
mt76_put_txwi(dev, t);
}
EXPORT_SYMBOL_GPL(mt76_connac2_txwi_free);
void mt76_connac2_tx_token_put(struct mt76_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->token_lock);
idr_for_each_entry(&dev->token, txwi, id) {
mt76_connac2_txwi_free(dev, txwi, NULL, NULL);
dev->token_count--;
}
spin_unlock_bh(&dev->token_lock);
idr_destroy(&dev->token);
}
EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put);
@@ -22,6 +22,7 @@
#define FW_START_OVERRIDE BIT(0)
#define FW_START_WORKING_PDA_CR4 BIT(2)
#define FW_START_WORKING_PDA_DSP BIT(3)
#define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0)
#define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
@@ -518,7 +519,8 @@ struct sta_rec_muru {
u8 uo_ra;
u8 he_2x996_tone;
u8 rx_t_frame_11ac;
u8 rsv[3];
u8 rx_ctrl_frame_to_mbss;
u8 rsv[2];
} ofdma_ul;
struct {
@@ -998,6 +1000,7 @@ enum {
MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
MCU_EXT_EVENT_RDD_REPORT = 0x3a,
MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
MCU_EXT_EVENT_WA_TX_STAT = 0x74,
MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
MCU_EXT_EVENT_MURU_CTRL = 0x9f,
};
@@ -1287,6 +1290,7 @@ enum {
UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21,
UNI_BSS_INFO_BCNFT = 22,
UNI_BSS_INFO_IFS_TIME = 23,
UNI_BSS_INFO_OFFLOAD = 25,
UNI_BSS_INFO_MLD = 26,
};
@@ -853,7 +853,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
if (WARN_ON_ONCE(len > skb->len))
return -EINVAL;
pskb_trim(skb, len);
if (pskb_trim(skb, len))
return -EINVAL;
status->chains = BIT(0);
signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
@@ -14,12 +14,12 @@ config MT7915E
To compile this driver as a module, choose M here.
config MT7986_WMAC
bool "MT7986 (SoC) WMAC support"
config MT798X_WMAC
bool "MT798x (SoC) WMAC support"
depends on MT7915E
depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
This adds support for the built-in WMAC on MT7986 SoC device
This adds support for the built-in WMAC on MT7981 and MT7986 SoC device
which has the same feature set as a MT7915, but enables 6E
support.
@@ -6,5 +6,5 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o
mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
mt7915e-$(CONFIG_MT798X_WMAC) += soc.o
mt7915e-$(CONFIG_DEV_COREDUMP) += coredump.o
@@ -52,7 +52,7 @@ static const struct mt7915_mem_region mt7916_mem_regions[] = {
},
};
static const struct mt7915_mem_region mt7986_mem_regions[] = {
static const struct mt7915_mem_region mt798x_mem_regions[] = {
{
.start = 0x00800000,
.len = 0x0005ffff,
@@ -92,9 +92,10 @@ mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num)
case 0x7915:
*num = ARRAY_SIZE(mt7915_mem_regions);
return &mt7915_mem_regions[0];
case 0x7981:
case 0x7986:
*num = ARRAY_SIZE(mt7986_mem_regions);
return &mt7986_mem_regions[0];
*num = ARRAY_SIZE(mt798x_mem_regions);
return &mt798x_mem_regions[0];
case 0x7916:
*num = ARRAY_SIZE(mt7916_mem_regions);
return &mt7916_mem_regions[0];
@@ -251,7 +251,6 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
{
struct mt7915_phy *phy = file->private;
struct mt7915_dev *dev = phy->dev;
struct mt7915_mcu_muru_stats mu_stats = {};
static const char * const dl_non_he_type[] = {
"CCK", "OFDM", "HT MIX", "HT GF",
"VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU"
@@ -275,7 +274,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
mutex_lock(&dev->mt76.mutex);
ret = mt7915_mcu_muru_debug_get(phy, &mu_stats);
ret = mt7915_mcu_muru_debug_get(phy);
if (ret)
goto exit;
@@ -285,14 +284,13 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
for (i = 0; i < 5; i++)
seq_printf(file, "%8s | ", dl_non_he_type[i]);
#define __dl_u32(s) le32_to_cpu(mu_stats.dl.s)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ",
__dl_u32(cck_cnt),
__dl_u32(ofdm_cnt),
__dl_u32(htmix_cnt),
__dl_u32(htgf_cnt),
__dl_u32(vht_su_cnt));
phy->mib.dl_cck_cnt,
phy->mib.dl_ofdm_cnt,
phy->mib.dl_htmix_cnt,
phy->mib.dl_htgf_cnt,
phy->mib.dl_vht_su_cnt);
seq_puts(file, "\nDownlink MU-MIMO\nData Type: ");
@@ -301,23 +299,23 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | ",
__dl_u32(vht_2mu_cnt),
__dl_u32(vht_3mu_cnt),
__dl_u32(vht_4mu_cnt));
phy->mib.dl_vht_2mu_cnt,
phy->mib.dl_vht_3mu_cnt,
phy->mib.dl_vht_4mu_cnt);
sub_total_cnt = __dl_u32(vht_2mu_cnt) +
__dl_u32(vht_3mu_cnt) +
__dl_u32(vht_4mu_cnt);
sub_total_cnt = 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);
total_ppdu_cnt = sub_total_cnt +
__dl_u32(cck_cnt) +
__dl_u32(ofdm_cnt) +
__dl_u32(htmix_cnt) +
__dl_u32(htgf_cnt) +
__dl_u32(vht_su_cnt);
phy->mib.dl_cck_cnt +
phy->mib.dl_ofdm_cnt +
phy->mib.dl_htmix_cnt +
phy->mib.dl_htgf_cnt +
phy->mib.dl_vht_su_cnt;
seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt);
@@ -329,8 +327,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | ",
__dl_u32(he_su_cnt),
__dl_u32(he_ext_su_cnt));
phy->mib.dl_he_su_cnt, phy->mib.dl_he_ext_su_cnt);
seq_puts(file, "\nDownlink MU-MIMO\nData Type: ");
@@ -339,9 +336,8 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | ",
__dl_u32(he_2mu_cnt),
__dl_u32(he_3mu_cnt),
__dl_u32(he_4mu_cnt));
phy->mib.dl_he_2mu_cnt, phy->mib.dl_he_3mu_cnt,
phy->mib.dl_he_4mu_cnt);
seq_puts(file, "\nDownlink OFDMA\nData Type: ");
@@ -350,37 +346,35 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ",
__dl_u32(he_2ru_cnt),
__dl_u32(he_3ru_cnt),
__dl_u32(he_4ru_cnt),
__dl_u32(he_5to8ru_cnt),
__dl_u32(he_9to16ru_cnt),
__dl_u32(he_gtr16ru_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 = __dl_u32(he_2mu_cnt) +
__dl_u32(he_3mu_cnt) +
__dl_u32(he_4mu_cnt);
sub_total_cnt = 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 = __dl_u32(he_2ru_cnt) +
__dl_u32(he_3ru_cnt) +
__dl_u32(he_4ru_cnt) +
__dl_u32(he_5to8ru_cnt) +
__dl_u32(he_9to16ru_cnt) +
__dl_u32(he_gtr16ru_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;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld",
sub_total_cnt);
total_ppdu_cnt += __dl_u32(he_su_cnt) +
__dl_u32(he_ext_su_cnt);
total_ppdu_cnt += 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);
#undef __dl_u32
/* HE Uplink */
seq_puts(file, "\n\nUplink");
@@ -389,12 +383,11 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
for (i = 0; i < 3; i++)
seq_printf(file, "%8s | ", ul_he_type[i]);
#define __ul_u32(s) le32_to_cpu(mu_stats.ul.s)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | ",
__ul_u32(hetrig_2mu_cnt),
__ul_u32(hetrig_3mu_cnt),
__ul_u32(hetrig_4mu_cnt));
phy->mib.ul_hetrig_2mu_cnt,
phy->mib.ul_hetrig_3mu_cnt,
phy->mib.ul_hetrig_4mu_cnt);
seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type: ");
@@ -403,37 +396,36 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
seq_puts(file, "\nTotal Count:");
seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u | %7u | ",
__ul_u32(hetrig_su_cnt),
__ul_u32(hetrig_2ru_cnt),
__ul_u32(hetrig_3ru_cnt),
__ul_u32(hetrig_4ru_cnt),
__ul_u32(hetrig_5to8ru_cnt),
__ul_u32(hetrig_9to16ru_cnt),
__ul_u32(hetrig_gtr16ru_cnt));
phy->mib.ul_hetrig_su_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 = __ul_u32(hetrig_2mu_cnt) +
__ul_u32(hetrig_3mu_cnt) +
__ul_u32(hetrig_4mu_cnt);
sub_total_cnt = 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 = __ul_u32(hetrig_2ru_cnt) +
__ul_u32(hetrig_3ru_cnt) +
__ul_u32(hetrig_4ru_cnt) +
__ul_u32(hetrig_5to8ru_cnt) +
__ul_u32(hetrig_9to16ru_cnt) +
__ul_u32(hetrig_gtr16ru_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;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld",
sub_total_cnt);
total_ppdu_cnt += __ul_u32(hetrig_su_cnt);
total_ppdu_cnt += phy->mib.ul_hetrig_su_cnt;
seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt);
#undef __ul_u32
exit:
mutex_unlock(&dev->mt76.mutex);
@@ -719,10 +711,10 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
static void
mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
{
struct mt76_mib_stats *mib = &phy->mib;
static const char * const bw[] = {
"BW20", "BW40", "BW80", "BW160"
};
struct mib_stats *mib = &phy->mib;
/* Tx Beamformer monitor */
seq_puts(s, "\nTx Beamformer applied PPDU counts: ");
@@ -768,7 +760,7 @@ mt7915_tx_stats_show(struct seq_file *file, void *data)
{
struct mt7915_phy *phy = file->private;
struct mt7915_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
struct mt76_mib_stats *mib = &phy->mib;
int i;
mutex_lock(&dev->mt76.mutex);
+84 -68
View File
@@ -11,7 +11,7 @@ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base
struct mt7915_dev *dev = phy->dev;
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
if (is_mt7986(&dev->mt76))
if (is_mt798x(&dev->mt76))
ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
else
ring_base = MT_WED_TX_RING_BASE;
@@ -250,12 +250,90 @@ static void mt7915_dma_disable(struct mt7915_dev *dev, bool rst)
}
}
static int mt7915_dma_enable(struct mt7915_dev *dev)
int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset)
{
struct mt76_dev *mdev = &dev->mt76;
u32 hif1_ofs = 0;
u32 irq_mask;
if (dev->hif2)
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
/* enable wpdma tx/rx */
if (!reset) {
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (is_mt7915(mdev))
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (is_mt7915(mdev))
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_PDMA_BAND);
}
}
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_RX_DONE_MCU |
MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD;
if (!dev->phy.mt76->band_idx)
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support || dev->phy.mt76->band_idx)
irq_mask |= MT_INT_BAND1_RX_DONE;
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) {
u32 wed_irq_mask = irq_mask;
int ret;
wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
if (!is_mt798x(&dev->mt76))
mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
else
mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
ret = mt7915_mcu_wed_enable_rx_stats(dev);
if (ret)
return ret;
mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
}
irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
mt7915_irq_enable(dev, irq_mask);
mt7915_irq_disable(dev, 0);
return 0;
}
static int mt7915_dma_enable(struct mt7915_dev *dev, bool reset)
{
struct mt76_dev *mdev = &dev->mt76;
u32 hif1_ofs = 0;
if (dev->hif2)
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
@@ -322,69 +400,7 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC,
MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000);
/* set WFDMA Tx/Rx */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (is_mt7915(mdev))
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (is_mt7915(mdev))
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_PDMA_BAND);
}
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_RX_DONE_MCU |
MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD;
if (!dev->phy.mt76->band_idx)
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support || dev->phy.mt76->band_idx)
irq_mask |= MT_INT_BAND1_RX_DONE;
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
u32 wed_irq_mask = irq_mask;
int ret;
wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
if (!is_mt7986(&dev->mt76))
mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
else
mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
ret = mt7915_mcu_wed_enable_rx_stats(dev);
if (ret)
return ret;
mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
}
mt7915_irq_enable(dev, irq_mask);
return 0;
return mt7915_dma_start(dev, reset, true);
}
int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
@@ -404,7 +420,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
mt7915_dma_disable(dev, true);
if (mtk_wed_device_active(&mdev->mmio.wed)) {
if (!is_mt7986(mdev)) {
if (!is_mt798x(mdev)) {
u8 wed_control_rx1 = is_mt7915(mdev) ? 1 : 2;
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
@@ -560,7 +576,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
mt7915_poll_tx);
napi_enable(&dev->mt76.tx_napi);
mt7915_dma_enable(dev);
mt7915_dma_enable(dev, false);
return 0;
}
@@ -642,7 +658,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
mt76_rmw(dev, MT_WFDMA0_EXT0_CFG, MT_WFDMA0_EXT0_RXWB_KEEP,
MT_WFDMA0_EXT0_RXWB_KEEP);
mt7915_dma_enable(dev);
mt7915_dma_enable(dev, !force);
return 0;
}
@@ -39,6 +39,8 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)
return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76));
case 0x7916:
return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76));
case 0x7981:
return CHECK_EEPROM_ERR(is_mt7981(&dev->mt76));
case 0x7986:
return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76));
default:
@@ -52,6 +54,9 @@ static char *mt7915_eeprom_name(struct mt7915_dev *dev)
case 0x7915:
return dev->dbdc_support ?
MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;
case 0x7981:
/* mt7981 only supports mt7976 and only in DBDC mode */
return MT7981_EEPROM_MT7976_DEFAULT_DBDC;
case 0x7986:
switch (mt7915_check_adie(dev, true)) {
case MT7976_ONE_ADIE_DBDC:
@@ -215,7 +220,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
eeprom[MT_EE_WIFI_CONF + 2 + band]);
}
if (!is_mt7986(&dev->mt76))
if (!is_mt798x(&dev->mt76))
nss_max = 2;
}
@@ -415,7 +415,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
if (!dev->dbdc_support)
vht_cap->cap |=
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
} else {
vht_cap->cap |=
@@ -500,6 +499,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
/* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
*/
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
}
static void
@@ -582,6 +587,8 @@ void mt7915_mac_init(struct mt7915_dev *dev)
if (!is_mt7915(&dev->mt76))
mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
else
mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY);
/* enable hardware de-agg */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
@@ -733,7 +740,7 @@ void mt7915_wfsys_reset(struct mt7915_dev *dev)
mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
msleep(100);
} else if (is_mt7986(&dev->mt76)) {
} else if (is_mt798x(&dev->mt76)) {
mt7986_wmac_disable(dev);
msleep(20);
@@ -754,7 +761,7 @@ static bool mt7915_band_config(struct mt7915_dev *dev)
dev->phy.mt76->band_idx = 0;
if (is_mt7986(&dev->mt76)) {
if (is_mt798x(&dev->mt76)) {
u32 sku = mt7915_check_adie(dev, true);
/*
@@ -1159,11 +1166,11 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
static void mt7915_stop_hardware(struct mt7915_dev *dev)
{
mt7915_mcu_exit(dev);
mt7915_tx_token_put(dev);
mt76_connac2_tx_token_put(&dev->mt76);
mt7915_dma_cleanup(dev);
tasklet_disable(&dev->mt76.irq_tasklet);
if (is_mt7986(&dev->mt76))
if (is_mt798x(&dev->mt76))
mt7986_wmac_disable(dev);
}
@@ -1178,9 +1185,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
+73 -121
View File
@@ -105,9 +105,9 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
LIST_HEAD(sta_poll_list);
int i;
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_lock();
@@ -118,15 +118,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
s8 rssi[4];
u8 bw;
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7915_sta, poll_list);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
struct mt7915_sta, wcid.poll_list);
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -326,10 +326,11 @@ 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->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -841,74 +842,6 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
return MT_TXD_SIZE + sizeof(*txp);
}
static void
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
struct mt7915_sta *msta;
u16 fc, tid;
u32 val;
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
return;
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
if (tid >= 6) /* skip VO queue */
return;
val = le32_to_cpu(txwi[2]);
fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
msta = (struct mt7915_sta *)sta->drv_priv;
if (!test_and_set_bit(tid, &msta->ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
static void
mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, struct list_head *free_list)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt7915_sta *msta;
struct mt76_wcid *wcid;
__le32 *txwi;
u16 wcid_idx;
mt76_connac_txp_skb_unmap(mdev, t);
if (!t->skb)
goto out;
txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
if (sta) {
wcid = (struct mt76_wcid *)sta->drv_priv;
wcid_idx = wcid->idx;
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]);
if (wcid && wcid->sta) {
msta = container_of(wcid, struct mt7915_sta, wcid);
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
}
}
if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7915_tx_check_aggr(sta, txwi);
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
out:
t->skb = NULL;
mt76_put_txwi(mdev, t);
}
static void
mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
{
@@ -951,6 +884,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid = NULL;
LIST_HEAD(free_list);
void *end = data + len;
bool v3, wake = false;
@@ -977,7 +911,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
info = le32_to_cpu(*cur_info);
if (info & MT_TX_FREE_PAIR) {
struct mt7915_sta *msta;
struct mt76_wcid *wcid;
u16 idx;
idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info);
@@ -987,14 +920,33 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7915_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
continue;
}
if (v3 && (info & MT_TX_FREE_MPDU_HEADER))
if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) {
u32 tx_retries = 0, tx_failed = 0;
if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) {
tx_retries =
FIELD_GET(MT_TX_FREE_COUNT_V3, info) - 1;
tx_failed = tx_retries +
!!FIELD_GET(MT_TX_FREE_STAT_V3, info);
} else if (!v3 && (info & MT_TX_FREE_MPDU_HEADER)) {
tx_retries =
FIELD_GET(MT_TX_FREE_COUNT, info) - 1;
tx_failed = tx_retries +
!!FIELD_GET(MT_TX_FREE_STAT, info);
}
wcid->stats.tx_retries += tx_retries;
wcid->stats.tx_failed += tx_failed;
}
if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3))
continue;
for (i = 0; i < 1 + v3; i++) {
@@ -1010,7 +962,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
if (!txwi)
continue;
mt7915_txwi_free(dev, txwi, sta, &free_list);
mt76_connac2_txwi_free(mdev, txwi, sta, &free_list);
}
}
@@ -1042,7 +994,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len)
if (!txwi)
continue;
mt7915_txwi_free(dev, txwi, NULL, &free_list);
mt76_connac2_txwi_free(mdev, txwi, NULL, &free_list);
}
mt7915_mac_tx_free_done(dev, &free_list, wake);
@@ -1081,10 +1033,10 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
if (!wcid->sta)
goto out;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
out:
rcu_read_unlock();
@@ -1357,20 +1309,6 @@ mt7915_update_beacons(struct mt7915_dev *dev)
mt7915_update_vif_beacon, mphy_ext->hw);
}
void mt7915_tx_token_put(struct mt7915_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7915_txwi_free(dev, txwi, NULL, NULL);
dev->mt76.token_count--;
}
spin_unlock_bh(&dev->mt76.token_lock);
idr_destroy(&dev->mt76.token);
}
static int
mt7915_mac_restart(struct mt7915_dev *dev)
{
@@ -1389,8 +1327,12 @@ mt7915_mac_restart(struct mt7915_dev *dev)
if (dev_is_pci(mdev->dev)) {
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
if (dev->hif2)
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
if (dev->hif2) {
if (is_mt7915(mdev))
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
else
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0x0);
}
}
set_bit(MT76_RESET, &dev->mphy.state);
@@ -1415,7 +1357,7 @@ mt7915_mac_restart(struct mt7915_dev *dev)
napi_disable(&dev->mt76.tx_napi);
/* token reinit */
mt7915_tx_token_put(dev);
mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7915_dma_reset(dev, true);
@@ -1440,8 +1382,12 @@ 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_PCIE1_MAC_INT_ENABLE, 0xff);
if (dev->hif2) {
if (is_mt7915(mdev))
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
else
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff);
}
}
/* load firmware */
@@ -1576,7 +1522,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
mtk_wed_device_stop(&dev->mt76.mmio.wed);
if (!is_mt7986(&dev->mt76))
if (!is_mt798x(&dev->mt76))
mt76_wr(dev, MT_INT_WED_MASK_CSR, 0);
}
@@ -1604,13 +1550,19 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7915_dma_reset(dev, false);
mt7915_tx_token_put(dev);
mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
}
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
/* enable DMA Tx/Rx and interrupt */
mt7915_dma_start(dev, false, false);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
@@ -1625,9 +1577,6 @@ void mt7915_mac_reset_work(struct work_struct *work)
tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
@@ -1747,8 +1696,8 @@ void mt7915_reset(struct mt7915_dev *dev)
void mt7915_mac_update_stats(struct mt7915_phy *phy)
{
struct mt76_mib_stats *mib = &phy->mib;
struct mt7915_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
int i, aggr0 = 0, aggr1, cnt;
u8 band = phy->mt76->band_idx;
u32 val;
@@ -2010,7 +1959,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
u32 changed;
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
@@ -2018,7 +1967,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
list_del_init(&msta->rc_list);
changed = msta->changed;
msta->changed = 0;
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
@@ -2031,10 +1980,10 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7915_mcu_add_smps(dev, vif, sta);
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
void mt7915_mac_work(struct work_struct *work)
@@ -2054,6 +2003,9 @@ void mt7915_mac_work(struct work_struct *work)
mt7915_mac_update_stats(phy);
mt7915_mac_severe_check(phy);
if (phy->dev->muru_debug)
mt7915_mcu_muru_debug_get(phy);
}
mutex_unlock(&mphy->dev->mutex);
@@ -9,7 +9,12 @@
#define MT_TX_FREE_VER GENMASK(18, 16)
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
/* 0: success, others: dropped */
#define MT_TX_FREE_MPDU_HEADER BIT(30)
#define MT_TX_FREE_COUNT GENMASK(12, 0)
#define MT_TX_FREE_COUNT_V3 GENMASK(27, 24)
#define MT_TX_FREE_STAT GENMASK(14, 13)
#define MT_TX_FREE_STAT_V3 GENMASK(29, 28)
#define MT_TX_FREE_MPDU_HEADER BIT(15)
#define MT_TX_FREE_MPDU_HEADER_V3 BIT(30)
#define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0)
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
+180 -53
View File
@@ -248,7 +248,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
idx = MT7915_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.poll_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;
@@ -269,6 +269,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
mt7915_init_bitrate_mask(vif);
memset(&mvif->cap, -1, sizeof(mvif->cap));
mt7915_mcu_add_bss_info(phy, vif, true);
mt7915_mcu_add_sta(dev, vif, NULL, true);
@@ -308,10 +309,10 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mutex_unlock(&dev->mt76.mutex);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
@@ -470,7 +471,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
ieee80211_wake_queues(hw);
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
if (changed & (IEEE80211_CONF_CHANGE_POWER |
IEEE80211_CONF_CHANGE_CHANNEL)) {
ret = mt7915_mcu_set_txpower_sku(phy);
if (ret)
return ret;
@@ -599,6 +601,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
{
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = mt7915_hw_dev(hw);
int set_bss_info = -1, set_sta = -1;
mutex_lock(&dev->mt76.mutex);
@@ -607,15 +610,18 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
* and then peer references bss_info_rfch to set bandwidth cap.
*/
if (changed & BSS_CHANGED_BSSID &&
vif->type == NL80211_IFTYPE_STATION) {
bool join = !is_zero_ether_addr(info->bssid);
mt7915_mcu_add_bss_info(phy, vif, join);
mt7915_mcu_add_sta(dev, vif, NULL, join);
}
vif->type == NL80211_IFTYPE_STATION)
set_bss_info = set_sta = !is_zero_ether_addr(info->bssid);
if (changed & BSS_CHANGED_ASSOC)
mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
set_bss_info = vif->cfg.assoc;
if (changed & BSS_CHANGED_BEACON_ENABLED &&
vif->type != NL80211_IFTYPE_AP)
set_bss_info = set_sta = info->enable_beacon;
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);
if (changed & BSS_CHANGED_ERP_CTS_PROT)
mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
@@ -629,11 +635,6 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
}
}
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
mt7915_mcu_add_bss_info(phy, vif, true);
mt7915_mcu_add_sta(dev, vif, NULL, true);
}
/* ensure that enable txcmd_mode after bss_info */
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_set_tx(dev, vif);
@@ -650,6 +651,62 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_FILS_DISCOVERY))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
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);
mutex_unlock(&dev->mt76.mutex);
}
static void
mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_vif_cap *vc = &mvif->cap;
vc->ht_ldpc = vif->bss_conf.ht_ldpc;
vc->vht_ldpc = vif->bss_conf.vht_ldpc;
vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer;
vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee;
vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer;
vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee;
vc->he_ldpc = vif->bss_conf.he_ldpc;
vc->he_su_ebfer = vif->bss_conf.he_su_beamformer;
vc->he_su_ebfee = vif->bss_conf.he_su_beamformee;
vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer;
}
static int
mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = mt7915_hw_dev(hw);
int err;
mutex_lock(&dev->mt76.mutex);
mt7915_vif_check_caps(phy, vif);
err = mt7915_mcu_add_bss_info(phy, vif, true);
if (err)
goto out;
err = mt7915_mcu_add_sta(dev, vif, NULL, true);
out:
mutex_unlock(&dev->mt76.mutex);
return err;
}
static void
mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mt7915_mcu_add_sta(dev, vif, NULL, false);
mutex_unlock(&dev->mt76.mutex);
}
@@ -679,7 +736,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
INIT_LIST_HEAD(&msta->poll_list);
INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -714,12 +771,12 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
mt7915_mac_twt_teardown_flow(dev, msta, i);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&mdev->sta_poll_lock);
}
static void mt7915_tx(struct ieee80211_hw *hw,
@@ -801,16 +858,16 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->ampdu_state);
clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7915_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
set_bit(tid, &msta->ampdu_state);
set_bit(tid, &msta->wcid.ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->ampdu_state);
clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7915_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@@ -842,7 +899,7 @@ mt7915_get_stats(struct ieee80211_hw *hw,
{
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mib_stats *mib = &phy->mib;
struct mt76_mib_stats *mib = &phy->mib;
mutex_lock(&dev->mt76.mutex);
@@ -1019,21 +1076,20 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
}
if (!txrate->legacy && !txrate->flags)
return;
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
if (txrate->legacy || txrate->flags) {
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
}
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
/* offloading flows bypass networking stack, so driver counts and
* reports sta statistics via NL80211_STA_INFO when WED is active.
@@ -1042,14 +1098,10 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
sinfo->tx_packets = msta->wcid.stats.tx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
sinfo->tx_failed = msta->wcid.stats.tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
sinfo->tx_retries = msta->wcid.stats.tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) {
sinfo->tx_packets = msta->wcid.stats.tx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
}
if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) {
sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
@@ -1060,6 +1112,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
}
}
sinfo->tx_failed = msta->wcid.stats.tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
sinfo->tx_retries = msta->wcid.stats.tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
sinfo->ack_signal = (s8)msta->ack_signal;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
@@ -1073,11 +1131,11 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
struct mt7915_dev *dev = msta->vif->phy->dev;
u32 *changed = data;
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
msta->changed |= *changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
@@ -1253,6 +1311,38 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_vec_queue_overflow_drop_cnt",
"rx_ba_cnt",
/* muru mu-mimo and ofdma related stats */
"dl_cck_cnt",
"dl_ofdm_cnt",
"dl_htmix_cnt",
"dl_htgf_cnt",
"dl_vht_su_cnt",
"dl_vht_2mu_cnt",
"dl_vht_3mu_cnt",
"dl_vht_4mu_cnt",
"dl_he_su_cnt",
"dl_he_ext_su_cnt",
"dl_he_2ru_cnt",
"dl_he_2mu_cnt",
"dl_he_3ru_cnt",
"dl_he_3mu_cnt",
"dl_he_4ru_cnt",
"dl_he_4mu_cnt",
"dl_he_5to8ru_cnt",
"dl_he_9to16ru_cnt",
"dl_he_gtr16ru_cnt",
"ul_hetrig_su_cnt",
"ul_hetrig_2ru_cnt",
"ul_hetrig_3ru_cnt",
"ul_hetrig_4ru_cnt",
"ul_hetrig_5to8ru_cnt",
"ul_hetrig_9to16ru_cnt",
"ul_hetrig_gtr16ru_cnt",
"ul_hetrig_2mu_cnt",
"ul_hetrig_3mu_cnt",
"ul_hetrig_4mu_cnt",
/* per vif counters */
"v_tx_mode_cck",
"v_tx_mode_ofdm",
@@ -1279,6 +1369,10 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
"v_tx_mcs_9",
"v_tx_mcs_10",
"v_tx_mcs_11",
"v_tx_nss_1",
"v_tx_nss_2",
"v_tx_nss_3",
"v_tx_nss_4",
};
#define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)
@@ -1326,11 +1420,11 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt76_mib_stats *mib = &phy->mib;
struct mt76_ethtool_worker_info wi = {
.data = data,
.idx = mvif->mt76.idx,
};
struct mib_stats *mib = &phy->mib;
/* See mt7915_ampdu_stat_read_phy, etc */
int i, ei = 0, stats_size;
@@ -1403,6 +1497,37 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
data[ei++] = mib->rx_vec_queue_overflow_drop_cnt;
data[ei++] = mib->rx_ba_cnt;
data[ei++] = mib->dl_cck_cnt;
data[ei++] = mib->dl_ofdm_cnt;
data[ei++] = mib->dl_htmix_cnt;
data[ei++] = mib->dl_htgf_cnt;
data[ei++] = mib->dl_vht_su_cnt;
data[ei++] = mib->dl_vht_2mu_cnt;
data[ei++] = mib->dl_vht_3mu_cnt;
data[ei++] = mib->dl_vht_4mu_cnt;
data[ei++] = mib->dl_he_su_cnt;
data[ei++] = mib->dl_he_ext_su_cnt;
data[ei++] = mib->dl_he_2ru_cnt;
data[ei++] = mib->dl_he_2mu_cnt;
data[ei++] = mib->dl_he_3ru_cnt;
data[ei++] = mib->dl_he_3mu_cnt;
data[ei++] = mib->dl_he_4ru_cnt;
data[ei++] = mib->dl_he_4mu_cnt;
data[ei++] = mib->dl_he_5to8ru_cnt;
data[ei++] = mib->dl_he_9to16ru_cnt;
data[ei++] = mib->dl_he_gtr16ru_cnt;
data[ei++] = mib->ul_hetrig_su_cnt;
data[ei++] = mib->ul_hetrig_2ru_cnt;
data[ei++] = mib->ul_hetrig_3ru_cnt;
data[ei++] = mib->ul_hetrig_4ru_cnt;
data[ei++] = mib->ul_hetrig_5to8ru_cnt;
data[ei++] = mib->ul_hetrig_9to16ru_cnt;
data[ei++] = mib->ul_hetrig_gtr16ru_cnt;
data[ei++] = mib->ul_hetrig_2mu_cnt;
data[ei++] = mib->ul_hetrig_3mu_cnt;
data[ei++] = mib->ul_hetrig_4mu_cnt;
/* Add values for all stations owned by this vif */
wi.initial_stat_idx = ei;
ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi);
@@ -1526,6 +1651,8 @@ const struct ieee80211_ops mt7915_ops = {
.conf_tx = mt7915_conf_tx,
.configure_filter = mt7915_configure_filter,
.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_pre_rcu_remove = mt76_sta_pre_rcu_remove,
+126 -25
View File
@@ -13,6 +13,9 @@
case 0x7915: \
_fw = MT7915_##name; \
break; \
case 0x7981: \
_fw = MT7981_##name; \
break; \
case 0x7986: \
_fw = MT7986_##name##__VA_ARGS__; \
break; \
@@ -164,7 +167,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (seq != rxd->seq)
if (seq != rxd->seq &&
!(rxd->eid == MCU_CMD_EXT_CID &&
rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
return -EAGAIN;
if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
@@ -274,7 +279,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
r = (struct mt7915_mcu_rdd_report *)skb->data;
if (r->band_idx > MT_BAND1)
if (r->band_idx > MT_RX_SEL2)
return;
if ((r->band_idx && !dev->phy.mt76->band_idx) &&
@@ -395,12 +400,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
!rxd->seq)
if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
!rxd->seq) &&
!(rxd->eid == MCU_CMD_EXT_CID &&
rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
mt7915_mcu_rx_unsolicited_event(dev, skb);
else
mt76_mcu_rx_event(&dev->mt76, skb);
@@ -706,6 +713,7 @@ static void
mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct ieee80211_he_mcs_nss_supp mcs_map;
struct sta_rec_he *he;
@@ -739,7 +747,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
if (vif->bss_conf.he_ldpc &&
if (mvif->cap.he_ldpc &&
(elem->phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
cap |= STA_REC_HE_CAP_LDPC;
@@ -848,6 +856,7 @@ static void
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
@@ -860,9 +869,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
muru = (struct sta_rec_muru *)tlv;
muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer ||
vif->bss_conf.vht_mu_beamformer ||
vif->bss_conf.vht_mu_beamformee;
muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
mvif->cap.vht_mu_ebfer ||
mvif->cap.vht_mu_ebfee;
if (!is_mt7915(&dev->mt76))
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
@@ -995,8 +1004,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
wtbl_hdr, vif->bss_conf.ht_ldpc,
vif->bss_conf.vht_ldpc);
wtbl_hdr, mvif->cap.ht_ldpc,
mvif->cap.vht_ldpc);
return 0;
}
@@ -1005,6 +1014,7 @@ static inline bool
mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -1018,10 +1028,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
if (bfee)
return vif->bss_conf.he_su_beamformee &&
return mvif->cap.he_su_ebfee &&
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
else
return vif->bss_conf.he_su_beamformer &&
return mvif->cap.he_su_ebfer &&
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
}
@@ -1029,10 +1039,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
u32 cap = sta->deflink.vht_cap.cap;
if (bfee)
return vif->bss_conf.vht_su_beamformee &&
return mvif->cap.vht_su_ebfee &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
else
return vif->bss_conf.vht_su_beamformer &&
return mvif->cap.vht_su_ebfer &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
}
@@ -1527,7 +1537,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_TX_STBC;
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
cap |= STA_CAP_RX_STBC;
if (vif->bss_conf.ht_ldpc &&
if (mvif->cap.ht_ldpc &&
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC;
@@ -1553,7 +1563,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_VHT_TX_STBC;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
cap |= STA_CAP_VHT_RX_STBC;
if (vif->bss_conf.vht_ldpc &&
if (mvif->cap.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC;
@@ -2112,12 +2122,11 @@ int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled)
sizeof(data), false);
}
int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms)
int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct sk_buff *skb;
struct mt7915_mcu_muru_stats *mu_stats =
(struct mt7915_mcu_muru_stats *)ms;
struct mt7915_mcu_muru_stats *mu_stats;
int ret;
struct {
@@ -2133,7 +2142,43 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms)
if (ret)
return ret;
memcpy(mu_stats, skb->data, sizeof(struct mt7915_mcu_muru_stats));
mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data);
/* accumulate stats, these are clear-on-read */
#define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s)
#define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s)
__dl_u32(cck_cnt);
__dl_u32(ofdm_cnt);
__dl_u32(htmix_cnt);
__dl_u32(htgf_cnt);
__dl_u32(vht_su_cnt);
__dl_u32(vht_2mu_cnt);
__dl_u32(vht_3mu_cnt);
__dl_u32(vht_4mu_cnt);
__dl_u32(he_su_cnt);
__dl_u32(he_2ru_cnt);
__dl_u32(he_2mu_cnt);
__dl_u32(he_3ru_cnt);
__dl_u32(he_3mu_cnt);
__dl_u32(he_4ru_cnt);
__dl_u32(he_4mu_cnt);
__dl_u32(he_5to8ru_cnt);
__dl_u32(he_9to16ru_cnt);
__dl_u32(he_gtr16ru_cnt);
__ul_u32(hetrig_su_cnt);
__ul_u32(hetrig_2ru_cnt);
__ul_u32(hetrig_3ru_cnt);
__ul_u32(hetrig_4ru_cnt);
__ul_u32(hetrig_5to8ru_cnt);
__ul_u32(hetrig_9to16ru_cnt);
__ul_u32(hetrig_gtr16ru_cnt);
__ul_u32(hetrig_2mu_cnt);
__ul_u32(hetrig_3mu_cnt);
__ul_u32(hetrig_4mu_cnt);
#undef __dl_u32
#undef __ul_u32
dev_kfree_skb(skb);
return 0;
@@ -2993,7 +3038,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
}
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
req, sizeof(req), true, &skb);
req, len * sizeof(req[0]), true, &skb);
if (ret)
return ret;
@@ -3733,6 +3778,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
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 = {
.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];
/* tx_bytes is deprecated since WA byte counter uses u32,
* which easily leads to overflow.
*/
__le32 tx_bytes;
__le32 tx_packets;
} *res;
struct mt76_wcid *wcid;
struct sk_buff *skb;
int ret;
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
&req, sizeof(req), true, &skb);
if (ret)
return ret;
if (!is_mt7915(&dev->mt76))
skb_pull(skb, 4);
res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
ret = -EINVAL;
goto out;
}
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (wcid)
wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
else
ret = -EINVAL;
rcu_read_unlock();
out:
dev_kfree_skb(skb);
return ret;
}
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
{
struct {
@@ -417,7 +417,7 @@ static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr)
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
u32 l1_remap;
if (is_mt7986(&dev->mt76))
if (is_mt798x(&dev->mt76))
return MT_CONN_INFRA_OFFSET(addr);
l1_remap = is_mt7915(&dev->mt76) ?
@@ -447,7 +447,7 @@ static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr)
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
} else {
u32 ofs = is_mt7986(&dev->mt76) ? 0x400000 : 0;
u32 ofs = is_mt798x(&dev->mt76) ? 0x400000 : 0;
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_MT7916, addr);
base = FIELD_GET(MT_HIF_REMAP_L2_BASE_MT7916, addr);
@@ -545,8 +545,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
struct mt7915_phy *phy;
int ret;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
@@ -554,43 +552,19 @@ static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed)
dev->mt76.token_size = wed->wlan.token_start;
spin_unlock_bh(&dev->mt76.token_lock);
ret = wait_event_timeout(dev->mt76.tx_wait,
!dev->mt76.wed_token_count, HZ);
if (!ret)
return -EAGAIN;
phy = &dev->phy;
mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H);
phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
if (phy)
mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx),
MT_AGG_ACR_PPDU_TXS2H);
return 0;
return !wait_event_timeout(dev->mt76.tx_wait,
!dev->mt76.wed_token_count, HZ);
}
static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
struct mt7915_phy *phy;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
spin_lock_bh(&dev->mt76.token_lock);
dev->mt76.token_size = MT7915_TOKEN_SIZE;
spin_unlock_bh(&dev->mt76.token_lock);
/* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
*/
phy = &dev->phy;
mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H);
phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
if (phy)
mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx),
MT_AGG_ACR_PPDU_TXS2H);
}
static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
@@ -785,7 +759,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
wed->wlan.nbuf = MT7915_HW_TOKEN_SIZE;
wed->wlan.tx_tbit[0] = is_mt7915(&dev->mt76) ? 4 : 30;
wed->wlan.tx_tbit[1] = is_mt7915(&dev->mt76) ? 5 : 31;
wed->wlan.txfree_tbit = is_mt7986(&dev->mt76) ? 2 : 1;
wed->wlan.txfree_tbit = is_mt798x(&dev->mt76) ? 2 : 1;
wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
wed->wlan.wcid_512 = !is_mt7915(&dev->mt76);
@@ -795,7 +769,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
if (is_mt7915(&dev->mt76)) {
wed->wlan.rx_tbit[0] = 16;
wed->wlan.rx_tbit[1] = 17;
} else if (is_mt7986(&dev->mt76)) {
} else if (is_mt798x(&dev->mt76)) {
wed->wlan.rx_tbit[0] = 22;
wed->wlan.rx_tbit[1] = 23;
} else {
@@ -853,6 +827,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev,
dev->reg.map = mt7916_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7916_reg_map);
break;
case 0x7981:
case 0x7986:
dev->reg.reg_rev = mt7986_reg;
dev->reg.offs_rev = mt7916_offs;
@@ -1062,8 +1037,8 @@ static int __init mt7915_init(void)
if (ret)
goto error_pci;
if (IS_ENABLED(CONFIG_MT7986_WMAC)) {
ret = platform_driver_register(&mt7986_wmac_driver);
if (IS_ENABLED(CONFIG_MT798X_WMAC)) {
ret = platform_driver_register(&mt798x_wmac_driver);
if (ret)
goto error_wmac;
}
@@ -1080,8 +1055,8 @@ error_pci:
static void __exit mt7915_exit(void)
{
if (IS_ENABLED(CONFIG_MT7986_WMAC))
platform_driver_unregister(&mt7986_wmac_driver);
if (IS_ENABLED(CONFIG_MT798X_WMAC))
platform_driver_unregister(&mt798x_wmac_driver);
pci_unregister_driver(&mt7915_pci_driver);
pci_unregister_driver(&mt7915_hif_driver);
@@ -34,6 +34,10 @@
#define MT7916_FIRMWARE_WM "mediatek/mt7916_wm.bin"
#define MT7916_ROM_PATCH "mediatek/mt7916_rom_patch.bin"
#define MT7981_FIRMWARE_WA "mediatek/mt7981_wa.bin"
#define MT7981_FIRMWARE_WM "mediatek/mt7981_wm.bin"
#define MT7981_ROM_PATCH "mediatek/mt7981_rom_patch.bin"
#define MT7986_FIRMWARE_WA "mediatek/mt7986_wa.bin"
#define MT7986_FIRMWARE_WM "mediatek/mt7986_wm.bin"
#define MT7986_FIRMWARE_WM_MT7975 "mediatek/mt7986_wm_mt7975.bin"
@@ -43,6 +47,9 @@
#define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin"
#define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin"
#define MT7916_EEPROM_DEFAULT "mediatek/mt7916_eeprom.bin"
#define MT7981_EEPROM_MT7976_DEFAULT_DBDC "mediatek/mt7981_eeprom_mt7976_dbdc.bin"
#define MT7986_EEPROM_MT7975_DEFAULT "mediatek/mt7986_eeprom_mt7975.bin"
#define MT7986_EEPROM_MT7975_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7975_dual.bin"
#define MT7986_EEPROM_MT7976_DEFAULT "mediatek/mt7986_eeprom_mt7976.bin"
@@ -129,7 +136,6 @@ struct mt7915_sta {
struct mt7915_vif *vif;
struct list_head poll_list;
struct list_head rc_list;
u32 airtime_ac[8];
@@ -138,7 +144,6 @@ struct mt7915_sta {
unsigned long changed;
unsigned long jiffies;
unsigned long ampdu_state;
struct mt76_connac_sta_key_conf bip;
struct {
@@ -147,9 +152,23 @@ struct mt7915_sta {
} twt;
};
struct mt7915_vif_cap {
bool ht_ldpc:1;
bool vht_ldpc:1;
bool he_ldpc:1;
bool vht_su_ebfer:1;
bool vht_su_ebfee:1;
bool vht_mu_ebfer:1;
bool vht_mu_ebfee:1;
bool he_su_ebfer:1;
bool he_su_ebfee:1;
bool he_mu_ebfer:1;
};
struct mt7915_vif {
struct mt76_vif mt76; /* must be first */
struct mt7915_vif_cap cap;
struct mt7915_sta sta;
struct mt7915_phy *phy;
@@ -157,67 +176,6 @@ struct mt7915_vif {
struct cfg80211_bitrate_mask bitrate_mask;
};
/* per-phy stats. */
struct mib_stats {
u32 ack_fail_cnt;
u32 fcs_err_cnt;
u32 rts_cnt;
u32 rts_retries_cnt;
u32 ba_miss_cnt;
u32 tx_bf_cnt;
u32 tx_mu_mpdu_cnt;
u32 tx_mu_acked_mpdu_cnt;
u32 tx_su_acked_mpdu_cnt;
u32 tx_bf_ibf_ppdu_cnt;
u32 tx_bf_ebf_ppdu_cnt;
u32 tx_bf_rx_fb_all_cnt;
u32 tx_bf_rx_fb_he_cnt;
u32 tx_bf_rx_fb_vht_cnt;
u32 tx_bf_rx_fb_ht_cnt;
u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */
u32 tx_bf_rx_fb_nc_cnt;
u32 tx_bf_rx_fb_nr_cnt;
u32 tx_bf_fb_cpl_cnt;
u32 tx_bf_fb_trig_cnt;
u32 tx_ampdu_cnt;
u32 tx_stop_q_empty_cnt;
u32 tx_mpdu_attempts_cnt;
u32 tx_mpdu_success_cnt;
u32 tx_pkt_ebf_cnt;
u32 tx_pkt_ibf_cnt;
u32 tx_rwp_fail_cnt;
u32 tx_rwp_need_cnt;
/* rx stats */
u32 rx_fifo_full_cnt;
u32 channel_idle_cnt;
u32 primary_cca_busy_time;
u32 secondary_cca_busy_time;
u32 primary_energy_detect_time;
u32 cck_mdrdy_time;
u32 ofdm_mdrdy_time;
u32 green_mdrdy_time;
u32 rx_vector_mismatch_cnt;
u32 rx_delimiter_fail_cnt;
u32 rx_mrdy_cnt;
u32 rx_len_mismatch_cnt;
u32 rx_mpdu_cnt;
u32 rx_ampdu_cnt;
u32 rx_ampdu_bytes_cnt;
u32 rx_ampdu_valid_subframe_cnt;
u32 rx_ampdu_valid_subframe_bytes_cnt;
u32 rx_pfdrop_cnt;
u32 rx_vec_queue_overflow_drop_cnt;
u32 rx_ba_cnt;
u32 tx_amsdu[8];
u32 tx_amsdu_cnt;
};
/* crash-dump */
struct mt7915_crash_data {
guid_t guid;
@@ -263,7 +221,7 @@ struct mt7915_phy {
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
struct mt76_mib_stats mib;
struct mt76_channel_state state_ts;
#ifdef CONFIG_NL80211_TESTMODE
@@ -328,9 +286,7 @@ struct mt7915_dev {
#endif
struct list_head sta_rc_list;
struct list_head sta_poll_list;
struct list_head twt_list;
spinlock_t sta_poll_lock;
u32 hw_pattern;
@@ -420,8 +376,7 @@ mt7915_ext_phy(struct mt7915_dev *dev)
static inline u32 mt7915_check_adie(struct mt7915_dev *dev, bool sku)
{
u32 mask = sku ? MT_CONNINFRA_SKU_MASK : MT_ADIE_TYPE_MASK;
if (!is_mt7986(&dev->mt76))
if (!is_mt798x(&dev->mt76))
return 0;
return mt76_rr(dev, MT_CONNINFRA_SKU_DEC_ADDR) & mask;
@@ -431,9 +386,9 @@ extern const struct ieee80211_ops mt7915_ops;
extern const struct mt76_testmode_ops mt7915_testmode_ops;
extern struct pci_driver mt7915_pci_driver;
extern struct pci_driver mt7915_hif_driver;
extern struct platform_driver mt7986_wmac_driver;
extern struct platform_driver mt798x_wmac_driver;
#ifdef CONFIG_MT7986_WMAC
#ifdef CONFIG_MT798X_WMAC
int mt7986_wmac_enable(struct mt7915_dev *dev);
void mt7986_wmac_disable(struct mt7915_dev *dev);
#else
@@ -466,6 +421,7 @@ 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);
int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset);
int mt7915_txbf_init(struct mt7915_dev *dev);
void mt7915_init_txpower(struct mt7915_dev *dev,
struct ieee80211_supported_band *sband);
@@ -539,6 +495,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
struct cfg80211_chan_def *chandef);
int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid);
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
@@ -612,7 +569,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7915_tx_token_put(struct mt7915_dev *dev);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
@@ -623,7 +579,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
void mt7915_update_channel(struct mt76_phy *mphy);
int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enable);
int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms);
int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy);
int mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev *dev);
int mt7915_init_debugfs(struct mt7915_phy *phy);
void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len);
@@ -145,6 +145,9 @@ enum offs_rev {
#define MT_PLE_BASE 0x820c0000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_PLE_HOST_RPT0 MT_PLE(0x030)
#define MT_PLE_HOST_RPT0_TX_LATENCY BIT(3)
#define MT_FL_Q_EMPTY MT_PLE(__OFFS(PLE_FL_Q_EMPTY))
#define MT_FL_Q0_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL))
#define MT_FL_Q2_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0x8)
@@ -871,7 +874,12 @@ enum offs_rev {
#define MT_AFE_RG_WBG_EN_WPLL_UP_MASK BIT(20)
#define MT_AFE_RG_WBG_EN_PLL_UP_MASK (MT_AFE_RG_WBG_EN_BPLL_UP_MASK | \
MT_AFE_RG_WBG_EN_WPLL_UP_MASK)
#define MT_AFE_RG_WBG_EN_TXCAL_MASK GENMASK(21, 17)
#define MT_AFE_RG_WBG_EN_TXCAL_WF4 BIT(29)
#define MT_AFE_RG_WBG_EN_TXCAL_BT BIT(21)
#define MT_AFE_RG_WBG_EN_TXCAL_WF3 BIT(20)
#define MT_AFE_RG_WBG_EN_TXCAL_WF2 BIT(19)
#define MT_AFE_RG_WBG_EN_TXCAL_WF1 BIT(18)
#define MT_AFE_RG_WBG_EN_TXCAL_WF0 BIT(17)
#define MT_ADIE_SLP_CTRL_BASE(_band) (0x18005000 + ((_band) << 19))
#define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs))
@@ -1096,6 +1104,12 @@ enum offs_rev {
#define MT_TOP_MCU_EMI_BASE MT_TOP(0x1c4)
#define MT_TOP_MCU_EMI_BASE_MASK GENMASK(19, 0)
#define MT_TOP_WF_AP_PERI_BASE MT_TOP(0x1c8)
#define MT_TOP_WF_AP_PERI_BASE_MASK GENMASK(19, 0)
#define MT_TOP_EFUSE_BASE MT_TOP(0x1cc)
#define MT_TOP_EFUSE_BASE_MASK GENMASK(19, 0)
#define MT_TOP_CONN_INFRA_WAKEUP MT_TOP(0x1a0)
#define MT_TOP_CONN_INFRA_WAKEUP_MASK BIT(0)
+114 -48
View File
@@ -15,6 +15,9 @@
#include "mt7915.h"
#define MT7981_CON_INFRA_VERSION 0x02090000
#define MT7986_CON_INFRA_VERSION 0x02070000
/* INFRACFG */
#define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0
#define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4
@@ -166,10 +169,14 @@ static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
return val;
}
static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev)
static u8 mt798x_wmac_check_adie_type(struct mt7915_dev *dev)
{
u32 val;
/* Only DBDC A-die is used with MT7981 */
if (is_mt7981(&dev->mt76))
return ADIE_DBDC;
val = readl(dev->sku + MT_TOP_POS_SKU);
return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val);
@@ -194,7 +201,7 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
int ret;
u8 type;
type = mt7986_wmac_check_adie_type(dev);
type = mt798x_wmac_check_adie_type(dev);
pinctrl = devm_pinctrl_get(dev->mt76.dev);
if (IS_ERR(pinctrl))
return PTR_ERR(pinctrl);
@@ -256,16 +263,26 @@ static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable)
return 0;
}
static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev)
static int mt798x_wmac_coninfra_check(struct mt7915_dev *dev)
{
u32 cur;
u32 con_infra_version;
return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000),
if (is_mt7981(&dev->mt76)) {
con_infra_version = MT7981_CON_INFRA_VERSION;
} else if (is_mt7986(&dev->mt76)) {
con_infra_version = MT7986_CON_INFRA_VERSION;
} else {
WARN_ON(1);
return -EINVAL;
}
return read_poll_timeout(mt76_rr, cur, (cur == con_infra_version),
USEC_PER_MSEC, 50 * USEC_PER_MSEC,
false, dev, MT_CONN_INFRA_BASE);
}
static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev)
static int mt798x_wmac_coninfra_setup(struct mt7915_dev *dev)
{
struct device *pdev = dev->mt76.dev;
struct reserved_mem *rmem;
@@ -283,15 +300,25 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev)
val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK;
/* Set conninfra subsys PLL check */
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
if (is_mt7986(&dev->mt76)) {
/* Set conninfra subsys PLL check */
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
}
mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE,
MT_TOP_MCU_EMI_BASE_MASK, val);
if (is_mt7981(&dev->mt76)) {
mt76_rmw_field(dev, MT_TOP_WF_AP_PERI_BASE,
MT_TOP_WF_AP_PERI_BASE_MASK, 0x300d0000 >> 16);
mt76_rmw_field(dev, MT_TOP_EFUSE_BASE,
MT_TOP_EFUSE_BASE_MASK, 0x11f20000 >> 16);
}
mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base);
mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size);
@@ -304,15 +331,18 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev)
return 0;
}
static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
static int mt798x_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
{
int ret;
u32 adie_main, adie_ext;
u32 adie_main = 0, adie_ext = 0;
mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1);
mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1);
if (is_mt7986(&dev->mt76)) {
mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1);
}
mt76_wmac_spi_lock(dev);
@@ -320,9 +350,11 @@ static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
if (ret)
goto out;
ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext);
if (ret)
goto out;
if (is_mt7986(&dev->mt76)) {
ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext);
if (ret)
goto out;
}
*adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) |
(MT_ADIE_CHIP_ID_MASK & adie_ext);
@@ -469,7 +501,7 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
return ret;
}
static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
{
u32 id, version, rg_xo_01, rg_xo_03;
int ret;
@@ -488,7 +520,14 @@ static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
rg_xo_01 = 0x1d59080f;
rg_xo_03 = 0x34c00fe0;
} else {
rg_xo_01 = 0x1959f80f;
if (is_mt7981(&dev->mt76)) {
rg_xo_01 = 0x1959c80f;
} else if (is_mt7986(&dev->mt76)) {
rg_xo_01 = 0x1959f80f;
} else {
WARN_ON(1);
return -EINVAL;
}
rg_xo_03 = 0x34d00fe0;
}
@@ -610,7 +649,15 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie)
return ret;
/* turn on SX0 LTBUF */
ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002);
if (is_mt7981(&dev->mt76)) {
ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000007);
} else if (is_mt7986(&dev->mt76)) {
ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002);
} else {
WARN_ON(1);
return -EINVAL;
}
if (ret)
return ret;
@@ -657,7 +704,10 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie)
return ret;
/* set CKB driving and filter */
return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072);
if (is_mt7986(&dev->mt76))
return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072);
return ret;
}
static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
@@ -685,7 +735,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
ret = mt7986_wmac_adie_patch_7975(dev, adie);
} else if (is_7976(dev, adie, adie_type)) {
if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) {
if (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC) {
ret = mt76_wmac_spi_write(dev, adie,
MT_ADIE_WRI_CK_SEL, 0x1c);
if (ret)
@@ -700,7 +750,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
if (ret)
goto out;
ret = mt7986_wmac_adie_patch_7976(dev, adie);
ret = mt798x_wmac_adie_patch_7976(dev, adie);
}
out:
mt76_wmac_spi_unlock(dev);
@@ -713,6 +763,7 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type)
{
int ret;
u8 idx;
u32 txcal;
mt76_wmac_spi_lock(dev);
if (is_7975(dev, adie, adie_type))
@@ -743,12 +794,18 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type)
MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1);
usleep_range(60, 100);
mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f);
txcal = (MT_AFE_RG_WBG_EN_TXCAL_BT |
MT_AFE_RG_WBG_EN_TXCAL_WF0 |
MT_AFE_RG_WBG_EN_TXCAL_WF1 |
MT_AFE_RG_WBG_EN_TXCAL_WF2 |
MT_AFE_RG_WBG_EN_TXCAL_WF3);
if (is_mt7981(&dev->mt76))
txcal |= MT_AFE_RG_WBG_EN_TXCAL_WF4;
mt76_set(dev, MT_AFE_DIG_EN_01(idx), txcal);
usleep_range(800, 1000);
mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0);
mt76_clear(dev, MT_AFE_DIG_EN_01(idx), txcal);
mt76_rmw(dev, MT_AFE_DIG_EN_03(idx),
MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0);
@@ -805,7 +862,7 @@ static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev)
mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
return mt7986_wmac_coninfra_check(dev);
return mt798x_wmac_coninfra_check(dev);
}
static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type)
@@ -875,14 +932,15 @@ static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable)
if (!enable)
return 0;
return mt7986_wmac_coninfra_check(dev);
return mt798x_wmac_coninfra_check(dev);
}
static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable)
{
u32 cur;
mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0);
if (is_mt7986(&dev->mt76))
mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0);
mt76_rmw_field(dev, MT7986_TOP_WM_RESET,
MT7986_TOP_WM_RESET_MASK, enable);
@@ -1005,7 +1063,7 @@ mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type)
if (ret)
return ret;
if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC))
if (!adie && (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC))
ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type);
return ret;
@@ -1060,15 +1118,15 @@ int mt7986_wmac_enable(struct mt7915_dev *dev)
if (ret)
return ret;
ret = mt7986_wmac_coninfra_check(dev);
ret = mt798x_wmac_coninfra_check(dev);
if (ret)
return ret;
ret = mt7986_wmac_coninfra_setup(dev);
ret = mt798x_wmac_coninfra_setup(dev);
if (ret)
return ret;
ret = mt7986_wmac_sku_setup(dev, &adie_type);
ret = mt798x_wmac_sku_setup(dev, &adie_type);
if (ret)
return ret;
@@ -1076,9 +1134,12 @@ int mt7986_wmac_enable(struct mt7915_dev *dev)
if (ret)
return ret;
ret = mt7986_wmac_adie_setup(dev, 1, adie_type);
if (ret)
return ret;
/* mt7981 doesn't support a second a-die */
if (is_mt7986(&dev->mt76)) {
ret = mt7986_wmac_adie_setup(dev, 1, adie_type);
if (ret)
return ret;
}
ret = mt7986_wmac_subsys_powerup(dev, adie_type);
if (ret)
@@ -1131,7 +1192,7 @@ void mt7986_wmac_disable(struct mt7915_dev *dev)
mt7986_wmac_consys_reset(dev, false);
}
static int mt7986_wmac_init(struct mt7915_dev *dev)
static int mt798x_wmac_init(struct mt7915_dev *dev)
{
struct device *pdev = dev->mt76.dev;
struct platform_device *pfdev = to_platform_device(pdev);
@@ -1164,7 +1225,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev)
return 0;
}
static int mt7986_wmac_probe(struct platform_device *pdev)
static int mt798x_wmac_probe(struct platform_device *pdev)
{
void __iomem *mem_base;
struct mt7915_dev *dev;
@@ -1202,7 +1263,7 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
if (ret)
goto free_device;
ret = mt7986_wmac_init(dev);
ret = mt798x_wmac_init(dev);
if (ret)
goto free_irq;
@@ -1224,7 +1285,7 @@ free_device:
return ret;
}
static int mt7986_wmac_remove(struct platform_device *pdev)
static int mt798x_wmac_remove(struct platform_device *pdev)
{
struct mt7915_dev *dev = platform_get_drvdata(pdev);
@@ -1233,20 +1294,21 @@ static int mt7986_wmac_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id mt7986_wmac_of_match[] = {
static const struct of_device_id mt798x_wmac_of_match[] = {
{ .compatible = "mediatek,mt7981-wmac", .data = (u32 *)0x7981 },
{ .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 },
{},
};
MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match);
MODULE_DEVICE_TABLE(of, mt798x_wmac_of_match);
struct platform_driver mt7986_wmac_driver = {
struct platform_driver mt798x_wmac_driver = {
.driver = {
.name = "mt7986-wmac",
.of_match_table = mt7986_wmac_of_match,
.name = "mt798x-wmac",
.of_match_table = mt798x_wmac_of_match,
},
.probe = mt7986_wmac_probe,
.remove = mt7986_wmac_remove,
.probe = mt798x_wmac_probe,
.remove = mt798x_wmac_remove,
};
MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
@@ -1254,3 +1316,7 @@ MODULE_FIRMWARE(MT7986_FIRMWARE_WM);
MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975);
MODULE_FIRMWARE(MT7986_ROM_PATCH);
MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975);
MODULE_FIRMWARE(MT7981_FIRMWARE_WA);
MODULE_FIRMWARE(MT7981_FIRMWARE_WM);
MODULE_FIRMWARE(MT7981_ROM_PATCH);
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: ISC
config MT7921_COMMON
tristate
select MT76_CONNAC_LIB
select MT792x_LIB
select WANT_DEV_COREDUMP
config MT7921E
@@ -27,7 +27,7 @@ config MT7921S
config MT7921U
tristate "MediaTek MT7921U (USB) support"
select MT76_USB
select MT792x_USB
select MT7921_COMMON
depends on MAC80211
depends on USB
@@ -5,11 +5,8 @@ obj-$(CONFIG_MT7921E) += mt7921e.o
obj-$(CONFIG_MT7921S) += mt7921s.o
obj-$(CONFIG_MT7921U) += mt7921u.o
CFLAGS_trace.o := -I$(src)
mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o
mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7921-common-$(CONFIG_ACPI) += acpi_sar.o
mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o
mt7921e-y := pci.o pci_mac.o pci_mcu.o
mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o
mt7921u-y := usb.o usb_mac.o
mt7921u-y := usb.o
@@ -1,105 +0,0 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2022 MediaTek Inc. */
#ifndef __MT7921_ACPI_SAR_H
#define __MT7921_ACPI_SAR_H
#define MT7921_ASAR_MIN_DYN 1
#define MT7921_ASAR_MAX_DYN 8
#define MT7921_ASAR_MIN_GEO 3
#define MT7921_ASAR_MAX_GEO 8
#define MT7921_ASAR_MIN_FG 8
#define MT7921_ACPI_MTCL "MTCL"
#define MT7921_ACPI_MTDS "MTDS"
#define MT7921_ACPI_MTGS "MTGS"
#define MT7921_ACPI_MTFG "MTFG"
struct mt7921_asar_dyn_limit {
u8 idx;
u8 frp[5];
} __packed;
struct mt7921_asar_dyn {
u8 names[4];
u8 enable;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl);
} __packed;
struct mt7921_asar_dyn_limit_v2 {
u8 idx;
u8 frp[11];
} __packed;
struct mt7921_asar_dyn_v2 {
u8 names[4];
u8 enable;
u8 rsvd;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl);
} __packed;
struct mt7921_asar_geo_band {
u8 pwr;
u8 offset;
} __packed;
struct mt7921_asar_geo_limit {
u8 idx;
/* 0:2G, 1:5G */
struct mt7921_asar_geo_band band[2];
} __packed;
struct mt7921_asar_geo {
u8 names[4];
u8 version;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl);
} __packed;
struct mt7921_asar_geo_limit_v2 {
u8 idx;
/* 0:2G, 1:5G, 2:6G */
struct mt7921_asar_geo_band band[3];
} __packed;
struct mt7921_asar_geo_v2 {
u8 names[4];
u8 version;
u8 rsvd;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl);
} __packed;
struct mt7921_asar_cl {
u8 names[4];
u8 version;
u8 mode_6g;
u8 cl6g[6];
} __packed;
struct mt7921_asar_fg {
u8 names[4];
u8 version;
u8 rsvd;
u8 nr_flag;
u8 rsvd1;
u8 flag[];
} __packed;
struct mt7921_acpi_sar {
u8 ver;
union {
struct mt7921_asar_dyn *dyn;
struct mt7921_asar_dyn_v2 *dyn_v2;
};
union {
struct mt7921_asar_geo *geo;
struct mt7921_asar_geo_v2 *geo_v2;
};
struct mt7921_asar_cl *countrylist;
struct mt7921_asar_fg *fg;
};
#endif
@@ -6,11 +6,11 @@
static int
mt7921_reg_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
mt76_wr(dev, dev->mt76.debugfs_reg, val);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
return 0;
}
@@ -18,11 +18,11 @@ mt7921_reg_set(void *data, u64 val)
static int
mt7921_reg_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
*val = mt76_rr(dev, dev->mt76.debugfs_reg);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
return 0;
}
@@ -32,14 +32,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set,
static int
mt7921_fw_debug_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
dev->fw_debug = (u8)val;
mt7921_mcu_fw_log_2_host(dev, dev->fw_debug);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
return 0;
}
@@ -47,7 +47,7 @@ mt7921_fw_debug_set(void *data, u64 val)
static int
mt7921_fw_debug_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
*val = dev->fw_debug;
@@ -57,128 +57,7 @@ mt7921_fw_debug_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get,
mt7921_fw_debug_set, "%lld\n");
static void
mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
struct seq_file *file)
{
struct mt7921_dev *dev = file->private;
int bound[15], range[4], i;
if (!phy)
return;
mt7921_mac_update_mib_stats(phy);
/* Tx ampdu stat */
for (i = 0; i < ARRAY_SIZE(range); i++)
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 % 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_puts(file, "\nCount: ");
for (i = 0; i < ARRAY_SIZE(bound); i++)
seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);
seq_puts(file, "\n");
seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
}
static int
mt7921_tx_stats_show(struct seq_file *file, void *data)
{
struct mt7921_dev *dev = file->private;
struct mt7921_phy *phy = &dev->phy;
struct mib_stats *mib = &phy->mib;
int i;
mt7921_mutex_acquire(dev);
mt7921_ampdu_stat_read_phy(phy, file);
seq_puts(file, "Tx MSDU stat:\n");
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
i + 1, mib->tx_amsdu[i]);
if (mib->tx_amsdu_cnt)
seq_printf(file, "(%3d%%)\n",
mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
else
seq_puts(file, "\n");
}
mt7921_mutex_release(dev);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats);
static int
mt7921_queues_acq(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
int i;
mt7921_mutex_acquire(dev);
for (i = 0; i < 4; i++) {
u32 ctrl, val, qlen = 0;
int j;
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
ctrl = BIT(31) | BIT(11) | (i << 24);
for (j = 0; j < 32; j++) {
if (val & BIT(j))
continue;
mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
GENMASK(11, 0));
}
seq_printf(s, "AC%d: queued=%d\n", i, qlen);
}
mt7921_mutex_release(dev);
return 0;
}
static int
mt7921_queues_read(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct {
struct mt76_queue *q;
char *queue;
} queue_map[] = {
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
};
int i;
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_queue *q = queue_map[i].q;
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->queued, q->head,
q->tail);
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats);
static void
mt7921_seq_puts_array(struct seq_file *file, const char *str,
@@ -211,13 +90,13 @@ mt7921_seq_puts_array(struct seq_file *file, const char *str,
static int
mt7921_txpwr(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct mt792x_dev *dev = dev_get_drvdata(s->private);
struct mt7921_txpwr txpwr;
int ret;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
ret = mt7921_get_txpwr_info(dev, &txpwr);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
if (ret)
return ret;
@@ -263,7 +142,7 @@ mt7921_txpwr(struct seq_file *s, void *data)
static int
mt7921_pm_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
struct mt76_connac_pm *pm = &dev->pm;
if (mt76_is_usb(&dev->mt76))
@@ -296,7 +175,7 @@ out:
static int
mt7921_pm_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
*val = dev->pm.enable_user;
@@ -308,7 +187,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
static int
mt7921_deep_sleep_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
struct mt76_connac_pm *pm = &dev->pm;
bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
bool enable = !!val;
@@ -316,7 +195,7 @@ mt7921_deep_sleep_set(void *data, u64 val)
if (mt76_is_usb(&dev->mt76))
return -EOPNOTSUPP;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
if (pm->ds_enable_user == enable)
goto out;
@@ -324,7 +203,7 @@ mt7921_deep_sleep_set(void *data, u64 val)
pm->ds_enable = enable && !monitor;
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
out:
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
return 0;
}
@@ -332,7 +211,7 @@ out:
static int
mt7921_deep_sleep_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
*val = dev->pm.ds_enable_user;
@@ -342,67 +221,24 @@ mt7921_deep_sleep_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get,
mt7921_deep_sleep_set, "%lld\n");
static int
mt7921_pm_stats(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct mt76_connac_pm *pm = &dev->pm;
unsigned long awake_time = pm->stats.awake_time;
unsigned long doze_time = pm->stats.doze_time;
if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
awake_time += jiffies - pm->stats.last_wake_event;
else
doze_time += jiffies - pm->stats.last_doze_event;
seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
jiffies_to_msecs(awake_time),
jiffies_to_msecs(doze_time));
seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
return 0;
}
static int
mt7921_pm_idle_timeout_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
dev->pm.idle_timeout = msecs_to_jiffies(val);
return 0;
}
static int
mt7921_pm_idle_timeout_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
*val = jiffies_to_msecs(dev->pm.idle_timeout);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get,
mt7921_pm_idle_timeout_set, "%lld\n");
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,
mt792x_pm_idle_timeout_set, "%lld\n");
static int mt7921_chip_reset(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt792x_dev *dev = data;
int ret = 0;
switch (val) {
case 1:
/* Reset wifisys directly. */
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
break;
default:
/* Collect the core dump before reset wifisys. */
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
ret = mt76_connac_mcu_chip_config(&dev->mt76);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
break;
}
@@ -414,7 +250,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n");
static int
mt7921s_sched_quota_read(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct mt792x_dev *dev = dev_get_drvdata(s->private);
struct mt76_sdio *sdio = &dev->mt76.sdio;
seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);
@@ -425,7 +261,7 @@ mt7921s_sched_quota_read(struct seq_file *s, void *data)
return 0;
}
int mt7921_init_debugfs(struct mt7921_dev *dev)
int mt7921_init_debugfs(struct mt792x_dev *dev)
{
struct dentry *dir;
@@ -435,23 +271,23 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
if (mt76_is_mmio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
dir, mt7921_queues_read);
dir, mt792x_queues_read);
else
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
dir, mt76_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7921_queues_acq);
mt792x_queues_acq);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
mt7921_txpwr);
debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops);
debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
debugfs_create_file("idle-timeout", 0600, dir, dev,
&fops_pm_idle_timeout);
debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
mt7921_pm_stats);
mt792x_pm_stats);
debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
if (mt76_is_sdio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
+78 -265
View File
@@ -2,259 +2,84 @@
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/etherdevice.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/thermal.h>
#include <linux/firmware.h>
#include "mt7921.h"
#include "../mt76_connac2_mac.h"
#include "mcu.h"
static const struct ieee80211_iface_limit if_limits[] = {
{
.max = MT7921_MAX_INTERFACES,
.types = BIT(NL80211_IFTYPE_STATION)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP)
}
};
static ssize_t mt7921_thermal_temp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
switch (to_sensor_dev_attr(attr)->index) {
case 0: {
struct mt792x_phy *phy = dev_get_drvdata(dev);
struct mt792x_dev *mdev = phy->dev;
int temperature;
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = MT7921_MAX_INTERFACES,
.num_different_channels = 1,
.beacon_int_infra_match = true,
},
};
mt792x_mutex_acquire(mdev);
temperature = mt7921_mcu_get_temperature(phy);
mt792x_mutex_release(mdev);
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO)
if (temperature < 0)
return temperature;
/* display in millidegree Celsius */
return sprintf(buf, "%u\n", temperature * 1000);
}
};
default:
return -EINVAL;
}
}
static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7921_thermal_temp, 0);
static const struct ieee80211_iface_combination if_comb_chanctx[] = {
{
.limits = if_limits_chanctx,
.n_limits = ARRAY_SIZE(if_limits_chanctx),
.max_interfaces = 2,
.num_different_channels = 2,
.beacon_int_infra_match = false,
}
static struct attribute *mt7921_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(mt7921_hwmon);
static int mt7921_thermal_init(struct mt792x_phy *phy)
{
struct wiphy *wiphy = phy->mt76->hw->wiphy;
struct device *hwmon;
const char *name;
if (!IS_REACHABLE(CONFIG_HWMON))
return 0;
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7921_%s",
wiphy_name(wiphy));
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7921_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
return 0;
}
static void
mt7921_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt792x_dev *dev = mt792x_hw_dev(hw);
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;
dev->country_ie_env = request->country_ie_env;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env);
mt76_connac_mcu_set_channel_domain(hw->priv);
mt7921_set_tx_sar_pwr(hw, NULL);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
}
static int
mt7921_init_wiphy(struct ieee80211_hw *hw)
{
struct mt7921_phy *phy = mt7921_hw_phy(hw);
struct mt7921_dev *dev = phy->dev;
struct wiphy *wiphy = hw->wiphy;
hw->queues = 4;
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->netdev_features = NETIF_F_RXCSUM;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
phy->slottime = 9;
hw->sta_data_size = sizeof(struct mt7921_sta);
hw->vif_data_size = sizeof(struct mt7921_vif);
if (dev->fw_features & MT7921_FW_CAP_CNM) {
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wiphy->iface_combinations = if_comb_chanctx;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
} else {
wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wiphy->iface_combinations = if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
}
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
WIPHY_FLAG_4ADDR_STATION);
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
wiphy->max_remain_on_channel_duration = 5000;
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_scan_ssids = 4;
wiphy->max_sched_scan_plan_interval =
MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;
wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
wiphy->max_sched_scan_reqs = 1;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy->reg_notifier = mt7921_regd_notifier;
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, CONNECTION_MONITOR);
if (dev->pm.enable)
ieee80211_hw_set(hw, CONNECTION_MONITOR);
hw->max_tx_fragments = 4;
return 0;
}
static void
mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
{
u32 mask, set;
mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
mt76_set(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
MT_TMAC_CTCR0_INS_DDLMT_EN);
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
/* enable MIB tx-rx time reporting */
mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN);
mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
/* filter out non-resp frames and get instantaneous signal reporting */
mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
}
static u8
mt7921_get_offload_capability(struct device *dev, const char *fw_wm)
{
const struct mt76_connac2_fw_trailer *hdr;
struct mt7921_realease_info *rel_info;
const struct firmware *fw;
int ret, i, offset = 0;
const u8 *data, *end;
u8 offload_caps = 0;
ret = request_firmware(&fw, fw_wm, dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev, "Invalid firmware\n");
goto out;
}
data = fw->data;
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
for (i = 0; i < hdr->n_region; i++) {
const struct mt76_connac2_fw_region *region;
region = (const void *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
offset += le32_to_cpu(region->len);
}
data += offset + 16;
rel_info = (struct mt7921_realease_info *)data;
data += sizeof(*rel_info);
end = data + le16_to_cpu(rel_info->len);
while (data < end) {
rel_info = (struct mt7921_realease_info *)data;
data += sizeof(*rel_info);
if (rel_info->tag == MT7921_FW_TAG_FEATURE) {
struct mt7921_fw_features *features;
features = (struct mt7921_fw_features *)data;
offload_caps = features->data;
break;
}
data += le16_to_cpu(rel_info->len) + rel_info->pad_len;
}
out:
release_firmware(fw);
return offload_caps;
}
struct ieee80211_ops *
mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features)
{
struct ieee80211_ops *ops;
ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL);
if (!ops)
return NULL;
*fw_features = mt7921_get_offload_capability(dev, drv_data);
if (!(*fw_features & MT7921_FW_CAP_CNM)) {
ops->remain_on_channel = NULL;
ops->cancel_remain_on_channel = NULL;
ops->add_chanctx = NULL;
ops->remove_chanctx = NULL;
ops->change_chanctx = NULL;
ops->assign_vif_chanctx = NULL;
ops->unassign_vif_chanctx = NULL;
ops->mgd_prepare_tx = NULL;
ops->mgd_complete_tx = NULL;
}
return ops;
}
EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops);
int mt7921_mac_init(struct mt7921_dev *dev)
int mt7921_mac_init(struct mt792x_dev *dev)
{
int i;
@@ -264,17 +89,17 @@ int mt7921_mac_init(struct mt7921_dev *dev)
/* enable hardware rx header translation */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
for (i = 0; i < MT7921_WTBL_SIZE; i++)
for (i = 0; i < MT792x_WTBL_SIZE; i++)
mt7921_mac_wtbl_update(dev, i,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < 2; i++)
mt7921_mac_init_band(dev, i);
mt792x_mac_init_band(dev, i);
return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
}
EXPORT_SYMBOL_GPL(mt7921_mac_init);
static int __mt7921_init_hardware(struct mt7921_dev *dev)
static int __mt7921_init_hardware(struct mt792x_dev *dev)
{
int ret;
@@ -282,7 +107,7 @@ static int __mt7921_init_hardware(struct mt7921_dev *dev)
* which should be set before firmware download stage.
*/
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7921_mcu_init(dev);
ret = mt792x_mcu_init(dev);
if (ret)
goto out;
@@ -297,21 +122,21 @@ out:
return ret;
}
static int mt7921_init_hardware(struct mt7921_dev *dev)
static int mt7921_init_hardware(struct mt792x_dev *dev)
{
int ret, i;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
for (i = 0; i < MT7921_MCU_INIT_RETRY_COUNT; i++) {
for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) {
ret = __mt7921_init_hardware(dev);
if (!ret)
break;
mt7921_init_reset(dev);
mt792x_init_reset(dev);
}
if (i == MT7921_MCU_INIT_RETRY_COUNT) {
if (i == MT792x_MCU_INIT_RETRY_COUNT) {
dev_err(dev->mt76.dev, "hardware init failed\n");
return ret;
}
@@ -319,26 +144,9 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
return 0;
}
static int mt7921_init_wcid(struct mt7921_dev *dev)
{
int idx;
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
if (idx)
return -ENOSPC;
dev->mt76.global_wcid.idx = idx;
dev->mt76.global_wcid.hw_key_idx = -1;
dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
return 0;
}
static void mt7921_init_work(struct work_struct *work)
{
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
init_work);
int ret;
@@ -362,13 +170,19 @@ static void mt7921_init_work(struct work_struct *work)
return;
}
ret = mt7921_thermal_init(&dev->phy);
if (ret) {
dev_err(dev->mt76.dev, "thermal init failed\n");
return;
}
/* we support chip reset now */
dev->hw_init_done = true;
mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
}
int mt7921_register_device(struct mt7921_dev *dev)
int mt7921_register_device(struct mt792x_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
int ret;
@@ -376,17 +190,17 @@ int mt7921_register_device(struct mt7921_dev *dev)
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
dev->mt76.tx_worker.fn = mt7921_tx_worker;
dev->mt76.tx_worker.fn = mt792x_tx_worker;
INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work);
INIT_WORK(&dev->pm.wake_work, mt7921_pm_wake_work);
INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work);
INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work);
spin_lock_init(&dev->pm.wake.lock);
mutex_init(&dev->pm.mutex);
init_waitqueue_head(&dev->pm.wait);
if (mt76_is_sdio(&dev->mt76))
init_waitqueue_head(&dev->mt76.sdio.wait);
spin_lock_init(&dev->pm.txq_lock);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work);
#if IS_ENABLED(CONFIG_IPV6)
@@ -395,17 +209,15 @@ int mt7921_register_device(struct mt7921_dev *dev)
#endif
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
INIT_WORK(&dev->init_work, mt7921_init_work);
INIT_WORK(&dev->phy.roc_work, mt7921_roc_work);
timer_setup(&dev->phy.roc_timer, mt7921_roc_timer, 0);
timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0);
init_waitqueue_head(&dev->phy.roc_wait);
dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
dev->pm.stats.last_wake_event = jiffies;
dev->pm.stats.last_doze_event = jiffies;
if (!mt76_is_usb(&dev->mt76)) {
@@ -418,16 +230,17 @@ int mt7921_register_device(struct mt7921_dev *dev)
if (!mt76_is_mmio(&dev->mt76))
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
mt7921_init_acpi_sar(dev);
mt792x_init_acpi_sar(dev);
ret = mt7921_init_wcid(dev);
ret = mt792x_init_wcid(dev);
if (ret)
return ret;
ret = mt7921_init_wiphy(hw);
ret = mt792x_init_wiphy(hw);
if (ret)
return ret;
hw->wiphy->reg_notifier = mt7921_regd_notifier;
dev->mphy.sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
+76 -478
View File
@@ -15,35 +15,7 @@
#define MT_WTBL_AC0_CTT_OFFSET 20
static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
{
return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
}
static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
u16 idx, bool unicast)
{
struct mt7921_sta *sta;
struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
if (unicast || !wcid)
return wcid;
if (!wcid->sta)
return NULL;
sta = container_of(wcid, struct mt7921_sta, wcid);
if (!sta->vif)
return NULL;
return &sta->vif->sta.wcid;
}
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask)
{
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);
@@ -52,7 +24,12 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
0, 5000);
}
void mt7921_mac_sta_poll(struct mt7921_dev *dev)
static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
{
return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
}
static void mt7921_mac_sta_poll(struct mt792x_dev *dev)
{
static const u8 ac_to_tid[] = {
[IEEE80211_AC_BE] = 0,
@@ -61,16 +38,16 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
[IEEE80211_AC_VO] = 6
};
struct ieee80211_sta *sta;
struct mt7921_sta *msta;
struct mt792x_sta *msta;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
struct rate_info *rate;
s8 rssi[4];
int i;
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
while (true) {
bool clear = false;
@@ -78,15 +55,15 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
u16 idx;
u8 bw;
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7921_sta, poll_list);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
struct mt792x_sta, wcid.poll_list);
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_AC0_CTT_OFFSET);
@@ -183,56 +160,9 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
}
}
EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll);
static void
mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy,
struct mt76_rx_status *status, u8 chfreq)
{
if (chfreq > 180) {
status->band = NL80211_BAND_6GHZ;
chfreq = (chfreq - 181) * 4 + 1;
} else if (chfreq > 14) {
status->band = NL80211_BAND_5GHZ;
} else {
status->band = NL80211_BAND_2GHZ;
}
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);
}
static int
mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
{
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
@@ -241,7 +171,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
u16 hdr_gap;
__le32 *rxv = NULL, *rxd = (__le32 *)skb->data;
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7921_phy *phy = &dev->phy;
struct mt792x_phy *phy = &dev->phy;
struct ieee80211_supported_band *sband;
u32 csum_status = *(u32 *)skb->cb;
u32 rxd0 = le32_to_cpu(rxd[0]);
@@ -249,7 +179,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
u32 rxd2 = le32_to_cpu(rxd[2]);
u32 rxd3 = le32_to_cpu(rxd[3]);
u32 rxd4 = le32_to_cpu(rxd[4]);
struct mt7921_sta *msta = NULL;
struct mt792x_sta *msta = NULL;
u16 seq_ctrl = 0;
__le16 fc = 0;
u8 mode = 0;
@@ -277,17 +207,18 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
status->wcid = mt792x_rx_get_wcid(dev, idx, unicast);
if (status->wcid) {
msta = container_of(status->wcid, struct mt7921_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
msta = container_of(status->wcid, struct mt792x_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);
}
mt7921_get_status_freq_info(dev, mphy, status, chfreq);
mt792x_get_status_freq_info(status, chfreq);
switch (status->band) {
case NL80211_BAND_5GHZ:
@@ -496,7 +427,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->flag |= RX_FLAG_8023;
}
mt7921_mac_assoc_rssi(dev, skb);
mt792x_mac_assoc_rssi(dev, skb);
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode);
@@ -511,33 +442,9 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
return 0;
}
static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data)
{
struct mt7921_sta *msta;
u16 fc, tid;
u32 val;
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
return;
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
if (tid >= 6) /* skip VO queue */
return;
val = le32_to_cpu(txwi[2]);
fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
msta = (struct mt7921_sta *)sta->drv_priv;
if (!test_and_set_bit(tid, &msta->ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
{
struct mt7921_sta *msta = NULL;
struct mt792x_sta *msta = NULL;
struct mt76_wcid *wcid;
__le32 *txs_data = data;
u16 wcidx;
@@ -552,7 +459,7 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
if (pid < MT_PACKET_ID_FIRST)
return;
if (wcidx >= MT7921_WTBL_SIZE)
if (wcidx >= MT792x_WTBL_SIZE)
return;
rcu_read_lock();
@@ -561,59 +468,29 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
if (!wcid)
goto out;
msta = container_of(wcid, struct mt7921_sta, wcid);
msta = container_of(wcid, struct mt792x_sta, wcid);
mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data);
if (!wcid->sta)
goto out;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
out:
rcu_read_unlock();
}
void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, bool clear_status,
struct list_head *free_list)
{
struct mt76_dev *mdev = &dev->mt76;
__le32 *txwi;
u16 wcid_idx;
mt76_connac_txp_skb_unmap(mdev, t);
if (!t->skb)
goto out;
txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
if (sta) {
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7921_tx_check_aggr(sta, txwi);
wcid_idx = wcid->idx;
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
}
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
out:
t->skb = NULL;
mt76_put_txwi(mdev, t);
}
EXPORT_SYMBOL_GPL(mt7921_txwi_free);
static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
{
struct mt76_connac_tx_free *free = data;
__le32 *tx_info = (__le32 *)(data + sizeof(*free));
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid = NULL;
struct sk_buff *skb, *tmp;
void *end = data + len;
LIST_HEAD(free_list);
@@ -636,8 +513,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
* 1'b0: msdu_id with the same 'wcid pair' as above.
*/
if (info & MT_TX_FREE_PAIR) {
struct mt7921_sta *msta;
struct mt76_wcid *wcid;
struct mt792x_sta *msta;
u16 idx;
count++;
@@ -647,22 +523,29 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
if (!sta)
continue;
msta = container_of(wcid, struct mt7921_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
msta = container_of(wcid, struct mt792x_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);
continue;
}
msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info);
stat = FIELD_GET(MT_TX_FREE_STATUS, info);
if (wcid) {
wcid->stats.tx_retries +=
FIELD_GET(MT_TX_FREE_COUNT, info) - 1;
wcid->stats.tx_failed += !!stat;
}
txwi = mt76_token_release(mdev, msdu, &wake);
if (!txwi)
continue;
mt7921_txwi_free(dev, txwi, sta, stat, &free_list);
mt76_connac2_txwi_free(mdev, txwi, sta, &free_list);
}
if (wake)
@@ -682,7 +565,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
__le32 *rxd = (__le32 *)data;
__le32 *end = (__le32 *)&rxd[len / 4];
enum rx_pkt_type type;
@@ -707,7 +590,7 @@ EXPORT_SYMBOL_GPL(mt7921_rx_check);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
__le32 *rxd = (__le32 *)skb->data;
__le32 *end = (__le32 *)&skb->data[skb->len];
enum rx_pkt_type type;
@@ -747,128 +630,12 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
}
EXPORT_SYMBOL_GPL(mt7921_queue_rx_skb);
void mt7921_mac_reset_counters(struct mt7921_phy *phy)
{
struct mt7921_dev *dev = phy->dev;
int i;
for (i = 0; i < 4; i++) {
mt76_rr(dev, MT_TX_AGG_CNT(0, i));
mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
}
dev->mt76.phy.survey_time = ktime_get_boottime();
memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));
/* reset airtime counters */
mt76_rr(dev, MT_MIB_SDR9(0));
mt76_rr(dev, MT_MIB_SDR36(0));
mt76_rr(dev, MT_MIB_SDR37(0));
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
}
void mt7921_mac_set_timing(struct mt7921_phy *phy)
{
s16 coverage_class = phy->coverage_class;
struct mt7921_dev *dev = phy->dev;
u32 val, reg_offset;
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
int sifs = is_2ghz ? 10 : 16, offset;
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
mt76_set(dev, MT_ARB_SCR(0),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
udelay(1);
offset = 3 * coverage_class;
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(0),
FIELD_PREP(MT_IFS_EIFS, 360) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, sifs) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
if (phy->slottime < 20 || !is_2ghz)
val = MT7921_CFEND_RATE_DEFAULT;
else
val = MT7921_CFEND_RATE_11B;
mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(0),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
}
static u8
mt7921_phy_get_nf(struct mt7921_phy *phy, int idx)
{
return 0;
}
static void
mt7921_phy_update_channel(struct mt76_phy *mphy, int idx)
{
struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76);
struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv;
struct mt76_channel_state *state;
u64 busy_time, tx_time, rx_time, obss_time;
int nf;
busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
MT_MIB_SDR9_BUSY_MASK);
tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
MT_MIB_SDR36_TXTIME_MASK);
rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
MT_MIB_SDR37_RXTIME_MASK);
obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
MT_MIB_OBSSTIME_MASK);
nf = mt7921_phy_get_nf(phy, idx);
if (!phy->noise)
phy->noise = nf << 4;
else if (nf)
phy->noise += nf - (phy->noise >> 4);
state = mphy->chan_state;
state->cc_busy += busy_time;
state->cc_tx += tx_time;
state->cc_rx += rx_time + obss_time;
state->cc_bss_rx += rx_time;
state->noise = -(phy->noise >> 4);
}
void mt7921_update_channel(struct mt76_phy *mphy)
{
struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76);
if (mt76_connac_pm_wake(mphy, &dev->pm))
return;
mt7921_phy_update_channel(mphy, 0);
/* reset obss airtime */
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
mt76_connac_power_save_sched(mphy, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt7921_update_channel);
static void
mt7921_vif_connect_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_dev *dev = mvif->phy->dev;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_dev *dev = mvif->phy->dev;
struct ieee80211_hw *hw = mt76_hw(dev);
if (vif->type == NL80211_IFTYPE_STATION)
@@ -889,7 +656,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
/* system error recovery */
void mt7921_mac_reset_work(struct work_struct *work)
{
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
reset_work);
struct ieee80211_hw *hw = mt76_hw(dev);
struct mt76_connac_pm *pm = &dev->pm;
@@ -905,7 +672,7 @@ void mt7921_mac_reset_work(struct work_struct *work)
for (i = 0; i < 10; i++) {
mutex_lock(&dev->mt76.mutex);
ret = mt7921_dev_reset(dev);
ret = mt792x_dev_reset(dev);
mutex_unlock(&dev->mt76.mutex);
if (!ret)
@@ -932,185 +699,12 @@ void mt7921_mac_reset_work(struct work_struct *work)
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
}
void mt7921_reset(struct mt76_dev *mdev)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
if (!dev->hw_init_done)
return;
if (dev->hw_full_reset)
return;
if (pm->suspended)
return;
queue_work(dev->mt76.wq, &dev->reset_work);
}
EXPORT_SYMBOL_GPL(mt7921_reset);
void mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
{
struct mt7921_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
int i, aggr0 = 0, aggr1;
u32 val;
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);
mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0));
mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0));
mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0));
val = mt76_rr(dev, MT_MIB_SDR32(0));
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val);
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val);
val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0));
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val);
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val);
val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0));
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val);
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val);
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val);
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val);
mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0));
mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0));
mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0));
mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0));
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
mib->tx_amsdu[i] += val;
mib->tx_amsdu_cnt += val;
}
for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) {
u32 val2;
val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
phy->mt76->aggr_stats[aggr0++] += val & 0xffff;
phy->mt76->aggr_stats[aggr0++] += val >> 16;
phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff;
phy->mt76->aggr_stats[aggr1++] += val2 >> 16;
}
}
void mt7921_mac_work(struct work_struct *work)
{
struct mt7921_phy *phy;
struct mt76_phy *mphy;
mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
mac_work.work);
phy = mphy->priv;
mt7921_mutex_acquire(phy->dev);
mt76_update_survey(mphy);
if (++mphy->mac_work_count == 2) {
mphy->mac_work_count = 0;
mt7921_mac_update_mib_stats(phy);
}
mt7921_mutex_release(phy->dev);
mt76_tx_status_check(mphy->dev, false);
ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
MT7921_WATCHDOG_TIME);
}
void mt7921_pm_wake_work(struct work_struct *work)
{
struct mt7921_dev *dev;
struct mt76_phy *mphy;
dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev,
pm.wake_work);
mphy = dev->phy.mt76;
if (!mt7921_mcu_drv_pmctrl(dev)) {
struct mt76_dev *mdev = &dev->mt76;
int i;
if (mt76_is_sdio(mdev)) {
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_worker_schedule(&mdev->sdio.txrx_worker);
} else {
local_bh_disable();
mt76_for_each_q_rx(mdev, i)
napi_schedule(&mdev->napi[i]);
local_bh_enable();
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_connac_tx_cleanup(mdev);
}
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7921_WATCHDOG_TIME);
}
ieee80211_wake_queues(mphy->hw);
wake_up(&dev->pm.wait);
}
void mt7921_pm_power_save_work(struct work_struct *work)
{
struct mt7921_dev *dev;
unsigned long delta;
struct mt76_phy *mphy;
dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev,
pm.ps_work.work);
mphy = dev->phy.mt76;
delta = dev->pm.idle_timeout;
if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) ||
dev->fw_assert)
goto out;
if (mutex_is_locked(&dev->mt76.mutex))
/* if mt76 mutex is held we should not put the device
* to sleep since we are currently accessing device
* register map. We need to wait for the next power_save
* trigger.
*/
goto out;
if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
delta = dev->pm.last_activity + delta - jiffies;
goto out;
}
if (!mt7921_mcu_fw_pmctrl(dev)) {
cancel_delayed_work_sync(&mphy->mac_work);
return;
}
out:
queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
}
void mt7921_coredump_work(struct work_struct *work)
{
struct mt7921_dev *dev;
struct mt792x_dev *dev;
char *dump, *data;
dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev,
dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
coredump.work.work);
if (time_is_after_jiffies(dev->coredump.last_activity +
@@ -1149,12 +743,12 @@ void mt7921_coredump_work(struct work_struct *work)
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
GFP_KERNEL);
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
}
/* usb_sdio */
static void
mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
mt7921_usb_sdio_write_txwi(struct mt792x_dev *dev, struct mt76_wcid *wcid,
enum mt76_txq_id qid, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key, int pid,
struct sk_buff *skb)
@@ -1171,7 +765,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct sk_buff *skb = tx_info->skb;
@@ -1180,11 +774,15 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL;
err = skb_cow_head(skb, MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE);
if (err)
return err;
if (!wcid)
wcid = &dev->mt76.global_wcid;
if (sta) {
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
if (time_after(jiffies, msta->last_txs + HZ / 4)) {
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -1224,7 +822,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
sta = wcid_to_sta(wcid);
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7921_tx_check_aggr(sta, txwi);
mt76_connac2_tx_check_aggr(sta, txwi);
skb_pull(e->skb, headroom);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
@@ -1233,11 +831,11 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb);
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
mt7921_mac_sta_poll(dev);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
return false;
}
@@ -1246,8 +844,8 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data);
#if IS_ENABLED(CONFIG_IPV6)
void mt7921_set_ipv6_ns_work(struct work_struct *work)
{
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
ipv6_ns_work);
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
ipv6_ns_work);
struct sk_buff *skb;
int ret = 0;
@@ -1257,10 +855,10 @@ void mt7921_set_ipv6_ns_work(struct work_struct *work)
if (!skb)
break;
mt7921_mutex_acquire(dev);
mt792x_mutex_acquire(dev);
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_UNI_CMD(OFFLOAD), true);
mt7921_mutex_release(dev);
mt792x_mutex_release(dev);
} while (!ret);
File diff suppressed because it is too large Load Diff
+72 -158
View File
@@ -4,9 +4,9 @@
#include <linux/fs.h>
#include <linux/firmware.h>
#include "mt7921.h"
#include "mt7921_trace.h"
#include "mcu.h"
#include "../mt76_connac2_mac.h"
#include "../mt792x_trace.h"
#define MT_STA_BFER BIT(0)
#define MT_STA_BFEE BIT(1)
@@ -25,7 +25,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
if (!skb) {
dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
cmd, seq);
mt7921_reset(mdev);
mt792x_reset(mdev);
return -ETIMEDOUT;
}
@@ -69,7 +69,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response);
static int mt7921_mcu_read_eeprom(struct mt7921_dev *dev, u32 offset, u8 *val)
static int mt7921_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)
{
struct mt7921_mcu_eeprom_info *res, req = {
.addr = cpu_to_le32(round_down(offset,
@@ -96,7 +96,7 @@ static int
mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev,
struct ieee80211_vif *vif, bool suspend)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct {
struct {
u8 bss_idx;
@@ -134,7 +134,7 @@ void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
#endif /* CONFIG_PM */
static void
mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt7921_roc_grant_tlv *grant;
struct mt76_connac2_mcu_rxd *rxd;
@@ -157,17 +157,17 @@ mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv;
struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
spin_lock_bh(&dev->mt76.lock);
__skb_queue_tail(&phy->scan_event_list, skb);
spin_unlock_bh(&dev->mt76.lock);
ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work,
MT7921_HW_SCAN_TIMEOUT);
MT792x_HW_SCAN_TIMEOUT);
}
static void
@@ -188,7 +188,7 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,
}
static void
mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac_beacon_loss_event *event;
struct mt76_phy *mphy = &dev->mt76.phy;
@@ -202,7 +202,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt7921_debug_msg {
__le16 id;
@@ -229,7 +229,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_low_power_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_lp_event {
u8 state;
@@ -243,7 +243,7 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_tx_done_event *event;
@@ -254,7 +254,7 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac2_mcu_rxd *rxd;
@@ -288,7 +288,7 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
static void
mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
mt7921_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,
struct sk_buff *skb)
{
struct mt76_connac2_mcu_rxd *rxd;
@@ -305,7 +305,7 @@ mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
dev_kfree_skb(skb);
}
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac2_mcu_rxd *rxd;
@@ -339,11 +339,11 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
}
/** starec & wtbl **/
int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable)
{
struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv;
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
if (enable && !params->amsdu)
msta->wcid.amsdu = false;
@@ -353,48 +353,24 @@ int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
enable, true);
}
int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable)
{
struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv;
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params,
MCU_UNI_CMD(STA_REC_UPDATE),
enable, false);
}
static char *mt7921_patch_name(struct mt7921_dev *dev)
{
char *ret;
if (is_mt7922(&dev->mt76))
ret = MT7922_ROM_PATCH;
else
ret = MT7921_ROM_PATCH;
return ret;
}
static char *mt7921_ram_name(struct mt7921_dev *dev)
{
char *ret;
if (is_mt7922(&dev->mt76))
ret = MT7922_FIRMWARE_WM;
else
ret = MT7921_FIRMWARE_WM;
return ret;
}
static int mt7921_load_clc(struct mt7921_dev *dev, const char *fw_name)
static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
{
const struct mt76_connac2_fw_trailer *hdr;
const struct mt76_connac2_fw_region *region;
const struct mt7921_clc *clc;
struct mt76_dev *mdev = &dev->mt76;
struct mt7921_phy *phy = &dev->phy;
struct mt792x_phy *phy = &dev->phy;
const struct firmware *fw;
int ret, i, len, offset = 0;
u8 *clc_base = NULL, hw_encap = 0;
@@ -472,42 +448,7 @@ out:
return ret;
}
static int mt7921_load_firmware(struct mt7921_dev *dev)
{
int ret;
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
if (ret)
return ret;
if (mt76_is_sdio(&dev->mt76)) {
/* activate again */
ret = __mt7921_mcu_fw_pmctrl(dev);
if (!ret)
ret = __mt7921_mcu_drv_pmctrl(dev);
}
ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL);
if (ret)
return ret;
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,
MT_TOP_MISC2_FW_N9_RDY, 1500)) {
dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
return -EIO;
}
#ifdef CONFIG_PM
dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
#endif /* CONFIG_PM */
dev_dbg(dev->mt76.dev, "Firmware init done\n");
return 0;
}
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl)
int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)
{
struct {
u8 ctrl_val;
@@ -520,11 +461,11 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl)
&data, sizeof(data), false);
}
int mt7921_run_firmware(struct mt7921_dev *dev)
int mt7921_run_firmware(struct mt792x_dev *dev)
{
int err;
err = mt7921_load_firmware(dev);
err = mt792x_load_firmware(dev);
if (err)
return err;
@@ -533,7 +474,7 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
return err;
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
err = mt7921_load_clc(dev, mt7921_ram_name(dev));
err = mt7921_load_clc(dev, mt792x_ram_name(dev));
if (err)
return err;
@@ -541,9 +482,9 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7921_run_firmware);
int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct edca {
__le16 cw_min;
__le16 cw_max;
@@ -635,12 +576,12 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
&req_mu, sizeof(req_mu), false);
}
int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
struct ieee80211_channel *chan, int duration,
enum mt7921_roc_req type, u8 token_id)
{
int center_ch = ieee80211_frequency_to_channel(chan->center_freq);
struct mt7921_dev *dev = phy->dev;
struct mt792x_dev *dev = phy->dev;
struct {
struct {
u8 rsv[4];
@@ -702,10 +643,10 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
&req, sizeof(req), false);
}
int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
u8 token_id)
{
struct mt7921_dev *dev = phy->dev;
struct mt792x_dev *dev = phy->dev;
struct {
struct {
u8 rsv[4];
@@ -732,9 +673,9 @@ int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
&req, sizeof(req), false);
}
int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd)
{
struct mt7921_dev *dev = phy->dev;
struct mt792x_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
int freq1 = chandef->center_freq1;
struct {
@@ -791,7 +732,7 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
}
int mt7921_mcu_set_eeprom(struct mt7921_dev *dev)
int mt7921_mcu_set_eeprom(struct mt792x_dev *dev)
{
struct req_hdr {
u8 buffer_mode;
@@ -807,9 +748,9 @@ int mt7921_mcu_set_eeprom(struct mt7921_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom);
int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)
int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct {
struct {
u8 bss_idx;
@@ -845,10 +786,10 @@ int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)
}
static int
mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct {
struct {
u8 bss_idx;
@@ -881,10 +822,10 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
}
int
mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct {
u8 bss_idx;
u8 dtim_period;
@@ -918,11 +859,11 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
&req, sizeof(req), false);
}
int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, bool enable,
enum mt76_sta_info_state state)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
int rssi = -ewma_rssi_read(&mvif->rssi);
struct mt76_sta_cmd_info info = {
.sta = sta,
@@ -933,60 +874,16 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
.offload_fw = true,
.rcpi = to_rcpi(rssi),
};
struct mt7921_sta *msta;
struct mt792x_sta *msta;
msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL;
msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL;
info.wcid = msta ? &msta->wcid : &mvif->sta.wcid;
info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;
return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);
}
int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
mutex_lock(&pm->mutex);
if (!test_bit(MT76_STATE_PM, &mphy->state))
goto out;
err = __mt7921_mcu_drv_pmctrl(dev);
out:
mutex_unlock(&pm->mutex);
if (err)
mt7921_reset(&dev->mt76);
return err;
}
EXPORT_SYMBOL_GPL(mt7921_mcu_drv_pmctrl);
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
mutex_lock(&pm->mutex);
if (mt76_connac_skip_fw_pmctrl(mphy, pm))
goto out;
err = __mt7921_mcu_fw_pmctrl(dev);
out:
mutex_unlock(&pm->mutex);
if (err)
mt7921_reset(&dev->mt76);
return err;
}
EXPORT_SYMBOL_GPL(mt7921_mcu_fw_pmctrl);
int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
bool enable)
{
@@ -1021,7 +918,7 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
return 0;
}
int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr)
int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr)
{
struct mt7921_txpwr_event *event;
struct mt7921_txpwr_req req = {
@@ -1044,7 +941,7 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr)
return 0;
}
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
@@ -1074,7 +971,7 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
true);
}
int mt7921_mcu_config_sniffer(struct mt7921_vif *vif,
int mt7921_mcu_config_sniffer(struct mt792x_vif *vif,
struct ieee80211_chanctx_conf *ctx)
{
struct cfg80211_chan_def *chandef = &ctx->def;
@@ -1143,12 +1040,12 @@ int mt7921_mcu_config_sniffer(struct mt7921_vif *vif,
}
int
mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,
struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
bool enable)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
struct ieee80211_mutable_offsets offs;
struct {
@@ -1221,7 +1118,7 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
}
static
int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap env_cap,
struct mt7921_clc *clc,
u8 idx)
@@ -1241,7 +1138,7 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
} __packed req = {
.idx = idx,
.env = env_cap,
.acpi_conf = mt7921_acpi_get_flags(&dev->phy),
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
};
int ret, valid_cnt = 0;
u8 i, *pos;
@@ -1283,10 +1180,10 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
return 0;
}
int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap env_cap)
{
struct mt7921_phy *phy = (struct mt7921_phy *)&dev->phy;
struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy;
int i, ret;
/* submit all clc config */
@@ -1305,7 +1202,24 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
return 0;
}
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
int mt7921_mcu_get_temperature(struct mt792x_phy *phy)
{
struct mt792x_dev *dev = phy->dev;
struct {
u8 ctrl_id;
u8 action;
u8 band_idx;
u8 rsv[5];
} req = {
.ctrl_id = THERMAL_SENSOR_TEMP_QUERY,
.band_idx = phy->mt76->band_idx,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,
sizeof(req), true);
}
int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map)
{
struct {
@@ -4,22 +4,8 @@
#ifndef __MT7921_H
#define __MT7921_H
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include "../mt76_connac_mcu.h"
#include "../mt792x.h"
#include "regs.h"
#include "acpi_sar.h"
#define MT7921_MAX_INTERFACES 4
#define MT7921_WTBL_SIZE 20
#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1)
#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \
MT7921_MAX_INTERFACES)
#define MT7921_PM_TIMEOUT (HZ / 12)
#define MT7921_HW_SCAN_TIMEOUT (HZ / 10)
#define MT7921_WATCHDOG_TIME (HZ / 4)
#define MT7921_RESET_TIMEOUT (30 * HZ)
#define MT7921_TX_RING_SIZE 2048
#define MT7921_TX_MCU_RING_SIZE 256
@@ -28,27 +14,11 @@
#define MT7921_RX_RING_SIZE 1536
#define MT7921_RX_MCU_RING_SIZE 512
#define MT7921_DRV_OWN_RETRY_COUNT 10
#define MT7921_MCU_INIT_RETRY_COUNT 10
#define MT7921_WFSYS_INIT_RETRY_COUNT 2
#define MT7921_FW_TAG_FEATURE 4
#define MT7921_FW_CAP_CNM BIT(7)
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
#define MT7921_EEPROM_SIZE 3584
#define MT7921_TOKEN_SIZE 8192
#define MT7921_EEPROM_BLOCK_SIZE 16
#define MT7921_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7921_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7921_SKU_RATE_NUM 161
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
@@ -128,9 +98,6 @@ struct mt7921_sdio_intr {
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
#define to_rcpi(rssi) (2 * (rssi) + 220)
struct mt7921_vif;
struct mt7921_sta;
enum mt7921_txq_id {
MT7921_TXQ_BAND0,
MT7921_TXQ_BAND1,
@@ -144,70 +111,6 @@ enum mt7921_rxq_id {
MT7921_RXQ_MCU_WM = 0,
};
DECLARE_EWMA(avg_signal, 10, 8)
struct mt7921_sta {
struct mt76_wcid wcid; /* must be first */
struct mt7921_vif *vif;
struct list_head poll_list;
u32 airtime_ac[8];
int ack_signal;
struct ewma_avg_signal avg_ack_signal;
unsigned long last_txs;
unsigned long ampdu_state;
struct mt76_connac_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_sta *wep_sta;
struct mt7921_phy *phy;
struct ewma_rssi rssi;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct ieee80211_chanctx_conf *ctx;
};
struct mib_stats {
u32 ack_fail_cnt;
u32 fcs_err_cnt;
u32 rts_cnt;
u32 rts_retries_cnt;
u32 ba_miss_cnt;
u32 tx_bf_ibf_ppdu_cnt;
u32 tx_bf_ebf_ppdu_cnt;
u32 tx_bf_rx_fb_all_cnt;
u32 tx_bf_rx_fb_he_cnt;
u32 tx_bf_rx_fb_vht_cnt;
u32 tx_bf_rx_fb_ht_cnt;
u32 tx_ampdu_cnt;
u32 tx_mpdu_attempts_cnt;
u32 tx_mpdu_success_cnt;
u32 tx_pkt_ebf_cnt;
u32 tx_pkt_ibf_cnt;
u32 rx_mpdu_cnt;
u32 rx_ampdu_cnt;
u32 rx_ampdu_bytes_cnt;
u32 rx_ba_cnt;
u32 tx_amsdu[8];
u32 tx_amsdu_cnt;
};
enum {
MT7921_CLC_POWER,
MT7921_CLC_CHAN,
@@ -231,41 +134,6 @@ struct mt7921_clc {
u8 data[];
} __packed;
struct mt7921_phy {
struct mt76_phy *mt76;
struct mt7921_dev *dev;
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
u64 omac_mask;
u16 noise;
s16 coverage_class;
u8 slottime;
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
u8 sta_work_count;
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
#ifdef CONFIG_ACPI
struct mt7921_acpi_sar *acpisar;
#endif
struct mt7921_clc *clc[MT7921_CLC_MAX_NUM];
struct work_struct roc_work;
struct timer_list roc_timer;
wait_queue_head_t roc_wait;
u8 roc_token_id;
bool roc_grant;
};
enum mt7921_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
@@ -277,52 +145,6 @@ enum mt7921_eeprom_field {
#define MT_EE_HW_TYPE_ENCAP BIT(0)
#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
#define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev))
#define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev))
#define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev))
#define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev))
struct mt7921_hif_ops {
int (*init_reset)(struct mt7921_dev *dev);
int (*reset)(struct mt7921_dev *dev);
int (*mcu_init)(struct mt7921_dev *dev);
int (*drv_own)(struct mt7921_dev *dev);
int (*fw_own)(struct mt7921_dev *dev);
};
struct mt7921_dev {
union { /* must be first */
struct mt76_dev mt76;
struct mt76_phy mphy;
};
const struct mt76_bus_ops *bus_ops;
struct mt7921_phy phy;
struct work_struct reset_work;
bool hw_full_reset:1;
bool hw_init_done:1;
bool fw_assert:1;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
struct work_struct init_work;
u8 fw_debug;
u8 fw_features;
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
const struct mt7921_hif_ops *hif_ops;
struct work_struct ipv6_ns_work;
/* IPv6 addresses for WoWLAN */
struct sk_buff_head ipv6_ns_list;
enum environment_cap country_ie_env;
};
enum {
TXPWR_USER,
TXPWR_EEPROM,
@@ -353,56 +175,31 @@ struct mt7921_txpwr {
} data[TXPWR_MAX_NUM];
};
static inline struct mt7921_phy *
mt7921_hw_phy(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return phy->priv;
}
static inline struct mt7921_dev *
mt7921_hw_dev(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return container_of(phy->dev, struct mt7921_dev, mt76);
}
#define mt7921_mutex_acquire(dev) \
mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm)
#define mt7921_mutex_release(dev) \
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
extern const struct ieee80211_ops mt7921_ops;
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
u32 mt7921_reg_map(struct mt792x_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_dma_init(struct mt7921_dev *dev);
int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force);
int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev);
void mt7921_dma_cleanup(struct mt7921_dev *dev);
int mt7921_run_firmware(struct mt7921_dev *dev);
int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
int __mt7921_start(struct mt792x_phy *phy);
int mt7921_register_device(struct mt792x_dev *dev);
void mt7921_unregister_device(struct mt792x_dev *dev);
int mt7921_run_firmware(struct mt792x_dev *dev);
int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, bool enable,
enum mt76_sta_info_state state);
int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd);
int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif);
int mt7921_mcu_set_eeprom(struct mt7921_dev *dev);
int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif,
int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd);
int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif);
int mt7921_mcu_set_eeprom(struct mt792x_dev *dev);
int mt7921_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl);
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl);
void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb);
int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
static inline u32
mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr)
mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
@@ -415,19 +212,19 @@ mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr)
}
static inline u32
mt7921_l1_rr(struct mt7921_dev *dev, u32 addr)
mt7921_l1_rr(struct mt792x_dev *dev, u32 addr)
{
return mt76_rr(dev, mt7921_reg_map_l1(dev, addr));
}
static inline void
mt7921_l1_wr(struct mt7921_dev *dev, u32 addr, u32 val)
mt7921_l1_wr(struct mt792x_dev *dev, u32 addr, u32 val)
{
mt76_wr(dev, mt7921_reg_map_l1(dev, addr), val);
}
static inline u32
mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val)
mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val)
{
val |= mt7921_l1_rr(dev, addr) & ~mask;
mt7921_l1_wr(dev, addr, val);
@@ -438,13 +235,8 @@ 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)
static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev)
{
return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
}
static inline void
mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
int type)
{
u32 hdr, len;
@@ -457,89 +249,69 @@ mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
}
void mt7921_stop(struct ieee80211_hw *hw);
int mt7921_mac_init(struct mt7921_dev *dev);
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
void mt7921_mac_set_timing(struct mt7921_phy *phy);
int mt7921_mac_init(struct mt792x_dev *dev);
bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
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_mac_update_mib_stats(struct mt7921_phy *phy);
void mt7921_reset(struct mt76_dev *mdev);
int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7921_tx_worker(struct mt76_worker *w);
void mt7921_tx_token_put(struct mt7921_dev *dev);
bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
void mt7921_stats_work(struct work_struct *work);
void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
void mt7921_update_channel(struct mt76_phy *mphy);
int mt7921_init_debugfs(struct mt7921_dev *dev);
void mt7921_set_stream_he_caps(struct mt792x_phy *phy);
int mt7921_init_debugfs(struct mt792x_dev *dev);
int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
void mt7921_scan_work(struct work_struct *work);
void mt7921_roc_work(struct work_struct *work);
void mt7921_roc_timer(struct timer_list *timer);
int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
void mt7921_pm_wake_work(struct work_struct *work);
void mt7921_pm_power_save_work(struct work_struct *work);
int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif);
void mt7921_coredump_work(struct work_struct *work);
int mt7921_wfsys_reset(struct mt7921_dev *dev);
int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr);
int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr);
int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
struct netlink_callback *cb, void *data, int len);
void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, bool clear_status,
struct list_head *free_list);
void mt7921_mac_sta_poll(struct mt7921_dev *dev);
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq);
int mt7921e_driver_own(struct mt7921_dev *dev);
int mt7921e_mac_reset(struct mt7921_dev *dev);
int mt7921e_mcu_init(struct mt7921_dev *dev);
int mt7921s_wfsys_reset(struct mt7921_dev *dev);
int mt7921s_mac_reset(struct mt7921_dev *dev);
int mt7921s_init_reset(struct mt7921_dev *dev);
int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
int mt7921e_driver_own(struct mt792x_dev *dev);
int mt7921e_mac_reset(struct mt792x_dev *dev);
int mt7921e_mcu_init(struct mt792x_dev *dev);
int mt7921s_wfsys_reset(struct mt792x_dev *dev);
int mt7921s_mac_reset(struct mt792x_dev *dev);
int mt7921s_init_reset(struct mt792x_dev *dev);
int mt7921s_mcu_init(struct mt7921_dev *dev);
int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev);
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data);
void mt7921_set_runtime_pm(struct mt7921_dev *dev);
int mt7921s_mcu_init(struct mt792x_dev *dev);
int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev);
int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev);
void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data);
void mt7921_set_runtime_pm(struct mt792x_dev *dev);
void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
void mt7921_set_ipv6_ns_work(struct work_struct *work);
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_config_sniffer(struct mt7921_vif *vif,
int mt7921_mcu_config_sniffer(struct mt792x_vif *vif,
struct ieee80211_chanctx_conf *ctx);
int mt7921_mcu_get_temperature(struct mt792x_phy *phy);
int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
@@ -550,51 +322,18 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
/* usb */
#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f)
#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e)
int mt7921u_mcu_power_on(struct mt7921_dev *dev);
int mt7921u_wfsys_reset(struct mt7921_dev *dev);
int mt7921u_dma_init(struct mt7921_dev *dev, bool resume);
int mt7921u_init_reset(struct mt7921_dev *dev);
int mt7921u_mac_reset(struct mt7921_dev *dev);
int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
int mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,
struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
bool enable);
#ifdef CONFIG_ACPI
int mt7921_init_acpi_sar(struct mt7921_dev *dev);
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default);
u8 mt7921_acpi_get_flags(struct mt7921_phy *phy);
#else
static inline int
mt7921_init_acpi_sar(struct mt7921_dev *dev)
{
return 0;
}
static inline int
mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
{
return 0;
}
static inline u8
mt7921_acpi_get_flags(struct mt7921_phy *phy)
{
return 0;
}
#endif
int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap env_cap);
int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
struct ieee80211_channel *chan, int duration,
enum mt7921_roc_req type, u8 token_id);
int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
u8 token_id);
struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev,
void *drv_data, u8 *fw_features);
#endif
+117 -108
View File
@@ -9,8 +9,8 @@
#include "mt7921.h"
#include "../mt76_connac2_mac.h"
#include "../dma.h"
#include "mcu.h"
#include "../trace.h"
static const struct pci_device_id mt7921_pci_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961),
@@ -28,81 +28,12 @@ static bool mt7921_disable_aspm;
module_param_named(disable_aspm, mt7921_disable_aspm, bool, 0644);
MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
static void
mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
static int mt7921e_init_reset(struct mt792x_dev *dev)
{
if (q == MT_RXQ_MAIN)
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA);
else if (q == MT_RXQ_MCU_WA)
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2);
else
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM);
return mt792x_wpdma_reset(dev, true);
}
static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
{
struct mt7921_dev *dev = dev_instance;
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
static void mt7921_irq_tasklet(unsigned long data)
{
struct mt7921_dev *dev = (struct mt7921_dev *)data;
u32 intr, mask = 0;
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr);
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
mask |= intr & MT_INT_RX_DONE_ALL;
if (intr & MT_INT_TX_DONE_MCU)
mask |= MT_INT_TX_DONE_MCU;
if (intr & MT_INT_MCU_CMD) {
u32 intr_sw;
intr_sw = mt76_rr(dev, MT_MCU_CMD);
/* ack MCU2HOST_SW_INT_STA */
mt76_wr(dev, MT_MCU_CMD, intr_sw);
if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) {
mask |= MT_INT_RX_DONE_DATA;
intr |= MT_INT_RX_DONE_DATA;
}
}
mt76_set_irq_mask(&dev->mt76, MT_WFDMA0_HOST_INT_ENA, mask, 0);
if (intr & MT_INT_TX_DONE_ALL)
napi_schedule(&dev->mt76.tx_napi);
if (intr & MT_INT_RX_DONE_WM)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
if (intr & MT_INT_RX_DONE_WM2)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);
if (intr & MT_INT_RX_DONE_DATA)
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
}
static int mt7921e_init_reset(struct mt7921_dev *dev)
{
return mt7921_wpdma_reset(dev, true);
}
static void mt7921e_unregister_device(struct mt7921_dev *dev)
static void mt7921e_unregister_device(struct mt792x_dev *dev)
{
int i;
struct mt76_connac_pm *pm = &dev->pm;
@@ -115,16 +46,16 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
cancel_work_sync(&pm->wake_work);
cancel_work_sync(&dev->reset_work);
mt7921_tx_token_put(dev);
__mt7921_mcu_drv_pmctrl(dev);
mt7921_dma_cleanup(dev);
mt7921_wfsys_reset(dev);
mt76_connac2_tx_token_put(&dev->mt76);
__mt792x_mcu_drv_pmctrl(dev);
mt792x_dma_cleanup(dev);
mt792x_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
tasklet_disable(&dev->mt76.irq_tasklet);
}
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
static u32 __mt7921_reg_addr(struct mt792x_dev *dev, u32 addr)
{
static const struct mt76_connac_reg_map fixed_map[] = {
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
@@ -203,7 +134,7 @@ static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
return dev->bus_ops->rr(mdev, addr);
@@ -211,7 +142,7 @@ static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
dev->bus_ops->wr(mdev, addr, val);
@@ -219,12 +150,77 @@ static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
return dev->bus_ops->rmw(mdev, addr, mask, val);
}
static int mt7921_dma_init(struct mt792x_dev *dev)
{
int ret;
mt76_dma_attach(&dev->mt76);
ret = mt792x_dma_disable(dev, true);
if (ret)
return ret;
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
if (ret)
return ret;
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
/* command to WM */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,
MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* firmware download */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL,
MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* event from WM before firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
if (ret)
return ret;
/* Change mcu queue after firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
if (ret)
return ret;
/* rx data */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
if (ret)
return ret;
ret = mt76_init_queues(dev, mt792x_poll_rx);
if (ret < 0)
return ret;
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt792x_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return mt792x_dma_enable(dev);
}
static int mt7921_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -241,22 +237,34 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_check = mt7921_rx_check,
.rx_skb = mt7921_queue_rx_skb,
.rx_poll_complete = mt7921_rx_poll_complete,
.rx_poll_complete = mt792x_rx_poll_complete,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
.update_survey = mt7921_update_channel,
.update_survey = mt792x_update_channel,
};
static const struct mt7921_hif_ops mt7921_pcie_ops = {
static const struct mt792x_hif_ops mt7921_pcie_ops = {
.init_reset = mt7921e_init_reset,
.reset = mt7921e_mac_reset,
.mcu_init = mt7921e_mcu_init,
.drv_own = mt7921e_mcu_drv_pmctrl,
.fw_own = mt7921e_mcu_fw_pmctrl,
.drv_own = mt792xe_mcu_drv_pmctrl,
.fw_own = mt792xe_mcu_fw_pmctrl,
};
static const struct mt792x_irq_map irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
.all_complete_mask = MT_INT_TX_DONE_ALL,
.mcu_complete_mask = MT_INT_TX_DONE_MCU,
},
.rx = {
.data_complete_mask = MT_INT_RX_DONE_DATA,
.wm_complete_mask = MT_INT_RX_DONE_WM,
.wm2_complete_mask = MT_INT_RX_DONE_WM2,
},
};
struct ieee80211_ops *ops;
struct mt76_bus_ops *bus_ops;
struct mt7921_dev *dev;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
@@ -288,8 +296,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
if (mt7921_disable_aspm)
mt76_pci_disable_aspm(pdev);
ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data,
&features);
ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7921_ops,
(void *)id->driver_data, &features);
if (!ops) {
ret = -ENOMEM;
goto err_free_pci_vec;
@@ -303,11 +311,12 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, mdev);
dev = container_of(mdev, struct mt7921_dev, mt76);
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7921_pcie_ops;
dev->irq_map = &irq_map;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
@@ -325,11 +334,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
bus_ops->rmw = mt7921_rmw;
dev->mt76.bus = bus_ops;
ret = mt7921e_mcu_fw_pmctrl(dev);
ret = mt792xe_mcu_fw_pmctrl(dev);
if (ret)
goto err_free_dev;
ret = __mt7921e_mcu_drv_pmctrl(dev);
ret = __mt792xe_mcu_drv_pmctrl(dev);
if (ret)
goto err_free_dev;
@@ -337,15 +346,15 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
ret = mt7921_wfsys_reset(dev);
ret = mt792x_wfsys_reset(dev);
if (ret)
goto err_free_dev;
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, irq_map.host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler,
ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto err_free_dev;
@@ -373,7 +382,7 @@ err_free_pci_vec:
static void mt7921_pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
mt7921e_unregister_device(dev);
devm_free_irq(&pdev->dev, pdev->irq, dev);
@@ -385,7 +394,7 @@ static int mt7921_pci_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
int i, err;
@@ -394,7 +403,7 @@ static int mt7921_pci_suspend(struct device *device)
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
err = mt7921_mcu_drv_pmctrl(dev);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto restore_suspend;
@@ -424,12 +433,12 @@ static int mt7921_pci_suspend(struct device *device)
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
/* disable interrupt */
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
synchronize_irq(pdev->irq);
tasklet_kill(&mdev->irq_tasklet);
err = mt7921_mcu_fw_pmctrl(dev);
err = mt792x_mcu_fw_pmctrl(dev);
if (err)
goto restore_napi;
@@ -450,7 +459,7 @@ restore_suspend:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
@@ -459,21 +468,21 @@ static int mt7921_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
int i, err;
err = mt7921_mcu_drv_pmctrl(dev);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto failed;
mt7921_wpdma_reinit_cond(dev);
mt792x_wpdma_reinit_cond(dev);
/* enable interrupt */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
mt76_connac_irq_enable(&dev->mt76,
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
MT_INT_MCU_CMD);
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
@@ -500,7 +509,7 @@ failed:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
@@ -10,7 +10,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct mt76_connac_hw_txp *txp;
@@ -32,7 +32,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return id;
if (sta) {
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
if (time_after(jiffies, msta->last_txs + HZ / 4)) {
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -53,29 +53,15 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
void mt7921_tx_token_put(struct mt7921_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7921_txwi_free(dev, txwi, NULL, false, NULL);
dev->mt76.token_count--;
}
spin_unlock_bh(&dev->mt76.token_lock);
idr_destroy(&dev->mt76.token);
}
int mt7921e_mac_reset(struct mt7921_dev *dev)
int mt7921e_mac_reset(struct mt792x_dev *dev)
{
int i, err;
mt7921e_mcu_drv_pmctrl(dev);
mt792xe_mcu_drv_pmctrl(dev);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
set_bit(MT76_RESET, &dev->mphy.state);
@@ -91,10 +77,10 @@ int mt7921e_mac_reset(struct mt7921_dev *dev)
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
napi_disable(&dev->mt76.tx_napi);
mt7921_tx_token_put(dev);
mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7921_wpdma_reset(dev, true);
mt792x_wpdma_reset(dev, true);
local_bh_disable();
mt76_for_each_q_rx(&dev->mt76, i) {
@@ -106,9 +92,9 @@ int mt7921e_mac_reset(struct mt7921_dev *dev)
dev->fw_assert = false;
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA,
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
MT_INT_MCU_CMD);
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt7921e_driver_own(dev);
@@ -4,7 +4,7 @@
#include "mt7921.h"
#include "mcu.h"
int mt7921e_driver_own(struct mt7921_dev *dev)
int mt7921e_driver_own(struct mt792x_dev *dev)
{
u32 reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0);
@@ -22,7 +22,7 @@ static int
mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *seq)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
enum mt76_mcuq_id txq = MT_MCUQ_WM;
int ret;
@@ -38,7 +38,7 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0);
}
int mt7921e_mcu_init(struct mt7921_dev *dev)
int mt7921e_mcu_init(struct mt792x_dev *dev)
{
static const struct mt76_mcu_ops mt7921_mcu_ops = {
.headroom = sizeof(struct mt76_connac2_mcu_txd),
@@ -61,68 +61,3 @@ int mt7921e_mcu_init(struct mt7921_dev *dev)
return err;
}
int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
{
int i, err = 0;
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))
break;
}
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "driver own failed\n");
err = -EIO;
}
return err;
}
int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err;
err = __mt7921e_mcu_drv_pmctrl(dev);
if (err < 0)
goto out;
mt7921_wpdma_reinit_cond(dev);
clear_bit(MT76_STATE_PM, &mphy->state);
pm->stats.last_wake_event = jiffies;
pm->stats.doze_time += pm->stats.last_wake_event -
pm->stats.last_doze_event;
out:
return err;
}
int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int i;
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1))
break;
}
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "firmware own failed\n");
clear_bit(MT76_STATE_PM, &mphy->state);
return -EIO;
}
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
return 0;
}
@@ -4,26 +4,7 @@
#ifndef __MT7921_REGS_H
#define __MT7921_REGS_H
/* MCU WFDMA1 */
#define MT_MCU_WFDMA1_BASE 0x3000
#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs))
#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108)
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2)
#define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
#define MT_PLE_BASE 0x820c0000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0)
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4)
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8)
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec)
#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
#include "../mt792x_regs.h"
#define MT_MDP_BASE 0x820cd000
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
@@ -47,280 +28,7 @@
#define MT_MDP_TO_HIF 0
#define MT_MDP_TO_WM 1
/* TMAC: band 0(0x21000), band 1(0xa1000) */
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0)
#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25)
#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090)
#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094)
#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4)
#define MT_IFS_EIFS GENMASK(8, 0)
#define MT_IFS_RIFS GENMASK(14, 10)
#define MT_IFS_SIFS GENMASK(22, 16)
#define MT_IFS_SLOT GENMASK(30, 24)
#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4)
#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0)
#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17)
#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18)
#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c)
#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0)
#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000)
#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs))
#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000)
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3)
#define MT_DMA_DCR0_RXD_G5_EN BIT(23)
/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */
#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000)
#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs))
#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008)
#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30)
#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24)
/* LPON: band 0(0x24200), band 1(0xa4200) */
#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000)
#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs))
#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080)
#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084)
#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4)
#define MT_LPON_TCR_SW_MODE GENMASK(1, 0)
#define MT_LPON_TCR_SW_WRITE BIT(0)
/* ETBF: band 0(0x24000), band 1(0xa4000) */
#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000)
#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs))
#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150)
#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16)
#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0)
#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158)
#define MT_ETBF_RX_FB_ALL GENMASK(31, 24)
#define MT_ETBF_RX_FB_HE GENMASK(23, 16)
#define MT_ETBF_RX_FB_VHT GENMASK(15, 8)
#define MT_ETBF_RX_FB_HT GENMASK(7, 0)
/* MIB: band 0(0x24800), band 1(0xa4800) */
#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000)
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004)
#define MT_MIB_TXDUR_EN BIT(8)
#define MT_MIB_RXDUR_EN BIT(9)
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698)
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16)
#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780)
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558)
#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564)
#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568)
#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048)
#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770)
#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774)
#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c)
#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8)
#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16)
#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0)
#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090)
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054)
#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058)
#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0)
#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0)
#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4)
#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc)
#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4))
#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16)
#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
#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, 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 0x820d4000
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0)
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12)
#define MT_WTBL_UPDATE_BUSY BIT(31)
#define MT_WTBL_BASE 0x820d8000
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
#define MT_WTBL_LMAC_DW GENMASK(7, 2)
#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
/* AGG: band 0(0x20800), band 1(0xa0800) */
#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000)
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4)
#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4)
#define MT_AGG_PCR0_MM_PROT BIT(0)
#define MT_AGG_PCR0_GF_PROT BIT(1)
#define MT_AGG_PCR0_BW20_PROT BIT(2)
#define MT_AGG_PCR0_BW40_PROT BIT(4)
#define MT_AGG_PCR0_BW80_PROT BIT(6)
#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8)
#define MT_AGG_PCR0_VHT_PROT BIT(13)
#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15)
#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23)
#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0)
#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084)
#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0)
#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16)
#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098)
#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12)
#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6)
#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7)
#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24)
#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0)
#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4)
/* ARB: band 0(0x20c00), band 1(0xa0c00) */
#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000)
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080)
#define MT_ARB_SCR_TX_DISABLE BIT(8)
#define MT_ARB_SCR_RX_DISABLE BIT(9)
#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4)
/* RMAC: band 0(0x21400), band 1(0xa1400) */
#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000)
#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs))
#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000)
#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0)
#define MT_WF_RFCR_DROP_FCSFAIL BIT(1)
#define MT_WF_RFCR_DROP_VERSION BIT(3)
#define MT_WF_RFCR_DROP_PROBEREQ BIT(4)
#define MT_WF_RFCR_DROP_MCAST BIT(5)
#define MT_WF_RFCR_DROP_BCAST BIT(6)
#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7)
#define MT_WF_RFCR_DROP_A3_MAC BIT(8)
#define MT_WF_RFCR_DROP_A3_BSSID BIT(9)
#define MT_WF_RFCR_DROP_A2_BSSID BIT(10)
#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11)
#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12)
#define MT_WF_RFCR_DROP_CTL_RSV BIT(13)
#define MT_WF_RFCR_DROP_CTS BIT(14)
#define MT_WF_RFCR_DROP_RTS BIT(15)
#define MT_WF_RFCR_DROP_DUPLICATE BIT(16)
#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17)
#define MT_WF_RFCR_DROP_OTHER_UC BIT(18)
#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19)
#define MT_WF_RFCR_DROP_NDPA BIT(20)
#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21)
#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004)
#define MT_WF_RFCR1_DROP_ACK BIT(4)
#define MT_WF_RFCR1_DROP_BF_POLL BIT(5)
#define MT_WF_RFCR1_DROP_BA BIT(6)
#define MT_WF_RFCR1_DROP_CFEND BIT(7)
#define MT_WF_RFCR1_DROP_CFACK BIT(8)
#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4)
#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30)
#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8)
#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0)
#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
/* WFDMA0 */
#define MT_WFDMA0_BASE 0xd4000
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
#define MT_WFDMA0_RST MT_WFDMA0(0x100)
#define MT_WFDMA0_RST_LOGIC_RST BIT(4)
#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5)
#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2)
#define MT_MCU_CMD MT_WFDMA0(0x1f0)
#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0)
#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1)
#define MT_MCU_CMD_STOP_DMA BIT(2)
#define MT_MCU_CMD_RESET_DONE BIT(3)
#define MT_MCU_CMD_RECOVERY_DONE BIT(4)
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4)
#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200)
#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */
#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */
#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */
#define HOST_TX_DONE_INT_STS16 BIT(26)
#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204)
#define HOST_RX_DONE_INT_ENA0 BIT(0)
#define HOST_RX_DONE_INT_ENA1 BIT(1)
#define HOST_RX_DONE_INT_ENA2 BIT(2)
#define HOST_RX_DONE_INT_ENA3 BIT(3)
#define HOST_TX_DONE_INT_ENA0 BIT(4)
#define HOST_TX_DONE_INT_ENA1 BIT(5)
#define HOST_TX_DONE_INT_ENA2 BIT(6)
#define HOST_TX_DONE_INT_ENA3 BIT(7)
#define HOST_TX_DONE_INT_ENA4 BIT(8)
#define HOST_TX_DONE_INT_ENA5 BIT(9)
#define HOST_TX_DONE_INT_ENA6 BIT(10)
#define HOST_TX_DONE_INT_ENA7 BIT(11)
#define HOST_TX_DONE_INT_ENA8 BIT(12)
#define HOST_TX_DONE_INT_ENA9 BIT(13)
#define HOST_TX_DONE_INT_ENA10 BIT(14)
@@ -328,14 +36,10 @@
#define HOST_TX_DONE_INT_ENA12 BIT(16)
#define HOST_TX_DONE_INT_ENA13 BIT(17)
#define HOST_TX_DONE_INT_ENA14 BIT(18)
#define HOST_RX_COHERENT_EN BIT(20)
#define HOST_TX_COHERENT_EN BIT(21)
#define HOST_RX_DONE_INT_ENA4 BIT(22)
#define HOST_RX_DONE_INT_ENA5 BIT(23)
#define HOST_TX_DONE_INT_ENA16 BIT(26)
#define HOST_TX_DONE_INT_ENA17 BIT(27)
#define MCU2HOST_SW_INT_ENA BIT(29)
#define HOST_TX_DONE_INT_ENA18 BIT(30)
/* WFDMA interrupt */
#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
@@ -347,7 +51,6 @@
#define MT_INT_TX_DONE_MCU_WM HOST_TX_DONE_INT_ENA17
#define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16
#define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0
#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \
MT_INT_TX_DONE_FWDL)
@@ -355,56 +58,8 @@
MT_INT_TX_DONE_BAND0 | \
GENMASK(18, 4))
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9)
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30)
#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x520)
#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600)
#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604)
#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608)
#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c)
#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610)
#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614)
#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618)
#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640)
#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644)
#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0)
#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16)
#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680)
#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684)
#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688)
#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c)
#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690)
#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694)
#define MT_TX_RING_BASE MT_WFDMA0(0x300)
#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500)
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE 0xd7000
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_INFRA_CFG_BASE 0xfe000
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
@@ -414,121 +69,13 @@
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
#define MT_HIF_REMAP_BASE_L1 0x40000
#define MT_SWDEF_BASE 0x41f200
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
#define MT_SWDEF_ICAP_MODE 1
#define MT_SWDEF_SPECTRUM_MODE 2
#define MT_TOP_BASE 0x18060000
#define MT_TOP(ofs) (MT_TOP_BASE + (ofs))
#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10)
#define MT_TOP_LPCR_HOST_FW_OWN BIT(0)
#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1)
#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_CBTOP_RGU(ofs) (0x70002000 + (ofs))
#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
#define MT_HW_BOUND 0x70010020
#define MT_HW_CHIPID 0x70010200
#define MT_HW_REV 0x70010204
#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)
#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194)
#define MT_PCIE_MAC_PM_L0S_DIS BIT(8)
#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs))
#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004)
#define MT_DMASHDL_DMASHDL_BYPASS BIT(28)
#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008)
#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c)
#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16)
#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010)
#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16)
#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c)
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)
#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2))
#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0)
#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16)
#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2))
#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0)
#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8))
#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2))
#define MT_WFDMA_HOST_CONFIG 0x7c027030
#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6)
#define MT_UMAC(ofs) (0x74000000 + (ofs))
#define MT_UDMA_TX_QSEL MT_UMAC(0x008)
#define MT_FW_DL_EN BIT(3)
#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c)
#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0)
#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8)
#define MT_UDMA_WLCFG_0 MT_UMAC(0x18)
#define MT_WL_RX_AGG_TO GENMASK(7, 0)
#define MT_WL_RX_AGG_LMT GENMASK(15, 8)
#define MT_WL_TX_TMOUT_FUNC_EN BIT(16)
#define MT_WL_TX_DPH_CHK_EN BIT(17)
#define MT_WL_RX_MPSZ_PAD0 BIT(18)
#define MT_WL_RX_FLUSH BIT(19)
#define MT_TICK_1US_EN BIT(20)
#define MT_WL_RX_AGG_EN BIT(21)
#define MT_WL_RX_EN BIT(22)
#define MT_WL_TX_EN BIT(23)
#define MT_WL_RX_BUSY BIT(30)
#define MT_WL_TX_BUSY BIT(31)
#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20)
#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22)
#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24)
#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs))
#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090)
#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs))
#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208)
#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0)
#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2))
#define MT_CONN_STATUS 0x7c053c10
#define MT_WIFI_PATCH_DL_STATE BIT(0)
#define MT_CONN_ON_LPCTL 0x7c060010
#define PCIE_LPCR_HOST_OWN_SYNC BIT(2)
#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_PWR_ON BIT(0)
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0)
#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs))
#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028)
#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6)
#define MT_WF_SW_SER_DONE_SUSPEND BIT(7)
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12)
#endif
@@ -27,7 +27,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w)
struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
txrx_worker);
struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
queue_work(mdev->wq, &dev->pm.wake_work);
@@ -38,7 +38,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w)
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
}
static void mt7921s_unregister_device(struct mt7921_dev *dev)
static void mt7921s_unregister_device(struct mt792x_dev *dev)
{
struct mt76_connac_pm *pm = &dev->pm;
@@ -102,7 +102,7 @@ static int mt7921s_probe(struct sdio_func *func,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
.update_survey = mt7921_update_channel,
.update_survey = mt792x_update_channel,
};
static const struct mt76_bus_ops mt7921s_ops = {
.rr = mt76s_rr,
@@ -114,7 +114,7 @@ static int mt7921s_probe(struct sdio_func *func,
.rd_rp = mt76s_rd_rp,
.type = MT76_BUS_SDIO,
};
static const struct mt7921_hif_ops mt7921_sdio_ops = {
static const struct mt792x_hif_ops mt7921_sdio_ops = {
.init_reset = mt7921s_init_reset,
.reset = mt7921s_mac_reset,
.mcu_init = mt7921s_mcu_init,
@@ -122,13 +122,13 @@ static int mt7921s_probe(struct sdio_func *func,
.fw_own = mt7921s_mcu_fw_pmctrl,
};
struct ieee80211_ops *ops;
struct mt7921_dev *dev;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data,
&features);
ops = mt792x_get_mac80211_ops(&func->dev, &mt7921_ops,
(void *)id->driver_data, &features);
if (!ops)
return -ENOMEM;
@@ -136,7 +136,7 @@ static int mt7921s_probe(struct sdio_func *func,
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt7921_dev, mt76);
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7921_sdio_ops;
sdio_set_drvdata(func, dev);
@@ -196,7 +196,7 @@ error:
static void mt7921s_remove(struct sdio_func *func)
{
struct mt7921_dev *dev = sdio_get_drvdata(func);
struct mt792x_dev *dev = sdio_get_drvdata(func);
mt7921s_unregister_device(dev);
}
@@ -204,7 +204,7 @@ static void mt7921s_remove(struct sdio_func *func)
static int mt7921s_suspend(struct device *__dev)
{
struct sdio_func *func = dev_to_sdio_func(__dev);
struct mt7921_dev *dev = sdio_get_drvdata(func);
struct mt792x_dev *dev = sdio_get_drvdata(func);
struct mt76_connac_pm *pm = &dev->pm;
struct mt76_dev *mdev = &dev->mt76;
int err;
@@ -216,7 +216,7 @@ static int mt7921s_suspend(struct device *__dev)
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
err = mt7921_mcu_drv_pmctrl(dev);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto restore_suspend;
@@ -244,7 +244,7 @@ static int mt7921s_suspend(struct device *__dev)
mt76_worker_disable(&mdev->sdio.txrx_worker);
mt76_worker_disable(&mdev->sdio.net_worker);
err = mt7921_mcu_fw_pmctrl(dev);
err = mt792x_mcu_fw_pmctrl(dev);
if (err)
goto restore_txrx_worker;
@@ -269,7 +269,7 @@ restore_suspend:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
@@ -277,14 +277,14 @@ restore_suspend:
static int mt7921s_resume(struct device *__dev)
{
struct sdio_func *func = dev_to_sdio_func(__dev);
struct mt7921_dev *dev = sdio_get_drvdata(func);
struct mt792x_dev *dev = sdio_get_drvdata(func);
struct mt76_connac_pm *pm = &dev->pm;
struct mt76_dev *mdev = &dev->mt76;
int err;
clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state);
err = mt7921_mcu_drv_pmctrl(dev);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto failed;
@@ -302,7 +302,7 @@ failed:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
@@ -30,7 +30,7 @@ static u32 mt7921s_read_whcr(struct mt76_dev *dev)
return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
}
int mt7921s_wfsys_reset(struct mt7921_dev *dev)
int mt7921s_wfsys_reset(struct mt792x_dev *dev)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
u32 val, status;
@@ -71,7 +71,7 @@ int mt7921s_wfsys_reset(struct mt7921_dev *dev)
return 0;
}
int mt7921s_init_reset(struct mt7921_dev *dev)
int mt7921s_init_reset(struct mt792x_dev *dev)
{
set_bit(MT76_MCU_RESET, &dev->mphy.state);
@@ -91,7 +91,7 @@ int mt7921s_init_reset(struct mt7921_dev *dev)
return 0;
}
int mt7921s_mac_reset(struct mt7921_dev *dev)
int mt7921s_mac_reset(struct mt792x_dev *dev)
{
int err;
@@ -16,14 +16,14 @@ static int
mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *seq)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
enum mt7921_sdio_pkt_type type = MT7921_SDIO_CMD;
enum mt76_mcuq_id txq = MT_MCUQ_WM;
int ret, pad;
/* We just return in case firmware assertion to avoid blocking the
* common workqueue to run, for example, the coredump work might be
* blocked by mt7921_mac_work that is excuting register access via sdio
* blocked by mt792x_mac_work that is excuting register access via sdio
* bus.
*/
if (dev->fw_assert)
@@ -51,14 +51,14 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
return ret;
}
static u32 mt7921s_read_rm3r(struct mt7921_dev *dev)
static u32 mt7921s_read_rm3r(struct mt792x_dev *dev)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
return sdio_readl(sdio->func, MCR_D2HRM3R, NULL);
}
static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev)
static u32 mt7921s_clear_rm3r_drv_own(struct mt792x_dev *dev)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
u32 val;
@@ -71,7 +71,7 @@ static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev)
return val;
}
int mt7921s_mcu_init(struct mt7921_dev *dev)
int mt7921s_mcu_init(struct mt792x_dev *dev)
{
static const struct mt76_mcu_ops mt7921s_mcu_ops = {
.headroom = MT_SDIO_HDR_SIZE +
@@ -97,7 +97,7 @@ int mt7921s_mcu_init(struct mt7921_dev *dev)
return 0;
}
int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev)
{
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
@@ -133,7 +133,7 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
return 0;
}
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev)
{
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
@@ -31,7 +31,7 @@ static const struct nla_policy mt7921_tm_policy[NUM_MT7921_TM_ATTRS] = {
};
static int
mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req)
mt7921_tm_set(struct mt792x_dev *dev, struct mt7921_tm_cmd *req)
{
struct mt7921_rftest_cmd cmd = {
.action = req->action,
@@ -57,7 +57,7 @@ mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req)
pm->enable = false;
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
__mt7921_mcu_drv_pmctrl(dev);
__mt792x_mcu_drv_pmctrl(dev);
phy->test.state = MT76_TM_STATE_ON;
}
@@ -82,7 +82,7 @@ out:
}
static int
mt7921_tm_query(struct mt7921_dev *dev, struct mt7921_tm_cmd *req,
mt7921_tm_query(struct mt792x_dev *dev, struct mt7921_tm_cmd *req,
struct mt7921_tm_evt *evt_resp)
{
struct mt7921_rftest_cmd cmd = {
@@ -113,7 +113,7 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct nlattr *tb[NUM_MT76_TM_ATTRS];
struct mt76_phy *mphy = hw->priv;
struct mt7921_phy *phy = mphy->priv;
struct mt792x_phy *phy = mphy->priv;
int err;
if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||
@@ -150,7 +150,7 @@ int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
{
struct nlattr *tb[NUM_MT76_TM_ATTRS];
struct mt76_phy *mphy = hw->priv;
struct mt7921_phy *phy = mphy->priv;
struct mt792x_phy *phy = mphy->priv;
int err;
if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||
@@ -1,12 +0,0 @@
// 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
+81 -126
View File
@@ -24,88 +24,11 @@ static const struct usb_device_id mt7921u_device_table[] = {
{ },
};
static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr)
{
u32 ret;
mutex_lock(&dev->usb.usb_ctrl_mtx);
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return ret;
}
static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
}
static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr,
u32 mask, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask;
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return val;
}
static void mt7921u_copy(struct mt76_dev *dev, u32 offset,
const void *data, int len)
{
struct mt76_usb *usb = &dev->usb;
int ret, i = 0, batch_len;
const u8 *val = data;
len = round_up(len, 4);
mutex_lock(&usb->usb_ctrl_mtx);
while (i < len) {
batch_len = min_t(int, usb->data_len, len - i);
memcpy(usb->data, val + i, batch_len);
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
(offset + i) >> 16, offset + i,
usb->data, batch_len);
if (ret < 0)
break;
i += batch_len;
}
mutex_unlock(&usb->usb_ctrl_mtx);
}
int mt7921u_mcu_power_on(struct mt7921_dev *dev)
{
int ret;
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
0x0, 0x1, NULL, 0);
if (ret)
return ret;
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
MT_TOP_MISC2_FW_PWR_ON, 500)) {
dev_err(dev->mt76.dev, "Timeout for power on\n");
ret = -EIO;
}
return ret;
}
static int
mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *seq)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 pad, ep;
int ret;
@@ -131,7 +54,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
return ret;
}
static int mt7921u_mcu_init(struct mt7921_dev *dev)
static int mt7921u_mcu_init(struct mt792x_dev *dev)
{
static const struct mt76_mcu_ops mcu_ops = {
.headroom = MT_SDIO_HDR_SIZE +
@@ -155,22 +78,71 @@ static int mt7921u_mcu_init(struct mt7921_dev *dev)
return 0;
}
static int mt7921u_mac_reset(struct mt792x_dev *dev)
{
int err;
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
mt792xu_wfsys_reset(dev);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
err = mt76u_resume_rx(&dev->mt76);
if (err)
goto out;
err = mt792xu_mcu_power_on(dev);
if (err)
goto out;
err = mt792xu_dma_init(dev, false);
if (err)
goto out;
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7921_run_firmware(dev);
if (err)
goto out;
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7921_mcu_set_eeprom(dev);
if (err)
goto out;
err = mt7921_mac_init(dev);
if (err)
goto out;
err = __mt7921_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
return err;
}
static void mt7921u_stop(struct ieee80211_hw *hw)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mt76u_stop_tx(&dev->mt76);
mt7921_stop(hw);
}
static void mt7921u_cleanup(struct mt7921_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
mt7921u_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_queues_deinit(&dev->mt76);
}
static int mt7921u_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
@@ -189,31 +161,31 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
.update_survey = mt7921_update_channel,
.update_survey = mt792x_update_channel,
};
static const struct mt7921_hif_ops hif_ops = {
static const struct mt792x_hif_ops hif_ops = {
.mcu_init = mt7921u_mcu_init,
.init_reset = mt7921u_init_reset,
.init_reset = mt792xu_init_reset,
.reset = mt7921u_mac_reset,
};
static struct mt76_bus_ops bus_ops = {
.rr = mt7921u_rr,
.wr = mt7921u_wr,
.rmw = mt7921u_rmw,
.rr = mt792xu_rr,
.wr = mt792xu_wr,
.rmw = mt792xu_rmw,
.read_copy = mt76u_read_copy,
.write_copy = mt7921u_copy,
.write_copy = mt792xu_copy,
.type = MT76_BUS_USB,
};
struct usb_device *udev = interface_to_usbdev(usb_intf);
struct ieee80211_ops *ops;
struct ieee80211_hw *hw;
struct mt7921_dev *dev;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info,
&features);
ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops,
(void *)id->driver_info, &features);
if (!ops)
return -ENOMEM;
@@ -222,7 +194,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt7921_dev, mt76);
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &hif_ops;
@@ -240,12 +212,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
ret = mt7921u_wfsys_reset(dev);
ret = mt792xu_wfsys_reset(dev);
if (ret)
goto error;
}
ret = mt7921u_mcu_power_on(dev);
ret = mt792xu_mcu_power_on(dev);
if (ret)
goto error;
@@ -257,7 +229,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
if (ret)
goto error;
ret = mt7921u_dma_init(dev, false);
ret = mt792xu_dma_init(dev, false);
if (ret)
goto error;
@@ -282,27 +254,10 @@ error:
return ret;
}
static void mt7921u_disconnect(struct usb_interface *usb_intf)
{
struct mt7921_dev *dev = usb_get_intfdata(usb_intf);
cancel_work_sync(&dev->init_work);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return;
mt76_unregister_device(&dev->mt76);
mt7921u_cleanup(dev);
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
mt76_free_device(&dev->mt76);
}
#ifdef CONFIG_PM
static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
{
struct mt7921_dev *dev = usb_get_intfdata(intf);
struct mt792x_dev *dev = usb_get_intfdata(intf);
struct mt76_connac_pm *pm = &dev->pm;
int err;
@@ -322,14 +277,14 @@ failed:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
static int mt7921u_resume(struct usb_interface *intf)
{
struct mt7921_dev *dev = usb_get_intfdata(intf);
struct mt792x_dev *dev = usb_get_intfdata(intf);
struct mt76_connac_pm *pm = &dev->pm;
bool reinit = true;
int err, i;
@@ -349,8 +304,8 @@ static int mt7921u_resume(struct usb_interface *intf)
msleep(20);
}
if (reinit || mt7921_dma_need_reinit(dev)) {
err = mt7921u_dma_init(dev, true);
if (reinit || mt792x_dma_need_reinit(dev)) {
err = mt792xu_dma_init(dev, true);
if (err)
goto failed;
}
@@ -364,7 +319,7 @@ failed:
pm->suspended = false;
if (err < 0)
mt7921_reset(&dev->mt76);
mt792x_reset(&dev->mt76);
return err;
}
@@ -378,7 +333,7 @@ static struct usb_driver mt7921u_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7921u_device_table,
.probe = mt7921u_probe,
.disconnect = mt7921u_disconnect,
.disconnect = mt792xu_disconnect,
#ifdef CONFIG_PM
.suspend = mt7921u_suspend,
.resume = mt7921u_resume,
@@ -1,255 +0,0 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2022 MediaTek Inc.
*
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "mt7921.h"
#include "mcu.h"
#include "../mt76_connac2_mac.h"
static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
{
u32 ret;
mutex_lock(&dev->usb.usb_ctrl_mtx);
ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return ret;
}
static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
___mt76u_wr(dev, MT_VEND_WRITE,
USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
}
static void mt7921u_dma_prefetch(struct mt7921_dev *dev)
{
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
MT_WPDMA0_BASE_PTR_MASK, 0x80);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
MT_WPDMA0_BASE_PTR_MASK, 0xc0);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
MT_WPDMA0_BASE_PTR_MASK, 0x100);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
MT_WPDMA0_BASE_PTR_MASK, 0x140);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
MT_WPDMA0_BASE_PTR_MASK, 0x180);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
MT_WPDMA0_BASE_PTR_MASK, 0x280);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
MT_WPDMA0_BASE_PTR_MASK, 0x2c0);
}
static void mt7921u_wfdma_init(struct mt7921_dev *dev)
{
mt7921u_dma_prefetch(dev);
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
mt76_set(dev, MT_UWFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
/* disable dmashdl */
mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0,
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
}
static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev)
{
if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
return -ETIMEDOUT;
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
return 0;
}
static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
{
u32 val;
/* usb endpoint reset opt
* bits[4,9]: out blk ep 4-9
* bits[20,21]: in blk ep 4-5
* bits[22]: in int ep 6
*/
val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
if (reset)
val |= GENMASK(9, 4) | GENMASK(22, 20);
else
val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
}
int mt7921u_dma_init(struct mt7921_dev *dev, bool resume)
{
int err;
mt7921u_wfdma_init(dev);
mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
mt76_set(dev, MT_UDMA_WLCFG_0,
MT_WL_RX_EN | MT_WL_TX_EN |
MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
mt76_clear(dev, MT_UDMA_WLCFG_0,
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
if (resume)
return 0;
err = mt7921u_dma_rx_evt_ep4(dev);
if (err)
return err;
mt7921u_epctl_rst_opt(dev, false);
return 0;
}
int mt7921u_wfsys_reset(struct mt7921_dev *dev)
{
u32 val;
int i;
mt7921u_epctl_rst_opt(dev, false);
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
usleep_range(10, 20);
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) {
val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
break;
msleep(100);
}
if (i == MT7921_WFSYS_INIT_RETRY_COUNT)
return -ETIMEDOUT;
return 0;
}
int mt7921u_init_reset(struct mt7921_dev *dev)
{
set_bit(MT76_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
mt7921u_wfsys_reset(dev);
clear_bit(MT76_RESET, &dev->mphy.state);
return mt76u_resume_rx(&dev->mt76);
}
int mt7921u_mac_reset(struct mt7921_dev *dev)
{
int err;
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
mt7921u_wfsys_reset(dev);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
err = mt76u_resume_rx(&dev->mt76);
if (err)
goto out;
err = mt7921u_mcu_power_on(dev);
if (err)
goto out;
err = mt7921u_dma_init(dev, false);
if (err)
goto out;
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7921_run_firmware(dev);
if (err)
goto out;
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7921_mcu_set_eeprom(dev);
if (err)
goto out;
err = mt7921_mac_init(dev);
if (err)
goto out;
err = __mt7921_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
return err;
}
+367
View File
@@ -0,0 +1,367 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT792X_H
#define __MT792X_H
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include "mt76_connac_mcu.h"
#include "mt792x_regs.h"
#include "mt792x_acpi_sar.h"
#define MT792x_PM_TIMEOUT (HZ / 12)
#define MT792x_HW_SCAN_TIMEOUT (HZ / 10)
#define MT792x_MAX_INTERFACES 4
#define MT792x_WTBL_SIZE 20
#define MT792x_WTBL_RESERVED (MT792x_WTBL_SIZE - 1)
#define MT792x_WTBL_STA (MT792x_WTBL_RESERVED - MT792x_MAX_INTERFACES)
#define MT792x_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT792x_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT792x_FW_TAG_FEATURE 4
#define MT792x_FW_CAP_CNM BIT(7)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 11
#define MT792x_WATCHDOG_TIME (HZ / 4)
#define MT792x_DRV_OWN_RETRY_COUNT 10
#define MT792x_MCU_INIT_RETRY_COUNT 10
#define MT792x_WFSYS_INIT_RETRY_COUNT 2
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
struct mt792x_vif;
struct mt792x_sta;
struct mt792x_realease_info {
__le16 len;
u8 pad_len;
u8 tag;
} __packed;
struct mt792x_fw_features {
u8 segment;
u8 data;
u8 rsv[14];
} __packed;
enum {
MT792x_CLC_POWER,
MT792x_CLC_CHAN,
MT792x_CLC_MAX_NUM,
};
DECLARE_EWMA(avg_signal, 10, 8)
struct mt792x_sta {
struct mt76_wcid wcid; /* must be first */
struct mt792x_vif *vif;
u32 airtime_ac[8];
int ack_signal;
struct ewma_avg_signal avg_ack_signal;
unsigned long last_txs;
struct mt76_connac_sta_key_conf bip;
};
DECLARE_EWMA(rssi, 10, 8);
struct mt792x_vif {
struct mt76_vif mt76; /* must be first */
struct mt792x_sta sta;
struct mt792x_sta *wep_sta;
struct mt792x_phy *phy;
struct ewma_rssi rssi;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct ieee80211_chanctx_conf *ctx;
};
struct mt792x_phy {
struct mt76_phy *mt76;
struct mt792x_dev *dev;
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
u64 omac_mask;
u16 noise;
s16 coverage_class;
u8 slottime;
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mt76_mib_stats mib;
u8 sta_work_count;
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
#ifdef CONFIG_ACPI
void *acpisar;
#endif
void *clc[MT792x_CLC_MAX_NUM];
struct work_struct roc_work;
struct timer_list roc_timer;
wait_queue_head_t roc_wait;
u8 roc_token_id;
bool roc_grant;
};
struct mt792x_irq_map {
u32 host_irq_enable;
struct {
u32 all_complete_mask;
u32 mcu_complete_mask;
} tx;
struct {
u32 data_complete_mask;
u32 wm_complete_mask;
u32 wm2_complete_mask;
} rx;
};
#define mt792x_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
#define mt792x_dev_reset(dev) ((dev)->hif_ops->reset(dev))
#define mt792x_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev))
#define __mt792x_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev))
#define __mt792x_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev))
struct mt792x_hif_ops {
int (*init_reset)(struct mt792x_dev *dev);
int (*reset)(struct mt792x_dev *dev);
int (*mcu_init)(struct mt792x_dev *dev);
int (*drv_own)(struct mt792x_dev *dev);
int (*fw_own)(struct mt792x_dev *dev);
};
struct mt792x_dev {
union { /* must be first */
struct mt76_dev mt76;
struct mt76_phy mphy;
};
const struct mt76_bus_ops *bus_ops;
struct mt792x_phy phy;
struct work_struct reset_work;
bool hw_full_reset:1;
bool hw_init_done:1;
bool fw_assert:1;
bool has_eht:1;
struct work_struct init_work;
u8 fw_debug;
u8 fw_features;
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
const struct mt792x_hif_ops *hif_ops;
const struct mt792x_irq_map *irq_map;
struct work_struct ipv6_ns_work;
/* IPv6 addresses for WoWLAN */
struct sk_buff_head ipv6_ns_list;
enum environment_cap country_ie_env;
u32 backup_l1;
u32 backup_l2;
};
static inline struct mt792x_dev *
mt792x_hw_dev(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return container_of(phy->dev, struct mt792x_dev, mt76);
}
static inline struct mt792x_phy *
mt792x_hw_phy(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return phy->priv;
}
static inline void
mt792x_get_status_freq_info(struct mt76_rx_status *status, u8 chfreq)
{
if (chfreq > 180) {
status->band = NL80211_BAND_6GHZ;
chfreq = (chfreq - 181) * 4 + 1;
} else if (chfreq > 14) {
status->band = NL80211_BAND_5GHZ;
} else {
status->band = NL80211_BAND_2GHZ;
}
status->freq = ieee80211_channel_to_frequency(chfreq, status->band);
}
static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev)
{
return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
}
#define mt792x_mutex_acquire(dev) \
mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm)
#define mt792x_mutex_release(dev) \
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
void mt792x_pm_wake_work(struct work_struct *work);
void mt792x_pm_power_save_work(struct work_struct *work);
void mt792x_reset(struct mt76_dev *mdev);
void mt792x_update_channel(struct mt76_phy *mphy);
void mt792x_mac_reset_counters(struct mt792x_phy *phy);
void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band);
void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb);
struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
bool unicast);
void mt792x_mac_update_mib_stats(struct mt792x_phy *phy);
void mt792x_mac_set_timeing(struct mt792x_phy *phy);
void mt792x_mac_work(struct work_struct *work);
void mt792x_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
struct sk_buff *skb);
int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params);
int mt792x_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u64 timestamp);
void mt792x_tx_worker(struct mt76_worker *w);
void mt792x_roc_timer(struct timer_list *timer);
void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx);
void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx);
void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled);
void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 sset, u8 *data);
int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int sset);
void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data);
void mt792x_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct station_info *sinfo);
void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class);
void mt792x_dma_cleanup(struct mt792x_dev *dev);
int mt792x_dma_enable(struct mt792x_dev *dev);
int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force);
int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev);
int mt792x_dma_disable(struct mt792x_dev *dev, bool force);
irqreturn_t mt792x_irq_handler(int irq, void *dev_instance);
void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
int mt792x_poll_tx(struct napi_struct *napi, int budget);
int mt792x_poll_rx(struct napi_struct *napi, int budget);
void mt792x_irq_tasklet(unsigned long data);
int mt792x_wfsys_reset(struct mt792x_dev *dev);
int mt792x_tx_stats_show(struct seq_file *file, void *data);
int mt792x_queues_acq(struct seq_file *s, void *data);
int mt792x_queues_read(struct seq_file *s, void *data);
int mt792x_pm_stats(struct seq_file *s, void *data);
int mt792x_pm_idle_timeout_set(void *data, u64 val);
int mt792x_pm_idle_timeout_get(void *data, u64 *val);
int mt792x_init_wiphy(struct ieee80211_hw *hw);
struct ieee80211_ops *
mt792x_get_mac80211_ops(struct device *dev,
const struct ieee80211_ops *mac80211_ops,
void *drv_data, u8 *fw_features);
int mt792x_init_wcid(struct mt792x_dev *dev);
int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev);
int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev);
static inline char *mt792x_ram_name(struct mt792x_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7922:
return MT7922_FIRMWARE_WM;
default:
return MT7921_FIRMWARE_WM;
}
}
static inline char *mt792x_patch_name(struct mt792x_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7922:
return MT7922_ROM_PATCH;
default:
return MT7921_ROM_PATCH;
}
}
int mt792x_load_firmware(struct mt792x_dev *dev);
/* usb */
#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f)
#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e)
int mt792xu_dma_init(struct mt792x_dev *dev, bool resume);
int mt792xu_mcu_power_on(struct mt792x_dev *dev);
int mt792xu_wfsys_reset(struct mt792x_dev *dev);
int mt792xu_init_reset(struct mt792x_dev *dev);
u32 mt792xu_rr(struct mt76_dev *dev, u32 addr);
void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val);
u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len);
void mt792xu_disconnect(struct usb_interface *usb_intf);
int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);
int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);
int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev);
#ifdef CONFIG_ACPI
int mt792x_init_acpi_sar(struct mt792x_dev *dev);
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default);
u8 mt792x_acpi_get_flags(struct mt792x_phy *phy);
#else
static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev)
{
return 0;
}
static inline int mt792x_init_acpi_sar_power(struct mt792x_phy *phy,
bool set_default)
{
return 0;
}
static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
{
return 0;
}
#endif
#endif /* __MT7925_H */
@@ -1,15 +1,15 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2022 MediaTek Inc. */
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/acpi.h>
#include "mt7921.h"
#include "mt792x.h"
static int
mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
{
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *sar_root, *sar_unit;
struct mt76_dev *mdev = &dev->mt76;
union acpi_object *sar_root;
acpi_handle root, handle;
acpi_status status;
u32 i = 0;
@@ -45,18 +45,20 @@ mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
goto free;
}
}
if (len)
*len = sar_root->package.count;
for (i = 0; i < sar_root->package.count; i++) {
sar_unit = &sar_root->package.elements[i];
union acpi_object *sar_unit = &sar_root->package.elements[i];
if (sar_unit->type != ACPI_TYPE_INTEGER)
break;
*(*tbl + i) = (u8)sar_unit->integer.value;
}
ret = (i == sar_root->package.count) ? 0 : -EINVAL;
ret = i == sar_root->package.count ? 0 : -EINVAL;
free:
kfree(sar_root);
@@ -64,36 +66,37 @@ free:
}
/* MTCL : Country List Table for 6G band */
static int
mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
static void
mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
{
*version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
? 1 : 2;
return 0;
if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0)
*version = 1;
else
*version = 2;
}
/* MTDS : Dynamic SAR Power Table */
static int
mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
{
int len, ret, sarlen, prelen, tblcnt;
bool enable;
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
if (ret)
return ret;
/* Table content validation */
switch (version) {
case 1:
enable = ((struct mt7921_asar_dyn *)*table)->enable;
sarlen = sizeof(struct mt7921_asar_dyn_limit);
prelen = sizeof(struct mt7921_asar_dyn);
enable = ((struct mt792x_asar_dyn *)*table)->enable;
sarlen = sizeof(struct mt792x_asar_dyn_limit);
prelen = sizeof(struct mt792x_asar_dyn);
break;
case 2:
enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
prelen = sizeof(struct mt7921_asar_dyn_v2);
enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
prelen = sizeof(struct mt792x_asar_dyn_v2);
break;
default:
return -EINVAL;
@@ -101,88 +104,89 @@ mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
tblcnt = (len - prelen) / sarlen;
if (!enable ||
tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
ret = -EINVAL;
tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
return -EINVAL;
return ret;
return 0;
}
/* MTGS : Geo SAR Power Table */
static int
mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
{
int len, ret = 0, sarlen, prelen, tblcnt;
int len, ret, sarlen, prelen, tblcnt;
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
if (ret)
return ret;
/* Table content validation */
switch (version) {
case 1:
sarlen = sizeof(struct mt7921_asar_geo_limit);
prelen = sizeof(struct mt7921_asar_geo);
sarlen = sizeof(struct mt792x_asar_geo_limit);
prelen = sizeof(struct mt792x_asar_geo);
break;
case 2:
sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
prelen = sizeof(struct mt7921_asar_geo_v2);
sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
prelen = sizeof(struct mt792x_asar_geo_v2);
break;
default:
return -EINVAL;
}
tblcnt = (len - prelen) / sarlen;
if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
ret = -EINVAL;
if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
return -EINVAL;
return ret;
return 0;
}
/* MTFG : Flag Table */
static int
mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table)
mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table)
{
int len, ret;
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len);
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len);
if (ret)
return ret;
if (len < MT7921_ASAR_MIN_FG)
ret = -EINVAL;
if (len < MT792x_ASAR_MIN_FG)
return -EINVAL;
return ret;
return 0;
}
int mt7921_init_acpi_sar(struct mt7921_dev *dev)
int mt792x_init_acpi_sar(struct mt792x_dev *dev)
{
struct mt7921_acpi_sar *asar;
struct mt792x_acpi_sar *asar;
int ret;
asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
if (!asar)
return -ENOMEM;
mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
/* MTDS is mandatory. Return error if table is invalid */
ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
if (ret) {
devm_kfree(dev->mt76.dev, asar->dyn);
devm_kfree(dev->mt76.dev, asar->countrylist);
devm_kfree(dev->mt76.dev, asar);
return ret;
}
/* MTGS is optional */
ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
if (ret) {
devm_kfree(dev->mt76.dev, asar->geo);
asar->geo = NULL;
}
/* MTFG is optional */
ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
if (ret) {
devm_kfree(dev->mt76.dev, asar->fg);
asar->fg = NULL;
@@ -191,13 +195,14 @@ int mt7921_init_acpi_sar(struct mt7921_dev *dev)
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar);
static s8
mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
enum nl80211_band band, s8 dyn_power)
{
struct mt7921_acpi_sar *asar = phy->acpisar;
struct mt7921_asar_geo_band *band_pwr;
struct mt792x_acpi_sar *asar = phy->acpisar;
struct mt792x_asar_geo_band *band_pwr;
s8 geo_power;
u8 idx, max;
@@ -248,12 +253,12 @@ mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
}
static s8
mt7921_asar_range_pwr(struct mt7921_phy *phy,
mt792x_asar_range_pwr(struct mt792x_phy *phy,
const struct cfg80211_sar_freq_ranges *range,
u8 idx)
{
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
struct mt7921_acpi_sar *asar = phy->acpisar;
struct mt792x_acpi_sar *asar = phy->acpisar;
u8 *limit, band, max;
if (!capa)
@@ -277,10 +282,10 @@ mt7921_asar_range_pwr(struct mt7921_phy *phy,
else
band = NL80211_BAND_2GHZ;
return mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
}
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
{
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
int i;
@@ -300,41 +305,46 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
continue;
frp->power = min_t(s8, set_default ? 127 : frp->power,
mt7921_asar_range_pwr(phy, frp->range, i));
mt792x_asar_range_pwr(phy, frp->range, i));
}
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power);
u8 mt7921_acpi_get_flags(struct mt7921_phy *phy)
u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
{
struct mt7921_asar_fg *fg;
struct mt792x_acpi_sar *acpisar = phy->acpisar;
struct mt792x_asar_fg *fg;
struct {
u8 acpi_idx;
u8 chip_idx;
} map[] = {
{1, 1},
{4, 2},
{ 1, 1 },
{ 4, 2 },
};
u8 flags = BIT(0);
int i, j;
if (!phy->acpisar)
if (!acpisar)
return 0;
fg = phy->acpisar->fg;
fg = acpisar->fg;
if (!fg)
return flags;
/* pickup necessary settings per device and
* translate the index of bitmap for chip command.
*/
for (i = 0; i < fg->nr_flag; i++)
for (j = 0; j < ARRAY_SIZE(map); j++)
for (i = 0; i < fg->nr_flag; i++) {
for (j = 0; j < ARRAY_SIZE(map); j++) {
if (fg->flag[i] == map[j].acpi_idx) {
flags |= BIT(map[j].chip_idx);
break;
}
}
}
return flags;
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
@@ -0,0 +1,105 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT7921_ACPI_SAR_H
#define __MT7921_ACPI_SAR_H
#define MT792x_ASAR_MIN_DYN 1
#define MT792x_ASAR_MAX_DYN 8
#define MT792x_ASAR_MIN_GEO 3
#define MT792x_ASAR_MAX_GEO 8
#define MT792x_ASAR_MIN_FG 8
#define MT792x_ACPI_MTCL "MTCL"
#define MT792x_ACPI_MTDS "MTDS"
#define MT792x_ACPI_MTGS "MTGS"
#define MT792x_ACPI_MTFG "MTFG"
struct mt792x_asar_dyn_limit {
u8 idx;
u8 frp[5];
} __packed;
struct mt792x_asar_dyn {
u8 names[4];
u8 enable;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit, tbl);
} __packed;
struct mt792x_asar_dyn_limit_v2 {
u8 idx;
u8 frp[11];
} __packed;
struct mt792x_asar_dyn_v2 {
u8 names[4];
u8 enable;
u8 rsvd;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit_v2, tbl);
} __packed;
struct mt792x_asar_geo_band {
u8 pwr;
u8 offset;
} __packed;
struct mt792x_asar_geo_limit {
u8 idx;
/* 0:2G, 1:5G */
struct mt792x_asar_geo_band band[2];
} __packed;
struct mt792x_asar_geo {
u8 names[4];
u8 version;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit, tbl);
} __packed;
struct mt792x_asar_geo_limit_v2 {
u8 idx;
/* 0:2G, 1:5G, 2:6G */
struct mt792x_asar_geo_band band[3];
} __packed;
struct mt792x_asar_geo_v2 {
u8 names[4];
u8 version;
u8 rsvd;
u8 nr_tbl;
DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl);
} __packed;
struct mt792x_asar_cl {
u8 names[4];
u8 version;
u8 mode_6g;
u8 cl6g[6];
} __packed;
struct mt792x_asar_fg {
u8 names[4];
u8 version;
u8 rsvd;
u8 nr_flag;
u8 rsvd1;
u8 flag[];
} __packed;
struct mt792x_acpi_sar {
u8 ver;
union {
struct mt792x_asar_dyn *dyn;
struct mt792x_asar_dyn_v2 *dyn_v2;
};
union {
struct mt792x_asar_geo *geo;
struct mt792x_asar_geo_v2 *geo_v2;
};
struct mt792x_asar_cl *countrylist;
struct mt792x_asar_fg *fg;
};
#endif
@@ -0,0 +1,844 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/module.h>
#include <linux/firmware.h>
#include "mt792x.h"
#include "dma.h"
static const struct ieee80211_iface_limit if_limits[] = {
{
.max = MT792x_MAX_INTERFACES,
.types = BIT(NL80211_IFTYPE_STATION)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP)
}
};
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = MT792x_MAX_INTERFACES,
.num_different_channels = 1,
.beacon_int_infra_match = true,
},
};
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO)
}
};
static const struct ieee80211_iface_combination if_comb_chanctx[] = {
{
.limits = if_limits_chanctx,
.n_limits = ARRAY_SIZE(if_limits_chanctx),
.max_interfaces = 2,
.num_different_channels = 2,
.beacon_int_infra_match = false,
}
};
void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt76_phy *mphy = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
int qid;
if (control->sta) {
struct mt792x_sta *sta;
sta = (struct mt792x_sta *)control->sta->drv_priv;
wcid = &sta->wcid;
}
if (vif && !control->sta) {
struct mt792x_vif *mvif;
mvif = (struct mt792x_vif *)vif->drv_priv;
wcid = &mvif->sta.wcid;
}
if (mt76_connac_pm_ref(mphy, &dev->pm)) {
mt76_tx(mphy, control->sta, wcid, skb);
mt76_connac_pm_unref(mphy, &dev->pm);
return;
}
qid = skb_get_queue_mapping(skb);
if (qid >= MT_TXQ_PSD) {
qid = IEEE80211_AC_BE;
skb_set_queue_mapping(skb, qid);
}
mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);
}
EXPORT_SYMBOL_GPL(mt792x_tx);
void mt792x_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_sta *msta = &mvif->sta;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt792x_phy *phy = mt792x_hw_phy(hw);
int idx = msta->wcid.idx;
mt792x_mutex_acquire(dev);
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mt792x_mutex_release(dev);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
EXPORT_SYMBOL_GPL(mt792x_remove_interface);
int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
/* no need to update right away, we'll get BSS_CHANGED_QOS */
queue = mt76_connac_lmac_mapping(queue);
mvif->queue_params[queue] = *params;
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_conf_tx);
int mt792x_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct mt792x_phy *phy = mt792x_hw_phy(hw);
struct mt76_mib_stats *mib = &phy->mib;
mt792x_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;
mt792x_mutex_release(phy->dev);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_get_stats);
u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
u8 omac_idx = mvif->mt76.omac_idx;
union {
u64 t64;
u32 t32[2];
} tsf;
u16 n;
mt792x_mutex_acquire(dev);
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
/* TSF software read */
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));
mt792x_mutex_release(dev);
return tsf.t64;
}
EXPORT_SYMBOL_GPL(mt792x_get_tsf);
void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u64 timestamp)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
u8 omac_idx = mvif->mt76.omac_idx;
union {
u64 t64;
u32 t32[2];
} tsf = { .t64 = timestamp, };
u16 n;
mt792x_mutex_acquire(dev);
n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;
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(0, n), MT_LPON_TCR_SW_WRITE);
mt792x_mutex_release(dev);
}
EXPORT_SYMBOL_GPL(mt792x_set_tsf);
void mt792x_tx_worker(struct mt76_worker *w)
{
struct mt792x_dev *dev = container_of(w, struct mt792x_dev,
mt76.tx_worker);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
queue_work(dev->mt76.wq, &dev->pm.wake_work);
return;
}
mt76_txq_schedule_all(&dev->mphy);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt792x_tx_worker);
void mt792x_roc_timer(struct timer_list *timer)
{
struct mt792x_phy *phy = from_timer(phy, timer, roc_timer);
ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
}
EXPORT_SYMBOL_GPL(mt792x_roc_timer);
void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
wait_event_timeout(dev->mt76.tx_wait,
!mt76_has_tx_pending(&dev->mphy), HZ / 2);
}
EXPORT_SYMBOL_GPL(mt792x_flush);
int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mvif->ctx = ctx;
mutex_unlock(&dev->mt76.mutex);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_assign_vif_chanctx);
void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mvif->ctx = NULL;
mutex_unlock(&dev->mt76.mutex);
}
EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx);
void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt76_dev *mdev = &dev->mt76;
device_set_wakeup_enable(mdev->dev, enabled);
}
EXPORT_SYMBOL_GPL(mt792x_set_wakeup);
static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = {
/* tx counters */
"tx_ampdu_cnt",
"tx_mpdu_attempts",
"tx_mpdu_success",
"tx_pkt_ebf_cnt",
"tx_pkt_ibf_cnt",
"tx_ampdu_len:0-1",
"tx_ampdu_len:2-10",
"tx_ampdu_len:11-19",
"tx_ampdu_len:20-28",
"tx_ampdu_len:29-37",
"tx_ampdu_len:38-46",
"tx_ampdu_len:47-55",
"tx_ampdu_len:56-79",
"tx_ampdu_len:80-103",
"tx_ampdu_len:104-127",
"tx_ampdu_len:128-151",
"tx_ampdu_len:152-175",
"tx_ampdu_len:176-199",
"tx_ampdu_len:200-223",
"tx_ampdu_len:224-247",
"ba_miss_count",
"tx_beamformer_ppdu_iBF",
"tx_beamformer_ppdu_eBF",
"tx_beamformer_rx_feedback_all",
"tx_beamformer_rx_feedback_he",
"tx_beamformer_rx_feedback_vht",
"tx_beamformer_rx_feedback_ht",
"tx_msdu_pack_1",
"tx_msdu_pack_2",
"tx_msdu_pack_3",
"tx_msdu_pack_4",
"tx_msdu_pack_5",
"tx_msdu_pack_6",
"tx_msdu_pack_7",
"tx_msdu_pack_8",
/* rx counters */
"rx_mpdu_cnt",
"rx_ampdu_cnt",
"rx_ampdu_bytes_cnt",
"rx_ba_cnt",
/* per vif counters */
"v_tx_mode_cck",
"v_tx_mode_ofdm",
"v_tx_mode_ht",
"v_tx_mode_ht_gf",
"v_tx_mode_vht",
"v_tx_mode_he_su",
"v_tx_mode_he_ext_su",
"v_tx_mode_he_tb",
"v_tx_mode_he_mu",
"v_tx_mode_eht_su",
"v_tx_mode_eht_trig",
"v_tx_mode_eht_mu",
"v_tx_bw_20",
"v_tx_bw_40",
"v_tx_bw_80",
"v_tx_bw_160",
"v_tx_mcs_0",
"v_tx_mcs_1",
"v_tx_mcs_2",
"v_tx_mcs_3",
"v_tx_mcs_4",
"v_tx_mcs_5",
"v_tx_mcs_6",
"v_tx_mcs_7",
"v_tx_mcs_8",
"v_tx_mcs_9",
"v_tx_mcs_10",
"v_tx_mcs_11",
"v_tx_mcs_12",
"v_tx_mcs_13",
"v_tx_nss_1",
"v_tx_nss_2",
"v_tx_nss_3",
"v_tx_nss_4",
};
void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 sset, u8 *data)
{
if (sset != ETH_SS_STATS)
return;
memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));
data += sizeof(mt792x_gstrings_stats);
page_pool_ethtool_stats_get_strings(data);
}
EXPORT_SYMBOL_GPL(mt792x_get_et_strings);
int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int sset)
{
if (sset != ETH_SS_STATS)
return 0;
return ARRAY_SIZE(mt792x_gstrings_stats) +
page_pool_ethtool_stats_get_count();
}
EXPORT_SYMBOL_GPL(mt792x_get_et_sset_count);
static void
mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
{
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
struct mt76_ethtool_worker_info *wi = wi_data;
if (msta->vif->mt76.idx != wi->idx)
return;
mt76_ethtool_worker(wi, &msta->wcid.stats, true);
}
void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
int stats_size = ARRAY_SIZE(mt792x_gstrings_stats);
struct mt792x_phy *phy = mt792x_hw_phy(hw);
struct mt792x_dev *dev = phy->dev;
struct mt76_mib_stats *mib = &phy->mib;
struct mt76_ethtool_worker_info wi = {
.data = data,
.idx = mvif->mt76.idx,
};
int i, ei = 0;
mt792x_mutex_acquire(dev);
mt792x_mac_update_mib_stats(phy);
data[ei++] = mib->tx_ampdu_cnt;
data[ei++] = mib->tx_mpdu_attempts_cnt;
data[ei++] = mib->tx_mpdu_success_cnt;
data[ei++] = mib->tx_pkt_ebf_cnt;
data[ei++] = mib->tx_pkt_ibf_cnt;
/* Tx ampdu stat */
for (i = 0; i < 15; i++)
data[ei++] = phy->mt76->aggr_stats[i];
data[ei++] = phy->mib.ba_miss_cnt;
/* Tx Beamformer monitor */
data[ei++] = mib->tx_bf_ibf_ppdu_cnt;
data[ei++] = mib->tx_bf_ebf_ppdu_cnt;
/* Tx Beamformer Rx feedback monitor */
data[ei++] = mib->tx_bf_rx_fb_all_cnt;
data[ei++] = mib->tx_bf_rx_fb_he_cnt;
data[ei++] = mib->tx_bf_rx_fb_vht_cnt;
data[ei++] = mib->tx_bf_rx_fb_ht_cnt;
/* Tx amsdu info (pack-count histogram) */
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)
data[ei++] = mib->tx_amsdu[i];
/* rx counters */
data[ei++] = mib->rx_mpdu_cnt;
data[ei++] = mib->rx_ampdu_cnt;
data[ei++] = mib->rx_ampdu_bytes_cnt;
data[ei++] = mib->rx_ba_cnt;
/* Add values for all stations owned by this vif */
wi.initial_stat_idx = ei;
ieee80211_iterate_stations_atomic(hw, mt792x_ethtool_worker, &wi);
mt792x_mutex_release(dev);
if (!wi.sta_count)
return;
ei += wi.worker_stat_count;
mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);
stats_size += page_pool_ethtool_stats_get_count();
if (ei != stats_size)
dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei,
stats_size);
}
EXPORT_SYMBOL_GPL(mt792x_get_et_stats);
void mt792x_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
struct rate_info *txrate = &msta->wcid.rate;
if (!txrate->legacy && !txrate->flags)
return;
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
}
sinfo->tx_failed = msta->wcid.stats.tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
sinfo->tx_retries = msta->wcid.stats.tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
sinfo->ack_signal = (s8)msta->ack_signal;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
}
EXPORT_SYMBOL_GPL(mt792x_sta_statistics);
void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
{
struct mt792x_phy *phy = mt792x_hw_phy(hw);
struct mt792x_dev *dev = phy->dev;
mt792x_mutex_acquire(dev);
phy->coverage_class = max_t(s16, coverage_class, 0);
mt792x_mac_set_timeing(phy);
mt792x_mutex_release(dev);
}
EXPORT_SYMBOL_GPL(mt792x_set_coverage_class);
int mt792x_init_wiphy(struct ieee80211_hw *hw)
{
struct mt792x_phy *phy = mt792x_hw_phy(hw);
struct mt792x_dev *dev = phy->dev;
struct wiphy *wiphy = hw->wiphy;
hw->queues = 4;
if (dev->has_eht) {
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT;
} else {
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
}
hw->netdev_features = NETIF_F_RXCSUM;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
phy->slottime = 9;
hw->sta_data_size = sizeof(struct mt792x_sta);
hw->vif_data_size = sizeof(struct mt792x_vif);
if (dev->fw_features & MT792x_FW_CAP_CNM) {
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wiphy->iface_combinations = if_comb_chanctx;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
} else {
wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
wiphy->iface_combinations = if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
}
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
WIPHY_FLAG_4ADDR_STATION);
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
wiphy->max_remain_on_channel_duration = 5000;
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_scan_ssids = 4;
wiphy->max_sched_scan_plan_interval =
MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;
wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
wiphy->max_sched_scan_reqs = 1;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
WIPHY_FLAG_SPLIT_SCAN_6GHZ;
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, CONNECTION_MONITOR);
if (dev->pm.enable)
ieee80211_hw_set(hw, CONNECTION_MONITOR);
hw->max_tx_fragments = 4;
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_wiphy);
static u8
mt792x_get_offload_capability(struct device *dev, const char *fw_wm)
{
const struct mt76_connac2_fw_trailer *hdr;
struct mt792x_realease_info *rel_info;
const struct firmware *fw;
int ret, i, offset = 0;
const u8 *data, *end;
u8 offload_caps = 0;
ret = request_firmware(&fw, fw_wm, dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev, "Invalid firmware\n");
goto out;
}
data = fw->data;
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
for (i = 0; i < hdr->n_region; i++) {
const struct mt76_connac2_fw_region *region;
region = (const void *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
offset += le32_to_cpu(region->len);
}
data += offset + 16;
rel_info = (struct mt792x_realease_info *)data;
data += sizeof(*rel_info);
end = data + le16_to_cpu(rel_info->len);
while (data < end) {
rel_info = (struct mt792x_realease_info *)data;
data += sizeof(*rel_info);
if (rel_info->tag == MT792x_FW_TAG_FEATURE) {
struct mt792x_fw_features *features;
features = (struct mt792x_fw_features *)data;
offload_caps = features->data;
break;
}
data += le16_to_cpu(rel_info->len) + rel_info->pad_len;
}
out:
release_firmware(fw);
return offload_caps;
}
struct ieee80211_ops *
mt792x_get_mac80211_ops(struct device *dev,
const struct ieee80211_ops *mac80211_ops,
void *drv_data, u8 *fw_features)
{
struct ieee80211_ops *ops;
ops = devm_kmemdup(dev, mac80211_ops, sizeof(struct ieee80211_ops),
GFP_KERNEL);
if (!ops)
return NULL;
*fw_features = mt792x_get_offload_capability(dev, drv_data);
if (!(*fw_features & MT792x_FW_CAP_CNM)) {
ops->remain_on_channel = NULL;
ops->cancel_remain_on_channel = NULL;
ops->add_chanctx = NULL;
ops->remove_chanctx = NULL;
ops->change_chanctx = NULL;
ops->assign_vif_chanctx = NULL;
ops->unassign_vif_chanctx = NULL;
ops->mgd_prepare_tx = NULL;
ops->mgd_complete_tx = NULL;
}
return ops;
}
EXPORT_SYMBOL_GPL(mt792x_get_mac80211_ops);
int mt792x_init_wcid(struct mt792x_dev *dev)
{
int idx;
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
if (idx)
return -ENOSPC;
dev->mt76.global_wcid.idx = idx;
dev->mt76.global_wcid.hw_key_idx = -1;
dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_init_wcid);
int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
mutex_lock(&pm->mutex);
if (!test_bit(MT76_STATE_PM, &mphy->state))
goto out;
err = __mt792x_mcu_drv_pmctrl(dev);
out:
mutex_unlock(&pm->mutex);
if (err)
mt792x_reset(&dev->mt76);
return err;
}
EXPORT_SYMBOL_GPL(mt792x_mcu_drv_pmctrl);
int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
mutex_lock(&pm->mutex);
if (mt76_connac_skip_fw_pmctrl(mphy, pm))
goto out;
err = __mt792x_mcu_fw_pmctrl(dev);
out:
mutex_unlock(&pm->mutex);
if (err)
mt792x_reset(&dev->mt76);
return err;
}
EXPORT_SYMBOL_GPL(mt792x_mcu_fw_pmctrl);
int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)
{
int i, err = 0;
for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))
break;
}
if (i == MT792x_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "driver own failed\n");
err = -EIO;
}
return err;
}
EXPORT_SYMBOL_GPL(__mt792xe_mcu_drv_pmctrl);
int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err;
err = __mt792xe_mcu_drv_pmctrl(dev);
if (err < 0)
goto out;
mt792x_wpdma_reinit_cond(dev);
clear_bit(MT76_STATE_PM, &mphy->state);
pm->stats.last_wake_event = jiffies;
pm->stats.doze_time += pm->stats.last_wake_event -
pm->stats.last_doze_event;
out:
return err;
}
EXPORT_SYMBOL_GPL(mt792xe_mcu_drv_pmctrl);
int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int i;
for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1))
break;
}
if (i == MT792x_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "firmware own failed\n");
clear_bit(MT76_STATE_PM, &mphy->state);
return -EIO;
}
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
return 0;
}
EXPORT_SYMBOL_GPL(mt792xe_mcu_fw_pmctrl);
int mt792x_load_firmware(struct mt792x_dev *dev)
{
int ret;
ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
if (ret)
return ret;
if (mt76_is_sdio(&dev->mt76)) {
/* activate again */
ret = __mt792x_mcu_fw_pmctrl(dev);
if (!ret)
ret = __mt792x_mcu_drv_pmctrl(dev);
}
ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL);
if (ret)
return ret;
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,
MT_TOP_MISC2_FW_N9_RDY, 1500)) {
dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
return -EIO;
}
#ifdef CONFIG_PM
dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
#endif /* CONFIG_PM */
dev_dbg(dev->mt76.dev, "Firmware init done\n");
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_load_firmware);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
@@ -0,0 +1,168 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt792x.h"
static void
mt792x_ampdu_stat_read_phy(struct mt792x_phy *phy,
struct seq_file *file)
{
struct mt792x_dev *dev = file->private;
int bound[15], range[4], i;
if (!phy)
return;
mt792x_mac_update_mib_stats(phy);
/* Tx ampdu stat */
for (i = 0; i < ARRAY_SIZE(range); i++)
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 % 4) + 1;
seq_puts(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_puts(file, "\nCount: ");
for (i = 0; i < ARRAY_SIZE(bound); i++)
seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);
seq_puts(file, "\n");
seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
}
int mt792x_tx_stats_show(struct seq_file *file, void *data)
{
struct mt792x_dev *dev = file->private;
struct mt792x_phy *phy = &dev->phy;
struct mt76_mib_stats *mib = &phy->mib;
int i;
mt792x_mutex_acquire(dev);
mt792x_ampdu_stat_read_phy(phy, file);
seq_puts(file, "Tx MSDU stat:\n");
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
i + 1, mib->tx_amsdu[i]);
if (mib->tx_amsdu_cnt)
seq_printf(file, "(%3d%%)\n",
mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
else
seq_puts(file, "\n");
}
mt792x_mutex_release(dev);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_tx_stats_show);
int mt792x_queues_acq(struct seq_file *s, void *data)
{
struct mt792x_dev *dev = dev_get_drvdata(s->private);
int i;
mt792x_mutex_acquire(dev);
for (i = 0; i < 4; i++) {
u32 ctrl, val, qlen = 0;
int j;
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
ctrl = BIT(31) | BIT(11) | (i << 24);
for (j = 0; j < 32; j++) {
if (val & BIT(j))
continue;
mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
GENMASK(11, 0));
}
seq_printf(s, "AC%d: queued=%d\n", i, qlen);
}
mt792x_mutex_release(dev);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_queues_acq);
int mt792x_queues_read(struct seq_file *s, void *data)
{
struct mt792x_dev *dev = dev_get_drvdata(s->private);
struct {
struct mt76_queue *q;
char *queue;
} queue_map[] = {
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
};
int i;
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_queue *q = queue_map[i].q;
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->queued, q->head,
q->tail);
}
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_queues_read);
int mt792x_pm_stats(struct seq_file *s, void *data)
{
struct mt792x_dev *dev = dev_get_drvdata(s->private);
struct mt76_connac_pm *pm = &dev->pm;
unsigned long awake_time = pm->stats.awake_time;
unsigned long doze_time = pm->stats.doze_time;
if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
awake_time += jiffies - pm->stats.last_wake_event;
else
doze_time += jiffies - pm->stats.last_doze_event;
seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
jiffies_to_msecs(awake_time),
jiffies_to_msecs(doze_time));
seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_pm_stats);
int mt792x_pm_idle_timeout_set(void *data, u64 val)
{
struct mt792x_dev *dev = data;
dev->pm.idle_timeout = msecs_to_jiffies(val);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_set);
int mt792x_pm_idle_timeout_get(void *data, u64 *val)
{
struct mt792x_dev *dev = data;
*val = jiffies_to_msecs(dev->pm.idle_timeout);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_get);
@@ -1,52 +1,93 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt7921.h"
#include "../dma.h"
#include "../mt76_connac2_mac.h"
#include <linux/module.h>
#include <linux/firmware.h>
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
#include "mt792x.h"
#include "dma.h"
#include "trace.h"
irqreturn_t mt792x_irq_handler(int irq, void *dev_instance)
{
struct mt7921_dev *dev;
struct mt792x_dev *dev = dev_instance;
dev = container_of(napi, struct mt7921_dev, mt76.tx_napi);
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
napi_complete(napi);
queue_work(dev->mt76.wq, &dev->pm.wake_work);
return 0;
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(mt792x_irq_handler);
void mt792x_irq_tasklet(unsigned long data)
{
struct mt792x_dev *dev = (struct mt792x_dev *)data;
const struct mt792x_irq_map *irq_map = dev->irq_map;
u32 intr, mask = 0;
mt76_wr(dev, irq_map->host_irq_enable, 0);
intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr);
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
mask |= intr & (irq_map->rx.data_complete_mask |
irq_map->rx.wm_complete_mask |
irq_map->rx.wm2_complete_mask);
if (intr & dev->irq_map->tx.mcu_complete_mask)
mask |= dev->irq_map->tx.mcu_complete_mask;
if (intr & MT_INT_MCU_CMD) {
u32 intr_sw;
intr_sw = mt76_rr(dev, MT_MCU_CMD);
/* ack MCU2HOST_SW_INT_STA */
mt76_wr(dev, MT_MCU_CMD, intr_sw);
if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) {
mask |= irq_map->rx.data_complete_mask;
intr |= irq_map->rx.data_complete_mask;
}
}
mt76_connac_tx_cleanup(&dev->mt76);
if (napi_complete(napi))
mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
mt76_set_irq_mask(&dev->mt76, irq_map->host_irq_enable, mask, 0);
return 0;
if (intr & dev->irq_map->tx.all_complete_mask)
napi_schedule(&dev->mt76.tx_napi);
if (intr & irq_map->rx.wm_complete_mask)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
if (intr & irq_map->rx.wm2_complete_mask)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);
if (intr & irq_map->rx.data_complete_mask)
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
}
EXPORT_SYMBOL_GPL(mt792x_irq_tasklet);
static int mt7921_poll_rx(struct napi_struct *napi, int budget)
void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
struct mt7921_dev *dev;
int done;
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
const struct mt792x_irq_map *irq_map = dev->irq_map;
dev = container_of(napi->dev, struct mt7921_dev, mt76.napi_dev);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
napi_complete(napi);
queue_work(dev->mt76.wq, &dev->pm.wake_work);
return 0;
}
done = mt76_dma_rx_poll(napi, budget);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
return done;
if (q == MT_RXQ_MAIN)
mt76_connac_irq_enable(mdev, irq_map->rx.data_complete_mask);
else if (q == MT_RXQ_MCU_WA)
mt76_connac_irq_enable(mdev, irq_map->rx.wm2_complete_mask);
else
mt76_connac_irq_enable(mdev, irq_map->rx.wm_complete_mask);
}
EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete);
static void mt7921_dma_prefetch(struct mt7921_dev *dev)
{
#define PREFETCH(base, depth) ((base) << 16 | (depth))
static void mt792x_dma_prefetch(struct mt792x_dev *dev)
{
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
@@ -64,7 +105,124 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
}
static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
int mt792x_dma_enable(struct mt792x_dev *dev)
{
/* configure perfetch settings */
mt792x_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 */
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
dev->irq_map->rx.data_complete_mask |
dev->irq_map->rx.wm2_complete_mask |
dev->irq_map->rx.wm_complete_mask |
MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_dma_enable);
static int
mt792x_dma_reset(struct mt792x_dev *dev, bool force)
{
int i, err;
err = mt792x_dma_disable(dev, force);
if (err)
return err;
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
for (i = 0; i < __MT_MCUQ_MAX; i++)
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
mt76_tx_status_check(&dev->mt76, true);
return mt792x_dma_enable(dev);
}
int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force)
{
int i, err;
/* 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);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
if (force) {
err = mt792x_wfsys_reset(dev);
if (err)
return err;
}
err = mt792x_dma_reset(dev, force);
if (err)
return err;
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_wpdma_reset);
int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev)
{
struct mt76_connac_pm *pm = &dev->pm;
int err;
/* check if the wpdma must be reinitialized */
if (mt792x_dma_need_reinit(dev)) {
/* disable interrutpts */
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
err = mt792x_wpdma_reset(dev, false);
if (err) {
dev_err(dev->mt76.dev, "wpdma reset failed\n");
return err;
}
/* enable interrutpts */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
pm->stats.lp_wake++;
}
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_wpdma_reinit_cond);
int mt792x_dma_disable(struct mt792x_dev *dev, bool force)
{
/* disable WFDMA0 */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
@@ -97,196 +255,9 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_dma_disable);
static int mt7921_dma_enable(struct mt7921_dev *dev)
{
/* 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 */
mt76_connac_irq_enable(&dev->mt76,
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
return 0;
}
static int mt7921_dma_reset(struct mt7921_dev *dev, bool force)
{
int i, err;
err = mt7921_dma_disable(dev, force);
if (err)
return err;
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
for (i = 0; i < __MT_MCUQ_MAX; i++)
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
mt76_tx_status_check(&dev->mt76, true);
return mt7921_dma_enable(dev);
}
int mt7921_wfsys_reset(struct mt7921_dev *dev)
{
mt76_clear(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B);
msleep(50);
mt76_set(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B);
if (!__mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B,
WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500))
return -ETIMEDOUT;
return 0;
}
int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force)
{
int i, err;
/* 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);
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
if (force) {
err = mt7921_wfsys_reset(dev);
if (err)
return err;
}
err = mt7921_dma_reset(dev, force);
if (err)
return err;
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
return 0;
}
int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
{
struct mt76_connac_pm *pm = &dev->pm;
int err;
/* check if the wpdma must be reinitialized */
if (mt7921_dma_need_reinit(dev)) {
/* disable interrutpts */
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
err = mt7921_wpdma_reset(dev, false);
if (err) {
dev_err(dev->mt76.dev, "wpdma reset failed\n");
return err;
}
/* enable interrutpts */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
pm->stats.lp_wake++;
}
return 0;
}
int mt7921_dma_init(struct mt7921_dev *dev)
{
int ret;
mt76_dma_attach(&dev->mt76);
ret = mt7921_dma_disable(dev, true);
if (ret)
return ret;
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
if (ret)
return ret;
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
/* command to WM */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,
MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* firmware download */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL,
MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* event from WM before firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
if (ret)
return ret;
/* Change mcu queue after firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
if (ret)
return ret;
/* rx data */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
if (ret)
return ret;
ret = mt76_init_queues(dev, mt7921_poll_rx);
if (ret < 0)
return ret;
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt7921_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return mt7921_dma_enable(dev);
}
void mt7921_dma_cleanup(struct mt7921_dev *dev)
void mt792x_dma_cleanup(struct mt792x_dev *dev)
{
/* disable */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
@@ -312,3 +283,62 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev)
mt76_dma_cleanup(&dev->mt76);
}
EXPORT_SYMBOL_GPL(mt792x_dma_cleanup);
int mt792x_poll_tx(struct napi_struct *napi, int budget)
{
struct mt792x_dev *dev;
dev = container_of(napi, struct mt792x_dev, mt76.tx_napi);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
napi_complete(napi);
queue_work(dev->mt76.wq, &dev->pm.wake_work);
return 0;
}
mt76_connac_tx_cleanup(&dev->mt76);
if (napi_complete(napi))
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_poll_tx);
int mt792x_poll_rx(struct napi_struct *napi, int budget)
{
struct mt792x_dev *dev;
int done;
dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev);
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
napi_complete(napi);
queue_work(dev->mt76.wq, &dev->pm.wake_work);
return 0;
}
done = mt76_dma_rx_poll(napi, budget);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
return done;
}
EXPORT_SYMBOL_GPL(mt792x_poll_rx);
int mt792x_wfsys_reset(struct mt792x_dev *dev)
{
u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140;
mt76_clear(dev, addr, WFSYS_SW_RST_B);
msleep(50);
mt76_set(dev, addr, WFSYS_SW_RST_B);
if (!__mt76_poll_msec(&dev->mt76, addr, WFSYS_SW_INIT_DONE,
WFSYS_SW_INIT_DONE, 500))
return -ETIMEDOUT;
return 0;
}
EXPORT_SYMBOL_GPL(mt792x_wfsys_reset);
@@ -0,0 +1,385 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/module.h>
#include "mt792x.h"
#include "mt792x_regs.h"
void mt792x_mac_work(struct work_struct *work)
{
struct mt792x_phy *phy;
struct mt76_phy *mphy;
mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
mac_work.work);
phy = mphy->priv;
mt792x_mutex_acquire(phy->dev);
mt76_update_survey(mphy);
if (++mphy->mac_work_count == 2) {
mphy->mac_work_count = 0;
mt792x_mac_update_mib_stats(phy);
}
mt792x_mutex_release(phy->dev);
mt76_tx_status_check(mphy->dev, false);
ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
MT792x_WATCHDOG_TIME);
}
EXPORT_SYMBOL_GPL(mt792x_mac_work);
void mt792x_mac_set_timeing(struct mt792x_phy *phy)
{
s16 coverage_class = phy->coverage_class;
struct mt792x_dev *dev = phy->dev;
u32 val, reg_offset;
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
int sifs = is_2ghz ? 10 : 16, offset;
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
mt76_set(dev, MT_ARB_SCR(0),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
udelay(1);
offset = 3 * coverage_class;
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(0),
FIELD_PREP(MT_IFS_EIFS, 360) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, sifs) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
if (phy->slottime < 20 || !is_2ghz)
val = MT792x_CFEND_RATE_DEFAULT;
else
val = MT792x_CFEND_RATE_11B;
mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(0),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
}
EXPORT_SYMBOL_GPL(mt792x_mac_set_timeing);
void mt792x_mac_update_mib_stats(struct mt792x_phy *phy)
{
struct mt76_mib_stats *mib = &phy->mib;
struct mt792x_dev *dev = phy->dev;
int i, aggr0 = 0, aggr1;
u32 val;
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);
mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0));
mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0));
mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0));
val = mt76_rr(dev, MT_MIB_SDR32(0));
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val);
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val);
val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0));
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val);
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val);
val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0));
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val);
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val);
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val);
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val);
mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0));
mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0));
mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0));
mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0));
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
mib->tx_amsdu[i] += val;
mib->tx_amsdu_cnt += val;
}
for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) {
u32 val2;
val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
phy->mt76->aggr_stats[aggr0++] += val & 0xffff;
phy->mt76->aggr_stats[aggr0++] += val >> 16;
phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff;
phy->mt76->aggr_stats[aggr1++] += val2 >> 16;
}
}
EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats);
struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
bool unicast)
{
struct mt792x_sta *sta;
struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
if (unicast || !wcid)
return wcid;
if (!wcid->sta)
return NULL;
sta = container_of(wcid, struct mt792x_sta, wcid);
if (!sta->vif)
return NULL;
return &sta->vif->sta.wcid;
}
EXPORT_SYMBOL_GPL(mt792x_rx_get_wcid);
static void
mt792x_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 mt792x_vif *mvif = (struct mt792x_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);
}
void mt792x_mac_assoc_rssi(struct mt792x_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,
mt792x_mac_rssi_iter, skb);
}
EXPORT_SYMBOL_GPL(mt792x_mac_assoc_rssi);
void mt792x_mac_reset_counters(struct mt792x_phy *phy)
{
struct mt792x_dev *dev = phy->dev;
int i;
for (i = 0; i < 4; i++) {
mt76_rr(dev, MT_TX_AGG_CNT(0, i));
mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
}
dev->mt76.phy.survey_time = ktime_get_boottime();
memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));
/* reset airtime counters */
mt76_rr(dev, MT_MIB_SDR9(0));
mt76_rr(dev, MT_MIB_SDR36(0));
mt76_rr(dev, MT_MIB_SDR37(0));
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
}
EXPORT_SYMBOL_GPL(mt792x_mac_reset_counters);
static u8
mt792x_phy_get_nf(struct mt792x_phy *phy, int idx)
{
return 0;
}
static void
mt792x_phy_update_channel(struct mt76_phy *mphy, int idx)
{
struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
struct mt76_channel_state *state;
u64 busy_time, tx_time, rx_time, obss_time;
int nf;
busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
MT_MIB_SDR9_BUSY_MASK);
tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
MT_MIB_SDR36_TXTIME_MASK);
rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
MT_MIB_SDR37_RXTIME_MASK);
obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
MT_MIB_OBSSTIME_MASK);
nf = mt792x_phy_get_nf(phy, idx);
if (!phy->noise)
phy->noise = nf << 4;
else if (nf)
phy->noise += nf - (phy->noise >> 4);
state = mphy->chan_state;
state->cc_busy += busy_time;
state->cc_tx += tx_time;
state->cc_rx += rx_time + obss_time;
state->cc_bss_rx += rx_time;
state->noise = -(phy->noise >> 4);
}
void mt792x_update_channel(struct mt76_phy *mphy)
{
struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
if (mt76_connac_pm_wake(mphy, &dev->pm))
return;
mt792x_phy_update_channel(mphy, 0);
/* reset obss airtime */
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
mt76_connac_power_save_sched(mphy, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt792x_update_channel);
void mt792x_reset(struct mt76_dev *mdev)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
if (!dev->hw_init_done)
return;
if (dev->hw_full_reset)
return;
if (pm->suspended)
return;
queue_work(dev->mt76.wq, &dev->reset_work);
}
EXPORT_SYMBOL_GPL(mt792x_reset);
void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band)
{
u32 mask, set;
mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
mt76_set(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
MT_TMAC_CTCR0_INS_DDLMT_EN);
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
/* enable MIB tx-rx time reporting */
mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN);
mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
/* filter out non-resp frames and get instantaneous signal reporting */
mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
}
EXPORT_SYMBOL_GPL(mt792x_mac_init_band);
void mt792x_pm_wake_work(struct work_struct *work)
{
struct mt792x_dev *dev;
struct mt76_phy *mphy;
dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
pm.wake_work);
mphy = dev->phy.mt76;
if (!mt792x_mcu_drv_pmctrl(dev)) {
struct mt76_dev *mdev = &dev->mt76;
int i;
if (mt76_is_sdio(mdev)) {
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_worker_schedule(&mdev->sdio.txrx_worker);
} else {
local_bh_disable();
mt76_for_each_q_rx(mdev, i)
napi_schedule(&mdev->napi[i]);
local_bh_enable();
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_connac_tx_cleanup(mdev);
}
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT792x_WATCHDOG_TIME);
}
ieee80211_wake_queues(mphy->hw);
wake_up(&dev->pm.wait);
}
EXPORT_SYMBOL_GPL(mt792x_pm_wake_work);
void mt792x_pm_power_save_work(struct work_struct *work)
{
struct mt792x_dev *dev;
unsigned long delta;
struct mt76_phy *mphy;
dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
pm.ps_work.work);
mphy = dev->phy.mt76;
delta = dev->pm.idle_timeout;
if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) ||
dev->fw_assert)
goto out;
if (mutex_is_locked(&dev->mt76.mutex))
/* if mt76 mutex is held we should not put the device
* to sleep since we are currently accessing device
* register map. We need to wait for the next power_save
* trigger.
*/
goto out;
if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
delta = dev->pm.last_activity + delta - jiffies;
goto out;
}
if (!mt792x_mcu_fw_pmctrl(dev)) {
cancel_delayed_work_sync(&mphy->mac_work);
return;
}
out:
queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
}
EXPORT_SYMBOL_GPL(mt792x_pm_power_save_work);
@@ -0,0 +1,479 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT792X_REGS_H
#define __MT792X_REGS_H
/* MCU WFDMA1 */
#define MT_MCU_WFDMA1_BASE 0x3000
#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs))
#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108)
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2)
#define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
#define MT_PLE_BASE 0x820c0000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0)
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4)
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8)
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec)
#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
/* TMAC: band 0(0x21000), band 1(0xa1000) */
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0)
#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25)
#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090)
#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094)
#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4)
#define MT_IFS_EIFS GENMASK(8, 0)
#define MT_IFS_RIFS GENMASK(14, 10)
#define MT_IFS_SIFS GENMASK(22, 16)
#define MT_IFS_SLOT GENMASK(30, 24)
#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4)
#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0)
#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17)
#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18)
#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c)
#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0)
#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000)
#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs))
#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000)
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3)
#define MT_DMA_DCR0_RXD_G5_EN BIT(23)
/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */
#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000)
#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs))
#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008)
#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30)
#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24)
/* LPON: band 0(0x24200), band 1(0xa4200) */
#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000)
#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs))
#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080)
#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084)
#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4)
#define MT_LPON_TCR_SW_MODE GENMASK(1, 0)
#define MT_LPON_TCR_SW_WRITE BIT(0)
/* ETBF: band 0(0x24000), band 1(0xa4000) */
#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000)
#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs))
#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150)
#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16)
#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0)
#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158)
#define MT_ETBF_RX_FB_ALL GENMASK(31, 24)
#define MT_ETBF_RX_FB_HE GENMASK(23, 16)
#define MT_ETBF_RX_FB_VHT GENMASK(15, 8)
#define MT_ETBF_RX_FB_HT GENMASK(7, 0)
/* MIB: band 0(0x24800), band 1(0xa4800) */
#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000)
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004)
#define MT_MIB_TXDUR_EN BIT(8)
#define MT_MIB_RXDUR_EN BIT(9)
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698)
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16)
#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780)
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558)
#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564)
#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568)
#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048)
#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770)
#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774)
#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c)
#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8)
#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16)
#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0)
#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090)
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054)
#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058)
#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0)
#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0)
#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4)
#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc)
#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4))
#define MT_MIB_RTS_RETRIES_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, 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 0x820d4000
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
#define MT_WTBL_UPDATE_BUSY BIT(31)
#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0)
#define MT_WTBL_ITCR_WR BIT(16)
#define MT_WTBL_ITCR_EXEC BIT(31)
#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8)
#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc)
#define MT_WTBL_SPE_IDX_SEL BIT(6)
#define MT_WTBL_BASE 0x820d8000
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
#define MT_WTBL_LMAC_DW GENMASK(7, 2)
#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
/* AGG: band 0(0x20800), band 1(0xa0800) */
#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000)
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4)
#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4)
#define MT_AGG_PCR0_MM_PROT BIT(0)
#define MT_AGG_PCR0_GF_PROT BIT(1)
#define MT_AGG_PCR0_BW20_PROT BIT(2)
#define MT_AGG_PCR0_BW40_PROT BIT(4)
#define MT_AGG_PCR0_BW80_PROT BIT(6)
#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8)
#define MT_AGG_PCR0_VHT_PROT BIT(13)
#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15)
#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23)
#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0)
#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084)
#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0)
#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16)
#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098)
#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12)
#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6)
#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7)
#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24)
#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0)
#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4)
/* ARB: band 0(0x20c00), band 1(0xa0c00) */
#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000)
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080)
#define MT_ARB_SCR_TX_DISABLE BIT(8)
#define MT_ARB_SCR_RX_DISABLE BIT(9)
#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4)
/* RMAC: band 0(0x21400), band 1(0xa1400) */
#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000)
#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs))
#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000)
#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0)
#define MT_WF_RFCR_DROP_FCSFAIL BIT(1)
#define MT_WF_RFCR_DROP_VERSION BIT(3)
#define MT_WF_RFCR_DROP_PROBEREQ BIT(4)
#define MT_WF_RFCR_DROP_MCAST BIT(5)
#define MT_WF_RFCR_DROP_BCAST BIT(6)
#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7)
#define MT_WF_RFCR_DROP_A3_MAC BIT(8)
#define MT_WF_RFCR_DROP_A3_BSSID BIT(9)
#define MT_WF_RFCR_DROP_A2_BSSID BIT(10)
#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11)
#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12)
#define MT_WF_RFCR_DROP_CTL_RSV BIT(13)
#define MT_WF_RFCR_DROP_CTS BIT(14)
#define MT_WF_RFCR_DROP_RTS BIT(15)
#define MT_WF_RFCR_DROP_DUPLICATE BIT(16)
#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17)
#define MT_WF_RFCR_DROP_OTHER_UC BIT(18)
#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19)
#define MT_WF_RFCR_DROP_NDPA BIT(20)
#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21)
#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004)
#define MT_WF_RFCR1_DROP_ACK BIT(4)
#define MT_WF_RFCR1_DROP_BF_POLL BIT(5)
#define MT_WF_RFCR1_DROP_BA BIT(6)
#define MT_WF_RFCR1_DROP_CFEND BIT(7)
#define MT_WF_RFCR1_DROP_CFACK BIT(8)
#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4)
#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30)
#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8)
#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0)
#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
/* WFDMA0 */
#define MT_WFDMA0_BASE 0xd4000
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
#define MT_WFDMA0_RST MT_WFDMA0(0x100)
#define MT_WFDMA0_RST_LOGIC_RST BIT(4)
#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5)
#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2)
#define MT_MCU_CMD MT_WFDMA0(0x1f0)
#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0)
#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1)
#define MT_MCU_CMD_STOP_DMA BIT(2)
#define MT_MCU_CMD_RESET_DONE BIT(3)
#define MT_MCU_CMD_RECOVERY_DONE BIT(4)
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4)
#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200)
#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */
#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */
#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */
#define HOST_TX_DONE_INT_STS16 BIT(26)
#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9)
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30)
#define HOST_RX_DONE_INT_ENA0 BIT(0)
#define HOST_RX_DONE_INT_ENA1 BIT(1)
#define HOST_RX_DONE_INT_ENA2 BIT(2)
#define HOST_RX_DONE_INT_ENA3 BIT(3)
#define HOST_TX_DONE_INT_ENA0 BIT(4)
#define HOST_TX_DONE_INT_ENA1 BIT(5)
#define HOST_TX_DONE_INT_ENA2 BIT(6)
#define HOST_TX_DONE_INT_ENA3 BIT(7)
#define HOST_TX_DONE_INT_ENA4 BIT(8)
#define HOST_TX_DONE_INT_ENA5 BIT(9)
#define HOST_TX_DONE_INT_ENA6 BIT(10)
#define HOST_TX_DONE_INT_ENA7 BIT(11)
#define HOST_RX_COHERENT_EN BIT(20)
#define HOST_TX_COHERENT_EN BIT(21)
#define MCU2HOST_SW_INT_ENA BIT(29)
#define HOST_TX_DONE_INT_ENA18 BIT(30)
#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA
#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
#define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280)
#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600)
#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604)
#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608)
#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c)
#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610)
#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614)
#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618)
#define MT_WFDMA0_TX_RING15_EXT_CTRL MT_WFDMA0(0x63c)
#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640)
#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644)
#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0)
#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16)
#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680)
#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684)
#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688)
#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c)
#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690)
#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694)
#define MT_WFDMA0_RX_RING6_EXT_CTRL MT_WFDMA0(0x698)
#define MT_WFDMA0_RX_RING7_EXT_CTRL MT_WFDMA0(0x69c)
#define MT_TX_RING_BASE MT_WFDMA0(0x300)
#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500)
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE 0xd7000
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_SWDEF_BASE 0x41f200
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
#define MT_SWDEF_ICAP_MODE 1
#define MT_SWDEF_SPECTRUM_MODE 2
#define MT_TOP_BASE 0x18060000
#define MT_TOP(ofs) (MT_TOP_BASE + (ofs))
#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10)
#define MT_TOP_LPCR_HOST_FW_OWN BIT(0)
#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1)
#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_CBTOP_RGU(ofs) (0x70002000 + (ofs))
#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
#define MT_HW_BOUND 0x70010020
#define MT_HW_CHIPID 0x70010200
#define MT_HW_REV 0x70010204
#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)
#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194)
#define MT_PCIE_MAC_PM_L0S_DIS BIT(8)
#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs))
#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004)
#define MT_DMASHDL_DMASHDL_BYPASS BIT(28)
#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008)
#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c)
#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16)
#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010)
#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16)
#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c)
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)
#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2))
#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0)
#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16)
#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2))
#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0)
#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8))
#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2))
#define MT_WFDMA_HOST_CONFIG 0x7c027030
#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6)
#define MT_UMAC(ofs) (0x74000000 + (ofs))
#define MT_UDMA_TX_QSEL MT_UMAC(0x008)
#define MT_FW_DL_EN BIT(3)
#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c)
#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0)
#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8)
#define MT_UDMA_WLCFG_0 MT_UMAC(0x18)
#define MT_WL_RX_AGG_TO GENMASK(7, 0)
#define MT_WL_RX_AGG_LMT GENMASK(15, 8)
#define MT_WL_TX_TMOUT_FUNC_EN BIT(16)
#define MT_WL_TX_DPH_CHK_EN BIT(17)
#define MT_WL_RX_MPSZ_PAD0 BIT(18)
#define MT_WL_RX_FLUSH BIT(19)
#define MT_TICK_1US_EN BIT(20)
#define MT_WL_RX_AGG_EN BIT(21)
#define MT_WL_RX_EN BIT(22)
#define MT_WL_TX_EN BIT(23)
#define MT_WL_RX_BUSY BIT(30)
#define MT_WL_TX_BUSY BIT(31)
#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20)
#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22)
#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24)
#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs))
#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090)
#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs))
#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208)
#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0)
#define MT_UWFDMA0_GLO_CFG_EXT1 MT_UWFDMA0(0x2b4)
#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2))
#define MT_CONN_STATUS 0x7c053c10
#define MT_WIFI_PATCH_DL_STATE BIT(0)
#define MT_CONN_ON_LPCTL 0x7c060010
#define PCIE_LPCR_HOST_SET_OWN BIT(0)
#define PCIE_LPCR_HOST_CLR_OWN BIT(1)
#define PCIE_LPCR_HOST_OWN_SYNC BIT(2)
#define MT_CONN_ON_MISC 0x7c0600f0
#define MT_TOP_MISC2_FW_PWR_ON BIT(0)
#define MT_TOP_MISC2_FW_N9_ON BIT(1)
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs))
#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028)
#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6)
#define MT_WF_SW_SER_DONE_SUSPEND BIT(7)
#define WFSYS_SW_RST_B BIT(0)
#define WFSYS_SW_INIT_DONE BIT(4)
#endif /* __MT792X_REGS_H */
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/module.h>
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "mt792x_trace.h"
EXPORT_TRACEPOINT_SYMBOL_GPL(lp_event);
#endif
@@ -1,27 +1,27 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org>
* Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org>
*/
#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define __MT7921_TRACE_H
#if !defined(__MT792X_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define __MT792X_TRACE_H
#include <linux/tracepoint.h>
#include "mt7921.h"
#include "mt792x.h"
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mt7921
#define TRACE_SYSTEM mt792x
#define MAXNAME 32
#define DEV_ENTRY __array(char, wiphy_name, 32)
#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
#define DEV_ASSIGN strscpy(__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_PROTO(struct mt792x_dev *dev, u8 lp_state),
TP_ARGS(dev, lp_state),
@@ -46,6 +46,6 @@ TRACE_EVENT(lp_event,
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE mt7921_trace
#define TRACE_INCLUDE_FILE mt792x_trace
#include <trace/define_trace.h>
@@ -0,0 +1,309 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc.
*
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "mt792x.h"
#include "mt76_connac2_mac.h"
u32 mt792xu_rr(struct mt76_dev *dev, u32 addr)
{
u32 ret;
mutex_lock(&dev->usb.usb_ctrl_mtx);
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return ret;
}
EXPORT_SYMBOL_GPL(mt792xu_rr);
void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
}
EXPORT_SYMBOL_GPL(mt792xu_wr);
u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask;
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return val;
}
EXPORT_SYMBOL_GPL(mt792xu_rmw);
void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len)
{
struct mt76_usb *usb = &dev->usb;
int ret, i = 0, batch_len;
const u8 *val = data;
len = round_up(len, 4);
mutex_lock(&usb->usb_ctrl_mtx);
while (i < len) {
batch_len = min_t(int, usb->data_len, len - i);
memcpy(usb->data, val + i, batch_len);
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
(offset + i) >> 16, offset + i,
usb->data, batch_len);
if (ret < 0)
break;
i += batch_len;
}
mutex_unlock(&usb->usb_ctrl_mtx);
}
EXPORT_SYMBOL_GPL(mt792xu_copy);
int mt792xu_mcu_power_on(struct mt792x_dev *dev)
{
int ret;
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
0x0, 0x1, NULL, 0);
if (ret)
return ret;
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
MT_TOP_MISC2_FW_PWR_ON, 500)) {
dev_err(dev->mt76.dev, "Timeout for power on\n");
ret = -EIO;
}
return ret;
}
EXPORT_SYMBOL_GPL(mt792xu_mcu_power_on);
static void mt792xu_cleanup(struct mt792x_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
mt792xu_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_queues_deinit(&dev->mt76);
}
static u32 mt792xu_uhw_rr(struct mt76_dev *dev, u32 addr)
{
u32 ret;
mutex_lock(&dev->usb.usb_ctrl_mtx);
ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
return ret;
}
static void mt792xu_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
{
mutex_lock(&dev->usb.usb_ctrl_mtx);
___mt76u_wr(dev, MT_VEND_WRITE,
USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
mutex_unlock(&dev->usb.usb_ctrl_mtx);
}
static void mt792xu_dma_prefetch(struct mt792x_dev *dev)
{
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
MT_WPDMA0_BASE_PTR_MASK, 0x80);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
MT_WPDMA0_BASE_PTR_MASK, 0xc0);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
MT_WPDMA0_BASE_PTR_MASK, 0x100);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
MT_WPDMA0_BASE_PTR_MASK, 0x140);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
MT_WPDMA0_BASE_PTR_MASK, 0x180);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
MT_WPDMA0_BASE_PTR_MASK, 0x280);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
MT_WPDMA0_MAX_CNT_MASK, 4);
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
MT_WPDMA0_BASE_PTR_MASK, 0x2c0);
}
static void mt792xu_wfdma_init(struct mt792x_dev *dev)
{
mt792xu_dma_prefetch(dev);
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
mt76_set(dev, MT_UWFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
/* disable dmashdl */
mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0,
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
}
static int mt792xu_dma_rx_evt_ep4(struct mt792x_dev *dev)
{
if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
return -ETIMEDOUT;
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
return 0;
}
static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset)
{
u32 val;
/* usb endpoint reset opt
* bits[4,9]: out blk ep 4-9
* bits[20,21]: in blk ep 4-5
* bits[22]: in int ep 6
*/
val = mt792xu_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
if (reset)
val |= GENMASK(9, 4) | GENMASK(22, 20);
else
val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
}
int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
{
int err;
mt792xu_wfdma_init(dev);
mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
mt76_set(dev, MT_UDMA_WLCFG_0,
MT_WL_RX_EN | MT_WL_TX_EN |
MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
mt76_clear(dev, MT_UDMA_WLCFG_0,
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
if (resume)
return 0;
err = mt792xu_dma_rx_evt_ep4(dev);
if (err)
return err;
mt792xu_epctl_rst_opt(dev, false);
return 0;
}
EXPORT_SYMBOL_GPL(mt792xu_dma_init);
int mt792xu_wfsys_reset(struct mt792x_dev *dev)
{
u32 val;
int i;
mt792xu_epctl_rst_opt(dev, false);
val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
usleep_range(10, 20);
val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {
val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
break;
msleep(100);
}
if (i == MT792x_WFSYS_INIT_RETRY_COUNT)
return -ETIMEDOUT;
return 0;
}
EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset);
int mt792xu_init_reset(struct mt792x_dev *dev)
{
set_bit(MT76_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
mt792xu_wfsys_reset(dev);
clear_bit(MT76_RESET, &dev->mphy.state);
return mt76u_resume_rx(&dev->mt76);
}
EXPORT_SYMBOL_GPL(mt792xu_init_reset);
void mt792xu_disconnect(struct usb_interface *usb_intf)
{
struct mt792x_dev *dev = usb_get_intfdata(usb_intf);
cancel_work_sync(&dev->init_work);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return;
mt76_unregister_device(&dev->mt76);
mt792xu_cleanup(dev);
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
mt76_free_device(&dev->mt76);
}
EXPORT_SYMBOL_GPL(mt792xu_disconnect);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
@@ -474,10 +474,10 @@ mt7996_ampdu_stat_read_phy(struct mt7996_phy *phy, struct seq_file *file)
static void
mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
{
struct mt76_mib_stats *mib = &phy->mib;
static const char * const bw[] = {
"BW20", "BW40", "BW80", "BW160"
};
struct mib_stats *mib = &phy->mib;
/* Tx Beamformer monitor */
seq_puts(s, "\nTx Beamformer applied PPDU counts: ");
@@ -523,7 +523,7 @@ mt7996_tx_stats_show(struct seq_file *file, void *data)
{
struct mt7996_phy *phy = file->private;
struct mt7996_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
struct mt76_mib_stats *mib = &phy->mib;
int i;
u32 attempts, success, per;
+49 -34
View File
@@ -128,11 +128,55 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
}
}
static int mt7996_dma_enable(struct mt7996_dev *dev)
void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
{
u32 hif1_ofs = 0;
u32 irq_mask;
if (dev->hif2)
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
/* enable WFDMA Tx/Rx */
if (!reset) {
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (dev->hif2)
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
}
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_MCU_CMD;
if (reset)
goto done;
irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
if (!dev->mphy.band_idx)
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support)
irq_mask |= MT_INT_BAND1_RX_DONE;
if (dev->tbtc_support)
irq_mask |= MT_INT_BAND2_RX_DONE;
done:
mt7996_irq_enable(dev, irq_mask);
mt7996_irq_disable(dev, 0);
}
static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
{
u32 hif1_ofs = 0;
if (dev->hif2)
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
@@ -170,13 +214,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC,
MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000);
/* set WFDMA Tx/Rx */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
/* GLO_CFG_EXT0 */
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0,
WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
@@ -187,12 +224,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
/* GLO_CFG_EXT0 */
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD |
@@ -216,23 +247,7 @@ static int mt7996_dma_enable(struct mt7996_dev *dev)
/* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
}
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_RX_DONE_MCU |
MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD;
if (!dev->mphy.band_idx)
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support)
irq_mask |= MT_INT_BAND1_RX_DONE;
if (dev->tbtc_support)
irq_mask |= MT_INT_BAND2_RX_DONE;
mt7996_irq_enable(dev, irq_mask);
return 0;
mt7996_dma_start(dev, reset);
}
int mt7996_dma_init(struct mt7996_dev *dev)
@@ -293,7 +308,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
/* event from WA */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT_RXQ_ID(MT_RXQ_MCU_WA),
MT7996_RX_MCU_RING_SIZE,
MT7996_RX_MCU_RING_SIZE_WA,
MT_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
if (ret)
@@ -347,7 +362,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
mt7996_poll_tx);
napi_enable(&dev->mt76.tx_napi);
mt7996_dma_enable(dev);
mt7996_dma_enable(dev, false);
return 0;
}
@@ -413,7 +428,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
mt7996_dma_enable(dev);
mt7996_dma_enable(dev, !force);
}
void mt7996_dma_cleanup(struct mt7996_dev *dev)
@@ -184,6 +184,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
if (!mdev->dev->of_node ||
!of_property_read_bool(mdev->dev->of_node,
@@ -218,6 +219,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_1;
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
}
mt76_set_stream_caps(phy->mt76, true);
@@ -854,9 +857,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7996_mac_reset_work);
+55 -245
View File
@@ -13,10 +13,6 @@
#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 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)
static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
.radar_pattern = {
@@ -111,9 +107,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
LIST_HEAD(sta_poll_list);
int i;
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&dev->sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_lock();
@@ -124,15 +120,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
s8 rssi[4];
u8 bw;
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7996_sta, poll_list);
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
struct mt7996_sta, wcid.poll_list);
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -263,180 +259,6 @@ void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
mt76_wr(dev, MT_WTBL_ITCR, ctrl);
}
static void
mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
struct ieee80211_radiotap_he *he,
__le32 *rxv)
{
u32 ru, offs = 0;
ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC);
status->bw = RATE_INFO_BW_HE_RU;
switch (ru) {
case 0 ... 36:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
offs = ru;
break;
case 37 ... 52:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
offs = ru - 37;
break;
case 53 ... 60:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
offs = ru - 53;
break;
case 61 ... 64:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
offs = ru - 61;
break;
case 65 ... 66:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
offs = ru - 65;
break;
case 67:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
break;
case 68:
status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
break;
}
he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
le16_encode_bits(offs,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
}
static void
mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he_mu mu_known = {
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
struct ieee80211_radiotap_he_mu *he_mu = NULL;
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
he_mu = skb_push(skb, sizeof(mu_known));
memcpy(he_mu, &mu_known, sizeof(mu_known));
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
if (status->he_dcm)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
if (status->bw >= RATE_INFO_BW_40) {
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
}
if (status->bw >= RATE_INFO_BW_80) {
u32 ru_h, ru_l;
he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
}
}
static void
mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he known = {
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
HE_BITS(DATA1_DATA_DCM_KNOWN) |
HE_BITS(DATA1_STBC_KNOWN) |
HE_BITS(DATA1_CODING_KNOWN) |
HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
HE_BITS(DATA1_DOPPLER_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
HE_BITS(DATA1_BSS_COLOR_KNOWN),
.data2 = HE_BITS(DATA2_GI_KNOWN) |
HE_BITS(DATA2_TXBF_KNOWN) |
HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
HE_BITS(DATA2_TXOP_KNOWN),
};
struct ieee80211_radiotap_he *he = NULL;
u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
status->flag |= RX_FLAG_RADIOTAP_HE;
he = skb_push(skb, sizeof(known));
memcpy(he, &known, sizeof(known));
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
le16_encode_bits(ltf_size,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
he->data5 |= HE_BITS(DATA5_TXBF);
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
switch (mode) {
case MT_PHY_TYPE_HE_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_MU:
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
HE_BITS(DATA1_UL_DL_KNOWN);
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
mt7996_mac_decode_he_mu_radiotap(skb, rxv);
break;
case MT_PHY_TYPE_HE_TB:
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
break;
default:
break;
}
}
/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
@@ -681,10 +503,11 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
struct mt7996_sta *msta;
msta = container_of(status->wcid, struct mt7996_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -836,14 +659,19 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
skb_pull(skb, hdr_gap);
if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) {
pad_start = ieee80211_get_hdrlen_from_skb(skb);
} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) &&
get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) {
} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
/* When header translation failure is indicated,
* the hardware will insert an extra 2-byte field
* containing the data length after the protocol
* type field.
* type field. This happens either when the LLC-SNAP
* pattern did not match, or if a VLAN header was
* detected.
*/
pad_start = 16;
pad_start = 12;
if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
pad_start += 4;
else
pad_start = 0;
}
if (pad_start) {
@@ -881,7 +709,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
}
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt7996_mac_decode_he_radiotap(skb, rxv, mode);
mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
@@ -1007,7 +835,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
struct mt7996_vif *mvif;
struct mt76_vif *mvif;
u16 tx_count = 15;
u32 val;
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
@@ -1015,11 +843,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
if (mvif) {
omac_idx = mvif->mt76.omac_idx;
wmm_idx = mvif->mt76.wmm_idx;
band_idx = mvif->mt76.band_idx;
omac_idx = mvif->omac_idx;
wmm_idx = mvif->wmm_idx;
band_idx = mvif->band_idx;
}
if (inband_disc) {
@@ -1198,7 +1026,7 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
return;
msta = (struct mt7996_sta *)sta->drv_priv;
if (!test_and_set_bit(tid, &msta->ampdu_state))
if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
@@ -1286,10 +1114,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7996_sta, wcid);
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
continue;
}
@@ -1324,9 +1153,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
}
static bool
mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid,
__le32 *txs_data, struct mt76_sta_stats *stats)
mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
int pid, __le32 *txs_data)
{
struct mt76_sta_stats *stats = &wcid->stats;
struct ieee80211_supported_band *sband;
struct mt76_dev *mdev = &dev->mt76;
struct mt76_phy *mphy;
@@ -1488,15 +1318,15 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
msta = container_of(wcid, struct mt7996_sta, wcid);
mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats);
mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
if (!wcid->sta)
goto out;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
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);
out:
rcu_read_unlock();
@@ -1609,20 +1439,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy)
mt7996_mcu_get_chan_mib_info(phy, true);
}
void mt7996_mac_set_timing(struct mt7996_phy *phy)
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy)
{
s16 coverage_class = phy->coverage_class;
struct mt7996_dev *dev = phy->dev;
struct mt7996_phy *phy2 = mt7996_phy2(dev);
struct mt7996_phy *phy3 = mt7996_phy3(dev);
u32 val, reg_offset;
u32 reg_offset;
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
u8 band_idx = phy->mt76->band_idx;
int offset;
bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
@@ -1635,34 +1464,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy)
coverage_class = max_t(s16, coverage_class,
phy3->coverage_class);
mt76_set(dev, MT_ARB_SCR(band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
udelay(1);
offset = 3 * coverage_class;
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(band_idx),
FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, 10) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
if (!a_band)
mt76_wr(dev, MT_TMAC_ICR1(band_idx),
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
if (phy->slottime < 20 || a_band)
val = MT7996_CFEND_RATE_DEFAULT;
else
val = MT7996_CFEND_RATE_11B;
mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
}
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band)
@@ -2046,6 +1853,12 @@ void mt7996_mac_reset_work(struct work_struct *work)
mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
}
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
/* enable DMA Tx/Tx and interrupt */
mt7996_dma_start(dev, false);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
@@ -2062,9 +1875,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
@@ -2191,8 +2001,8 @@ void mt7996_reset(struct mt7996_dev *dev)
void mt7996_mac_update_stats(struct mt7996_phy *phy)
{
struct mt76_mib_stats *mib = &phy->mib;
struct mt7996_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
u8 band_idx = phy->mt76->band_idx;
u32 cnt;
int i;
@@ -2339,7 +2149,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
u32 changed;
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
@@ -2347,7 +2157,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
list_del_init(&msta->rc_list);
changed = msta->changed;
msta->changed = 0;
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
@@ -2359,10 +2169,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
/* TODO: smps change */
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
void mt7996_mac_work(struct work_struct *work)
+1 -314
View File
@@ -6,320 +6,7 @@
#ifndef __MT7996_MAC_H
#define __MT7996_MAC_H
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
#define MT_RXD0_LENGTH GENMASK(15, 0)
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
#define MT_RXD0_MESH BIT(18)
#define MT_RXD0_MHCP BIT(19)
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16)
#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
#define MT_RXD1_NORMAL_GROUP_2 BIT(17)
#define MT_RXD1_NORMAL_GROUP_3 BIT(18)
#define MT_RXD1_NORMAL_GROUP_4 BIT(19)
#define MT_RXD1_NORMAL_GROUP_5 BIT(20)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(7)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13)
#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(18)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_CO_ANT BIT(22)
#define MT_RXD3_NORMAL_FCS_ERR BIT(24)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
#define MT_RXV_HDR_BAND_IDX BIT(24)
/* RXD GROUP4 */
#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD10_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD10_QOS_CTL GENMASK(31, 16)
#define MT_RXD11_HT_CONTROL GENMASK(31, 0)
/* P-RXV */
#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(10, 7)
#define MT_PRXV_TXBF BIT(11)
#define MT_PRXV_HT_AD_CODE BIT(12)
#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3)
#define MT_PRXV_HT_STBC GENMASK(10, 9)
#define MT_PRXV_TX_MODE GENMASK(14, 11)
#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
#define MT_PRXV_DCM BIT(5)
/* C-RXV */
#define MT_CRXV_HE_NUM_USER GENMASK(26, 20)
#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30)
#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
#define MT_CRXV_HE_UPLINK BIT(2)
#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
#define MT_CRXV_HE_BEAM_CHNG BIT(29)
#define MT_CRXV_HE_DOPPLER BIT(0)
#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_RU0 GENMASK(8, 0)
#define MT_CRXV_HE_RU1 GENMASK(17, 9)
#define MT_CRXV_HE_RU2 GENMASK(26, 18)
#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
enum tx_mgnt_type {
MT_TX_NORMAL,
MT_TX_TIMING,
MT_TX_ADDBA,
};
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
#define MT_TXD_SIZE (8 * 4)
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_FIXED_RATE BIT(31)
#define MT_TXD1_OWN_MAC GENMASK(30, 25)
#define MT_TXD1_TID GENMASK(24, 21)
#define MT_TXD1_BIP BIT(24)
#define MT_TXD1_ETH_802_3 BIT(20)
#define MT_TXD1_HDR_INFO GENMASK(20, 16)
#define MT_TXD1_HDR_FORMAT GENMASK(15, 14)
#define MT_TXD1_TGID GENMASK(13, 12)
#define MT_TXD1_WLAN_IDX GENMASK(11, 0)
#define MT_TXD2_POWER_OFFSET GENMASK(31, 26)
#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_HDR_PAD GENMASK(11, 10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_OWN_MAC_MAP BIT(8)
#define MT_TXD2_BF_TYPE GENMASK(6, 7)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_HW_AMSDU BIT(5)
#define MT_TXD3_BCM BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_FL BIT(15)
#define MT_TXD5_BYPASS_TBB BIT(14)
#define MT_TXD5_BYPASS_RBB BIT(13)
#define MT_TXD5_BSS_COLOR_ZERO BIT(12)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_SRC GENMASK(31, 30)
#define MT_TXD6_VTA BIT(28)
#define MT_TXD6_BW GENMASK(25, 22)
#define MT_TXD6_TX_RATE GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
#define MT_TXD6_DIS_MAT BIT(3)
#define MT_TXD6_DAS BIT(2)
#define MT_TXD6_AMSDU_CAP BIT(1)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_IP_SUM BIT(29)
#define MT_TXD7_DROP_BY_SDO BIT(28)
#define MT_TXD7_MAC_TXD BIT(27)
#define MT_TXD7_CTXD BIT(26)
#define MT_TXD7_CTXD_CNT GENMASK(25, 22)
#define MT_TXD7_UDP_TCP_SUM BIT(15)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TX_RATE_STBC BIT(14)
#define MT_TX_RATE_NSS GENMASK(13, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
/* VHT/HE only use bits 0-3 */
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
#define MT_TXFREE1_VER GENMASK(18, 16)
#define MT_TXFREE_INFO_PAIR BIT(31)
#define MT_TXFREE_INFO_HEADER BIT(30)
#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
#define MT_TXS0_BW GENMASK(31, 29)
#define MT_TXS0_TID GENMASK(28, 26)
#define MT_TXS0_AMPDU BIT(25)
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
#define MT_TXS0_BA_ERROR BIT(22)
#define MT_TXS0_PS_FLAG BIT(21)
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
#define MT_TXS0_BIP_ERROR BIT(19)
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
#define MT_TXS0_RTS_TIMEOUT BIT(17)
#define MT_TXS0_ACK_TIMEOUT BIT(16)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_STATUS_HOST BIT(15)
#define MT_TXS0_TX_STATUS_MCU BIT(14)
#define MT_TXS0_TX_RATE GENMASK(13, 0)
#define MT_TXS1_SEQNO GENMASK(31, 20)
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
#define MT_TXS2_BAND GENMASK(29, 28)
#define MT_TXS2_WCID GENMASK(27, 16)
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
#define MT_TXS3_PID GENMASK(31, 24)
#define MT_TXS3_RATE_STBC BIT(7)
#define MT_TXS3_FIXED_RATE BIT(6)
#define MT_TXS3_SRC GENMASK(5, 4)
#define MT_TXS3_SHARED_ANTENNA BIT(3)
#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0)
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
#define MT_TXS5_F0_QOS BIT(30)
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0)
#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24)
#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0)
#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24)
#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16)
#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8)
#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0)
#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24)
#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0)
#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24)
#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16)
#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8)
#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0)
#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
#include "../mt76_connac3_mac.h"
struct mt7996_dfs_pulse {
u32 max_width; /* us */
@@ -43,6 +43,10 @@ int mt7996_run(struct ieee80211_hw *hw)
if (ret)
goto out;
ret = mt7996_mcu_set_radio_en(phy, true);
if (ret)
goto out;
ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);
if (ret)
goto out;
@@ -82,6 +86,8 @@ static void mt7996_stop(struct ieee80211_hw *hw)
mutex_lock(&dev->mt76.mutex);
mt7996_mcu_set_radio_en(phy, false);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
mutex_unlock(&dev->mt76.mutex);
@@ -190,17 +196,13 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out;
ret = mt7996_mcu_set_radio_en(phy, true);
if (ret)
goto out;
dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
idx = MT7996_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.poll_list);
INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = band_idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -221,9 +223,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
else
mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;
mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL;
mt7996_init_bitrate_mask(vif);
@@ -253,7 +255,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
phy->monitor_vif = NULL;
mt7996_mcu_add_dev_info(phy, vif, false);
mt7996_mcu_set_radio_en(phy, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
@@ -262,10 +263,10 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mutex_unlock(&dev->mt76.mutex);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
@@ -286,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy)
if (ret)
goto out;
mt7996_mac_set_timing(phy);
ret = mt7996_dfs_init_radar_detector(phy);
mt7996_mac_cca_stats_reset(phy);
@@ -505,7 +505,7 @@ static u8
mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
bool beacon, bool mcast)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt76_phy *mphy = hw->priv;
u16 rate;
u8 i, idx, ht;
@@ -517,7 +517,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt7996_dev *dev = mt7996_hw_dev(hw);
/* must odd index */
idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
return idx;
}
@@ -530,12 +530,32 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return mvif->basic_rates_idx;
}
static void
mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_dev *dev = mt7996_hw_dev(hw);
u8 band = mvif->mt76.band_idx;
u32 *mu;
mu = (u32 *)info->mu_group.membership;
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD0(band), mu[0]);
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD1(band), mu[1]);
mu = (u32 *)info->mu_group.position;
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS0(band), mu[0]);
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS1(band), mu[1]);
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS2(band), mu[2]);
mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]);
}
static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u64 changed)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_dev *dev = mt7996_hw_dev(hw);
@@ -563,7 +583,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
if (slottime != phy->slottime) {
phy->slottime = slottime;
mt7996_mac_set_timing(phy);
mt7996_mcu_set_timing(phy, vif);
}
}
@@ -602,6 +622,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
changed & BSS_CHANGED_FILS_DISCOVERY)
mt7996_mcu_beacon_inband_discov(dev, vif, changed);
if (changed & BSS_CHANGED_MU_GROUPS)
mt7996_update_mu_group(hw, vif, info);
mutex_unlock(&dev->mt76.mutex);
}
@@ -631,7 +654,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
INIT_LIST_HEAD(&msta->poll_list);
INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -666,12 +689,12 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
mt7996_mac_twt_teardown_flow(dev, msta, i);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->wcid.poll_list))
list_del_init(&msta->wcid.poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&mdev->sta_poll_lock);
}
static void mt7996_tx(struct ieee80211_hw *hw,
@@ -751,16 +774,16 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->ampdu_state);
clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7996_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
set_bit(tid, &msta->ampdu_state);
set_bit(tid, &msta->wcid.ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->ampdu_state);
clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7996_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@@ -792,7 +815,7 @@ mt7996_get_stats(struct ieee80211_hw *hw,
{
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_dev *dev = mt7996_hw_dev(hw);
struct mib_stats *mib = &phy->mib;
struct mt76_mib_stats *mib = &phy->mib;
mutex_lock(&dev->mt76.mutex);
@@ -903,7 +926,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
mutex_lock(&dev->mt76.mutex);
phy->coverage_class = max_t(s16, coverage_class, 0);
mt7996_mac_set_timing(phy);
mt7996_mac_set_coverage_class(phy);
mutex_unlock(&dev->mt76.mutex);
}
@@ -952,18 +975,19 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct rate_info *txrate = &msta->wcid.rate;
if (!txrate->legacy && !txrate->flags)
return;
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
if (txrate->legacy || txrate->flags) {
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
}
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
@@ -981,11 +1005,11 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
struct mt7996_dev *dev = msta->vif->phy->dev;
u32 *changed = data;
spin_lock_bh(&dev->sta_poll_lock);
spin_lock_bh(&dev->mt76.sta_poll_lock);
msta->changed |= *changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
@@ -1153,6 +1177,10 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {
"v_tx_mcs_11",
"v_tx_mcs_12",
"v_tx_mcs_13",
"v_tx_nss_1",
"v_tx_nss_2",
"v_tx_nss_3",
"v_tx_nss_4",
};
#define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats)
@@ -1186,7 +1214,7 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
if (msta->vif->mt76.idx != wi->idx)
return;
mt76_ethtool_worker(wi, &msta->stats, true);
mt76_ethtool_worker(wi, &msta->wcid.stats, true);
}
static
@@ -1197,11 +1225,11 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw,
struct mt7996_dev *dev = mt7996_hw_dev(hw);
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_mib_stats *mib = &phy->mib;
struct mt76_ethtool_worker_info wi = {
.data = data,
.idx = mvif->mt76.idx,
};
struct mib_stats *mib = &phy->mib;
/* See mt7996_ampdu_stat_read_phy, etc */
int i, ei = 0;
+143 -39
View File
@@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
return;
mphy = dev->mt76.phys[r->band_idx];
if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
mphy = dev->rdd2_phy->mt76;
else
mphy = dev->mt76.phys[r->band_idx];
if (!mphy)
return;
@@ -600,7 +604,7 @@ static void
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct mt7996_phy *phy)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct bss_rate_tlv *bmc;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
enum nl80211_band band = chandef->chan->band;
@@ -701,6 +705,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif,
sizeof(req), true);
}
static void
mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_phy *phy = mvif->phy;
struct bss_ifs_time_tlv *ifs_time;
struct tlv *tlv;
bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time));
ifs_time = (struct bss_ifs_time_tlv *)tlv;
ifs_time->slot_valid = true;
ifs_time->sifs_valid = true;
ifs_time->rifs_valid = true;
ifs_time->eifs_valid = true;
ifs_time->slot_time = cpu_to_le16(phy->slottime);
ifs_time->sifs_time = cpu_to_le16(10);
ifs_time->rifs_time = cpu_to_le16(2);
ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84);
if (is_2ghz) {
ifs_time->eifs_cck_valid = true;
ifs_time->eifs_cck_time = cpu_to_le16(314);
}
}
static int
mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
@@ -712,6 +744,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct cfg80211_chan_def *chandef = &phy->chandef;
struct mt76_connac_bss_basic_tlv *bss;
u32 type = CONNECTION_INFRA_AP;
u16 sta_wlan_idx = wlan_idx;
struct tlv *tlv;
int idx;
@@ -731,7 +764,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct mt76_wcid *wcid;
wcid = (struct mt76_wcid *)sta->drv_priv;
wlan_idx = wcid->idx;
sta_wlan_idx = wcid->idx;
}
rcu_read_unlock();
}
@@ -751,7 +784,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
bss->dtim_period = vif->bss_conf.dtim_period;
bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
bss->sta_idx = cpu_to_le16(wlan_idx);
bss->sta_idx = cpu_to_le16(sta_wlan_idx);
bss->conn_type = cpu_to_le32(type);
bss->omac_idx = mvif->omac_idx;
bss->band_idx = mvif->band_idx;
@@ -825,6 +858,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
mt7996_mcu_bss_ra_tlv(skb, vif, phy);
mt7996_mcu_bss_txcmd_tlv(skb, true);
mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
if (vif->bss_conf.he_support)
mt7996_mcu_bss_he_tlv(skb, vif, phy);
@@ -837,6 +871,23 @@ out:
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_dev *dev = phy->dev;
struct sk_buff *skb;
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
MT7996_BSS_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
mt7996_mcu_bss_ifs_timing_tlv(skb, vif);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
static int
mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
struct ieee80211_ampdu_params *params,
@@ -1050,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
}
}
static void
mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
if (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP)
return;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
muru = (struct sta_rec_muru *)tlv;
muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
vif->bss_conf.he_mu_beamformer ||
vif->bss_conf.vht_mu_beamformer ||
vif->bss_conf.vht_mu_beamformee;
muru->cfg.ofdma_dl_en = true;
if (sta->deflink.vht_cap.vht_supported)
muru->mimo_dl.vht_mu_bfee =
!!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
if (!sta->deflink.he_cap.has_he)
return;
muru->mimo_dl.partial_bw_dl_mimo =
HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);
muru->mimo_ul.full_ul_mimo =
HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);
muru->mimo_ul.partial_ul_mimo =
HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
muru->ofdma_dl.punc_pream_rx =
HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
muru->ofdma_dl.he_20m_in_40m_2g =
HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]);
muru->ofdma_dl.he_20m_in_160m =
HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
muru->ofdma_dl.he_80m_in_160m =
HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
muru->ofdma_ul.t_frame_dur =
HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
muru->ofdma_ul.mu_cascading =
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
muru->ofdma_ul.uo_ra =
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
}
static inline bool
mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
@@ -1727,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mt7996_mcu_sta_he_6g_tlv(skb, sta);
/* starec eht */
mt7996_mcu_sta_eht_tlv(skb, sta);
/* TODO: starec muru */
/* starec muru */
mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta);
/* starec bfee */
mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
/* starec hdr trans */
@@ -2155,7 +2260,7 @@ out:
static int
mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
const struct mt7996_fw_trailer *hdr,
const u8 *data, bool is_wa)
const u8 *data, enum mt7996_ram_type type)
{
int i, offset = 0;
u32 override = 0, option = 0;
@@ -2167,8 +2272,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
region = (const struct mt7996_fw_region *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
/* DSP and WA use same mode */
mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
region->feature_set, is_wa);
region->feature_set,
type != MT7996_RAM_TYPE_WM);
len = le32_to_cpu(region->len);
addr = le32_to_cpu(region->addr);
@@ -2195,19 +2302,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
if (override)
option |= FW_START_OVERRIDE;
if (is_wa)
if (type == MT7996_RAM_TYPE_WA)
option |= FW_START_WORKING_PDA_CR4;
else if (type == MT7996_RAM_TYPE_DSP)
option |= FW_START_WORKING_PDA_DSP;
return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
}
static int mt7996_load_ram(struct mt7996_dev *dev)
static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
const char *fw_file, enum mt7996_ram_type ram_type)
{
const struct mt7996_fw_trailer *hdr;
const struct firmware *fw;
int ret;
ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
ret = request_firmware(&fw, fw_file, dev->mt76.dev);
if (ret)
return ret;
@@ -2217,37 +2327,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
goto out;
}
hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n",
fw_type, hdr->fw_ver, hdr->build_date);
dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
goto out;
}
release_firmware(fw);
ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type);
goto out;
}
@@ -2261,6 +2347,24 @@ out:
return ret;
}
static int mt7996_load_ram(struct mt7996_dev *dev)
{
int ret;
ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
MT7996_RAM_TYPE_WM);
if (ret)
return ret;
ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP,
MT7996_RAM_TYPE_DSP);
if (ret)
return ret;
return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA,
MT7996_RAM_TYPE_WA);
}
static int
mt7996_firmware_state(struct mt7996_dev *dev, bool wa)
{
@@ -317,6 +317,22 @@ struct bss_sec_tlv {
u8 __rsv2[1];
} __packed;
struct bss_ifs_time_tlv {
__le16 tag;
__le16 len;
u8 slot_valid;
u8 sifs_valid;
u8 rifs_valid;
u8 eifs_valid;
__le16 slot_time;
__le16 sifs_time;
__le16 rifs_time;
__le16 eifs_time;
u8 eifs_cck_valid;
u8 rsv;
__le16 eifs_cck_time;
} __packed;
struct bss_power_save {
__le16 tag;
__le16 len;
@@ -552,6 +568,7 @@ enum {
sizeof(struct bss_txcmd_tlv) + \
sizeof(struct bss_power_save) + \
sizeof(struct bss_sec_tlv) + \
sizeof(struct bss_ifs_time_tlv) + \
sizeof(struct bss_mld_tlv))
#define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
@@ -26,15 +26,17 @@
#define MT7996_RX_RING_SIZE 1536
#define MT7996_RX_MCU_RING_SIZE 512
#define MT7996_RX_MCU_RING_SIZE_WA 1024
#define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
#define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
#define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
#define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
#define MT7996_EEPROM_SIZE 7680
#define MT7996_EEPROM_BLOCK_SIZE 16
#define MT7996_TOKEN_SIZE 8192
#define MT7996_TOKEN_SIZE 16384
#define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
@@ -52,6 +54,12 @@ struct mt7996_sta;
struct mt7996_dfs_pulse;
struct mt7996_dfs_pattern;
enum mt7996_ram_type {
MT7996_RAM_TYPE_WM,
MT7996_RAM_TYPE_WA,
MT7996_RAM_TYPE_DSP,
};
enum mt7996_txq_id {
MT7996_TXQ_FWDL = 16,
MT7996_TXQ_MCU_WM,
@@ -95,7 +103,6 @@ struct mt7996_sta {
struct mt7996_vif *vif;
struct list_head poll_list;
struct list_head rc_list;
u32 airtime_ac[8];
@@ -104,9 +111,6 @@ struct mt7996_sta {
unsigned long changed;
unsigned long jiffies;
unsigned long ampdu_state;
struct mt76_sta_stats stats;
struct mt76_connac_sta_key_conf bip;
@@ -124,64 +128,6 @@ struct mt7996_vif {
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct cfg80211_bitrate_mask bitrate_mask;
u8 basic_rates_idx;
u8 mcast_rates_idx;
u8 beacon_rates_idx;
};
/* per-phy stats. */
struct mib_stats {
u32 ack_fail_cnt;
u32 fcs_err_cnt;
u32 rts_cnt;
u32 rts_retries_cnt;
u32 ba_miss_cnt;
u32 tx_mu_bf_cnt;
u32 tx_mu_mpdu_cnt;
u32 tx_mu_acked_mpdu_cnt;
u32 tx_su_acked_mpdu_cnt;
u32 tx_bf_ibf_ppdu_cnt;
u32 tx_bf_ebf_ppdu_cnt;
u32 tx_bf_rx_fb_all_cnt;
u32 tx_bf_rx_fb_eht_cnt;
u32 tx_bf_rx_fb_he_cnt;
u32 tx_bf_rx_fb_vht_cnt;
u32 tx_bf_rx_fb_ht_cnt;
u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */
u32 tx_bf_rx_fb_nc_cnt;
u32 tx_bf_rx_fb_nr_cnt;
u32 tx_bf_fb_cpl_cnt;
u32 tx_bf_fb_trig_cnt;
u32 tx_ampdu_cnt;
u32 tx_stop_q_empty_cnt;
u32 tx_mpdu_attempts_cnt;
u32 tx_mpdu_success_cnt;
/* BF counter is PPDU-based, so remove MPDU-based BF counter */
u32 tx_rwp_fail_cnt;
u32 tx_rwp_need_cnt;
/* rx stats */
u32 rx_fifo_full_cnt;
u32 channel_idle_cnt;
u32 rx_vector_mismatch_cnt;
u32 rx_delimiter_fail_cnt;
u32 rx_len_mismatch_cnt;
u32 rx_mpdu_cnt;
u32 rx_ampdu_cnt;
u32 rx_ampdu_bytes_cnt;
u32 rx_ampdu_valid_subframe_cnt;
u32 rx_ampdu_valid_subframe_bytes_cnt;
u32 rx_pfdrop_cnt;
u32 rx_vec_queue_overflow_drop_cnt;
u32 rx_ba_cnt;
u32 tx_amsdu[8];
u32 tx_amsdu_cnt;
};
/* crash-dump */
@@ -222,7 +168,7 @@ struct mt7996_phy {
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
struct mt76_mib_stats mib;
struct mt76_channel_state state_ts;
};
@@ -272,9 +218,7 @@ struct mt7996_dev {
#endif
struct list_head sta_rc_list;
struct list_head sta_poll_list;
struct list_head twt_list;
spinlock_t sta_poll_lock;
u32 hw_pattern;
@@ -310,20 +254,6 @@ enum {
__MT_WFDMA_MAX,
};
enum {
MT_CTX0,
MT_HIF0 = 0x0,
MT_LMAC_AC00 = 0x0,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
MT_LMAC_PSMP0,
};
enum {
MT_RX_SEL0,
MT_RX_SEL1,
@@ -405,6 +335,7 @@ int mt7996_dma_init(struct mt7996_dev *dev);
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
void mt7996_dma_prefetch(struct mt7996_dev *dev);
void mt7996_dma_cleanup(struct mt7996_dev *dev);
void mt7996_dma_start(struct mt7996_dev *dev, bool reset);
void mt7996_init_txpower(struct mt7996_dev *dev,
struct ieee80211_supported_band *sband);
int mt7996_txbf_init(struct mt7996_dev *dev);
@@ -456,6 +387,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
const struct mt7996_dfs_pattern *pattern);
int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val);
@@ -519,7 +451,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed);
void mt7996_mac_set_timing(struct mt7996_phy *phy);
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
MODULE_FIRMWARE(MT7996_ROM_PATCH);
@@ -557,15 +557,6 @@ enum base_rev {
#define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188)
/* PHYRX CTRL */
#define MT_WF_PHYRX_BAND_BASE 0x83080000
#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
((_band) << 20) + (ofs))
#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
#define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
#define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
/* PHYRX CSD */
#define MT_WF_PHYRX_CSD_BASE 0x83000000
#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \
@@ -573,6 +564,22 @@ enum base_rev {
((_wf) << 16) + (ofs))
#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
/* PHYRX CTRL */
#define MT_WF_PHYRX_BAND_BASE 0x83080000
#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
((_band) << 20) + (ofs))
#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
#define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
#define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
/* PHYRX CSD BAND */
#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230)
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
@@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
[MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
[MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
[MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 },
+15 -1
View File
@@ -121,6 +121,7 @@ int
mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
int pid;
@@ -134,8 +135,14 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
return MT_PACKET_ID_NO_ACK;
if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
IEEE80211_TX_CTL_RATE_CTRL_PROBE))) {
if (mtk_wed_device_active(&dev->mmio.wed) &&
((info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) ||
ieee80211_is_data(hdr->frame_control)))
return MT_PACKET_ID_WED;
return MT_PACKET_ID_NO_SKB;
}
spin_lock_bh(&dev->status_lock);
@@ -263,8 +270,15 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
#endif
if (cb->pktid < MT_PACKET_ID_FIRST) {
struct ieee80211_rate_status rs = {};
hw = mt76_tx_status_get_hw(dev, skb);
status.sta = wcid_to_sta(wcid);
if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) {
rs.rate_idx = wcid->rate;
status.rates = &rs;
status.n_rates = 1;
}
spin_lock_bh(&dev->rx_lock);
ieee80211_tx_status_ext(hw, &status);
spin_unlock_bh(&dev->rx_lock);