mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 13:06:59 +02:00
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:
commit
089482a06b
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
30
drivers/net/wireless/mediatek/mt76/mt7925/Kconfig
Normal file
30
drivers/net/wireless/mediatek/mt76/mt7925/Kconfig
Normal 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.
|
||||
9
drivers/net/wireless/mediatek/mt76/mt7925/Makefile
Normal file
9
drivers/net/wireless/mediatek/mt76/mt7925/Makefile
Normal 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
|
||||
319
drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
Normal file
319
drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
Normal 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, ®val, 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, ®val, 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;
|
||||
}
|
||||
235
drivers/net/wireless/mediatek/mt76/mt7925/init.c
Normal file
235
drivers/net/wireless/mediatek/mt76/mt7925/init.c
Normal 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);
|
||||
1452
drivers/net/wireless/mediatek/mt76/mt7925/mac.c
Normal file
1452
drivers/net/wireless/mediatek/mt76/mt7925/mac.c
Normal file
File diff suppressed because it is too large
Load Diff
23
drivers/net/wireless/mediatek/mt76/mt7925/mac.h
Normal file
23
drivers/net/wireless/mediatek/mt76/mt7925/mac.h
Normal 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
|
||||
1454
drivers/net/wireless/mediatek/mt76/mt7925/main.c
Normal file
1454
drivers/net/wireless/mediatek/mt76/mt7925/main.c
Normal file
File diff suppressed because it is too large
Load Diff
3174
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
Normal file
3174
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
Normal file
File diff suppressed because it is too large
Load Diff
537
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
Normal file
537
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
Normal 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
|
||||
309
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
Normal file
309
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
Normal 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
|
||||
586
drivers/net/wireless/mediatek/mt76/mt7925/pci.c
Normal file
586
drivers/net/wireless/mediatek/mt76/mt7925/pci.c
Normal 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");
|
||||
148
drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
Normal file
148
drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
Normal 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;
|
||||
}
|
||||
53
drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
Normal file
53
drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
Normal 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;
|
||||
}
|
||||
92
drivers/net/wireless/mediatek/mt76/mt7925/regs.h
Normal file
92
drivers/net/wireless/mediatek/mt76/mt7925/regs.h
Normal 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
|
||||
332
drivers/net/wireless/mediatek/mt76/mt7925/usb.c
Normal file
332
drivers/net/wireless/mediatek/mt76/mt7925/usb.c
Normal 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");
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user