mt76 patches for 6.7

* mt7603/mt7628 stability improvements
 * fixes
 * new driver for mt7925
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCZRhnXgAKCRDXfRQdAqdu
 9dBVAJsFnKibKH8DJDx6nfwPGS4dgyjcMACgyOXvMzWlvZudcviTPThTDzj5epY=
 =K6mR
 -----END PGP SIGNATURE-----

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

mt76 patches for 6.7

* mt7603/mt7628 stability improvements
* fixes
* new driver for mt7925
This commit is contained in:
Kalle Valo 2023-10-09 09:35:41 +03:00
commit 089482a06b
72 changed files with 10202 additions and 564 deletions

View File

@ -44,3 +44,4 @@ source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7996/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig"

View File

@ -44,3 +44,4 @@ obj-$(CONFIG_MT7615_COMMON) += mt7615/
obj-$(CONFIG_MT7915E) += mt7915/
obj-$(CONFIG_MT7921_COMMON) += mt7921/
obj-$(CONFIG_MT7996E) += mt7996/
obj-$(CONFIG_MT7925_COMMON) += mt7925/

View File

@ -109,8 +109,6 @@ mt76_register_debugfs_fops(struct mt76_phy *phy,
struct dentry *dir;
dir = debugfs_create_dir("mt76", phy->hw->wiphy->debugfsdir);
if (!dir)
return NULL;
debugfs_create_u8("led_pin", 0600, dir, &phy->leds.pin);
debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg);

View File

@ -53,6 +53,11 @@ mt76_alloc_txwi(struct mt76_dev *dev)
addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size,
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
kfree(txwi);
return NULL;
}
t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
t->dma_addr = addr;
@ -330,9 +335,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
if (e->txwi == DMA_DUMMY_DATA)
e->txwi = NULL;
if (e->skb == DMA_DUMMY_DATA)
e->skb = NULL;
*prev_e = *e;
memset(e, 0, sizeof(*e));
}
@ -737,16 +739,18 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
if (!q->ndesc)
return;
spin_lock_bh(&q->lock);
do {
spin_lock_bh(&q->lock);
buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
spin_unlock_bh(&q->lock);
if (!buf)
break;
mt76_put_page_pool_buf(buf, false);
} while (1);
spin_lock_bh(&q->lock);
if (q->rx_head) {
dev_kfree_skb(q->rx_head);
q->rx_head = NULL;

View File

@ -188,7 +188,7 @@ static bool mt76_string_prop_find(struct property *prop, const char *str)
return false;
}
static struct device_node *
struct device_node *
mt76_find_power_limits_node(struct mt76_dev *dev)
{
struct device_node *np = dev->dev->of_node;
@ -227,6 +227,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
of_node_put(np);
return fallback;
}
EXPORT_SYMBOL_GPL(mt76_find_power_limits_node);
static const __be32 *
mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min)
@ -241,7 +242,7 @@ mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min)
return prop->value;
}
static struct device_node *
struct device_node *
mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
{
struct device_node *cur;
@ -265,6 +266,8 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
return NULL;
}
EXPORT_SYMBOL_GPL(mt76_find_channel_node);
static s8
mt76_get_txs_delta(struct device_node *np, u8 nss)

View File

@ -415,6 +415,9 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
struct mt76_dev *dev = phy->dev;
struct wiphy *wiphy = hw->wiphy;
INIT_LIST_HEAD(&phy->tx_list);
spin_lock_init(&phy->tx_lock);
SET_IEEE80211_DEV(hw, dev->dev);
SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
@ -452,7 +455,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) &&
hw->max_tx_fragments > 1) {
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
}
@ -688,6 +692,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
int ret;
dev_set_drvdata(dev->dev, dev);
mt76_wcid_init(&dev->global_wcid);
ret = mt76_phy_init(phy, hw);
if (ret)
return ret;
@ -743,6 +748,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
if (IS_ENABLED(CONFIG_MT76_LEDS))
mt76_led_cleanup(&dev->phy);
mt76_tx_status_check(dev, true);
mt76_wcid_cleanup(dev, &dev->global_wcid);
ieee80211_unregister_hw(hw);
}
EXPORT_SYMBOL_GPL(mt76_unregister_device);
@ -1411,7 +1417,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
wcid->phy_idx = phy->band_idx;
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
mt76_packet_id_init(wcid);
mt76_wcid_init(wcid);
out:
mutex_unlock(&dev->mutex);
@ -1430,7 +1436,7 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
if (dev->drv->sta_remove)
dev->drv->sta_remove(dev, vif, sta);
mt76_packet_id_flush(dev, wcid);
mt76_wcid_cleanup(dev, wcid);
mt76_wcid_mask_clear(dev->wcid_mask, idx);
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
@ -1486,6 +1492,47 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
void mt76_wcid_init(struct mt76_wcid *wcid)
{
INIT_LIST_HEAD(&wcid->tx_list);
skb_queue_head_init(&wcid->tx_pending);
INIT_LIST_HEAD(&wcid->list);
idr_init(&wcid->pktid);
}
EXPORT_SYMBOL_GPL(mt76_wcid_init);
void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
{
struct mt76_phy *phy = dev->phys[wcid->phy_idx];
struct ieee80211_hw *hw;
struct sk_buff_head list;
struct sk_buff *skb;
mt76_tx_status_lock(dev, &list);
mt76_tx_status_skb_get(dev, wcid, -1, &list);
mt76_tx_status_unlock(dev, &list);
idr_destroy(&wcid->pktid);
spin_lock_bh(&phy->tx_lock);
if (!list_empty(&wcid->tx_list))
list_del_init(&wcid->tx_list);
spin_lock(&wcid->tx_pending.lock);
skb_queue_splice_tail_init(&wcid->tx_pending, &list);
spin_unlock(&wcid->tx_pending.lock);
spin_unlock_bh(&phy->tx_lock);
while ((skb = __skb_dequeue(&list)) != NULL) {
hw = mt76_tx_status_get_hw(dev, skb);
ieee80211_free_txskb(hw, skb);
}
}
EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm)
{
@ -1697,11 +1744,16 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
}
EXPORT_SYMBOL_GPL(mt76_init_queue);
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx)
u16 mt76_calculate_default_rate(struct mt76_phy *phy,
struct ieee80211_vif *vif, int rateidx)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = mvif->ctx ?
&mvif->ctx->def :
&phy->chandef;
int offset = 0;
if (phy->chandef.chan->band != NL80211_BAND_2GHZ)
if (chandef->chan->band != NL80211_BAND_2GHZ)
offset = 4;
/* pick the lowest rate for hidden nodes */

View File

@ -334,6 +334,9 @@ struct mt76_wcid {
u32 tx_info;
bool sw_iv;
struct list_head tx_list;
struct sk_buff_head tx_pending;
struct list_head list;
struct idr pktid;
@ -376,7 +379,7 @@ struct mt76_rx_tid {
u8 started:1, stopped:1, timer_pending:1;
struct sk_buff *reorder_buf[];
struct sk_buff *reorder_buf[] __counted_by(size);
};
#define MT_TX_CB_DMA_DONE BIT(0)
@ -709,6 +712,7 @@ struct mt76_vif {
u8 basic_rates_idx;
u8 mcast_rates_idx;
u8 beacon_rates_idx;
struct ieee80211_chanctx_conf *ctx;
};
struct mt76_phy {
@ -719,6 +723,8 @@ struct mt76_phy {
unsigned long state;
u8 band_idx;
spinlock_t tx_lock;
struct list_head tx_list;
struct mt76_queue *q_tx[__MT_TXQ_MAX];
struct cfg80211_chan_def chandef;
@ -967,6 +973,7 @@ struct mt76_power_limits {
s8 ofdm[8];
s8 mcs[4][10];
s8 ru[7][12];
s8 eht[16][16];
};
struct mt76_ethtool_worker_info {
@ -1100,7 +1107,8 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
int ring_base, u32 flags);
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
u16 mt76_calculate_default_rate(struct mt76_phy *phy,
struct ieee80211_vif *vif, int rateidx);
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
int n_desc, int ring_base, u32 flags)
{
@ -1529,6 +1537,11 @@ mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd,
void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);
struct device_node *
mt76_find_power_limits_node(struct mt76_dev *dev);
struct device_node *
mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan);
s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
struct ieee80211_channel *chan,
struct mt76_power_limits *dest,
@ -1598,22 +1611,7 @@ mt76_token_put(struct mt76_dev *dev, int token)
return txwi;
}
static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
{
INIT_LIST_HEAD(&wcid->list);
idr_init(&wcid->pktid);
}
static inline void
mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
{
struct sk_buff_head list;
mt76_tx_status_lock(dev, &list);
mt76_tx_status_skb_get(dev, wcid, -1, &list);
mt76_tx_status_unlock(dev, &list);
idr_destroy(&wcid->pktid);
}
void mt76_wcid_init(struct mt76_wcid *wcid);
void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid);
#endif

View File

@ -9,6 +9,23 @@ struct beacon_bc_data {
int count[MT7603_MAX_INTERFACES];
};
static void
mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev)
{
if (dev->beacon_check % 5 != 4)
return;
mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
}
static void
mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
@ -16,6 +33,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
struct mt76_dev *mdev = &dev->mt76;
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
struct sk_buff *skb = NULL;
u32 om_idx = mvif->idx;
u32 val;
if (!(mdev->beacon_mask & BIT(mvif->idx)))
return;
@ -24,20 +43,33 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!skb)
return;
if (om_idx)
om_idx |= 0x10;
val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE |
FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) |
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8);
spin_lock_bh(&dev->ps_lock);
mt76_wr(dev, MT_DMA_FQCR0, val |
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN));
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
goto out;
}
mt76_wr(dev, MT_DMA_FQCR0, val |
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC));
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
goto out;
}
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
spin_lock_bh(&dev->ps_lock);
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) |
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
out:
spin_unlock_bh(&dev->ps_lock);
}
@ -81,6 +113,18 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
data.dev = dev;
__skb_queue_head_init(&data.q);
/* Flush all previous CAB queue packets and beacons */
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0)
dev->beacon_check++;
else
dev->beacon_check = 0;
mt7603_mac_stuck_beacon_recovery(dev);
q = dev->mphy.q_tx[MT_TXQ_BEACON];
spin_lock(&q->lock);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
@ -89,14 +133,9 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
mt76_queue_kick(dev, q);
spin_unlock(&q->lock);
/* Flush all previous CAB queue packets */
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
mt76_csa_check(mdev);
if (mdev->csa_complete)
goto out;
return;
q = dev->mphy.q_tx[MT_TXQ_CAB];
do {
@ -108,7 +147,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
skb_queue_len(&data.q) < 8);
if (skb_queue_empty(&data.q))
goto out;
return;
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
if (!data.tail[i])
@ -136,11 +175,6 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
MT_WF_ARB_CAB_START_BSSn(0) |
(MT_WF_ARB_CAB_START_BSS0n(1) *
((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
out:
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask))
dev->beacon_check++;
}
void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)

View File

@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
}
if (intr & MT_INT_RX_DONE(0)) {
dev->rx_pse_check = 0;
mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
dev->rx_pse_check = 0;
mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
napi_schedule(&dev->mt76.napi[1]);
}

View File

@ -184,6 +184,13 @@ mt7603_mac_init(struct mt7603_dev *dev)
mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE);
if (is_mt7628(dev)) {
mt76_set(dev, MT_TMAC_TCR,
MT_TMAC_TCR_TXOP_BURST_STOP | BIT(1) | BIT(0));
mt76_set(dev, MT_TXREQ, BIT(27));
mt76_set(dev, MT_AGG_TMP, GENMASK(4, 2));
}
mt7603_set_tmac_template(dev);
/* Enable RX group to HIF */
@ -517,6 +524,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
hw->max_rates = 3;
hw->max_report_rates = 7;
hw->max_rate_tries = 11;
hw->max_tx_fragments = 1;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;

View File

@ -1441,15 +1441,6 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
mt7603_beacon_set_timer(dev, -1, 0);
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY ||
dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK ||
dev->cur_reset_cause == RESET_CAUSE_TX_HANG)
mt7603_pse_reset(dev);
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED])
goto skip_dma_reset;
mt7603_mac_stop(dev);
mt76_clear(dev, MT_WPDMA_GLO_CFG,
@ -1459,28 +1450,32 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
mt7603_irq_disable(dev, mask);
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
mt7603_pse_client_reset(dev);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
mt7603_dma_sched_reset(dev);
mt76_tx_status_check(&dev->mt76, true);
mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
}
mt76_tx_status_check(&dev->mt76, true);
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY)
mt7603_pse_reset(dev);
mt7603_dma_sched_reset(dev);
if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) {
mt7603_mac_dma_start(dev);
mt7603_mac_dma_start(dev);
mt7603_irq_enable(dev, mask);
mt7603_irq_enable(dev, mask);
clear_bit(MT76_RESET, &dev->mphy.state);
}
skip_dma_reset:
clear_bit(MT76_RESET, &dev->mphy.state);
mutex_unlock(&dev->mt76.mutex);
mt76_worker_enable(&dev->mt76.tx_worker);
@ -1570,20 +1565,29 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
{
u32 addr, val;
if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
return true;
if (mt7603_rx_fifo_busy(dev))
return false;
goto out;
addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
mt76_wr(dev, addr, 3);
val = mt76_rr(dev, addr) >> 16;
if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
return true;
if (!(val & BIT(0)))
return false;
return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
if (is_mt7628(dev))
val &= 0xa000;
else
val &= 0x8000;
if (!val)
return false;
out:
if (mt76_rr(dev, MT_INT_SOURCE_CSR) &
(MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1)))
return false;
return true;
}
static bool

View File

@ -70,7 +70,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.vif = mvif;
mt76_packet_id_init(&mvif->sta.wcid);
mt76_wcid_init(&mvif->sta.wcid);
eth_broadcast_addr(bc_addr);
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
@ -110,7 +110,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
mutex_unlock(&dev->mt76.mutex);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
}
void mt7603_init_edcca(struct mt7603_dev *dev)

View File

@ -469,6 +469,11 @@ enum {
#define MT_WF_SEC_BASE 0x21a00
#define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs))
#define MT_WF_CFG_OFF_BASE 0x21e00
#define MT_WF_CFG_OFF(ofs) (MT_WF_CFG_OFF_BASE + (ofs))
#define MT_WF_CFG_OFF_WOCCR MT_WF_CFG_OFF(0x004)
#define MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS BIT(4)
#define MT_SEC_SCR MT_WF_SEC(0x004)
#define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0)

View File

@ -58,10 +58,7 @@ int mt7615_thermal_init(struct mt7615_dev *dev)
wiphy_name(wiphy));
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev,
mt7615_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
return 0;
return PTR_ERR_OR_ZERO(hwmon);
}
EXPORT_SYMBOL_GPL(mt7615_thermal_init);

View File

@ -226,7 +226,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->sta.wcid);
mt76_wcid_init(&mvif->sta.wcid);
mt7615_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -279,7 +279,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
}
int mt7615_set_channel(struct mt7615_phy *phy)

View File

@ -2147,7 +2147,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
};
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
req.switch_reason = CH_SWITCH_NORMAL;
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;

View File

@ -106,7 +106,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
else
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
tx_info->skb = NULL;
return 0;
}

View File

@ -172,6 +172,11 @@ struct mt76_connac_tx_free {
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
static inline bool is_mt7925(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7925;
}
static inline bool is_mt7922(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7922;
@ -245,6 +250,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
switch (mt76_chip(dev)) {
case 0x7961:
case 0x7922:
case 0x7925:
case 0x7663:
case 0x7622:
return false;

View File

@ -257,6 +257,8 @@ enum tx_mgnt_type {
#define MT_TXD7_UDP_TCP_SUM BIT(15)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TXD9_WLAN_IDX GENMASK(23, 8)
#define MT_TX_RATE_STBC BIT(14)
#define MT_TX_RATE_NSS GENMASK(13, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
@ -269,7 +271,7 @@ enum tx_mgnt_type {
#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
#define MT_TXFREE1_VER GENMASK(18, 16)
#define MT_TXFREE1_VER GENMASK(19, 16)
#define MT_TXFREE_INFO_PAIR BIT(31)
#define MT_TXFREE_INFO_HEADER BIT(30)
@ -315,6 +317,7 @@ enum tx_mgnt_type {
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
/* MPDU based TXS */
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
#define MT_TXS5_F0_QOS BIT(30)
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
@ -336,4 +339,17 @@ enum tx_mgnt_type {
#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
/* PPDU based TXS */
#define MT_TXS5_MPDU_TX_CNT GENMASK(30, 20)
#define MT_TXS5_MPDU_TX_BYTE_SCALE BIT(15)
#define MT_TXS5_MPDU_TX_BYTE GENMASK(14, 0)
#define MT_TXS6_MPDU_FAIL_CNT GENMASK(30, 20)
#define MT_TXS6_MPDU_FAIL_BYTE_SCALE BIT(15)
#define MT_TXS6_MPDU_FAIL_BYTE GENMASK(14, 0)
#define MT_TXS7_MPDU_RETRY_CNT GENMASK(30, 20)
#define MT_TXS7_MPDU_RETRY_BYTE_SCALE BIT(15)
#define MT_TXS7_MPDU_RETRY_BYTE GENMASK(14, 0)
#endif /* __MT76_CONNAC3_MAC_H */

View File

@ -151,23 +151,6 @@ void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
return;
}
/* error path */
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_connac_txp_common *txp;
struct mt76_txwi_cache *t;
u16 token;
txp = mt76_connac_txwi_to_txp(mdev, e->txwi);
if (is_mt76_fw_txp(mdev))
token = le16_to_cpu(txp->fw.token);
else
token = le16_to_cpu(txp->hw.msdu_id[0]) &
~MT_MSDU_ID_VALID;
t = mt76_token_put(mdev, token);
e->skb = t ? t->skb : NULL;
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
@ -187,7 +170,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev,
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
if (is_mt7663(dev) || is_mt7921(dev))
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_AMSDU_LAST |
@ -231,7 +214,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
u32 last_mask;
int i;
if (is_mt7663(dev) || is_mt7921(dev))
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_MSDU_LAST;
@ -310,7 +293,10 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
struct ieee80211_vif *vif,
bool beacon, bool mcast)
{
u8 nss = 0, mode = 0, band = mphy->chandef.chan->band;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = mvif->ctx ?
&mvif->ctx->def : &mphy->chandef;
u8 nss = 0, mode = 0, band = chandef->chan->band;
int rateidx = 0, mcast_rate;
if (!vif)
@ -343,7 +329,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
legacy:
rateidx = mt76_calculate_default_rate(mphy, rateidx);
rateidx = mt76_calculate_default_rate(mphy, vif, rateidx);
mode = rateidx >> 8;
rateidx &= GENMASK(7, 0);
out:

View File

@ -66,6 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
(is_mt7921(dev) && addr == 0x900000) ||
(is_mt7925(dev) && addr == 0x900000) ||
(is_mt7996(dev) && addr == 0x900000))
cmd = MCU_CMD(PATCH_START_REQ);
else
@ -745,7 +746,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
he->pkt_ext = 2;
}
static void
void
mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)
{
struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
@ -777,20 +778,23 @@ mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)
he->pkt_ext = IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US;
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2);
static u8
u8
mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
enum nl80211_band band, struct ieee80211_sta *sta)
{
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
const struct ieee80211_sta_he_cap *he_cap;
const struct ieee80211_sta_eht_cap *eht_cap;
u8 mode = 0;
if (sta) {
ht_cap = &sta->deflink.ht_cap;
vht_cap = &sta->deflink.vht_cap;
he_cap = &sta->deflink.he_cap;
eht_cap = &sta->deflink.eht_cap;
} else {
struct ieee80211_supported_band *sband;
@ -798,6 +802,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
ht_cap = &sband->ht_cap;
vht_cap = &sband->vht_cap;
he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);
eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);
}
if (band == NL80211_BAND_2GHZ) {
@ -808,6 +813,9 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (he_cap && he_cap->has_he)
mode |= PHY_TYPE_BIT_HE;
if (eht_cap && eht_cap->has_eht)
mode |= PHY_TYPE_BIT_BE;
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
mode |= PHY_TYPE_BIT_OFDM;
@ -819,17 +827,23 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (he_cap && he_cap->has_he)
mode |= PHY_TYPE_BIT_HE;
if (eht_cap && eht_cap->has_eht)
mode |= PHY_TYPE_BIT_BE;
}
return mode;
}
EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_v2);
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif,
u8 rcpi, u8 sta_state)
{
struct cfg80211_chan_def *chandef = &mphy->chandef;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = mvif->ctx ?
&mvif->ctx->def : &mphy->chandef;
enum nl80211_band band = chandef->chan->band;
struct mt76_dev *dev = mphy->dev;
struct sta_rec_ra_info *ra_info;
@ -1369,7 +1383,10 @@ EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext);
const struct ieee80211_sta_he_cap *
mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)
{
enum nl80211_band band = phy->chandef.chan->band;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = mvif->ctx ?
&mvif->ctx->def : &phy->chandef;
enum nl80211_band band = chandef->chan->band;
struct ieee80211_supported_band *sband;
sband = phy->hw->wiphy->bands[band];
@ -1924,126 +1941,6 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
static void mt76_connac_mcu_parse_tx_resource(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt76_sdio *sdio = &dev->sdio;
struct mt76_connac_tx_resource {
__le32 version;
__le32 pse_data_quota;
__le32 pse_mcu_quota;
__le32 ple_data_quota;
__le32 ple_mcu_quota;
__le16 pse_page_size;
__le16 ple_page_size;
u8 pp_padding;
u8 pad[3];
} __packed * tx_res;
tx_res = (struct mt76_connac_tx_resource *)skb->data;
sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);
sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota);
sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);
sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);
sdio->sched.deficit = tx_res->pp_padding;
}
static void mt76_connac_mcu_parse_phy_cap(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt76_connac_phy_cap {
u8 ht;
u8 vht;
u8 _5g;
u8 max_bw;
u8 nss;
u8 dbdc;
u8 tx_ldpc;
u8 rx_ldpc;
u8 tx_stbc;
u8 rx_stbc;
u8 hw_path;
u8 he;
} __packed * cap;
enum {
WF0_24G,
WF0_5G
};
cap = (struct mt76_connac_phy_cap *)skb->data;
dev->phy.antenna_mask = BIT(cap->nss) - 1;
dev->phy.chainmask = dev->phy.antenna_mask;
dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
}
int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
{
struct mt76_connac_cap_hdr {
__le16 n_element;
u8 rsv[2];
} __packed * hdr;
struct sk_buff *skb;
int ret, i;
ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),
NULL, 0, true, &skb);
if (ret)
return ret;
hdr = (struct mt76_connac_cap_hdr *)skb->data;
if (skb->len < sizeof(*hdr)) {
ret = -EINVAL;
goto out;
}
skb_pull(skb, sizeof(*hdr));
for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
struct tlv_hdr {
__le32 type;
__le32 len;
} __packed * tlv = (struct tlv_hdr *)skb->data;
int len;
if (skb->len < sizeof(*tlv))
break;
skb_pull(skb, sizeof(*tlv));
len = le32_to_cpu(tlv->len);
if (skb->len < len)
break;
switch (le32_to_cpu(tlv->type)) {
case MT_NIC_CAP_6G:
phy->cap.has_6ghz = skb->data[0];
break;
case MT_NIC_CAP_MAC_ADDR:
memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);
break;
case MT_NIC_CAP_PHY:
mt76_connac_mcu_parse_phy_cap(phy->dev, skb);
break;
case MT_NIC_CAP_TX_RESOURCE:
if (mt76_is_sdio(phy->dev))
mt76_connac_mcu_parse_tx_resource(phy->dev,
skb);
break;
default:
break;
}
skb_pull(skb, len);
}
out:
dev_kfree_skb(skb);
return ret;
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_get_nic_capability);
static void
mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
struct mt76_power_limits *limits,
@ -2087,9 +1984,9 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
}
}
static s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
struct ieee80211_channel *chan,
s8 target_power)
s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
struct ieee80211_channel *chan,
s8 target_power)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_supported_band *sband;
@ -2126,6 +2023,7 @@ static s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
return target_power;
}
EXPORT_SYMBOL_GPL(mt76_connac_get_ch_power);
static int
mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
@ -2144,7 +2042,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
112, 114, 116, 118, 120, 122, 124,
126, 128, 132, 134, 136, 138, 140,
142, 144, 149, 151, 153, 155, 157,
159, 161, 165
159, 161, 165, 169, 173, 177
};
static const u8 chan_list_6ghz[] = {
1, 3, 5, 7, 9, 11, 13,
@ -2164,11 +2062,15 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
209, 211, 213, 215, 217, 219, 221,
225, 227, 229, 233
};
int i, n_chan, batch_size, idx = 0, tx_power, last_ch;
int i, n_chan, batch_size, idx = 0, tx_power, last_ch, err = 0;
struct mt76_connac_sku_tlv sku_tlbv;
struct mt76_power_limits limits;
struct mt76_power_limits *limits;
const u8 *ch_list;
limits = devm_kmalloc(dev->dev, sizeof(*limits), GFP_KERNEL);
if (!limits)
return -ENOMEM;
sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
tx_power = 2 * phy->hw->conf.power_level;
if (!tx_power)
@ -2195,14 +2097,16 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
for (i = 0; i < batch_size; i++) {
struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {};
int j, err, msg_len, num_ch;
int j, msg_len, num_ch;
struct sk_buff *skb;
num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len;
msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
if (!skb)
return -ENOMEM;
if (!skb) {
err = -ENOMEM;
goto out;
}
skb_reserve(skb, sizeof(tx_power_tlv));
@ -2233,14 +2137,14 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
tx_power);
sar_power = mt76_get_sar_power(phy, &chan, reg_power);
mt76_get_rate_power_limits(phy, &chan, &limits,
mt76_get_rate_power_limits(phy, &chan, limits,
sar_power);
tx_power_tlv.last_msg = ch_list[idx] == last_ch;
sku_tlbv.channel = ch_list[idx];
mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
&limits, band);
limits, band);
skb_put_data(skb, &sku_tlbv, sku_len);
}
__skb_push(skb, sizeof(tx_power_tlv));
@ -2250,10 +2154,12 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
MCU_CE_CMD(SET_RATE_TX_POWER),
false);
if (err < 0)
return err;
goto out;
}
return 0;
out:
devm_kfree(dev->dev, limits);
return err;
}
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
@ -2457,7 +2363,7 @@ mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif,
sizeof(req), true);
}
static int
int
mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
bool suspend)
{
@ -2482,8 +2388,9 @@ mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req,
sizeof(req), true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_gtk_rekey);
static int
int
mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
struct ieee80211_vif *vif,
bool enable, u8 mdtim,
@ -2512,6 +2419,7 @@ mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,
sizeof(req), true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_mode);
static int
mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
@ -2547,7 +2455,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true);
}
static int
int
mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
bool suspend, struct cfg80211_wowlan *wowlan)
{
@ -2599,6 +2507,7 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,
sizeof(req), true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_wow_ctrl);
int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend)
{
@ -3064,7 +2973,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
{
u32 mode = DL_MODE_NEED_RSP;
if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
return mode;
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {

View File

@ -191,6 +191,7 @@ struct mt76_connac2_fw_region {
struct tlv {
__le16 tag;
__le16 len;
u8 data[];
} __packed;
struct bss_info_omac {
@ -795,6 +796,7 @@ enum {
STA_REC_PHY = 0x15,
STA_REC_HE_6G = 0x17,
STA_REC_HE_V2 = 0x19,
STA_REC_MLD = 0x20,
STA_REC_EHT = 0x22,
STA_REC_HDRT = 0x28,
STA_REC_HDR_TRANS = 0x2B,
@ -919,6 +921,7 @@ enum {
PHY_TYPE_HT_INDEX,
PHY_TYPE_VHT_INDEX,
PHY_TYPE_HE_INDEX,
PHY_TYPE_BE_INDEX,
PHY_TYPE_INDEX_NUM
};
@ -928,6 +931,7 @@ enum {
#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX)
#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX)
#define PHY_TYPE_BIT_HE BIT(PHY_TYPE_HE_INDEX)
#define PHY_TYPE_BIT_BE BIT(PHY_TYPE_BE_INDEX)
#define MT_WTBL_RATE_TX_MODE GENMASK(9, 6)
#define MT_WTBL_RATE_MCS GENMASK(5, 0)
@ -1009,8 +1013,17 @@ enum {
enum {
MCU_UNI_EVENT_RESULT = 0x01,
MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
MCU_UNI_EVENT_ACCESS_REG = 0x6,
MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
MCU_UNI_EVENT_COREDUMP = 0x0a,
MCU_UNI_EVENT_BSS_BEACON_LOSS = 0x0c,
MCU_UNI_EVENT_SCAN_DONE = 0x0e,
MCU_UNI_EVENT_RDD_REPORT = 0x11,
MCU_UNI_EVENT_ROC = 0x27,
MCU_UNI_EVENT_TX_DONE = 0x2d,
MCU_UNI_EVENT_NIC_CAPAB = 0x43,
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
};
#define MCU_UNI_CMD_EVENT BIT(1)
@ -1209,12 +1222,17 @@ enum {
MCU_UNI_CMD_RX_HDR_TRANS = 0x12,
MCU_UNI_CMD_SER = 0x13,
MCU_UNI_CMD_TWT = 0x14,
MCU_UNI_CMD_SET_DOMAIN_INFO = 0x15,
MCU_UNI_CMD_SCAN_REQ = 0x16,
MCU_UNI_CMD_RDD_CTRL = 0x19,
MCU_UNI_CMD_GET_MIB_INFO = 0x22,
MCU_UNI_CMD_GET_STAT_INFO = 0x23,
MCU_UNI_CMD_SNIFFER = 0x24,
MCU_UNI_CMD_SR = 0x25,
MCU_UNI_CMD_ROC = 0x27,
MCU_UNI_CMD_SET_DBDC_PARMS = 0x28,
MCU_UNI_CMD_TXPOWER = 0x2b,
MCU_UNI_CMD_SET_POWER_LIMIT = 0x2c,
MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
MCU_UNI_CMD_RA = 0x2f,
MCU_UNI_CMD_MURU = 0x31,
@ -1224,6 +1242,8 @@ enum {
MCU_UNI_CMD_VOW = 0x37,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
};
@ -1279,6 +1299,7 @@ enum {
UNI_BSS_INFO_RLM = 2,
UNI_BSS_INFO_BSS_COLOR = 4,
UNI_BSS_INFO_HE_BASIC = 5,
UNI_BSS_INFO_11V_MBSSID = 6,
UNI_BSS_INFO_BCN_CONTENT = 7,
UNI_BSS_INFO_BCN_CSA = 8,
UNI_BSS_INFO_BCN_BCC = 9,
@ -1293,6 +1314,7 @@ enum {
UNI_BSS_INFO_IFS_TIME = 23,
UNI_BSS_INFO_OFFLOAD = 25,
UNI_BSS_INFO_MLD = 26,
UNI_BSS_INFO_PM_DISABLE = 27,
};
enum {
@ -1302,6 +1324,17 @@ enum {
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};
enum UNI_ALL_STA_INFO_TAG {
UNI_ALL_STA_TX_RATE,
UNI_ALL_STA_TX_STAT,
UNI_ALL_STA_TXRX_ADM_STAT,
UNI_ALL_STA_TXRX_AIR_TIME,
UNI_ALL_STA_DATA_TX_RETRY_COUNT,
UNI_ALL_STA_GI_MODE,
UNI_ALL_STA_TXRX_MSDU_COUNT,
UNI_ALL_STA_MAX_NUM
};
enum {
MT_NIC_CAP_TX_RESOURCE,
MT_NIC_CAP_TX_EFUSE_ADDR,
@ -1322,6 +1355,7 @@ enum {
MT_NIC_CAP_ANTSWP = 0x16,
MT_NIC_CAP_WFDMA_REALLOC,
MT_NIC_CAP_6G,
MT_NIC_CAP_CHIP_CAP = 0x20,
};
#define UNI_WOW_DETECT_TYPE_MAGIC BIT(0)
@ -1549,6 +1583,15 @@ struct bss_info_uni_he {
u8 rsv[2];
} __packed;
struct bss_info_uni_mbssid {
__le16 tag;
__le16 len;
u8 max_indicator;
u8 mbss_idx;
u8 tx_bss_omac_idx;
u8 rsv;
} __packed;
struct mt76_connac_gtk_rekey_tlv {
__le16 tag;
__le16 len;
@ -1739,7 +1782,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa)
ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;
if (is_mt7921(dev))
if (is_mt7921(dev) || is_mt7925(dev))
ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
DL_CONFIG_ENCRY_MODE_SEL : 0;
ret |= FIELD_PREP(DL_MODE_KEY_IDX,
@ -1807,6 +1850,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
struct ieee80211_vif *vif,
struct mt76_wcid *wcid, int cmd);
void mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta);
u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
enum nl80211_band band, struct ieee80211_sta *sta);
int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@ -1851,7 +1897,6 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy);
int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_scan_request *scan_req);
@ -1866,9 +1911,17 @@ int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy,
int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,
struct mt76_vif *vif,
struct ieee80211_bss_conf *info);
int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
bool suspend);
int mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
bool suspend, struct cfg80211_wowlan *wowlan);
int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *key);
int mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
struct ieee80211_vif *vif,
bool enable, u8 mdtim,
bool wow_suspend);
int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
@ -1879,6 +1932,9 @@ int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
struct mt76_connac_coredump *coredump);
s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
struct ieee80211_channel *chan,
s8 target_power);
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy);
int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);

View File

@ -136,7 +136,8 @@ EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer);
void
mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt76x02_dev *dev = (struct mt76x02_dev *)priv;
struct beacon_bc_data *data = priv;
struct mt76x02_dev *dev = data->dev;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
struct sk_buff *skb = NULL;
@ -147,7 +148,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!skb)
return;
mt76x02_mac_set_beacon(dev, skb);
__skb_queue_tail(&data->q, skb);
}
EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter);
@ -182,9 +183,6 @@ mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev,
{
int i, nframes;
data->dev = dev;
__skb_queue_head_init(&data->q);
do {
nframes = skb_queue_len(&data->q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),

View File

@ -16,13 +16,17 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet);
struct mt76_dev *mdev = &dev->mt76;
struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD];
struct beacon_bc_data data = {};
struct beacon_bc_data data = {
.dev = dev,
};
struct sk_buff *skb;
int i;
if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
return;
__skb_queue_head_init(&data.q);
mt76x02_resync_beacon_timer(dev);
/* Prevent corrupt transmissions during update */
@ -31,7 +35,10 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_update_beacon_iter, dev);
mt76x02_update_beacon_iter, &data);
while ((skb = __skb_dequeue(&data.q)) != NULL)
mt76x02_mac_set_beacon(dev, skb);
mt76_wr(dev, MT_BCN_BYPASS_MASK,
0xff00 | ~(0xff00 >> dev->beacon_data_count));

View File

@ -182,7 +182,9 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
{
struct mt76x02_dev *dev =
container_of(work, struct mt76x02_dev, pre_tbtt_work);
struct beacon_bc_data data = {};
struct beacon_bc_data data = {
.dev = dev,
};
struct sk_buff *skb;
int nbeacons;
@ -192,15 +194,20 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
return;
__skb_queue_head_init(&data.q);
mt76x02_resync_beacon_timer(dev);
/* Prevent corrupt transmissions during update */
mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff);
dev->beacon_data_count = 0;
ieee80211_iterate_active_interfaces(mt76_hw(dev),
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_update_beacon_iter, dev);
mt76x02_update_beacon_iter, &data);
while ((skb = __skb_dequeue(&data.q)) != NULL)
mt76x02_mac_set_beacon(dev, skb);
mt76_csa_check(&dev->mt76);

View File

@ -288,7 +288,7 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mvif->idx = idx;
mvif->group_wcid.idx = MT_VIF_WCID(idx);
mvif->group_wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->group_wcid);
mt76_wcid_init(&mvif->group_wcid);
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
@ -346,7 +346,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
mt76_wcid_cleanup(&dev->mt76, &mvif->group_wcid);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);

View File

@ -213,10 +213,7 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7915_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
return 0;
return PTR_ERR_OR_ZERO(hwmon);
}
static void mt7915_led_set_config(struct led_classdev *led_cdev,
@ -347,6 +344,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->netdev_features = NETIF_F_RXCSUM;
if (mtk_wed_device_active(&mdev->mmio.wed))
hw->netdev_features |= NETIF_F_HW_TC;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
@ -393,8 +393,12 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
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_4;
if (is_mt7915(&dev->mt76))
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_4;
else
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_2;
}
if (phy->mt76->cap.has_5ghz) {
@ -404,10 +408,11 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
phy->mt76->sband_5g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_4;
if (is_mt7915(&dev->mt76)) {
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_4;
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
@ -417,6 +422,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
IEEE80211_VHT_CAP_SHORT_GI_160 |
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
} else {
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_2;
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;

View File

@ -809,7 +809,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
else
txp->rept_wds_wcid = cpu_to_le16(0x3ff);
tx_info->skb = DMA_DUMMY_DATA;
tx_info->skb = NULL;
/* pass partial skb header to fw */
tx_info->buf[1].len = MT_CT_PARSE_LEN;

View File

@ -253,7 +253,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mvif->sta.wcid.phy_idx = ext_phy;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
mt76_wcid_init(&mvif->sta.wcid);
mt7915_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -314,7 +314,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
}
int mt7915_set_channel(struct mt7915_phy *phy)
@ -483,16 +483,22 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
bool band = phy->mt76->band_idx;
u32 rxfilter = phy->rxfilter;
if (!enabled)
phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
else
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
if (!enabled) {
rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
dev->monitor_mask &= ~BIT(band);
} else {
rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
dev->monitor_mask |= BIT(band);
}
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
enabled);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_MDP_DCR0_RX_HDR_TRANS_EN,
!dev->monitor_mask);
mt76_testmode_reset(phy->mt76, true);
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
}
mutex_unlock(&dev->mt76.mutex);
@ -527,6 +533,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
MT_WF_RFCR1_DROP_BA |
MT_WF_RFCR1_DROP_CFEND |
MT_WF_RFCR1_DROP_CFACK;
u32 rxfilter;
u32 flags = 0;
#define MT76_FILTER(_flag, _hw) do { \
@ -561,7 +568,12 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
MT_WF_RFCR_DROP_NDPA);
*total_flags = flags;
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
rxfilter = phy->rxfilter;
if (hw->conf.flags & IEEE80211_CONF_MONITOR)
rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
else
rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
if (*total_flags & FIF_CONTROL)
mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
@ -646,11 +658,13 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
mt7915_update_bss_color(hw, vif, &info->he_bss_color);
if (changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY))
BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY))
mt7915_mcu_add_inband_discov(dev, vif, changed);
if (set_bss_info == 0)
mt7915_mcu_add_bss_info(phy, vif, false);
if (set_sta == 0)
@ -1386,7 +1400,7 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
if (sset != ETH_SS_STATS)
return;
memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
data += sizeof(mt7915_gstrings_stats);
page_pool_ethtool_stats_get_strings(data);
}
@ -1639,6 +1653,20 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
return 0;
}
static int
mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
if (!mtk_wed_device_active(wed))
return -EOPNOTSUPP;
return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
}
#endif
const struct ieee80211_ops mt7915_ops = {
@ -1693,5 +1721,6 @@ const struct ieee80211_ops mt7915_ops = {
.set_radar_background = mt7915_set_radar_background,
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
.net_fill_forward_path = mt7915_net_fill_forward_path,
.net_setup_tc = mt7915_net_setup_tc,
#endif
};

View File

@ -225,8 +225,10 @@ int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
static void
mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
if (vif->bss_conf.csa_active)
ieee80211_csa_finish(vif);
if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
return;
ieee80211_csa_finish(vif);
}
static void
@ -326,7 +328,7 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
static void
mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
if (!vif->bss_conf.color_change_active)
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;
ieee80211_color_change_finish(vif);
@ -906,6 +908,8 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
muru->ofdma_ul.uo_ra =
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
muru->ofdma_ul.rx_ctrl_frame_to_mbss =
HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
}
static void
@ -1015,13 +1019,13 @@ 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;
int sts = hweight16(phy->mt76->chainmask);
if (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP)
return false;
if (!bfee && tx_ant < 2)
if (!bfee && sts < 2)
return false;
if (sta->deflink.he_cap.has_he) {
@ -1882,10 +1886,9 @@ 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_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct sk_buff *rskb, struct bss_info_bcn *bcn,
u32 changed)
int
mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
u32 changed)
{
#define OFFLOAD_TX_MODE_SU BIT(0)
#define OFFLOAD_TX_MODE_MU BIT(1)
@ -1895,14 +1898,27 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
enum nl80211_band band = chandef->chan->band;
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
struct bss_info_bcn *bcn;
struct bss_info_inband_discovery *discov;
struct ieee80211_tx_info *info;
struct sk_buff *skb = NULL;
struct tlv *tlv;
struct sk_buff *rskb, *skb = NULL;
struct tlv *tlv, *sub_tlv;
bool ext_phy = phy != &dev->phy;
u8 *buf, interval;
int len;
if (vif->bss_conf.nontransmitted)
return 0;
rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,
MT7915_MAX_BSS_OFFLOAD_SIZE);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
bcn = (struct bss_info_bcn *)tlv;
bcn->enable = true;
if (changed & BSS_CHANGED_FILS_DISCOVERY &&
vif->bss_conf.fils_discovery.max_interval) {
interval = vif->bss_conf.fils_discovery.max_interval;
@ -1913,27 +1929,29 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
}
if (!skb)
return;
if (!skb) {
dev_kfree_skb(rskb);
return -EINVAL;
}
info = IEEE80211_SKB_CB(skb);
info->control.vif = vif;
info->band = band;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) {
if (skb->len > MT7915_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return;
return -EINVAL;
}
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
len, &bcn->sub_ntlv, &bcn->len);
discov = (struct bss_info_inband_discovery *)tlv;
sub_tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
len, &bcn->sub_ntlv, &bcn->len);
discov = (struct bss_info_inband_discovery *)sub_tlv;
discov->tx_mode = OFFLOAD_TX_MODE_SU;
/* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
@ -1941,13 +1959,16 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
discov->enable = true;
buf = (u8 *)tlv + sizeof(*discov);
buf = (u8 *)sub_tlv + sizeof(*discov);
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
0, changed);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
dev_kfree_skb(skb);
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
}
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@ -1980,11 +2001,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out;
skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
if (!skb)
if (!skb) {
dev_kfree_skb(rskb);
return -EINVAL;
}
if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) {
if (skb->len > MT7915_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return -EINVAL;
}
@ -1997,11 +2021,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
dev_kfree_skb(skb);
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
changed & BSS_CHANGED_FILS_DISCOVERY)
mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
bcn, changed);
out:
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
@ -2725,10 +2744,10 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
if (mt76_connac_spe_idx(phy->mt76->antenna_mask))
req.tx_path_num = fls(phy->mt76->antenna_mask);
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
req.switch_reason = CH_SWITCH_NORMAL;
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
NL80211_IFTYPE_AP))

View File

@ -495,10 +495,14 @@ enum {
SER_RECOVER
};
#define MT7915_MAX_BEACON_SIZE 512
#define MT7915_MAX_INBAND_FRAME_SIZE 256
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
MT7915_MAX_INBAND_FRAME_SIZE + \
#define MT7915_MAX_BEACON_SIZE 1308
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_bcn) + \
sizeof(struct bss_info_bcn_cntdwn) + \
sizeof(struct bss_info_bcn_mbss) + \
MT_TXD_SIZE + \
sizeof(struct bss_info_bcn_cont))
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
MT7915_BEACON_UPDATE_SIZE)
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
@ -511,12 +515,6 @@ enum {
sizeof(struct bss_info_bmc_rate) +\
sizeof(struct bss_info_ext_bss))
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_bcn_cntdwn) + \
sizeof(struct bss_info_bcn_mbss) + \
sizeof(struct bss_info_bcn_cont) + \
sizeof(struct bss_info_inband_discovery))
static inline s8
mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
{

View File

@ -295,6 +295,8 @@ struct mt7915_dev {
bool muru_debug;
bool ibf;
u8 monitor_mask;
struct dentry *debugfs_dir;
struct rchan *relay_fwlog;
@ -447,6 +449,8 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
bool add);
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct cfg80211_he_bss_color *he_bss_color);
int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
u32 changed);
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int enable, u32 changed);
int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,

View File

@ -172,6 +172,7 @@ enum offs_rev {
#define MT_MDP_DCR0 MT_MDP(0x000)
#define MT_MDP_DCR0_DAMSDU_EN BIT(15)
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
#define MT_MDP_DCR1 MT_MDP(0x004)
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)

View File

@ -1219,10 +1219,7 @@ static int mt798x_wmac_init(struct mt7915_dev *dev)
return PTR_ERR(dev->sku);
dev->rstc = devm_reset_control_get(pdev, "consys");
if (IS_ERR(dev->rstc))
return PTR_ERR(dev->rstc);
return 0;
return PTR_ERR_OR_ZERO(dev->rstc);
}
static int mt798x_wmac_probe(struct platform_device *pdev)

View File

@ -55,10 +55,56 @@ static int mt7921_thermal_init(struct mt792x_phy *phy)
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7921_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
return PTR_ERR_OR_ZERO(hwmon);
}
return 0;
static void
mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
{
#define IS_UNII_INVALID(idx, sfreq, efreq) \
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
struct ieee80211_supported_band *sband;
struct mt76_dev *mdev = &dev->mt76;
struct device_node *np, *band_np;
struct ieee80211_channel *ch;
int i, cfreq;
np = mt76_find_power_limits_node(mdev);
sband = wiphy->bands[NL80211_BAND_5GHZ];
band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
cfreq = ch->center_freq;
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
ch->flags |= IEEE80211_CHAN_DISABLED;
continue;
}
/* UNII-4 */
if (IS_UNII_INVALID(0, 5850, 5925))
ch->flags |= IEEE80211_CHAN_DISABLED;
}
sband = wiphy->bands[NL80211_BAND_6GHZ];
band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
cfreq = ch->center_freq;
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
ch->flags |= IEEE80211_CHAN_DISABLED;
continue;
}
/* UNII-5/6/7/8 */
if (IS_UNII_INVALID(1, 5925, 6425) ||
IS_UNII_INVALID(2, 6425, 6525) ||
IS_UNII_INVALID(3, 6525, 6875) ||
IS_UNII_INVALID(4, 6875, 7125))
ch->flags |= IEEE80211_CHAN_DISABLED;
}
}
static void
@ -77,6 +123,8 @@ mt7921_regd_notifier(struct wiphy *wiphy,
mt76_connac_mcu_set_channel_domain(hw->priv);
mt7921_set_tx_sar_pwr(hw, NULL);
mt792x_mutex_release(dev);
mt7921_regd_channel_update(wiphy, dev);
}
int mt7921_mac_init(struct mt792x_dev *dev)

View File

@ -794,7 +794,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0;
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
mt792x_skb_add_usb_sdio_hdr(dev, skb, type);
pad = round_up(skb->len, 4) - skb->len;
if (mt76_is_usb(mdev))
pad += 4;

View File

@ -259,25 +259,6 @@ static int mt7921_start(struct ieee80211_hw *hw)
return err;
}
void mt7921_stop(struct ieee80211_hw *hw)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt792x_phy *phy = mt792x_hw_phy(hw);
cancel_delayed_work_sync(&phy->mt76->mac_work);
cancel_delayed_work_sync(&dev->pm.ps_work);
cancel_work_sync(&dev->pm.wake_work);
cancel_work_sync(&dev->reset_work);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt792x_mutex_acquire(dev);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
mt792x_mutex_release(dev);
}
EXPORT_SYMBOL_GPL(mt7921_stop);
static int
mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
@ -315,7 +296,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
mt76_wcid_init(&mvif->sta.wcid);
mt7921_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -701,6 +682,38 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
mt792x_mutex_release(dev);
}
static void
mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_phy *phy = mvif->phy;
struct mt792x_dev *dev = phy->dev;
if (hweight64(dev->mt76.vif_mask) > 1) {
phy->power_type = MT_AP_DEFAULT;
goto out;
}
switch (vif->bss_conf.power_type) {
case IEEE80211_REG_SP_AP:
phy->power_type = MT_AP_SP;
break;
case IEEE80211_REG_VLP_AP:
phy->power_type = MT_AP_VLP;
break;
case IEEE80211_REG_LPI_AP:
phy->power_type = MT_AP_LPI;
break;
case IEEE80211_REG_UNSET_AP:
default:
phy->power_type = MT_AP_DEFAULT;
break;
}
out:
mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env);
}
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
@ -736,6 +749,8 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (ret)
return ret;
mt7921_regd_set_6ghz_power_type(vif);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
return 0;
@ -753,7 +768,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
true, mvif->ctx);
true, mvif->mt76.ctx);
ewma_avg_signal_init(&msta->avg_ack_signal);
@ -788,7 +803,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (!sta->tdls)
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
&mvif->sta.wcid, false,
mvif->ctx);
mvif->mt76.ctx);
}
spin_lock_bh(&dev->mt76.sta_poll_lock);
@ -1205,7 +1220,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt792x_mutex_acquire(dev);
err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
true, mvif->ctx);
true, mvif->mt76.ctx);
if (err)
goto out;
@ -1237,7 +1252,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out;
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
mvif->ctx);
mvif->mt76.ctx);
out:
mt792x_mutex_release(dev);
@ -1262,7 +1277,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac,
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct ieee80211_chanctx_conf *ctx = priv;
if (ctx != mvif->ctx)
if (ctx != mvif->mt76.ctx)
return;
if (vif->type == NL80211_IFTYPE_MONITOR)
@ -1295,7 +1310,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
jiffies_to_msecs(HZ);
mt792x_mutex_acquire(dev);
mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
mt7921_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration,
MT7921_ROC_REQ_JOIN);
mt792x_mutex_release(dev);
}
@ -1312,7 +1327,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
const struct ieee80211_ops mt7921_ops = {
.tx = mt792x_tx,
.start = mt7921_start,
.stop = mt7921_stop,
.stop = mt792x_stop,
.add_interface = mt7921_add_interface,
.remove_interface = mt792x_remove_interface,
.config = mt7921_config,

View File

@ -448,6 +448,129 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
return ret;
}
static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt76_sdio *sdio = &dev->sdio;
struct mt7921_tx_resource {
__le32 version;
__le32 pse_data_quota;
__le32 pse_mcu_quota;
__le32 ple_data_quota;
__le32 ple_mcu_quota;
__le16 pse_page_size;
__le16 ple_page_size;
u8 pp_padding;
u8 pad[3];
} __packed * tx_res;
tx_res = (struct mt7921_tx_resource *)skb->data;
sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);
sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota);
sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);
sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);
sdio->sched.deficit = tx_res->pp_padding;
}
static void mt7921_mcu_parse_phy_cap(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt7921_phy_cap {
u8 ht;
u8 vht;
u8 _5g;
u8 max_bw;
u8 nss;
u8 dbdc;
u8 tx_ldpc;
u8 rx_ldpc;
u8 tx_stbc;
u8 rx_stbc;
u8 hw_path;
u8 he;
} __packed * cap;
enum {
WF0_24G,
WF0_5G
};
cap = (struct mt7921_phy_cap *)skb->data;
dev->phy.antenna_mask = BIT(cap->nss) - 1;
dev->phy.chainmask = dev->phy.antenna_mask;
dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
}
static int mt7921_mcu_get_nic_capability(struct mt792x_phy *mphy)
{
struct mt76_connac_cap_hdr {
__le16 n_element;
u8 rsv[2];
} __packed * hdr;
struct sk_buff *skb;
struct mt76_phy *phy = mphy->mt76;
int ret, i;
ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),
NULL, 0, true, &skb);
if (ret)
return ret;
hdr = (struct mt76_connac_cap_hdr *)skb->data;
if (skb->len < sizeof(*hdr)) {
ret = -EINVAL;
goto out;
}
skb_pull(skb, sizeof(*hdr));
for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
struct tlv_hdr {
__le32 type;
__le32 len;
} __packed * tlv = (struct tlv_hdr *)skb->data;
int len;
if (skb->len < sizeof(*tlv))
break;
skb_pull(skb, sizeof(*tlv));
len = le32_to_cpu(tlv->len);
if (skb->len < len)
break;
switch (le32_to_cpu(tlv->type)) {
case MT_NIC_CAP_6G:
phy->cap.has_6ghz = skb->data[0];
break;
case MT_NIC_CAP_MAC_ADDR:
memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);
break;
case MT_NIC_CAP_PHY:
mt7921_mcu_parse_phy_cap(phy->dev, skb);
break;
case MT_NIC_CAP_TX_RESOURCE:
if (mt76_is_sdio(phy->dev))
mt7921_mcu_parse_tx_resource(phy->dev,
skb);
break;
case MT_NIC_CAP_CHIP_CAP:
memcpy(&mphy->chip_cap, (void *)skb->data, sizeof(u64));
break;
default:
break;
}
skb_pull(skb, len);
}
out:
dev_kfree_skb(skb);
return ret;
}
int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)
{
struct {
@ -469,7 +592,7 @@ int mt7921_run_firmware(struct mt792x_dev *dev)
if (err)
return err;
err = mt76_connac_mcu_get_nic_capability(&dev->mphy);
err = mt7921_mcu_get_nic_capability(&dev->phy);
if (err)
return err;
@ -1123,7 +1246,9 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
struct mt7921_clc *clc,
u8 idx)
{
struct sk_buff *skb;
#define CLC_CAP_EVT_EN BIT(0)
#define CLC_CAP_DTS_EN BIT(1)
struct sk_buff *skb, *ret_skb = NULL;
struct {
u8 ver;
u8 pad0;
@ -1131,13 +1256,15 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
u8 idx;
u8 env;
u8 acpi_conf;
u8 pad1;
u8 cap;
u8 alpha2[2];
u8 type[2];
u8 rsvd[64];
u8 env_6g;
u8 rsvd[63];
} __packed req = {
.idx = idx,
.env = env_cap,
.env_6g = dev->phy.power_type,
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
};
int ret, valid_cnt = 0;
@ -1146,6 +1273,11 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
if (!clc)
return 0;
if (dev->phy.chip_cap & MT792x_CHIP_CAP_CLC_EVT_EN)
req.cap |= CLC_CAP_EVT_EN;
if (mt76_find_power_limits_node(&dev->mt76))
req.cap |= CLC_CAP_DTS_EN;
pos = clc->data;
for (i = 0; i < clc->nr_country; i++) {
struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;
@ -1167,10 +1299,21 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
return -ENOMEM;
skb_put_data(skb, rule->data, len);
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_CE_CMD(SET_CLC), false);
ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
MCU_CE_CMD(SET_CLC),
!!(req.cap & CLC_CAP_EVT_EN),
&ret_skb);
if (ret < 0)
return ret;
if (ret_skb) {
struct mt7921_clc_info_tlv *info;
info = (struct mt7921_clc_info_tlv *)(ret_skb->data + 4);
dev->phy.clc_chan_conf = info->chan_conf;
dev_kfree_skb(ret_skb);
}
valid_cnt++;
}

View File

@ -99,4 +99,17 @@ struct mt7921_rftest_evt {
__le32 param0;
__le32 param1;
} __packed;
struct mt7921_clc_info_tlv {
__le16 tag;
__le16 len;
u8 chan_conf; /* BIT(0) : Enable UNII-4
* BIT(1) : Enable UNII-5
* BIT(2) : Enable UNII-6
* BIT(3) : Enable UNII-7
* BIT(4) : Enable UNII-8
*/
u8 rsv[63];
} __packed;
#endif

View File

@ -23,10 +23,8 @@
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
#define MT7921_SDIO_HDR_TX_BYTES GENMASK(15, 0)
#define MT7921_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
#define MCU_UNI_EVENT_ROC 0x27
#define MCU_UNI_EVENT_CLC 0x80
enum {
UNI_ROC_ACQUIRE,
@ -235,20 +233,6 @@ mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val)
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
static inline void
mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
int type)
{
u32 hdr, len;
len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr);
hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) |
FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type);
put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
}
void mt7921_stop(struct ieee80211_hw *hw);
int mt7921_mac_init(struct mt792x_dev *dev);
bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,

View File

@ -17,6 +17,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7922),
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_ITTIM, 0x7922),
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),

View File

@ -48,7 +48,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
tx_info->skb = NULL;
return 0;
}

View File

@ -38,7 +38,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
if (cmd == MCU_CMD(FW_SCATTER))
type = MT7921_SDIO_FWDL;
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
mt792x_skb_add_usb_sdio_hdr(dev, skb, type);
pad = round_up(skb->len, 4) - skb->len;
__skb_put_zero(skb, pad);

View File

@ -43,7 +43,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
else
ep = MT_EP_OUT_AC_BE;
mt7921_skb_add_usb_sdio_hdr(dev, skb, 0);
mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
pad = round_up(skb->len, 4) + 4 - skb->len;
__skb_put_zero(skb, pad);
@ -135,14 +135,6 @@ static int mt7921u_mac_reset(struct mt792x_dev *dev)
return err;
}
static void mt7921u_stop(struct ieee80211_hw *hw)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mt76u_stop_tx(&dev->mt76);
mt7921_stop(hw);
}
static int mt7921u_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
@ -189,7 +181,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
if (!ops)
return -ENOMEM;
ops->stop = mt7921u_stop;
ops->stop = mt792xu_stop;
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev)
return -ENOMEM;

View File

@ -0,0 +1,30 @@
# SPDX-License-Identifier: ISC
config MT7925_COMMON
tristate
select MT792x_LIB
select WANT_DEV_COREDUMP
config MT7925E
tristate "MediaTek MT7925E (PCIe) support"
select MT7925_COMMON
depends on MAC80211
depends on PCI
help
This adds support for MT7925-based wireless PCIe devices,
which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be
2x2:2SS 4096-QAM, 160MHz channels.
To compile this driver as a module, choose M here.
config MT7925U
tristate "MediaTek MT7925U (USB) support"
select MT792x_USB
select MT7925_COMMON
depends on MAC80211
depends on USB
help
This adds support for MT7925-based wireless USB devices,
which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be
2x2:2SS 4096-QAM, 160MHz channels.
To compile this driver as a module, choose M here.

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: ISC
obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o
obj-$(CONFIG_MT7925E) += mt7925e.o
obj-$(CONFIG_MT7925U) += mt7925u.o
mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o
mt7925e-y := pci.o pci_mac.o pci_mcu.o
mt7925u-y := usb.o

View File

@ -0,0 +1,319 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt7925.h"
#include "mcu.h"
static int
mt7925_reg_set(void *data, u64 val)
{
struct mt792x_dev *dev = data;
u32 regval = val;
mt792x_mutex_acquire(dev);
mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, true);
mt792x_mutex_release(dev);
return 0;
}
static int
mt7925_reg_get(void *data, u64 *val)
{
struct mt792x_dev *dev = data;
u32 regval;
int ret;
mt792x_mutex_acquire(dev);
ret = mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, false);
mt792x_mutex_release(dev);
if (!ret)
*val = regval;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set,
"0x%08llx\n");
static int
mt7925_fw_debug_set(void *data, u64 val)
{
struct mt792x_dev *dev = data;
mt792x_mutex_acquire(dev);
dev->fw_debug = (u8)val;
mt7925_mcu_fw_log_2_host(dev, dev->fw_debug);
mt792x_mutex_release(dev);
return 0;
}
static int
mt7925_fw_debug_get(void *data, u64 *val)
{
struct mt792x_dev *dev = data;
*val = dev->fw_debug;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get,
mt7925_fw_debug_set, "%lld\n");
DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats);
static void
mt7925_seq_puts_array(struct seq_file *file, const char *str,
s8 val[][2], int len, u8 band_idx)
{
int i;
seq_printf(file, "%-22s:", str);
for (i = 0; i < len; i++)
if (val[i][band_idx] == 127)
seq_printf(file, " %6s", "N.A");
else
seq_printf(file, " %6d", val[i][band_idx]);
seq_puts(file, "\n");
}
#define mt7925_print_txpwr_entry(prefix, rate, idx) \
({ \
mt7925_seq_puts_array(s, #prefix " (tmac)", \
txpwr->rate, \
ARRAY_SIZE(txpwr->rate), \
idx); \
})
static inline void
mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx)
{
seq_printf(s, "%-22s %6s %6s %6s %6s %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",
"mcs12", "mcs13", "mcs14", "mcs15");
mt7925_print_txpwr_entry(EHT26, eht26, band_idx);
mt7925_print_txpwr_entry(EHT52, eht52, band_idx);
mt7925_print_txpwr_entry(EHT106, eht106, band_idx);
mt7925_print_txpwr_entry(EHT242, eht242, band_idx);
mt7925_print_txpwr_entry(EHT484, eht484, band_idx);
mt7925_print_txpwr_entry(EHT996, eht996, band_idx);
mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);
mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);
mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);
mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);
mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);
mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);
mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);
mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);
mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);
mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);
}
static int
mt7925_txpwr(struct seq_file *s, void *data)
{
struct mt792x_dev *dev = dev_get_drvdata(s->private);
struct mt7925_txpwr *txpwr = NULL;
u8 band_idx = dev->mphy.band_idx;
int ret = 0;
txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL);
if (!txpwr)
return -ENOMEM;
mt792x_mutex_acquire(dev);
ret = mt7925_get_txpwr_info(dev, band_idx, txpwr);
mt792x_mutex_release(dev);
if (ret)
goto out;
seq_printf(s, "%-22s %6s %6s %6s %6s\n",
" ", "1m", "2m", "5m", "11m");
mt7925_print_txpwr_entry(CCK, cck, band_idx);
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "6m", "9m", "12m", "18m", "24m", "36m",
"48m", "54m");
mt7925_print_txpwr_entry(OFDM, ofdm, band_idx);
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7");
mt7925_print_txpwr_entry(HT20, ht20, band_idx);
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7", "mcs32");
mt7925_print_txpwr_entry(HT40, ht40, band_idx);
seq_printf(s, "%-22s %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");
mt7925_print_txpwr_entry(VHT20, vht20, band_idx);
mt7925_print_txpwr_entry(VHT40, vht40, band_idx);
mt7925_print_txpwr_entry(VHT80, vht80, band_idx);
mt7925_print_txpwr_entry(VHT160, vht160, band_idx);
mt7925_print_txpwr_entry(HE26, he26, band_idx);
mt7925_print_txpwr_entry(HE52, he52, band_idx);
mt7925_print_txpwr_entry(HE106, he106, band_idx);
mt7925_print_txpwr_entry(HE242, he242, band_idx);
mt7925_print_txpwr_entry(HE484, he484, band_idx);
mt7925_print_txpwr_entry(HE996, he996, band_idx);
mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);
mt7925_eht_txpwr(s, txpwr, band_idx);
out:
devm_kfree(dev->mt76.dev, txpwr);
return ret;
}
static int
mt7925_pm_set(void *data, u64 val)
{
struct mt792x_dev *dev = data;
struct mt76_connac_pm *pm = &dev->pm;
if (mt76_is_usb(&dev->mt76))
return -EOPNOTSUPP;
mutex_lock(&dev->mt76.mutex);
if (val == pm->enable_user)
goto out;
if (!pm->enable_user) {
pm->stats.last_wake_event = jiffies;
pm->stats.last_doze_event = jiffies;
}
/* make sure the chip is awake here and ps_work is scheduled
* just at end of the this routine.
*/
pm->enable = false;
mt76_connac_pm_wake(&dev->mphy, pm);
pm->enable_user = val;
mt7925_set_runtime_pm(dev);
mt76_connac_power_save_sched(&dev->mphy, pm);
out:
mutex_unlock(&dev->mt76.mutex);
return 0;
}
static int
mt7925_pm_get(void *data, u64 *val)
{
struct mt792x_dev *dev = data;
*val = dev->pm.enable_user;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, "%lld\n");
static int
mt7925_deep_sleep_set(void *data, u64 val)
{
struct mt792x_dev *dev = data;
struct mt76_connac_pm *pm = &dev->pm;
bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
bool enable = !!val;
if (mt76_is_usb(&dev->mt76))
return -EOPNOTSUPP;
mt792x_mutex_acquire(dev);
if (pm->ds_enable_user == enable)
goto out;
pm->ds_enable_user = enable;
pm->ds_enable = enable && !monitor;
mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
out:
mt792x_mutex_release(dev);
return 0;
}
static int
mt7925_deep_sleep_get(void *data, u64 *val)
{
struct mt792x_dev *dev = data;
*val = dev->pm.ds_enable_user;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get,
mt7925_deep_sleep_set, "%lld\n");
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,
mt792x_pm_idle_timeout_set, "%lld\n");
static int mt7925_chip_reset(void *data, u64 val)
{
struct mt792x_dev *dev = data;
int ret = 0;
switch (val) {
case 1:
/* Reset wifisys directly. */
mt792x_reset(&dev->mt76);
break;
default:
/* Collect the core dump before reset wifisys. */
mt792x_mutex_acquire(dev);
ret = mt7925_mcu_chip_config(dev, "assert");
mt792x_mutex_release(dev);
break;
}
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n");
int mt7925_init_debugfs(struct mt792x_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
if (!dir)
return -ENOMEM;
if (mt76_is_mmio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
dir, mt792x_queues_read);
else
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
dir, mt76_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt792x_queues_acq);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
mt7925_txpwr);
debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
debugfs_create_file("idle-timeout", 0600, dir, dev,
&fops_pm_idle_timeout);
debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
mt792x_pm_stats);
debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
return 0;
}

View File

@ -0,0 +1,235 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/etherdevice.h>
#include <linux/firmware.h>
#include "mt7925.h"
#include "mac.h"
#include "mcu.h"
static void
mt7925_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt76_dev *mdev = &dev->mt76;
/* allow world regdom at the first boot only */
if (!memcmp(req->alpha2, "00", 2) &&
mdev->alpha2[0] && mdev->alpha2[1])
return;
/* do not need to update the same country twice */
if (!memcmp(req->alpha2, mdev->alpha2, 2) &&
dev->country_ie_env == req->country_ie_env)
return;
memcpy(mdev->alpha2, req->alpha2, 2);
mdev->region = req->dfs_region;
dev->country_ie_env = req->country_ie_env;
mt792x_mutex_acquire(dev);
mt7925_mcu_set_clc(dev, req->alpha2, req->country_ie_env);
mt7925_mcu_set_channel_domain(hw->priv);
mt7925_set_tx_sar_pwr(hw, NULL);
mt792x_mutex_release(dev);
}
static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
u16 rate = mt76_rates[i].hw_value;
u16 idx = MT792x_BASIC_RATES_TBL + i;
rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
mt7925_mac_set_fixed_rate_table(dev, idx, rate);
}
}
int mt7925_mac_init(struct mt792x_dev *dev)
{
int i;
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
/* enable hardware de-agg */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
for (i = 0; i < MT792x_WTBL_SIZE; i++)
mt7925_mac_wtbl_update(dev, i,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < 2; i++)
mt792x_mac_init_band(dev, i);
mt7925_mac_init_basic_rates(dev);
memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
return 0;
}
EXPORT_SYMBOL_GPL(mt7925_mac_init);
static int __mt7925_init_hardware(struct mt792x_dev *dev)
{
int ret;
ret = mt792x_mcu_init(dev);
if (ret)
goto out;
mt76_eeprom_override(&dev->mphy);
ret = mt7925_mcu_set_eeprom(dev);
if (ret)
goto out;
ret = mt7925_mac_init(dev);
if (ret)
goto out;
out:
return ret;
}
static int mt7925_init_hardware(struct mt792x_dev *dev)
{
int ret, i;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) {
ret = __mt7925_init_hardware(dev);
if (!ret)
break;
mt792x_init_reset(dev);
}
if (i == MT792x_MCU_INIT_RETRY_COUNT) {
dev_err(dev->mt76.dev, "hardware init failed\n");
return ret;
}
return 0;
}
static void mt7925_init_work(struct work_struct *work)
{
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
init_work);
int ret;
ret = mt7925_init_hardware(dev);
if (ret)
return;
mt76_set_stream_caps(&dev->mphy, true);
mt7925_set_stream_he_eht_caps(&dev->phy);
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret) {
dev_err(dev->mt76.dev, "register device failed\n");
return;
}
ret = mt7925_init_debugfs(dev);
if (ret) {
dev_err(dev->mt76.dev, "register debugfs failed\n");
return;
}
/* we support chip reset now */
dev->hw_init_done = true;
mt7925_mcu_set_deep_sleep(dev, dev->pm.ds_enable);
}
int mt7925_register_device(struct mt792x_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
int ret;
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
dev->mt76.tx_worker.fn = mt792x_tx_worker;
INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work);
INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work);
spin_lock_init(&dev->pm.wake.lock);
mutex_init(&dev->pm.mutex);
init_waitqueue_head(&dev->pm.wait);
spin_lock_init(&dev->pm.txq_lock);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7925_scan_work);
INIT_DELAYED_WORK(&dev->coredump.work, mt7925_coredump_work);
#if IS_ENABLED(CONFIG_IPV6)
INIT_WORK(&dev->ipv6_ns_work, mt7925_set_ipv6_ns_work);
skb_queue_head_init(&dev->ipv6_ns_list);
#endif
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_WORK(&dev->reset_work, mt7925_mac_reset_work);
INIT_WORK(&dev->init_work, mt7925_init_work);
INIT_WORK(&dev->phy.roc_work, mt7925_roc_work);
timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0);
init_waitqueue_head(&dev->phy.roc_wait);
dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
dev->pm.stats.last_wake_event = jiffies;
dev->pm.stats.last_doze_event = jiffies;
if (!mt76_is_usb(&dev->mt76)) {
dev->pm.enable_user = true;
dev->pm.enable = true;
dev->pm.ds_enable_user = true;
dev->pm.ds_enable = true;
}
if (!mt76_is_mmio(&dev->mt76))
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
mt792x_init_acpi_sar(dev);
ret = mt792x_init_wcid(dev);
if (ret)
return ret;
ret = mt792x_init_wiphy(hw);
if (ret)
return ret;
hw->wiphy->reg_notifier = mt7925_regd_notifier;
dev->mphy.sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
dev->mphy.sband_2g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_2;
dev->mphy.sband_5g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
dev->mphy.sband_2g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_1;
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
(3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
IEEE80211_VHT_CAP_SHORT_GI_160;
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
queue_work(system_wq, &dev->init_work);
return 0;
}
EXPORT_SYMBOL_GPL(mt7925_register_device);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT7925_MAC_H
#define __MT7925_MAC_H
#include "../mt76_connac3_mac.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 inline u32 mt7925_mac_wtbl_lmac_addr(struct mt792x_dev *dev, u16 wcid, u8 dw)
{
mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
return MT_WTBL_LMAC_OFFS(wcid, dw);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT7925_MCU_H
#define __MT7925_MCU_H
#include "../mt76_connac_mcu.h"
/* ext event table */
enum {
MCU_EXT_EVENT_RATE_REPORT = 0x87,
};
struct mt7925_mcu_eeprom_info {
__le32 addr;
__le32 valid;
u8 data[MT7925_EEPROM_BLOCK_SIZE];
} __packed;
#define MT_RA_RATE_NSS GENMASK(8, 6)
#define MT_RA_RATE_MCS GENMASK(3, 0)
#define MT_RA_RATE_TX_MODE GENMASK(12, 9)
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
struct mt7925_mcu_rxd {
__le32 rxd[8];
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
u8 option;
u8 __rsv;
u8 ext_eid;
u8 __rsv1[2];
u8 s2d_index;
u8 tlv[];
};
struct mt7925_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 mt7925_mcu_reg_event {
__le32 reg;
__le32 val;
} __packed;
struct mt7925_mcu_ant_id_config {
u8 ant_id[4];
} __packed;
struct mt7925_txpwr_req {
u8 _rsv[4];
__le16 tag;
__le16 len;
u8 format_id;
u8 catg;
u8 band_idx;
u8 _rsv1;
} __packed;
struct mt7925_txpwr_event {
u8 rsv[4];
__le16 tag;
__le16 len;
u8 catg;
u8 band_idx;
u8 ch_band;
u8 format; /* 0:Legacy, 1:HE */
/* Rate power info */
struct mt7925_txpwr txpwr;
s8 pwr_max;
s8 pwr_min;
u8 rsv1;
} __packed;
enum {
TM_SWITCH_MODE,
TM_SET_AT_CMD,
TM_QUERY_AT_CMD,
};
enum {
MT7925_TM_NORMAL,
MT7925_TM_TESTMODE,
MT7925_TM_ICAP,
MT7925_TM_ICAP_OVERLAP,
MT7925_TM_WIFISPECTRUM,
};
struct mt7925_rftest_cmd {
u8 action;
u8 rsv[3];
__le32 param0;
__le32 param1;
} __packed;
struct mt7925_rftest_evt {
__le32 param0;
__le32 param1;
} __packed;
enum {
UNI_CHANNEL_SWITCH,
UNI_CHANNEL_RX_PATH,
};
enum {
UNI_CHIP_CONFIG_CHIP_CFG = 0x2,
UNI_CHIP_CONFIG_NIC_CAPA = 0x3,
};
enum {
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
UNI_BAND_CONFIG_SET_MAC80211_RX_FILTER = 0x0C,
};
enum {
UNI_WSYS_CONFIG_FW_LOG_CTRL,
UNI_WSYS_CONFIG_FW_DBG_CTRL,
};
enum {
UNI_EFUSE_ACCESS = 1,
UNI_EFUSE_BUFFER_MODE,
UNI_EFUSE_FREE_BLOCK,
UNI_EFUSE_BUFFER_RD,
};
enum {
UNI_CMD_ACCESS_REG_BASIC = 0x0,
UNI_CMD_ACCESS_RF_REG_BASIC,
};
enum {
UNI_MBMC_SETTING,
};
enum {
UNI_EVENT_SCAN_DONE_BASIC = 0,
UNI_EVENT_SCAN_DONE_CHNLINFO = 2,
UNI_EVENT_SCAN_DONE_NLO = 3,
};
struct mt7925_mcu_scan_chinfo_event {
u8 nr_chan;
u8 alpha2[3];
} __packed;
enum {
UNI_SCAN_REQ = 1,
UNI_SCAN_CANCEL = 2,
UNI_SCAN_SCHED_REQ = 3,
UNI_SCAN_SCHED_ENABLE = 4,
UNI_SCAN_SSID = 10,
UNI_SCAN_BSSID,
UNI_SCAN_CHANNEL,
UNI_SCAN_IE,
UNI_SCAN_MISC,
UNI_SCAN_SSID_MATCH_SETS,
};
enum {
UNI_SNIFFER_ENABLE,
UNI_SNIFFER_CONFIG,
};
struct scan_hdr_tlv {
/* fixed field */
u8 seq_num;
u8 bss_idx;
u8 pad[2];
/* tlv */
u8 data[];
} __packed;
struct scan_req_tlv {
__le16 tag;
__le16 len;
u8 scan_type; /* 0: PASSIVE SCAN
* 1: ACTIVE SCAN
*/
u8 probe_req_num; /* Number of probe request for each SSID */
u8 scan_func; /* BIT(0) Enable random MAC scan
* BIT(1) Disable DBDC scan type 1~3.
* BIT(2) Use DBDC scan type 3 (dedicated one RF to scan).
*/
u8 src_mask;
__le16 channel_min_dwell_time;
__le16 channel_dwell_time; /* channel Dwell interval */
__le16 timeout_value;
__le16 probe_delay_time;
u8 func_mask_ext;
};
struct scan_ssid_tlv {
__le16 tag;
__le16 len;
u8 ssid_type; /* BIT(0) wildcard SSID
* BIT(1) P2P wildcard SSID
* BIT(2) specified SSID + wildcard SSID
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
*/
u8 ssids_num;
u8 pad[2];
struct mt76_connac_mcu_scan_ssid ssids[4];
};
struct scan_bssid_tlv {
__le16 tag;
__le16 len;
u8 bssid[ETH_ALEN];
u8 match_ch;
u8 match_ssid_ind;
u8 rcpi;
u8 pad[3];
};
struct scan_chan_info_tlv {
__le16 tag;
__le16 len;
u8 channel_type; /* 0: Full channels
* 1: Only 2.4GHz channels
* 2: Only 5GHz channels
* 3: P2P social channel only (channel #1, #6 and #11)
* 4: Specified channels
* Others: Reserved
*/
u8 channels_num; /* valid when channel_type is 4 */
u8 pad[2];
struct mt76_connac_mcu_scan_channel channels[64];
};
struct scan_ie_tlv {
__le16 tag;
__le16 len;
__le16 ies_len;
u8 band;
u8 pad;
u8 ies[MT76_CONNAC_SCAN_IE_LEN];
};
struct scan_misc_tlv {
__le16 tag;
__le16 len;
u8 random_mac[ETH_ALEN];
u8 rsv[2];
};
struct scan_sched_req {
__le16 tag;
__le16 len;
u8 version;
u8 stop_on_match;
u8 intervals_num;
u8 scan_func;
__le16 intervals[MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL];
};
struct scan_sched_ssid_match_sets {
__le16 tag;
__le16 len;
u8 match_num;
u8 rsv[3];
struct mt76_connac_mcu_scan_match match[MT76_CONNAC_MAX_SCAN_MATCH];
};
struct scan_sched_enable {
__le16 tag;
__le16 len;
u8 active;
u8 rsv[3];
};
struct mbmc_set_req {
u8 pad[4];
u8 data[];
} __packed;
struct mbmc_conf_tlv {
__le16 tag;
__le16 len;
u8 mbmc_en;
u8 band;
u8 pad[2];
} __packed;
struct edca {
__le16 tag;
__le16 len;
u8 queue;
u8 set;
u8 cw_min;
u8 cw_max;
__le16 txop;
u8 aifs;
u8 __rsv;
};
struct bss_req_hdr {
u8 bss_idx;
u8 __rsv[3];
} __packed;
struct bss_rate_tlv {
__le16 tag;
__le16 len;
u8 __rsv1[4];
__le16 bc_trans;
__le16 mc_trans;
u8 short_preamble;
u8 bc_fixed_rate;
u8 mc_fixed_rate;
u8 __rsv2;
} __packed;
struct bss_mld_tlv {
__le16 tag;
__le16 len;
u8 group_mld_id;
u8 own_mld_id;
u8 mac_addr[ETH_ALEN];
u8 remap_idx;
u8 link_id;
u8 __rsv[2];
} __packed;
struct sta_rec_ba_uni {
__le16 tag;
__le16 len;
u8 tid;
u8 ba_type;
u8 amsdu;
u8 ba_en;
__le16 ssn;
__le16 winsize;
u8 ba_rdd_rro;
u8 __rsv[3];
} __packed;
struct sta_rec_eht {
__le16 tag;
__le16 len;
u8 tid_bitmap;
u8 _rsv;
__le16 mac_cap;
__le64 phy_cap;
__le64 phy_cap_ext;
u8 mcs_map_bw20[4];
u8 mcs_map_bw80[3];
u8 mcs_map_bw160[3];
u8 mcs_map_bw320[3];
u8 _rsv2[3];
} __packed;
struct sec_key_uni {
__le16 wlan_idx;
u8 mgmt_prot;
u8 cipher_id;
u8 cipher_len;
u8 key_id;
u8 key_len;
u8 need_resp;
u8 key[32];
} __packed;
struct sta_rec_sec_uni {
__le16 tag;
__le16 len;
u8 add;
u8 n_cipher;
u8 rsv[2];
struct sec_key_uni key[2];
} __packed;
struct sta_rec_hdr_trans {
__le16 tag;
__le16 len;
u8 from_ds;
u8 to_ds;
u8 dis_rx_hdr_tran;
u8 rsv;
} __packed;
struct sta_rec_mld {
__le16 tag;
__le16 len;
u8 mac_addr[ETH_ALEN];
__le16 primary_id;
__le16 secondary_id;
__le16 wlan_id;
u8 link_num;
u8 rsv[3];
struct {
__le16 wlan_id;
u8 bss_idx;
u8 rsv;
} __packed link[2];
} __packed;
#define MT7925_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_bf) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_he_v2) + \
sizeof(struct sta_rec_ba_uni) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct sta_rec_bfee) + \
sizeof(struct sta_rec_phy) + \
sizeof(struct sta_rec_ra) + \
sizeof(struct sta_rec_sec) + \
sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct sta_rec_eht) + \
sizeof(struct sta_rec_hdr_trans) + \
sizeof(struct sta_rec_mld) + \
sizeof(struct tlv))
#define MT7925_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \
sizeof(struct mt76_connac_bss_basic_tlv) + \
sizeof(struct mt76_connac_bss_qos_tlv) + \
sizeof(struct bss_rate_tlv) + \
sizeof(struct bss_mld_tlv) + \
sizeof(struct bss_info_uni_he) + \
sizeof(struct bss_info_uni_bss_color) + \
sizeof(struct tlv))
#define MT_CONNAC3_SKU_POWER_LIMIT 449
struct mt7925_sku_tlv {
u8 channel;
s8 pwr_limit[MT_CONNAC3_SKU_POWER_LIMIT];
} __packed;
struct mt7925_tx_power_limit_tlv {
u8 rsv[4];
__le16 tag;
__le16 len;
/* DW0 - common info*/
u8 ver;
u8 pad0;
__le16 rsv1;
/* DW1 - cmd hint */
u8 n_chan; /* # channel */
u8 band; /* 2.4GHz - 5GHz - 6GHz */
u8 last_msg;
u8 limit_type;
/* DW3 */
u8 alpha2[4]; /* regulatory_request.alpha2 */
u8 pad2[32];
u8 data[];
} __packed;
struct mt7925_arpns_tlv {
__le16 tag;
__le16 len;
u8 enable;
u8 ips_num;
u8 rsv[2];
} __packed;
struct mt7925_wow_pattern_tlv {
__le16 tag;
__le16 len;
u8 bss_idx;
u8 index; /* pattern index */
u8 enable; /* 0: disable
* 1: enable
*/
u8 data_len; /* pattern length */
u8 offset;
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
u8 rsv[4];
} __packed;
int mt7925_mcu_set_dbdc(struct mt76_phy *phy);
int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_scan_request *scan_req);
int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
struct ieee80211_vif *vif);
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq);
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
struct ieee80211_vif *vif,
bool enable);
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
struct ieee80211_chanctx_conf *ctx,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
int enable);
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
int mt7925_mcu_set_channel_domain(struct mt76_phy *phy);
int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable);
int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,
struct ieee80211_chanctx_conf *ctx);
int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy);
int mt7925_mcu_update_arp_filter(struct mt76_dev *dev,
struct mt76_vif *vif,
struct ieee80211_bss_conf *info);
#endif

View File

@ -0,0 +1,309 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT7925_H
#define __MT7925_H
#include "../mt792x.h"
#include "regs.h"
#define MT7925_BEACON_RATES_TBL 25
#define MT7925_TX_RING_SIZE 2048
#define MT7925_TX_MCU_RING_SIZE 256
#define MT7925_TX_FWDL_RING_SIZE 128
#define MT7925_RX_RING_SIZE 1536
#define MT7925_RX_MCU_RING_SIZE 512
#define MT7925_EEPROM_SIZE 3584
#define MT7925_TOKEN_SIZE 8192
#define MT7925_EEPROM_BLOCK_SIZE 16
#define MT7925_SKU_RATE_NUM 161
#define MT7925_SKU_MAX_DELTA_IDX MT7925_SKU_RATE_NUM
#define MT7925_SKU_TABLE_SIZE (MT7925_SKU_RATE_NUM + 1)
#define MCU_UNI_EVENT_ROC 0x27
enum {
UNI_ROC_ACQUIRE,
UNI_ROC_ABORT,
UNI_ROC_NUM
};
enum mt7925_roc_req {
MT7925_ROC_REQ_JOIN,
MT7925_ROC_REQ_ROC,
MT7925_ROC_REQ_NUM
};
enum {
UNI_EVENT_ROC_GRANT = 0,
UNI_EVENT_ROC_TAG_NUM
};
struct mt7925_roc_grant_tlv {
__le16 tag;
__le16 len;
u8 bss_idx;
u8 tokenid;
u8 status;
u8 primarychannel;
u8 rfsco;
u8 rfband;
u8 channelwidth;
u8 centerfreqseg1;
u8 centerfreqseg2;
u8 reqtype;
u8 dbdcband;
u8 rsv[1];
__le32 max_interval;
} __packed;
struct mt7925_beacon_loss_tlv {
__le16 tag;
__le16 len;
u8 reason;
u8 nr_btolink;
u8 pad[2];
} __packed;
struct mt7925_uni_beacon_loss_event {
struct {
u8 bss_idx;
u8 pad[3];
} __packed hdr;
struct mt7925_beacon_loss_tlv beacon_loss;
} __packed;
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
#define to_rcpi(rssi) (2 * (rssi) + 220)
enum mt7925_txq_id {
MT7925_TXQ_BAND0,
MT7925_TXQ_BAND1,
MT7925_TXQ_MCU_WM = 15,
MT7925_TXQ_FWDL,
};
enum mt7925_rxq_id {
MT7925_RXQ_BAND0 = 2,
MT7925_RXQ_BAND1,
MT7925_RXQ_MCU_WM = 0,
MT7925_RXQ_MCU_WM2, /* for tx done */
};
enum {
MODE_OPEN = 0,
MODE_SHARED = 1,
MODE_WPA = 3,
MODE_WPA_PSK = 4,
MODE_WPA_NONE = 5,
MODE_WPA2 = 6,
MODE_WPA2_PSK = 7,
MODE_WPA3_SAE = 11,
};
enum {
MT7925_CLC_POWER,
MT7925_CLC_CHAN,
MT7925_CLC_MAX_NUM,
};
struct mt7925_clc_rule {
u8 alpha2[2];
u8 type[2];
u8 seg_idx;
u8 rsv[3];
} __packed;
struct mt7925_clc_segment {
u8 idx;
u8 rsv1[3];
u32 offset;
u32 len;
u8 rsv2[4];
} __packed;
struct mt7925_clc {
__le32 len;
u8 idx;
u8 ver;
u8 nr_country;
u8 type;
u8 nr_seg;
u8 rsv[7];
u8 data[];
} __packed;
enum mt7925_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
__MT_EE_MAX = 0x9ff
};
enum {
TXPWR_USER,
TXPWR_EEPROM,
TXPWR_MAC,
TXPWR_MAX_NUM,
};
struct mt7925_txpwr {
s8 cck[4][2];
s8 ofdm[8][2];
s8 ht20[8][2];
s8 ht40[9][2];
s8 vht20[12][2];
s8 vht40[12][2];
s8 vht80[12][2];
s8 vht160[12][2];
s8 he26[12][2];
s8 he52[12][2];
s8 he106[12][2];
s8 he242[12][2];
s8 he484[12][2];
s8 he996[12][2];
s8 he996x2[12][2];
s8 eht26[16][2];
s8 eht52[16][2];
s8 eht106[16][2];
s8 eht242[16][2];
s8 eht484[16][2];
s8 eht996[16][2];
s8 eht996x2[16][2];
s8 eht996x4[16][2];
s8 eht26_52[16][2];
s8 eht26_106[16][2];
s8 eht484_242[16][2];
s8 eht996_484[16][2];
s8 eht996_484_242[16][2];
s8 eht996x2_484[16][2];
s8 eht996x3[16][2];
s8 eht996x3_484[16][2];
};
extern const struct ieee80211_ops mt7925_ops;
int __mt7925_start(struct mt792x_phy *phy);
int mt7925_register_device(struct mt792x_dev *dev);
void mt7925_unregister_device(struct mt792x_dev *dev);
int mt7925_run_firmware(struct mt792x_dev *dev);
int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, bool enable,
enum mt76_sta_info_state state);
int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif);
int mt7925_mcu_set_eeprom(struct mt792x_dev *dev);
int mt7925_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl);
void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb);
int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd);
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
int mt7925_mac_init(struct mt792x_dev *dev);
int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7925_mac_reset_work(struct work_struct *work);
int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7925_tx_token_put(struct mt792x_dev *dev);
bool mt7925_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
void mt7925_stats_work(struct work_struct *work);
void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy);
int mt7925_init_debugfs(struct mt792x_dev *dev);
int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
bool enable);
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
void mt7925_scan_work(struct work_struct *work);
void mt7925_roc_work(struct work_struct *work);
int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif);
void mt7925_coredump_work(struct work_struct *work);
int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx,
struct mt7925_txpwr *txpwr);
void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev,
u8 tbl_idx, u16 rate_idx);
void mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed);
void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, bool clear_status,
struct list_head *free_list);
int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq);
int mt7925e_mac_reset(struct mt792x_dev *dev);
int mt7925e_mcu_init(struct mt792x_dev *dev);
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
void mt7925_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
void mt7925_set_ipv6_ns_work(struct work_struct *work);
int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7925_mcu_config_sniffer(struct mt792x_vif *vif,
struct ieee80211_chanctx_conf *ctx);
int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
struct mt76_queue_entry *e);
bool mt7925_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
int mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,
struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
bool enable);
int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);
int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap env_cap);
int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
struct ieee80211_channel *chan, int duration,
enum mt7925_roc_req type, u8 token_id);
int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
u8 token_id);
int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq);
int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct mt76_connac_sta_key_conf *sta_key_conf,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);
int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
#endif

View File

@ -0,0 +1,586 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "mt7925.h"
#include "mac.h"
#include "mcu.h"
#include "../dma.h"
static const struct pci_device_id mt7925_pci_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7925),
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0717),
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
{ },
};
static bool mt7925_disable_aspm;
module_param_named(disable_aspm, mt7925_disable_aspm, bool, 0644);
MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
static int mt7925e_init_reset(struct mt792x_dev *dev)
{
return mt792x_wpdma_reset(dev, true);
}
static void mt7925e_unregister_device(struct mt792x_dev *dev)
{
int i;
struct mt76_connac_pm *pm = &dev->pm;
cancel_work_sync(&dev->init_work);
mt76_unregister_device(&dev->mt76);
mt76_for_each_q_rx(&dev->mt76, i)
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);
mt7925_tx_token_put(dev);
__mt792x_mcu_drv_pmctrl(dev);
mt792x_dma_cleanup(dev);
mt792x_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
tasklet_disable(&dev->mt76.irq_tasklet);
}
static void mt7925_reg_remap_restore(struct mt792x_dev *dev)
{
/* remap to ori status */
if (unlikely(dev->backup_l1)) {
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->backup_l1);
dev->backup_l1 = 0;
}
if (dev->backup_l2) {
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->backup_l2);
dev->backup_l2 = 0;
}
}
static u32 mt7925_reg_map_l1(struct mt792x_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
dev->backup_l1 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
MT_HIF_REMAP_L1_MASK,
FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
return MT_HIF_REMAP_BASE_L1 + offset;
}
static u32 mt7925_reg_map_l2(struct mt792x_dev *dev, u32 addr)
{
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, MT_HIF_REMAP_BASE_L2);
dev->backup_l2 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
MT_HIF_REMAP_L1_MASK,
FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, addr);
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
return MT_HIF_REMAP_BASE_L1;
}
static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr)
{
static const struct mt76_connac_reg_map fixed_map[] = {
{ 0x830c0000, 0x000000, 0x0001000 }, /* WF_MCU_BUS_CR_REMAP */
{ 0x54000000, 0x002000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA0 */
{ 0x55000000, 0x003000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA1 */
{ 0x56000000, 0x004000, 0x0001000 }, /* WFDMA reserved */
{ 0x57000000, 0x005000, 0x0001000 }, /* WFDMA MCU wrap CR */
{ 0x58000000, 0x006000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
{ 0x59000000, 0x007000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA1 */
{ 0x820c0000, 0x008000, 0x0004000 }, /* WF_UMAC_TOP (PLE) */
{ 0x820c8000, 0x00c000, 0x0002000 }, /* WF_UMAC_TOP (PSE) */
{ 0x820cc000, 0x00e000, 0x0002000 }, /* WF_UMAC_TOP (PP) */
{ 0x74030000, 0x010000, 0x0001000 }, /* PCIe MAC */
{ 0x820e0000, 0x020000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
{ 0x820e1000, 0x020400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
{ 0x820e2000, 0x020800, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
{ 0x820e3000, 0x020c00, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
{ 0x820e4000, 0x021000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
{ 0x820e5000, 0x021400, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
{ 0x820ce000, 0x021c00, 0x0000200 }, /* WF_LMAC_TOP (WF_SEC) */
{ 0x820e7000, 0x021e00, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
{ 0x820cf000, 0x022000, 0x0001000 }, /* WF_LMAC_TOP (WF_PF) */
{ 0x820e9000, 0x023400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
{ 0x820ea000, 0x024000, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
{ 0x820eb000, 0x024200, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
{ 0x820ec000, 0x024600, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
{ 0x820ed000, 0x024800, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
{ 0x820ca000, 0x026000, 0x0002000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
{ 0x820d0000, 0x030000, 0x0010000 }, /* WF_LMAC_TOP (WF_WTBLON) */
{ 0x40000000, 0x070000, 0x0010000 }, /* WF_UMAC_SYSRAM */
{ 0x00400000, 0x080000, 0x0010000 }, /* WF_MCU_SYSRAM */
{ 0x00410000, 0x090000, 0x0010000 }, /* WF_MCU_SYSRAM (configure register) */
{ 0x820f0000, 0x0a0000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
{ 0x820f1000, 0x0a0600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
{ 0x820f2000, 0x0a0800, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
{ 0x820f3000, 0x0a0c00, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
{ 0x820f4000, 0x0a1000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
{ 0x820f5000, 0x0a1400, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
{ 0x820f7000, 0x0a1e00, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
{ 0x820f9000, 0x0a3400, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
{ 0x820fa000, 0x0a4000, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
{ 0x820fb000, 0x0a4200, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
{ 0x820fc000, 0x0a4600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
{ 0x820fd000, 0x0a4800, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
{ 0x820c4000, 0x0a8000, 0x0004000 }, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
{ 0x820b0000, 0x0ae000, 0x0001000 }, /* [APB2] WFSYS_ON */
{ 0x80020000, 0x0b0000, 0x0010000 }, /* WF_TOP_MISC_OFF */
{ 0x81020000, 0x0c0000, 0x0010000 }, /* WF_TOP_MISC_ON */
{ 0x7c020000, 0x0d0000, 0x0010000 }, /* CONN_INFRA, wfdma */
{ 0x7c060000, 0x0e0000, 0x0010000 }, /* CONN_INFRA, conn_host_csr_top */
{ 0x7c000000, 0x0f0000, 0x0010000 }, /* CONN_INFRA */
{ 0x70020000, 0x1f0000, 0x0010000 }, /* Reserved for CBTOP, can't switch */
{ 0x7c500000, 0x060000, 0x2000000 }, /* remap */
{ 0x0, 0x0, 0x0 } /* End */
};
int i;
if (addr < 0x200000)
return addr;
mt7925_reg_remap_restore(dev);
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
u32 ofs;
if (addr < fixed_map[i].phys)
continue;
ofs = addr - fixed_map[i].phys;
if (ofs > fixed_map[i].size)
continue;
return fixed_map[i].maps + ofs;
}
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
(addr >= 0x70000000 && addr < 0x78000000) ||
(addr >= 0x7c000000 && addr < 0x7c400000))
return mt7925_reg_map_l1(dev, addr);
return mt7925_reg_map_l2(dev, addr);
}
static u32 mt7925_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7925_reg_addr(dev, offset);
return dev->bus_ops->rr(mdev, addr);
}
static void mt7925_wr(struct mt76_dev *mdev, u32 offset, u32 val)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7925_reg_addr(dev, offset);
dev->bus_ops->wr(mdev, addr, val);
}
static u32 mt7925_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 addr = __mt7925_reg_addr(dev, offset);
return dev->bus_ops->rmw(mdev, addr, mask, val);
}
static int mt7925_dma_init(struct mt792x_dev *dev)
{
int ret;
mt76_dma_attach(&dev->mt76);
ret = mt792x_dma_disable(dev, true);
if (ret)
return ret;
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0,
MT7925_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
if (ret)
return ret;
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
/* command to WM */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7925_TXQ_MCU_WM,
MT7925_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* firmware download */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7925_TXQ_FWDL,
MT7925_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* rx event */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
MT7925_RXQ_MCU_WM, MT7925_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
if (ret)
return ret;
/* rx data */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT7925_RXQ_BAND0, MT7925_RX_RING_SIZE,
MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
if (ret)
return ret;
ret = mt76_init_queues(dev, mt792x_poll_rx);
if (ret < 0)
return ret;
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt792x_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return mt792x_dma_enable(dev);
}
static int mt7925_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
MT_DRV_AMSDU_OFFLOAD,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.token_size = MT7925_TOKEN_SIZE,
.tx_prepare_skb = mt7925e_tx_prepare_skb,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_check = mt7925_rx_check,
.rx_skb = mt7925_queue_rx_skb,
.rx_poll_complete = mt792x_rx_poll_complete,
.sta_add = mt7925_mac_sta_add,
.sta_assoc = mt7925_mac_sta_assoc,
.sta_remove = mt7925_mac_sta_remove,
.update_survey = mt792x_update_channel,
};
static const struct mt792x_hif_ops mt7925_pcie_ops = {
.init_reset = mt7925e_init_reset,
.reset = mt7925e_mac_reset,
.mcu_init = mt7925e_mcu_init,
.drv_own = mt792xe_mcu_drv_pmctrl,
.fw_own = mt792xe_mcu_fw_pmctrl,
};
static const struct mt792x_irq_map irq_map = {
.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
.tx = {
.all_complete_mask = MT_INT_TX_DONE_ALL,
.mcu_complete_mask = MT_INT_TX_DONE_MCU,
},
.rx = {
.data_complete_mask = HOST_RX_DONE_INT_ENA2,
.wm_complete_mask = HOST_RX_DONE_INT_ENA0,
},
};
struct ieee80211_ops *ops;
struct mt76_bus_ops *bus_ops;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
u16 cmd;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(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);
if (ret < 0)
return ret;
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
goto err_free_pci_vec;
if (mt7925_disable_aspm)
mt76_pci_disable_aspm(pdev);
ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7925_ops,
(void *)id->driver_data, &features);
if (!ops) {
ret = -ENOMEM;
goto err_free_pci_vec;
}
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev) {
ret = -ENOMEM;
goto err_free_pci_vec;
}
pci_set_drvdata(pdev, mdev);
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7925_pcie_ops;
dev->irq_map = &irq_map;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
dev->bus_ops = dev->mt76.bus;
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
GFP_KERNEL);
if (!bus_ops) {
ret = -ENOMEM;
goto err_free_dev;
}
bus_ops->rr = mt7925_rr;
bus_ops->wr = mt7925_wr;
bus_ops->rmw = mt7925_rmw;
dev->mt76.bus = bus_ops;
ret = __mt792x_mcu_fw_pmctrl(dev);
if (ret)
goto err_free_dev;
ret = __mt792xe_mcu_drv_pmctrl(dev);
if (ret)
goto err_free_dev;
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
ret = mt792x_wfsys_reset(dev);
if (ret)
goto err_free_dev;
mt76_wr(dev, irq_map.host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto err_free_dev;
ret = mt7925_dma_init(dev);
if (ret)
goto err_free_irq;
ret = mt7925_register_device(dev);
if (ret)
goto err_free_irq;
return 0;
err_free_irq:
devm_free_irq(&pdev->dev, pdev->irq, dev);
err_free_dev:
mt76_free_device(&dev->mt76);
err_free_pci_vec:
pci_free_irq_vectors(pdev);
return ret;
}
static void mt7925_pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
mt7925e_unregister_device(dev);
devm_free_irq(&pdev->dev, pdev->irq, dev);
mt76_free_device(&dev->mt76);
pci_free_irq_vectors(pdev);
}
static int mt7925_pci_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
int i, err;
pm->suspended = true;
flush_work(&dev->reset_work);
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto restore_suspend;
/* always enable deep sleep during suspend to reduce
* power consumption
*/
mt7925_mcu_set_deep_sleep(dev, true);
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
if (err)
goto restore_suspend;
napi_disable(&mdev->tx_napi);
mt76_worker_disable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]);
}
/* wait until dma is idle */
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
/* put dma disabled */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
/* disable interrupt */
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_WFDMA0_HOST_INT_DIS,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
synchronize_irq(pdev->irq);
tasklet_kill(&mdev->irq_tasklet);
err = mt792x_mcu_fw_pmctrl(dev);
if (err)
goto restore_napi;
return 0;
restore_napi:
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
if (!pm->ds_enable)
mt7925_mcu_set_deep_sleep(dev, false);
mt76_connac_mcu_set_hif_suspend(mdev, false);
restore_suspend:
pm->suspended = false;
if (err < 0)
mt792x_reset(&dev->mt76);
return err;
}
static int mt7925_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
int i, err;
err = mt792x_mcu_drv_pmctrl(dev);
if (err < 0)
goto failed;
mt792x_wpdma_reinit_cond(dev);
/* enable interrupt */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
mt76_connac_irq_enable(&dev->mt76,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
/* restore previous ds setting */
if (!pm->ds_enable)
mt7925_mcu_set_deep_sleep(dev, false);
failed:
pm->suspended = false;
if (err < 0)
mt792x_reset(&dev->mt76);
return err;
}
static void mt7925_pci_shutdown(struct pci_dev *pdev)
{
mt7925_pci_remove(pdev);
}
static DEFINE_SIMPLE_DEV_PM_OPS(mt7925_pm_ops, mt7925_pci_suspend, mt7925_pci_resume);
static struct pci_driver mt7925_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7925_pci_device_table,
.probe = mt7925_pci_probe,
.remove = mt7925_pci_remove,
.shutdown = mt7925_pci_shutdown,
.driver.pm = pm_sleep_ptr(&mt7925_pm_ops),
};
module_pci_driver(mt7925_pci_driver);
MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table);
MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
MODULE_FIRMWARE(MT7925_ROM_PATCH);
MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,148 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt7925.h"
#include "../dma.h"
#include "mac.h"
int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct mt76_connac_hw_txp *txp;
struct mt76_txwi_cache *t;
int id, pid;
u8 *txwi = (u8 *)txwi_ptr;
if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL;
if (!wcid)
wcid = &dev->mt76.global_wcid;
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
id = mt76_token_consume(mdev, &t);
if (id < 0)
return id;
if (sta) {
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
if (time_after(jiffies, msta->last_txs + HZ / 4)) {
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
msta->last_txs = jiffies;
}
}
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7925_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key,
pid, qid, 0);
txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE);
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
tx_info->skb = NULL;
return 0;
}
void mt7925_tx_token_put(struct mt792x_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7925_txwi_free(dev, txwi, NULL, false, NULL);
dev->mt76.token_count--;
}
spin_unlock_bh(&dev->mt76.token_lock);
idr_destroy(&dev->mt76.token);
}
int mt7925e_mac_reset(struct mt792x_dev *dev)
{
const struct mt792x_irq_map *irq_map = dev->irq_map;
int i, err;
mt792xe_mcu_drv_pmctrl(dev);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
if (irq_map->rx.data_complete_mask)
napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
if (irq_map->rx.wm_complete_mask)
napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
if (irq_map->rx.wm2_complete_mask)
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
if (irq_map->tx.all_complete_mask)
napi_disable(&dev->mt76.tx_napi);
mt7925_tx_token_put(dev);
idr_init(&dev->mt76.token);
mt792x_wpdma_reset(dev, true);
local_bh_disable();
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
local_bh_enable();
dev->fw_assert = false;
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
mt76_wr(dev, dev->irq_map->host_irq_enable,
dev->irq_map->tx.all_complete_mask |
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt792xe_mcu_fw_pmctrl(dev);
if (err)
return err;
err = __mt792xe_mcu_drv_pmctrl(dev);
if (err)
goto out;
err = mt7925_run_firmware(dev);
if (err)
goto out;
err = mt7925_mcu_set_eeprom(dev);
if (err)
goto out;
err = mt7925_mac_init(dev);
if (err)
goto out;
err = __mt7925_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
return err;
}

View File

@ -0,0 +1,53 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include "mt7925.h"
#include "mcu.h"
static int
mt7925_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *seq)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
enum mt76_mcuq_id txq = MT_MCUQ_WM;
int ret;
ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq);
if (ret)
return ret;
mdev->mcu.timeout = 3 * HZ;
if (cmd == MCU_CMD(FW_SCATTER))
txq = MT_MCUQ_FWDL;
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0);
}
int mt7925e_mcu_init(struct mt792x_dev *dev)
{
static const struct mt76_mcu_ops mt7925_mcu_ops = {
.headroom = sizeof(struct mt76_connac2_mcu_txd),
.mcu_skb_send_msg = mt7925_mcu_send_message,
.mcu_parse_response = mt7925_mcu_parse_response,
};
int err;
dev->mt76.mcu_ops = &mt7925_mcu_ops;
err = mt792xe_mcu_fw_pmctrl(dev);
if (err)
return err;
err = __mt792xe_mcu_drv_pmctrl(dev);
if (err)
return err;
mt76_rmw_field(dev, MT_PCIE_MAC_PM, MT_PCIE_MAC_PM_L0S_DIS, 1);
err = mt7925_run_firmware(dev);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
return err;
}

View File

@ -0,0 +1,92 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2023 MediaTek Inc. */
#ifndef __MT7925_REGS_H
#define __MT7925_REGS_H
#include "../mt792x_regs.h"
#define MT_MDP_BASE 0x820cc800
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
#define MT_MDP_DCR0 MT_MDP(0x000)
#define MT_MDP_DCR0_DAMSDU_EN BIT(15)
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
#define MT_MDP_DCR1 MT_MDP(0x004)
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
#define MT_MDP_BNRCFR0(_band) MT_MDP(0x090 + ((_band) << 8))
#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4)
#define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6)
#define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8)
#define MT_MDP_BNRCFR1(_band) MT_MDP(0x094 + ((_band) << 8))
#define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22)
#define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27)
#define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29)
#define MT_MDP_TO_HIF 0
#define MT_MDP_TO_WM 1
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x228)
#define MT_WFDMA0_HOST_INT_DIS MT_WFDMA0(0x22c)
#define HOST_RX_DONE_INT_ENA4 BIT(12)
#define HOST_RX_DONE_INT_ENA5 BIT(13)
#define HOST_RX_DONE_INT_ENA6 BIT(14)
#define HOST_RX_DONE_INT_ENA7 BIT(15)
#define HOST_RX_DONE_INT_ENA8 BIT(16)
#define HOST_RX_DONE_INT_ENA9 BIT(17)
#define HOST_RX_DONE_INT_ENA10 BIT(18)
#define HOST_RX_DONE_INT_ENA11 BIT(19)
#define HOST_TX_DONE_INT_ENA15 BIT(25)
#define HOST_TX_DONE_INT_ENA16 BIT(26)
#define HOST_TX_DONE_INT_ENA17 BIT(27)
/* WFDMA interrupt */
#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
#define MT_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0
#define MT_INT_RX_DONE_WM2 HOST_RX_DONE_INT_ENA1
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_DATA | \
MT_INT_RX_DONE_WM | \
MT_INT_RX_DONE_WM2)
#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \
HOST_TX_DONE_INT_ENA17)
#define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16
#define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \
MT_INT_TX_DONE_FWDL)
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \
MT_INT_TX_DONE_BAND0 | \
GENMASK(18, 4))
#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x500)
#define MT_INFRA_CFG_BASE 0xd1000
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
#define MT_HIF_REMAP_L1 0x155024
#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
#define MT_HIF_REMAP_BASE_L1 0x130000
#define MT_HIF_REMAP_L2 0x0120
#if IS_ENABLED(CONFIG_MT76_DEV)
#define MT_HIF_REMAP_BASE_L2 (0x7c500000 - (0x7c000000 - 0x18000000))
#else
#define MT_HIF_REMAP_BASE_L2 0x18500000
#endif
#define MT_WFSYS_SW_RST_B 0x7c000140
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
#endif

View File

@ -0,0 +1,332 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2023 MediaTek Inc. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "mt7925.h"
#include "mcu.h"
#include "mac.h"
static const struct usb_device_id mt7925u_device_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7925, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
{ },
};
static int
mt7925u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *seq)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
u32 pad, ep;
int ret;
ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq);
if (ret)
return ret;
mdev->mcu.timeout = 3 * HZ;
if (cmd != MCU_CMD(FW_SCATTER))
ep = MT_EP_OUT_INBAND_CMD;
else
ep = MT_EP_OUT_AC_BE;
mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
pad = round_up(skb->len, 4) + 4 - skb->len;
__skb_put_zero(skb, pad);
ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
1000, ep);
dev_kfree_skb(skb);
return ret;
}
static int mt7925u_mcu_init(struct mt792x_dev *dev)
{
static const struct mt76_mcu_ops mcu_ops = {
.headroom = MT_SDIO_HDR_SIZE +
sizeof(struct mt76_connac2_mcu_txd),
.tailroom = MT_USB_TAIL_SIZE,
.mcu_skb_send_msg = mt7925u_mcu_send_message,
.mcu_parse_response = mt7925_mcu_parse_response,
};
int ret;
dev->mt76.mcu_ops = &mcu_ops;
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
ret = mt7925_run_firmware(dev);
if (ret)
return ret;
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
return 0;
}
static int mt7925u_mac_reset(struct mt792x_dev *dev)
{
int err;
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&dev->mt76.tx_worker);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
mt792xu_wfsys_reset(dev);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
err = mt76u_resume_rx(&dev->mt76);
if (err)
goto out;
err = mt792xu_mcu_power_on(dev);
if (err)
goto out;
err = mt792xu_dma_init(dev, false);
if (err)
goto out;
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7925_run_firmware(dev);
if (err)
goto out;
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
err = mt7925_mcu_set_eeprom(dev);
if (err)
goto out;
err = mt7925_mac_init(dev);
if (err)
goto out;
err = __mt7925_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
return err;
}
static int mt7925u_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = MT_SDIO_TXD_SIZE,
.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
MT_DRV_AMSDU_OFFLOAD,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.tx_prepare_skb = mt7925_usb_sdio_tx_prepare_skb,
.tx_complete_skb = mt7925_usb_sdio_tx_complete_skb,
.tx_status_data = mt7925_usb_sdio_tx_status_data,
.rx_skb = mt7925_queue_rx_skb,
.rx_check = mt7925_rx_check,
.sta_add = mt7925_mac_sta_add,
.sta_assoc = mt7925_mac_sta_assoc,
.sta_remove = mt7925_mac_sta_remove,
.update_survey = mt792x_update_channel,
};
static const struct mt792x_hif_ops hif_ops = {
.mcu_init = mt7925u_mcu_init,
.init_reset = mt792xu_init_reset,
.reset = mt7925u_mac_reset,
};
static struct mt76_bus_ops bus_ops = {
.rr = mt792xu_rr,
.wr = mt792xu_wr,
.rmw = mt792xu_rmw,
.read_copy = mt76u_read_copy,
.write_copy = mt792xu_copy,
.type = MT76_BUS_USB,
};
struct usb_device *udev = interface_to_usbdev(usb_intf);
struct ieee80211_ops *ops;
struct ieee80211_hw *hw;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7925_ops,
(void *)id->driver_info, &features);
if (!ops)
return -ENOMEM;
ops->stop = mt792xu_stop;
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &hif_ops;
udev = usb_get_dev(udev);
usb_reset_device(udev);
usb_set_intfdata(usb_intf, dev);
ret = __mt76u_init(mdev, usb_intf, &bus_ops);
if (ret < 0)
goto error;
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
ret = mt792xu_wfsys_reset(dev);
if (ret)
goto error;
}
ret = mt792xu_mcu_power_on(dev);
if (ret)
goto error;
ret = mt76u_alloc_mcu_queue(&dev->mt76);
if (ret)
goto error;
ret = mt76u_alloc_queues(&dev->mt76);
if (ret)
goto error;
ret = mt792xu_dma_init(dev, false);
if (ret)
goto error;
hw = mt76_hw(dev);
/* check hw sg support in order to enable AMSDU */
hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
ret = mt7925_register_device(dev);
if (ret)
goto error;
return 0;
error:
mt76u_queues_deinit(&dev->mt76);
usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf));
mt76_free_device(&dev->mt76);
return ret;
}
#ifdef CONFIG_PM
static int mt7925u_suspend(struct usb_interface *intf, pm_message_t state)
{
struct mt792x_dev *dev = usb_get_intfdata(intf);
struct mt76_connac_pm *pm = &dev->pm;
int err;
pm->suspended = true;
flush_work(&dev->reset_work);
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
if (err)
goto failed;
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
return 0;
failed:
pm->suspended = false;
if (err < 0)
mt792x_reset(&dev->mt76);
return err;
}
static int mt7925u_resume(struct usb_interface *intf)
{
struct mt792x_dev *dev = usb_get_intfdata(intf);
struct mt76_connac_pm *pm = &dev->pm;
bool reinit = true;
int err, i;
for (i = 0; i < 10; i++) {
u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
reinit = false;
break;
}
if (val & MT_WF_SW_SER_DONE_SUSPEND) {
mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
break;
}
msleep(20);
}
if (reinit || mt792x_dma_need_reinit(dev)) {
err = mt792xu_dma_init(dev, true);
if (err)
goto failed;
}
err = mt76u_resume_rx(&dev->mt76);
if (err < 0)
goto failed;
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
failed:
pm->suspended = false;
if (err < 0)
mt792x_reset(&dev->mt76);
return err;
}
#endif /* CONFIG_PM */
MODULE_DEVICE_TABLE(usb, mt7925u_device_table);
MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
MODULE_FIRMWARE(MT7925_ROM_PATCH);
static struct usb_driver mt7925u_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7925u_device_table,
.probe = mt7925u_probe,
.disconnect = mt792xu_disconnect,
#ifdef CONFIG_PM
.suspend = mt7925u_suspend,
.resume = mt7925u_resume,
.reset_resume = mt7925u_resume,
#endif /* CONFIG_PM */
.soft_unbind = 1,
.disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt7925u_driver);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -25,6 +25,8 @@
#define MT792x_FW_TAG_FEATURE 4
#define MT792x_FW_CAP_CNM BIT(7)
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 11
@ -36,9 +38,14 @@
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
#define MT7925_ROM_PATCH "mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin"
#define MT792x_SDIO_HDR_TX_BYTES GENMASK(15, 0)
#define MT792x_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
struct mt792x_vif;
struct mt792x_sta;
@ -61,6 +68,14 @@ enum {
MT792x_CLC_MAX_NUM,
};
enum mt792x_reg_power_type {
MT_AP_UNSET = 0,
MT_AP_DEFAULT,
MT_AP_LPI,
MT_AP_SP,
MT_AP_VLP,
};
DECLARE_EWMA(avg_signal, 10, 8)
struct mt792x_sta {
@ -91,7 +106,6 @@ struct mt792x_vif {
struct ewma_rssi rssi;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct ieee80211_chanctx_conf *ctx;
};
struct mt792x_phy {
@ -113,6 +127,8 @@ struct mt792x_phy {
struct mt76_mib_stats mib;
u8 sta_work_count;
u8 clc_chan_conf;
enum mt792x_reg_power_type power_type;
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
@ -120,6 +136,7 @@ struct mt792x_phy {
void *acpisar;
#endif
void *clc[MT792x_CLC_MAX_NUM];
u64 chip_cap;
struct work_struct roc_work;
struct timer_list roc_timer;
@ -229,6 +246,7 @@ static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev)
#define mt792x_mutex_release(dev) \
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
void mt792x_stop(struct ieee80211_hw *hw);
void mt792x_pm_wake_work(struct work_struct *work);
void mt792x_pm_power_save_work(struct work_struct *work);
void mt792x_reset(struct mt76_dev *mdev);
@ -308,6 +326,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
switch (mt76_chip(&dev->mt76)) {
case 0x7922:
return MT7922_FIRMWARE_WM;
case 0x7925:
return MT7925_FIRMWARE_WM;
default:
return MT7921_FIRMWARE_WM;
}
@ -318,6 +338,8 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev)
switch (mt76_chip(&dev->mt76)) {
case 0x7922:
return MT7922_ROM_PATCH;
case 0x7925:
return MT7925_ROM_PATCH;
default:
return MT7921_ROM_PATCH;
}
@ -337,6 +359,20 @@ void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val);
u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len);
void mt792xu_disconnect(struct usb_interface *usb_intf);
void mt792xu_stop(struct ieee80211_hw *hw);
static inline void
mt792x_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
int type)
{
u32 hdr, len;
len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr);
hdr = FIELD_PREP(MT792x_SDIO_HDR_TX_BYTES, len) |
FIELD_PREP(MT792x_SDIO_HDR_PKT_TYPE, type);
put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
}
int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);
int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);

View File

@ -91,6 +91,28 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
}
EXPORT_SYMBOL_GPL(mt792x_tx);
void mt792x_stop(struct ieee80211_hw *hw)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt792x_phy *phy = mt792x_hw_phy(hw);
cancel_delayed_work_sync(&phy->mt76->mac_work);
cancel_delayed_work_sync(&dev->pm.ps_work);
cancel_work_sync(&dev->pm.wake_work);
cancel_work_sync(&dev->reset_work);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
if (is_mt7921(&dev->mt76)) {
mt792x_mutex_acquire(dev);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
mt792x_mutex_release(dev);
}
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
}
EXPORT_SYMBOL_GPL(mt792x_stop);
void mt792x_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@ -115,7 +137,7 @@ void mt792x_remove_interface(struct ieee80211_hw *hw,
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
}
EXPORT_SYMBOL_GPL(mt792x_remove_interface);
@ -243,7 +265,7 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mvif->ctx = ctx;
mvif->mt76.ctx = ctx;
mutex_unlock(&dev->mt76.mutex);
return 0;
@ -259,7 +281,7 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mvif->ctx = NULL;
mvif->mt76.ctx = NULL;
mutex_unlock(&dev->mt76.mutex);
}
EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx);
@ -358,7 +380,7 @@ void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (sset != ETH_SS_STATS)
return;
memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));
memcpy(data, mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));
data += sizeof(mt792x_gstrings_stats);
page_pool_ethtool_stats_get_strings(data);

View File

@ -88,25 +88,44 @@ EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete);
#define PREFETCH(base, depth) ((base) << 16 | (depth))
static void mt792x_dma_prefetch(struct mt792x_dev *dev)
{
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
if (is_mt7925(&dev->mt76)) {
/* rx ring */
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
/* tx ring */
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x10));
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0200, 0x10));
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0300, 0x10));
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
} else {
/* rx ring */
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4));
/* tx ring */
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
}
}
int mt792x_dma_enable(struct mt792x_dev *dev)
{
if (is_mt7925(&dev->mt76))
mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
/* configure perfetch settings */
mt792x_dma_prefetch(dev);

View File

@ -287,6 +287,15 @@ int mt792xu_init_reset(struct mt792x_dev *dev)
}
EXPORT_SYMBOL_GPL(mt792xu_init_reset);
void mt792xu_stop(struct ieee80211_hw *hw)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
mt76u_stop_tx(&dev->mt76);
mt792x_stop(hw);
}
EXPORT_SYMBOL_GPL(mt792xu_stop);
void mt792xu_disconnect(struct usb_interface *usb_intf)
{
struct mt792x_dev *dev = usb_get_intfdata(usb_intf);

View File

@ -54,23 +54,31 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev,
dev = container_of(mphy->dev, struct mt7996_dev, mt76);
/* select TX blink mode, 2: only data frames */
mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2);
mt76_rmw_field(dev, MT_TMAC_TCR0(mphy->band_idx), MT_TMAC_TCR0_TX_BLINK, 2);
/* enable LED */
mt76_wr(dev, MT_LED_EN(0), 1);
mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);
/* set LED Tx blink on/off time */
val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) |
FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off);
mt76_wr(dev, MT_LED_TX_BLINK(0), val);
mt76_wr(dev, MT_LED_TX_BLINK(mphy->band_idx), val);
/* turn LED off */
if (delay_off == 0xff && delay_on == 0x0) {
val = MT_LED_CTRL_POLARITY | MT_LED_CTRL_KICK;
} else {
/* control LED */
val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
if (mphy->band_idx == MT_BAND1)
val |= MT_LED_CTRL_BLINK_BAND_SEL;
}
/* control LED */
val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
if (mphy->leds.al)
val |= MT_LED_CTRL_POLARITY;
mt76_wr(dev, MT_LED_CTRL(0), val);
mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK);
mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);
mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);
}
static int mt7996_led_set_blink(struct led_classdev *led_cdev,
@ -173,6 +181,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
wiphy->reg_notifier = mt7996_regd_notifier;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy->mbssid_max_interfaces = 16;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
@ -196,6 +205,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
hw->max_tx_fragments = 4;
@ -223,6 +233,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
}
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness;
phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink;
}
mt76_set_stream_caps(phy->mt76, true);
mt7996_set_stream_vht_txbf_caps(phy);
mt7996_set_stream_he_eht_caps(phy);
@ -258,6 +274,11 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
set = FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
/* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
*/
mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
}
static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
@ -733,16 +754,17 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
val = max_t(u8, sts - 1, 3);
eht_cap_elem->phy_cap_info[0] |=
u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
u8_encode_bits(u8_get_bits(val, BIT(0)),
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
eht_cap_elem->phy_cap_info[1] =
u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),
u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)),
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |
u8_encode_bits(sts - 1,
u8_encode_bits(val,
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) |
u8_encode_bits(sts - 1,
u8_encode_bits(val,
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
eht_cap_elem->phy_cap_info[2] =
@ -869,12 +891,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
mt7996_init_wiphy(hw);
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink;
}
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)

View File

@ -433,7 +433,9 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
case IEEE80211_STA_RX_BW_160:
status->bw = RATE_INFO_BW_160;
break;
/* rxv reports bw 320-1 and 320-2 separately */
case IEEE80211_STA_RX_BW_320:
case IEEE80211_STA_RX_BW_320 + 1:
status->bw = RATE_INFO_BW_320;
break;
default:
@ -948,15 +950,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (!wcid)
wcid = &dev->mt76.global_wcid;
if (sta) {
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
if (time_after(jiffies, msta->jiffies + HZ / 4)) {
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
msta->jiffies = jiffies;
}
}
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
@ -991,11 +984,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
txp->fw.token = cpu_to_le16(id);
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
else
txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
tx_info->skb = DMA_DUMMY_DATA;
txp->fw.rept_wds_wcid = cpu_to_le16(sta ? wcid->idx : 0xfff);
tx_info->skb = NULL;
/* pass partial skb header to fw */
tx_info->buf[1].len = MT_CT_PARSE_LEN;
@ -1006,22 +997,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
static void
mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
{
struct mt7996_sta *msta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
u16 fc, tid;
u32 val;
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
return;
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
if (tid >= 6) /* skip VO queue */
return;
val = le32_to_cpu(txwi[2]);
fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
if (is_8023) {
fc = IEEE80211_FTYPE_DATA |
(sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
} else {
/* No need to get precise TID for Action/Management Frame,
* since it will not meet the following Frame Control
* condition anyway.
*/
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control) &
(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
}
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
return;
@ -1049,9 +1053,9 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
wcid_idx = wcid->idx;
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
mt7996_tx_check_aggr(sta, txwi);
mt7996_tx_check_aggr(sta, t->skb);
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
}
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
@ -1070,6 +1074,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid;
LIST_HEAD(free_list);
struct sk_buff *skb, *tmp;
void *end = data + len;
@ -1088,7 +1093,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
}
if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
return;
total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
@ -1104,7 +1109,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
info = le32_to_cpu(*cur_info);
if (info & MT_TXFREE_INFO_PAIR) {
struct mt7996_sta *msta;
struct mt76_wcid *wcid;
u16 idx;
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
@ -1120,10 +1124,21 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
&mdev->sta_poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
continue;
}
} else if (info & MT_TXFREE_INFO_HEADER) {
u32 tx_retries = 0, tx_failed = 0;
if (info & MT_TXFREE_INFO_HEADER)
if (!wcid)
continue;
tx_retries =
FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
tx_failed = tx_retries +
!!FIELD_GET(MT_TXFREE_INFO_STAT, info);
wcid->stats.tx_retries += tx_retries;
wcid->stats.tx_failed += tx_failed;
continue;
}
for (i = 0; i < 2; i++) {
msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
@ -1167,22 +1182,31 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
bool cck = false;
u32 txrate, txs, mode, stbc;
mt76_tx_status_lock(mdev, &list);
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
if (!skb)
goto out_no_skb;
txs = le32_to_cpu(txs_data[0]);
info = IEEE80211_SKB_CB(skb);
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
mt76_tx_status_lock(mdev, &list);
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
info->status.ampdu_len = 1;
info->status.ampdu_ack_len = !!(info->flags &
IEEE80211_TX_STAT_ACK);
if (skb) {
info = IEEE80211_SKB_CB(skb);
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.rates[0].idx = -1;
info->status.ampdu_len = 1;
info->status.ampdu_ack_len =
!!(info->flags & IEEE80211_TX_STAT_ACK);
info->status.rates[0].idx = -1;
}
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && 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);
@ -1282,9 +1306,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
wcid->rate = rate;
out:
mt76_tx_status_skb_done(mdev, skb, &list);
out_no_skb:
if (skb)
mt76_tx_status_skb_done(mdev, skb, &list);
mt76_tx_status_unlock(mdev, &list);
return !!skb;
@ -1298,13 +1321,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
u16 wcidx;
u8 pid;
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
return;
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
if (pid < MT_PACKET_ID_FIRST)
if (pid < MT_PACKET_ID_NO_SKB)
return;
if (wcidx >= mt7996_wtbl_size(dev))
@ -2191,6 +2211,11 @@ void mt7996_mac_work(struct work_struct *work)
mphy->mac_work_count = 0;
mt7996_mac_update_stats(phy);
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
}
}
mutex_unlock(&mphy->dev->mutex);

View File

@ -190,7 +190,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
mvif->mt76.omac_idx = idx;
mvif->phy = phy;
mvif->mt76.band_idx = band_idx;
mvif->mt76.wmm_idx = band_idx;
mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
ret = mt7996_mcu_add_dev_info(phy, vif, true);
if (ret)
@ -207,7 +207,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
mvif->sta.wcid.phy_idx = band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
mt76_wcid_init(&mvif->sta.wcid);
mt7996_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -248,8 +248,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
struct mt7996_phy *phy = mt7996_hw_phy(hw);
int idx = msta->wcid.idx;
mt7996_mcu_add_bss_info(phy, vif, false);
mt7996_mcu_add_sta(dev, vif, NULL, false);
mt7996_mcu_add_bss_info(phy, vif, false);
if (vif == phy->monitor_vif)
phy->monitor_vif = NULL;
@ -268,7 +268,7 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
}
int mt7996_set_channel(struct mt7996_phy *phy)
@ -414,10 +414,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const struct ieee80211_tx_queue_params *params)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
const u8 mq_to_aci[] = {
[IEEE80211_AC_VO] = 3,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_BE] = 0,
[IEEE80211_AC_BK] = 1,
};
/* firmware uses access class index */
mvif->queue_params[mq_to_aci[queue]] = *params;
/* no need to update right away, we'll get BSS_CHANGED_QOS */
queue = mt76_connac_lmac_mapping(queue);
mvif->queue_params[queue] = *params;
return 0;
}
@ -564,17 +570,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
/* station mode uses BSSID to map the wlan entry to a peer,
* and then peer references bss_info_rfch to set bandwidth cap.
*/
if (changed & BSS_CHANGED_BSSID &&
vif->type == NL80211_IFTYPE_STATION) {
bool join = !is_zero_ether_addr(info->bssid);
mt7996_mcu_add_bss_info(phy, vif, join);
mt7996_mcu_add_sta(dev, vif, NULL, join);
if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
(changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
(changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
mt7996_mcu_add_bss_info(phy, vif, true);
mt7996_mcu_add_sta(dev, vif, NULL, true);
}
if (changed & BSS_CHANGED_ASSOC)
mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
if (changed & BSS_CHANGED_ERP_CTS_PROT)
mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
@ -595,11 +597,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
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);
}
/* ensure that enable txcmd_mode after bss_info */
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7996_mcu_set_tx(dev, vif);
@ -618,8 +615,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
}
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
changed & BSS_CHANGED_FILS_DISCOVERY)
if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY))
mt7996_mcu_beacon_inband_discov(dev, vif, changed);
if (changed & BSS_CHANGED_MU_GROUPS)
@ -660,7 +657,6 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->wcid.idx = idx;
msta->wcid.phy_idx = band_idx;
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->jiffies = jiffies;
ewma_avg_signal_init(&msta->avg_ack_signal);
@ -972,6 +968,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct rate_info *txrate = &msta->wcid.rate;
@ -992,11 +989,31 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
sinfo->tx_failed = msta->wcid.stats.tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
sinfo->tx_retries = msta->wcid.stats.tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
sinfo->ack_signal = (s8)msta->ack_signal;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
sinfo->tx_packets = msta->wcid.stats.tx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
sinfo->rx_packets = msta->wcid.stats.rx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
}
}
static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
@ -1192,7 +1209,7 @@ void mt7996_get_et_strings(struct ieee80211_hw *hw,
u32 sset, u8 *data)
{
if (sset == ETH_SS_STATS)
memcpy(data, *mt7996_gstrings_stats,
memcpy(data, mt7996_gstrings_stats,
sizeof(mt7996_gstrings_stats));
}

View File

@ -324,8 +324,10 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
static void
mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
if (vif->bss_conf.csa_active)
ieee80211_csa_finish(vif);
if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
return;
ieee80211_csa_finish(vif);
}
static void
@ -399,7 +401,7 @@ mt7996_mcu_rx_log_message(struct mt7996_dev *dev, struct sk_buff *skb)
static void
mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
if (!vif->bss_conf.color_change_active)
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;
ieee80211_color_change_finish(vif);
@ -447,6 +449,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
static void
mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
struct mt7996_mcu_all_sta_info_event *res;
u16 i;
skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
u8 ac;
u16 wlan_idx;
struct mt76_wcid *wcid;
switch (le16_to_cpu(res->tag)) {
case UNI_ALL_STA_TXRX_ADM_STAT:
wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
break;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
wcid->stats.tx_bytes +=
le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
wcid->stats.rx_bytes +=
le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
}
break;
case UNI_ALL_STA_TXRX_MSDU_COUNT:
wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
break;
wcid->stats.tx_packets +=
le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
wcid->stats.rx_packets +=
le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
break;
default:
break;
}
}
}
static void
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -491,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_RDD_REPORT:
mt7996_mcu_rx_radar_detected(dev, skb);
break;
case MCU_UNI_EVENT_ALL_STA_INFO:
mt7996_mcu_rx_all_sta_info_event(dev, skb);
break;
default:
break;
}
@ -600,6 +653,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
}
static void
mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct mt7996_phy *phy, int enable)
{
struct bss_info_uni_mbssid *mbssid;
struct tlv *tlv;
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid));
mbssid = (struct bss_info_uni_mbssid *)tlv;
if (enable && vif->bss_conf.bssid_indicator) {
mbssid->max_indicator = vif->bss_conf.bssid_indicator;
mbssid->mbss_idx = vif->bss_conf.bssid_index;
mbssid->tx_bss_omac_idx = 0;
}
}
static void
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct mt7996_phy *phy)
@ -866,6 +937,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
/* this tag is necessary no matter if the vif is MLD */
mt7996_mcu_bss_mld_tlv(skb, vif);
}
mt7996_mcu_bss_mbssid_tlv(skb, vif, phy, enable);
out:
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
@ -1152,6 +1226,8 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
muru->ofdma_ul.uo_ra =
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
muru->ofdma_ul.rx_ctrl_frame_to_mbss =
HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
}
static inline bool
@ -1624,6 +1700,132 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
MCU_WM_UNI_CMD(RA), true);
}
static int
mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *data, u32 field)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct sta_phy *phy = data;
struct sta_rec_ra_fixed *ra;
struct sk_buff *skb;
struct tlv *tlv;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
&msta->wcid,
MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
ra = (struct sta_rec_ra_fixed *)tlv;
switch (field) {
case RATE_PARAM_AUTO:
break;
case RATE_PARAM_FIXED:
case RATE_PARAM_FIXED_MCS:
case RATE_PARAM_FIXED_GI:
case RATE_PARAM_FIXED_HE_LTF:
if (phy)
ra->phy = *phy;
break;
default:
break;
}
ra->field = cpu_to_le32(field);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
static int
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
enum nl80211_band band = chandef->chan->band;
struct sta_phy phy = {};
int ret, nrates = 0;
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
do { \
u8 i, gi = mask->control[band]._gi; \
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
phy.sgi = gi; \
phy.he_ltf = mask->control[band].he_ltf; \
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
if (!mask->control[band]._mcs[i]) \
continue; \
nrates += hweight16(mask->control[band]._mcs[i]); \
phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
if (_ht) \
phy.mcs += 8 * i; \
} \
} while (0)
if (sta->deflink.he_cap.has_he) {
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
} else if (sta->deflink.vht_cap.vht_supported) {
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
} else if (sta->deflink.ht_cap.ht_supported) {
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
} else {
nrates = hweight32(mask->control[band].legacy);
phy.mcs = ffs(mask->control[band].legacy) - 1;
}
#undef __sta_phy_bitrate_mask_check
/* fall back to auto rate control */
if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
mask->control[band].he_gi == GENMASK(7, 0) &&
mask->control[band].he_ltf == GENMASK(7, 0) &&
nrates != 1)
return 0;
/* fixed single rate */
if (nrates == 1) {
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
RATE_PARAM_FIXED_MCS);
if (ret)
return ret;
}
/* fixed GI */
if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
mask->control[band].he_gi != GENMASK(7, 0)) {
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
u32 addr;
/* firmware updates only TXCMD but doesn't take WTBL into
* account, so driver should update here to reflect the
* actual txrate hardware sends out.
*/
addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
if (sta->deflink.he_cap.has_he)
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
else
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
RATE_PARAM_FIXED_GI);
if (ret)
return ret;
}
/* fixed HE_LTF */
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
RATE_PARAM_FIXED_HE_LTF);
if (ret)
return ret;
}
return 0;
}
static void
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
@ -1733,6 +1935,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct sk_buff *skb;
int ret;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
&msta->wcid,
@ -1752,8 +1955,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
*/
mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
if (ret)
return ret;
return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
}
static int
@ -1995,6 +2202,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
}
static void
mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn,
struct ieee80211_mutable_offsets *offs)
{
struct bss_bcn_mbss_tlv *mbss;
const struct element *elem;
struct tlv *tlv;
if (!vif->bss_conf.bssid_indicator)
return;
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss));
mbss = (struct bss_bcn_mbss_tlv *)tlv;
mbss->offset[0] = cpu_to_le16(offs->tim_offset);
mbss->bitmap = cpu_to_le32(1);
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
&skb->data[offs->mbssid_off],
skb->len - offs->mbssid_off) {
const struct element *sub_elem;
if (elem->datalen < 2)
continue;
for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
const struct ieee80211_bssid_index *idx;
const u8 *idx_ie;
/* not a valid BSS profile */
if (sub_elem->id || sub_elem->datalen < 4)
continue;
/* Find WLAN_EID_MULTI_BSSID_IDX
* in the merged nontransmitted profile
*/
idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
sub_elem->data, sub_elem->datalen);
if (!idx_ie || idx_ie[1] < sizeof(*idx))
continue;
idx = (void *)(idx_ie + 2);
if (!idx->bssid_index || idx->bssid_index > 31)
continue;
mbss->offset[idx->bssid_index] = cpu_to_le16(idx_ie -
skb->data);
mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
}
}
}
static void
mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct sk_buff *rskb, struct sk_buff *skb,
@ -2016,7 +2276,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
bcn->bcc_ie_pos = cpu_to_le16(offset - 3);
}
buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
buf = (u8 *)bcn + sizeof(*bcn);
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
BSS_CHANGED_BEACON);
@ -2034,26 +2294,25 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
struct sk_buff *skb, *rskb;
struct tlv *tlv;
struct bss_bcn_content_tlv *bcn;
int len;
if (vif->bss_conf.nontransmitted)
return 0;
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
MT7996_BEACON_UPDATE_SIZE);
MT7996_MAX_BSS_OFFLOAD_SIZE);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
tlv = mt7996_mcu_add_uni_tlv(rskb,
UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn));
bcn = (struct bss_bcn_content_tlv *)tlv;
bcn->enable = en;
if (!en)
goto out;
skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
if (!skb)
if (!skb) {
dev_kfree_skb(rskb);
return -EINVAL;
}
if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
if (skb->len > MT7996_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return -EINVAL;
}
@ -2061,11 +2320,18 @@ 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);
len = sizeof(*bcn) + MT_TXD_SIZE + skb->len;
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
bcn = (struct bss_bcn_content_tlv *)tlv;
bcn->enable = en;
if (!en)
goto out;
mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
/* TODO: subtag - 11v MBSSID */
mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
dev_kfree_skb(skb);
out:
dev_kfree_skb(skb);
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
@ -2086,9 +2352,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
struct sk_buff *rskb, *skb = NULL;
struct tlv *tlv;
u8 *buf, interval;
int len;
if (vif->bss_conf.nontransmitted)
return 0;
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
MT7996_INBAND_FRAME_SIZE);
MT7996_MAX_BSS_OFFLOAD_SIZE);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
@ -2102,11 +2372,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
}
if (!skb)
if (!skb) {
dev_kfree_skb(rskb);
return -EINVAL;
}
if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) {
if (skb->len > MT7996_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return -EINVAL;
}
@ -2116,7 +2389,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
info->band = band;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov));
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
discov = (struct bss_inband_discovery_tlv *)tlv;
discov->tx_mode = OFFLOAD_TX_MODE_SU;
@ -2127,7 +2402,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
discov->enable = true;
discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
buf = (u8 *)tlv + sizeof(*discov);
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
@ -2679,7 +2954,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
e = (struct edca *)tlv;
e->set = WMM_PARAM_SET;
e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS;
e->queue = ac;
e->aifs = q->aifs;
e->txop = cpu_to_le16(q->txop);
@ -2960,10 +3235,10 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
.channel_band = ch_band[chandef->chan->band],
};
if (tag == UNI_CHANNEL_RX_PATH ||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
req.switch_reason = CH_SWITCH_NORMAL;
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
NL80211_IFTYPE_AP))
@ -3307,8 +3582,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en));
req_mod_en = (struct bf_mod_en_ctrl *)tlv;
req_mod_en->bf_num = 2;
req_mod_en->bf_bitmap = GENMASK(0, 0);
req_mod_en->bf_num = 3;
req_mod_en->bf_bitmap = GENMASK(2, 0);
break;
}
default:
@ -3548,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
int cmd)
{
struct {
u8 _rsv[4];
/* fixed field */
u8 bss;
u8 _rsv[3];
__le16 tag;
__le16 len;
@ -3566,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
u8 exponent;
u8 is_ap;
u8 agrt_params;
u8 __rsv2[135];
u8 __rsv2[23];
} __packed req = {
.tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE),
.len = cpu_to_le16(sizeof(req) - 4),
@ -3576,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
.flowid = flow->id,
.peer_id = cpu_to_le16(flow->wcid),
.duration = flow->duration,
.bss = mvif->mt76.idx,
.bss_idx = mvif->mt76.idx,
.start_tsf = cpu_to_le64(flow->tsf),
.mantissa = flow->mantissa,
@ -3786,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
sizeof(req), true);
}
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
{
struct mt7996_dev *dev = phy->dev;
struct {
u8 _rsv[4];
__le16 tag;
__le16 len;
} __packed req = {
.tag = cpu_to_le16(tag),
.len = cpu_to_le16(sizeof(req) - 4),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
&req, sizeof(req), false);
}

View File

@ -153,6 +153,32 @@ struct mt7996_mcu_mib {
__le64 data;
} __packed;
struct mt7996_mcu_all_sta_info_event {
u8 rsv[4];
__le16 tag;
__le16 len;
u8 more;
u8 rsv2;
__le16 sta_num;
u8 rsv3[2];
union {
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_bytes[IEEE80211_NUM_ACS];
__le32 rx_bytes[IEEE80211_NUM_ACS];
} adm_stat[0];
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_msdu_cnt;
__le32 rx_msdu_cnt;
} msdu_cnt[0];
};
} __packed;
enum mt7996_chan_mib_offs {
UNI_MIB_OBSS_AIRTIME = 26,
UNI_MIB_NON_WIFI_TIME = 27,
@ -270,8 +296,6 @@ struct bss_inband_discovery_tlv {
u8 enable;
__le16 wcid;
__le16 prob_rsp_len;
#define MAX_INBAND_FRAME_SIZE 512
u8 pkt[MAX_INBAND_FRAME_SIZE];
} __packed;
struct bss_bcn_content_tlv {
@ -283,8 +307,6 @@ struct bss_bcn_content_tlv {
u8 enable;
u8 type;
__le16 pkt_len;
#define MAX_BEACON_SIZE 512
u8 pkt[MAX_BEACON_SIZE];
} __packed;
struct bss_bcn_cntdwn_tlv {
@ -591,13 +613,14 @@ enum {
sizeof(struct sta_rec_hdr_trans) + \
sizeof(struct tlv))
#define MT7996_MAX_BEACON_SIZE 1342
#define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \
sizeof(struct bss_bcn_content_tlv) + \
MT_TXD_SIZE + \
sizeof(struct bss_bcn_cntdwn_tlv) + \
sizeof(struct bss_bcn_mbss_tlv))
#define MT7996_INBAND_FRAME_SIZE (sizeof(struct bss_req_hdr) + \
sizeof(struct bss_inband_discovery_tlv))
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
MT7996_BEACON_UPDATE_SIZE)
enum {
UNI_BAND_CONFIG_RADIO_ENABLE,

View File

@ -110,7 +110,6 @@ struct mt7996_sta {
struct ewma_avg_signal avg_ack_signal;
unsigned long changed;
unsigned long jiffies;
struct mt76_connac_sta_key_conf bip;
@ -402,6 +401,7 @@ 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);
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{

View File

@ -243,6 +243,13 @@ enum base_rev {
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */
#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band))
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, 0x3c)
#define MT_AGG_ACR_PPDU_TXS2H BIT(1)
/* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */
#define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band))
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
@ -509,6 +516,7 @@ enum base_rev {
#define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4))
#define MT_LED_CTRL_KICK BIT(7)
#define MT_LED_CTRL_BLINK_BAND_SEL BIT(4)
#define MT_LED_CTRL_BLINK_MODE BIT(2)
#define MT_LED_CTRL_POLARITY BIT(1)

View File

@ -329,40 +329,32 @@ void
mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
struct mt76_wcid *wcid, struct sk_buff *skb)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct mt76_queue *q;
int qid = skb_get_queue_mapping(skb);
if (mt76_testmode_enabled(phy)) {
ieee80211_free_txskb(phy->hw, skb);
return;
}
if (WARN_ON(qid >= MT_TXQ_PSD)) {
qid = MT_TXQ_BE;
skb_set_queue_mapping(skb, qid);
}
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
!ieee80211_is_data(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(skb)) {
qid = MT_TXQ_PSD;
}
if (WARN_ON(skb_get_queue_mapping(skb) >= MT_TXQ_PSD))
skb_set_queue_mapping(skb, MT_TXQ_BE);
if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
ieee80211_get_tx_rates(info->control.vif, sta, skb,
info->control.rates, 1);
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
q = phy->q_tx[qid];
spin_lock_bh(&q->lock);
__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
dev->queue_ops->kick(dev, q);
spin_unlock_bh(&q->lock);
spin_lock_bh(&wcid->tx_pending.lock);
__skb_queue_tail(&wcid->tx_pending, skb);
spin_unlock_bh(&wcid->tx_pending.lock);
spin_lock_bh(&phy->tx_lock);
if (list_empty(&wcid->tx_list))
list_add_tail(&wcid->tx_list, &phy->tx_list);
spin_unlock_bh(&phy->tx_lock);
mt76_worker_schedule(&phy->dev->tx_worker);
}
EXPORT_SYMBOL_GPL(mt76_tx);
@ -593,10 +585,86 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
}
EXPORT_SYMBOL_GPL(mt76_txq_schedule);
static int
mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_sta *sta;
struct mt76_queue *q;
struct sk_buff *skb;
int ret = 0;
spin_lock(&wcid->tx_pending.lock);
while ((skb = skb_peek(&wcid->tx_pending)) != NULL) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int qid = skb_get_queue_mapping(skb);
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
!ieee80211_is_data(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(skb))
qid = MT_TXQ_PSD;
q = phy->q_tx[qid];
if (mt76_txq_stopped(q)) {
ret = -1;
break;
}
__skb_unlink(skb, &wcid->tx_pending);
spin_unlock(&wcid->tx_pending.lock);
sta = wcid_to_sta(wcid);
spin_lock(&q->lock);
__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
dev->queue_ops->kick(dev, q);
spin_unlock(&q->lock);
spin_lock(&wcid->tx_pending.lock);
}
spin_unlock(&wcid->tx_pending.lock);
return ret;
}
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
{
if (list_empty(&phy->tx_list))
return;
local_bh_disable();
rcu_read_lock();
spin_lock(&phy->tx_lock);
while (!list_empty(&phy->tx_list)) {
struct mt76_wcid *wcid = NULL;
int ret;
wcid = list_first_entry(&phy->tx_list, struct mt76_wcid, tx_list);
list_del_init(&wcid->tx_list);
spin_unlock(&phy->tx_lock);
ret = mt76_txq_schedule_pending_wcid(phy, wcid);
spin_lock(&phy->tx_lock);
if (ret) {
if (list_empty(&wcid->tx_list))
list_add_tail(&wcid->tx_list, &phy->tx_list);
break;
}
}
spin_unlock(&phy->tx_lock);
rcu_read_unlock();
local_bh_enable();
}
void mt76_txq_schedule_all(struct mt76_phy *phy)
{
int i;
mt76_txq_schedule_pending(phy);
for (i = 0; i <= MT_TXQ_BK; i++)
mt76_txq_schedule(phy, i);
}

View File

@ -180,6 +180,8 @@
#define PCI_DEVICE_ID_BERKOM_A4T 0xffa4
#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xffa8
#define PCI_VENDOR_ID_ITTIM 0x0b48
#define PCI_VENDOR_ID_COMPAQ 0x0e11
#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
#define PCI_DEVICE_ID_COMPAQ_TACHYON 0xa0fc