mt76 patches for 6.4
- fixes - connac code unification - mt7921 p2p support - mt7996 mesh a-msdu support - mt7996 eht support - mt7996 coredump support -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCZD+h2wAKCRDXfRQdAqdu 9dqxAJ0cqAw0rJbQ39bq903geCEx7EZ5UgCfVG7zlnA+iAOee07ilmBwDJ8E7ho= =Ef06 -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2023-04-18' of https://github.com/nbd168/wireless mt76 patches for 6.4 - fixes - connac code unification - mt7921 p2p support - mt7996 mesh a-msdu support - mt7996 eht support - mt7996 coredump support
This commit is contained in:
Коммит
d2a158d113
|
@ -111,6 +111,11 @@ properties:
|
|||
$ref: /schemas/leds/common.yaml#
|
||||
additionalProperties: false
|
||||
properties:
|
||||
led-active-low:
|
||||
description:
|
||||
LED is enabled with ground signal.
|
||||
type: boolean
|
||||
|
||||
led-sources:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
@ -402,8 +402,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
|||
*info = le32_to_cpu(desc->info);
|
||||
|
||||
if (mt76_queue_is_wed_rx(q)) {
|
||||
u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
|
||||
le32_to_cpu(desc->buf1));
|
||||
u32 buf1 = le32_to_cpu(desc->buf1);
|
||||
u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
|
||||
struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
|
||||
|
||||
if (!t)
|
||||
|
@ -424,6 +424,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
|||
|
||||
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
|
||||
MT_DMA_CTL_DROP));
|
||||
|
||||
*drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
|
||||
}
|
||||
} else {
|
||||
buf = e->buf;
|
||||
|
@ -576,7 +578,9 @@ free:
|
|||
free_skb:
|
||||
status.skb = tx_info.skb;
|
||||
hw = mt76_tx_status_get_hw(dev, tx_info.skb);
|
||||
spin_lock_bh(&dev->rx_lock);
|
||||
ieee80211_tx_status_ext(hw, &status);
|
||||
spin_unlock_bh(&dev->rx_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -849,7 +853,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
|||
!(dev->drv->rx_check(dev, data, len)))
|
||||
goto free_frag;
|
||||
|
||||
skb = build_skb(data, q->buf_size);
|
||||
skb = napi_build_skb(data, q->buf_size);
|
||||
if (!skb)
|
||||
goto free_frag;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define MT_DMA_CTL_TO_HOST_A BIT(12)
|
||||
#define MT_DMA_CTL_DROP BIT(14)
|
||||
#define MT_DMA_CTL_TOKEN GENMASK(31, 16)
|
||||
#define MT_DMA_CTL_WO_DROP BIT(8)
|
||||
|
||||
#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
|
||||
#define MT_DMA_PPE_ENTRY GENMASK(30, 16)
|
||||
|
|
|
@ -418,7 +418,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
|||
SET_IEEE80211_DEV(hw, dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
|
||||
|
||||
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
|
||||
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
|
||||
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
|
||||
WIPHY_FLAG_SUPPORTS_TDLS |
|
||||
WIPHY_FLAG_AP_UAPSD;
|
||||
|
@ -1066,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
|
|||
status->enc_flags = mstat.enc_flags;
|
||||
status->encoding = mstat.encoding;
|
||||
status->bw = mstat.bw;
|
||||
status->he_ru = mstat.he_ru;
|
||||
status->he_gi = mstat.he_gi;
|
||||
status->he_dcm = mstat.he_dcm;
|
||||
if (status->encoding == RX_ENC_EHT) {
|
||||
status->eht.ru = mstat.eht.ru;
|
||||
status->eht.gi = mstat.eht.gi;
|
||||
} else {
|
||||
status->he_ru = mstat.he_ru;
|
||||
status->he_gi = mstat.he_gi;
|
||||
status->he_dcm = mstat.he_dcm;
|
||||
}
|
||||
status->rate_idx = mstat.rate_idx;
|
||||
status->nss = mstat.nss;
|
||||
status->band = mstat.band;
|
||||
|
@ -1303,7 +1309,8 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
|||
if (ps)
|
||||
set_bit(MT_WCID_FLAG_PS, &wcid->flags);
|
||||
|
||||
dev->drv->sta_ps(dev, sta, ps);
|
||||
if (dev->drv->sta_ps)
|
||||
dev->drv->sta_ps(dev, sta, ps);
|
||||
|
||||
if (!ps)
|
||||
clear_bit(MT_WCID_FLAG_PS, &wcid->flags);
|
||||
|
|
|
@ -621,12 +621,22 @@ struct mt76_rx_status {
|
|||
u16 freq;
|
||||
u32 flag;
|
||||
u8 enc_flags;
|
||||
u8 encoding:2, bw:3, he_ru:3;
|
||||
u8 he_gi:2, he_dcm:1;
|
||||
u8 encoding:3, bw:4;
|
||||
union {
|
||||
struct {
|
||||
u8 he_ru:3;
|
||||
u8 he_gi:2;
|
||||
u8 he_dcm:1;
|
||||
};
|
||||
struct {
|
||||
u8 ru:4;
|
||||
u8 gi:2;
|
||||
} eht;
|
||||
};
|
||||
|
||||
u8 amsdu:1, first_amsdu:1, last_amsdu:1;
|
||||
u8 rate_idx;
|
||||
u8 nss;
|
||||
u8 band;
|
||||
u8 nss:5, band:3;
|
||||
s8 signal;
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
|
@ -778,6 +788,7 @@ struct mt76_dev {
|
|||
spinlock_t rx_lock;
|
||||
struct napi_struct napi[__MT_RXQ_MAX];
|
||||
struct sk_buff_head rx_skb[__MT_RXQ_MAX];
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
struct list_head txwi_cache;
|
||||
struct list_head rxwi_cache;
|
||||
|
|
|
@ -1279,8 +1279,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
|
|||
if (wcidx >= MT7603_WTBL_STA || !sta)
|
||||
goto out;
|
||||
|
||||
if (mt7603_fill_txs(dev, msta, &info, txs_data))
|
||||
if (mt7603_fill_txs(dev, msta, &info, txs_data)) {
|
||||
spin_lock_bh(&dev->mt76.rx_lock);
|
||||
ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
|
||||
spin_unlock_bh(&dev->mt76.rx_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -76,7 +76,8 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
|
|||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
|
||||
if (napi_complete(napi))
|
||||
mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev));
|
||||
mt76_connac_irq_enable(&dev->mt76,
|
||||
mt7615_tx_mcu_int_mask(dev));
|
||||
|
||||
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
|
||||
|
||||
|
@ -297,7 +298,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
|
|||
else
|
||||
mask |= MT_INT_MCU_CMD;
|
||||
|
||||
mt7615_irq_enable(dev, mask);
|
||||
mt76_connac_irq_enable(&dev->mt76, mask);
|
||||
|
||||
mt7615_dma_start(dev);
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
|
|||
void *buf;
|
||||
u32 val;
|
||||
|
||||
if (is_mt7663(&dev->mt76))
|
||||
len = MT7663_EEPROM_SIZE;
|
||||
|
||||
val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
|
||||
if (val & MT_EFUSE_BASE_CTRL_EMPTY)
|
||||
return 0;
|
||||
|
@ -72,6 +75,8 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
|
|||
{
|
||||
int ret;
|
||||
|
||||
BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE);
|
||||
|
||||
ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -336,7 +341,7 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
|
|||
ret = mt7615_check_eeprom(&dev->mt76);
|
||||
if (ret && dev->mt76.otp.data) {
|
||||
memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
|
||||
MT7615_EEPROM_SIZE);
|
||||
dev->mt76.otp.size);
|
||||
} else {
|
||||
dev->flash_eeprom = true;
|
||||
mt7615_cal_free_data(dev);
|
||||
|
|
|
@ -46,7 +46,7 @@ enum mt7615_eeprom_field {
|
|||
|
||||
MT7615_EE_MAX = 0x3bf,
|
||||
MT7622_EE_MAX = 0x3db,
|
||||
MT7663_EE_MAX = 0x400,
|
||||
MT7663_EE_MAX = 0x600,
|
||||
};
|
||||
|
||||
#define MT_EE_RATE_POWER_MASK GENMASK(5, 0)
|
||||
|
|
|
@ -396,6 +396,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
|
|||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
|
||||
|
|
|
@ -655,11 +655,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_sta_ps);
|
||||
|
||||
static u16
|
||||
mt7615_mac_tx_rate_val(struct mt7615_dev *dev,
|
||||
struct mt76_phy *mphy,
|
||||
|
@ -1558,8 +1553,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
|
|||
if (wcid->phy_idx && dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (mt7615_fill_txs(dev, msta, &info, txs_data))
|
||||
if (mt7615_fill_txs(dev, msta, &info, txs_data)) {
|
||||
spin_lock_bh(&dev->mt76.rx_lock);
|
||||
ieee80211_tx_status_noskb(mphy->hw, sta, &info);
|
||||
spin_unlock_bh(&dev->mt76.rx_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
@ -2380,7 +2378,7 @@ void mt7615_coredump_work(struct work_struct *work)
|
|||
break;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
|
||||
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
|
||||
if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
@ -2390,6 +2388,8 @@ void mt7615_coredump_work(struct work_struct *work)
|
|||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (dump)
|
||||
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
|
|
@ -19,18 +19,6 @@
|
|||
#define MT_RXD0_NORMAL_GROUP_3 BIT(27)
|
||||
#define MT_RXD0_NORMAL_GROUP_4 BIT(28)
|
||||
|
||||
enum rx_pkt_type {
|
||||
PKT_TYPE_TXS,
|
||||
PKT_TYPE_TXRXV,
|
||||
PKT_TYPE_NORMAL,
|
||||
PKT_TYPE_RX_DUP_RFB,
|
||||
PKT_TYPE_RX_TMR,
|
||||
PKT_TYPE_RETRIEVE,
|
||||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_NORMAL_MCU,
|
||||
};
|
||||
|
||||
#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
|
||||
#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
|
||||
#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0)
|
||||
|
|
|
@ -163,16 +163,16 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
|||
cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND)) {
|
||||
struct mt7615_mcu_uni_event *event;
|
||||
struct mt76_connac_mcu_uni_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt7615_mcu_uni_event *)skb->data;
|
||||
event = (struct mt76_connac_mcu_uni_event *)skb->data;
|
||||
ret = le32_to_cpu(event->status);
|
||||
} else if (cmd == MCU_CE_QUERY(REG_READ)) {
|
||||
struct mt7615_mcu_reg_event *event;
|
||||
struct mt76_connac_mcu_reg_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt7615_mcu_reg_event *)skb->data;
|
||||
event = (struct mt76_connac_mcu_reg_event *)skb->data;
|
||||
ret = (int)le32_to_cpu(event->val);
|
||||
}
|
||||
|
||||
|
@ -861,7 +861,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
|||
else
|
||||
mvif->sta_added = true;
|
||||
}
|
||||
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry);
|
||||
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, vif, sta, enable,
|
||||
new_entry);
|
||||
if (enable && sta)
|
||||
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
|
|
|
@ -206,17 +206,6 @@ enum {
|
|||
MCU_ATE_SET_TX_POWER_CONTROL = 0x15,
|
||||
};
|
||||
|
||||
struct mt7615_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 pad[3];
|
||||
__le32 status; /* 0: success, others: fail */
|
||||
} __packed;
|
||||
|
||||
struct mt7615_mcu_reg_event {
|
||||
__le32 reg;
|
||||
__le32 val;
|
||||
} __packed;
|
||||
|
||||
struct mt7615_roc_tlv {
|
||||
u8 bss_idx;
|
||||
u8 token;
|
||||
|
|
|
@ -66,9 +66,7 @@ const u32 mt7663e_reg_map[] = {
|
|||
static void
|
||||
mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
|
||||
{
|
||||
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
|
||||
mt7615_irq_enable(dev, MT_INT_RX_DONE(q));
|
||||
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE(q));
|
||||
}
|
||||
|
||||
static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
|
||||
|
@ -80,14 +78,14 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
|
|||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return IRQ_NONE;
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mt7615_irq_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet);
|
||||
struct mt7615_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
|
||||
u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);
|
||||
u32 mcu_int;
|
||||
|
||||
|
@ -181,7 +179,6 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
|
|||
.rx_check = mt7615_rx_check,
|
||||
.rx_skb = mt7615_queue_rx_skb,
|
||||
.rx_poll_complete = mt7615_rx_poll_complete,
|
||||
.sta_ps = mt7615_sta_ps,
|
||||
.sta_add = mt7615_mac_sta_add,
|
||||
.sta_remove = mt7615_mac_sta_remove,
|
||||
.update_survey = mt7615_update_channel,
|
||||
|
@ -202,7 +199,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
|
|||
|
||||
dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
mt76_mmio_init(&dev->mt76, mem_base);
|
||||
tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet);
|
||||
tasklet_setup(&mdev->irq_tasklet, mt7615_irq_tasklet);
|
||||
|
||||
dev->reg_map = map;
|
||||
dev->ops = ops;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#define MT7663_FIRMWARE_N9 "mediatek/mt7663_n9_rebb.bin"
|
||||
|
||||
#define MT7615_EEPROM_SIZE 1024
|
||||
#define MT7663_EEPROM_SIZE 1536
|
||||
#define MT7615_TOKEN_SIZE 4096
|
||||
|
||||
#define MT_FRAC_SCALE 12
|
||||
|
@ -245,8 +246,6 @@ struct mt7615_dev {
|
|||
};
|
||||
|
||||
const struct mt76_bus_ops *bus_ops;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
struct mt7615_phy phy;
|
||||
u64 omac_mask;
|
||||
|
||||
|
@ -412,13 +411,6 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb);
|
|||
int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev);
|
||||
int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl);
|
||||
|
||||
static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
|
||||
{
|
||||
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
}
|
||||
|
||||
static inline bool mt7615_firmware_offload(struct mt7615_dev *dev)
|
||||
{
|
||||
return dev->fw_ver > MT7615_FIRMWARE_V2;
|
||||
|
@ -520,7 +512,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev);
|
|||
bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
|
||||
int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
|
|
|
@ -94,7 +94,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
mt76_for_each_q_rx(mdev, i) {
|
||||
napi_disable(&mdev->napi[i]);
|
||||
}
|
||||
tasklet_kill(&dev->irq_tasklet);
|
||||
tasklet_kill(&mdev->irq_tasklet);
|
||||
|
||||
mt7615_dma_reset(dev);
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev)
|
|||
|
||||
mt7615_tx_token_put(dev);
|
||||
mt7615_dma_cleanup(dev);
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
tasklet_disable(&dev->mt76.irq_tasklet);
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ static int mt7663s_probe(struct sdio_func *func,
|
|||
.tx_status_data = mt7663_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7615_queue_rx_skb,
|
||||
.rx_check = mt7615_rx_check,
|
||||
.sta_ps = mt7615_sta_ps,
|
||||
.sta_add = mt7615_mac_sta_add,
|
||||
.sta_remove = mt7615_mac_sta_remove,
|
||||
.update_survey = mt7615_update_channel,
|
||||
|
|
|
@ -120,7 +120,6 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
|||
.tx_status_data = mt7663_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7615_queue_rx_skb,
|
||||
.rx_check = mt7615_rx_check,
|
||||
.sta_ps = mt7615_sta_ps,
|
||||
.sta_add = mt7615_mac_sta_add,
|
||||
.sta_remove = mt7615_mac_sta_remove,
|
||||
.update_survey = mt7615_update_channel,
|
||||
|
|
|
@ -6,6 +6,20 @@
|
|||
|
||||
#include "mt76.h"
|
||||
|
||||
enum rx_pkt_type {
|
||||
PKT_TYPE_TXS,
|
||||
PKT_TYPE_TXRXV,
|
||||
PKT_TYPE_NORMAL,
|
||||
PKT_TYPE_RX_DUP_RFB,
|
||||
PKT_TYPE_RX_TMR,
|
||||
PKT_TYPE_RETRIEVE,
|
||||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_NORMAL_MCU,
|
||||
PKT_TYPE_RX_FW_MONITOR = 0x0c,
|
||||
PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
|
||||
};
|
||||
|
||||
#define MT76_CONNAC_SCAN_IE_LEN 600
|
||||
#define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL 10
|
||||
#define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX
|
||||
|
@ -279,6 +293,12 @@ static inline u8 mt76_connac_spe_idx(u8 antenna_mask)
|
|||
return ant_to_spe[antenna_mask];
|
||||
}
|
||||
|
||||
static inline void mt76_connac_irq_enable(struct mt76_dev *dev, u32 mask)
|
||||
{
|
||||
mt76_set_irq_mask(dev, 0, 0, mask);
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
}
|
||||
|
||||
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
|
||||
void mt76_connac_power_save_sched(struct mt76_phy *phy,
|
||||
struct mt76_connac_pm *pm);
|
||||
|
@ -353,6 +373,7 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
|
|||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
|
||||
void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss);
|
||||
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
||||
int ring_base, u32 flags);
|
||||
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
|
|
|
@ -32,6 +32,16 @@ enum {
|
|||
MT_LMAC_PSMP0,
|
||||
};
|
||||
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
|
||||
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
|
||||
/* 0: success, others: dropped */
|
||||
#define MT_TX_FREE_STATUS GENMASK(14, 13)
|
||||
#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
|
||||
#define MT_TX_FREE_PAIR BIT(31)
|
||||
/* will support this field in further revision */
|
||||
#define MT_TX_FREE_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXD0_Q_IDX GENMASK(31, 25)
|
||||
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
|
||||
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
|
||||
|
@ -166,6 +176,15 @@ enum {
|
|||
|
||||
#define MT_TXS7_MPDU_RETRY_CNT GENMASK(31, 23)
|
||||
|
||||
/* RXD DW0 */
|
||||
#define MT_RXD0_LENGTH GENMASK(15, 0)
|
||||
#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
|
||||
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
|
||||
|
||||
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
|
||||
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
|
||||
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
|
||||
|
||||
/* RXD DW1 */
|
||||
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
|
||||
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
|
||||
|
@ -308,6 +327,9 @@ enum {
|
|||
#define MT_CRXV_FOE_HI GENMASK(6, 0)
|
||||
#define MT_CRXV_FOE_SHIFT 13
|
||||
|
||||
#define MT_CT_PARSE_LEN 72
|
||||
#define MT_CT_DMA_BUF_NUM 2
|
||||
|
||||
#define MT_CT_INFO_APPLY_TXD BIT(0)
|
||||
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
|
||||
#define MT_CT_INFO_MGMT_FRAME BIT(2)
|
||||
|
|
|
@ -9,6 +9,27 @@
|
|||
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
|
||||
IEEE80211_RADIOTAP_HE_##f)
|
||||
|
||||
void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = { 0x1c, 0xc7, 0x71 };
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
ru_bit_mask);
|
||||
|
||||
ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
|
||||
nss * hweight8(ru_bit_mask) * 2;
|
||||
ppet_size = DIV_ROUND_UP(ppet_bits, 8);
|
||||
|
||||
for (i = 0; i < ppet_size - 1; i++)
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
|
||||
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
|
||||
(0xff >> (8 - (ppet_bits - 1) % 8));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_gen_ppe_thresh);
|
||||
|
||||
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
|
@ -267,11 +288,29 @@ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
|
||||
|
||||
#define __bitrate_mask_check(_mcs, _mode) \
|
||||
({ \
|
||||
u8 i = 0; \
|
||||
for (nss = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
|
||||
if (!mask->control[band]._mcs[i]) \
|
||||
continue; \
|
||||
if (hweight16(mask->control[band]._mcs[i]) == 1) { \
|
||||
mode = MT_PHY_TYPE_##_mode; \
|
||||
rateidx = ffs(mask->control[band]._mcs[i]) - 1; \
|
||||
if (mode == MT_PHY_TYPE_HT) \
|
||||
rateidx += 8 * i; \
|
||||
else \
|
||||
nss = i + 1; \
|
||||
goto out; \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
|
||||
u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
{
|
||||
u8 mode = 0, band = mphy->chandef.chan->band;
|
||||
u8 nss = 0, mode = 0, band = mphy->chandef.chan->band;
|
||||
int rateidx = 0, mcast_rate;
|
||||
|
||||
if (!vif)
|
||||
|
@ -286,19 +325,12 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
|||
struct cfg80211_bitrate_mask *mask;
|
||||
|
||||
mask = &vif->bss_conf.beacon_tx_rate;
|
||||
if (hweight16(mask->control[band].he_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HE_SU;
|
||||
goto out;
|
||||
} else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_VHT;
|
||||
goto out;
|
||||
} else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HT;
|
||||
goto out;
|
||||
} else if (hweight32(mask->control[band].legacy) == 1) {
|
||||
|
||||
__bitrate_mask_check(he_mcs, HE_SU);
|
||||
__bitrate_mask_check(vht_mcs, VHT);
|
||||
__bitrate_mask_check(ht_mcs, HT);
|
||||
|
||||
if (hweight32(mask->control[band].legacy) == 1) {
|
||||
rateidx = ffs(mask->control[band].legacy) - 1;
|
||||
goto legacy;
|
||||
}
|
||||
|
@ -314,9 +346,9 @@ legacy:
|
|||
rateidx = mt76_calculate_default_rate(mphy, rateidx);
|
||||
mode = rateidx >> 8;
|
||||
rateidx &= GENMASK(7, 0);
|
||||
|
||||
out:
|
||||
return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
|
||||
return FIELD_PREP(MT_TX_RATE_NSS, nss) |
|
||||
FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
|
||||
FIELD_PREP(MT_TX_RATE_MODE, mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_tx_rate_val);
|
||||
|
@ -537,7 +569,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
|||
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
|
||||
/* Fixed rata is available just for 802.11 txd */
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
bool multicast = ieee80211_is_data(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1);
|
||||
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
|
||||
multicast);
|
||||
u32 val = MT_TXD6_FIXED_BW;
|
||||
|
@ -582,6 +615,17 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||
le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
|
||||
stats->tx_retries +=
|
||||
le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT);
|
||||
|
||||
if (wcid->sta) {
|
||||
struct ieee80211_sta *sta;
|
||||
u8 tid;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta,
|
||||
drv_priv);
|
||||
tid = FIELD_GET(MT_TXS0_TID, txs);
|
||||
|
||||
ieee80211_refresh_tx_agg_session_timer(sta, tid);
|
||||
}
|
||||
}
|
||||
|
||||
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
|
||||
|
|
|
@ -363,7 +363,7 @@ void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv);
|
||||
|
||||
void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
|
||||
void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
bool enable, bool newly)
|
||||
|
@ -394,7 +394,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
|
|||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (vif->p2p)
|
||||
if (vif->p2p && !is_mt7921(dev))
|
||||
conn_type = CONNECTION_P2P_GC;
|
||||
else
|
||||
conn_type = CONNECTION_INFRA_STA;
|
||||
|
@ -402,7 +402,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
|
|||
basic->aid = cpu_to_le16(sta->aid);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->p2p)
|
||||
if (vif->p2p && !is_mt7921(dev))
|
||||
conn_type = CONNECTION_P2P_GO;
|
||||
else
|
||||
conn_type = CONNECTION_INFRA_AP;
|
||||
|
@ -1029,7 +1029,7 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
return PTR_ERR(skb);
|
||||
|
||||
if (info->sta || !info->offload_fw)
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta,
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta,
|
||||
info->enable, info->newly);
|
||||
if (info->sta && info->enable)
|
||||
mt76_connac_mcu_sta_tlv(phy, skb, info->sta,
|
||||
|
@ -1678,8 +1678,16 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
req->channel_min_dwell_time = cpu_to_le16(duration);
|
||||
req->channel_dwell_time = cpu_to_le16(duration);
|
||||
|
||||
req->channels_num = min_t(u8, sreq->n_channels, 32);
|
||||
req->ext_channels_num = min_t(u8, ext_channels_num, 32);
|
||||
if (sreq->n_channels == 0 || sreq->n_channels > 64) {
|
||||
req->channel_type = 0;
|
||||
req->channels_num = 0;
|
||||
req->ext_channels_num = 0;
|
||||
} else {
|
||||
req->channel_type = 4;
|
||||
req->channels_num = min_t(u8, sreq->n_channels, 32);
|
||||
req->ext_channels_num = min_t(u8, ext_channels_num, 32);
|
||||
}
|
||||
|
||||
for (i = 0; i < req->channels_num + req->ext_channels_num; i++) {
|
||||
if (i >= 32)
|
||||
chan = &req->ext_channels[i - 32];
|
||||
|
@ -1699,7 +1707,6 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
|||
}
|
||||
chan->channel_num = scan_list[i]->hw_value;
|
||||
}
|
||||
req->channel_type = sreq->n_channels ? 4 : 0;
|
||||
|
||||
if (sreq->ie_len > 0) {
|
||||
memcpy(req->ies, sreq->ie, sreq->ie_len);
|
||||
|
|
|
@ -127,7 +127,7 @@ struct mt76_connac2_mcu_rxd {
|
|||
u8 rsv1[2];
|
||||
u8 s2d_index;
|
||||
|
||||
u8 tlv[0];
|
||||
u8 tlv[];
|
||||
};
|
||||
|
||||
struct mt76_connac2_patch_hdr {
|
||||
|
@ -967,9 +967,6 @@ enum {
|
|||
DEV_INFO_MAX_NUM
|
||||
};
|
||||
|
||||
#define MCU_UNI_CMD_EVENT BIT(1)
|
||||
#define MCU_UNI_CMD_UNSOLICITED_EVENT BIT(2)
|
||||
|
||||
/* event table */
|
||||
enum {
|
||||
MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
|
||||
|
@ -1224,6 +1221,7 @@ enum {
|
|||
MCU_UNI_CMD_VOW = 0x37,
|
||||
MCU_UNI_CMD_RRO = 0x57,
|
||||
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
|
||||
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -1692,6 +1690,17 @@ struct mt76_connac_config {
|
|||
u8 data[320];
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 pad[3];
|
||||
__le32 status; /* 0: success, others: fail */
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_mcu_reg_event {
|
||||
__le32 reg;
|
||||
__le32 val;
|
||||
} __packed;
|
||||
|
||||
static inline enum mcu_cipher_type
|
||||
mt76_connac_mcu_get_cipher(int cipher)
|
||||
{
|
||||
|
@ -1779,7 +1788,7 @@ mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len)
|
|||
|
||||
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
|
||||
int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
|
||||
void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
|
||||
void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enable,
|
||||
bool newly);
|
||||
|
|
|
@ -631,8 +631,11 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
|||
|
||||
mt76_tx_status_unlock(mdev, &list);
|
||||
|
||||
if (!status.skb)
|
||||
if (!status.skb) {
|
||||
spin_lock_bh(&dev->mt76.rx_lock);
|
||||
ieee80211_tx_status_ext(mt76_hw(dev), &status);
|
||||
spin_unlock_bh(&dev->mt76.rx_lock);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
goto out;
|
||||
|
|
|
@ -958,10 +958,10 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data)
|
|||
|
||||
DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
|
||||
|
||||
#define mt7915_txpower_puts(prefix, rate) \
|
||||
#define mt7915_txpower_puts(rate) \
|
||||
({ \
|
||||
len += scnprintf(buf + len, sz - len, "%-16s:", #prefix " (tmac)"); \
|
||||
for (i = 0; i < mt7915_sku_group_len[rate]; i++, offs++) \
|
||||
len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \
|
||||
for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \
|
||||
len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \
|
||||
len += scnprintf(buf + len, sz - len, "\n"); \
|
||||
})
|
||||
|
@ -1004,41 +1004,41 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
|
|||
phy != &dev->phy, phy->mt76->chandef.chan->hw_value);
|
||||
len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n",
|
||||
" ", "1m", "2m", "5m", "11m");
|
||||
mt7915_txpower_puts(CCK, SKU_CCK);
|
||||
mt7915_txpower_puts(CCK);
|
||||
|
||||
len += scnprintf(buf + len, sz - len,
|
||||
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
|
||||
"54m");
|
||||
mt7915_txpower_puts(OFDM, SKU_OFDM);
|
||||
mt7915_txpower_puts(OFDM);
|
||||
|
||||
len += scnprintf(buf + len, sz - len,
|
||||
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
|
||||
"mcs5", "mcs6", "mcs7");
|
||||
mt7915_txpower_puts(HT20, SKU_HT_BW20);
|
||||
mt7915_txpower_puts(HT_BW20);
|
||||
|
||||
len += scnprintf(buf + len, sz - len,
|
||||
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7", "mcs32");
|
||||
mt7915_txpower_puts(HT40, SKU_HT_BW40);
|
||||
mt7915_txpower_puts(HT_BW40);
|
||||
|
||||
len += scnprintf(buf + len, sz - len,
|
||||
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
|
||||
mt7915_txpower_puts(VHT20, SKU_VHT_BW20);
|
||||
mt7915_txpower_puts(VHT40, SKU_VHT_BW40);
|
||||
mt7915_txpower_puts(VHT80, SKU_VHT_BW80);
|
||||
mt7915_txpower_puts(VHT160, SKU_VHT_BW160);
|
||||
mt7915_txpower_puts(HE26, SKU_HE_RU26);
|
||||
mt7915_txpower_puts(HE52, SKU_HE_RU52);
|
||||
mt7915_txpower_puts(HE106, SKU_HE_RU106);
|
||||
mt7915_txpower_puts(HE242, SKU_HE_RU242);
|
||||
mt7915_txpower_puts(HE484, SKU_HE_RU484);
|
||||
mt7915_txpower_puts(HE996, SKU_HE_RU996);
|
||||
mt7915_txpower_puts(HE996x2, SKU_HE_RU2x996);
|
||||
mt7915_txpower_puts(VHT_BW20);
|
||||
mt7915_txpower_puts(VHT_BW40);
|
||||
mt7915_txpower_puts(VHT_BW80);
|
||||
mt7915_txpower_puts(VHT_BW160);
|
||||
mt7915_txpower_puts(HE_RU26);
|
||||
mt7915_txpower_puts(HE_RU52);
|
||||
mt7915_txpower_puts(HE_RU106);
|
||||
mt7915_txpower_puts(HE_RU242);
|
||||
mt7915_txpower_puts(HE_RU484);
|
||||
mt7915_txpower_puts(HE_RU996);
|
||||
mt7915_txpower_puts(HE_RU2x996);
|
||||
|
||||
reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) :
|
||||
MT_WF_PHY_TPC_CTRL_STAT_MT7916(band);
|
||||
|
|
|
@ -87,8 +87,14 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
|
|||
MT7916_RXQ_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916,
|
||||
MT7916_RXQ_MCU_WA);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
|
||||
MT7916_RXQ_BAND1);
|
||||
if (dev->hif2)
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0,
|
||||
MT_INT_RX_DONE_BAND1_MT7916,
|
||||
MT7916_RXQ_BAND1);
|
||||
else
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0,
|
||||
MT_INT_WED_RX_DONE_BAND1_MT7916,
|
||||
MT7916_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916,
|
||||
MT7916_RXQ_MCU_WA_MAIN);
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0,
|
||||
|
|
|
@ -89,6 +89,7 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
|
|||
val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) {
|
||||
dev_err(phy->dev->mt76.dev,
|
||||
"temp1_max shall be greater than temp1_crit.");
|
||||
mutex_unlock(&phy->dev->mt76.mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -202,6 +203,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
|
|||
phy->cdev = cdev;
|
||||
}
|
||||
|
||||
/* initialize critical/maximum high temperature */
|
||||
phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
|
||||
phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
|
||||
|
||||
if (!IS_REACHABLE(CONFIG_HWMON))
|
||||
return 0;
|
||||
|
||||
|
@ -210,10 +215,6 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
|
|||
if (IS_ERR(hwmon))
|
||||
return PTR_ERR(hwmon);
|
||||
|
||||
/* initialize critical/maximum high temperature */
|
||||
phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
|
||||
phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -368,6 +369,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
|||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
|
||||
|
@ -930,27 +932,6 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
ru_bit_mask);
|
||||
|
||||
ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
|
||||
nss * hweight8(ru_bit_mask) * 2;
|
||||
ppet_size = DIV_ROUND_UP(ppet_bits, 8);
|
||||
|
||||
for (i = 0; i < ppet_size - 1; i++)
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
|
||||
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
|
||||
(0xff >> (8 - (ppet_bits - 1) % 8));
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data)
|
||||
|
@ -1100,7 +1081,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
|||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
|
@ -1179,7 +1160,7 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
|
|||
mt7915_mcu_exit(dev);
|
||||
mt7915_tx_token_put(dev);
|
||||
mt7915_dma_cleanup(dev);
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
tasklet_disable(&dev->mt76.irq_tasklet);
|
||||
|
||||
if (is_mt7986(&dev->mt76))
|
||||
mt7986_wmac_disable(dev);
|
||||
|
|
|
@ -73,10 +73,6 @@ static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev,
|
|||
return &sta->vif->sta.wcid;
|
||||
}
|
||||
|
||||
void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
|
||||
{
|
||||
}
|
||||
|
||||
bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
|
||||
{
|
||||
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
|
||||
|
@ -1627,7 +1623,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
|
|||
}
|
||||
local_bh_enable();
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
|
||||
mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
|
||||
|
|
|
@ -6,43 +6,12 @@
|
|||
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
#define MT_CT_PARSE_LEN 72
|
||||
#define MT_CT_DMA_BUF_NUM 2
|
||||
|
||||
#define MT_RXD0_LENGTH GENMASK(15, 0)
|
||||
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
|
||||
|
||||
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
|
||||
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
|
||||
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
|
||||
|
||||
enum rx_pkt_type {
|
||||
PKT_TYPE_TXS,
|
||||
PKT_TYPE_TXRXV,
|
||||
PKT_TYPE_NORMAL,
|
||||
PKT_TYPE_RX_DUP_RFB,
|
||||
PKT_TYPE_RX_TMR,
|
||||
PKT_TYPE_RETRIEVE,
|
||||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_RX_FW_MONITOR = 0x0c,
|
||||
PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
|
||||
};
|
||||
|
||||
#define MT_TX_FREE_VER GENMASK(18, 16)
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
|
||||
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
|
||||
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
|
||||
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
|
||||
/* 0: success, others: dropped */
|
||||
#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
|
||||
#define MT_TX_FREE_PAIR BIT(31)
|
||||
#define MT_TX_FREE_MPDU_HEADER BIT(30)
|
||||
#define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0)
|
||||
|
||||
/* will support this field in further revision */
|
||||
#define MT_TX_FREE_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
|
||||
#define MT_TXS5_F0_QOS BIT(30)
|
||||
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
|
||||
|
|
|
@ -269,7 +269,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
|||
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
|
||||
|
||||
mt7915_init_bitrate_mask(vif);
|
||||
memset(&mvif->cap, -1, sizeof(mvif->cap));
|
||||
|
||||
mt7915_mcu_add_bss_info(phy, vif, true);
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, true);
|
||||
|
|
|
@ -706,7 +706,6 @@ static void
|
|||
mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
|
||||
struct ieee80211_he_mcs_nss_supp mcs_map;
|
||||
struct sta_rec_he *he;
|
||||
|
@ -740,7 +739,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
|||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
|
||||
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
|
||||
|
||||
if (mvif->cap.he_ldpc &&
|
||||
if (vif->bss_conf.he_ldpc &&
|
||||
(elem->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
cap |= STA_REC_HE_CAP_LDPC;
|
||||
|
@ -849,7 +848,6 @@ static void
|
|||
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
|
||||
struct sta_rec_muru *muru;
|
||||
struct tlv *tlv;
|
||||
|
@ -862,9 +860,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
|||
|
||||
muru = (struct sta_rec_muru *)tlv;
|
||||
|
||||
muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
|
||||
mvif->cap.vht_mu_ebfer ||
|
||||
mvif->cap.vht_mu_ebfee;
|
||||
muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer ||
|
||||
vif->bss_conf.vht_mu_beamformer ||
|
||||
vif->bss_conf.vht_mu_beamformee;
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
muru->cfg.mimo_ul_en = true;
|
||||
muru->cfg.ofdma_dl_en = true;
|
||||
|
@ -997,8 +995,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
|||
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
|
||||
wtbl_hdr, mvif->cap.ht_ldpc,
|
||||
mvif->cap.vht_ldpc);
|
||||
wtbl_hdr, vif->bss_conf.ht_ldpc,
|
||||
vif->bss_conf.vht_ldpc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1007,7 +1005,6 @@ static inline bool
|
|||
mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool bfee)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
|
@ -1021,10 +1018,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.he_su_ebfee &&
|
||||
return vif->bss_conf.he_su_beamformee &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
else
|
||||
return mvif->cap.he_su_ebfer &&
|
||||
return vif->bss_conf.he_su_beamformer &&
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
|
||||
}
|
||||
|
||||
|
@ -1032,10 +1029,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
u32 cap = sta->deflink.vht_cap.cap;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.vht_su_ebfee &&
|
||||
return vif->bss_conf.vht_su_beamformee &&
|
||||
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
else
|
||||
return mvif->cap.vht_su_ebfer &&
|
||||
return vif->bss_conf.vht_su_beamformer &&
|
||||
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
|
||||
}
|
||||
|
||||
|
@ -1530,7 +1527,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
|||
cap |= STA_CAP_TX_STBC;
|
||||
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
cap |= STA_CAP_RX_STBC;
|
||||
if (mvif->cap.ht_ldpc &&
|
||||
if (vif->bss_conf.ht_ldpc &&
|
||||
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
|
||||
cap |= STA_CAP_LDPC;
|
||||
|
||||
|
@ -1556,7 +1553,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
|||
cap |= STA_CAP_VHT_TX_STBC;
|
||||
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
|
||||
cap |= STA_CAP_VHT_RX_STBC;
|
||||
if (mvif->cap.vht_ldpc &&
|
||||
if (vif->bss_conf.vht_ldpc &&
|
||||
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
|
||||
cap |= STA_CAP_VHT_LDPC;
|
||||
|
||||
|
@ -1657,8 +1654,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
return PTR_ERR(skb);
|
||||
|
||||
/* starec basic */
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
|
||||
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
|
||||
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable,
|
||||
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
|
@ -1875,84 +1872,6 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct mt7915_vif_cap *vc = &mvif->cap;
|
||||
const struct ieee80211_he_cap_elem *he;
|
||||
const struct ieee80211_vht_cap *vht;
|
||||
const struct ieee80211_ht_cap *ht;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
const u8 *ie;
|
||||
u32 len, bc;
|
||||
|
||||
/* Check missing configuration options to allow AP mode in mac80211
|
||||
* to remain in sync with hostapd settings, and get a subset of
|
||||
* beacon and hardware capabilities.
|
||||
*/
|
||||
if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data)))
|
||||
return;
|
||||
|
||||
memset(vc, 0, sizeof(*vc));
|
||||
|
||||
len = skb->len - (mgmt->u.beacon.variable - skb->data);
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
len);
|
||||
if (ie && ie[1] >= sizeof(*ht)) {
|
||||
ht = (void *)(ie + 2);
|
||||
vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
len);
|
||||
if (ie && ie[1] >= sizeof(*vht)) {
|
||||
u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap;
|
||||
|
||||
vht = (void *)(ie + 2);
|
||||
bc = le32_to_cpu(vht->vht_cap_info);
|
||||
|
||||
vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_su_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
vc->vht_su_ebfee =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
|
||||
vc->vht_mu_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
|
||||
vc->vht_mu_ebfee =
|
||||
(bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY,
|
||||
mgmt->u.beacon.variable, len);
|
||||
if (ie && ie[1] >= sizeof(*he) + 1) {
|
||||
const struct ieee80211_sta_he_cap *pc =
|
||||
mt76_connac_get_he_phy_cap(phy->mt76, vif);
|
||||
const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
|
||||
|
||||
he = (void *)(ie + 3);
|
||||
|
||||
vc->he_ldpc =
|
||||
HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
|
||||
vc->he_su_ebfer =
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
vc->he_su_ebfee =
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) &&
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
|
||||
vc->he_mu_ebfer =
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) &&
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct bss_info_bcn *bcn,
|
||||
|
@ -2063,8 +1982,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
|
||||
|
||||
mt7915_mcu_beacon_check_caps(phy, vif, skb);
|
||||
|
||||
mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
|
||||
mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
|
||||
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
|
@ -2370,7 +2287,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76))
|
||||
if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
|
||||
is_mt7915(&dev->mt76)) ||
|
||||
!mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
|
||||
mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
|
||||
|
||||
ret = mt7915_mcu_set_mwds(dev, 1);
|
||||
|
|
|
@ -916,7 +916,7 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
|
|||
/* TODO: support 2/4/6/8 MSI-X vectors */
|
||||
static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
|
||||
struct mt7915_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
u32 intr, intr1, mask;
|
||||
|
||||
|
@ -989,18 +989,18 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
|
|||
struct mt7915_dev *dev = dev_instance;
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
if (mtk_wed_device_active(wed))
|
||||
mtk_wed_device_irq_set_mask(wed, 0);
|
||||
} else {
|
||||
else
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
}
|
||||
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return IRQ_NONE;
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1022,7 +1022,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
|||
.rx_skb = mt7915_queue_rx_skb,
|
||||
.rx_check = mt7915_rx_check,
|
||||
.rx_poll_complete = mt7915_rx_poll_complete,
|
||||
.sta_ps = mt7915_sta_ps,
|
||||
.sta_add = mt7915_mac_sta_add,
|
||||
.sta_remove = mt7915_mac_sta_remove,
|
||||
.update_survey = mt7915_update_channel,
|
||||
|
@ -1041,7 +1040,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
|
||||
tasklet_setup(&mdev->irq_tasklet, mt7915_irq_tasklet);
|
||||
|
||||
return dev;
|
||||
|
||||
|
|
|
@ -147,23 +147,9 @@ struct mt7915_sta {
|
|||
} twt;
|
||||
};
|
||||
|
||||
struct mt7915_vif_cap {
|
||||
bool ht_ldpc:1;
|
||||
bool vht_ldpc:1;
|
||||
bool he_ldpc:1;
|
||||
bool vht_su_ebfer:1;
|
||||
bool vht_su_ebfee:1;
|
||||
bool vht_mu_ebfer:1;
|
||||
bool vht_mu_ebfee:1;
|
||||
bool he_su_ebfer:1;
|
||||
bool he_su_ebfee:1;
|
||||
bool he_mu_ebfer:1;
|
||||
};
|
||||
|
||||
struct mt7915_vif {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
|
||||
struct mt7915_vif_cap cap;
|
||||
struct mt7915_sta sta;
|
||||
struct mt7915_phy *phy;
|
||||
|
||||
|
@ -308,7 +294,6 @@ struct mt7915_dev {
|
|||
u32 wfdma_mask;
|
||||
|
||||
const struct mt76_bus_ops *bus_ops;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct mt7915_phy phy;
|
||||
|
||||
/* monitor rx chain configured channel */
|
||||
|
@ -581,7 +566,7 @@ static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask)
|
|||
else
|
||||
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
}
|
||||
|
||||
static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
|
||||
|
@ -631,7 +616,6 @@ void mt7915_tx_token_put(struct mt7915_dev *dev);
|
|||
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
|
||||
void mt7915_stats_work(struct work_struct *work);
|
||||
int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
|
||||
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
|
||||
|
|
|
@ -1239,6 +1239,8 @@ static const struct of_device_id mt7986_wmac_of_match[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match);
|
||||
|
||||
struct platform_driver mt7986_wmac_driver = {
|
||||
.driver = {
|
||||
.name = "mt7986-wmac",
|
||||
|
|
|
@ -24,7 +24,7 @@ struct mt7921_asar_dyn {
|
|||
u8 names[4];
|
||||
u8 enable;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_dyn_limit tbl[0];
|
||||
DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl);
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_dyn_limit_v2 {
|
||||
|
@ -37,7 +37,7 @@ struct mt7921_asar_dyn_v2 {
|
|||
u8 enable;
|
||||
u8 rsvd;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_dyn_limit_v2 tbl[0];
|
||||
DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl);
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_band {
|
||||
|
@ -55,7 +55,7 @@ struct mt7921_asar_geo {
|
|||
u8 names[4];
|
||||
u8 version;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_geo_limit tbl[0];
|
||||
DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl);
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_geo_limit_v2 {
|
||||
|
@ -69,7 +69,7 @@ struct mt7921_asar_geo_v2 {
|
|||
u8 version;
|
||||
u8 rsvd;
|
||||
u8 nr_tbl;
|
||||
struct mt7921_asar_geo_limit_v2 tbl[0];
|
||||
DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl);
|
||||
} __packed;
|
||||
|
||||
struct mt7921_asar_cl {
|
||||
|
@ -85,7 +85,7 @@ struct mt7921_asar_fg {
|
|||
u8 rsvd;
|
||||
u8 nr_flag;
|
||||
u8 rsvd1;
|
||||
u8 flag[0];
|
||||
u8 flag[];
|
||||
} __packed;
|
||||
|
||||
struct mt7921_acpi_sar {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
static int
|
||||
mt7921_reg_set(void *data, u64 val)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
|
|||
|
||||
mt76_connac_tx_cleanup(&dev->mt76);
|
||||
if (napi_complete(napi))
|
||||
mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
|
||||
mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL);
|
||||
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
|
||||
|
||||
return 0;
|
||||
|
@ -66,6 +66,24 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
|
|||
|
||||
static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
|
||||
{
|
||||
/* disable WFDMA0 */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
|
||||
|
||||
if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* disable dmashdl */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
|
||||
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
|
||||
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
|
||||
|
||||
if (force) {
|
||||
/* reset */
|
||||
mt76_clear(dev, MT_WFDMA0_RST,
|
||||
|
@ -77,24 +95,6 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
|
|||
MT_WFDMA0_RST_LOGIC_RST);
|
||||
}
|
||||
|
||||
/* disable dmashdl */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
|
||||
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
|
||||
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
|
||||
|
||||
/* disable WFDMA0 */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
|
||||
|
||||
if (!mt76_poll(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -123,9 +123,9 @@ static int mt7921_dma_enable(struct mt7921_dev *dev)
|
|||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
|
||||
/* enable interrupts for TX/RX rings */
|
||||
mt7921_irq_enable(dev,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_connac_irq_enable(&dev->mt76,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
|
||||
|
||||
return 0;
|
||||
|
@ -301,6 +301,10 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev)
|
|||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
|
||||
|
||||
mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1);
|
||||
|
||||
/* reset */
|
||||
mt76_clear(dev, MT_WFDMA0_RST,
|
||||
MT_WFDMA0_RST_DMASHDL_ALL_RST |
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7921_EEPROM_H
|
||||
#define __MT7921_EEPROM_H
|
||||
|
||||
#include "mt7921.h"
|
||||
|
||||
enum mt7921_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
MT_EE_WIFI_CONF = 0x07c,
|
||||
MT_EE_HW_TYPE = 0x55b,
|
||||
__MT_EE_MAX = 0x9ff
|
||||
};
|
||||
|
||||
#define MT_EE_WIFI_CONF_TX_MASK BIT(0)
|
||||
#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2)
|
||||
|
||||
#define MT_EE_HW_TYPE_ENCAP BIT(0)
|
||||
|
||||
enum mt7921_eeprom_band {
|
||||
MT_EE_NA,
|
||||
MT_EE_5GHZ,
|
||||
MT_EE_2GHZ,
|
||||
MT_EE_DUAL_BAND,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -4,9 +4,8 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "mt7921.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits[] = {
|
||||
{
|
||||
|
@ -32,11 +31,13 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
|||
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION),
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP),
|
||||
.types = BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -100,7 +101,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
|
||||
WIPHY_FLAG_4ADDR_STATION);
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
|
||||
wiphy->max_scan_ssids = 4;
|
||||
|
@ -121,6 +124,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
|
@ -169,7 +173,8 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
|
|||
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
|
||||
}
|
||||
|
||||
u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
||||
static u8
|
||||
mt7921_get_offload_capability(struct device *dev, const char *fw_wm)
|
||||
{
|
||||
struct mt7921_fw_features *features = NULL;
|
||||
const struct mt76_connac2_fw_trailer *hdr;
|
||||
|
@ -220,7 +225,31 @@ out:
|
|||
|
||||
return features ? features->data : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_check_offload_capability);
|
||||
|
||||
struct ieee80211_ops *
|
||||
mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features)
|
||||
{
|
||||
struct ieee80211_ops *ops;
|
||||
|
||||
ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL);
|
||||
if (!ops)
|
||||
return NULL;
|
||||
|
||||
*fw_features = mt7921_get_offload_capability(dev, drv_data);
|
||||
if (!(*fw_features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops);
|
||||
|
||||
int mt7921_mac_init(struct mt7921_dev *dev)
|
||||
{
|
||||
|
|
|
@ -6,9 +6,20 @@
|
|||
#include <linux/timekeeping.h>
|
||||
#include "mt7921.h"
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
#define MT_WTBL_TXRX_RATE_G2_HE 24
|
||||
#define MT_WTBL_TXRX_RATE_G2 12
|
||||
|
||||
#define MT_WTBL_AC0_CTT_OFFSET 20
|
||||
|
||||
static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
|
||||
{
|
||||
return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
|
||||
}
|
||||
|
||||
static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
|
||||
u16 idx, bool unicast)
|
||||
{
|
||||
|
@ -32,11 +43,6 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
|
|||
return &sta->vif->sta.wcid;
|
||||
}
|
||||
|
||||
void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_sta_ps);
|
||||
|
||||
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
|
||||
{
|
||||
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7921_MAC_H
|
||||
#define __MT7921_MAC_H
|
||||
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
#define MT_CT_PARSE_LEN 72
|
||||
#define MT_CT_DMA_BUF_NUM 2
|
||||
|
||||
#define MT_RXD0_LENGTH GENMASK(15, 0)
|
||||
#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
|
||||
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
|
||||
|
||||
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
|
||||
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
|
||||
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
|
||||
|
||||
enum rx_pkt_type {
|
||||
PKT_TYPE_TXS,
|
||||
PKT_TYPE_TXRXV,
|
||||
PKT_TYPE_NORMAL,
|
||||
PKT_TYPE_RX_DUP_RFB,
|
||||
PKT_TYPE_RX_TMR,
|
||||
PKT_TYPE_RETRIEVE,
|
||||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_NORMAL_MCU,
|
||||
};
|
||||
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
|
||||
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
|
||||
/* 0: success, others: dropped */
|
||||
#define MT_TX_FREE_STATUS GENMASK(14, 13)
|
||||
#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
|
||||
#define MT_TX_FREE_PAIR BIT(31)
|
||||
/* will support this field in further revision */
|
||||
#define MT_TX_FREE_RATE GENMASK(13, 0)
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
#define MT_WTBL_TXRX_RATE_G2_HE 24
|
||||
#define MT_WTBL_TXRX_RATE_G2 12
|
||||
|
||||
#define MT_WTBL_AC0_CTT_OFFSET 20
|
||||
|
||||
static inline u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
|
||||
{
|
||||
return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -9,27 +9,6 @@
|
|||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static void
|
||||
mt7921_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
ru_bit_mask);
|
||||
|
||||
ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
|
||||
nss * hweight8(ru_bit_mask) * 2;
|
||||
ppet_size = DIV_ROUND_UP(ppet_bits, 8);
|
||||
|
||||
for (i = 0; i < ppet_size - 1; i++)
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
|
||||
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
|
||||
(0xff >> (8 - (ppet_bits - 1) % 8));
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data)
|
||||
|
@ -168,7 +147,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
|||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
mt7921_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
|
@ -703,10 +682,25 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
|||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
{
|
||||
#define MT7921_FILTER_FCSFAIL BIT(2)
|
||||
#define MT7921_FILTER_CONTROL BIT(5)
|
||||
#define MT7921_FILTER_OTHER_BSS BIT(6)
|
||||
#define MT7921_FILTER_ENABLE BIT(31)
|
||||
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
u32 flags = MT7921_FILTER_ENABLE;
|
||||
|
||||
#define MT7921_FILTER(_fif, _type) do { \
|
||||
if (*total_flags & (_fif)) \
|
||||
flags |= MT7921_FILTER_##_type; \
|
||||
} while (0)
|
||||
|
||||
MT7921_FILTER(FIF_FCSFAIL, FCSFAIL);
|
||||
MT7921_FILTER(FIF_CONTROL, CONTROL);
|
||||
MT7921_FILTER(FIF_OTHER_BSS, OTHER_BSS);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mcu_set_rxfilter(dev, *total_flags, 0, 0);
|
||||
mt7921_mcu_set_rxfilter(dev, flags, 0, 0);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
*total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL);
|
||||
|
@ -1695,7 +1689,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac,
|
|||
if (ctx != mvif->ctx)
|
||||
return;
|
||||
|
||||
if (vif->type & NL80211_IFTYPE_MONITOR)
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
mt7921_mcu_config_sniffer(mvif, ctx);
|
||||
else
|
||||
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
#include <linux/firmware.h>
|
||||
#include "mt7921.h"
|
||||
#include "mt7921_trace.h"
|
||||
#include "eeprom.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
#define MT_STA_BFER BIT(0)
|
||||
#define MT_STA_BFEE BIT(1)
|
||||
|
@ -16,24 +15,6 @@ static bool mt7921_disable_clc;
|
|||
module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_clc, "disable CLC support");
|
||||
|
||||
static int
|
||||
mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_mcu_eeprom_info *res;
|
||||
u8 *buf;
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
|
||||
res = (struct mt7921_mcu_eeprom_info *)skb->data;
|
||||
buf = dev->eeprom.data + le32_to_cpu(res->addr);
|
||||
memcpy(buf, res->data, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq)
|
||||
{
|
||||
|
@ -60,27 +41,25 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
|||
} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
|
||||
skb_pull(skb, sizeof(*rxd) + 4);
|
||||
ret = le32_to_cpu(*(__le32 *)skb->data);
|
||||
} else if (cmd == MCU_EXT_CMD(EFUSE_ACCESS)) {
|
||||
ret = mt7921_mcu_parse_eeprom(mdev, skb);
|
||||
} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||
|
||||
cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||
|
||||
cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||
|
||||
cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(OFFLOAD) ||
|
||||
cmd == MCU_UNI_CMD(SUSPEND)) {
|
||||
struct mt7921_mcu_uni_event *event;
|
||||
struct mt76_connac_mcu_uni_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt7921_mcu_uni_event *)skb->data;
|
||||
event = (struct mt76_connac_mcu_uni_event *)skb->data;
|
||||
ret = le32_to_cpu(event->status);
|
||||
/* skip invalid event */
|
||||
if (mcu_cmd != event->cid)
|
||||
ret = -EAGAIN;
|
||||
} else if (cmd == MCU_CE_QUERY(REG_READ)) {
|
||||
struct mt7921_mcu_reg_event *event;
|
||||
struct mt76_connac_mcu_reg_event *event;
|
||||
|
||||
skb_pull(skb, sizeof(*rxd));
|
||||
event = (struct mt7921_mcu_reg_event *)skb->data;
|
||||
event = (struct mt76_connac_mcu_reg_event *)skb->data;
|
||||
ret = (int)le32_to_cpu(event->val);
|
||||
} else {
|
||||
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
|
||||
|
|
|
@ -50,22 +50,11 @@ struct mt7921_mcu_eeprom_info {
|
|||
#define MT_RA_RATE_DCM_EN BIT(4)
|
||||
#define MT_RA_RATE_BW GENMASK(14, 13)
|
||||
|
||||
struct mt7921_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 pad[3];
|
||||
__le32 status; /* 0: success, others: fail */
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
MT_EBF = BIT(0), /* explicit beamforming */
|
||||
MT_IBF = BIT(1) /* implicit beamforming */
|
||||
};
|
||||
|
||||
struct mt7921_mcu_reg_event {
|
||||
__le32 reg;
|
||||
__le32 val;
|
||||
} __packed;
|
||||
|
||||
struct mt7921_mcu_ant_id_config {
|
||||
u8 ant_id[4];
|
||||
} __packed;
|
||||
|
|
|
@ -266,6 +266,17 @@ struct mt7921_phy {
|
|||
bool roc_grant;
|
||||
};
|
||||
|
||||
enum mt7921_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
MT_EE_WIFI_CONF = 0x07c,
|
||||
MT_EE_HW_TYPE = 0x55b,
|
||||
__MT_EE_MAX = 0x9ff
|
||||
};
|
||||
|
||||
#define MT_EE_HW_TYPE_ENCAP BIT(0)
|
||||
|
||||
#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
|
||||
#define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev))
|
||||
#define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev))
|
||||
|
@ -287,7 +298,6 @@ struct mt7921_dev {
|
|||
|
||||
const struct mt76_bus_ops *bus_ops;
|
||||
struct mt7921_phy phy;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
struct work_struct reset_work;
|
||||
bool hw_full_reset:1;
|
||||
|
@ -391,13 +401,6 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
|
|||
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map);
|
||||
|
||||
static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
|
||||
{
|
||||
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr)
|
||||
{
|
||||
|
@ -478,7 +481,6 @@ void mt7921_tx_token_put(struct mt7921_dev *dev);
|
|||
bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
|
||||
void mt7921_stats_work(struct work_struct *work);
|
||||
void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
|
||||
void mt7921_update_channel(struct mt76_phy *mphy);
|
||||
|
@ -593,5 +595,6 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
|
|||
enum mt7921_roc_req type, u8 token_id);
|
||||
int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
|
||||
u8 token_id);
|
||||
u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm);
|
||||
struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev,
|
||||
void *drv_data, u8 *fw_features);
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <linux/pci.h>
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
#include "../trace.h"
|
||||
|
||||
|
@ -31,14 +31,12 @@ MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
|
|||
static void
|
||||
mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
if (q == MT_RXQ_MAIN)
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_DATA);
|
||||
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA);
|
||||
else if (q == MT_RXQ_MCU_WA)
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_WM2);
|
||||
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2);
|
||||
else
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_WM);
|
||||
mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM);
|
||||
}
|
||||
|
||||
static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
|
||||
|
@ -50,7 +48,7 @@ static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
|
|||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return IRQ_NONE;
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -115,14 +113,15 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
|
|||
napi_disable(&dev->mt76.napi[i]);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
|
||||
mt7921_tx_token_put(dev);
|
||||
mt7921_mcu_drv_pmctrl(dev);
|
||||
__mt7921_mcu_drv_pmctrl(dev);
|
||||
mt7921_dma_cleanup(dev);
|
||||
mt7921_wfsys_reset(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
tasklet_disable(&dev->mt76.irq_tasklet);
|
||||
}
|
||||
|
||||
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
|
||||
|
@ -243,7 +242,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
.rx_check = mt7921_rx_check,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.rx_poll_complete = mt7921_rx_poll_complete,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
.sta_assoc = mt7921_mac_sta_assoc,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
|
@ -256,13 +254,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
.drv_own = mt7921e_mcu_drv_pmctrl,
|
||||
.fw_own = mt7921e_mcu_fw_pmctrl,
|
||||
};
|
||||
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt76_bus_ops *bus_ops;
|
||||
struct mt7921_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
u8 features;
|
||||
int ret;
|
||||
u16 cmd;
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
|
@ -272,6 +270,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
|
||||
if (!(cmd & PCI_COMMAND_MEMORY)) {
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
pci_write_config_word(pdev, PCI_COMMAND, cmd);
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
|
@ -285,27 +288,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
if (mt7921_disable_aspm)
|
||||
mt76_pci_disable_aspm(pdev);
|
||||
|
||||
features = mt7921_check_offload_capability(&pdev->dev, (const char *)
|
||||
id->driver_data);
|
||||
ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
|
||||
GFP_KERNEL);
|
||||
ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data,
|
||||
&features);
|
||||
if (!ops) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pci_vec;
|
||||
}
|
||||
|
||||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -318,7 +307,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
dev->fw_features = features;
|
||||
dev->hif_ops = &mt7921_pcie_ops;
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
|
||||
tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
|
||||
|
||||
dev->phy.dev = dev;
|
||||
dev->phy.mt76 = &dev->mt76.phy;
|
||||
|
@ -430,7 +419,7 @@ static int mt7921_pci_suspend(struct device *device)
|
|||
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
|
||||
synchronize_irq(pdev->irq);
|
||||
tasklet_kill(&dev->irq_tasklet);
|
||||
tasklet_kill(&mdev->irq_tasklet);
|
||||
|
||||
err = mt7921_mcu_fw_pmctrl(dev);
|
||||
if (err)
|
||||
|
@ -474,8 +463,9 @@ static int mt7921_pci_resume(struct device *device)
|
|||
|
||||
/* enable interrupt */
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_connac_irq_enable(&dev->mt76,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_MCU_CMD);
|
||||
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
|
||||
|
||||
/* put dma enabled */
|
||||
|
@ -509,17 +499,7 @@ failed:
|
|||
|
||||
static void mt7921_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
|
||||
/* chip cleanup before reboot */
|
||||
mt7921_mcu_drv_pmctrl(dev);
|
||||
mt7921_dma_cleanup(dev);
|
||||
mt7921_wfsys_reset(dev);
|
||||
mt7921_pci_remove(pdev);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "../sdio.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static const struct sdio_device_id mt7921s_table[] = {
|
||||
|
@ -99,7 +99,6 @@ static int mt7921s_probe(struct sdio_func *func,
|
|||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.rx_check = mt7921_rx_check,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
.sta_assoc = mt7921_mac_sta_assoc,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
|
@ -122,33 +121,17 @@ static int mt7921s_probe(struct sdio_func *func,
|
|||
.drv_own = mt7921s_mcu_drv_pmctrl,
|
||||
.fw_own = mt7921s_mcu_fw_pmctrl,
|
||||
};
|
||||
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt7921_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
u8 features;
|
||||
int ret;
|
||||
|
||||
features = mt7921_check_offload_capability(&func->dev, (const char *)
|
||||
id->driver_data);
|
||||
|
||||
ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
|
||||
GFP_KERNEL);
|
||||
ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data,
|
||||
&features);
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include "mt7921.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "../sdio.h"
|
||||
|
||||
static void mt7921s_enable_irq(struct mt76_dev *dev)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "../sdio.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "mcu.h"
|
||||
#include "regs.h"
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
static const struct usb_device_id mt7921u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
|
||||
|
@ -18,6 +18,9 @@ static const struct usb_device_id mt7921u_device_table[] = {
|
|||
/* Comfast CF-952AX */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
/* Netgear, Inc. [A8000,AXE3000] */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -183,7 +186,6 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.rx_check = mt7921_rx_check,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
.sta_assoc = mt7921_mac_sta_assoc,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
|
@ -210,27 +212,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
u8 features;
|
||||
int ret;
|
||||
|
||||
features = mt7921_check_offload_capability(&usb_intf->dev, (const char *)
|
||||
id->driver_info);
|
||||
ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops),
|
||||
GFP_KERNEL);
|
||||
ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info,
|
||||
&features);
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
ops->stop = mt7921u_stop;
|
||||
|
||||
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
@ -272,7 +259,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
|
||||
ret = mt7921u_dma_init(dev, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
hw = mt76_hw(dev);
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
|
||||
static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
config MT7996E
|
||||
tristate "MediaTek MT7996 (PCIe) support"
|
||||
select MT76_CONNAC_LIB
|
||||
select WANT_DEV_COREDUMP
|
||||
select RELAY
|
||||
depends on MAC80211
|
||||
depends on PCI
|
||||
|
|
|
@ -4,3 +4,5 @@ obj-$(CONFIG_MT7996E) += mt7996e.o
|
|||
|
||||
mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
|
||||
debugfs.o mmio.o
|
||||
|
||||
mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include <linux/devcoredump.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/utsname.h>
|
||||
#include "coredump.h"
|
||||
|
||||
static bool coredump_memdump;
|
||||
module_param(coredump_memdump, bool, 0644);
|
||||
MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory");
|
||||
|
||||
static const struct mt7996_mem_region mt7996_mem_regions[] = {
|
||||
{
|
||||
.start = 0x00800000,
|
||||
.len = 0x0004ffff,
|
||||
.name = "ULM0",
|
||||
},
|
||||
{
|
||||
.start = 0x00900000,
|
||||
.len = 0x00037fff,
|
||||
.name = "ULM1",
|
||||
},
|
||||
{
|
||||
.start = 0x02200000,
|
||||
.len = 0x0003ffff,
|
||||
.name = "ULM2",
|
||||
},
|
||||
{
|
||||
.start = 0x00400000,
|
||||
.len = 0x00067fff,
|
||||
.name = "SRAM",
|
||||
},
|
||||
{
|
||||
.start = 0xe0000000,
|
||||
.len = 0x0015ffff,
|
||||
.name = "CRAM0",
|
||||
},
|
||||
{
|
||||
.start = 0xe0160000,
|
||||
.len = 0x0011bfff,
|
||||
.name = "CRAM1",
|
||||
},
|
||||
};
|
||||
|
||||
const struct mt7996_mem_region*
|
||||
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7990:
|
||||
case 0x7991:
|
||||
*num = ARRAY_SIZE(mt7996_mem_regions);
|
||||
return &mt7996_mem_regions[0];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
|
||||
{
|
||||
const struct mt7996_mem_region *mem_region;
|
||||
size_t size = 0;
|
||||
u32 num;
|
||||
int i;
|
||||
|
||||
mem_region = mt7996_coredump_get_mem_layout(dev, &num);
|
||||
if (!mem_region)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
size += mem_region->len;
|
||||
mem_region++;
|
||||
}
|
||||
|
||||
/* reserve space for the headers */
|
||||
size += num * sizeof(struct mt7996_mem_hdr);
|
||||
/* make sure it is aligned 4 bytes for debug message print out */
|
||||
size = ALIGN(size, 4);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
|
||||
|
||||
lockdep_assert_held(&dev->dump_mutex);
|
||||
|
||||
if (coredump_memdump &&
|
||||
!mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500))
|
||||
return NULL;
|
||||
|
||||
guid_gen(&crash_data->guid);
|
||||
ktime_get_real_ts64(&crash_data->timestamp);
|
||||
|
||||
return crash_data;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
|
||||
bool *exception)
|
||||
{
|
||||
u32 count;
|
||||
|
||||
count = mt76_rr(dev, MT_FW_ASSERT_CNT);
|
||||
|
||||
/* normal mode: driver can manually trigger assert for detail info */
|
||||
if (!count)
|
||||
strscpy(dump->fw_state, "normal", sizeof(dump->fw_state));
|
||||
else
|
||||
strscpy(dump->fw_state, "exception", sizeof(dump->fw_state));
|
||||
|
||||
*exception = !!count;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump,
|
||||
bool exception)
|
||||
{
|
||||
u32 oldest, i, idx;
|
||||
|
||||
strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current));
|
||||
|
||||
/* 0: WM PC log output */
|
||||
mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0);
|
||||
/* choose 33th PC log buffer to read current PC index */
|
||||
mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f);
|
||||
|
||||
/* read current PC */
|
||||
dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
|
||||
|
||||
/* stop call stack record */
|
||||
if (!exception) {
|
||||
mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
|
||||
mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
|
||||
}
|
||||
|
||||
oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL,
|
||||
GENMASK(20, 16)) + 2;
|
||||
for (i = 0; i < 16; i++) {
|
||||
idx = ((oldest + 2 * i + 1) % 32);
|
||||
dump->pc_stack[i + 1] =
|
||||
mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4);
|
||||
}
|
||||
|
||||
oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL,
|
||||
GENMASK(20, 16)) + 2;
|
||||
for (i = 0; i < 16; i++) {
|
||||
idx = ((oldest + 2 * i + 1) % 32);
|
||||
dump->lr_stack[i] =
|
||||
mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4);
|
||||
}
|
||||
|
||||
/* start call stack record */
|
||||
if (!exception) {
|
||||
mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
|
||||
mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
|
||||
}
|
||||
}
|
||||
|
||||
static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
|
||||
struct mt7996_coredump *dump;
|
||||
struct mt7996_coredump_mem *dump_mem;
|
||||
size_t len, sofar = 0, hdr_len = sizeof(*dump);
|
||||
unsigned char *buf;
|
||||
bool exception;
|
||||
|
||||
len = hdr_len;
|
||||
|
||||
if (coredump_memdump && crash_data->memdump_buf_len)
|
||||
len += sizeof(*dump_mem) + crash_data->memdump_buf_len;
|
||||
|
||||
sofar += hdr_len;
|
||||
|
||||
/* this is going to get big when we start dumping memory and such,
|
||||
* so go ahead and use vmalloc.
|
||||
*/
|
||||
buf = vzalloc(len);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&dev->dump_mutex);
|
||||
|
||||
dump = (struct mt7996_coredump *)(buf);
|
||||
dump->len = len;
|
||||
|
||||
/* plain text */
|
||||
strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic));
|
||||
strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel));
|
||||
strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version,
|
||||
sizeof(dump->fw_ver));
|
||||
|
||||
guid_copy(&dump->guid, &crash_data->guid);
|
||||
dump->tv_sec = crash_data->timestamp.tv_sec;
|
||||
dump->tv_nsec = crash_data->timestamp.tv_nsec;
|
||||
dump->device_id = mt76_chip(&dev->mt76);
|
||||
|
||||
mt7996_coredump_fw_state(dev, dump, &exception);
|
||||
mt7996_coredump_fw_stack(dev, dump, exception);
|
||||
|
||||
/* gather memory content */
|
||||
dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
|
||||
dump_mem->len = crash_data->memdump_buf_len;
|
||||
if (coredump_memdump && crash_data->memdump_buf_len)
|
||||
memcpy(dump_mem->data, crash_data->memdump_buf,
|
||||
crash_data->memdump_buf_len);
|
||||
|
||||
mutex_unlock(&dev->dump_mutex);
|
||||
|
||||
return dump;
|
||||
}
|
||||
|
||||
int mt7996_coredump_submit(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_coredump *dump;
|
||||
|
||||
dump = mt7996_coredump_build(dev);
|
||||
if (!dump) {
|
||||
dev_warn(dev->mt76.dev, "no crash dump data found\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_coredump_register(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_crash_data *crash_data;
|
||||
|
||||
crash_data = vzalloc(sizeof(*dev->coredump.crash_data));
|
||||
if (!crash_data)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->coredump.crash_data = crash_data;
|
||||
|
||||
if (coredump_memdump) {
|
||||
crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev);
|
||||
if (!crash_data->memdump_buf_len)
|
||||
/* no memory content */
|
||||
return 0;
|
||||
|
||||
crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
|
||||
if (!crash_data->memdump_buf) {
|
||||
vfree(crash_data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7996_coredump_unregister(struct mt7996_dev *dev)
|
||||
{
|
||||
if (dev->coredump.crash_data->memdump_buf) {
|
||||
vfree(dev->coredump.crash_data->memdump_buf);
|
||||
dev->coredump.crash_data->memdump_buf = NULL;
|
||||
dev->coredump.crash_data->memdump_buf_len = 0;
|
||||
}
|
||||
|
||||
vfree(dev->coredump.crash_data);
|
||||
dev->coredump.crash_data = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#ifndef _COREDUMP_H_
|
||||
#define _COREDUMP_H_
|
||||
|
||||
#include "mt7996.h"
|
||||
|
||||
struct mt7996_coredump {
|
||||
char magic[16];
|
||||
|
||||
u32 len;
|
||||
|
||||
guid_t guid;
|
||||
|
||||
/* time-of-day stamp */
|
||||
u64 tv_sec;
|
||||
/* time-of-day stamp, nano-seconds */
|
||||
u64 tv_nsec;
|
||||
/* kernel version */
|
||||
char kernel[64];
|
||||
/* firmware version */
|
||||
char fw_ver[ETHTOOL_FWVERS_LEN];
|
||||
|
||||
u32 device_id;
|
||||
|
||||
/* exception state */
|
||||
char fw_state[12];
|
||||
|
||||
/* program counters */
|
||||
char pc_current[16];
|
||||
u32 pc_stack[17];
|
||||
/* link registers */
|
||||
u32 lr_stack[16];
|
||||
|
||||
/* memory content */
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct mt7996_coredump_mem {
|
||||
u32 len;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mem_hdr {
|
||||
u32 start;
|
||||
u32 len;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct mt7996_mem_region {
|
||||
u32 start;
|
||||
size_t len;
|
||||
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEV_COREDUMP
|
||||
|
||||
const struct mt7996_mem_region *
|
||||
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num);
|
||||
struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev);
|
||||
int mt7996_coredump_submit(struct mt7996_dev *dev);
|
||||
int mt7996_coredump_register(struct mt7996_dev *dev);
|
||||
void mt7996_coredump_unregister(struct mt7996_dev *dev);
|
||||
|
||||
#else /* CONFIG_DEV_COREDUMP */
|
||||
|
||||
static inline const struct mt7996_mem_region *
|
||||
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int mt7996_coredump_submit(struct mt7996_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct
|
||||
mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int mt7996_coredump_register(struct mt7996_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mt7996_coredump_unregister(struct mt7996_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEV_COREDUMP */
|
||||
|
||||
#endif /* _COREDUMP_H_ */
|
|
@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
|
|||
|
||||
/* test knob of system error recovery */
|
||||
static ssize_t
|
||||
mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct mt7996_phy *phy = file->private_data;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
u8 band_idx = phy->mt76->band_idx;
|
||||
bool band = phy->mt76->band_idx;
|
||||
char buf[16];
|
||||
int ret = 0;
|
||||
u16 val;
|
||||
|
@ -73,17 +73,47 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
|
|||
return -EINVAL;
|
||||
|
||||
switch (val) {
|
||||
case SER_SET_RECOVER_L1:
|
||||
case SER_SET_RECOVER_L2:
|
||||
case SER_SET_RECOVER_L3_RX_ABORT:
|
||||
case SER_SET_RECOVER_L3_TX_ABORT:
|
||||
case SER_SET_RECOVER_L3_TX_DISABLE:
|
||||
case SER_SET_RECOVER_L3_BF:
|
||||
ret = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx);
|
||||
/*
|
||||
* 0: grab firmware current SER state.
|
||||
* 1: trigger & enable system error L1 recovery.
|
||||
* 2: trigger & enable system error L2 recovery.
|
||||
* 3: trigger & enable system error L3 rx abort.
|
||||
* 4: trigger & enable system error L3 tx abort
|
||||
* 5: trigger & enable system error L3 tx disable.
|
||||
* 6: trigger & enable system error L3 bf recovery.
|
||||
* 7: trigger & enable system error L4 mdp recovery.
|
||||
* 8: trigger & enable system error full recovery.
|
||||
* 9: trigger firmware crash.
|
||||
*/
|
||||
case UNI_CMD_SER_QUERY:
|
||||
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
|
||||
break;
|
||||
case UNI_CMD_SER_SET_RECOVER_L1:
|
||||
case UNI_CMD_SER_SET_RECOVER_L2:
|
||||
case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
|
||||
case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
|
||||
case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
|
||||
case UNI_CMD_SER_SET_RECOVER_L3_BF:
|
||||
case UNI_CMD_SER_SET_RECOVER_L4_MDP:
|
||||
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx);
|
||||
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
|
||||
break;
|
||||
|
||||
/* enable full chip reset */
|
||||
case UNI_CMD_SER_SET_RECOVER_FULL:
|
||||
mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
|
||||
dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
|
||||
mt7996_reset(dev);
|
||||
break;
|
||||
|
||||
/* WARNING: trigger firmware crash */
|
||||
case UNI_CMD_SER_SET_SYSTEM_ASSERT:
|
||||
ret = mt7996_mcu_trigger_assert(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -92,9 +122,97 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
|
|||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static const struct file_operations mt7996_fw_ser_ops = {
|
||||
.write = mt7996_fw_ser_set,
|
||||
/* TODO: ser read */
|
||||
static ssize_t
|
||||
mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct mt7996_phy *phy = file->private_data;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
char *buff;
|
||||
int desc = 0;
|
||||
ssize_t ret;
|
||||
static const size_t bufsz = 1024;
|
||||
|
||||
buff = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
/* HELP */
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"Please echo the correct value ...\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"0: grab firmware transient SER state\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"1: trigger system error L1 recovery\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"2: trigger system error L2 recovery\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"3: trigger system error L3 rx abort\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"4: trigger system error L3 tx abort\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"5: trigger system error L3 tx disable\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"6: trigger system error L3 bf recovery\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"7: trigger system error L4 mdp recovery\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"8: trigger system error full recovery\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"9: trigger firmware crash\n");
|
||||
|
||||
/* SER statistics */
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"\nlet's dump firmware SER statistics...\n");
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_STATUS = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_SER_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR_1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR_AMSDU = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PSE_ERR = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PSE_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PSE_ERR_1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PSE1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR6_B0 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR6_B1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR6_B2 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR7_B0 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR7_B2 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"\nSYS_RESET_COUNT: WM %d, WA %d\n",
|
||||
dev->recovery.wm_reset_count,
|
||||
dev->recovery.wa_reset_count);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
|
||||
kfree(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations mt7996_sys_recovery_ops = {
|
||||
.write = mt7996_sys_recovery_set,
|
||||
.read = mt7996_sys_recovery_get,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
@ -674,6 +792,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
|
|||
debugfs_create_file("xmit-queues", 0400, dir, phy,
|
||||
&mt7996_xmit_queues_fops);
|
||||
debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops);
|
||||
debugfs_create_file("sys_recovery", 0600, dir, phy,
|
||||
&mt7996_sys_recovery_ops);
|
||||
debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
|
||||
debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
|
||||
debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
|
||||
|
@ -684,7 +804,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
|
|||
&fops_implicit_txbf);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
|
||||
mt7996_twt_stats);
|
||||
debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops);
|
||||
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
|
|
|
@ -352,6 +352,70 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
|
||||
{
|
||||
struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
|
||||
struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
|
||||
u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
int i;
|
||||
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
if (dev->hif2)
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++) {
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
if (phy2)
|
||||
mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
|
||||
if (phy3)
|
||||
mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
|
||||
}
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
/* reset wfsys */
|
||||
if (force)
|
||||
mt7996_wfsys_reset(dev);
|
||||
|
||||
mt7996_dma_disable(dev, force);
|
||||
|
||||
/* reset hw queues */
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++) {
|
||||
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
|
||||
if (phy2)
|
||||
mt76_queue_reset(dev, phy2->q_tx[i]);
|
||||
if (phy3)
|
||||
mt76_queue_reset(dev, phy3->q_tx[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
}
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
|
||||
mt7996_dma_enable(dev);
|
||||
}
|
||||
|
||||
void mt7996_dma_cleanup(struct mt7996_dev *dev)
|
||||
{
|
||||
mt7996_dma_disable(dev, true);
|
||||
|
|
|
@ -138,10 +138,6 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
|
|||
case MT_EE_BAND_SEL_6GHZ:
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
break;
|
||||
case MT_EE_BAND_SEL_5GHZ_6GHZ:
|
||||
phy->mt76->cap.has_5ghz = true;
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
|
|
@ -31,11 +31,11 @@ enum mt7996_eeprom_field {
|
|||
#define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0)
|
||||
|
||||
#define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)
|
||||
|
||||
#define MT_EE_RATE_DELTA_MASK GENMASK(5, 0)
|
||||
#define MT_EE_RATE_DELTA_SIGN BIT(6)
|
||||
|
@ -46,7 +46,6 @@ enum mt7996_eeprom_band {
|
|||
MT_EE_BAND_SEL_2GHZ,
|
||||
MT_EE_BAND_SEL_5GHZ,
|
||||
MT_EE_BAND_SEL_6GHZ,
|
||||
MT_EE_BAND_SEL_5GHZ_6GHZ,
|
||||
};
|
||||
|
||||
static inline int
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "mt7996.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "coredump.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits[] = {
|
||||
|
@ -99,9 +100,8 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
|
|||
mt7996_led_set_config(led_cdev, 0xff, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_init_txpower(struct mt7996_dev *dev,
|
||||
struct ieee80211_supported_band *sband)
|
||||
void mt7996_init_txpower(struct mt7996_dev *dev,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
int i, nss = hweight8(dev->mphy.antenna_mask);
|
||||
int nss_delta = mt76_tx_power_nss_delta(nss);
|
||||
|
@ -182,6 +182,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
|
||||
if (!mdev->dev->of_node ||
|
||||
!of_property_read_bool(mdev->dev->of_node,
|
||||
|
@ -196,10 +197,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
|||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
||||
if (phy->mt76->cap.has_2ghz)
|
||||
if (phy->mt76->cap.has_2ghz) {
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_2;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |=
|
||||
|
@ -211,6 +215,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
|||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_1;
|
||||
}
|
||||
|
||||
mt76_set_stream_caps(phy->mt76, true);
|
||||
|
@ -250,7 +256,21 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
|
|||
mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
|
||||
}
|
||||
|
||||
static void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
|
||||
u16 rate = mt76_rates[i].hw_value;
|
||||
u16 idx = MT7996_BASIC_RATES_TBL + i;
|
||||
|
||||
rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
|
||||
FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
|
||||
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
{
|
||||
#define HIF_TXD_V2_1 4
|
||||
int i;
|
||||
|
@ -282,9 +302,11 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
|
|||
|
||||
for (i = MT_BAND0; i <= MT_BAND2; i++)
|
||||
mt7996_mac_init_band(dev, i);
|
||||
|
||||
mt7996_mac_init_basic_rates(dev);
|
||||
}
|
||||
|
||||
static int mt7996_txbf_init(struct mt7996_dev *dev)
|
||||
int mt7996_txbf_init(struct mt7996_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -552,27 +574,6 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
|
|||
elem->phy_cap_info[7] |= c;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
ru_bit_mask);
|
||||
|
||||
ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
|
||||
nss * hweight8(ru_bit_mask) * 2;
|
||||
ppet_size = DIV_ROUND_UP(ppet_bits, 8);
|
||||
|
||||
for (i = 0; i < ppet_size - 1; i++)
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
|
||||
|
||||
he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
|
||||
(0xff >> (8 - (ppet_bits - 1) % 8));
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data,
|
||||
|
@ -678,7 +679,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
|||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
|
@ -689,7 +690,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
|||
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
|
||||
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
|
||||
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
|
@ -858,6 +859,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
|||
|
||||
init_waitqueue_head(&dev->reset_wait);
|
||||
INIT_WORK(&dev->reset_work, mt7996_mac_reset_work);
|
||||
INIT_WORK(&dev->dump_work, mt7996_mac_dump_work);
|
||||
mutex_init(&dev->dump_mutex);
|
||||
|
||||
ret = mt7996_init_hardware(dev);
|
||||
if (ret)
|
||||
|
@ -886,18 +889,25 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_init_debugfs(&dev->phy);
|
||||
dev->recovery.hw_init_done = true;
|
||||
|
||||
ret = mt7996_init_debugfs(&dev->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_coredump_register(dev);
|
||||
}
|
||||
|
||||
void mt7996_unregister_device(struct mt7996_dev *dev)
|
||||
{
|
||||
mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
|
||||
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
|
||||
mt7996_coredump_unregister(dev);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7996_mcu_exit(dev);
|
||||
mt7996_tx_token_put(dev);
|
||||
mt7996_dma_cleanup(dev);
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
tasklet_disable(&dev->mt76.irq_tasklet);
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include "coredump.h"
|
||||
#include "mt7996.h"
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
@ -78,10 +79,6 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
|||
return &sta->vif->sta.wcid;
|
||||
}
|
||||
|
||||
void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
|
||||
{
|
||||
}
|
||||
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
|
||||
{
|
||||
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
|
||||
|
@ -255,17 +252,25 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
|
|||
mt76_clear(dev, addr, BIT(5));
|
||||
}
|
||||
|
||||
void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
|
||||
u8 tbl_idx, u16 rate_idx)
|
||||
{
|
||||
u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
|
||||
|
||||
mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
|
||||
/* use wtbl spe idx */
|
||||
mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
|
||||
mt76_wr(dev, MT_WTBL_ITCR, ctrl);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
||||
struct ieee80211_radiotap_he *he,
|
||||
__le32 *rxv)
|
||||
{
|
||||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
u32 ru, offs = 0;
|
||||
|
||||
ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
|
||||
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
|
||||
ru = (u8)(ru_l | ru_h << 4);
|
||||
ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC);
|
||||
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
|
||||
|
@ -330,18 +335,23 @@ mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
|
|||
|
||||
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
|
||||
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
|
||||
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
|
||||
le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
|
||||
|
||||
he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
|
||||
he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_40) {
|
||||
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
|
||||
he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
|
||||
he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
|
||||
}
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_80) {
|
||||
he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
|
||||
he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
|
||||
u32 ru_h, ru_l;
|
||||
|
||||
he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
|
||||
|
||||
ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
|
||||
ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
|
||||
he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,23 +374,23 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
|
|||
HE_BITS(DATA2_TXOP_KNOWN),
|
||||
};
|
||||
struct ieee80211_radiotap_he *he = NULL;
|
||||
u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
|
||||
u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
|
||||
|
||||
status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
|
||||
he = skb_push(skb, sizeof(known));
|
||||
memcpy(he, &known, sizeof(known));
|
||||
|
||||
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
|
||||
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
|
||||
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
|
||||
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
|
||||
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
|
||||
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
|
||||
he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
|
||||
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
|
||||
le16_encode_bits(ltf_size,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
|
||||
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
|
||||
he->data5 |= HE_BITS(DATA5_TXBF);
|
||||
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
|
||||
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
|
||||
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
|
||||
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
|
||||
|
||||
switch (mode) {
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
|
@ -389,22 +399,22 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
|
|||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
|
||||
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
|
||||
|
||||
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
mt7996_mac_decode_he_mu_radiotap(skb, rxv);
|
||||
|
@ -415,10 +425,10 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
|
|||
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
|
||||
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
|
||||
|
||||
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
|
||||
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
|
||||
HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
|
||||
|
||||
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
|
||||
break;
|
||||
|
@ -570,11 +580,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
|
|||
case MT_PHY_TYPE_EHT_SU:
|
||||
case MT_PHY_TYPE_EHT_TRIG:
|
||||
case MT_PHY_TYPE_EHT_MU:
|
||||
/* TODO: currently report rx rate with HE rate */
|
||||
status->nss = nss;
|
||||
status->encoding = RX_ENC_HE;
|
||||
bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
|
||||
i = min_t(int, i & 0xf, 11);
|
||||
status->encoding = RX_ENC_EHT;
|
||||
i &= GENMASK(3, 0);
|
||||
|
||||
if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
|
||||
status->eht.gi = gi;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -630,6 +641,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
|
|||
u32 rxd4 = le32_to_cpu(rxd[4]);
|
||||
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
|
||||
u32 csum_status = *(u32 *)skb->cb;
|
||||
u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP;
|
||||
bool is_mesh = (rxd0 & mesh_mask) == mesh_mask;
|
||||
bool unicast, insert_ccmp_hdr = false;
|
||||
u8 remove_pad, amsdu_info, band_idx;
|
||||
u8 mode = 0, qos_ctl = 0;
|
||||
|
@ -821,19 +834,16 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
|
|||
int pad_start = 0;
|
||||
|
||||
skb_pull(skb, hdr_gap);
|
||||
if (!hdr_trans && status->amsdu) {
|
||||
if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) {
|
||||
pad_start = ieee80211_get_hdrlen_from_skb(skb);
|
||||
} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
|
||||
} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) &&
|
||||
get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) {
|
||||
/* When header translation failure is indicated,
|
||||
* the hardware will insert an extra 2-byte field
|
||||
* containing the data length after the protocol
|
||||
* type field.
|
||||
*/
|
||||
pad_start = 12;
|
||||
if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
|
||||
pad_start += 4;
|
||||
else
|
||||
pad_start = 0;
|
||||
pad_start = 16;
|
||||
}
|
||||
|
||||
if (pad_start) {
|
||||
|
@ -854,8 +864,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
|
|||
hdr = mt76_skb_get_hdr(skb);
|
||||
fc = hdr->frame_control;
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
u8 *qos = ieee80211_get_qos_ctl(hdr);
|
||||
|
||||
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
|
||||
qos_ctl = *ieee80211_get_qos_ctl(hdr);
|
||||
qos_ctl = *qos;
|
||||
|
||||
/* Mesh DA/SA/Length will be stripped after hardware
|
||||
* de-amsdu, so here needs to clear amsdu present bit
|
||||
* to mark it as a normal mesh frame.
|
||||
*/
|
||||
if (ieee80211_has_a4(fc) && is_mesh && status->amsdu)
|
||||
*qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
}
|
||||
} else {
|
||||
status->flag |= RX_FLAG_8023;
|
||||
|
@ -979,12 +998,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
|||
}
|
||||
|
||||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, u32 changed)
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt76_phy *mphy = &dev->mphy;
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
|
@ -996,22 +1016,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
BSS_CHANGED_FILS_DISCOVERY));
|
||||
|
||||
if (vif) {
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
|
||||
omac_idx = mvif->mt76.omac_idx;
|
||||
wmm_idx = mvif->mt76.wmm_idx;
|
||||
band_idx = mvif->mt76.band_idx;
|
||||
}
|
||||
|
||||
mphy = mt76_dev_phy(&dev->mt76, band_idx);
|
||||
|
||||
if (inband_disc) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else if (beacon) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_BCN0;
|
||||
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
||||
} else if (qid >= MT_TXQ_PSD) {
|
||||
p_fmt = MT_TX_TYPE_CT;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else {
|
||||
|
@ -1062,18 +1078,17 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
|
||||
|
||||
if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
|
||||
/* Fixed rata is available just for 802.11 txd */
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
|
||||
multicast);
|
||||
bool mcast = ieee80211_is_data(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1);
|
||||
u8 idx = mvif->basic_rates_idx;
|
||||
|
||||
/* fix to bw 20 */
|
||||
val = MT_TXD6_FIXED_BW |
|
||||
FIELD_PREP(MT_TXD6_BW, 0) |
|
||||
FIELD_PREP(MT_TXD6_TX_RATE, rate);
|
||||
if (mcast && mvif->mcast_rates_idx)
|
||||
idx = mvif->mcast_rates_idx;
|
||||
else if (beacon && mvif->beacon_rates_idx)
|
||||
idx = mvif->beacon_rates_idx;
|
||||
|
||||
txwi[6] |= cpu_to_le32(val);
|
||||
txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
||||
}
|
||||
}
|
||||
|
@ -1117,11 +1132,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
return id;
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
memset(txwi_ptr, 0, MT_TXD_SIZE);
|
||||
/* Transmit non qos data by 802.11 header and need to fill txd by host*/
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
|
||||
key, 0);
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
|
||||
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
|
@ -1130,10 +1142,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
}
|
||||
txp->fw.nbuf = nbuf;
|
||||
|
||||
txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
|
||||
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
|
||||
txp->fw.flags =
|
||||
cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD);
|
||||
|
||||
if (!key)
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
|
||||
|
@ -1704,7 +1714,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
|
|||
bool ret;
|
||||
|
||||
ret = wait_event_timeout(dev->reset_wait,
|
||||
(READ_ONCE(dev->reset_state) & state),
|
||||
(READ_ONCE(dev->recovery.state) & state),
|
||||
MT7996_RESET_TIMEOUT);
|
||||
|
||||
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
|
||||
|
@ -1753,53 +1763,6 @@ mt7996_update_beacons(struct mt7996_dev *dev)
|
|||
mt7996_update_vif_beacon, phy3->hw);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_dma_reset(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
|
||||
struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
|
||||
u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
int i;
|
||||
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
if (dev->hif2)
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++) {
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
if (phy2)
|
||||
mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
|
||||
if (phy3)
|
||||
mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
|
||||
}
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
/* re-init prefetch settings after reset */
|
||||
mt7996_dma_prefetch(dev);
|
||||
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *txwi;
|
||||
|
@ -1814,7 +1777,193 @@ void mt7996_tx_token_put(struct mt7996_dev *dev)
|
|||
idr_destroy(&dev->mt76.token);
|
||||
}
|
||||
|
||||
/* system error recovery */
|
||||
static int
|
||||
mt7996_mac_restart(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_phy *phy2, *phy3;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
int i, ret;
|
||||
|
||||
phy2 = mt7996_phy2(dev);
|
||||
phy3 = mt7996_phy3(dev);
|
||||
|
||||
if (dev->hif2) {
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
|
||||
mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
if (phy2) {
|
||||
set_bit(MT76_RESET, &phy2->mt76->state);
|
||||
set_bit(MT76_MCU_RESET, &phy2->mt76->state);
|
||||
}
|
||||
if (phy3) {
|
||||
set_bit(MT76_RESET, &phy3->mt76->state);
|
||||
set_bit(MT76_MCU_RESET, &phy3->mt76->state);
|
||||
}
|
||||
|
||||
/* lock/unlock all queues to ensure that no tx is pending */
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
if (phy2)
|
||||
mt76_txq_schedule_all(phy2->mt76);
|
||||
if (phy3)
|
||||
mt76_txq_schedule_all(phy3->mt76);
|
||||
|
||||
/* disable all tx/rx napi */
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
mt76_for_each_q_rx(mdev, i) {
|
||||
if (mdev->q_rx[i].ndesc)
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
}
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
/* token reinit */
|
||||
mt7996_tx_token_put(dev);
|
||||
idr_init(&dev->mt76.token);
|
||||
|
||||
mt7996_dma_reset(dev, true);
|
||||
|
||||
local_bh_disable();
|
||||
mt76_for_each_q_rx(mdev, i) {
|
||||
if (mdev->q_rx[i].ndesc) {
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
}
|
||||
}
|
||||
local_bh_enable();
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
|
||||
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
|
||||
if (dev->hif2) {
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
|
||||
mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
|
||||
}
|
||||
if (dev_is_pci(mdev->dev)) {
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
|
||||
}
|
||||
|
||||
/* load firmware */
|
||||
ret = mt7996_mcu_init_firmware(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* set the necessary init items */
|
||||
ret = mt7996_mcu_set_eeprom(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7996_mac_init(dev);
|
||||
mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
|
||||
mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
|
||||
mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
|
||||
ret = mt7996_txbf_init(dev);
|
||||
|
||||
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
|
||||
ret = mt7996_run(dev->mphy.hw);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
|
||||
ret = mt7996_run(phy2->mt76->hw);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
|
||||
ret = mt7996_run(phy3->mt76->hw);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
/* reset done */
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
if (phy2)
|
||||
clear_bit(MT76_RESET, &phy2->mt76->state);
|
||||
if (phy3)
|
||||
clear_bit(MT76_RESET, &phy3->mt76->state);
|
||||
|
||||
local_bh_disable();
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
local_bh_enable();
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mac_full_reset(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt7996_phy *phy2, *phy3;
|
||||
int i;
|
||||
|
||||
phy2 = mt7996_phy2(dev);
|
||||
phy3 = mt7996_phy3(dev);
|
||||
dev->recovery.hw_full_reset = true;
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
if (phy2)
|
||||
ieee80211_stop_queues(phy2->mt76->hw);
|
||||
if (phy3)
|
||||
ieee80211_stop_queues(phy3->mt76->hw);
|
||||
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
if (phy2)
|
||||
cancel_delayed_work_sync(&phy2->mt76->mac_work);
|
||||
if (phy3)
|
||||
cancel_delayed_work_sync(&phy3->mt76->mac_work);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (!mt7996_mac_restart(dev))
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip full reset failed\n");
|
||||
|
||||
ieee80211_restart_hw(mt76_hw(dev));
|
||||
if (phy2)
|
||||
ieee80211_restart_hw(phy2->mt76->hw);
|
||||
if (phy3)
|
||||
ieee80211_restart_hw(phy3->mt76->hw);
|
||||
|
||||
ieee80211_wake_queues(mt76_hw(dev));
|
||||
if (phy2)
|
||||
ieee80211_wake_queues(phy2->mt76->hw);
|
||||
if (phy3)
|
||||
ieee80211_wake_queues(phy3->mt76->hw);
|
||||
|
||||
dev->recovery.hw_full_reset = false;
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev),
|
||||
&dev->mphy.mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
if (phy2)
|
||||
ieee80211_queue_delayed_work(phy2->mt76->hw,
|
||||
&phy2->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
if (phy3)
|
||||
ieee80211_queue_delayed_work(phy3->mt76->hw,
|
||||
&phy3->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
}
|
||||
|
||||
void mt7996_mac_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7996_phy *phy2, *phy3;
|
||||
|
@ -1825,9 +1974,36 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
|||
phy2 = mt7996_phy2(dev);
|
||||
phy3 = mt7996_phy3(dev);
|
||||
|
||||
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
|
||||
/* chip full reset */
|
||||
if (dev->recovery.restart) {
|
||||
/* disable WA/WM WDT */
|
||||
mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
|
||||
MT_MCU_CMD_WDT_MASK);
|
||||
|
||||
if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
|
||||
dev->recovery.wa_reset_count++;
|
||||
else
|
||||
dev->recovery.wm_reset_count++;
|
||||
|
||||
mt7996_mac_full_reset(dev);
|
||||
|
||||
/* enable mcu irq */
|
||||
mt7996_irq_enable(dev, MT_INT_MCU_CMD);
|
||||
mt7996_irq_disable(dev, 0);
|
||||
|
||||
/* enable WA/WM WDT */
|
||||
mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
|
||||
|
||||
dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
|
||||
dev->recovery.restart = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
|
||||
return;
|
||||
|
||||
dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
|
||||
wiphy_name(dev->mt76.hw->wiphy));
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
if (phy2)
|
||||
ieee80211_stop_queues(phy2->mt76->hw);
|
||||
|
@ -1856,7 +2032,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
|||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
|
||||
|
||||
if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
mt7996_dma_reset(dev);
|
||||
mt7996_dma_reset(dev, false);
|
||||
|
||||
mt7996_tx_token_put(dev);
|
||||
idr_init(&dev->mt76.token);
|
||||
|
@ -1879,7 +2055,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
|||
}
|
||||
local_bh_enable();
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
|
||||
mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
|
||||
|
@ -1911,6 +2087,101 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
|||
ieee80211_queue_delayed_work(phy3->mt76->hw,
|
||||
&phy3->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
|
||||
wiphy_name(dev->mt76.hw->wiphy));
|
||||
}
|
||||
|
||||
/* firmware coredump */
|
||||
void mt7996_mac_dump_work(struct work_struct *work)
|
||||
{
|
||||
const struct mt7996_mem_region *mem_region;
|
||||
struct mt7996_crash_data *crash_data;
|
||||
struct mt7996_dev *dev;
|
||||
struct mt7996_mem_hdr *hdr;
|
||||
size_t buf_len;
|
||||
int i;
|
||||
u32 num;
|
||||
u8 *buf;
|
||||
|
||||
dev = container_of(work, struct mt7996_dev, dump_work);
|
||||
|
||||
mutex_lock(&dev->dump_mutex);
|
||||
|
||||
crash_data = mt7996_coredump_new(dev);
|
||||
if (!crash_data) {
|
||||
mutex_unlock(&dev->dump_mutex);
|
||||
goto skip_coredump;
|
||||
}
|
||||
|
||||
mem_region = mt7996_coredump_get_mem_layout(dev, &num);
|
||||
if (!mem_region || !crash_data->memdump_buf_len) {
|
||||
mutex_unlock(&dev->dump_mutex);
|
||||
goto skip_memdump;
|
||||
}
|
||||
|
||||
buf = crash_data->memdump_buf;
|
||||
buf_len = crash_data->memdump_buf_len;
|
||||
|
||||
/* dumping memory content... */
|
||||
memset(buf, 0, buf_len);
|
||||
for (i = 0; i < num; i++) {
|
||||
if (mem_region->len > buf_len) {
|
||||
dev_warn(dev->mt76.dev, "%s len %zu is too large\n",
|
||||
mem_region->name, mem_region->len);
|
||||
break;
|
||||
}
|
||||
|
||||
/* reserve space for the header */
|
||||
hdr = (void *)buf;
|
||||
buf += sizeof(*hdr);
|
||||
buf_len -= sizeof(*hdr);
|
||||
|
||||
mt7996_memcpy_fromio(dev, buf, mem_region->start,
|
||||
mem_region->len);
|
||||
|
||||
hdr->start = mem_region->start;
|
||||
hdr->len = mem_region->len;
|
||||
|
||||
if (!mem_region->len)
|
||||
/* note: the header remains, just with zero length */
|
||||
break;
|
||||
|
||||
buf += mem_region->len;
|
||||
buf_len -= mem_region->len;
|
||||
|
||||
mem_region++;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->dump_mutex);
|
||||
|
||||
skip_memdump:
|
||||
mt7996_coredump_submit(dev);
|
||||
skip_coredump:
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
}
|
||||
|
||||
void mt7996_reset(struct mt7996_dev *dev)
|
||||
{
|
||||
if (!dev->recovery.hw_init_done)
|
||||
return;
|
||||
|
||||
if (dev->recovery.hw_full_reset)
|
||||
return;
|
||||
|
||||
/* wm/wa exception: do full recovery */
|
||||
if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
|
||||
dev->recovery.restart = true;
|
||||
dev_info(dev->mt76.dev,
|
||||
"%s indicated firmware crash, attempting recovery\n",
|
||||
wiphy_name(dev->mt76.hw->wiphy));
|
||||
|
||||
mt7996_irq_disable(dev, MT_INT_MCU_CMD);
|
||||
queue_work(dev->mt76.wq, &dev->dump_work);
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
wake_up(&dev->reset_wait);
|
||||
}
|
||||
|
||||
void mt7996_mac_update_stats(struct mt7996_phy *phy)
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#define MT_RXD0_LENGTH GENMASK(15, 0)
|
||||
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
|
||||
|
||||
#define MT_RXD0_MESH BIT(18)
|
||||
#define MT_RXD0_MHCP BIT(19)
|
||||
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
|
||||
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
|
||||
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
|
||||
|
@ -20,18 +22,6 @@
|
|||
#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
|
||||
#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
|
||||
|
||||
enum rx_pkt_type {
|
||||
PKT_TYPE_TXS,
|
||||
PKT_TYPE_TXRXV,
|
||||
PKT_TYPE_NORMAL,
|
||||
PKT_TYPE_RX_DUP_RFB,
|
||||
PKT_TYPE_RX_TMR,
|
||||
PKT_TYPE_RETRIEVE,
|
||||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_RX_FW_MONITOR = 0x0c,
|
||||
};
|
||||
|
||||
/* RXD DW1 */
|
||||
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
|
||||
#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
|
||||
|
@ -102,8 +92,7 @@ enum rx_pkt_type {
|
|||
#define MT_PRXV_NSTS GENMASK(10, 7)
|
||||
#define MT_PRXV_TXBF BIT(11)
|
||||
#define MT_PRXV_HT_AD_CODE BIT(12)
|
||||
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
|
||||
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
|
||||
#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
|
||||
#define MT_PRXV_RCPI3 GENMASK(31, 24)
|
||||
#define MT_PRXV_RCPI2 GENMASK(23, 16)
|
||||
#define MT_PRXV_RCPI1 GENMASK(15, 8)
|
||||
|
@ -113,34 +102,32 @@ enum rx_pkt_type {
|
|||
#define MT_PRXV_TX_MODE GENMASK(14, 11)
|
||||
#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
|
||||
#define MT_PRXV_DCM BIT(5)
|
||||
#define MT_PRXV_NUM_RX BIT(8, 6)
|
||||
|
||||
/* C-RXV */
|
||||
#define MT_CRXV_HT_STBC GENMASK(1, 0)
|
||||
#define MT_CRXV_TX_MODE GENMASK(7, 4)
|
||||
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
|
||||
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
|
||||
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
|
||||
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
|
||||
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
|
||||
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
|
||||
#define MT_CRXV_HE_UPLINK BIT(31)
|
||||
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
|
||||
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
|
||||
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
|
||||
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
|
||||
#define MT_CRXV_HE_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_MU_AID GENMASK(30, 20)
|
||||
#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
|
||||
#define MT_CRXV_HE_UPLINK BIT(2)
|
||||
|
||||
#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
|
||||
#define MT_CRXV_HE_BEAM_CHNG BIT(29)
|
||||
|
||||
#define MT_CRXV_HE_DOPPLER BIT(0)
|
||||
#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
|
||||
#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
|
||||
|
||||
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
|
||||
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
|
||||
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
|
||||
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
|
||||
|
||||
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
|
||||
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
|
||||
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
|
||||
#define MT_CRXV_HE_DOPPLER BIT(16)
|
||||
#define MT_CRXV_HE_RU0 GENMASK(8, 0)
|
||||
#define MT_CRXV_HE_RU1 GENMASK(17, 9)
|
||||
#define MT_CRXV_HE_RU2 GENMASK(26, 18)
|
||||
#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
|
||||
#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
|
||||
|
||||
enum tx_header_format {
|
||||
MT_HDR_FORMAT_802_3,
|
||||
|
@ -239,14 +226,11 @@ enum tx_mgnt_type {
|
|||
|
||||
#define MT_TXD6_TX_SRC GENMASK(31, 30)
|
||||
#define MT_TXD6_VTA BIT(28)
|
||||
#define MT_TXD6_FIXED_BW BIT(25)
|
||||
#define MT_TXD6_BW GENMASK(24, 22)
|
||||
#define MT_TXD6_BW GENMASK(25, 22)
|
||||
#define MT_TXD6_TX_RATE GENMASK(21, 16)
|
||||
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
|
||||
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
|
||||
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
|
||||
#define MT_TXD6_SPE_ID_IDX BIT(10)
|
||||
#define MT_TXD6_ANT_ID GENMASK(7, 4)
|
||||
#define MT_TXD6_DIS_MAT BIT(3)
|
||||
#define MT_TXD6_DAS BIT(2)
|
||||
#define MT_TXD6_AMSDU_CAP BIT(1)
|
||||
|
@ -260,7 +244,7 @@ enum tx_mgnt_type {
|
|||
#define MT_TXD7_UDP_TCP_SUM BIT(15)
|
||||
#define MT_TXD7_TX_TIME GENMASK(9, 0)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(13)
|
||||
#define MT_TX_RATE_STBC BIT(14)
|
||||
#define MT_TX_RATE_NSS GENMASK(13, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "mt7996.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static bool mt7996_dev_running(struct mt7996_dev *dev)
|
||||
{
|
||||
|
@ -22,17 +23,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
|
|||
return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
}
|
||||
|
||||
static int mt7996_start(struct ieee80211_hw *hw)
|
||||
int mt7996_run(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
bool running;
|
||||
int ret;
|
||||
|
||||
flush_work(&dev->init_work);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
running = mt7996_dev_running(dev);
|
||||
if (!running) {
|
||||
ret = mt7996_mcu_set_hdr_trans(dev, true);
|
||||
|
@ -52,10 +49,6 @@ static int mt7996_start(struct ieee80211_hw *hw)
|
|||
|
||||
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
|
||||
ieee80211_iterate_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_mcu_set_pm, dev->mt76.hw);
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
|
||||
|
@ -63,6 +56,18 @@ static int mt7996_start(struct ieee80211_hw *hw)
|
|||
mt7996_mac_reset_counters(phy);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7996_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
int ret;
|
||||
|
||||
flush_work(&dev->init_work);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
ret = mt7996_run(hw);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -79,10 +84,6 @@ static void mt7996_stop(struct ieee80211_hw *hw)
|
|||
|
||||
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
|
||||
ieee80211_iterate_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_mcu_set_pm, dev->mt76.hw);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
|
@ -219,8 +220,12 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
|
|||
vif->offload_flags = 0;
|
||||
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
|
||||
|
||||
if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
|
||||
mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
|
||||
else
|
||||
mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;
|
||||
|
||||
mt7996_init_bitrate_mask(vif);
|
||||
memset(&mvif->cap, -1, sizeof(mvif->cap));
|
||||
|
||||
mt7996_mcu_add_bss_info(phy, vif, true);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, true);
|
||||
|
@ -497,11 +502,41 @@ mt7996_update_bss_color(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
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_phy *mphy = hw->priv;
|
||||
u16 rate;
|
||||
u8 i, idx, ht;
|
||||
|
||||
rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
|
||||
ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
|
||||
|
||||
if (beacon && ht) {
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
|
||||
/* must odd index */
|
||||
idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
|
||||
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
|
||||
return idx;
|
||||
}
|
||||
|
||||
idx = FIELD_GET(MT_TX_RATE_IDX, rate);
|
||||
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
|
||||
if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
|
||||
return MT7996_BASIC_RATES_TBL + i;
|
||||
|
||||
return mvif->basic_rates_idx;
|
||||
}
|
||||
|
||||
static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
u64 changed)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
|
||||
|
@ -533,6 +568,14 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_MCAST_RATE)
|
||||
mvif->mcast_rates_idx =
|
||||
mt7996_get_rates_table(hw, vif, false, true);
|
||||
|
||||
if (changed & BSS_CHANGED_BASIC_RATES)
|
||||
mvif->basic_rates_idx =
|
||||
mt7996_get_rates_table(hw, vif, false, false);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
mt7996_mcu_add_bss_info(phy, vif, true);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, true);
|
||||
|
@ -549,8 +592,12 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
|||
mt7996_update_bss_color(hw, vif, &info->he_bss_color);
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
BSS_CHANGED_BEACON_ENABLED)) {
|
||||
mvif->beacon_rates_idx =
|
||||
mt7996_get_rates_table(hw, vif, true, false);
|
||||
|
||||
mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
|
||||
changed & BSS_CHANGED_FILS_DISCOVERY)
|
||||
|
@ -892,6 +939,7 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
|||
mt7996_set_stream_vht_txbf_caps(phy);
|
||||
mt7996_set_stream_he_eht_caps(phy);
|
||||
|
||||
/* TODO: update bmc_wtbl spe_idx when antenna changes */
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -422,7 +422,8 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
|
|||
if (hdr->band && dev->mt76.phys[hdr->band])
|
||||
mphy = dev->mt76.phys[hdr->band];
|
||||
|
||||
tail = skb->data + le16_to_cpu(rxd->len);
|
||||
tail = skb->data + skb->len;
|
||||
data += sizeof(struct header);
|
||||
while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) {
|
||||
switch (le16_to_cpu(tlv->tag)) {
|
||||
case UNI_EVENT_IE_COUNTDOWN_CSA:
|
||||
|
@ -596,25 +597,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7996_phy *phy)
|
||||
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
struct mt7996_phy *phy)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct bss_rate_tlv *bmc;
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct tlv *tlv;
|
||||
u8 idx = mvif->mcast_rates_idx ?
|
||||
mvif->mcast_rates_idx : mvif->basic_rates_idx;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc));
|
||||
|
||||
bmc = (struct bss_rate_tlv *)tlv;
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
bmc->short_preamble = true;
|
||||
} else {
|
||||
bmc->bc_trans = cpu_to_le16(0x8080);
|
||||
bmc->mc_trans = cpu_to_le16(0x8080);
|
||||
bmc->bc_fixed_rate = 1;
|
||||
bmc->mc_fixed_rate = 1;
|
||||
bmc->short_preamble = 1;
|
||||
}
|
||||
|
||||
bmc->short_preamble = (band == NL80211_BAND_2GHZ);
|
||||
bmc->bc_fixed_rate = idx;
|
||||
bmc->mc_fixed_rate = idx;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -822,7 +822,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
|
|||
|
||||
if (enable) {
|
||||
mt7996_mcu_bss_rfch_tlv(skb, vif, phy);
|
||||
mt7996_mcu_bss_bmc_tlv(skb, phy);
|
||||
mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
|
||||
mt7996_mcu_bss_ra_tlv(skb, vif, phy);
|
||||
mt7996_mcu_bss_txcmd_tlv(skb, true);
|
||||
|
||||
|
@ -1022,6 +1022,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
struct tlv *tlv;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_MESH_POINT &&
|
||||
vif->type != NL80211_IFTYPE_AP)
|
||||
return;
|
||||
|
||||
|
@ -1053,7 +1054,6 @@ static inline bool
|
|||
mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool bfee)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
int sts = hweight16(phy->mt76->chainmask);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
|
@ -1068,10 +1068,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
|||
struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.eht_su_ebfee &&
|
||||
return vif->bss_conf.eht_su_beamformee &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
|
||||
else
|
||||
return mvif->cap.eht_su_ebfer &&
|
||||
return vif->bss_conf.eht_su_beamformer &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
|
||||
}
|
||||
|
||||
|
@ -1079,10 +1079,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
|||
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.he_su_ebfee &&
|
||||
return vif->bss_conf.he_su_beamformee &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
else
|
||||
return mvif->cap.he_su_ebfer &&
|
||||
return vif->bss_conf.he_su_beamformer &&
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
|
||||
}
|
||||
|
||||
|
@ -1090,10 +1090,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
|||
u32 cap = sta->deflink.vht_cap.cap;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.vht_su_ebfee &&
|
||||
return vif->bss_conf.vht_su_beamformee &&
|
||||
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
else
|
||||
return mvif->cap.vht_su_ebfer &&
|
||||
return vif->bss_conf.vht_su_beamformer &&
|
||||
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
|
||||
}
|
||||
|
||||
|
@ -1471,6 +1471,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
|||
hdr_trans->to_ds = true;
|
||||
hdr_trans->from_ds = true;
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_MESH_POINT) {
|
||||
hdr_trans->to_ds = true;
|
||||
hdr_trans->from_ds = true;
|
||||
hdr_trans->mesh = true;
|
||||
}
|
||||
}
|
||||
|
||||
static enum mcu_mmps_mode
|
||||
|
@ -1572,7 +1578,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
|||
cap |= STA_CAP_TX_STBC;
|
||||
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
cap |= STA_CAP_RX_STBC;
|
||||
if (mvif->cap.ht_ldpc &&
|
||||
if (vif->bss_conf.ht_ldpc &&
|
||||
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
|
||||
cap |= STA_CAP_LDPC;
|
||||
|
||||
|
@ -1598,7 +1604,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
|||
cap |= STA_CAP_VHT_TX_STBC;
|
||||
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
|
||||
cap |= STA_CAP_VHT_RX_STBC;
|
||||
if (mvif->cap.vht_ldpc &&
|
||||
if (vif->bss_conf.vht_ldpc &&
|
||||
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
|
||||
cap |= STA_CAP_VHT_LDPC;
|
||||
|
||||
|
@ -1694,8 +1700,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
return PTR_ERR(skb);
|
||||
|
||||
/* starec basic */
|
||||
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
|
||||
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
|
||||
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable,
|
||||
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
|
@ -1906,107 +1912,12 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
|
||||
BSS_CHANGED_BEACON);
|
||||
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_vif_cap *vc = &mvif->cap;
|
||||
const struct ieee80211_eht_cap_elem_fixed *eht;
|
||||
const struct ieee80211_he_cap_elem *he;
|
||||
const struct ieee80211_vht_cap *vht;
|
||||
const struct ieee80211_ht_cap *ht;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
const u8 *ie;
|
||||
u32 len, bc;
|
||||
|
||||
/* Check missing configuration options to allow AP mode in mac80211
|
||||
* to remain in sync with hostapd settings, and get a subset of
|
||||
* beacon and hardware capabilities.
|
||||
*/
|
||||
if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data)))
|
||||
return;
|
||||
|
||||
memset(vc, 0, sizeof(*vc));
|
||||
|
||||
len = skb->len - (mgmt->u.beacon.variable - skb->data);
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
len);
|
||||
if (ie && ie[1] >= sizeof(*ht)) {
|
||||
ht = (void *)(ie + 2);
|
||||
vc->ht_ldpc |= !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
len);
|
||||
if (ie && ie[1] >= sizeof(*vht)) {
|
||||
u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap;
|
||||
|
||||
vht = (void *)(ie + 2);
|
||||
bc = le32_to_cpu(vht->vht_cap_info);
|
||||
|
||||
vc->vht_ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_su_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
vc->vht_su_ebfee =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
|
||||
vc->vht_mu_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
|
||||
vc->vht_mu_ebfee =
|
||||
(bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY,
|
||||
mgmt->u.beacon.variable, len);
|
||||
if (ie && ie[1] >= sizeof(*he) + 1) {
|
||||
const struct ieee80211_sta_he_cap *pc =
|
||||
mt76_connac_get_he_phy_cap(phy->mt76, vif);
|
||||
const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
|
||||
|
||||
he = (void *)(ie + 3);
|
||||
|
||||
vc->he_ldpc =
|
||||
HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
|
||||
vc->he_su_ebfer =
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
vc->he_su_ebfee =
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) &&
|
||||
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
|
||||
vc->he_mu_ebfer =
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) &&
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY,
|
||||
mgmt->u.beacon.variable, len);
|
||||
if (ie && ie[1] >= sizeof(*eht) + 1) {
|
||||
const struct ieee80211_sta_eht_cap *pc =
|
||||
mt76_connac_get_eht_phy_cap(phy->mt76, vif);
|
||||
const struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
|
||||
|
||||
eht = (void *)(ie + 3);
|
||||
|
||||
vc->eht_su_ebfer =
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, eht->phy_cap_info[0]) &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
|
||||
vc->eht_su_ebfee =
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
|
||||
}
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int en)
|
||||
{
|
||||
|
@ -2045,8 +1956,6 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
|
|||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
|
||||
|
||||
mt7996_mcu_beacon_check_caps(phy, vif, skb);
|
||||
|
||||
mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
/* TODO: subtag - 11v MBSSID */
|
||||
mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
|
||||
|
@ -2115,8 +2024,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
|||
|
||||
buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
|
||||
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
changed);
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
|
||||
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
|
||||
|
@ -2523,17 +2431,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
|
|||
MCU_WM_UNI_CMD(VOW), true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_init(struct mt7996_dev *dev)
|
||||
int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7996_mcu_ops = {
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
|
||||
.mcu_skb_send_msg = mt7996_mcu_send_message,
|
||||
.mcu_parse_response = mt7996_mcu_parse_response,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mt7996_mcu_ops;
|
||||
|
||||
/* force firmware operation mode into normal state,
|
||||
* which should be set before firmware download stage.
|
||||
*/
|
||||
|
@ -2574,6 +2475,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
|
|||
MCU_WA_PARAM_RED, 0, 0);
|
||||
}
|
||||
|
||||
int mt7996_mcu_init(struct mt7996_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7996_mcu_ops = {
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
|
||||
.mcu_skb_send_msg = mt7996_mcu_send_message,
|
||||
.mcu_parse_response = mt7996_mcu_parse_response,
|
||||
};
|
||||
|
||||
dev->mt76.mcu_ops = &mt7996_mcu_ops;
|
||||
|
||||
return mt7996_mcu_init_firmware(dev);
|
||||
}
|
||||
|
||||
void mt7996_mcu_exit(struct mt7996_dev *dev)
|
||||
{
|
||||
mt7996_mcu_restart(&dev->mt76);
|
||||
|
@ -3133,7 +3047,7 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
|
|||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
buf += le16_to_cpu(tlv->len);
|
||||
}
|
||||
|
@ -3576,32 +3490,6 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
|||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
#define EXIT_PM_STATE 0
|
||||
#define ENTER_PM_STATE 1
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct bss_power_save *ps;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
bool running = test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
|
||||
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
|
||||
MT7996_BSS_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PS, sizeof(*ps));
|
||||
ps = (struct bss_power_save *)tlv;
|
||||
ps->profile = running ? EXIT_PM_STATE : ENTER_PM_STATE;
|
||||
|
||||
mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
|
||||
{
|
||||
struct {
|
||||
|
@ -3733,6 +3621,22 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev)
|
||||
{
|
||||
struct {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 enable;
|
||||
u8 rsv[3];
|
||||
} __packed req = {
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
.enable = true,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ASSERT_DUMP),
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
|
||||
{
|
||||
struct {
|
||||
|
|
|
@ -396,7 +396,7 @@ struct sta_rec_hdr_trans {
|
|||
u8 from_ds;
|
||||
u8 to_ds;
|
||||
u8 dis_rx_hdr_tran;
|
||||
u8 rsv;
|
||||
u8 mesh;
|
||||
} __packed;
|
||||
|
||||
struct hdr_trans_en {
|
||||
|
@ -648,23 +648,21 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
UNI_CMD_SER_QUERY = 0x0,
|
||||
UNI_CMD_SER_SET = 0x2,
|
||||
UNI_CMD_SER_TRIGGER = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
SER_QUERY,
|
||||
UNI_CMD_SER_QUERY,
|
||||
/* recovery */
|
||||
SER_SET_RECOVER_L1,
|
||||
SER_SET_RECOVER_L2,
|
||||
SER_SET_RECOVER_L3_RX_ABORT,
|
||||
SER_SET_RECOVER_L3_TX_ABORT,
|
||||
SER_SET_RECOVER_L3_TX_DISABLE,
|
||||
SER_SET_RECOVER_L3_BF,
|
||||
UNI_CMD_SER_SET_RECOVER_L1,
|
||||
UNI_CMD_SER_SET_RECOVER_L2,
|
||||
UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT,
|
||||
UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT,
|
||||
UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
|
||||
UNI_CMD_SER_SET_RECOVER_L3_BF,
|
||||
UNI_CMD_SER_SET_RECOVER_L4_MDP,
|
||||
UNI_CMD_SER_SET_RECOVER_FULL,
|
||||
UNI_CMD_SER_SET_SYSTEM_ASSERT,
|
||||
/* action */
|
||||
SER_ENABLE = 2,
|
||||
SER_RECOVER
|
||||
UNI_CMD_SER_ENABLE = 1,
|
||||
UNI_CMD_SER_SET,
|
||||
UNI_CMD_SER_TRIGGER
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -162,6 +162,14 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
|
|||
return mt7996_reg_map_l2(dev, addr);
|
||||
}
|
||||
|
||||
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
|
||||
size_t len)
|
||||
{
|
||||
u32 addr = __mt7996_reg_addr(dev, offset);
|
||||
|
||||
memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
|
||||
}
|
||||
|
||||
static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset)
|
||||
{
|
||||
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
|
||||
|
@ -251,7 +259,7 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
|
|||
/* TODO: support 2/4/6/8 MSI-X vectors */
|
||||
static void mt7996_irq_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct mt7996_dev *dev = from_tasklet(dev, t, irq_tasklet);
|
||||
struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
|
||||
u32 i, intr, mask, intr1;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
|
@ -289,10 +297,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
|
|||
u32 val = mt76_rr(dev, MT_MCU_CMD);
|
||||
|
||||
mt76_wr(dev, MT_MCU_CMD, val);
|
||||
if (val & MT_MCU_CMD_ERROR_MASK) {
|
||||
dev->reset_state = val;
|
||||
ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
|
||||
wake_up(&dev->reset_wait);
|
||||
if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
|
||||
dev->recovery.state = val;
|
||||
mt7996_reset(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +315,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
|
|||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return IRQ_NONE;
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -320,6 +327,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
|||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE |
|
||||
MT_DRV_AMSDU_OFFLOAD |
|
||||
MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
|
@ -330,7 +338,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
|||
.rx_skb = mt7996_queue_rx_skb,
|
||||
.rx_check = mt7996_rx_check,
|
||||
.rx_poll_complete = mt7996_rx_poll_complete,
|
||||
.sta_ps = mt7996_sta_ps,
|
||||
.sta_add = mt7996_mac_sta_add,
|
||||
.sta_remove = mt7996_mac_sta_remove,
|
||||
.update_survey = mt7996_update_channel,
|
||||
|
@ -349,7 +356,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
tasklet_setup(&dev->irq_tasklet, mt7996_irq_tasklet);
|
||||
tasklet_setup(&mdev->irq_tasklet, mt7996_irq_tasklet);
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
#define MT7996_MAX_STA_TWT_AGRT 8
|
||||
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
|
||||
|
||||
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
|
||||
#define MT7996_BASIC_RATES_TBL 11
|
||||
#define MT7996_BEACON_RATES_TBL 25
|
||||
|
||||
struct mt7996_vif;
|
||||
struct mt7996_sta;
|
||||
struct mt7996_dfs_pulse;
|
||||
|
@ -112,30 +116,18 @@ struct mt7996_sta {
|
|||
} twt;
|
||||
};
|
||||
|
||||
struct mt7996_vif_cap {
|
||||
bool ht_ldpc:1;
|
||||
bool vht_ldpc:1;
|
||||
bool he_ldpc:1;
|
||||
bool vht_su_ebfer:1;
|
||||
bool vht_su_ebfee:1;
|
||||
bool vht_mu_ebfer:1;
|
||||
bool vht_mu_ebfee:1;
|
||||
bool he_su_ebfer:1;
|
||||
bool he_su_ebfee:1;
|
||||
bool he_mu_ebfer:1;
|
||||
bool eht_su_ebfer:1;
|
||||
bool eht_su_ebfee:1;
|
||||
};
|
||||
|
||||
struct mt7996_vif {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
|
||||
struct mt7996_vif_cap cap;
|
||||
struct mt7996_sta sta;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
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. */
|
||||
|
@ -192,6 +184,15 @@ struct mib_stats {
|
|||
u32 tx_amsdu_cnt;
|
||||
};
|
||||
|
||||
/* crash-dump */
|
||||
struct mt7996_crash_data {
|
||||
guid_t guid;
|
||||
struct timespec64 timestamp;
|
||||
|
||||
u8 *memdump_buf;
|
||||
size_t memdump_buf_len;
|
||||
};
|
||||
|
||||
struct mt7996_hif {
|
||||
struct list_head list;
|
||||
|
||||
|
@ -238,7 +239,6 @@ struct mt7996_dev {
|
|||
u32 q_wfdma_mask;
|
||||
|
||||
const struct mt76_bus_ops *bus_ops;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct mt7996_phy phy;
|
||||
|
||||
/* monitor rx chain configured channel */
|
||||
|
@ -251,9 +251,25 @@ struct mt7996_dev {
|
|||
|
||||
struct work_struct init_work;
|
||||
struct work_struct rc_work;
|
||||
struct work_struct dump_work;
|
||||
struct work_struct reset_work;
|
||||
wait_queue_head_t reset_wait;
|
||||
u32 reset_state;
|
||||
struct {
|
||||
u32 state;
|
||||
u32 wa_reset_count;
|
||||
u32 wm_reset_count;
|
||||
bool hw_full_reset:1;
|
||||
bool hw_init_done:1;
|
||||
bool restart:1;
|
||||
} recovery;
|
||||
|
||||
/* protects coredump data */
|
||||
struct mutex dump_mutex;
|
||||
#ifdef CONFIG_DEV_COREDUMP
|
||||
struct {
|
||||
struct mt7996_crash_data *crash_data;
|
||||
} coredump;
|
||||
#endif
|
||||
|
||||
struct list_head sta_rc_list;
|
||||
struct list_head sta_poll_list;
|
||||
|
@ -386,9 +402,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
|
|||
struct ieee80211_channel *chan);
|
||||
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
|
||||
int mt7996_dma_init(struct mt7996_dev *dev);
|
||||
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
|
||||
void mt7996_dma_prefetch(struct mt7996_dev *dev);
|
||||
void mt7996_dma_cleanup(struct mt7996_dev *dev);
|
||||
void mt7996_init_txpower(struct mt7996_dev *dev,
|
||||
struct ieee80211_supported_band *sband);
|
||||
int mt7996_txbf_init(struct mt7996_dev *dev);
|
||||
void mt7996_reset(struct mt7996_dev *dev);
|
||||
int mt7996_run(struct ieee80211_hw *hw);
|
||||
int mt7996_mcu_init(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||
struct mt7996_vif *mvif,
|
||||
struct mt7996_twt_flow *flow,
|
||||
|
@ -432,7 +455,6 @@ int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev,
|
|||
int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
|
||||
const struct mt7996_dfs_pattern *pattern);
|
||||
int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
|
||||
void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif);
|
||||
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
|
||||
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
|
||||
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
|
||||
|
@ -445,6 +467,7 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
|
|||
int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
|
||||
int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
|
||||
int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
|
||||
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
|
||||
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
|
||||
void mt7996_mcu_exit(struct mt7996_dev *dev);
|
||||
|
||||
|
@ -468,7 +491,7 @@ static inline void mt7996_irq_enable(struct mt7996_dev *dev, u32 mask)
|
|||
else
|
||||
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
|
||||
|
||||
tasklet_schedule(&dev->irq_tasklet);
|
||||
tasklet_schedule(&dev->mt76.irq_tasklet);
|
||||
}
|
||||
|
||||
static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
|
||||
|
@ -479,6 +502,10 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
|
|||
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
|
||||
}
|
||||
|
||||
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
|
||||
size_t len);
|
||||
|
||||
void mt7996_mac_init(struct mt7996_dev *dev);
|
||||
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
|
||||
void mt7996_mac_reset_counters(struct mt7996_phy *phy);
|
||||
|
@ -486,9 +513,12 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
|
|||
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
|
||||
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
|
||||
u8 tbl_idx, u16 rate_idx);
|
||||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, u32 changed);
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
void mt7996_mac_set_timing(struct mt7996_phy *phy);
|
||||
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
@ -496,6 +526,7 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
struct ieee80211_sta *sta);
|
||||
void mt7996_mac_work(struct work_struct *work);
|
||||
void mt7996_mac_reset_work(struct work_struct *work);
|
||||
void mt7996_mac_dump_work(struct work_struct *work);
|
||||
void mt7996_mac_sta_rc_work(struct work_struct *work);
|
||||
void mt7996_mac_update_stats(struct mt7996_phy *phy);
|
||||
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
|
||||
|
@ -512,7 +543,6 @@ void mt7996_tx_token_put(struct mt7996_dev *dev);
|
|||
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
|
||||
void mt7996_stats_work(struct work_struct *work);
|
||||
int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
|
||||
int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy);
|
||||
|
|
|
@ -228,6 +228,13 @@ enum base_rev {
|
|||
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
|
||||
#define MT_WTBL_UPDATE_BUSY BIT(31)
|
||||
|
||||
#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0)
|
||||
#define MT_WTBL_ITCR_WR BIT(16)
|
||||
#define MT_WTBL_ITCR_EXEC BIT(31)
|
||||
#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8)
|
||||
#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc)
|
||||
#define MT_WTBL_SPE_IDX_SEL BIT(6)
|
||||
|
||||
/* WTBL */
|
||||
#define MT_WTBL_BASE 0x820d8000
|
||||
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
|
||||
|
@ -317,6 +324,8 @@ enum base_rev {
|
|||
#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
|
||||
#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
|
||||
|
||||
#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
|
||||
|
||||
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
|
||||
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
|
||||
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
|
||||
|
@ -444,6 +453,10 @@ enum base_rev {
|
|||
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
|
||||
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
|
||||
|
||||
#define MT_MCU_CMD_WA_WDT BIT(31)
|
||||
#define MT_MCU_CMD_WM_WDT BIT(30)
|
||||
#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
|
||||
|
||||
/* l1/l2 remap */
|
||||
#define MT_HIF_REMAP_L1 0x155024
|
||||
#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
|
||||
|
@ -468,9 +481,28 @@ enum base_rev {
|
|||
#define MT_INFRA_MCU_END 0x7c3fffff
|
||||
|
||||
/* FW MODE SYNC */
|
||||
#define MT_SWDEF_MODE 0x9143c
|
||||
#define MT_FW_ASSERT_CNT 0x02208274
|
||||
#define MT_FW_DUMP_STATE 0x02209e90
|
||||
|
||||
#define MT_SWDEF_BASE 0x00401400
|
||||
|
||||
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
|
||||
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
|
||||
#define MT_SWDEF_NORMAL_MODE 0
|
||||
|
||||
#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
|
||||
#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
|
||||
#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
|
||||
#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04c)
|
||||
#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
|
||||
#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
|
||||
#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
|
||||
#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05c)
|
||||
#define MT_SWDEF_LAMC_WISR6_BN2_STATS MT_SWDEF(0x060)
|
||||
#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064)
|
||||
#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068)
|
||||
#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06c)
|
||||
|
||||
/* LED */
|
||||
#define MT_LED_TOP_BASE 0x18013000
|
||||
#define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
|
||||
|
@ -486,6 +518,13 @@ enum base_rev {
|
|||
|
||||
#define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4))
|
||||
|
||||
/* CONN DBG */
|
||||
#define MT_CONN_DBG_CTL_BASE 0x18023000
|
||||
#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs))
|
||||
#define MT_CONN_DBG_CTL_OUT_SEL MT_CONN_DBG_CTL(0x604)
|
||||
#define MT_CONN_DBG_CTL_PC_LOG_SEL MT_CONN_DBG_CTL(0x60c)
|
||||
#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x610)
|
||||
|
||||
#define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */
|
||||
#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */
|
||||
#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8)
|
||||
|
@ -506,7 +545,7 @@ enum base_rev {
|
|||
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
|
||||
|
||||
#define MT_HW_REV 0x70010204
|
||||
#define MT_WF_SUBSYS_RST 0x70002600
|
||||
#define MT_WF_SUBSYS_RST 0x70028600
|
||||
|
||||
/* PCIE MAC */
|
||||
#define MT_PCIE_MAC_BASE 0x74030000
|
||||
|
@ -539,4 +578,12 @@ enum base_rev {
|
|||
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
|
||||
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
|
||||
|
||||
/* CONN MCU EXCP CON */
|
||||
#define MT_MCU_WM_EXCP_BASE 0x89050000
|
||||
#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs))
|
||||
#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100)
|
||||
#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104)
|
||||
#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200)
|
||||
#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,7 +77,9 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
|
|||
}
|
||||
|
||||
hw = mt76_tx_status_get_hw(dev, skb);
|
||||
spin_lock_bh(&dev->rx_lock);
|
||||
ieee80211_tx_status_ext(hw, &status);
|
||||
spin_unlock_bh(&dev->rx_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -263,7 +265,9 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
|
|||
if (cb->pktid < MT_PACKET_ID_FIRST) {
|
||||
hw = mt76_tx_status_get_hw(dev, skb);
|
||||
status.sta = wcid_to_sta(wcid);
|
||||
spin_lock_bh(&dev->rx_lock);
|
||||
ieee80211_tx_status_ext(hw, &status);
|
||||
spin_unlock_bh(&dev->rx_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче