diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76')
129 files changed, 10606 insertions, 3974 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index d6575fe18c6b..87512d101a91 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_MT792x_USB) += mt792x-usb.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ - tx.o agg-rx.o mcu.o + tx.o agg-rx.o mcu.o wed.o scan.o channel.o mt76-$(CONFIG_PCI) += pci.o mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 10cbd9e560e7..07c386c7b4d0 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -122,7 +122,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) struct ieee80211_bar *bar = mt76_skb_get_hdr(skb); struct mt76_wcid *wcid = status->wcid; struct mt76_rx_tid *tid; - u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; + u8 tidno; u16 seqno; if (!ieee80211_is_ctl(bar->frame_control)) diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c new file mode 100644 index 000000000000..cc2d888e3f17 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/channel.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> + */ +#include "mt76.h" + +static struct mt76_vif_link * +mt76_alloc_mlink(struct mt76_dev *dev, struct mt76_vif_data *mvif) +{ + struct mt76_vif_link *mlink; + + mlink = kzalloc(dev->drv->link_data_size, GFP_KERNEL); + if (!mlink) + return NULL; + + mlink->mvif = mvif; + + return mlink; +} + +static int +mt76_phy_update_channel(struct mt76_phy *phy, + struct ieee80211_chanctx_conf *conf) +{ + phy->radar_enabled = conf->radar_enabled; + phy->main_chandef = conf->def; + phy->chanctx = (struct mt76_chanctx *)conf->drv_priv; + + return __mt76_set_channel(phy, &phy->main_chandef, false); +} + +int mt76_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf) +{ + struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + int ret = -EINVAL; + + phy = ctx->phy = dev->band_phys[conf->def.chan->band]; + if (WARN_ON_ONCE(!phy)) + return ret; + + if (dev->scan.phy == phy) + mt76_abort_scan(dev); + + mutex_lock(&dev->mutex); + if (!phy->chanctx) + ret = mt76_phy_update_channel(phy, conf); + else + ret = 0; + mutex_unlock(&dev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_add_chanctx); + +void mt76_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf) +{ + struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + + phy = ctx->phy; + if (WARN_ON_ONCE(!phy)) + return; + + if (dev->scan.phy == phy) + mt76_abort_scan(dev); + + mutex_lock(&dev->mutex); + if (phy->chanctx == ctx) + phy->chanctx = NULL; + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_remove_chanctx); + +void mt76_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + u32 changed) +{ + struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; + struct mt76_phy *phy = ctx->phy; + struct mt76_dev *dev = phy->dev; + + if (!(changed & (IEEE80211_CHANCTX_CHANGE_WIDTH | + IEEE80211_CHANCTX_CHANGE_RADAR))) + return; + + cancel_delayed_work_sync(&phy->mac_work); + + mutex_lock(&dev->mutex); + mt76_phy_update_channel(phy, conf); + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_change_chanctx); + + +int mt76_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *conf) +{ + struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + int link_id = link_conf->link_id; + struct mt76_phy *phy = ctx->phy; + struct mt76_dev *dev = phy->dev; + bool mlink_alloc = false; + int ret = 0; + + if (dev->scan.vif == vif) + mt76_abort_scan(dev); + + mutex_lock(&dev->mutex); + + if (vif->type == NL80211_IFTYPE_MONITOR && + is_zero_ether_addr(vif->addr)) + goto out; + + mlink = mt76_vif_conf_link(dev, vif, link_conf); + if (!mlink) { + mlink = mt76_alloc_mlink(dev, mvif); + if (!mlink) { + ret = -ENOMEM; + goto out; + } + mlink_alloc = true; + } + + mlink->ctx = conf; + ret = dev->drv->vif_link_add(phy, vif, link_conf, mlink); + if (ret) { + if (mlink_alloc) + kfree(mlink); + goto out; + } + + if (link_conf != &vif->bss_conf) + rcu_assign_pointer(mvif->link[link_id], mlink); + +out: + mutex_unlock(&dev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_assign_vif_chanctx); + +void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *conf) +{ + struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + int link_id = link_conf->link_id; + struct mt76_phy *phy = ctx->phy; + struct mt76_dev *dev = phy->dev; + + if (dev->scan.vif == vif) + mt76_abort_scan(dev); + + mutex_lock(&dev->mutex); + + if (vif->type == NL80211_IFTYPE_MONITOR && + is_zero_ether_addr(vif->addr)) + goto out; + + mlink = mt76_vif_conf_link(dev, vif, link_conf); + if (!mlink) + goto out; + + if (link_conf != &vif->bss_conf) + rcu_assign_pointer(mvif->link[link_id], NULL); + + dev->drv->vif_link_remove(phy, vif, link_conf, mlink); + mlink->ctx = NULL; + + if (link_conf != &vif->bss_conf) + kfree_rcu(mlink, rcu_head); + +out: + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_unassign_vif_chanctx); + +int mt76_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, + enum ieee80211_chanctx_switch_mode mode) +{ + struct mt76_chanctx *old_ctx = (struct mt76_chanctx *)vifs->old_ctx->drv_priv; + struct mt76_chanctx *new_ctx = (struct mt76_chanctx *)vifs->new_ctx->drv_priv; + struct ieee80211_chanctx_conf *conf = vifs->new_ctx; + struct mt76_phy *old_phy = old_ctx->phy; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_vif_link *mlink; + bool update_chan; + int i, ret = 0; + + if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) + phy = new_ctx->phy = dev->band_phys[conf->def.chan->band]; + else + phy = new_ctx->phy; + if (!phy) + return -EINVAL; + + update_chan = phy->chanctx != new_ctx; + if (update_chan) { + if (dev->scan.phy == phy) + mt76_abort_scan(dev); + + cancel_delayed_work_sync(&phy->mac_work); + } + + mutex_lock(&dev->mutex); + + if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && + phy != old_phy && old_phy->chanctx == old_ctx) + old_phy->chanctx = NULL; + + if (update_chan) + ret = mt76_phy_update_channel(phy, vifs->new_ctx); + + if (ret) + goto out; + + if (old_phy == phy) + goto skip_link_replace; + + for (i = 0; i < n_vifs; i++) { + mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); + if (!mlink) + continue; + + dev->drv->vif_link_remove(old_phy, vifs[i].vif, + vifs[i].link_conf, mlink); + + ret = dev->drv->vif_link_add(phy, vifs[i].vif, + vifs[i].link_conf, mlink); + if (ret) + goto out; + + } + +skip_link_replace: + for (i = 0; i < n_vifs; i++) { + mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); + if (!mlink) + continue; + + mlink->ctx = vifs->new_ctx; + } + +out: + mutex_unlock(&dev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx); + +struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, + struct ieee80211_vif *vif) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + struct mt76_dev *dev = phy->dev; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(mvif->link); i++) { + mlink = mt76_dereference(mvif->link[i], dev); + if (!mlink) + continue; + + if (mt76_vif_link_phy(mlink) == phy) + return mlink; + } + + if (!dev->drv->vif_link_add) + return ERR_PTR(-EINVAL); + + mlink = mt76_alloc_mlink(dev, mvif); + if (!mlink) + return ERR_PTR(-ENOMEM); + + mlink->offchannel = true; + ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink); + if (ret) { + kfree(mlink); + return ERR_PTR(ret); + } + rcu_assign_pointer(mvif->offchannel_link, mlink); + + return mlink; +} + +void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct mt76_vif_link *mlink) +{ + struct mt76_dev *dev = phy->dev; + struct mt76_vif_data *mvif; + + if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel) + return; + + mvif = mlink->mvif; + + rcu_assign_pointer(mvif->offchannel_link, NULL); + dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink); + kfree(mlink); +} + +static void mt76_roc_complete(struct mt76_phy *phy) +{ + struct mt76_vif_link *mlink = phy->roc_link; + + if (!phy->roc_vif) + return; + + if (mlink) + mlink->mvif->roc_phy = NULL; + if (phy->main_chandef.chan) + mt76_set_channel(phy, &phy->main_chandef, false); + mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link); + phy->roc_vif = NULL; + phy->roc_link = NULL; + ieee80211_remain_on_channel_expired(phy->hw); +} + +void mt76_roc_complete_work(struct work_struct *work) +{ + struct mt76_phy *phy = container_of(work, struct mt76_phy, roc_work.work); + struct mt76_dev *dev = phy->dev; + + mutex_lock(&dev->mutex); + mt76_roc_complete(phy); + mutex_unlock(&dev->mutex); +} + +void mt76_abort_roc(struct mt76_phy *phy) +{ + struct mt76_dev *dev = phy->dev; + + cancel_delayed_work_sync(&phy->roc_work); + + mutex_lock(&dev->mutex); + mt76_roc_complete(phy); + mutex_unlock(&dev->mutex); +} + +int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration, + enum ieee80211_roc_type type) +{ + struct cfg80211_chan_def chandef = {}; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_vif_link *mlink; + int ret = 0; + + phy = dev->band_phys[chan->band]; + if (!phy) + return -EINVAL; + + mutex_lock(&dev->mutex); + + if (phy->roc_vif || dev->scan.phy == phy) { + ret = -EBUSY; + goto out; + } + + mlink = mt76_get_vif_phy_link(phy, vif); + if (IS_ERR(mlink)) { + ret = PTR_ERR(mlink); + goto out; + } + + mlink->mvif->roc_phy = phy; + phy->roc_vif = vif; + phy->roc_link = mlink; + cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); + mt76_set_channel(phy, &chandef, true); + ieee80211_ready_on_channel(hw); + ieee80211_queue_delayed_work(phy->hw, &phy->roc_work, + msecs_to_jiffies(duration)); + +out: + mutex_unlock(&dev->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(mt76_remain_on_channel); + +int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + struct mt76_phy *phy = mvif->roc_phy; + + if (!phy) + return 0; + + mt76_abort_roc(phy); + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_cancel_remain_on_channel); diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index ae83be572b94..b6a2746c187d 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -33,8 +33,8 @@ mt76_napi_threaded_set(void *data, u64 val) if (!mt76_is_mmio(dev)) return -EOPNOTSUPP; - if (dev->napi_dev.threaded != val) - return dev_set_threaded(&dev->napi_dev, val); + if (dev->napi_dev->threaded != val) + return dev_set_threaded(dev->napi_dev, val); return 0; } @@ -44,7 +44,7 @@ mt76_napi_threaded_get(void *data, u64 *val) { struct mt76_dev *dev = data; - *val = dev->napi_dev.threaded; + *val = dev->napi_dev->threaded; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 00230f106294..35b4ec91979e 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -197,9 +197,8 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) q->tail = q->head; } -static void -__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, - bool reset_idx) +void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, + bool reset_idx) { if (!q || !q->ndesc) return; @@ -219,8 +218,7 @@ __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, mt76_dma_sync_idx(dev, q); } -static void -mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) +void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) { __mt76_dma_queue_reset(dev, q, true); } @@ -534,7 +532,7 @@ error: } static int -mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, +mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { @@ -544,6 +542,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_tx_info tx_info = { .skb = skb, }; + struct mt76_dev *dev = phy->dev; struct ieee80211_hw *hw; int len, n = 0, ret = -ENOMEM; struct mt76_txwi_cache *t; @@ -551,7 +550,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, dma_addr_t addr; u8 *txwi; - if (test_bit(MT76_RESET, &dev->phy.state)) + if (test_bit(MT76_RESET, &phy->state)) goto free_skb; t = mt76_get_txwi(dev); @@ -633,8 +632,8 @@ free_skb: } static int -mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, - bool allow_direct) +mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q, + bool allow_direct) { int len = SKB_WITH_OVERHEAD(q->buf_size); int frames = 0; @@ -642,8 +641,6 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, if (!q->ndesc) return 0; - spin_lock_bh(&q->lock); - while (q->queued < q->ndesc - 1) { struct mt76_queue_buf qbuf = {}; enum dma_data_direction dir; @@ -676,85 +673,23 @@ done: if (frames || mt76_queue_is_wed_rx(q)) mt76_dma_kick_queue(dev, q); - spin_unlock_bh(&q->lock); - return frames; } -int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) +int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, + bool allow_direct) { -#ifdef CONFIG_NET_MEDIATEK_SOC_WED - int ret = 0, type, ring; - u16 flags; - - if (!q || !q->ndesc) - return -EINVAL; + int frames; - flags = q->flags; - if (!q->wed || !mtk_wed_device_active(q->wed)) - q->flags &= ~MT_QFLAG_WED; - - if (!(q->flags & MT_QFLAG_WED)) + if (!q->ndesc) return 0; - type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags); - ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags); - - switch (type) { - case MT76_WED_Q_TX: - ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs, - reset); - if (!ret) - q->wed_regs = q->wed->tx_ring[ring].reg_base; - break; - case MT76_WED_Q_TXFREE: - /* WED txfree queue needs ring to be initialized before setup */ - q->flags = 0; - mt76_dma_queue_reset(dev, q); - mt76_dma_rx_fill(dev, q, false); - - ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); - if (!ret) - q->wed_regs = q->wed->txfree_ring.reg_base; - break; - case MT76_WED_Q_RX: - ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs, - reset); - if (!ret) - q->wed_regs = q->wed->rx_ring[ring].reg_base; - break; - case MT76_WED_RRO_Q_DATA: - q->flags &= ~MT_QFLAG_WED; - __mt76_dma_queue_reset(dev, q, false); - mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs); - q->head = q->ndesc - 1; - q->queued = q->head; - break; - case MT76_WED_RRO_Q_MSDU_PG: - q->flags &= ~MT_QFLAG_WED; - __mt76_dma_queue_reset(dev, q, false); - mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs); - q->head = q->ndesc - 1; - q->queued = q->head; - break; - case MT76_WED_RRO_Q_IND: - q->flags &= ~MT_QFLAG_WED; - mt76_dma_queue_reset(dev, q); - mt76_dma_rx_fill(dev, q, false); - mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs); - break; - default: - ret = -EINVAL; - break; - } - q->flags = flags; + spin_lock_bh(&q->lock); + frames = mt76_dma_rx_fill_buf(dev, q, allow_direct); + spin_unlock_bh(&q->lock); - return ret; -#else - return 0; -#endif + return frames; } -EXPORT_SYMBOL_GPL(mt76_dma_wed_setup); static int mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, @@ -800,7 +735,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, if (ret) return ret; - ret = mt76_dma_wed_setup(dev, q, false); + ret = mt76_wed_dma_setup(dev, q, false); if (ret) return ret; @@ -863,7 +798,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) mt76_dma_rx_cleanup(dev, q); /* reset WED rx queues */ - mt76_dma_wed_setup(dev, q, true); + mt76_wed_dma_setup(dev, q, true); if (mt76_queue_is_wed_tx_free(q)) return; @@ -873,7 +808,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) return; mt76_dma_sync_idx(dev, q); - mt76_dma_rx_fill(dev, q, false); + mt76_dma_rx_fill_buf(dev, q, false); } static void @@ -993,7 +928,7 @@ int mt76_dma_rx_poll(struct napi_struct *napi, int budget) struct mt76_dev *dev; int qid, done = 0, cur; - dev = container_of(napi->dev, struct mt76_dev, napi_dev); + dev = mt76_priv(napi->dev); qid = napi - dev->napi; rcu_read_lock(); @@ -1017,19 +952,36 @@ static int mt76_dma_init(struct mt76_dev *dev, int (*poll)(struct napi_struct *napi, int budget)) { + struct mt76_dev **priv; int i; - init_dummy_netdev(&dev->napi_dev); - init_dummy_netdev(&dev->tx_napi_dev); - snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s", + dev->napi_dev = alloc_netdev_dummy(sizeof(struct mt76_dev *)); + if (!dev->napi_dev) + return -ENOMEM; + + /* napi_dev private data points to mt76_dev parent, so, mt76_dev + * can be retrieved given napi_dev + */ + priv = netdev_priv(dev->napi_dev); + *priv = dev; + + dev->tx_napi_dev = alloc_netdev_dummy(sizeof(struct mt76_dev *)); + if (!dev->tx_napi_dev) { + free_netdev(dev->napi_dev); + return -ENOMEM; + } + priv = netdev_priv(dev->tx_napi_dev); + *priv = dev; + + snprintf(dev->napi_dev->name, sizeof(dev->napi_dev->name), "%s", wiphy_name(dev->hw->wiphy)); - dev->napi_dev.threaded = 1; + dev->napi_dev->threaded = 1; init_completion(&dev->mmio.wed_reset); init_completion(&dev->mmio.wed_reset_complete); mt76_for_each_q_rx(dev, i) { - netif_napi_add(&dev->napi_dev, &dev->napi[i], poll); - mt76_dma_rx_fill(dev, &dev->q_rx[i], false); + netif_napi_add(dev->napi_dev, &dev->napi[i], poll); + mt76_dma_rx_fill_buf(dev, &dev->q_rx[i], false); napi_enable(&dev->napi[i]); } @@ -1054,25 +1006,12 @@ void mt76_dma_attach(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_dma_attach); -void mt76_dma_wed_reset(struct mt76_dev *dev) -{ - struct mt76_mmio *mmio = &dev->mmio; - - if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state)) - return; - - complete(&mmio->wed_reset); - - if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ)) - dev_err(dev->dev, "wed reset complete timeout\n"); -} -EXPORT_SYMBOL_GPL(mt76_dma_wed_reset); - void mt76_dma_cleanup(struct mt76_dev *dev) { int i; mt76_worker_disable(&dev->tx_worker); + napi_disable(&dev->tx_napi); netif_napi_del(&dev->tx_napi); for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { @@ -1110,5 +1049,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) mt76_free_pending_txwi(dev); mt76_free_pending_rxwi(dev); + free_netdev(dev->napi_dev); + free_netdev(dev->tx_napi_dev); } EXPORT_SYMBOL_GPL(mt76_dma_cleanup); diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index c479cc6388ef..e3ddc7a83757 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -79,15 +79,18 @@ enum mt76_dma_wed_ind_reason { int mt76_dma_rx_poll(struct napi_struct *napi, int budget); void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev); -int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset); -void mt76_dma_wed_reset(struct mt76_dev *dev); +int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, + bool allow_direct); +void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, + bool reset_idx); +void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q); static inline void mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q) { dev->queue_ops->reset_q(dev, q); if (mtk_wed_device_active(&dev->mmio.wed)) - mt76_dma_wed_setup(dev, q, true); + mt76_wed_dma_setup(dev, q, true); } static inline void @@ -113,4 +116,13 @@ mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info) } } +static inline void *mt76_priv(struct net_device *dev) +{ + struct mt76_dev **priv; + + priv = netdev_priv(dev); + + return *priv; +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 0bc66cc19acd..443517d06c9f 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -95,6 +95,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l #ifdef CONFIG_NL80211_TESTMODE dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL); + if (!dev->test_mtd.name) { + ret = -ENOMEM; + goto out_put_node; + } dev->test_mtd.offset = offset; #endif diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 8a3a90d1bfac..45c8db939d55 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -411,13 +411,16 @@ mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, } if (found) { - phy->chandef.chan = &sband->channels[0]; + cfg80211_chandef_create(&phy->chandef, &sband->channels[0], + NL80211_CHAN_HT20); phy->chan_state = &msband->chan[0]; + phy->dev->band_phys[band] = phy; return; } sband->n_channels = 0; - phy->hw->wiphy->bands[band] = NULL; + if (phy->hw->wiphy->bands[band] == sband) + phy->hw->wiphy->bands[band] = NULL; } static int @@ -428,6 +431,10 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) INIT_LIST_HEAD(&phy->tx_list); spin_lock_init(&phy->tx_lock); + INIT_DELAYED_WORK(&phy->roc_work, mt76_roc_complete_work); + + if ((void *)phy != hw->priv) + return 0; SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, phy->macaddr); @@ -442,8 +449,10 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); - wiphy->available_antennas_tx = phy->antenna_mask; - wiphy->available_antennas_rx = phy->antenna_mask; + if (!wiphy->available_antennas_tx) + wiphy->available_antennas_tx = phy->antenna_mask; + if (!wiphy->available_antennas_rx) + wiphy->available_antennas_rx = phy->antenna_mask; wiphy->sar_capa = &mt76_sar_capa; phy->frp = devm_kcalloc(dev->dev, wiphy->sar_capa->num_freq_ranges, @@ -465,6 +474,7 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); + ieee80211_hw_set(hw, SPECTRUM_MGMT); if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) && hw->max_tx_fragments > 1) { @@ -480,6 +490,28 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) } struct mt76_phy * +mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size, + u8 band_idx) +{ + struct ieee80211_hw *hw = dev->phy.hw; + unsigned int phy_size; + struct mt76_phy *phy; + + phy_size = ALIGN(sizeof(*phy), 8); + phy = devm_kzalloc(dev->dev, size + phy_size, GFP_KERNEL); + if (!phy) + return NULL; + + phy->dev = dev; + phy->hw = hw; + phy->priv = (void *)phy + phy_size; + phy->band_idx = band_idx; + + return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_radio_phy); + +struct mt76_phy * mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, const struct ieee80211_ops *ops, u8 band_idx) { @@ -551,9 +583,11 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); mt76_check_sband(phy, &phy->sband_6g, NL80211_BAND_6GHZ); - ret = ieee80211_register_hw(phy->hw); - if (ret) - return ret; + if ((void *)phy == phy->hw->priv) { + ret = ieee80211_register_hw(phy->hw); + if (ret) + return ret; + } set_bit(MT76_STATE_REGISTERED, &phy->state); phy->dev->phys[phy->band_idx] = phy; @@ -579,13 +613,18 @@ EXPORT_SYMBOL_GPL(mt76_unregister_phy); int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) { + bool is_qrx = mt76_queue_is_rx(dev, q); struct page_pool_params pp_params = { .order = 0, .flags = 0, .nid = NUMA_NO_NODE, .dev = dev->dma_dev, }; - int idx = q - dev->q_rx; + int idx = is_qrx ? q - dev->q_rx : -1; + + /* Allocate page_pools just for rx/wed_tx_free queues */ + if (!is_qrx && !mt76_queue_is_wed_tx_free(q)) + return 0; switch (idx) { case MT_RXQ_MAIN: @@ -604,6 +643,9 @@ int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) pp_params.dma_dir = DMA_FROM_DEVICE; pp_params.max_len = PAGE_SIZE; pp_params.offset = 0; + /* NAPI is available just for rx queues */ + if (idx >= 0 && idx < ARRAY_SIZE(dev->napi)) + pp_params.napi = &dev->napi[idx]; } q->page_pool = page_pool_create(&pp_params); @@ -681,6 +723,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, INIT_LIST_HEAD(&dev->txwi_cache); INIT_LIST_HEAD(&dev->rxwi_cache); dev->token_size = dev->drv->token_size; + INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work); for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) skb_queue_head_init(&dev->rx_skb[i]); @@ -703,7 +746,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); + mt76_wcid_init(&dev->global_wcid, phy->band_idx); ret = mt76_phy_init(phy, hw); if (ret) return ret; @@ -775,6 +818,23 @@ void mt76_free_device(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_free_device); +struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_chanctx *ctx; + + if (!hw->wiphy->n_radio) + return hw->priv; + + if (!mlink->ctx) + return NULL; + + ctx = (struct mt76_chanctx *)mlink->ctx->drv_priv; + return ctx->phy; +} +EXPORT_SYMBOL_GPL(mt76_vif_phy); + static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q) { struct sk_buff *skb = phy->rx_amsdu[q].head; @@ -920,14 +980,16 @@ void mt76_update_survey(struct mt76_phy *phy) } EXPORT_SYMBOL_GPL(mt76_update_survey); -void mt76_set_channel(struct mt76_phy *phy) +int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, + bool offchannel) { struct mt76_dev *dev = phy->dev; - struct ieee80211_hw *hw = phy->hw; - struct cfg80211_chan_def *chandef = &hw->conf.chandef; - bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; int timeout = HZ / 5; + int ret; + set_bit(MT76_RESET, &phy->state); + + mt76_worker_disable(&dev->tx_worker); wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); mt76_update_survey(phy); @@ -937,42 +999,97 @@ void mt76_set_channel(struct mt76_phy *phy) phy->chandef = *chandef; phy->chan_state = mt76_channel_state(phy, chandef->chan); + phy->offchannel = offchannel; if (!offchannel) - phy->main_chan = chandef->chan; + phy->main_chandef = *chandef; - if (chandef->chan != phy->main_chan) + if (chandef->chan != phy->main_chandef.chan) memset(phy->chan_state, 0, sizeof(*phy->chan_state)); + + ret = dev->drv->set_channel(phy); + + clear_bit(MT76_RESET, &phy->state); + mt76_worker_enable(&dev->tx_worker); + mt76_worker_schedule(&dev->tx_worker); + + return ret; +} + +int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, + bool offchannel) +{ + struct mt76_dev *dev = phy->dev; + int ret; + + cancel_delayed_work_sync(&phy->mac_work); + + mutex_lock(&dev->mutex); + ret = __mt76_set_channel(phy, chandef, offchannel); + mutex_unlock(&dev->mutex); + + return ret; +} + +int mt76_update_channel(struct mt76_phy *phy) +{ + struct ieee80211_hw *hw = phy->hw; + struct cfg80211_chan_def *chandef = &hw->conf.chandef; + bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; + + phy->radar_enabled = hw->conf.radar_enabled; + + return mt76_set_channel(phy, chandef, offchannel); +} +EXPORT_SYMBOL_GPL(mt76_update_channel); + +static struct mt76_sband * +mt76_get_survey_sband(struct mt76_phy *phy, int *idx) +{ + if (*idx < phy->sband_2g.sband.n_channels) + return &phy->sband_2g; + + *idx -= phy->sband_2g.sband.n_channels; + if (*idx < phy->sband_5g.sband.n_channels) + return &phy->sband_5g; + + *idx -= phy->sband_5g.sband.n_channels; + if (*idx < phy->sband_6g.sband.n_channels) + return &phy->sband_6g; + + *idx -= phy->sband_6g.sband.n_channels; + return NULL; } -EXPORT_SYMBOL_GPL(mt76_set_channel); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; - struct mt76_sband *sband; + struct mt76_sband *sband = NULL; struct ieee80211_channel *chan; struct mt76_channel_state *state; + int phy_idx = 0; int ret = 0; mutex_lock(&dev->mutex); - if (idx == 0 && dev->drv->update_survey) - mt76_update_survey(phy); - - if (idx >= phy->sband_2g.sband.n_channels + - phy->sband_5g.sband.n_channels) { - idx -= (phy->sband_2g.sband.n_channels + - phy->sband_5g.sband.n_channels); - sband = &phy->sband_6g; - } else if (idx >= phy->sband_2g.sband.n_channels) { - idx -= phy->sband_2g.sband.n_channels; - sband = &phy->sband_5g; - } else { - sband = &phy->sband_2g; + + for (phy_idx = 0; phy_idx < ARRAY_SIZE(dev->phys); phy_idx++) { + sband = NULL; + phy = dev->phys[phy_idx]; + if (!phy || phy->hw != hw) + continue; + + sband = mt76_get_survey_sband(phy, &idx); + + if (idx == 0 && phy->dev->drv->update_survey) + mt76_update_survey(phy); + + if (sband || !hw->wiphy->n_radio) + break; } - if (idx >= sband->sband.n_channels) { + if (!sband) { ret = -ENOENT; goto out; } @@ -987,7 +1104,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, if (state->noise) survey->filled |= SURVEY_INFO_NOISE_DBM; - if (chan == phy->main_chan) { + if (chan == phy->main_chandef.chan) { survey->filled |= SURVEY_INFO_IN_USE; if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) @@ -1116,6 +1233,11 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); + if (mstat.wcid) { + status->link_valid = mstat.wcid->link_valid; + status->link_id = mstat.wcid->link_id; + } + *sta = wcid_to_sta(mstat.wcid); *hw = mt76_phy_hw(dev, mstat.phy_idx); } @@ -1423,21 +1545,20 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif, } ewma_signal_init(&wcid->rssi); - if (phy->band_idx == MT_BAND1) - mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); - wcid->phy_idx = phy->band_idx; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); + phy->num_sta++; - mt76_wcid_init(wcid); + mt76_wcid_init(wcid, phy->band_idx); out: mutex_unlock(&dev->mutex); return ret; } -void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, +void __mt76_sta_remove(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { + struct mt76_dev *dev = phy->dev; struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int i, idx = wcid->idx; @@ -1450,16 +1571,18 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, mt76_wcid_cleanup(dev, wcid); mt76_wcid_mask_clear(dev->wcid_mask, idx); - mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); + phy->num_sta--; } EXPORT_SYMBOL_GPL(__mt76_sta_remove); static void -mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, +mt76_sta_remove(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { + struct mt76_dev *dev = phy->dev; + mutex_lock(&dev->mutex); - __mt76_sta_remove(dev, vif, sta); + __mt76_sta_remove(phy, vif, sta); mutex_unlock(&dev->mutex); } @@ -1470,21 +1593,36 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; + enum mt76_sta_event ev; + + phy = mt76_vif_phy(hw, vif); + if (!phy) + return -EINVAL; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) return mt76_sta_add(phy, vif, sta); - if (old_state == IEEE80211_STA_AUTH && - new_state == IEEE80211_STA_ASSOC && - dev->drv->sta_assoc) - dev->drv->sta_assoc(dev, vif, sta); - if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST) - mt76_sta_remove(dev, vif, sta); + mt76_sta_remove(phy, vif, sta); - return 0; + if (!dev->drv->sta_event) + return 0; + + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) + ev = MT76_STA_EVENT_ASSOC; + else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) + ev = MT76_STA_EVENT_AUTHORIZE; + else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) + ev = MT76_STA_EVENT_DISASSOC; + else + return 0; + + return dev->drv->sta_event(dev, vif, sta, ev); } EXPORT_SYMBOL_GPL(mt76_sta_state); @@ -1503,19 +1641,25 @@ 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) +void mt76_wcid_init(struct mt76_wcid *wcid, u8 band_idx) { + wcid->hw_key_idx = -1; + wcid->phy_idx = band_idx; + INIT_LIST_HEAD(&wcid->tx_list); skb_queue_head_init(&wcid->tx_pending); + skb_queue_head_init(&wcid->tx_offchannel); INIT_LIST_HEAD(&wcid->list); idr_init(&wcid->pktid); + + INIT_LIST_HEAD(&wcid->poll_list); } 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 mt76_phy *phy = mt76_dev_phy(dev, wcid->phy_idx); struct ieee80211_hw *hw; struct sk_buff_head list; struct sk_buff *skb; @@ -1544,13 +1688,40 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) } EXPORT_SYMBOL_GPL(mt76_wcid_cleanup); -int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int *dbm) +void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid) +{ + if (test_bit(MT76_MCU_RESET, &dev->phy.state)) + return; + + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&wcid->poll_list)) + list_add_tail(&wcid->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); +} +EXPORT_SYMBOL_GPL(mt76_wcid_add_poll); + +s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower) { - struct mt76_phy *phy = hw->priv; int n_chains = hweight16(phy->chainmask); - int delta = mt76_tx_power_nss_delta(n_chains); + txpower = mt76_get_sar_power(phy, phy->chandef.chan, txpower * 2); + txpower -= mt76_tx_power_path_delta(n_chains); + + return txpower; +} +EXPORT_SYMBOL_GPL(mt76_get_power_bound); + +int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, int *dbm) +{ + struct mt76_phy *phy = mt76_vif_phy(hw, vif); + int n_chains, delta; + + if (!phy) + return -EINVAL; + + n_chains = hweight16(phy->chainmask); + delta = mt76_tx_power_path_delta(n_chains); *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); return 0; @@ -1613,8 +1784,8 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power); static void __mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (vif->bss_conf.csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) - ieee80211_csa_finish(vif); + if (vif->bss_conf.csa_active && ieee80211_beacon_cntdwn_is_complete(vif, 0)) + ieee80211_csa_finish(vif, 0); } void mt76_csa_finish(struct mt76_dev *dev) @@ -1638,7 +1809,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!vif->bss_conf.csa_active) return; - dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif); + dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif, 0); } void mt76_csa_check(struct mt76_dev *dev) @@ -1683,14 +1854,15 @@ int mt76_get_rate(struct mt76_dev *dev, struct ieee80211_supported_band *sband, int idx, bool cck) { + bool is_2g = sband->band == NL80211_BAND_2GHZ; int i, offset = 0, len = sband->n_bitrates; if (cck) { - if (sband != &dev->phy.sband_2g.sband) + if (!is_2g) return 0; idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->phy.sband_2g.sband) { + } else if (is_2g) { offset = 4; } @@ -1724,10 +1896,14 @@ int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; + int i; mutex_lock(&dev->mutex); - *tx_ant = phy->antenna_mask; - *rx_ant = phy->antenna_mask; + *tx_ant = 0; + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) + if (dev->phys[i] && dev->phys[i]->hw == hw) + *tx_ant |= dev->phys[i]->chainmask; + *rx_ant = *tx_ant; mutex_unlock(&dev->mutex); return 0; @@ -1756,30 +1932,6 @@ 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, - 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 (chandef->chan->band != NL80211_BAND_2GHZ) - offset = 4; - - /* pick the lowest rate for hidden nodes */ - if (rateidx < 0) - rateidx = 0; - - rateidx += offset; - if (rateidx >= ARRAY_SIZE(mt76_rates)) - rateidx = offset; - - return mt76_rates[rateidx].hw_value; -} -EXPORT_SYMBOL_GPL(mt76_calculate_default_rate); - void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, struct mt76_sta_stats *stats, bool eht) { @@ -1840,7 +1992,7 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) test_bit(MT76_SCANNING, &phy->state)) return MT_DFS_STATE_DISABLED; - if (!hw->conf.radar_enabled) { + if (!phy->radar_enabled) { if ((hw->conf.flags & IEEE80211_CONF_MONITOR) && (phy->chandef.chan->flags & IEEE80211_CHAN_RADAR)) return MT_DFS_STATE_ACTIVE; @@ -1855,18 +2007,14 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) } EXPORT_SYMBOL_GPL(mt76_phy_dfs_state); -#ifdef CONFIG_NET_MEDIATEK_SOC_WED -int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct net_device *netdev, enum tc_setup_type type, - void *type_data) +void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif) { - struct mt76_phy *phy = hw->priv; - struct mtk_wed_device *wed = &phy->dev->mmio.wed; - - if (!mtk_wed_device_active(wed)) - return -EOPNOTSUPP; + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; - return mtk_wed_device_setup_tc(wed, netdev, type, type_data); + rcu_assign_pointer(mvif->link[0], NULL); + mt76_abort_scan(dev); + if (mvif->roc_phy) + mt76_abort_roc(mvif->roc_phy); } -EXPORT_SYMBOL_GPL(mt76_net_setup_tc); -#endif /* CONFIG_NET_MEDIATEK_SOC_WED */ +EXPORT_SYMBOL_GPL(mt76_vif_cleanup); diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index a8cafa39a56d..3353012e8542 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -73,6 +73,8 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, bool wait_resp, struct sk_buff **ret_skb) { + unsigned int retry = 0; + struct sk_buff *orig_skb = NULL; unsigned long expires; int ret, seq; @@ -81,6 +83,17 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, mutex_lock(&dev->mcu.mutex); + if (dev->mcu_ops->mcu_skb_prepare_msg) { + orig_skb = skb; + ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq); + if (ret < 0) + goto out; + } + +retry: + /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */ + if (orig_skb) + skb_get(orig_skb); ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq); if (ret < 0) goto out; @@ -94,6 +107,14 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, do { skb = mt76_mcu_get_response(dev, expires); + if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) && + orig_skb && retry++ < dev->mcu_ops->max_retry) { + dev_err(dev->dev, "Retry message %08x (seq %d)\n", + cmd, seq); + skb = orig_skb; + goto retry; + } + ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq); if (!ret && ret_skb) *ret_skb = skb; @@ -101,7 +122,9 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, dev_kfree_skb(skb); } while (ret == -EAGAIN); + out: + dev_kfree_skb(orig_skb); mutex_unlock(&dev->mcu.mutex); return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index c3e0e23e0161..cd2e9737c3bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -85,113 +85,6 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, } EXPORT_SYMBOL_GPL(mt76_set_irq_mask); -#ifdef CONFIG_NET_MEDIATEK_SOC_WED -void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - int i; - - for (i = 0; i < dev->rx_token_size; i++) { - struct mt76_txwi_cache *t; - - t = mt76_rx_token_release(dev, i); - if (!t || !t->ptr) - continue; - - mt76_put_page_pool_buf(t->ptr, false); - t->ptr = NULL; - - mt76_put_rxwi(dev, t); - } - - mt76_free_pending_rxwi(dev); -} -EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf); - -u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i, len = SKB_WITH_OVERHEAD(q->buf_size); - struct mt76_txwi_cache *t = NULL; - - for (i = 0; i < size; i++) { - enum dma_data_direction dir; - dma_addr_t addr; - u32 offset; - int token; - void *buf; - - t = mt76_get_rxwi(dev); - if (!t) - goto unmap; - - buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); - if (!buf) - goto unmap; - - addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; - dir = page_pool_get_dma_dir(q->page_pool); - dma_sync_single_for_device(dev->dma_dev, addr, len, dir); - - desc->buf0 = cpu_to_le32(addr); - token = mt76_rx_token_consume(dev, buf, t, addr); - if (token < 0) { - mt76_put_page_pool_buf(buf, false); - goto unmap; - } - - token = FIELD_PREP(MT_DMA_CTL_TOKEN, token); -#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT - token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32); -#endif - desc->token |= cpu_to_le32(token); - desc++; - } - - return 0; - -unmap: - if (t) - mt76_put_rxwi(dev, t); - mt76_mmio_wed_release_rx_buf(wed); - - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf); - -int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - - spin_lock_bh(&dev->token_lock); - dev->token_size = wed->wlan.token_start; - spin_unlock_bh(&dev->token_lock); - - return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ); -} -EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable); - -void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - - spin_lock_bh(&dev->token_lock); - dev->token_size = dev->drv->token_size; - spin_unlock_bh(&dev->token_lock); -} -EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable); - -void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed) -{ - struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); - - complete(&dev->mmio.wed_reset_complete); -} -EXPORT_SYMBOL_GPL(mt76_mmio_wed_reset_complete); -#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ - void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) { static const struct mt76_bus_ops mt76_mmio_ops = { diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index b20c34d5a0f7..5f8d81cda6cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -50,6 +50,8 @@ struct mt76_dev; struct mt76_phy; struct mt76_wcid; struct mt76s_intr; +struct mt76_chanctx; +struct mt76_vif_link; struct mt76_reg_pair { u32 reg; @@ -160,10 +162,20 @@ enum mt76_dfs_state { MT_DFS_STATE_ACTIVE, }; +#define MT76_RNR_SCAN_MAX_BSSIDS 16 +struct mt76_scan_rnr_param { + u8 bssid[MT76_RNR_SCAN_MAX_BSSIDS][ETH_ALEN]; + u8 channel[MT76_RNR_SCAN_MAX_BSSIDS]; + u8 random_mac[ETH_ALEN]; + u8 seq_num; + u8 bssid_num; + u32 sreq_flag; +}; + struct mt76_queue_buf { dma_addr_t addr; - u16 len; - bool skip_unmap; + u16 len:15, + skip_unmap:1; }; struct mt76_tx_info { @@ -210,6 +222,8 @@ struct mt76_queue { u16 first; u16 head; u16 tail; + u8 hw_idx; + u8 ep; int ndesc; int queued; int buf_size; @@ -217,7 +231,6 @@ struct mt76_queue { bool blocked; u8 buf_offset; - u8 hw_idx; u16 flags; struct mtk_wed_device *wed; @@ -229,11 +242,14 @@ struct mt76_queue { }; struct mt76_mcu_ops { + unsigned int max_retry; u32 headroom; u32 tailroom; int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data, int len, bool wait_resp); + int (*mcu_skb_prepare_msg)(struct mt76_dev *dev, struct sk_buff *skb, + int cmd, int *seq); int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb, int cmd, int *seq); int (*mcu_parse_response)(struct mt76_dev *dev, int cmd, @@ -255,7 +271,7 @@ struct mt76_queue_ops { int idx, int n_desc, int bufsize, u32 ring_base); - int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q, + int (*tx_queue_skb)(struct mt76_phy *phy, struct mt76_queue *q, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); @@ -345,9 +361,13 @@ struct mt76_wcid { u8 hw_key_idx; u8 hw_key_idx2; + u8 offchannel:1; u8 sta:1; + u8 sta_disabled:1; u8 amsdu:1; u8 phy_idx:2; + u8 link_id:4; + bool link_valid; u8 rx_check_pn; u8 rx_key_pn[IEEE80211_NUM_TIDS + 1][6]; @@ -358,6 +378,7 @@ struct mt76_wcid { struct list_head tx_list; struct sk_buff_head tx_pending; + struct sk_buff_head tx_offchannel; struct list_head list; struct idr pktid; @@ -365,6 +386,8 @@ struct mt76_wcid { struct mt76_sta_stats stats; struct list_head poll_list; + + struct mt76_wcid *def_wcid; }; struct mt76_txq { @@ -461,6 +484,12 @@ enum { MT76_STATE_WED_RESET, }; +enum mt76_sta_event { + MT76_STA_EVENT_ASSOC, + MT76_STA_EVENT_AUTHORIZE, + MT76_STA_EVENT_DISASSOC, +}; + struct mt76_hw_cap { bool has_2ghz; bool has_5ghz; @@ -473,6 +502,7 @@ struct mt76_hw_cap { #define MT_DRV_RX_DMA_HDR BIT(3) #define MT_DRV_HW_MGMT_TXQ BIT(4) #define MT_DRV_AMSDU_OFFLOAD BIT(5) +#define MT_DRV_IGNORE_TXS_FAILED BIT(6) struct mt76_driver_ops { u32 drv_flags; @@ -481,7 +511,10 @@ struct mt76_driver_ops { u16 token_size; u8 mcs_rates; + unsigned int link_data_size; + void (*update_survey)(struct mt76_phy *phy); + int (*set_channel)(struct mt76_phy *phy); int (*tx_prepare_skb)(struct mt76_dev *dev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -506,11 +539,20 @@ struct mt76_driver_ops { int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); - void (*sta_assoc)(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + int (*sta_event)(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev); void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); + + int (*vif_link_add)(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink); + + void (*vif_link_remove)(struct mt76_phy *phy, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink); }; struct mt76_channel_state { @@ -619,6 +661,7 @@ struct mt76_sdio { u8 hw_ver; wait_queue_head_t wait; + int pse_mcu_quota_max; struct { int pse_data_quota; int ple_data_quota; @@ -736,8 +779,9 @@ struct mt76_testmode_data { } rx_stats; }; -struct mt76_vif { +struct mt76_vif_link { u8 idx; + u8 link_idx; u8 omac_idx; u8 band_idx; u8 wmm_idx; @@ -746,7 +790,20 @@ struct mt76_vif { u8 basic_rates_idx; u8 mcast_rates_idx; u8 beacon_rates_idx; + bool offchannel; struct ieee80211_chanctx_conf *ctx; + struct mt76_wcid *wcid; + struct mt76_vif_data *mvif; + struct rcu_head rcu_head; +}; + +struct mt76_vif_data { + struct mt76_vif_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; + struct mt76_vif_link __rcu *offchannel_link; + + struct mt76_phy *roc_phy; + u16 valid_links; + u8 deflink_id; }; struct mt76_phy { @@ -755,6 +812,7 @@ struct mt76_phy { void *priv; unsigned long state; + unsigned int num_sta; u8 band_idx; spinlock_t tx_lock; @@ -762,7 +820,15 @@ struct mt76_phy { struct mt76_queue *q_tx[__MT_TXQ_MAX]; struct cfg80211_chan_def chandef; - struct ieee80211_channel *main_chan; + struct cfg80211_chan_def main_chandef; + bool offchannel; + bool radar_enabled; + + struct delayed_work roc_work; + struct ieee80211_vif *roc_vif; + struct mt76_vif_link *roc_link; + + struct mt76_chanctx *chanctx; struct mt76_channel_state *chan_state; enum mt76_dfs_state dfs_state; @@ -807,6 +873,7 @@ struct mt76_phy { struct mt76_dev { struct mt76_phy phy; /* must be first */ struct mt76_phy *phys[__MT_MAX_BAND]; + struct mt76_phy *band_phys[NUM_NL80211_BANDS]; struct ieee80211_hw *hw; @@ -830,8 +897,8 @@ struct mt76_dev { struct mt76_mcu mcu; - struct net_device napi_dev; - struct net_device tx_napi_dev; + struct net_device *napi_dev; + struct net_device *tx_napi_dev; spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; @@ -862,7 +929,6 @@ struct mt76_dev { spinlock_t status_lock; u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; - u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; u64 vif_mask; @@ -885,12 +951,24 @@ struct mt76_dev { char alpha2[3]; enum nl80211_dfs_regions region; + struct mt76_scan_rnr_param rnr; + u32 debugfs_reg; u8 csa_complete; u32 rxfilter; + struct delayed_work scan_work; + struct { + struct cfg80211_scan_request *req; + struct ieee80211_channel *chan; + struct ieee80211_vif *vif; + struct mt76_vif_link *mlink; + struct mt76_phy *phy; + int chan_idx; + } scan; + #ifdef CONFIG_NL80211_TESTMODE const struct mt76_testmode_ops *test_ops; struct { @@ -1018,6 +1096,10 @@ struct mt76_ethtool_worker_info { int sta_count; }; +struct mt76_chanctx { + struct mt76_phy *phy; +}; + #define CCK_RATE(_idx, _rate) { \ .bitrate = _rate, \ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ @@ -1080,12 +1162,7 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs); void mt76_pci_disable_aspm(struct pci_dev *pdev); - -#ifdef CONFIG_NET_MEDIATEK_SOC_WED -int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct net_device *netdev, enum tc_setup_type type, - void *type_data); -#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ +bool mt76_pci_aspm_supported(struct pci_dev *pdev); static inline u16 mt76_chip(struct mt76_dev *dev) { @@ -1097,13 +1174,34 @@ static inline u16 mt76_rev(struct mt76_dev *dev) return dev->rev & 0xffff; } +void mt76_wed_release_rx_buf(struct mtk_wed_device *wed); +void mt76_wed_offload_disable(struct mtk_wed_device *wed); +void mt76_wed_reset_complete(struct mtk_wed_device *wed); +void mt76_wed_dma_reset(struct mt76_dev *dev); +int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct net_device *netdev, enum tc_setup_type type, + void *type_data); #ifdef CONFIG_NET_MEDIATEK_SOC_WED -u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size); -void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed); -int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed); -void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed); -void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed); -#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ +u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size); +int mt76_wed_offload_enable(struct mtk_wed_device *wed); +int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset); +#else +static inline u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size) +{ + return 0; +} + +static inline int mt76_wed_offload_enable(struct mtk_wed_device *wed) +{ + return 0; +} + +static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, + bool reset) +{ + return 0; +} +#endif /* CONFIG_NET_MEDIATEK_SOC_WED */ #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76)) @@ -1111,7 +1209,7 @@ void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed); #define mt76_init_queues(dev, ...) (dev)->mt76.queue_ops->init(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) -#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__) +#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mphy), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__) @@ -1122,6 +1220,10 @@ void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed); for (i = 0; i < ARRAY_SIZE((dev)->q_rx); i++) \ if ((dev)->q_rx[i].ndesc) + +#define mt76_dereference(p, dev) \ + rcu_dereference_protected(p, lockdep_is_held(&(dev)->mutex)) + struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, const struct mt76_driver_ops *drv_ops); @@ -1131,11 +1233,15 @@ void mt76_unregister_device(struct mt76_dev *dev); void mt76_free_device(struct mt76_dev *dev); void mt76_unregister_phy(struct mt76_phy *phy); +struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size, + u8 band_idx); struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, const struct ieee80211_ops *ops, u8 band_idx); int mt76_register_phy(struct mt76_phy *phy, bool vht, struct ieee80211_rate *rates, int n_rates); +struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); struct dentry *mt76_register_debugfs_fops(struct mt76_phy *phy, const struct file_operations *ops); @@ -1157,8 +1263,6 @@ int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep, struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, int ring_base, void *wed, u32 flags); -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, void *wed, u32 flags) @@ -1240,6 +1344,9 @@ wcid_to_sta(struct mt76_wcid *wcid) if (!wcid || !wcid->sta) return NULL; + if (wcid->def_wcid) + ptr = wcid->def_wcid; + return container_of(ptr, struct ieee80211_sta, drv_priv); } @@ -1291,12 +1398,12 @@ static inline bool mt76_is_skb_pktid(u8 pktid) return pktid >= MT_PACKET_ID_FIRST; } -static inline u8 mt76_tx_power_nss_delta(u8 nss) +static inline u8 mt76_tx_power_path_delta(u8 path) { - static const u8 nss_delta[4] = { 0, 6, 9, 12 }; - u8 idx = nss - 1; + static const u8 path_delta[5] = { 0, 6, 9, 12, 14 }; + u8 idx = path - 1; - return (idx < ARRAY_SIZE(nss_delta)) ? nss_delta[idx] : 0; + return (idx < ARRAY_SIZE(path_delta)) ? path_delta[idx] : 0; } static inline bool mt76_testmode_enabled(struct mt76_phy *phy) @@ -1346,7 +1453,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw, enum ieee80211_frame_release_type reason, bool more_data); bool mt76_has_tx_pending(struct mt76_phy *phy); -void mt76_set_channel(struct mt76_phy *phy); +int mt76_update_channel(struct mt76_phy *phy); void mt76_update_survey(struct mt76_phy *phy); void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time); int mt76_get_survey(struct ieee80211_hw *hw, int idx, @@ -1386,15 +1493,17 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); -void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, +void __mt76_sta_remove(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy); +int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx); + +s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int *dbm); + unsigned int link_id, int *dbm); int mt76_init_sar_power(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); int mt76_get_sar_power(struct mt76_phy *phy, @@ -1410,11 +1519,38 @@ void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id); int mt76_get_rate(struct mt76_dev *dev, struct ieee80211_supported_band *sband, int idx, bool cck); +int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req); +void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif); enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy); +int mt76_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf); +void mt76_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf); +void mt76_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + u32 changed); +int mt76_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *conf); +void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *conf); +int mt76_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, + enum ieee80211_chanctx_switch_mode mode); +int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration, + enum ieee80211_roc_type type); +int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, @@ -1460,6 +1596,18 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames); void mt76_testmode_tx_pending(struct mt76_phy *phy); void mt76_queue_tx_complete(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_entry *e); +int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, + bool offchannel); +int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, + bool offchannel); +void mt76_scan_work(struct work_struct *work); +void mt76_abort_scan(struct mt76_dev *dev); +void mt76_roc_complete_work(struct work_struct *work); +void mt76_abort_roc(struct mt76_phy *phy); +struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, + struct ieee80211_vif *vif); +void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct mt76_vif_link *mlink); /* usb */ static inline bool mt76u_urb_error(struct urb *urb) @@ -1470,13 +1618,6 @@ static inline bool mt76u_urb_error(struct urb *urb) urb->status != -ENOENT; } -/* Map hardware queues to usb endpoints */ -static inline u8 q2ep(u8 qid) -{ - /* TODO: take management packets to queue 5 */ - return qid + 1; -} - static inline int mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, int timeout, int ep) @@ -1598,6 +1739,18 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, struct mt76_power_limits *dest, s8 target_power); +static inline bool mt76_queue_is_rx(struct mt76_dev *dev, struct mt76_queue *q) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + if (q == &dev->q_rx[i]) + return true; + } + + return false; +} + static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q) { return (q->flags & MT_QFLAG_WED) && @@ -1690,7 +1843,54 @@ mt76_token_put(struct mt76_dev *dev, int token) return txwi; } -void mt76_wcid_init(struct mt76_wcid *wcid); +void mt76_wcid_init(struct mt76_wcid *wcid, u8 band_idx); void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid); +void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid); + +static inline void +mt76_vif_init(struct ieee80211_vif *vif, struct mt76_vif_data *mvif) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + + mlink->mvif = mvif; + rcu_assign_pointer(mvif->link[0], mlink); +} + +void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif); + +static inline struct mt76_vif_link * +mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + + return mt76_dereference(mvif->link[link_id], dev); +} + +static inline struct mt76_vif_link * +mt76_vif_conf_link(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; + struct mt76_vif_data *mvif = mlink->mvif; + + if (link_conf == &vif->bss_conf) + return mlink; + + return mt76_dereference(mvif->link[link_conf->link_id], dev); +} + +static inline struct mt76_phy * +mt76_vif_link_phy(struct mt76_vif_link *mlink) +{ + struct mt76_chanctx *ctx; + + if (!mlink->ctx) + return NULL; + + ctx = (struct mt76_chanctx *)mlink->ctx->drv_priv; + + return ctx->phy; +} #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index c223f7c19e6d..6457ee06bb5a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -107,7 +107,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) struct sk_buff *skb; int i, nframes; - if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (dev->mphy.offchannel) return; data.dev = dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 7a2f5d38562b..863e5770df51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -4,6 +4,13 @@ #include "mac.h" #include "../dma.h" +static const u8 wmm_queue_map[] = { + [IEEE80211_AC_BK] = 0, + [IEEE80211_AC_BE] = 1, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_VO] = 3, +}; + static void mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) { @@ -22,10 +29,10 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) struct ieee80211_sta *sta; struct mt7603_sta *msta; struct mt76_wcid *wcid; + u8 qid, tid = 0, hwq = 0; void *priv; int idx; u32 val; - u8 tid = 0; if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) goto free; @@ -42,19 +49,36 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) goto free; priv = msta = container_of(wcid, struct mt7603_sta, wcid); - val = le32_to_cpu(txd[0]); - val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); - val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); - txd[0] = cpu_to_le32(val); sta = container_of(priv, struct ieee80211_sta, drv_priv); hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE]; - if (ieee80211_is_data_qos(hdr->frame_control)) + + hwq = wmm_queue_map[IEEE80211_AC_BE]; + if (ieee80211_is_data_qos(hdr->frame_control)) { tid = *ieee80211_get_qos_ctl(hdr) & - IEEE80211_QOS_CTL_TAG1D_MASK; - skb_set_queue_mapping(skb, tid_to_ac[tid]); + IEEE80211_QOS_CTL_TAG1D_MASK; + qid = tid_to_ac[tid]; + hwq = wmm_queue_map[qid]; + skb_set_queue_mapping(skb, qid); + } else if (ieee80211_is_data(hdr->frame_control)) { + skb_set_queue_mapping(skb, IEEE80211_AC_BE); + hwq = wmm_queue_map[IEEE80211_AC_BE]; + } else { + skb_pull(skb, MT_TXD_SIZE); + if (!ieee80211_is_bufferable_mmpdu(skb)) + goto free; + skb_push(skb, MT_TXD_SIZE); + skb_set_queue_mapping(skb, MT_TXQ_PSD); + hwq = MT_TX_HW_QUEUE_MGMT; + } + ieee80211_sta_set_buffered(sta, tid, true); + val = le32_to_cpu(txd[0]); + val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); + val |= FIELD_PREP(MT_TXD0_Q_IDX, hwq); + txd[0] = cpu_to_le32(val); + spin_lock_bh(&dev->ps_lock); __skb_queue_tail(&msta->psq, skb); if (skb_queue_len(&msta->psq) >= 64) { @@ -151,12 +175,6 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget) int mt7603_dma_init(struct mt7603_dev *dev) { - static const u8 wmm_queue_map[] = { - [IEEE80211_AC_BK] = 0, - [IEEE80211_AC_BE] = 1, - [IEEE80211_AC_VI] = 2, - [IEEE80211_AC_VO] = 3, - }; int ret; int i; @@ -224,7 +242,7 @@ int mt7603_dma_init(struct mt7603_dev *dev) if (ret) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7603_poll_tx); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c index d951cb81df83..f5a6b03bc61d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c @@ -181,6 +181,7 @@ int mt7603_eeprom_init(struct mt7603_dev *dev) is_mt7688(dev)) dev->mphy.antenna_mask = 1; + dev->mphy.chainmask = dev->mphy.antenna_mask; mt76_eeprom_override(&dev->mphy); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 6c55c72f28a2..86617a3e4328 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -15,9 +15,10 @@ const struct mt76_driver_ops mt7603_drv_ops = { .rx_poll_complete = mt7603_rx_poll_complete, .sta_ps = mt7603_sta_ps, .sta_add = mt7603_sta_add, - .sta_assoc = mt7603_sta_assoc, + .sta_event = mt7603_sta_event, .sta_remove = mt7603_sta_remove, .update_survey = mt7603_update_channel, + .set_channel = mt7603_set_channel, }; static void @@ -456,11 +457,13 @@ mt7603_init_txpower(struct mt7603_dev *dev, int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; bool ext_pa = eeprom[MT_EE_NIC_CONF_0 + 1] & BIT(1); + u8 ext_pa_pwr; int max_offset, cur_offset; int i; - if (ext_pa && is_mt7603(dev)) - target_power = eeprom[MT_EE_TX_POWER_TSSI_OFF] & ~BIT(7); + ext_pa_pwr = eeprom[MT_EE_TX_POWER_TSSI_OFF]; + if (ext_pa && is_mt7603(dev) && ext_pa_pwr != 0 && ext_pa_pwr != 0xff) + target_power = ext_pa_pwr & ~BIT(7); if (target_power & BIT(6)) target_power = -(target_power & GENMASK(5, 0)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index cf21d06257e5..413973d05b43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1277,12 +1277,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) msta = container_of(wcid, struct mt7603_sta, wcid); sta = wcid_to_sta(wcid); - - if (list_empty(&msta->wcid.poll_list)) { - spin_lock_bh(&dev->mt76.sta_poll_lock); - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); - } + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) goto out; @@ -1393,6 +1388,7 @@ void mt7603_pse_client_reset(struct mt7603_dev *dev) MT_CLIENT_RESET_TX_R_E_2_S); /* Start PSE client TX abort */ + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, MT_CLIENT_RESET_TX_R_E_1_S, 500); @@ -1483,14 +1479,13 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt7603_beacon_set_timer(dev, -1, beacon_int); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); - napi_schedule(&dev->mt76.tx_napi); - napi_enable(&dev->mt76.napi[0]); - napi_schedule(&dev->mt76.napi[0]); - napi_enable(&dev->mt76.napi[1]); + + local_bh_disable(); + napi_schedule(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.napi[0]); napi_schedule(&dev->mt76.napi[1]); local_bh_enable(); @@ -1792,7 +1787,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev) mt7603_cca_stats_reset(dev); - min_signal = mt76_get_min_avg_rssi(&dev->mt76, false); + min_signal = mt76_get_min_avg_rssi(&dev->mt76, 0); if (!min_signal) { dev->sensitivity = 0; dev->last_cca_adj = jiffies; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index e2146d30e553..3e8b1ec76169 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -23,7 +23,7 @@ mt7603_start(struct ieee80211_hw *hw) } static void -mt7603_stop(struct ieee80211_hw *hw) +mt7603_stop(struct ieee80211_hw *hw, bool suspend) { struct mt7603_dev *dev = hw->priv; @@ -66,11 +66,9 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; dev->mt76.vif_mask |= BIT_ULL(mvif->idx); - INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.hw_key_idx = -1; mvif->sta.vif = mvif; - mt76_wcid_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid, 0); eth_broadcast_addr(bc_addr); mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); @@ -133,30 +131,24 @@ void mt7603_init_edcca(struct mt7603_dev *dev) mt7603_edcca_set_strict(dev, false); } -static int -mt7603_set_channel(struct ieee80211_hw *hw, struct cfg80211_chan_def *def) +int mt7603_set_channel(struct mt76_phy *mphy) { - struct mt7603_dev *dev = hw->priv; + struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, mt76); + struct cfg80211_chan_def *def = &mphy->chandef; + u8 *rssi_data = (u8 *)dev->mt76.eeprom.data; int idx, ret; u8 bw = MT_BW_20; bool failed = false; - ieee80211_stop_queues(hw); - cancel_delayed_work_sync(&dev->mphy.mac_work); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); - mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mphy.state); - mt7603_beacon_set_timer(dev, -1, 0); - mt76_set_channel(&dev->mphy); mt7603_mac_stop(dev); if (def->width == NL80211_CHAN_WIDTH_40) bw = MT_BW_40; - dev->mphy.chandef = *def; mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); ret = mt7603_mcu_set_channel(dev); if (ret) { @@ -180,10 +172,6 @@ mt7603_set_channel(struct ieee80211_hw *hw, struct cfg80211_chan_def *def) mt7603_mac_set_timing(dev); mt7603_mac_start(dev); - clear_bit(MT76_RESET, &dev->mphy.state); - - mt76_txq_schedule_all(&dev->mphy); - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, msecs_to_jiffies(MT7603_WATCHDOG_TIME)); @@ -199,17 +187,14 @@ mt7603_set_channel(struct ieee80211_hw *hw, struct cfg80211_chan_def *def) mt7603_init_edcca(dev); out: - if (!(mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)) + if (!mphy->offchannel) mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int); - mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); if (failed) mt7603_mac_work(&dev->mphy.mac_work.work); - ieee80211_wake_queues(hw); - return ret; } @@ -227,7 +212,7 @@ static int mt7603_set_sar_specs(struct ieee80211_hw *hw, if (err) return err; - return mt7603_set_channel(hw, &mphy->chandef); + return mt76_update_channel(mphy); } static int @@ -238,7 +223,7 @@ mt7603_config(struct ieee80211_hw *hw, u32 changed) if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | IEEE80211_CONF_CHANGE_POWER)) - ret = mt7603_set_channel(hw, &hw->conf.chandef); + ret = mt76_update_channel(&dev->mphy); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { mutex_lock(&dev->mt76.mutex); @@ -368,13 +353,19 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, return ret; } -void -mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int +mt7603_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); - mt7603_wtbl_update_cap(dev, sta); + if (ev == MT76_STA_EVENT_ASSOC) { + mutex_lock(&dev->mt76.mutex); + mt7603_wtbl_update_cap(dev, sta); + mutex_unlock(&dev->mt76.mutex); + } + + return 0; } void @@ -701,6 +692,10 @@ static void mt7603_tx(struct ieee80211_hw *hw, } const struct ieee80211_ops mt7603_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt7603_tx, .start = mt7603_start, .stop = mt7603_stop, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 9e58df7042ad..55a034ccbacd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -213,6 +213,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev); void mt7603_pse_client_reset(struct mt7603_dev *dev); +int mt7603_set_channel(struct mt76_phy *mphy); int mt7603_mcu_set_channel(struct mt7603_dev *dev); int mt7603_mcu_set_eeprom(struct mt7603_dev *dev); void mt7603_mcu_exit(struct mt7603_dev *dev); @@ -245,8 +246,8 @@ void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); void mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); int mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int mt7603_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev); void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c index ec02148a7f1f..08590aa68356 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c @@ -71,7 +71,7 @@ MODULE_FIRMWARE(MT7628_FIRMWARE_E2); struct platform_driver mt76_wmac_driver = { .probe = mt76_wmac_probe, - .remove_new = mt76_wmac_remove, + .remove = mt76_wmac_remove, .driver = { .name = "mt76_wmac", .of_match_table = of_wmac_match, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index e7135b2f1742..bcf7864312d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -67,7 +67,7 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) { struct mt7615_dev *dev; - dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); + dev = mt76_priv(napi->dev); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { napi_complete(napi); queue_work(dev->mt76.wq, &dev->pm.wake_work); @@ -89,7 +89,7 @@ static int mt7615_poll_rx(struct napi_struct *napi, int budget) struct mt7615_dev *dev; int done; - dev = container_of(napi->dev, struct mt7615_dev, mt76.napi_dev); + dev = mt76_priv(napi->dev); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { napi_complete(napi); @@ -282,7 +282,7 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret < 0) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7615_poll_tx); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index f7722f67db57..aae80005a3c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -56,6 +56,9 @@ int mt7615_thermal_init(struct mt7615_dev *dev) name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", wiphy_name(wiphy)); + if (!name) + return -ENOMEM; + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, mt7615_hwmon_groups); return PTR_ERR_OR_ZERO(hwmon); @@ -270,7 +273,7 @@ void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) { int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; - int delta_idx, delta = mt76_tx_power_nss_delta(n_chains); + int delta_idx, delta = mt76_tx_power_path_delta(n_chains); u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; struct mt76_power_limits limits; @@ -319,7 +322,7 @@ void mt7615_init_work(struct mt7615_dev *dev) mt7615_mcu_set_eeprom(dev); mt7615_mac_init(dev); mt7615_phy_init(dev); - mt7615_mcu_del_wtbl_all(dev); + mt76_connac_mcu_del_wtbl_all(&dev->mt76); mt7615_check_offload_capability(dev); } EXPORT_SYMBOL_GPL(mt7615_init_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 7ba789834e8d..3ca4fae7c4b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -387,11 +387,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) struct mt7615_sta *msta; msta = container_of(status->wcid, struct mt7615_sta, wcid); - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); } if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && @@ -734,7 +730,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, u16 seqno = 0; if (vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; omac_idx = mvif->omac_idx; wmm_idx = mvif->wmm_idx; @@ -1514,11 +1510,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) msta = container_of(wcid, struct mt7615_sta, wcid); sta = wcid_to_sta(wcid); - - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data)) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 0971c164b57e..c54005df08ca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -91,13 +91,13 @@ out: return ret; } -static void mt7615_stop(struct ieee80211_hw *hw) +static void mt7615_stop(struct ieee80211_hw *hw, bool suspend) { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&dev->pm.ps_work); @@ -209,6 +209,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, mvif->mt76.band_idx = ext_phy; mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; + mvif->mt76.wcid = &mvif->sta.wcid; if (ext_phy) mvif->mt76.wmm_idx += 2; @@ -224,9 +225,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; - mvif->sta.wcid.hw_key_idx = -1; - mt76_wcid_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid, mvif->mt76.band_idx); mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -282,19 +281,14 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid); } -int mt7615_set_channel(struct mt7615_phy *phy) +int mt7615_set_channel(struct mt76_phy *mphy) { + struct mt7615_phy *phy = mphy->priv; struct mt7615_dev *dev = phy->dev; bool ext_phy = phy != &dev->phy; int ret; - cancel_delayed_work_sync(&phy->mt76->mac_work); - - mt7615_mutex_acquire(dev); - - set_bit(MT76_RESET, &phy->mt76->state); - - mt76_set_channel(phy->mt76); + mt76_connac_pm_wake(mphy, &dev->pm); if (is_mt7615(&dev->mt76) && dev->flash_eeprom) { ret = mt7615_mcu_apply_rx_dcoc(phy); @@ -325,11 +319,8 @@ int mt7615_set_channel(struct mt7615_phy *phy) phy->chfreq = mt76_rr(dev, MT_CHFREQ(ext_phy)); out: - clear_bit(MT76_RESET, &phy->mt76->state); + mt76_connac_power_save_sched(mphy, &dev->pm); - mt7615_mutex_release(dev); - - mt76_worker_schedule(&dev->mt76.tx_worker); if (!mt76_testmode_enabled(phy->mt76)) { unsigned long timeout = mt7615_get_macwork_timeout(dev); @@ -339,6 +330,7 @@ out: return ret; } +EXPORT_SYMBOL_GPL(mt7615_set_channel); static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -425,11 +417,7 @@ static int mt7615_set_sar_specs(struct ieee80211_hw *hw, if (mt7615_firmware_offload(phy->dev)) return mt76_connac_mcu_set_rate_txpower(phy->mt76); - ieee80211_stop_queues(hw); - err = mt7615_set_channel(phy); - ieee80211_wake_queues(hw); - - return err; + return mt76_update_channel(phy->mt76); } static int mt7615_config(struct ieee80211_hw *hw, u32 changed) @@ -448,9 +436,7 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) mt7615_mutex_release(dev); } #endif - ieee80211_stop_queues(hw); - ret = mt7615_set_channel(phy); - ieee80211_wake_queues(hw); + ret = mt76_update_channel(phy->mt76); } mt7615_mutex_acquire(dev); @@ -476,7 +462,7 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); int err; @@ -1208,7 +1194,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt7615_mutex_acquire(phy->dev); @@ -1262,7 +1248,7 @@ static int mt7615_suspend(struct ieee80211_hw *hw, phy->mt76); if (!mt7615_dev_running(dev)) - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, true); mt7615_mutex_release(dev); @@ -1284,7 +1270,7 @@ static int mt7615_resume(struct ieee80211_hw *hw) if (!running) { int err; - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false, true); if (err < 0) { mt7615_mutex_release(dev); return err; @@ -1326,6 +1312,10 @@ static void mt7615_set_rekey_data(struct ieee80211_hw *hw, #endif /* CONFIG_PM */ const struct ieee80211_ops mt7615_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt7615_tx, .start = mt7615_start, .stop = mt7615_stop, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index ae34d019e588..4064e193d4de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -353,7 +353,7 @@ static void mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { if (vif->bss_conf.csa_active) - ieee80211_csa_finish(vif); + ieee80211_csa_finish(vif, 0); } static void @@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC) return; - ieee80211_radar_detected(mphy->hw); + ieee80211_radar_detected(mphy->hw, NULL); dev->hw_pattern++; } @@ -842,13 +842,16 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct sk_buff *skb, *sskb, *wskb = NULL; + struct ieee80211_link_sta *link_sta; struct mt7615_dev *dev = phy->dev; struct wtbl_req_hdr *wtbl_hdr; struct mt7615_sta *msta; bool new_entry = true; + int conn_state; int cmd, err; msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; + link_sta = sta ? &sta->deflink : NULL; sskb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &msta->wcid); @@ -861,8 +864,9 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, else mvif->sta_added = true; } - mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, vif, sta, enable, - new_entry); + conn_state = enable ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT; + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, &vif->bss_conf, + link_sta, conn_state, new_entry); if (enable && sta) mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0, MT76_STA_INFO_STATE_ASSOC); @@ -1109,8 +1113,8 @@ mt7615_mcu_uni_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - return mt76_connac_mcu_uni_add_dev(phy->mt76, vif, &mvif->sta.wcid, - enable); + return mt76_connac_mcu_uni_add_dev(phy->mt76, &vif->bss_conf, &mvif->mt76, + &mvif->sta.wcid, enable); } static int @@ -1696,7 +1700,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) }; int ret; - dev->mt76.mcu_ops = &mt7615_mcu_ops, + dev->mt76.mcu_ops = &mt7615_mcu_ops; ret = mt7615_mcu_drv_pmctrl(dev); if (ret) @@ -1876,16 +1880,6 @@ out: sizeof(req), true); } -int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) -{ - struct wtbl_req_hdr req = { - .operation = WTBL_RESET_ALL, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(WTBL_UPDATE), - &req, sizeof(req), true); -} - int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) { struct { @@ -2073,7 +2067,7 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) }; tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power); - tx_power -= mt76_tx_power_nss_delta(n_chains); + tx_power -= mt76_tx_power_path_delta(n_chains); tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, &limits, tx_power); mphy->txpower_cur = tx_power; @@ -2090,8 +2084,8 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) int delta = 0; if (i < n_chains - 1) - delta = mt76_tx_power_nss_delta(n_chains) - - mt76_tx_power_nss_delta(i + 1); + delta = mt76_tx_power_path_delta(n_chains) - + mt76_tx_power_path_delta(i + 1); sku[MT_SKU_1SS_DELTA + i] = delta; } } @@ -2149,7 +2143,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) if (cmd == MCU_EXT_CMD(SET_RX_PATH) || phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + else if (phy->mt76->offchannel) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, NL80211_IFTYPE_AP)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 87a956ea3ad7..dbb2c82407df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -182,6 +182,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, + .set_channel = mt7615_set_channel, }; struct mt76_bus_ops *bus_ops; struct ieee80211_ops *ops; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index a20322aae967..9bdd29e8d25e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -139,7 +139,7 @@ struct mt7615_sta { }; struct mt7615_vif { - struct mt76_vif mt76; /* must be first */ + struct mt76_vif_link mt76; /* must be first */ struct mt7615_sta sta; bool sta_added; }; @@ -399,7 +399,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *rates); void mt7615_pm_wake_work(struct work_struct *work); void mt7615_pm_power_save_work(struct work_struct *work); -int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); @@ -457,7 +456,7 @@ void mt7615_roc_work(struct work_struct *work); void mt7615_roc_timer(struct timer_list *timer); void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband); -int mt7615_set_channel(struct mt7615_phy *phy); +int mt7615_set_channel(struct mt76_phy *mphy); void mt7615_init_work(struct mt7615_dev *dev); int mt7615_mcu_restart(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 9f43e673518b..68010e27f065 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -83,7 +83,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) && mt7615_firmware_offload(dev); if (hif_suspend) { - err = mt76_connac_mcu_set_hif_suspend(mdev, true); + err = mt76_connac_mcu_set_hif_suspend(mdev, true, true); if (err) return err; } @@ -131,7 +131,7 @@ restore: } napi_enable(&mdev->tx_napi); if (hif_suspend) - mt76_connac_mcu_set_hif_suspend(mdev, false); + mt76_connac_mcu_set_hif_suspend(mdev, false, true); return err; } @@ -164,18 +164,22 @@ static int mt7615_pci_resume(struct pci_dev *pdev) dev_err(mdev->dev, "PDMA engine must be reinitialized\n"); 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); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_schedule(&mdev->napi[i]); + } napi_schedule(&mdev->tx_napi); local_bh_enable(); if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) && mt7615_firmware_offload(dev)) - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + err = mt76_connac_mcu_set_hif_suspend(mdev, false, true); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index fbb1181c58ff..b795d11d943d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -48,7 +48,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); if (vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; txp->bss_idx = mvif->idx; } @@ -220,12 +220,12 @@ void mt7615_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->mphy.mac_work); - del_timer_sync(&dev->phy.roc_timer); + timer_delete_sync(&dev->phy.roc_timer); cancel_work_sync(&dev->phy.roc_work); if (phy2) { set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); - del_timer_sync(&phy2->roc_timer); + timer_delete_sync(&phy2->roc_timer); cancel_work_sync(&phy2->roc_work); } @@ -262,12 +262,14 @@ void mt7615_mac_reset_work(struct work_struct *work) mt76_worker_enable(&dev->mt76.tx_worker); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); - napi_schedule(&dev->mt76.tx_napi); - mt76_for_each_q_rx(&dev->mt76, i) { napi_enable(&dev->mt76.napi[i]); + } + + local_bh_disable(); + napi_schedule(&dev->mt76.tx_napi); + mt76_for_each_q_rx(&dev->mt76, i) { napi_schedule(&dev->mt76.napi[i]); } local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 9692890ba51b..f56038cd4d3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -87,6 +87,7 @@ static int mt7663s_probe(struct sdio_func *func, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, + .set_channel = mt7615_set_channel, }; static const struct mt76_bus_ops mt7663s_ops = { .rr = mt76s_rr, @@ -190,7 +191,7 @@ static int mt7663s_suspend(struct device *dev) mt7615_firmware_offload(mdev)) { int err; - err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, true); + err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, true, true); if (err < 0) return err; } @@ -229,7 +230,7 @@ static int mt7663s_resume(struct device *dev) if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) && mt7615_firmware_offload(mdev)) - err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, false); + err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, false, true); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c index b0094205ba95..a7b8acb2da83 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c @@ -147,7 +147,7 @@ int mt7663s_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - dev->mt76.mcu_ops = &mt7663s_mcu_ops, + dev->mt76.mcu_ops = &mt7663s_mcu_ops; ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY); if (ret) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c index 12e3e4a91d27..06a0f2a141e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -63,7 +63,7 @@ struct platform_driver mt7622_wmac_driver = { .of_match_table = mt7622_wmac_of_match, }, .probe = mt7622_wmac_probe, - .remove_new = mt7622_wmac_remove, + .remove = mt7622_wmac_remove, }; MODULE_FIRMWARE(MT7622_FIRMWARE_N9); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c index a3d1cfa729ed..03f5af84424b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c @@ -141,7 +141,7 @@ mt7615_tm_init(struct mt7615_phy *phy) mt7615_mcu_set_sku_en(phy, phy->mt76->test.state == MT76_TM_STATE_OFF); mutex_unlock(&dev->mt76.mutex); - mt7615_set_channel(phy); + mt76_update_channel(phy->mt76); mt7615_ops.configure_filter(phy->mt76->hw, 0, &total_flags, 0); mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index df737e1ff27b..d96e06b4fee1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -79,13 +79,13 @@ static void mt7663u_copy(struct mt76_dev *dev, u32 offset, mutex_unlock(&usb->usb_ctrl_mtx); } -static void mt7663u_stop(struct ieee80211_hw *hw) +static void mt7663u_stop(struct ieee80211_hw *hw, bool suspend) { struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_dev *dev = hw->priv; clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -123,6 +123,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, + .set_channel = mt7615_set_channel, }; static struct mt76_bus_ops bus_ops = { .rr = mt7663u_rr, @@ -224,7 +225,7 @@ static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state) mt7615_firmware_offload(dev)) { int err; - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, true); if (err < 0) return err; } @@ -252,7 +253,7 @@ static int mt7663u_resume(struct usb_interface *intf) if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) && mt7615_firmware_offload(dev)) - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false, true); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index a8b1a0f8b2d7..33c01f8ce8e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -72,7 +72,7 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) }; int ret; - dev->mt76.mcu_ops = &mt7663u_mcu_ops, + dev->mt76.mcu_ops = &mt7663u_mcu_ops; mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index fdde3d70b300..192dcc374a64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -177,6 +177,11 @@ static inline bool is_mt7925(struct mt76_dev *dev) return mt76_chip(dev) == 0x7925; } +static inline bool is_mt7920(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7920; +} + static inline bool is_mt7922(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7922; @@ -184,7 +189,7 @@ static inline bool is_mt7922(struct mt76_dev *dev) static inline bool is_mt7921(struct mt76_dev *dev) { - return mt76_chip(dev) == 0x7961 || is_mt7922(dev); + return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev); } static inline bool is_mt7663(struct mt76_dev *dev) @@ -227,6 +232,16 @@ static inline bool is_mt7992(struct mt76_dev *dev) return mt76_chip(dev) == 0x7992; } +static inline bool is_mt7990(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7993; +} + +static inline bool is_mt799x(struct mt76_dev *dev) +{ + return is_mt7996(dev) || is_mt7992(dev) || is_mt7990(dev); +} + static inline bool is_mt7622(struct mt76_dev *dev) { if (!IS_ENABLED(CONFIG_MT7622_WMAC)) @@ -254,6 +269,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev) { switch (mt76_chip(dev)) { case 0x7961: + case 0x7920: case 0x7922: case 0x7925: case 0x7663: @@ -394,7 +410,7 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm) mutex_unlock(&dev->mutex); } -void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss); +void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss, enum nl80211_band band); int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, int ring_base, void *wed, u32 flags); @@ -416,7 +432,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed); u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, - struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, bool beacon, bool mcast); bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, __le32 *txs_data); @@ -440,4 +456,6 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev); /* connac3 */ void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode); +void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode); #endif /* __MT76_CONNAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h index bd2a92467a97..eb4765365b8c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h @@ -32,6 +32,11 @@ enum { MT_LMAC_PSMP0, }; +enum { + MT_TXS_MPDU_FMT = 0, + MT_TXS_PPDU_FMT = 2, +}; + #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) #define MT_TX_FREE_COUNT GENMASK(12, 0) @@ -350,4 +355,11 @@ enum tx_port_idx { MT_TX_PORT_IDX_MCU }; +enum tx_frag_idx { + MT_TX_FRAG_NONE, + MT_TX_FRAG_FIRST, + MT_TX_FRAG_MID, + MT_TX_FRAG_LAST +}; + #endif /* __MT76_CONNAC2_MAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c index 73e9f283d0ae..2d300948308d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c @@ -6,8 +6,11 @@ #include "dma.h" #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define EHT_BITS(f) cpu_to_le32(IEEE80211_RADIOTAP_EHT_##f) #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ IEEE80211_RADIOTAP_HE_##f) +#define EHT_PREP(f, m, v) le32_encode_bits(le32_get_bits(v, MT_CRXV_EHT_##m),\ + IEEE80211_RADIOTAP_EHT_##f) static void mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, @@ -180,3 +183,86 @@ void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, } } EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap); + +static void * +mt76_connac3_mac_radiotap_push_tlv(struct sk_buff *skb, u16 type, u16 len) +{ + struct ieee80211_radiotap_tlv *tlv; + + tlv = skb_push(skb, sizeof(*tlv) + len); + tlv->type = cpu_to_le16(type); + tlv->len = cpu_to_le16(len); + memset(tlv->data, 0, len); + + return tlv->data; +} + +void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ieee80211_radiotap_eht_usig *usig; + struct ieee80211_radiotap_eht *eht; + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; + u8 bw = FIELD_GET(MT_PRXV_FRAME_MODE, le32_to_cpu(rxv[2])); + + if (WARN_ONCE(skb_mac_header(skb) != skb->data, + "Should push tlv at the top of mac hdr")) + return; + + eht = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT, + sizeof(*eht) + sizeof(u32)); + usig = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG, + sizeof(*usig)); + + status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END; + + eht->known |= EHT_BITS(KNOWN_SPATIAL_REUSE) | + EHT_BITS(KNOWN_GI) | + EHT_BITS(KNOWN_EHT_LTF) | + EHT_BITS(KNOWN_LDPC_EXTRA_SYM_OM) | + EHT_BITS(KNOWN_PE_DISAMBIGUITY_OM) | + EHT_BITS(KNOWN_NSS_S); + + eht->data[0] |= + EHT_PREP(DATA0_SPATIAL_REUSE, SR_MASK, rxv[13]) | + cpu_to_le32(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI, status->eht.gi) | + FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF, ltf_size)) | + EHT_PREP(DATA0_PE_DISAMBIGUITY_OM, PE_DISAMBIG, rxv[5]) | + EHT_PREP(DATA0_LDPC_EXTRA_SYM_OM, LDPC_EXT_SYM, rxv[4]); + + /* iwlwifi and wireshark expect radiotap to report zero-based NSS, so subtract 1. */ + eht->data[7] |= le32_encode_bits(status->nss - 1, IEEE80211_RADIOTAP_EHT_DATA7_NSS_S); + + eht->user_info[0] |= + EHT_BITS(USER_INFO_MCS_KNOWN) | + EHT_BITS(USER_INFO_CODING_KNOWN) | + EHT_BITS(USER_INFO_NSS_KNOWN_O) | + EHT_BITS(USER_INFO_BEAMFORMING_KNOWN_O) | + EHT_BITS(USER_INFO_DATA_FOR_USER) | + le32_encode_bits(status->rate_idx, IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) | + le32_encode_bits(status->nss - 1, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O); + + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) + eht->user_info[0] |= EHT_BITS(USER_INFO_BEAMFORMING_O); + + if (le32_to_cpu(rxv[0]) & MT_PRXV_HT_AD_CODE) + eht->user_info[0] |= EHT_BITS(USER_INFO_CODING); + + if (mode == MT_PHY_TYPE_EHT_MU) + eht->user_info[0] |= EHT_BITS(USER_INFO_STA_ID_KNOWN) | + EHT_PREP(USER_INFO_STA_ID, MU_AID, rxv[8]); + + usig->common |= + EHT_BITS(USIG_COMMON_PHY_VER_KNOWN) | + EHT_BITS(USIG_COMMON_BW_KNOWN) | + EHT_BITS(USIG_COMMON_UL_DL_KNOWN) | + EHT_BITS(USIG_COMMON_BSS_COLOR_KNOWN) | + EHT_BITS(USIG_COMMON_TXOP_KNOWN) | + le32_encode_bits(0, IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER) | + le32_encode_bits(bw, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW) | + EHT_PREP(USIG_COMMON_UL_DL, UPLINK, rxv[5]) | + EHT_PREP(USIG_COMMON_BSS_COLOR, BSS_COLOR, rxv[9]) | + EHT_PREP(USIG_COMMON_TXOP, TXOP_DUR, rxv[9]); +} +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_eht_radiotap); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h index 83dcd964bfd0..1013cad57a7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h @@ -28,8 +28,6 @@ enum { #define MT_RXD0_MESH BIT(18) #define MT_RXD0_MHCP BIT(19) #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) -#define MT_RXD0_NORMAL_IP_SUM BIT(23) -#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) #define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) #define MT_RXD0_SW_PKT_TYPE_MAP 0x380F @@ -80,6 +78,8 @@ enum { #define MT_RXD3_NORMAL_BEACON_UC BIT(21) #define MT_RXD3_NORMAL_CO_ANT BIT(22) #define MT_RXD3_NORMAL_FCS_ERR BIT(24) +#define MT_RXD3_NORMAL_IP_SUM BIT(26) +#define MT_RXD3_NORMAL_UDP_TCP_SUM BIT(27) #define MT_RXD3_NORMAL_VLAN2ETH BIT(31) /* RXD DW4 */ @@ -142,6 +142,28 @@ enum { #define MT_CRXV_HE_RU3_L GENMASK(31, 27) #define MT_CRXV_HE_RU3_H GENMASK(3, 0) +#define MT_CRXV_EHT_NUM_USER GENMASK(26, 20) +#define MT_CRXV_EHT_LTF_SIZE GENMASK(28, 27) +#define MT_CRXV_EHT_LDPC_EXT_SYM BIT(30) +#define MT_CRXV_EHT_PE_DISAMBIG BIT(1) +#define MT_CRXV_EHT_UPLINK BIT(2) +#define MT_CRXV_EHT_MU_AID GENMASK(27, 17) +#define MT_CRXV_EHT_BEAM_CHNG BIT(29) +#define MT_CRXV_EHT_DOPPLER BIT(0) +#define MT_CRXV_EHT_BSS_COLOR GENMASK(15, 10) +#define MT_CRXV_EHT_TXOP_DUR GENMASK(23, 17) +#define MT_CRXV_EHT_SR_MASK GENMASK(11, 8) +#define MT_CRXV_EHT_SR1_MASK GENMASK(15, 12) +#define MT_CRXV_EHT_SR2_MASK GENMASK(19, 16) +#define MT_CRXV_EHT_SR3_MASK GENMASK(23, 20) +#define MT_CRXV_EHT_RU0 GENMASK(8, 0) +#define MT_CRXV_EHT_RU1 GENMASK(17, 9) +#define MT_CRXV_EHT_RU2 GENMASK(26, 18) +#define MT_CRXV_EHT_RU3_L GENMASK(31, 27) +#define MT_CRXV_EHT_RU3_H GENMASK(3, 0) +#define MT_CRXV_EHT_SIG_MCS GENMASK(19, 18) +#define MT_CRXV_EHT_LTF_SYM GENMASK(22, 20) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, @@ -175,6 +197,13 @@ enum tx_mgnt_type { MT_TX_ADDBA, }; +enum tx_frag_idx { + MT_TX_FRAG_NONE, + MT_TX_FRAG_FIRST, + MT_TX_FRAG_MID, + MT_TX_FRAG_LAST +}; + #define MT_CT_INFO_APPLY_TXD BIT(0) #define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) #define MT_CT_INFO_MGMT_FRAME BIT(2) @@ -244,6 +273,7 @@ enum tx_mgnt_type { #define MT_TXD6_TX_RATE GENMASK(21, 16) #define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) #define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) +#define MT_TXD6_TID_ADDBA GENMASK(10, 8) #define MT_TXD6_MSDU_CNT GENMASK(9, 4) #define MT_TXD6_MSDU_CNT_V2 GENMASK(15, 10) #define MT_TXD6_DIS_MAT BIT(3) @@ -285,6 +315,9 @@ enum tx_mgnt_type { #define MT_TXFREE_INFO_COUNT GENMASK(27, 24) #define MT_TXFREE_INFO_STAT GENMASK(29, 28) +#define MT_TXS_HDR_SIZE 4 /* Unit: DW */ +#define MT_TXS_SIZE 12 /* Unit: DW */ + #define MT_TXS0_BW GENMASK(31, 29) #define MT_TXS0_TID GENMASK(28, 26) #define MT_TXS0_AMPDU BIT(25) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index c7914643e9c0..e9ac8a7317a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -9,10 +9,13 @@ #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ IEEE80211_RADIOTAP_HE_##f) -void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss) +void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss, enum nl80211_band band) { static const u8 ppet16_ppet8_ru3_ru0[] = { 0x1c, 0xc7, 0x71 }; - u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ + u8 i, ppet_bits, ppet_size, ru_bit_mask = 0xf; + + if (band == NL80211_BAND_2GHZ) + ru_bit_mask = 0x3; he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, @@ -291,27 +294,28 @@ EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues); }) u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, - struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, bool beacon, bool mcast) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = mt76_vif_conf_link(mphy->dev, conf->vif, conf); 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; + int offset = 0; - if (!vif) + if (!conf) goto legacy; if (is_mt7921(mphy->dev)) { - rateidx = ffs(vif->bss_conf.basic_rates) - 1; + rateidx = ffs(conf->basic_rates) - 1; goto legacy; } if (beacon) { struct cfg80211_bitrate_mask *mask; - mask = &vif->bss_conf.beacon_tx_rate; + mask = &conf->beacon_tx_rate; __bitrate_mask_check(he_mcs, HE_SU); __bitrate_mask_check(vht_mcs, VHT); @@ -323,14 +327,25 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, } } - mcast_rate = vif->bss_conf.mcast_rate[band]; + mcast_rate = conf->mcast_rate[band]; if (mcast && mcast_rate > 0) rateidx = mcast_rate - 1; else - rateidx = ffs(vif->bss_conf.basic_rates) - 1; + rateidx = ffs(conf->basic_rates) - 1; legacy: - rateidx = mt76_calculate_default_rate(mphy, vif, rateidx); + if (band != NL80211_BAND_2GHZ) + offset = 4; + + /* pick the lowest rate for hidden nodes */ + if (rateidx < 0) + rateidx = 0; + + rateidx += offset; + if (rateidx >= ARRAY_SIZE(mt76_rates)) + rateidx = offset; + + rateidx = mt76_rates[rateidx].hw_value; mode = rateidx >> 8; rateidx &= GENMASK(7, 0); out: @@ -391,6 +406,7 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, bool multicast = is_multicast_ether_addr(hdr->addr1); u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; __le16 fc = hdr->frame_control; + __le16 sc = hdr->seq_ctrl; u8 fc_type, fc_stype; u32 val; @@ -432,6 +448,13 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, info->flags & IEEE80211_TX_CTL_USE_MINRATE) val |= MT_TXD2_FIX_RATE; + if (ieee80211_has_morefrags(fc) && ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_FIRST); + else if (ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_MID); + else if (!ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_LAST); + txwi[2] |= cpu_to_le32(val); if (ieee80211_is_beacon(fc)) { @@ -440,7 +463,7 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, } if (info->flags & IEEE80211_TX_CTL_INJECTED) { - u16 seqno = le16_to_cpu(hdr->seq_ctrl); + u16 seqno = le16_to_cpu(sc); if (ieee80211_is_back_req(hdr->frame_control)) { struct ieee80211_bar *bar; @@ -485,7 +508,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, bool amsdu_en = wcid->amsdu; if (vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; omac_idx = mvif->omac_idx; wmm_idx = mvif->wmm_idx; @@ -544,7 +567,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, val = FIELD_PREP(MT_TXD5_PID, pid); if (pid >= MT_PACKET_ID_FIRST) { val |= MT_TXD5_TX_STATUS_HOST; - amsdu_en = amsdu_en && !is_mt7921(dev); + amsdu_en = 0; } txwi[5] = cpu_to_le32(val); @@ -561,7 +584,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool multicast = ieee80211_is_data(hdr->frame_control) && is_multicast_ether_addr(hdr->addr1); - u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, + u16 rate = mt76_connac2_mac_tx_rate_val(mphy, &vif->bss_conf, beacon, multicast); u32 val = MT_TXD6_FIXED_BW; @@ -579,6 +602,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, spe_idx = 24 + phy_idx; txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, spe_idx)); } + + txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU); } } EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi); @@ -714,6 +739,9 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, struct sk_buff_head list; struct sk_buff *skb; + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_PPDU_FMT) + return false; + mt76_tx_status_lock(dev, &list); skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); if (skb) { @@ -1149,11 +1177,7 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, if (wcid && wcid->sta) { sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&wcid->poll_list)) - list_add_tail(&wcid->poll_list, - &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + mt76_wcid_add_poll(dev, wcid); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 3a20ba0d2492..cb13d0a76878 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -66,9 +66,8 @@ 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) || - (is_mt7992(dev) && addr == 0x900000)) + (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) || + (is_mt799x(dev) && addr == 0x900000)) cmd = MCU_CMD(PATCH_START_REQ); else cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ); @@ -189,7 +188,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_mac_enable); int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { u8 bss_idx; u8 ps_state; /* 0: device awake @@ -232,7 +231,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rts_thresh); void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_connac_beacon_loss_event *event = priv; if (mvif->idx != event->bss_idx) @@ -257,7 +256,7 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, }; u16 ntlv; - ptlv = skb_put(skb, len); + ptlv = skb_put_zero(skb, len); memcpy(ptlv, &tlv, sizeof(tlv)); ntlv = le16_to_cpu(ntlv_hdr->tlv_num); @@ -273,7 +272,7 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_nested_tlv); struct sk_buff * -__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, +__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct mt76_wcid *wcid, int len) { struct sta_req_hdr hdr = { @@ -283,6 +282,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, }; struct sk_buff *skb; + if (wcid && !wcid->sta && !wcid->sta_disabled) + hdr.muar_idx = 0xe; + mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo, &hdr.wlan_idx_hi); skb = mt76_mcu_msg_alloc(dev, NULL, len); @@ -326,7 +328,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req); void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; u8 omac_idx = mvif->omac_idx; struct bss_info_omac *omac; struct tlv *tlv; @@ -366,10 +368,11 @@ void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv); void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - bool enable, bool newly) + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + int conn_state, bool newly) { + struct ieee80211_vif *vif = link_conf->vif; struct sta_rec_basic *basic; struct tlv *tlv; int conn_type; @@ -379,17 +382,20 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, basic = (struct sta_rec_basic *)tlv; basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); - if (enable) { - if (newly) - basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); - basic->conn_state = CONN_STATE_PORT_SECURE; - } else { - basic->conn_state = CONN_STATE_DISCONNECT; - } + if (newly && conn_state != CONN_STATE_DISCONNECT) + basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); + basic->conn_state = conn_state; - if (!sta) { + if (!link_sta) { basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); - eth_broadcast_addr(basic->peer_addr); + + if (vif->type == NL80211_IFTYPE_STATION && + !is_zero_ether_addr(link_conf->bssid)) { + memcpy(basic->peer_addr, link_conf->bssid, ETH_ALEN); + basic->aid = cpu_to_le16(vif->cfg.aid); + } else { + eth_broadcast_addr(basic->peer_addr); + } return; } @@ -401,7 +407,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, else conn_type = CONNECTION_INFRA_STA; basic->conn_type = cpu_to_le32(conn_type); - basic->aid = cpu_to_le16(sta->aid); + basic->aid = cpu_to_le16(link_sta->sta->aid); break; case NL80211_IFTYPE_STATION: if (vif->p2p && !is_mt7921(dev)) @@ -413,15 +419,15 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, break; case NL80211_IFTYPE_ADHOC: basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); - basic->aid = cpu_to_le16(sta->aid); + basic->aid = cpu_to_le16(link_sta->sta->aid); break; default: WARN_ON(1); break; } - memcpy(basic->peer_addr, sta->addr, ETH_ALEN); - basic->qos = sta->wme; + memcpy(basic->peer_addr, link_sta->addr, ETH_ALEN); + basic->qos = link_sta->sta->wme; } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_basic_tlv); @@ -491,7 +497,7 @@ int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid, int cmd) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct wtbl_req_hdr *wtbl_hdr; struct tlv *sta_wtbl; struct sk_buff *skb; @@ -539,7 +545,7 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct ieee80211_sta *sta, void *sta_wtbl, void *wtbl_tlv) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct wtbl_generic *generic; struct wtbl_rx *rx; struct wtbl_spe *spe; @@ -783,7 +789,8 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2); u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, - enum nl80211_band band, struct ieee80211_sta *sta) + enum nl80211_band band, + struct ieee80211_link_sta *link_sta) { struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_vht_cap *vht_cap; @@ -791,11 +798,11 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, 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; + if (link_sta) { + ht_cap = &link_sta->ht_cap; + vht_cap = &link_sta->vht_cap; + he_cap = &link_sta->he_cap; + eht_cap = &link_sta->eht_cap; } else { struct ieee80211_supported_band *sband; @@ -842,7 +849,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_vif *vif, u8 rcpi, u8 sta_state) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct cfg80211_chan_def *chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef; enum nl80211_band band = chandef->chan->band; @@ -901,7 +908,8 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy)); phy = (struct sta_rec_phy *)tlv; - phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band, sta); + phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band, + &sta->deflink); phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates); phy->rcpi = rcpi; phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR, @@ -1033,19 +1041,28 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv); int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy, struct mt76_sta_cmd_info *info) { - struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)info->vif->drv_priv; + struct ieee80211_link_sta *link_sta; struct mt76_dev *dev = phy->dev; struct wtbl_req_hdr *wtbl_hdr; struct tlv *sta_wtbl; struct sk_buff *skb; + int conn_state; + + if (!info->link_conf) + info->link_conf = &info->vif->bss_conf; skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); + conn_state = info->enable ? CONN_STATE_PORT_SECURE : + CONN_STATE_DISCONNECT; + link_sta = info->sta ? &info->sta->deflink : NULL; if (info->sta || !info->offload_fw) - mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta, - info->enable, info->newly); + mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, + link_sta, conn_state, + info->newly); if (info->sta && info->enable) mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif, info->rcpi, @@ -1122,11 +1139,11 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb, EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ba_tlv); int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, - struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + struct mt76_vif_link *mvif, struct mt76_wcid *wcid, bool enable) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct mt76_dev *dev = phy->dev; struct { struct { @@ -1138,7 +1155,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, __le16 tag; __le16 len; u8 active; - u8 pad; + u8 link_idx; /* not link_id */ u8 omac_addr[ETH_ALEN]; } __packed tlv; } dev_req = { @@ -1150,6 +1167,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, .tag = cpu_to_le16(DEV_INFO_ACTIVE), .len = cpu_to_le16(sizeof(struct req_tlv)), .active = enable, + .link_idx = mvif->link_idx, }, }; struct { @@ -1172,12 +1190,13 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, .bmc_tx_wlan_idx = cpu_to_le16(wcid->idx), .sta_idx = cpu_to_le16(wcid->idx), .conn_state = 1, + .link_idx = mvif->link_idx, }, }; int err, idx, cmd, len; void *data; - switch (vif->type) { + switch (bss_conf->vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: @@ -1186,6 +1205,9 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, case NL80211_IFTYPE_STATION: basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); break; + case NL80211_IFTYPE_P2P_DEVICE: + basic_req.basic.conn_type = cpu_to_le32(CONNECTION_P2P_GO); + break; case NL80211_IFTYPE_ADHOC: basic_req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); break; @@ -1197,7 +1219,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; basic_req.basic.hw_bss_idx = idx; - memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN); + memcpy(dev_req.tlv.omac_addr, bss_conf->addr, ETH_ALEN); cmd = enable ? MCU_UNI_CMD(DEV_INFO_UPDATE) : MCU_UNI_CMD(BSS_INFO_UPDATE); data = enable ? (void *)&dev_req : (void *)&basic_req; @@ -1247,7 +1269,7 @@ int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_wed_update); -int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, +int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct ieee80211_ampdu_params *params, int cmd, bool enable, bool tx) { @@ -1295,7 +1317,8 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba); u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, - enum nl80211_band band, struct ieee80211_sta *sta) + enum nl80211_band band, + struct ieee80211_link_sta *link_sta) { struct mt76_dev *dev = phy->dev; const struct ieee80211_sta_he_cap *he_cap; @@ -1306,10 +1329,10 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, if (is_connac_v1(dev)) return 0x38; - if (sta) { - ht_cap = &sta->deflink.ht_cap; - vht_cap = &sta->deflink.vht_cap; - he_cap = &sta->deflink.he_cap; + if (link_sta) { + ht_cap = &link_sta->ht_cap; + vht_cap = &link_sta->vht_cap; + he_cap = &link_sta->he_cap; } else { struct ieee80211_supported_band *sband; @@ -1347,7 +1370,7 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode); -u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, +u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_bss_conf *conf, enum nl80211_band band) { const struct ieee80211_sta_eht_cap *eht_cap; @@ -1358,9 +1381,9 @@ u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, mode |= PHY_MODE_AX_6G; sband = phy->hw->wiphy->bands[band]; - eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type); + eht_cap = ieee80211_get_eht_iftype_cap(sband, conf->vif->type); - if (!eht_cap || !eht_cap->has_eht || !vif->bss_conf.eht_support) + if (!eht_cap || !eht_cap->has_eht || !conf->eht_support) return mode; switch (band) { @@ -1384,7 +1407,7 @@ 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) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct cfg80211_chan_def *chandef = mvif->ctx ? &mvif->ctx->def : &phy->chandef; enum nl80211_band band = chandef->chan->band; @@ -1433,7 +1456,7 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80; } -int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif, +int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif, struct ieee80211_chanctx_conf *ctx) { struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; @@ -1521,7 +1544,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, bool enable, struct ieee80211_chanctx_conf *ctx) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; enum nl80211_band band = chandef->chan->band; struct mt76_dev *mdev = phy->dev; @@ -1643,11 +1666,49 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss); +void mt76_connac_mcu_build_rnr_scan_param(struct mt76_dev *mdev, + struct cfg80211_scan_request *sreq) +{ + struct ieee80211_channel **scan_list = sreq->channels; + int i, bssid_index = 0; + + /* clear 6G active Scan BSSID table */ + memset(&mdev->rnr, 0, sizeof(mdev->rnr)); + + for (i = 0; i < sreq->n_6ghz_params; i++) { + u8 ch_idx = sreq->scan_6ghz_params[i].channel_idx; + int k = 0; + + /* Remove the duplicated BSSID */ + for (k = 0; k < bssid_index; k++) { + if (!memcmp(&mdev->rnr.bssid[k], + sreq->scan_6ghz_params[i].bssid, + ETH_ALEN)) + break; + } + + if (k == bssid_index && + bssid_index < MT76_RNR_SCAN_MAX_BSSIDS) { + memcpy(&mdev->rnr.bssid[bssid_index++], + sreq->scan_6ghz_params[i].bssid, ETH_ALEN); + mdev->rnr.channel[k] = scan_list[ch_idx]->hw_value; + } + } + + mdev->rnr.bssid_num = bssid_index; + + if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + memcpy(mdev->rnr.random_mac, sreq->mac_addr, ETH_ALEN); + mdev->rnr.sreq_flag = sreq->flags; + } +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_build_rnr_scan_param); + #define MT76_CONNAC_SCAN_CHANNEL_TIME 60 int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_scan_request *scan_req) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct cfg80211_scan_request *sreq = &scan_req->req; int n_ssids = 0, err, i, duration; int ext_channels_num = max_t(int, sreq->n_channels - 32, 0); @@ -1667,7 +1728,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, set_bit(MT76_HW_SCANNING, &phy->state); mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f; - req = (struct mt76_connac_hw_scan_req *)skb_put(skb, sizeof(*req)); + req = (struct mt76_connac_hw_scan_req *)skb_put_zero(skb, sizeof(*req)); req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; req->bss_idx = mvif->idx; @@ -1753,7 +1814,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_hw_scan); int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { u8 seq_num; u8 is_ext_channel; @@ -1779,7 +1840,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *sreq) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct ieee80211_channel **scan_list = sreq->channels; struct mt76_connac_mcu_scan_channel *chan; struct mt76_connac_sched_scan_req *req; @@ -1795,7 +1856,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f; - req = (struct mt76_connac_sched_scan_req *)skb_put(skb, sizeof(*req)); + req = (struct mt76_connac_sched_scan_req *)skb_put_zero(skb, sizeof(*req)); req->version = 1; req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; @@ -2101,7 +2162,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, int j, msg_len, num_ch; struct sk_buff *skb; - num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len; + num_ch = i == batch_size - 1 ? n_chan - i * 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) { @@ -2191,7 +2252,7 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower); int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, - struct mt76_vif *vif, + struct mt76_vif_link *vif, struct ieee80211_bss_conf *info) { struct ieee80211_vif *mvif = container_of(info, struct ieee80211_vif, @@ -2234,7 +2295,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_arp_filter); int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; int ct_window = vif->bss_conf.p2p_noa_attr.oppps_ctwindow; struct mt76_phy *phy = hw->priv; struct { @@ -2301,7 +2362,7 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *key) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_connac_gtk_rekey_tlv *gtk_tlv; struct mt76_phy *phy = hw->priv; struct sk_buff *skb; @@ -2318,7 +2379,7 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw, return -ENOMEM; skb_put_data(skb, &hdr, sizeof(hdr)); - gtk_tlv = (struct mt76_connac_gtk_rekey_tlv *)skb_put(skb, + gtk_tlv = (struct mt76_connac_gtk_rekey_tlv *)skb_put_zero(skb, sizeof(*gtk_tlv)); gtk_tlv->tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY); gtk_tlv->len = cpu_to_le16(sizeof(*gtk_tlv)); @@ -2342,7 +2403,7 @@ static int mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -2368,7 +2429,7 @@ int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -2397,7 +2458,7 @@ mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev, bool enable, u8 mdtim, bool wow_suspend) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -2428,7 +2489,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev, u8 index, bool enable, struct cfg80211_pkt_pattern *pattern) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_connac_wow_pattern_tlv *ptlv; struct sk_buff *skb; struct req_hdr { @@ -2443,7 +2504,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev, return -ENOMEM; skb_put_data(skb, &hdr, sizeof(hdr)); - ptlv = (struct mt76_connac_wow_pattern_tlv *)skb_put(skb, sizeof(*ptlv)); + ptlv = (struct mt76_connac_wow_pattern_tlv *)skb_put_zero(skb, sizeof(*ptlv)); ptlv->tag = cpu_to_le16(UNI_SUSPEND_WOW_PATTERN); ptlv->len = cpu_to_le16(sizeof(*ptlv)); ptlv->data_len = pattern->pattern_len; @@ -2460,7 +2521,7 @@ int mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, bool suspend, struct cfg80211_wowlan *wowlan) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_dev *dev = phy->dev; struct { struct { @@ -2510,7 +2571,7 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_wow_ctrl); -int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) +int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend, bool wait_resp) { struct { struct { @@ -2524,6 +2585,7 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) __le16 tag; __le16 len; u8 suspend; + u8 pad[7]; } __packed hif_suspend; } req = { .hif_suspend = { @@ -2541,7 +2603,7 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) req.hdr.hif_type = 0; return mt76_mcu_send_msg(dev, MCU_UNI_CMD(HIF_CTRL), &req, - sizeof(req), true); + sizeof(req), wait_resp); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_hif_suspend); @@ -2668,7 +2730,7 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct sk_buff *skb; int ret; @@ -2690,7 +2752,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_key); /* SIFS 20us + 512 byte beacon transmitted by 1Mbps (3906us) */ #define BCN_TX_ESTIMATE_TIME (4096 + 20) -void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif *mvif) +void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif_link *mvif) { struct bss_info_ext_bss *ext; int ext_bss_idx, tsf_offset; @@ -2714,7 +2776,7 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, struct mt76_phy *phy, u16 wlan_idx, bool enable) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; struct bss_info_basic *bss; struct tlv *tlv; @@ -2831,6 +2893,17 @@ int mt76_connac_mcu_restart(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_connac_mcu_restart); +int mt76_connac_mcu_del_wtbl_all(struct mt76_dev *dev) +{ + struct wtbl_req_hdr req = { + .operation = WTBL_RESET_ALL, + }; + + return mt76_mcu_send_msg(dev, MCU_EXT_CMD(WTBL_UPDATE), + &req, sizeof(req), true); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_del_wtbl_all); + int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index, u8 rx_sel, u8 val) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index ae6d0179727d..27daf419560a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -115,21 +115,26 @@ struct mt76_connac2_mcu_uni_txd { } __packed __aligned(4); struct mt76_connac2_mcu_rxd { - __le32 rxd[6]; + /* New members MUST be added within the struct_group() macro below. */ + struct_group_tagged(mt76_connac2_mcu_rxd_hdr, hdr, + __le32 rxd[6]; - __le16 len; - __le16 pkt_type_id; + __le16 len; + __le16 pkt_type_id; - u8 eid; - u8 seq; - u8 option; - u8 rsv; - u8 ext_eid; - u8 rsv1[2]; - u8 s2d_index; + u8 eid; + u8 seq; + u8 option; + u8 rsv; + u8 ext_eid; + u8 rsv1[2]; + u8 s2d_index; + ); u8 tlv[]; }; +static_assert(offsetof(struct mt76_connac2_mcu_rxd, tlv) == sizeof(struct mt76_connac2_mcu_rxd_hdr), + "struct member likely outside of struct_group_tagged()"); struct mt76_connac2_patch_hdr { char build_date[16]; @@ -545,6 +550,13 @@ struct sta_rec_muru { } mimo_ul; } __packed; +struct sta_rec_remove { + __le16 tag; + __le16 len; + u8 action; + u8 pad[3]; +} __packed; + struct sta_phy { u8 type; u8 flag; @@ -610,6 +622,12 @@ struct sta_rec_ra_fixed { u8 mmps_mode; } __packed; +struct sta_rec_tx_proc { + __le16 tag; + __le16 len; + __le32 flag; +} __packed; + /* wtbl_rec */ struct wtbl_req_hdr { @@ -777,6 +795,7 @@ struct wtbl_raw { sizeof(struct sta_rec_ra_fixed) + \ sizeof(struct sta_rec_he_6g_capa) + \ sizeof(struct sta_rec_pn_info) + \ + sizeof(struct sta_rec_tx_proc) + \ sizeof(struct tlv) + \ MT76_CONNAC_WTBL_UPDATE_MAX_SIZE) @@ -806,8 +825,12 @@ enum { STA_REC_HE_6G = 0x17, STA_REC_HE_V2 = 0x19, STA_REC_MLD = 0x20, + STA_REC_EHT_MLD = 0x21, STA_REC_EHT = 0x22, + STA_REC_MLD_OFF = 0x23, + STA_REC_REMOVE = 0x25, STA_REC_PN_INFO = 0x26, + STA_REC_KEY_V3 = 0x27, STA_REC_HDRT = 0x28, STA_REC_HDR_TRANS = 0x2B, STA_REC_MAX_NUM @@ -846,6 +869,7 @@ enum { #define NETWORK_WDS BIT(21) #define SCAN_FUNC_RANDOM_MAC BIT(0) +#define SCAN_FUNC_RNR_SCAN BIT(3) #define SCAN_FUNC_SPLIT_SCAN BIT(5) #define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) @@ -935,6 +959,9 @@ enum { PHY_TYPE_INDEX_NUM }; +#define HR_DSSS_ERP_BASIC_RATE GENMASK(3, 0) +#define OFDM_BASIC_RATE (BIT(6) | BIT(8) | BIT(10)) + #define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) #define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) #define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) @@ -1000,6 +1027,7 @@ enum { MCU_EVENT_CH_PRIVILEGE = 0x18, MCU_EVENT_SCHED_SCAN_DONE = 0x23, MCU_EVENT_DBG_MSG = 0x27, + MCU_EVENT_RSSI_NOTIFY = 0x96, MCU_EVENT_TXPWR = 0xd0, MCU_EVENT_EXT = 0xed, MCU_EVENT_RESTART_DL = 0xef, @@ -1016,12 +1044,14 @@ enum { MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, MCU_EXT_EVENT_WA_TX_STAT = 0x74, MCU_EXT_EVENT_BCC_NOTIFY = 0x75, + MCU_EXT_EVENT_WF_RF_PIN_CTRL = 0x9a, MCU_EXT_EVENT_MURU_CTRL = 0x9f, }; /* unified event table */ enum { MCU_UNI_EVENT_RESULT = 0x01, + MCU_UNI_EVENT_HIF_CTRL = 0x03, MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04, MCU_UNI_EVENT_ACCESS_REG = 0x6, MCU_UNI_EVENT_IE_COUNTDOWN = 0x09, @@ -1036,6 +1066,7 @@ enum { MCU_UNI_EVENT_WED_RRO = 0x57, MCU_UNI_EVENT_PER_STA_INFO = 0x6d, MCU_UNI_EVENT_ALL_STA_INFO = 0x6e, + MCU_UNI_EVENT_SDO = 0x83, }; #define MCU_UNI_CMD_EVENT BIT(1) @@ -1153,6 +1184,11 @@ enum { #define MCU_UNI_CMD(_t) (__MCU_CMD_FIELD_UNI | \ FIELD_PREP(__MCU_CMD_FIELD_ID, \ MCU_UNI_CMD_##_t)) + +#define MCU_UNI_QUERY(_t) (__MCU_CMD_FIELD_UNI | __MCU_CMD_FIELD_QUERY | \ + FIELD_PREP(__MCU_CMD_FIELD_ID, \ + MCU_UNI_CMD_##_t)) + #define MCU_CE_CMD(_t) (__MCU_CMD_FIELD_CE | \ FIELD_PREP(__MCU_CMD_FIELD_ID, \ MCU_CE_CMD_##_t)) @@ -1178,6 +1214,7 @@ enum { MCU_EXT_CMD_EFUSE_ACCESS = 0x01, MCU_EXT_CMD_RF_REG_ACCESS = 0x02, MCU_EXT_CMD_RF_TEST = 0x04, + MCU_EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05, MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, @@ -1209,6 +1246,7 @@ enum { MCU_EXT_CMD_TXDPD_CAL = 0x60, MCU_EXT_CMD_CAL_CACHE = 0x67, MCU_EXT_CMD_RED_ENABLE = 0x68, + MCU_EXT_CMD_CP_SUPPORT = 0x75, MCU_EXT_CMD_SET_RADAR_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, MCU_EXT_CMD_MWDS_SUPPORT = 0x80, @@ -1222,6 +1260,7 @@ enum { MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, MCU_EXT_CMD_PHY_STAT_INFO = 0xad, + MCU_EXT_CMD_WF_RF_PIN_CTRL = 0xbd, }; enum { @@ -1255,16 +1294,20 @@ enum { MCU_UNI_CMD_EFUSE_CTRL = 0x2d, MCU_UNI_CMD_RA = 0x2f, MCU_UNI_CMD_MURU = 0x31, + MCU_UNI_CMD_TESTMODE_RX_STAT = 0x32, MCU_UNI_CMD_BF = 0x33, MCU_UNI_CMD_CHANNEL_SWITCH = 0x34, MCU_UNI_CMD_THERMAL = 0x35, MCU_UNI_CMD_VOW = 0x37, MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40, + MCU_UNI_CMD_TESTMODE_CTRL = 0x46, 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, + MCU_UNI_CMD_RADIO_STATUS = 0x80, + MCU_UNI_CMD_SDO = 0x88, }; enum { @@ -1299,6 +1342,7 @@ enum { MCU_CE_CMD_SCHED_SCAN_ENABLE = 0x61, MCU_CE_CMD_SCHED_SCAN_REQ = 0x62, MCU_CE_CMD_GET_NIC_CAPAB = 0x8a, + MCU_CE_CMD_RSSI_MONITOR = 0xa1, MCU_CE_CMD_SET_MU_EDCA_PARMS = 0xb0, MCU_CE_CMD_REG_WRITE = 0xc0, MCU_CE_CMD_REG_READ = 0xc0, @@ -1336,6 +1380,7 @@ enum { UNI_BSS_INFO_OFFLOAD = 25, UNI_BSS_INFO_MLD = 26, UNI_BSS_INFO_PM_DISABLE = 27, + UNI_BSS_INFO_EHT = 30, }; enum { @@ -1377,6 +1422,7 @@ enum { MT_NIC_CAP_WFDMA_REALLOC, MT_NIC_CAP_6G, MT_NIC_CAP_CHIP_CAP = 0x20, + MT_NIC_CAP_EML_CAP = 0x22, }; #define UNI_WOW_DETECT_TYPE_MAGIC BIT(0) @@ -1428,7 +1474,7 @@ struct mt76_connac_bss_basic_tlv { __le16 sta_idx; __le16 nonht_basic_phy; u8 phymode_ext; /* bit(0) AX_6G */ - u8 pad[1]; + u8 link_idx; } __packed; struct mt76_connac_bss_qos_tlv { @@ -1444,6 +1490,10 @@ struct mt76_connac_beacon_loss_event { u8 pad[2]; } __packed; +struct mt76_connac_rssi_notify_event { + __le32 rssi[4]; +} __packed; + struct mt76_connac_mcu_bss_event { u8 bss_idx; u8 is_absent; @@ -1714,10 +1764,14 @@ enum mt76_sta_info_state { }; struct mt76_sta_cmd_info { - struct ieee80211_sta *sta; + union { + struct ieee80211_sta *sta; + struct ieee80211_link_sta *link_sta; + }; struct mt76_wcid *wcid; struct ieee80211_vif *vif; + struct ieee80211_bss_conf *link_conf; bool offload_fw; bool enable; @@ -1838,10 +1892,10 @@ mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid, } struct sk_buff * -__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, +__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct mt76_wcid *wcid, int len); static inline struct sk_buff * -mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, +mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct mt76_wcid *wcid) { return __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, @@ -1863,9 +1917,9 @@ mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len) int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy); int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif); void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable, - bool newly); + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + int state, bool newly); void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta, void *sta_wtbl, @@ -1879,7 +1933,8 @@ int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev, 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); + enum nl80211_band band, + struct ieee80211_link_sta *link_sta); int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -1898,14 +1953,15 @@ void mt76_connac_mcu_sta_ba_tlv(struct sk_buff *skb, struct ieee80211_ampdu_params *params, bool enable, bool tx); int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, - struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + struct mt76_vif_link *mvif, struct mt76_wcid *wcid, bool enable); -int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, +int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct ieee80211_ampdu_params *params, int cmd, bool enable, bool tx); int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, - struct mt76_vif *vif, + struct mt76_vif_link *vif, struct ieee80211_chanctx_conf *ctx); int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, struct ieee80211_vif *vif, @@ -1925,6 +1981,8 @@ 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); +void mt76_connac_mcu_build_rnr_scan_param(struct mt76_dev *mdev, + struct cfg80211_scan_request *sreq); int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_scan_request *scan_req); int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy, @@ -1936,7 +1994,7 @@ int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy, struct ieee80211_vif *vif, bool enable); int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, - struct mt76_vif *vif, + struct mt76_vif_link *vif, struct ieee80211_bss_conf *info); int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend); @@ -1949,7 +2007,7 @@ 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); +int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend, bool wait_resp); void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); int mt76_connac_sta_state_dp(struct mt76_dev *dev, @@ -1973,8 +2031,9 @@ mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif); const struct ieee80211_sta_eht_cap * mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif); u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, - enum nl80211_band band, struct ieee80211_sta *sta); -u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, + enum nl80211_band band, + struct ieee80211_link_sta *sta); +u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_bss_conf *conf, enum nl80211_band band); int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, @@ -1982,7 +2041,7 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd); -void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif *mvif); +void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif_link *mvif); void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif); int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, @@ -1997,6 +2056,7 @@ void mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb, void *sta_wtbl, void *wtbl_tlv); int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter); int mt76_connac_mcu_restart(struct mt76_dev *dev); +int mt76_connac_mcu_del_wtbl_all(struct mt76_dev *dev); int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index, u8 rx_sel, u8 val); int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index bcd24c9072ec..4de45a56812d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -10,7 +10,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/etherdevice.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "mt76x0.h" #include "eeprom.h" #include "../mt76x02_phy.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index 07380cce8755..4aa2dcedc874 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -8,16 +8,15 @@ #include <linux/etherdevice.h> #include "mt76x0.h" -static void -mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) +int mt76x0_set_channel(struct mt76_phy *mphy) { - cancel_delayed_work_sync(&dev->cal_work); + struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76); + mt76x02_pre_tbtt_enable(dev, false); if (mt76_is_mmio(&dev->mt76)) tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mt76_set_channel(&dev->mphy); - mt76x0_phy_set_channel(dev, chandef); + mt76x0_phy_set_channel(dev, &mphy->chandef); mt76x02_mac_cc_reset(dev); mt76x02_edcca_init(dev); @@ -28,8 +27,9 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) } mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mphy); + return 0; } +EXPORT_SYMBOL_GPL(mt76x0_set_channel); int mt76x0_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) @@ -61,13 +61,10 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) { struct mt76x02_dev *dev = hw->priv; - mutex_lock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + mt76_update_channel(&dev->mphy); - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - mt76x0_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } + mutex_lock(&dev->mt76.mutex); if (changed & IEEE80211_CONF_CHANGE_POWER) { struct mt76_phy *mphy = &dev->mphy; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h index 99dcb8feb9f7..50f755344968 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h @@ -49,6 +49,7 @@ void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); void mt76x0_mac_stop(struct mt76x02_dev *dev); int mt76x0_config(struct ieee80211_hw *hw, u32 changed); +int mt76x0_set_channel(struct mt76_phy *mphy); int mt76x0_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 293e66fa83d5..11c16d1fc70f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -44,7 +44,7 @@ static void mt76x0e_stop_hw(struct mt76x02_dev *dev) mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN); } -static void mt76x0e_stop(struct ieee80211_hw *hw) +static void mt76x0e_stop(struct ieee80211_hw *hw, bool suspend) { struct mt76x02_dev *dev = hw->priv; @@ -59,6 +59,10 @@ mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static const struct ieee80211_ops mt76x0e_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt76x02_tx, .start = mt76x0e_start, .stop = mt76x0e_stop, @@ -152,9 +156,11 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | - MT_DRV_SW_RX_AIRTIME, + MT_DRV_SW_RX_AIRTIME | + MT_DRV_IGNORE_TXS_FAILED, .survey_flags = SURVEY_INFO_TIME_TX, .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, .rx_skb = mt76x02_queue_rx_skb, @@ -277,14 +283,16 @@ static int mt76x0e_resume(struct pci_dev *pdev) mt76_worker_enable(&mdev->tx_worker); - local_bh_disable(); mt76_for_each_q_rx(mdev, i) { mt76_queue_rx_reset(dev, i); napi_enable(&mdev->napi[i]); - napi_schedule(&mdev->napi[i]); } - napi_enable(&mdev->tx_napi); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_schedule(&mdev->napi[i]); + } napi_schedule(&mdev->tx_napi); local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index d543ef3de65b..ec554a059216 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1071,7 +1071,7 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) u8 gain_delta; int low_gain; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, 0); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index dd042949cf82..90e5666c0857 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -77,7 +77,7 @@ static void mt76x0u_cleanup(struct mt76x02_dev *dev) mt76u_queues_deinit(&dev->mt76); } -static void mt76x0u_stop(struct ieee80211_hw *hw) +static void mt76x0u_stop(struct ieee80211_hw *hw, bool suspend) { struct mt76x02_dev *dev = hw->priv; @@ -118,6 +118,10 @@ static int mt76x0u_start(struct ieee80211_hw *hw) } static const struct ieee80211_ops mt76x0u_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt76x02_tx, .start = mt76x0u_start, .stop = mt76x0u_stop, @@ -210,9 +214,11 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, const struct usb_device_id *id) { static const struct mt76_driver_ops drv_ops = { - .drv_flags = MT_DRV_SW_RX_AIRTIME, + .drv_flags = MT_DRV_SW_RX_AIRTIME | + MT_DRV_IGNORE_TXS_FAILED, .survey_flags = SURVEY_INFO_TIME_TX, .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, .tx_prepare_skb = mt76x02u_tx_prepare_skb, .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 024a5c0a5a57..7a07636d09c6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct tasklet_struct *t) radar_detected = mt76x02_dfs_check_detection(dev); if (radar_detected) { /* sw detector rx radar pattern */ - ieee80211_radar_detected(dev->mt76.hw); + ieee80211_radar_detected(dev->mt76.hw, NULL); mt76x02_dfs_detector_reset(dev); return; @@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct tasklet_struct *t) /* hw detector rx radar pattern */ dfs_pd->stats[i].hw_pattern++; - ieee80211_radar_detected(dev->mt76.hw); + ieee80211_radar_detected(dev->mt76.hw, NULL); mt76x02_dfs_detector_reset(dev); return; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c index 5d402cf2951c..a5e3392c0b48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c @@ -4,7 +4,7 @@ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "mt76x02_eeprom.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index e5ad635d3c56..a683d53c7ceb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -22,7 +22,7 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t) struct sk_buff *skb; int i; - if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (dev->mphy.offchannel) return; __skb_queue_head_init(&data.q); @@ -174,7 +174,6 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget) int mt76x02_dma_init(struct mt76x02_dev *dev) { - struct mt76_txwi_cache __maybe_unused *t; int i, ret, fifo_size; struct mt76_queue *q; void *status_fifo; @@ -239,7 +238,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt76x02_poll_tx); napi_enable(&dev->mt76.tx_napi); @@ -423,7 +422,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) priv = msta->vif; vif = container_of(priv, struct ieee80211_vif, drv_priv); - __mt76_sta_remove(&dev->mt76, vif, sta); + __mt76_sta_remove(&dev->mphy, vif, sta); memset(msta, 0, sizeof(*msta)); } @@ -504,12 +503,14 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) mt76_worker_enable(&dev->mt76.tx_worker); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); - napi_schedule(&dev->mt76.tx_napi); - mt76_for_each_q_rx(&dev->mt76, i) { napi_enable(&dev->mt76.napi[i]); + } + + local_bh_disable(); + napi_schedule(&dev->mt76.tx_napi); + mt76_for_each_q_rx(&dev->mt76, i) { napi_schedule(&dev->mt76.napi[i]); } local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 85a78dea4085..4840d0b500b3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -67,7 +67,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, struct mt76_tx_info *tx_info) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); - int pid, len = tx_info->skb->len, ep = q2ep(dev->mphy.q_tx[qid]->hw_idx); + int pid, len = tx_info->skb->len, ep = dev->mphy.q_tx[qid]->ep; struct mt76x02_txwi *txwi; bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; enum mt76_qsel qsel; @@ -188,10 +188,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) struct sk_buff *skb; int nbeacons; - if (!dev->mt76.beacon_mask) - return; - - if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (!dev->mt76.beacon_mask || dev->mphy.offchannel) return; __skb_queue_head_init(&data.q); @@ -267,8 +264,8 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) }; dev->beacon_ops = &beacon_ops; - hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt; + hrtimer_setup(&dev->pre_tbtt_timer, mt76x02u_pre_tbtt_interrupt, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work); mt76x02_init_beacon_config(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 8020446be37b..4fb30589fa7a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -287,8 +287,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_wcid_init(&mvif->group_wcid); + mt76_wcid_init(&mvif->group_wcid, 0); mtxq = (struct mt76_txq *)vif->txq->drv_priv; rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 1fe5f5a02f93..156b16c17b2b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -5,7 +5,7 @@ #include <linux/module.h> #include <linux/of.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "mt76x2.h" #include "eeprom.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index be1217329a77..f051721bb00e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -47,6 +47,8 @@ void mt76x2_phy_power_on(struct mt76x02_dev *dev); void mt76x2_stop_hardware(struct mt76x02_dev *dev); int mt76x2_eeprom_init(struct mt76x02_dev *dev); int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel); +int mt76x2e_set_channel(struct mt76_phy *phy); +int mt76x2u_set_channel(struct mt76_phy *phy); void mt76x2_phy_set_antenna(struct mt76x02_dev *dev); int mt76x2_phy_start(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 30959746e924..2303019670e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -22,9 +22,11 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id) static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | - MT_DRV_SW_RX_AIRTIME, + MT_DRV_SW_RX_AIRTIME | + MT_DRV_IGNORE_TXS_FAILED, .survey_flags = SURVEY_INFO_TIME_TX, .update_survey = mt76x02_update_channel, + .set_channel = mt76x2e_set_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, .rx_skb = mt76x02_queue_rx_skb, @@ -150,12 +152,15 @@ mt76x2e_resume(struct pci_dev *pdev) 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); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_schedule(&mdev->napi[i]); + } napi_schedule(&mdev->tx_napi); local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index b38bb7a2362b..eb70130d2711 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -24,7 +24,7 @@ mt76x2_start(struct ieee80211_hw *hw) } static void -mt76x2_stop(struct ieee80211_hw *hw) +mt76x2_stop(struct ieee80211_hw *hw, bool suspend) { struct mt76x02_dev *dev = hw->priv; @@ -32,33 +32,25 @@ mt76x2_stop(struct ieee80211_hw *hw) mt76x2_stop_hardware(dev); } -static void -mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) +int mt76x2e_set_channel(struct mt76_phy *phy) { - cancel_delayed_work_sync(&dev->cal_work); + struct mt76x02_dev *dev = container_of(phy->dev, struct mt76x02_dev, mt76); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mphy.state); - - mt76_set_channel(&dev->mphy); - mt76x2_mac_stop(dev, true); - mt76x2_phy_set_channel(dev, chandef); + mt76x2_phy_set_channel(dev, &phy->chandef); mt76x02_mac_cc_reset(dev); mt76x02_dfs_init_params(dev); mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mphy.state); - mutex_unlock(&dev->mt76.mutex); - tasklet_enable(&dev->dfs_pd.dfs_tasklet); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); - mt76_txq_schedule_all(&dev->mphy); + return 0; } static int @@ -95,11 +87,8 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - mt76x2_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + mt76_update_channel(&dev->mphy); return 0; } @@ -132,6 +121,10 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, } const struct ieee80211_ops mt76x2_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt76x02_tx, .start = mt76x2_start, .stop = mt76x2_stop, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index f84517d932dc..e2b4cf30dc44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -280,7 +280,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) int low_gain; u32 val; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, 0); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index ca78e14251c2..96cecc576a98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -17,10 +17,14 @@ static const struct usb_device_id mt76x2u_device_table[] = { { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */ { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */ { USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */ + { USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */ + { USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */ { USB_DEVICE(0x2c4e, 0x0103) }, /* Mercury UD13 */ + { USB_DEVICE(0x0846, 0x9014) }, /* Netgear WNDA3100v3 */ { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */ { USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */ { USB_DEVICE(0x045e, 0x02fe) }, /* XBox One Wireless Adapter */ + { USB_DEVICE(0x2357, 0x0137) }, /* TP-Link TL-WDN6200 */ { }, }; @@ -28,9 +32,11 @@ static int mt76x2u_probe(struct usb_interface *intf, const struct usb_device_id *id) { static const struct mt76_driver_ops drv_ops = { - .drv_flags = MT_DRV_SW_RX_AIRTIME, + .drv_flags = MT_DRV_SW_RX_AIRTIME | + MT_DRV_IGNORE_TXS_FAILED, .survey_flags = SURVEY_INFO_TIME_TX, .update_survey = mt76x02_update_channel, + .set_channel = mt76x2u_set_channel, .tx_prepare_skb = mt76x02u_tx_prepare_skb, .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 33a14365ec9b..3b5562811511 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -191,6 +191,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_usb *usb = &dev->mt76.usb; + bool vht; int err; INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate); @@ -217,7 +218,17 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) /* check hw sg support in order to enable AMSDU */ hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1; - err = mt76_register_device(&dev->mt76, true, mt76x02_rates, + switch (dev->mt76.rev) { + case 0x76320044: + /* these ASIC revisions do not support VHT */ + vht = false; + break; + default: + vht = true; + break; + } + + err = mt76_register_device(&dev->mt76, vht, mt76x02_rates, ARRAY_SIZE(mt76x02_rates)); if (err) goto fail; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index ac07ed1f63a3..83e7061b10e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -22,7 +22,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) return 0; } -static void mt76x2u_stop(struct ieee80211_hw *hw) +static void mt76x2u_stop(struct ieee80211_hw *hw, bool suspend) { struct mt76x02_dev *dev = hw->priv; @@ -31,32 +31,20 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) mt76x2u_stop_hw(dev); } -static int -mt76x2u_set_channel(struct mt76x02_dev *dev, - struct cfg80211_chan_def *chandef) +int mt76x2u_set_channel(struct mt76_phy *mphy) { + struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76); int err; - cancel_delayed_work_sync(&dev->cal_work); mt76x02_pre_tbtt_enable(dev, false); - - mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mphy.state); - - mt76_set_channel(&dev->mphy); - mt76x2_mac_stop(dev, false); - err = mt76x2u_phy_set_channel(dev, chandef); + err = mt76x2u_phy_set_channel(dev, &mphy->chandef); mt76x02_mac_cc_reset(dev); mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mphy.state); - mutex_unlock(&dev->mt76.mutex); - mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mphy); return err; } @@ -93,16 +81,17 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - err = mt76x2u_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + mt76_update_channel(&dev->mphy); return err; } const struct ieee80211_ops mt76x2u_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt76x02_tx, .start = mt76x2u_start, .stop = mt76x2u_stop, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 6c3696c8c700..b287b7d9394e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -211,13 +211,28 @@ static const struct file_operations mt7915_sys_recovery_ops = { static int mt7915_radar_trigger(void *data, u64 val) { - struct mt7915_dev *dev = data; +#define RADAR_MAIN_CHAIN 1 +#define RADAR_BACKGROUND 2 + struct mt7915_phy *phy = data; + struct mt7915_dev *dev = phy->dev; + int rdd_idx; + + if (!val || val > RADAR_BACKGROUND) + return -EINVAL; - if (val > MT_RX_SEL2) + if (val == RADAR_BACKGROUND && !dev->rdd2_phy) { + dev_err(dev->mt76.dev, "Background radar is not enabled\n"); return -EINVAL; + } + + rdd_idx = mt7915_get_rdd_idx(phy, val == RADAR_BACKGROUND); + if (rdd_idx < 0) { + dev_err(dev->mt76.dev, "No RDD found\n"); + return -EINVAL; + } return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE, - val, 0, 0); + rdd_idx, 0, 0); } DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, @@ -303,9 +318,9 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) phy->mib.dl_vht_3mu_cnt, phy->mib.dl_vht_4mu_cnt); - sub_total_cnt = phy->mib.dl_vht_2mu_cnt + - phy->mib.dl_vht_3mu_cnt + - phy->mib.dl_vht_4mu_cnt; + sub_total_cnt = (u64)phy->mib.dl_vht_2mu_cnt + + phy->mib.dl_vht_3mu_cnt + + phy->mib.dl_vht_4mu_cnt; seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); @@ -353,26 +368,27 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) phy->mib.dl_he_9to16ru_cnt, phy->mib.dl_he_gtr16ru_cnt); - sub_total_cnt = phy->mib.dl_he_2mu_cnt + - phy->mib.dl_he_3mu_cnt + - phy->mib.dl_he_4mu_cnt; + sub_total_cnt = (u64)phy->mib.dl_he_2mu_cnt + + phy->mib.dl_he_3mu_cnt + + phy->mib.dl_he_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); - sub_total_cnt = phy->mib.dl_he_2ru_cnt + - phy->mib.dl_he_3ru_cnt + - phy->mib.dl_he_4ru_cnt + - phy->mib.dl_he_5to8ru_cnt + - phy->mib.dl_he_9to16ru_cnt + - phy->mib.dl_he_gtr16ru_cnt; + sub_total_cnt = (u64)phy->mib.dl_he_2ru_cnt + + phy->mib.dl_he_3ru_cnt + + phy->mib.dl_he_4ru_cnt + + phy->mib.dl_he_5to8ru_cnt + + phy->mib.dl_he_9to16ru_cnt + + phy->mib.dl_he_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", sub_total_cnt); - total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt; + total_ppdu_cnt += (u64)phy->mib.dl_he_su_cnt + + phy->mib.dl_he_ext_su_cnt; seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); @@ -404,20 +420,20 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) phy->mib.ul_hetrig_9to16ru_cnt, phy->mib.ul_hetrig_gtr16ru_cnt); - sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt + - phy->mib.ul_hetrig_3mu_cnt + - phy->mib.ul_hetrig_4mu_cnt; + sub_total_cnt = (u64)phy->mib.ul_hetrig_2mu_cnt + + phy->mib.ul_hetrig_3mu_cnt + + phy->mib.ul_hetrig_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", sub_total_cnt); - sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt + - phy->mib.ul_hetrig_3ru_cnt + - phy->mib.ul_hetrig_4ru_cnt + - phy->mib.ul_hetrig_5to8ru_cnt + - phy->mib.ul_hetrig_9to16ru_cnt + - phy->mib.ul_hetrig_gtr16ru_cnt; + sub_total_cnt = (u64)phy->mib.ul_hetrig_2ru_cnt + + phy->mib.ul_hetrig_3ru_cnt + + phy->mib.ul_hetrig_4ru_cnt + + phy->mib.ul_hetrig_5to8ru_cnt + + phy->mib.ul_hetrig_9to16ru_cnt + + phy->mib.ul_hetrig_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", @@ -444,6 +460,11 @@ mt7915_rdd_monitor(struct seq_file *s, void *data) mutex_lock(&dev->mt76.mutex); + if (!mt7915_eeprom_has_background_radar(dev)) { + seq_puts(s, "no background radar capability\n"); + goto out; + } + if (!cfg80211_chandef_valid(chandef)) { ret = -EINVAL; goto out; @@ -523,7 +544,8 @@ mt7915_fw_debug_wm_set(void *data, u64 val) /* WM CPU info record control */ mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0)); - mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm); + mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | + (dev->fw.debug_wm ? 0 : BIT(0))); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5)); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5)); @@ -1049,6 +1071,7 @@ static ssize_t mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { + int i, ret, pwr, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0; struct mt7915_phy *phy = file->private_data; struct mt7915_dev *dev = phy->dev; struct mt76_phy *mphy = phy->mt76; @@ -1057,7 +1080,6 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, .band_idx = phy->mt76->band_idx, }; char buf[100]; - int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0; enum mac80211_rx_encoding mode; u32 offs = 0, len = 0; @@ -1083,13 +1105,13 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, return -EINVAL; if (pwr160) - pwr160 = mt7915_get_power_bound(phy, pwr160); + pwr160 = mt76_get_power_bound(mphy, pwr160); if (pwr80) - pwr80 = mt7915_get_power_bound(phy, pwr80); + pwr80 = mt76_get_power_bound(mphy, pwr80); if (pwr40) - pwr40 = mt7915_get_power_bound(phy, pwr40); + pwr40 = mt76_get_power_bound(mphy, pwr40); if (pwr20) - pwr20 = mt7915_get_power_bound(phy, pwr20); + pwr20 = mt76_get_power_bound(mphy, pwr20); if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0) return -EINVAL; @@ -1130,8 +1152,8 @@ skip: if (ret) goto out; - mphy->txpower_cur = max(mphy->txpower_cur, - max(pwr160, max(pwr80, max(pwr40, pwr20)))); + pwr = max3(pwr80, pwr40, pwr20); + mphy->txpower_cur = max3(mphy->txpower_cur, pwr160, pwr); out: mutex_unlock(&dev->mt76.mutex); @@ -1240,7 +1262,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) if (!dev->dbdc_support || phy->mt76->band_idx) { debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); - debugfs_create_file("radar_trigger", 0200, dir, dev, + debugfs_create_file("radar_trigger", 0200, dir, phy, &fops_radar_trigger); debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, mt7915_rdd_monitor); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index c91a1c54027f..0c62272fe7d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -578,7 +578,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (ret < 0) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7915_poll_tx); napi_enable(&dev->mt76.tx_napi); @@ -614,7 +614,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mtk_wed_device_dma_reset(wed); mt7915_dma_disable(dev, force); - mt76_dma_wed_reset(&dev->mt76); + mt76_wed_dma_reset(&dev->mt76); /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 3bb2643d1b26..c0f3402d30bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -2,35 +2,46 @@ /* Copyright (C) 2020 MediaTek Inc. */ #include <linux/firmware.h> +#include <linux/moduleparam.h> #include "mt7915.h" #include "eeprom.h" +static bool enable_6ghz; +module_param(enable_6ghz, bool, 0644); +MODULE_PARM_DESC(enable_6ghz, "Enable 6 GHz instead of 5 GHz on hardware that supports both"); + static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) { struct mt76_dev *mdev = &dev->mt76; u8 *eeprom = mdev->eeprom.data; - u32 val = eeprom[MT_EE_DO_PRE_CAL]; - u32 offs; + u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2; + u32 size, val = eeprom[offs]; int ret; - if (!dev->flash_mode) + if (!dev->flash_mode || !val) return 0; - if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP)) - return 0; + size = mt7915_get_cal_group_size(dev) + mt7915_get_cal_dpd_size(dev); - val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE; - dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL); + dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL); if (!dev->cal) return -ENOMEM; offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2; - ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, val); + ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size); if (!ret) return ret; - return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", val); + ret = mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size); + if (!ret) + return ret; + + dev_warn(mdev->dev, "missing precal data, size=%d\n", size); + devm_kfree(mdev->dev, dev->cal); + dev->cal = NULL; + + return ret; } static int mt7915_check_eeprom(struct mt7915_dev *dev) @@ -136,7 +147,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) /* read eeprom data from efuse */ block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size); for (i = 0; i < block_num; i++) { - ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size); + ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL); if (ret < 0) return ret; } @@ -164,8 +175,20 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) phy->mt76->cap.has_6ghz = true; return; case MT_EE_V2_BAND_SEL_5GHZ_6GHZ: - phy->mt76->cap.has_5ghz = true; - phy->mt76->cap.has_6ghz = true; + if (enable_6ghz) { + phy->mt76->cap.has_6ghz = true; + u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band], + MT_EE_V2_BAND_SEL_6GHZ, + MT_EE_WIFI_CONF0_BAND_SEL); + } else { + phy->mt76->cap.has_5ghz = true; + u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band], + MT_EE_V2_BAND_SEL_5GHZ, + MT_EE_WIFI_CONF0_BAND_SEL); + } + /* force to buffer mode */ + dev->flash_mode = true; + return; default: phy->mt76->cap.has_2ghz = true; @@ -256,10 +279,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) return ret; } - ret = mt7915_eeprom_load_precal(dev); - if (ret) - return ret; - + mt7915_eeprom_load_precal(dev); mt7915_eeprom_parse_hw_cap(dev, &dev->phy); memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); @@ -341,6 +361,37 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band) return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta; } +bool +mt7915_eeprom_has_background_radar(struct mt7915_dev *dev) +{ + u8 val, buf[MT7915_EEPROM_BLOCK_SIZE]; + u8 band_sel, tx_path, rx_path; + int offs = MT_EE_WIFI_CONF + 1; + + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + return true; + case 0x7906: + /* read efuse to check background radar capability */ + if (mt7915_mcu_get_eeprom(dev, offs, buf)) + break; + + val = buf[offs % MT7915_EEPROM_BLOCK_SIZE]; + band_sel = u8_get_bits(val, MT_EE_WIFI_CONF0_BAND_SEL); + tx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_TX_PATH); + rx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_RX_PATH); + + return (band_sel == MT_EE_V2_BAND_SEL_5GHZ && + tx_path == rx_path && rx_path == 2); + case 0x7981: + case 0x7986: + default: + break; + } + + return false; +} + const u8 mt7915_sku_group_len[] = { [SKU_CCK] = 4, [SKU_OFDM] = 8, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index adc26a222823..31aec0f40232 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -19,6 +19,7 @@ enum mt7915_eeprom_field { MT_EE_DDIE_FT_VERSION = 0x050, MT_EE_DO_PRE_CAL = 0x062, MT_EE_WIFI_CONF = 0x190, + MT_EE_DO_PRE_CAL_V2 = 0x19a, MT_EE_RATE_DELTA_2G = 0x252, MT_EE_RATE_DELTA_5G = 0x29d, MT_EE_TX0_POWER_2G = 0x2fc, @@ -39,12 +40,22 @@ enum mt7915_eeprom_field { }; #define MT_EE_WIFI_CAL_GROUP BIT(0) -#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1) +#define MT_EE_WIFI_CAL_DPD_2G BIT(2) +#define MT_EE_WIFI_CAL_DPD_5G BIT(1) +#define MT_EE_WIFI_CAL_DPD_6G BIT(3) +#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1) #define MT_EE_CAL_UNIT 1024 -#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16) -#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT) +#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16) +#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16) +#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16) +#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16) +#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16) +#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT) +#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT) +#define MT_EE_CAL_DPD_SIZE_V2_7981 (102 * MT_EE_CAL_UNIT) /* no 6g dpd data */ #define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0) +#define MT_EE_WIFI_CONF0_RX_PATH GENMASK(5, 3) #define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6) #define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(7, 6) #define MT_EE_WIFI_CONF_STREAM_NUM GENMASK(7, 5) @@ -156,6 +167,37 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) return val & MT_EE_WIFI_CONF7_TSSI0_5G; } +static inline u32 +mt7915_get_cal_group_size(struct mt7915_dev *dev) +{ + u8 *eep = dev->mt76.eeprom.data; + u32 val; + + if (is_mt7915(&dev->mt76)) { + return MT_EE_CAL_GROUP_SIZE_7915; + } else if (is_mt7916(&dev->mt76)) { + val = eep[MT_EE_WIFI_CONF + 1]; + val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); + return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G : + MT_EE_CAL_GROUP_SIZE_7916; + } else if (mt7915_check_adie(dev, false)) { + return MT_EE_CAL_GROUP_SIZE_7976; + } else { + return MT_EE_CAL_GROUP_SIZE_7975; + } +} + +static inline u32 +mt7915_get_cal_dpd_size(struct mt7915_dev *dev) +{ + if (is_mt7915(&dev->mt76)) + return MT_EE_CAL_DPD_SIZE_V1; + else if (is_mt7981(&dev->mt76)) + return MT_EE_CAL_DPD_SIZE_V2_7981; + else + return MT_EE_CAL_DPD_SIZE_V2; +} + extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM]; #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index cea2f6d9050a..3e30ca5155d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -53,7 +53,9 @@ static ssize_t mt7915_thermal_temp_show(struct device *dev, switch (i) { case 0: + mutex_lock(&phy->dev->mt76.mutex); temperature = mt7915_mcu_get_temperature(phy); + mutex_unlock(&phy->dev->mt76.mutex); if (temperature < 0) return temperature; /* display in millidegree celcius */ @@ -82,7 +84,7 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev, return ret; mutex_lock(&phy->dev->mt76.mutex); - val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 60, 130); + val = DIV_ROUND_CLOSEST(clamp_val(val, 60 * 1000, 130 * 1000), 1000); if ((i - 1 == MT7915_CRIT_TEMP_IDX && val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) || @@ -95,9 +97,8 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev, } phy->throttle_temp[i - 1] = val; - mutex_unlock(&phy->dev->mt76.mutex); - ret = mt7915_mcu_set_thermal_protect(phy); + mutex_unlock(&phy->dev->mt76.mutex); if (ret) return ret; @@ -159,7 +160,9 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev, * cooling_device convention: 0 = no cooling, more = more cooling * mcu convention: 1 = max cooling, more = less cooling */ + mutex_lock(&phy->dev->mt76.mutex); ret = mt7915_mcu_set_thermal_throttling(phy, throttling); + mutex_unlock(&phy->dev->mt76.mutex); if (ret) return ret; @@ -194,6 +197,8 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s", wiphy_name(wiphy)); + if (!name) + return -ENOMEM; cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops); if (!IS_ERR(cdev)) { @@ -280,7 +285,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy, { struct mt7915_dev *dev = phy->dev; int i, n_chains = hweight16(phy->mt76->chainmask); - int nss_delta = mt76_tx_power_nss_delta(n_chains); + int path_delta = mt76_tx_power_path_delta(n_chains); int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band); struct mt76_power_limits limits; @@ -300,7 +305,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy, target_power = mt76_get_rate_power_limits(phy->mt76, chan, &limits, target_power); - target_power += nss_delta; + target_power += path_delta; target_power = DIV_ROUND_UP(target_power, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); @@ -387,9 +392,10 @@ mt7915_init_wiphy(struct mt7915_phy *phy) if (!is_mt7915(&dev->mt76)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); - if (!mdev->dev->of_node || - !of_property_read_bool(mdev->dev->of_node, - "mediatek,disable-radar-background")) + if (mt7915_eeprom_has_background_radar(phy->dev) && + (!mdev->dev->of_node || + !of_property_read_bool(mdev->dev->of_node, + "mediatek,disable-radar-background"))) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RADAR_BACKGROUND); @@ -398,6 +404,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy) ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_TX_FRAG); hw->max_tx_fragments = 4; @@ -509,6 +516,15 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band), MT_WF_RMAC_MIB_QOS23_BACKOFF); + /* clear backoff time for Tx duration */ + mt76_clear(dev, MT_WTBLOFF_TOP_ACR(band), + MT_WTBLOFF_TOP_ADM_BACKOFFTIME); + + /* exclude estimated backoff time for Tx duration on MT7915 */ + if (is_mt7915(&dev->mt76)) + mt76_set(dev, MT_AGG_ATCR0(band), + MT_AGG_ATCR_MAC_BFF_TIME_EN); + /* clear backoff time and set software compensation for OBSS time */ mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET; set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) | @@ -823,7 +839,7 @@ mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2) if (ret < 0) return ret; - if (dev->flash_mode) { + if (dev->cal) { ret = mt7915_mcu_apply_group_cal(dev); if (ret) return ret; @@ -909,8 +925,7 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy, c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US; if (!is_mt7915(&dev->mt76)) - c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; + c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; elem->phy_cap_info[2] |= c; c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | @@ -934,11 +949,10 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy, /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3; - if (vif != NL80211_IFTYPE_AP) + if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION) return; elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; - elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, sts - 1); @@ -947,6 +961,11 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy, sts_160 - 1); elem->phy_cap_info[5] |= c; + if (vif != NL80211_IFTYPE_AP) + return; + + elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; + c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; @@ -1107,7 +1126,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, @@ -1232,14 +1251,14 @@ int mt7915_register_device(struct mt7915_dev *dev) if (ret) goto unreg_dev; - ieee80211_queue_work(mt76_hw(dev), &dev->init_work); - if (phy2) { ret = mt7915_register_ext_phy(dev, phy2); if (ret) goto unreg_thermal; } + ieee80211_queue_work(mt76_hw(dev), &dev->init_work); + dev->recovery.hw_init_done = true; ret = mt7915_init_debugfs(&dev->phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index b01edbed969c..9400e4af2a04 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -140,8 +140,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) msta->airtime_ac[i] = mt76_rr(dev, addr); msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); - tx_time[i] = msta->airtime_ac[i] - tx_last; - rx_time[i] = msta->airtime_ac[i + 4] - rx_last; + if (msta->airtime_ac[i] <= tx_last) + tx_time[i] = 0; + else + tx_time[i] = msta->airtime_ac[i] - tx_last; + + if (msta->airtime_ac[i + 4] <= rx_last) + rx_time[i] = 0; + else + rx_time[i] = msta->airtime_ac[i + 4] - rx_last; if ((tx_last | rx_last) & BIT(30)) clear = true; @@ -326,11 +333,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, if (status->wcid) { msta = container_of(status->wcid, struct mt7915_sta, wcid); - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); } status->freq = mphy->chandef.chan->center_freq; @@ -920,11 +923,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7915_sta, wcid); - spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &mdev->sta_poll_list); - spin_unlock_bh(&mdev->sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); continue; } @@ -1033,10 +1032,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) if (!wcid->sta) goto out; - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); out: rcu_read_unlock(); @@ -1156,7 +1152,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); u8 band = phy->mt76->band_idx; - int eifs_ofdm = 360, sifs = 10, offset; + int eifs_ofdm = 84, sifs = 10, offset; bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) @@ -1338,10 +1334,8 @@ mt7915_mac_restart(struct mt7915_dev *dev) set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); - if (ext_phy) { + if (ext_phy) set_bit(MT76_RESET, &ext_phy->state); - set_bit(MT76_MCU_RESET, &ext_phy->state); - } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); @@ -1362,10 +1356,15 @@ mt7915_mac_restart(struct mt7915_dev *dev) mt7915_dma_reset(dev, true); - local_bh_disable(); mt76_for_each_q_rx(mdev, i) { if (mdev->q_rx[i].ndesc) { napi_enable(&dev->mt76.napi[i]); + } + } + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + if (mdev->q_rx[i].ndesc) { napi_schedule(&dev->mt76.napi[i]); } } @@ -1383,6 +1382,8 @@ mt7915_mac_restart(struct mt7915_dev *dev) if (dev_is_pci(mdev->dev)) { mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); if (dev->hif2) { + mt76_wr(dev, MT_PCIE_RECOG_ID, + dev->hif2->index | MT_PCIE_RECOG_ID_SEM); if (is_mt7915(mdev)) mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); else @@ -1423,8 +1424,9 @@ out: if (phy2) clear_bit(MT76_RESET, &phy2->mt76->state); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); + + local_bh_disable(); napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); @@ -1437,12 +1439,15 @@ static void mt7915_mac_full_reset(struct mt7915_dev *dev) { struct mt76_phy *ext_phy; + struct mt7915_phy *phy2; int i; ext_phy = dev->mt76.phys[MT_BAND1]; + phy2 = ext_phy ? ext_phy->priv : NULL; dev->recovery.hw_full_reset = true; + set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); ieee80211_stop_queues(mt76_hw(dev)); if (ext_phy) @@ -1457,26 +1462,30 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) if (!mt7915_mac_restart(dev)) break; } - mutex_unlock(&dev->mt76.mutex); if (i == 10) dev_err(dev->mt76.dev, "chip full reset failed\n"); - ieee80211_restart_hw(mt76_hw(dev)); - if (ext_phy) - ieee80211_restart_hw(ext_phy->hw); + spin_lock_bh(&dev->mt76.sta_poll_lock); + while (!list_empty(&dev->mt76.sta_poll_list)) + list_del_init(dev->mt76.sta_poll_list.next); + spin_unlock_bh(&dev->mt76.sta_poll_lock); - ieee80211_wake_queues(mt76_hw(dev)); - if (ext_phy) - ieee80211_wake_queues(ext_phy->hw); + memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask)); + dev->mt76.vif_mask = 0; + dev->phy.omac_mask = 0; + if (phy2) + phy2->omac_mask = 0; + i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); + dev->mt76.global_wcid.idx = i; dev->recovery.hw_full_reset = false; - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, - MT7915_WATCHDOG_TIME); + + mutex_unlock(&dev->mt76.mutex); + + ieee80211_restart_hw(mt76_hw(dev)); if (ext_phy) - ieee80211_queue_delayed_work(ext_phy->hw, - &ext_phy->mac_work, - MT7915_WATCHDOG_TIME); + ieee80211_restart_hw(ext_phy->hw); } /* system error recovery */ @@ -1520,12 +1529,6 @@ void mt7915_mac_reset_work(struct work_struct *work) if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) return; - if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { - mtk_wed_device_stop(&dev->mt76.mmio.wed); - if (!is_mt798x(&dev->mt76)) - mt76_wr(dev, MT_INT_WED_MASK_CSR, 0); - } - ieee80211_stop_queues(mt76_hw(dev)); if (ext_phy) ieee80211_stop_queues(ext_phy->hw); @@ -1538,12 +1541,17 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); } + + mutex_lock(&dev->mt76.mutex); + mt76_worker_disable(&dev->mt76.tx_worker); mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); napi_disable(&dev->mt76.tx_napi); - mutex_lock(&dev->mt76.mutex); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mtk_wed_device_stop(&dev->mt76.mmio.wed); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); @@ -1568,9 +1576,12 @@ void mt7915_mac_reset_work(struct work_struct *work) if (phy2) clear_bit(MT76_RESET, &phy2->mt76->state); - local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { napi_enable(&dev->mt76.napi[i]); + } + + local_bh_disable(); + mt76_for_each_q_rx(&dev->mt76, i) { napi_schedule(&dev->mt76.napi[i]); } local_bh_enable(); @@ -1579,8 +1590,8 @@ void mt7915_mac_reset_work(struct work_struct *work) mt76_worker_enable(&dev->mt76.tx_worker); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); + local_bh_disable(); napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); @@ -1690,6 +1701,11 @@ void mt7915_reset(struct mt7915_dev *dev) return; } + if ((READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) { + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + } + queue_work(dev->mt76.wq, &dev->reset_work); wake_up(&dev->reset_wait); } @@ -2019,16 +2035,15 @@ void mt7915_mac_work(struct work_struct *work) static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; + int rdd_idx = mt7915_get_rdd_idx(phy, false); - if (phy->rdd_state & BIT(0)) - mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0, - MT_RX_SEL0, 0); - if (phy->rdd_state & BIT(1)) - mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1, - MT_RX_SEL0, 0); + if (rdd_idx < 0) + return; + + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0); } -static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) +static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int rdd_idx) { int err, region; @@ -2045,52 +2060,38 @@ static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) break; } - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain, - MT_RX_SEL0, region); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region); if (err < 0) return err; if (is_mt7915(&dev->mt76)) { - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, chain, + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, rdd_idx, 0, dev->dbdc_support ? 2 : 0); if (err < 0) return err; } - return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain, - MT_RX_SEL0, 1); + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, rdd_idx, 0, 1); } static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy) { - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; struct mt7915_dev *dev = phy->dev; - int err; + int err, rdd_idx; + + rdd_idx = mt7915_get_rdd_idx(phy, false); + if (rdd_idx < 0) + return -EINVAL; /* start CAC */ - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, - phy->mt76->band_idx, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, rdd_idx, 0, 0); if (err < 0) return err; - err = mt7915_dfs_start_rdd(dev, phy->mt76->band_idx); + err = mt7915_dfs_start_rdd(dev, rdd_idx); if (err < 0) return err; - phy->rdd_state |= BIT(phy->mt76->band_idx); - - if (!is_mt7915(&dev->mt76)) - return 0; - - if (chandef->width == NL80211_CHAN_WIDTH_160 || - chandef->width == NL80211_CHAN_WIDTH_80P80) { - err = mt7915_dfs_start_rdd(dev, 1); - if (err < 0) - return err; - - phy->rdd_state |= BIT(1); - } - return 0; } @@ -2132,12 +2133,12 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; enum mt76_dfs_state dfs_state, prev_state; - int err; + int err, rdd_idx = mt7915_get_rdd_idx(phy, false); prev_state = phy->mt76->dfs_state; dfs_state = mt76_phy_dfs_state(phy->mt76); - if (prev_state == dfs_state) + if (prev_state == dfs_state || rdd_idx < 0) return 0; if (prev_state == MT_DFS_STATE_UNKNOWN) @@ -2161,8 +2162,7 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) if (dfs_state == MT_DFS_STATE_CAC) return 0; - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, - phy->mt76->band_idx, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, rdd_idx, 0, 0); if (err < 0) { phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; return err; @@ -2172,15 +2172,13 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) return 0; stop: - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, - phy->mt76->band_idx, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, rdd_idx, 0, 0); if (err < 0) return err; if (is_mt7915(&dev->mt76)) { err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, - phy->mt76->band_idx, 0, - dev->dbdc_support ? 2 : 0); + rdd_idx, 0, dev->dbdc_support ? 2 : 0); if (err < 0) return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index df2d4279790d..3aa31c5cefa6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -108,7 +108,7 @@ static int mt7915_start(struct ieee80211_hw *hw) return ret; } -static void mt7915_stop(struct ieee80211_hw *hw) +static void mt7915_stop(struct ieee80211_hw *hw, bool suspend) { struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); @@ -233,6 +233,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, mvif->mt76.omac_idx = idx; mvif->phy = phy; mvif->mt76.band_idx = phy->mt76->band_idx; + mvif->mt76.wcid = &mvif->sta.wcid; mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; if (ext_phy) @@ -245,15 +246,16 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev)); + if (idx < 0) { + ret = -ENOSPC; + goto out; + } INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.phy_idx = ext_phy; - mvif->sta.wcid.hw_key_idx = -1; mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_wcid_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid, phy->mt76->band_idx); mt7915_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -272,7 +274,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, memset(&mvif->cap, -1, sizeof(mvif->cap)); mt7915_mcu_add_bss_info(phy, vif, true); - mt7915_mcu_add_sta(dev, vif, NULL, true); + mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true); rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); out: @@ -291,7 +293,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, int idx = msta->wcid.idx; mt7915_mcu_add_bss_info(phy, vif, false); - mt7915_mcu_add_sta(dev, vif, NULL, false); + mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false); + mt76_wcid_mask_clear(dev->mt76.wcid_mask, mvif->sta.wcid.idx); mutex_lock(&dev->mt76.mutex); mt76_testmode_reset(phy->mt76, true); @@ -317,19 +320,13 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, mt76_wcid_cleanup(&dev->mt76, &msta->wcid); } -int mt7915_set_channel(struct mt7915_phy *phy) +int mt7915_set_channel(struct mt76_phy *mphy) { + struct mt7915_phy *phy = mphy->priv; struct mt7915_dev *dev = phy->dev; int ret; - cancel_delayed_work_sync(&phy->mt76->mac_work); - - mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &phy->mt76->state); - - mt76_set_channel(phy->mt76); - - if (dev->flash_mode) { + if (dev->cal) { ret = mt7915_mcu_apply_tx_dpd(phy); if (ret) goto out; @@ -347,11 +344,6 @@ int mt7915_set_channel(struct mt7915_phy *phy) phy->noise = 0; out: - clear_bit(MT76_RESET, &phy->mt76->state); - mutex_unlock(&dev->mt76.mutex); - - mt76_txq_schedule_all(phy->mt76); - if (!mt76_testmode_enabled(phy->mt76)) ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, @@ -374,6 +366,13 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int idx = key->keyidx; int err = 0; + if (sta && !wcid->sta) { + if (cmd != SET_KEY) + return 0; + + return -EOPNOTSUPP; + } + /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. */ @@ -464,11 +463,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); } #endif - ieee80211_stop_queues(hw); - ret = mt7915_set_channel(phy); + ret = mt76_update_channel(phy->mt76); if (ret) return ret; - ieee80211_wake_queues(hw); } if (changed & (IEEE80211_CONF_CHANGE_POWER | @@ -564,8 +561,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | MT_WF_RFCR_DROP_RTS | - MT_WF_RFCR_DROP_CTL_RSV | - MT_WF_RFCR_DROP_NDPA); + MT_WF_RFCR_DROP_CTL_RSV); *total_flags = flags; rxfilter = phy->rxfilter; @@ -627,19 +623,24 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) set_bss_info = vif->cfg.assoc; if (changed & BSS_CHANGED_BEACON_ENABLED && + info->enable_beacon && vif->type != NL80211_IFTYPE_AP) - set_bss_info = set_sta = info->enable_beacon; + set_bss_info = set_sta = 1; if (set_bss_info == 1) mt7915_mcu_add_bss_info(phy, vif, true); if (set_sta == 1) - mt7915_mcu_add_sta(dev, vif, NULL, true); + mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false); if (changed & BSS_CHANGED_ERP_CTS_PROT) mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot); if (changed & BSS_CHANGED_ERP_SLOT) { - int slottime = info->use_short_slot ? 9 : 20; + int slottime = 9; + + if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ && + !info->use_short_slot) + slottime = 20; if (slottime != phy->slottime) { phy->slottime = slottime; @@ -668,7 +669,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, if (set_bss_info == 0) mt7915_mcu_add_bss_info(phy, vif, false); if (set_sta == 0) - mt7915_mcu_add_sta(dev, vif, NULL, false); + mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false); mutex_unlock(&dev->mt76.mutex); } @@ -706,7 +707,7 @@ mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = mt7915_mcu_add_bss_info(phy, vif, true); if (err) goto out; - err = mt7915_mcu_add_sta(dev, vif, NULL, true); + err = mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false); out: mutex_unlock(&dev->mt76.mutex); @@ -720,7 +721,7 @@ mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7915_dev *dev = mt7915_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7915_mcu_add_sta(dev, vif, NULL, false); + mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false); mutex_unlock(&dev->mt76.mutex); } @@ -743,7 +744,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; bool ext_phy = mvif->phy != &dev->phy; - int ret, idx; + int idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); if (idx < 0) @@ -752,22 +753,113 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, INIT_LIST_HEAD(&msta->rc_list); INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; - msta->wcid.sta = 1; + msta->wcid.sta_disabled = 1; msta->wcid.idx = idx; msta->wcid.phy_idx = ext_phy; - msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; msta->jiffies = jiffies; ewma_avg_signal_init(&msta->avg_ack_signal); mt7915_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, true); - ret = mt7915_mcu_add_sta(dev, vif, sta, true); - if (ret) - return ret; + return 0; +} + +struct drop_sta_iter { + struct mt7915_dev *dev; + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + u8 sta_addr[ETH_ALEN]; +}; + +static void +__mt7915_drop_sta(void *ptr, u8 *mac, struct ieee80211_vif *vif) +{ + struct drop_sta_iter *data = ptr; + struct ieee80211_sta *sta; + struct mt7915_sta *msta; + + if (vif == data->vif || vif->type != NL80211_IFTYPE_AP) + return; + + sta = ieee80211_find_sta_by_ifaddr(data->hw, data->sta_addr, mac); + if (!sta) + return; + + msta = (struct mt7915_sta *)sta->drv_priv; + mt7915_mcu_add_sta(data->dev, vif, sta, CONN_STATE_DISCONNECT, false); + msta->wcid.sta_disabled = 1; + msta->wcid.sta = 0; +} + +static void +mt7915_drop_other_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_phy *ext_phy = dev->mt76.phys[MT_BAND1]; + struct drop_sta_iter data = { + .dev = dev, + .hw = dev->mphy.hw, + .vif = vif, + }; + + if (vif->type != NL80211_IFTYPE_AP) + return; + + memcpy(data.sta_addr, sta->addr, ETH_ALEN); + ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data); + + if (!ext_phy) + return; + + data.hw = ext_phy->hw; + ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data); +} + +int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + int i, ret; + u32 addr; - return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); + switch (ev) { + case MT76_STA_EVENT_ASSOC: + ret = mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_CONNECT, true); + if (ret) + return ret; + + addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30); + mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0); + + ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); + if (ret) + return ret; + + msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta->wcid.sta = 1; + msta->wcid.sta_disabled = 0; + + return 0; + + case MT76_STA_EVENT_AUTHORIZE: + mt7915_drop_other_sta(dev, vif, sta); + return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false); + + case MT76_STA_EVENT_DISASSOC: + for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) + mt7915_mac_twt_teardown_flow(dev, msta, i); + + mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false); + msta->wcid.sta_disabled = 1; + msta->wcid.sta = 0; + return 0; + } + + return 0; } void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, @@ -775,16 +867,10 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - int i; - - mt7915_mcu_add_sta(dev, vif, sta, false); mt7915_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) - mt7915_mac_twt_teardown_flow(dev, msta, i); - spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&msta->wcid.poll_list)) list_del_init(&msta->wcid.poll_list); @@ -892,22 +978,6 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static int -mt7915_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, - IEEE80211_STA_NONE); -} - -static int -mt7915_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, - IEEE80211_STA_NOTEXIST); -} - -static int mt7915_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -1085,8 +1155,7 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, struct rate_info *txrate = &msta->wcid.rate; struct rate_info rxrate = {}; - if (is_mt7915(&phy->dev->mt76) && - !mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { + if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { sinfo->rxrate = rxrate; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); } @@ -1155,11 +1224,16 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) static void mt7915_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = phy->dev; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + + if (!msta->wcid.sta) + return; mt7915_sta_rc_work(&changed, sta); ieee80211_queue_work(hw, &dev->rc_work); @@ -1203,6 +1277,9 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, else clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + if (!msta->wcid.sta) + return; + mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } @@ -1219,6 +1296,9 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw, else clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + if (!msta->wcid.sta) + return; + mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } @@ -1575,6 +1655,12 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw, } static int +mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val) +{ + return 0; +} + +static int mt7915_set_radar_background(struct ieee80211_hw *hw, struct cfg80211_chan_def *chandef) { @@ -1656,7 +1742,22 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, } #endif +static void +mt7915_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + + ieee80211_wake_queues(hw); + ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + MT7915_WATCHDOG_TIME); +} + const struct ieee80211_ops mt7915_ops = { + .add_chanctx = ieee80211_emulate_add_chanctx, + .remove_chanctx = ieee80211_emulate_remove_chanctx, + .change_chanctx = ieee80211_emulate_change_chanctx, + .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, .tx = mt7915_tx, .start = mt7915_start, .stop = mt7915_stop, @@ -1668,10 +1769,9 @@ const struct ieee80211_ops mt7915_ops = { .bss_info_changed = mt7915_bss_info_changed, .start_ap = mt7915_start_ap, .stop_ap = mt7915_stop_ap, - .sta_add = mt7915_sta_add, - .sta_remove = mt7915_sta_remove, + .sta_state = mt76_sta_state, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, - .sta_rc_update = mt7915_sta_rc_update, + .link_sta_rc_update = mt7915_sta_rc_update, .set_key = mt7915_set_key, .ampdu_action = mt7915_ampdu_action, .set_rts_threshold = mt7915_set_rts_threshold, @@ -1700,6 +1800,7 @@ const struct ieee80211_ops mt7915_ops = { .sta_set_decap_offload = mt7915_sta_set_decap_offload, .add_twt_setup = mt7915_mac_add_twt_setup, .twt_teardown_request = mt7915_twt_teardown_request, + .set_frag_threshold = mt7915_set_frag_threshold, CFG80211_TESTMODE_CMD(mt76_testmode_cmd) CFG80211_TESTMODE_DUMP(mt76_testmode_dump) #ifdef CONFIG_MAC80211_DEBUGFS @@ -1708,6 +1809,7 @@ const struct ieee80211_ops mt7915_ops = { .set_radar_background = mt7915_set_radar_background, #ifdef CONFIG_NET_MEDIATEK_SOC_WED .net_fill_forward_path = mt7915_net_fill_forward_path, - .net_setup_tc = mt76_net_setup_tc, + .net_setup_tc = mt76_wed_net_setup_tc, #endif + .reconfig_complete = mt7915_reconfig_complete, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index c67c4f6ca2aa..427542777abc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -157,12 +157,21 @@ static int mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq) { + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); struct mt76_connac2_mcu_rxd *rxd; int ret = 0; if (!skb) { dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", cmd, seq); + + if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) { + dev->recovery.restart = true; + wake_up(&dev->mt76.mcu.wait); + queue_work(dev->mt76.wq, &dev->reset_work); + wake_up(&dev->reset_wait); + } + return -ETIMEDOUT; } @@ -185,17 +194,31 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, return ret; } +static void +mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd) +{ + if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID) + return; + + switch (FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd)) { + case MCU_EXT_CMD_THERMAL_CTRL: + case MCU_EXT_CMD_GET_MIB_INFO: + case MCU_EXT_CMD_PHY_STAT_INFO: + case MCU_EXT_CMD_STA_REC_UPDATE: + case MCU_EXT_CMD_BSS_INFO_UPDATE: + mdev->mcu.timeout = 2 * HZ; + return; + default: + break; + } +} + static int mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *wait_seq) { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); enum mt76_mcuq_id qid; - int ret; - - ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq); - if (ret) - return ret; if (cmd == MCU_CMD(FW_SCATTER)) qid = MT_MCUQ_FWDL; @@ -204,6 +227,8 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, else qid = MT_MCUQ_WM; + mt7915_mcu_set_timeout(mdev, cmd); + return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0); } @@ -228,7 +253,7 @@ mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION) return; - ieee80211_csa_finish(vif); + ieee80211_csa_finish(vif, 0); } static void @@ -278,22 +303,40 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt7915_mcu_rdd_report *r; + u32 sku; r = (struct mt7915_mcu_rdd_report *)skb->data; - if (r->band_idx > MT_RX_SEL2) + switch (r->rdd_idx) { + case MT_RDD_IDX_BAND0: + break; + case MT_RDD_IDX_BAND1: + sku = mt7915_check_adie(dev, true); + /* the main phy is bound to band 1 for this sku */ + if (is_mt7986(&dev->mt76) && + (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE)) + break; + mphy = dev->mt76.phys[MT_BAND1]; + break; + case MT_RDD_IDX_BACKGROUND: + if (!dev->rdd2_phy) + return; + mphy = dev->rdd2_phy->mt76; + break; + default: + dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx); return; + } - if ((r->band_idx && !dev->phy.mt76->band_idx) && - dev->mt76.phys[MT_BAND1]) - mphy = dev->mt76.phys[MT_BAND1]; + if (!mphy) + return; - if (r->band_idx == MT_RX_SEL2) + if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) cfg80211_background_radar_event(mphy->hw->wiphy, &dev->rdd2_chandef, GFP_ATOMIC); else - ieee80211_radar_detected(mphy->hw); + ieee80211_radar_detected(mphy->hw, NULL); dev->hw_pattern++; } @@ -331,7 +374,7 @@ mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION) return; - ieee80211_color_change_finish(vif); + ieee80211_color_change_finish(vif, 0); } static void @@ -424,7 +467,7 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, .len = cpu_to_le16(sub_len), }; - ptlv = skb_put(skb, sub_len); + ptlv = skb_put_zero(skb, sub_len); memcpy(ptlv, &tlv, sizeof(tlv)); le16_add_cpu(sub_ntlv, 1); @@ -463,10 +506,10 @@ static bool mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw, .tolerated = true, }; - if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) + if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR)) return false; - cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef, + cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper, mt7915_check_he_obss_narrow_bw_ru_iter, &iter_data); @@ -690,13 +733,17 @@ int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, { struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; struct mt7915_vif *mvif = msta->vif; + int ret; + mt76_worker_disable(&dev->mt76.tx_worker); if (enable && !params->amsdu) msta->wcid.amsdu = false; + ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, true); + mt76_worker_enable(&dev->mt76.tx_worker); - return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, - MCU_EXT_CMD(STA_REC_UPDATE), - enable, true); + return ret; } int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, @@ -1193,7 +1240,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; - const u8 matrix[4][4] = { + static const u8 matrix[4][4] = { {0, 0, 0, 0}, {1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */ {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */ @@ -1503,7 +1550,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ra->valid = true; ra->auto_rate = true; - ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta); + ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink); ra->channel = chandef->chan->hw_value; ra->bw = sta->deflink.bandwidth; ra->phy.bw = sta->deflink.bandwidth; @@ -1653,14 +1700,16 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif, } int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable) + struct ieee80211_sta *sta, int conn_state, bool newly) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta; struct mt7915_sta *msta; struct sk_buff *skb; int ret; msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; + link_sta = sta ? &sta->deflink : NULL; skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &msta->wcid); @@ -1668,13 +1717,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, return PTR_ERR(skb); /* starec basic */ - mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable, - !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); - if (!enable) - goto out; - + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, &vif->bss_conf, link_sta, + conn_state, newly); /* tag order is in accordance with firmware dependency. */ - if (sta) { + if (sta && conn_state != CONN_STATE_DISCONNECT) { /* starec bfer */ mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta); /* starec ht */ @@ -1685,12 +1731,17 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, mt76_connac_mcu_sta_uapsd(skb, vif, sta); } - ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta); - if (ret) { - dev_kfree_skb(skb); - return ret; + if (newly || conn_state != CONN_STATE_DISCONNECT) { + ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta); + if (ret) { + dev_kfree_skb(skb); + return ret; + } } + if (conn_state == CONN_STATE_DISCONNECT) + goto out; + if (sta) { /* starec amsdu */ mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta); @@ -1919,8 +1970,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, bcn = (struct bss_info_bcn *)tlv; bcn->enable = true; - if (changed & BSS_CHANGED_FILS_DISCOVERY && - vif->bss_conf.fils_discovery.max_interval) { + if (changed & BSS_CHANGED_FILS_DISCOVERY) { interval = vif->bss_conf.fils_discovery.max_interval; skb = ieee80211_get_fils_discovery_tmpl(hw, vif); } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && @@ -1957,7 +2007,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); discov->tx_interval = interval; discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); - discov->enable = true; + discov->enable = !!interval; buf = (u8 *)sub_tlv + sizeof(*discov); @@ -2351,6 +2401,8 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) if (ret) return ret; + mt76_connac_mcu_del_wtbl_all(&dev->mt76); + if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76)) || !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) @@ -2375,7 +2427,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) int mt7915_mcu_init(struct mt7915_dev *dev) { static const struct mt76_mcu_ops mt7915_mcu_ops = { + .max_retry = 1, .headroom = sizeof(struct mt76_connac2_mcu_txd), + .mcu_skb_prepare_msg = mt76_connac2_mcu_fill_message, .mcu_skb_send_msg = mt7915_mcu_send_message, .mcu_parse_response = mt7915_mcu_parse_response, }; @@ -2661,11 +2715,14 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef) { struct mt7915_dev *dev = phy->dev; - int err, region; + int err, region, rdd_idx; + + rdd_idx = mt7915_get_rdd_idx(phy, true); + if (rdd_idx < 0) + return -EINVAL; if (!chandef) { /* disable offchain */ - err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2, - 0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0); if (err) return err; @@ -2691,8 +2748,7 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, break; } - return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2, - 0, region); + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region); } int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) @@ -2746,7 +2802,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL || + else if (phy->mt76->offchannel || phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, @@ -2823,7 +2879,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev) &req, sizeof(req), true); } -int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) +int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf) { struct mt7915_mcu_eeprom_info req = { .addr = cpu_to_le32(round_down(offset, @@ -2831,8 +2887,8 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) }; struct mt7915_mcu_eeprom_info *res; struct sk_buff *skb; + u8 *buf = read_buf; int ret; - u8 *buf; ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_ACCESS), @@ -2841,8 +2897,10 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) return ret; res = (struct mt7915_mcu_eeprom_info *)skb->data; - buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); + if (!buf) + buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE); + dev_kfree_skb(skb); return 0; @@ -2904,9 +2962,10 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx, int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev) { u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data; - u32 total = MT_EE_CAL_GROUP_SIZE; + u32 total = mt7915_get_cal_group_size(dev); + u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2; - if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP)) + if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP)) return 0; /* @@ -2942,9 +3001,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur) return -1; } -static int mt7915_dpd_freq_idx(u16 freq, u8 bw) +static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw) { - static const u16 freq_list[] = { + static const u16 freq_list_v1[] = { 5180, 5200, 5220, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, @@ -2952,65 +3011,135 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw) 5660, 5680, 5700, 5745, 5765, 5785, 5805, 5825 }; - int offset_2g = ARRAY_SIZE(freq_list); + static const u16 freq_list_v2[] = { + /* 6G BW20*/ + 5955, 5975, 5995, 6015, + 6035, 6055, 6075, 6095, + 6115, 6135, 6155, 6175, + 6195, 6215, 6235, 6255, + 6275, 6295, 6315, 6335, + 6355, 6375, 6395, 6415, + 6435, 6455, 6475, 6495, + 6515, 6535, 6555, 6575, + 6595, 6615, 6635, 6655, + 6675, 6695, 6715, 6735, + 6755, 6775, 6795, 6815, + 6835, 6855, 6875, 6895, + 6915, 6935, 6955, 6975, + 6995, 7015, 7035, 7055, + 7075, 7095, 7115, + /* 6G BW160 */ + 6025, 6185, 6345, 6505, + 6665, 6825, 6985, + /* 5G BW20 */ + 5180, 5200, 5220, 5240, + 5260, 5280, 5300, 5320, + 5500, 5520, 5540, 5560, + 5580, 5600, 5620, 5640, + 5660, 5680, 5700, 5720, + 5745, 5765, 5785, 5805, + 5825, 5845, 5865, 5885, + /* 5G BW160 */ + 5250, 5570, 5815 + }; + static const u16 freq_list_v2_7981[] = { + /* 5G BW20 */ + 5180, 5200, 5220, 5240, + 5260, 5280, 5300, 5320, + 5500, 5520, 5540, 5560, + 5580, 5600, 5620, 5640, + 5660, 5680, 5700, 5720, + 5745, 5765, 5785, 5805, + 5825, 5845, 5865, 5885, + /* 5G BW160 */ + 5250, 5570, 5815 + }; + const u16 *freq_list = freq_list_v1; + int n_freqs = ARRAY_SIZE(freq_list_v1); int idx; + if (!is_mt7915(&dev->mt76)) { + if (is_mt7981(&dev->mt76)) { + freq_list = freq_list_v2_7981; + n_freqs = ARRAY_SIZE(freq_list_v2_7981); + } else { + freq_list = freq_list_v2; + n_freqs = ARRAY_SIZE(freq_list_v2); + } + } + if (freq < 4000) { if (freq < 2432) - return offset_2g; + return n_freqs; if (freq < 2457) - return offset_2g + 1; + return n_freqs + 1; - return offset_2g + 2; + return n_freqs + 2; } - if (bw == NL80211_CHAN_WIDTH_80P80 || bw == NL80211_CHAN_WIDTH_160) + if (bw == NL80211_CHAN_WIDTH_80P80) return -1; if (bw != NL80211_CHAN_WIDTH_20) { - idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), - freq + 10); + idx = mt7915_find_freq_idx(freq_list, n_freqs, freq + 10); if (idx >= 0) return idx; - idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), - freq - 10); + idx = mt7915_find_freq_idx(freq_list, n_freqs, freq - 10); if (idx >= 0) return idx; } - return mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq); + return mt7915_find_freq_idx(freq_list, n_freqs, freq); } int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; - u16 total = 2, center_freq = chandef->center_freq1; + enum nl80211_band band = chandef->chan->band; + u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2; + u16 center_freq = chandef->center_freq1; u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data; + u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3; int idx; - if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD)) + switch (band) { + case NL80211_BAND_2GHZ: + dpd_mask = MT_EE_WIFI_CAL_DPD_2G; + break; + case NL80211_BAND_5GHZ: + dpd_mask = MT_EE_WIFI_CAL_DPD_5G; + break; + case NL80211_BAND_6GHZ: + dpd_mask = MT_EE_WIFI_CAL_DPD_6G; + break; + default: + dpd_mask = 0; + break; + } + + if (!(eep[offs] & dpd_mask)) return 0; - idx = mt7915_dpd_freq_idx(center_freq, chandef->width); + idx = mt7915_dpd_freq_idx(dev, center_freq, chandef->width); if (idx < 0) return -EINVAL; /* Items: Tx DPD, Tx Flatness */ - idx = idx * 2; - cal += MT_EE_CAL_GROUP_SIZE; + idx = idx * cal_num; + cal += mt7915_get_cal_group_size(dev) + (idx * MT_EE_CAL_UNIT); - while (total--) { + while (cal_num--) { int ret; - cal += (idx * MT_EE_CAL_UNIT); ret = mt7915_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT, MCU_EXT_CMD(DPD_PRE_CAL_INFO)); if (ret) return ret; idx++; + cal += MT_EE_CAL_UNIT; } return 0; @@ -3064,8 +3193,13 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) res = (struct mt7915_mcu_mib *)(skb->data + offs_cc); #define __res_u64(s) le64_to_cpu(res[s].data) - /* subtract Tx backoff time from Tx duration */ - cc_tx = is_mt7915(&dev->mt76) ? __res_u64(1) - __res_u64(4) : __res_u64(1); + /* subtract Tx backoff time from Tx duration for MT7915 */ + if (is_mt7915(&dev->mt76)) { + u64 backoff = (__res_u64(4) & 0xffff) * 79; /* 16us + 9us * 7 */ + cc_tx = __res_u64(1) - backoff; + } else { + cc_tx = __res_u64(1); + } if (chan_switch) goto out; @@ -3211,7 +3345,7 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, if (ret) return ret; - txpower = mt7915_get_power_bound(phy, txpower); + txpower = mt76_get_power_bound(mphy, txpower); if (txpower > mphy->txpower_cur || txpower < 0) return -EINVAL; @@ -3261,7 +3395,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy) int i, idx; int tx_power; - tx_power = mt7915_get_power_bound(phy, hw->conf.power_level); + tx_power = mt76_get_power_bound(mphy, hw->conf.power_level); tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, &limits_array, tx_power); mphy->txpower_cur = tx_power; @@ -3801,30 +3935,38 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx) { struct { __le32 cmd; - __le32 num; - __le32 __rsv; - __le16 wlan_idx; - } req = { + __le32 arg0; + __le32 arg1; + __le16 arg2; + } __packed req = { .cmd = cpu_to_le32(0x15), - .num = cpu_to_le32(1), - .wlan_idx = cpu_to_le16(wlan_idx), }; struct mt7915_mcu_wa_tx_stat { - __le16 wlan_idx; - u8 __rsv[2]; + __le16 wcid; + u8 __rsv2[2]; /* tx_bytes is deprecated since WA byte counter uses u32, * which easily leads to overflow. */ __le32 tx_bytes; __le32 tx_packets; - } *res; + } __packed *res; struct mt76_wcid *wcid; struct sk_buff *skb; - int ret; + int ret, len; + u16 ret_wcid; + + if (is_mt7915(&dev->mt76)) { + req.arg0 = cpu_to_le32(wlan_idx); + len = sizeof(req) - sizeof(req.arg2); + } else { + req.arg0 = cpu_to_le32(1); + req.arg2 = cpu_to_le16(wlan_idx); + len = sizeof(req); + } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY), - &req, sizeof(req), true, &skb); + &req, len, true, &skb); if (ret) return ret; @@ -3833,7 +3975,11 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx) res = (struct mt7915_mcu_wa_tx_stat *)skb->data; - if (le16_to_cpu(res->wlan_idx) != wlan_idx) { + ret_wcid = le16_to_cpu(res->wcid); + if (is_mt7915(&dev->mt76)) + ret_wcid &= 0xff; + + if (ret_wcid != wlan_idx) { ret = -EINVAL; goto out; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index b41ac4aaced7..086ad89ecd91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -29,7 +29,7 @@ struct mt7915_mcu_thermal_ctrl { } __packed; struct mt7915_mcu_thermal_notify { - struct mt76_connac2_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd_hdr rxd; struct mt7915_mcu_thermal_ctrl ctrl; __le32 temperature; @@ -37,7 +37,7 @@ struct mt7915_mcu_thermal_notify { } __packed; struct mt7915_mcu_csa_notify { - struct mt76_connac2_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd_hdr rxd; u8 omac_idx; u8 csa_count; @@ -46,7 +46,7 @@ struct mt7915_mcu_csa_notify { } __packed; struct mt7915_mcu_bcc_notify { - struct mt76_connac2_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd_hdr rxd; u8 band_idx; u8 omac_idx; @@ -55,9 +55,9 @@ struct mt7915_mcu_bcc_notify { } __packed; struct mt7915_mcu_rdd_report { - struct mt76_connac2_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd_hdr rxd; - u8 band_idx; + u8 rdd_idx; u8 long_detected; u8 constant_prf_detected; u8 staggered_prf_detected; @@ -515,16 +515,4 @@ enum { sizeof(struct bss_info_bmc_rate) +\ sizeof(struct bss_info_ext_bss)) -static inline s8 -mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower) -{ - struct mt76_phy *mphy = phy->mt76; - int n_chains = hweight16(mphy->chainmask); - - txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2); - txpower -= mt76_tx_power_nss_delta(n_chains); - - return txpower; -} - #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 3039f53e2245..9c4d5cea0c42 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -138,6 +138,7 @@ static const u32 mt7915_offs[] = { [AGG_ACR0] = 0x084, [AGG_ACR4] = 0x08c, [AGG_MRCR] = 0x098, + [AGG_ATCR0] = 0x0ec, [AGG_ATCR1] = 0x0f0, [AGG_ATCR3] = 0x0f4, [LPON_UTTR0] = 0x080, @@ -212,6 +213,7 @@ static const u32 mt7916_offs[] = { [AGG_ACR0] = 0x054, [AGG_ACR4] = 0x05c, [AGG_MRCR] = 0x068, + [AGG_ATCR0] = 0x1a4, [AGG_ATCR1] = 0x1a8, [AGG_ATCR3] = 0x080, [LPON_UTTR0] = 0x360, @@ -484,12 +486,17 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr) continue; ofs = addr - dev->reg.map[i].phys; - if (ofs > dev->reg.map[i].size) + if (ofs >= dev->reg.map[i].size) continue; return dev->reg.map[i].maps + ofs; } + return 0; +} + +static u32 __mt7915_reg_remap_addr(struct mt7915_dev *dev, u32 addr) +{ if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) || (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) || (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END)) @@ -514,15 +521,30 @@ void mt7915_memcpy_fromio(struct mt7915_dev *dev, void *buf, u32 offset, { u32 addr = __mt7915_reg_addr(dev, offset); - memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len); + if (addr) { + memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len); + return; + } + + spin_lock_bh(&dev->reg_lock); + memcpy_fromio(buf, dev->mt76.mmio.regs + + __mt7915_reg_remap_addr(dev, offset), len); + spin_unlock_bh(&dev->reg_lock); } static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset) { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - u32 addr = __mt7915_reg_addr(dev, offset); + u32 addr = __mt7915_reg_addr(dev, offset), val; + + if (addr) + return dev->bus_ops->rr(mdev, addr); - return dev->bus_ops->rr(mdev, addr); + spin_lock_bh(&dev->reg_lock); + val = dev->bus_ops->rr(mdev, __mt7915_reg_remap_addr(dev, offset)); + spin_unlock_bh(&dev->reg_lock); + + return val; } static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val) @@ -530,7 +552,14 @@ static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val) struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); u32 addr = __mt7915_reg_addr(dev, offset); - dev->bus_ops->wr(mdev, addr, val); + if (addr) { + dev->bus_ops->wr(mdev, addr, val); + return; + } + + spin_lock_bh(&dev->reg_lock); + dev->bus_ops->wr(mdev, __mt7915_reg_remap_addr(dev, offset), val); + spin_unlock_bh(&dev->reg_lock); } static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) @@ -538,7 +567,14 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); u32 addr = __mt7915_reg_addr(dev, offset); - return dev->bus_ops->rmw(mdev, addr, mask, val); + if (addr) + return dev->bus_ops->rmw(mdev, addr, mask, val); + + spin_lock_bh(&dev->reg_lock); + val = dev->bus_ops->rmw(mdev, __mt7915_reg_remap_addr(dev, offset), mask, val); + spin_unlock_bh(&dev->reg_lock); + + return val; } #ifdef CONFIG_NET_MEDIATEK_SOC_WED @@ -615,6 +651,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.base = devm_ioremap(dev->mt76.dev, pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); + if (!wed->wlan.base) + return -ENOMEM; + wed->wlan.phy_base = pci_resource_start(pci_dev, 0); wed->wlan.wpdma_int = pci_resource_start(pci_dev, 0) + MT_INT_WED_SOURCE_CSR; @@ -642,6 +681,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.bus_type = MTK_WED_BUS_AXI; wed->wlan.base = devm_ioremap(dev->mt76.dev, res->start, resource_size(res)); + if (!wed->wlan.base) + return -ENOMEM; + wed->wlan.phy_base = res->start; wed->wlan.wpdma_int = res->start + MT_INT_SOURCE_CSR; wed->wlan.wpdma_mask = res->start + MT_INT_MASK_CSR; @@ -672,13 +714,13 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, } wed->wlan.init_buf = mt7915_wed_init_buf; - wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; - wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; - wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf; - wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; + wed->wlan.offload_enable = mt76_wed_offload_enable; + wed->wlan.offload_disable = mt76_wed_offload_disable; + wed->wlan.init_rx_buf = mt76_wed_init_rx_buf; + wed->wlan.release_rx_buf = mt76_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; wed->wlan.reset = mt7915_mmio_wed_reset; - wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; + wed->wlan.reset_complete = mt76_wed_reset_complete; dev->mt76.rx_token_size = wed->wlan.rx_npkt; @@ -707,6 +749,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev, dev = container_of(mdev, struct mt7915_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); + spin_lock_init(&dev->reg_lock); switch (device_id) { case 0x7915: @@ -892,8 +935,10 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, .rx_check = mt7915_rx_check, .rx_poll_complete = mt7915_rx_poll_complete, .sta_add = mt7915_mac_sta_add, + .sta_event = mt7915_mac_sta_event, .sta_remove = mt7915_mac_sta_remove, .update_survey = mt7915_update_channel, + .set_channel = mt7915_set_channel, }; struct mt7915_dev *dev; struct mt76_dev *mdev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 4727d9c7b11d..2e94347c46d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -166,7 +166,7 @@ struct mt7915_vif_cap { }; struct mt7915_vif { - struct mt76_vif mt76; /* must be first */ + struct mt76_vif_link mt76; /* must be first */ struct mt7915_vif_cap cap; struct mt7915_sta sta; @@ -191,6 +191,7 @@ struct mt7915_hif { struct device *dev; void __iomem *regs; int irq; + u32 index; }; struct mt7915_phy { @@ -214,8 +215,6 @@ struct mt7915_phy { s16 coverage_class; u8 slottime; - u8 rdd_state; - u32 trb_ts; u32 rx_ampdu_ts; @@ -287,6 +286,7 @@ struct mt7915_dev { struct list_head sta_rc_list; struct list_head twt_list; + spinlock_t reg_lock; u32 hw_pattern; @@ -301,6 +301,10 @@ struct mt7915_dev { struct rchan *relay_fwlog; void *cal; + u32 cur_prek_offset; + u8 dpd_chan_num_2g; + u8 dpd_chan_num_5g; + u8 dpd_chan_num_6g; struct { u8 debug_wm; @@ -325,10 +329,10 @@ enum { __MT_WFDMA_MAX, }; -enum { - MT_RX_SEL0, - MT_RX_SEL1, - MT_RX_SEL2, /* monitor chain */ +enum rdd_idx { + MT_RDD_IDX_BAND0, /* RDD idx for band idx 0 (single-band) */ + MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */ + MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */ }; enum mt7915_rdd_cmd { @@ -348,6 +352,18 @@ enum mt7915_rdd_cmd { RDD_IRQ_OFF, }; +static inline int +mt7915_get_rdd_idx(struct mt7915_phy *phy, bool is_background) +{ + if (!phy->mt76->cap.has_5ghz) + return -1; + + if (is_background) + return MT_RDD_IDX_BACKGROUND; + + return phy->mt76->band_idx; +} + static inline struct mt7915_phy * mt7915_hw_phy(struct ieee80211_hw *hw) { @@ -419,6 +435,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx); s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band); +bool mt7915_eeprom_has_background_radar(struct mt7915_dev *dev); int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); @@ -439,7 +456,7 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable); int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable); + struct ieee80211_sta *sta, int conn_state, bool newly); int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool add); @@ -458,7 +475,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool changed); int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int mt7915_set_channel(struct mt7915_phy *phy); +int mt7915_set_channel(struct mt76_phy *mphy); int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd); int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif); int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req); @@ -467,7 +484,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_sta *sta, void *data, u32 field); int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); -int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); +int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf); int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num); int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans); @@ -555,6 +572,8 @@ void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, void mt7915_mac_set_timing(struct mt7915_phy *phy); int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev); void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7915_mac_work(struct work_struct *work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index 39132894e8ea..07b0a5766eab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -42,6 +42,7 @@ static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx) continue; get_device(hif->dev); + hif->index = idx; goto out; } hif = NULL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 89ac8e6707b8..c5ec63a25a42 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -66,6 +66,7 @@ enum offs_rev { AGG_ACR0, AGG_ACR4, AGG_MRCR, + AGG_ATCR0, AGG_ATCR1, AGG_ATCR3, LPON_UTTR0, @@ -254,6 +255,9 @@ enum offs_rev { #define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30) #define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24) +#define MT_WTBLOFF_TOP_ACR(_band) MT_WTBLOFF_TOP(_band, 0x010) +#define MT_WTBLOFF_TOP_ADM_BACKOFFTIME BIT(29) + /* ETBF: band 0(0x820ea000), band 1(0x820fa000) */ #define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) #define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) @@ -505,6 +509,9 @@ enum offs_rev { #define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) #define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) +#define MT_AGG_ATCR0(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR0)) +#define MT_AGG_ATCR_MAC_BFF_TIME_EN BIT(30) + #define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR1)) #define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR3)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 8b4809703efc..c823a7554a3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -7,7 +7,6 @@ #include <linux/pinctrl/consumer.h> #include <linux/of.h> #include <linux/of_reserved_mem.h> -#include <linux/of_gpio.h> #include <linux/iopoll.h> #include <linux/reset.h> #include <linux/of_net.h> @@ -516,7 +515,8 @@ static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) if (ret) return ret; - if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) { + if (version == 0x8a00 || version == 0x8a10 || + version == 0x8b00 || version == 0x8c10) { rg_xo_01 = 0x1d59080f; rg_xo_03 = 0x34c00fe0; } else { @@ -1303,7 +1303,7 @@ struct platform_driver mt798x_wmac_driver = { .of_match_table = mt798x_wmac_of_match, }, .probe = mt798x_wmac_probe, - .remove_new = mt798x_wmac_remove, + .remove = mt798x_wmac_remove, }; MODULE_FIRMWARE(MT7986_FIRMWARE_WA); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c index 0d76ae31b376..d534fff5c952 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -404,6 +404,7 @@ static void mt7915_tm_init(struct mt7915_phy *phy, bool en) { struct mt7915_dev *dev = phy->dev; + int state; if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; @@ -415,7 +416,8 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en) mt7915_tm_set_trx(phy, TM_MAC_TXRX, !en); mt7915_mcu_add_bss_info(phy, phy->monitor_vif, en); - mt7915_mcu_add_sta(dev, phy->monitor_vif, NULL, en); + state = en ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT; + mt7915_mcu_add_sta(dev, phy->monitor_vif, NULL, state, true); if (!en) mt7915_tm_set_tam_arb(phy, en, 0); @@ -425,7 +427,7 @@ static void mt7915_tm_update_channel(struct mt7915_phy *phy) { mutex_unlock(&phy->dev->mt76.mutex); - mt7915_set_channel(phy); + mt76_update_channel(phy->mt76); mutex_lock(&phy->dev->mt76.mutex); mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 48433c6d5e7d..14e17dc90256 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -52,6 +52,8 @@ static int mt7921_thermal_init(struct mt792x_phy *phy) name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7921_%s", wiphy_name(wiphy)); + if (!name) + return -ENOMEM; hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, mt7921_hwmon_groups); @@ -83,7 +85,7 @@ mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) } /* UNII-4 */ - if (IS_UNII_INVALID(0, 5850, 5925)) + if (IS_UNII_INVALID(0, 5845, 5925)) ch->flags |= IEEE80211_CHAN_DISABLED; } @@ -135,12 +137,24 @@ mt7921_regd_notifier(struct wiphy *wiphy, dev->mt76.region = request->dfs_region; dev->country_ie_env = request->country_ie_env; + if (request->initiator == NL80211_REGDOM_SET_BY_USER) { + if (dev->mt76.alpha2[0] == '0' && dev->mt76.alpha2[1] == '0') + wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; + else + wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; + } + if (pm->suspended) return; + dev->regd_in_progress = true; + mt792x_mutex_acquire(dev); mt7921_regd_update(dev); mt792x_mutex_release(dev); + + dev->regd_in_progress = false; + wake_up(&dev->wait); } int mt7921_mac_init(struct mt792x_dev *dev) @@ -220,6 +234,7 @@ static void mt7921_init_work(struct work_struct *work) mt76_set_stream_caps(&dev->mphy, true); mt7921_set_stream_he_caps(&dev->phy); + mt792x_config_mac_addr_list(dev); ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); @@ -261,6 +276,7 @@ int mt7921_register_device(struct mt792x_dev *dev) spin_lock_init(&dev->pm.wake.lock); mutex_init(&dev->pm.mutex); init_waitqueue_head(&dev->pm.wait); + init_waitqueue_head(&dev->wait); if (mt76_is_sdio(&dev->mt76)) init_waitqueue_head(&dev->mt76.sdio.wait); spin_lock_init(&dev->pm.txq_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 867e14f6b93a..5dd57de59f27 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -39,6 +39,7 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) }; struct ieee80211_sta *sta; struct mt792x_sta *msta; + struct mt792x_link_sta *mlink; u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; LIST_HEAD(sta_poll_list); struct rate_info *rate; @@ -60,23 +61,25 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } - msta = list_first_entry(&sta_poll_list, - struct mt792x_sta, wcid.poll_list); - list_del_init(&msta->wcid.poll_list); + mlink = list_first_entry(&sta_poll_list, + struct mt792x_link_sta, + wcid.poll_list); + msta = container_of(mlink, struct mt792x_sta, deflink); + list_del_init(&mlink->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); - idx = msta->wcid.idx; + idx = mlink->wcid.idx; addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_AC0_CTT_OFFSET); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - u32 tx_last = msta->airtime_ac[i]; - u32 rx_last = msta->airtime_ac[i + 4]; + u32 tx_last = mlink->airtime_ac[i]; + u32 rx_last = mlink->airtime_ac[i + 4]; - msta->airtime_ac[i] = mt76_rr(dev, addr); - msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); + mlink->airtime_ac[i] = mt76_rr(dev, addr); + mlink->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); - tx_time[i] = msta->airtime_ac[i] - tx_last; - rx_time[i] = msta->airtime_ac[i + 4] - rx_last; + tx_time[i] = mlink->airtime_ac[i] - tx_last; + rx_time[i] = mlink->airtime_ac[i + 4] - rx_last; if ((tx_last | rx_last) & BIT(30)) clear = true; @@ -87,10 +90,10 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) if (clear) { mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac)); } - if (!msta->wcid.sta) + if (!mlink->wcid.sta) continue; sta = container_of((void *)msta, struct ieee80211_sta, @@ -113,7 +116,7 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) * we need to make sure that flags match so polling GI * from per-sta counters directly. */ - rate = &msta->wcid.rate; + rate = &mlink->wcid.rate; addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_TXRX_CAP_RATE_OFFSET); val = mt76_rr(dev, addr); @@ -154,10 +157,10 @@ static void mt7921_mac_sta_poll(struct mt792x_dev *dev) rssi[2] = to_rssi(GENMASK(23, 16), val); rssi[3] = to_rssi(GENMASK(31, 14), val); - msta->ack_signal = + mlink->ack_signal = mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); - ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); + ewma_avg_signal_add(&mlink->avg_ack_signal, -mlink->ack_signal); } } @@ -180,6 +183,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); struct mt792x_sta *msta = NULL; + struct mt792x_link_sta *mlink; u16 seq_ctrl = 0; __le16 fc = 0; u8 mode = 0; @@ -210,12 +214,9 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) status->wcid = mt792x_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - msta = container_of(status->wcid, struct mt792x_sta, wcid); - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mlink = container_of(status->wcid, struct mt792x_link_sta, wcid); + msta = container_of(mlink, struct mt792x_sta, deflink); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); } mt792x_get_status_freq_info(status, chfreq); @@ -444,7 +445,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) { - struct mt792x_sta *msta = NULL; + struct mt792x_link_sta *mlink; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; @@ -468,16 +469,13 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) if (!wcid) goto out; - msta = container_of(wcid, struct mt792x_sta, wcid); + mlink = container_of(wcid, struct mt792x_link_sta, wcid); mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); if (!wcid->sta) goto out; - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); out: rcu_read_unlock(); @@ -513,7 +511,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) * 1'b0: msdu_id with the same 'wcid pair' as above. */ if (info & MT_TX_FREE_PAIR) { - struct mt792x_sta *msta; + struct mt792x_link_sta *mlink; u16 idx; count++; @@ -523,12 +521,8 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) if (!sta) continue; - msta = container_of(wcid, struct mt792x_sta, wcid); - spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &mdev->sta_poll_list); - spin_unlock_bh(&mdev->sta_poll_lock); + mlink = container_of(wcid, struct mt792x_link_sta, wcid); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); continue; } @@ -641,11 +635,13 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, if (vif->type == NL80211_IFTYPE_STATION) ieee80211_disconnect(vif, true); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); + mt76_connac_mcu_uni_add_dev(&dev->mphy, &vif->bss_conf, + &mvif->bss_conf.mt76, + &mvif->sta.deflink.wcid, true); mt7921_mcu_set_tx(dev, vif); if (vif->type == NL80211_IFTYPE_AP) { - mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid, + mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid, true, NULL); mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_NONE); @@ -663,6 +659,7 @@ void mt7921_mac_reset_work(struct work_struct *work) int i, ret; dev_dbg(dev->mt76.dev, "chip reset\n"); + set_bit(MT76_RESET, &dev->mphy.state); dev->hw_full_reset = true; ieee80211_stop_queues(hw); @@ -691,6 +688,7 @@ void mt7921_mac_reset_work(struct work_struct *work) } dev->hw_full_reset = false; + clear_bit(MT76_RESET, &dev->mphy.state); pm->suspended = false; ieee80211_wake_queues(hw); ieee80211_iterate_active_interfaces(hw, @@ -784,9 +782,9 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (sta) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - if (time_after(jiffies, msta->last_txs + HZ / 4)) { + if (time_after(jiffies, msta->deflink.last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; + msta->deflink.last_txs = jiffies; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 0d5adc5ddae3..1fffa43379b2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -83,6 +83,11 @@ mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, he_cap_elem->phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; + + if (is_mt7922(phy->mt76->dev)) { + he_cap_elem->phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + } break; case NL80211_IFTYPE_STATION: he_cap_elem->mac_cap_info[1] |= @@ -147,7 +152,7 @@ mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, @@ -242,6 +247,20 @@ int __mt7921_start(struct mt792x_phy *phy) ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, MT792x_WATCHDOG_TIME); + if (mt76_is_mmio(mphy->dev)) { + err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_LED_CTRL_ENABLE); + if (err) + return err; + + err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_ON_LED); + if (err) + return err; + } + + if (phy->chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN) { + mt7921_mcu_wf_rf_pin_ctrl(phy, WF_RF_PIN_INIT); + wiphy_rfkill_start_polling(mphy->hw->wiphy); + } return 0; } @@ -259,6 +278,22 @@ static int mt7921_start(struct ieee80211_hw *hw) return err; } +static void mt7921_stop(struct ieee80211_hw *hw, bool suspend) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err = 0; + + if (mt76_is_mmio(&dev->mt76)) { + mt792x_mutex_acquire(dev); + err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED); + mt792x_mutex_release(dev); + if (err) + return; + } + + mt792x_stop(hw, false); +} + static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -270,46 +305,51 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mt792x_mutex_acquire(dev); - mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { + mvif->bss_conf.mt76.idx = __ffs64(~dev->mt76.vif_mask); + if (mvif->bss_conf.mt76.idx >= MT792x_MAX_INTERFACES) { ret = -ENOSPC; goto out; } - mvif->mt76.omac_idx = mvif->mt76.idx; + mvif->bss_conf.mt76.omac_idx = mvif->bss_conf.mt76.idx; mvif->phy = phy; - mvif->mt76.band_idx = 0; - mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; + mvif->bss_conf.vif = mvif; + mvif->bss_conf.mt76.band_idx = 0; + mvif->bss_conf.mt76.wmm_idx = mvif->bss_conf.mt76.idx % MT76_CONNAC_MAX_WMM_SETS; - ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, - true); + ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, &vif->bss_conf, + &mvif->bss_conf.mt76, + &mvif->sta.deflink.wcid, true); if (ret) goto out; - dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); - phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->bss_conf.mt76.idx); + phy->omac_mask |= BIT_ULL(mvif->bss_conf.mt76.omac_idx); - idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; + idx = MT792x_WTBL_RESERVED - mvif->bss_conf.mt76.idx; - INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); - mvif->sta.wcid.idx = idx; - mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; - mvif->sta.wcid.hw_key_idx = -1; - mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_wcid_init(&mvif->sta.wcid); + INIT_LIST_HEAD(&mvif->sta.deflink.wcid.poll_list); + mvif->sta.deflink.wcid.idx = idx; + mvif->sta.deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt76_wcid_init(&mvif->sta.deflink.wcid, mvif->bss_conf.mt76.band_idx); mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - ewma_rssi_init(&mvif->rssi); + ewma_rssi_init(&mvif->bss_conf.rssi); - rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.deflink.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; mtxq->wcid = idx; } vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN) + vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI; + + INIT_WORK(&mvif->csa_work, mt7921_csa_work); + timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0); out: mt792x_mutex_release(dev); @@ -325,6 +365,19 @@ static void mt7921_roc_iter(void *priv, u8 *mac, mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id); } +void mt7921_roc_abort_sync(struct mt792x_dev *dev) +{ + struct mt792x_phy *phy = &dev->phy; + + timer_delete_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); + if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + ieee80211_iterate_interfaces(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_roc_iter, (void *)phy); +} +EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync); + void mt7921_roc_work(struct work_struct *work) { struct mt792x_phy *phy; @@ -347,7 +400,7 @@ static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) { int err = 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt792x_mutex_acquire(phy->dev); @@ -414,37 +467,30 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, return mt7921_abort_roc(phy, mvif); } -static int mt7921_set_channel(struct mt792x_phy *phy) +int mt7921_set_channel(struct mt76_phy *mphy) { + struct mt792x_phy *phy = mphy->priv; struct mt792x_dev *dev = phy->dev; int ret; - cancel_delayed_work_sync(&phy->mt76->mac_work); - - mt792x_mutex_acquire(dev); - set_bit(MT76_RESET, &phy->mt76->state); - - mt76_set_channel(phy->mt76); - + mt76_connac_pm_wake(mphy, &dev->pm); ret = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH)); if (ret) goto out; mt792x_mac_set_timeing(phy); - mt792x_mac_reset_counters(phy); phy->noise = 0; out: - clear_bit(MT76_RESET, &phy->mt76->state); - mt792x_mutex_release(dev); + mt76_connac_power_save_sched(mphy, &dev->pm); - mt76_worker_schedule(&dev->mt76.tx_worker); - ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, MT792x_WATCHDOG_TIME); return ret; } +EXPORT_SYMBOL_GPL(mt7921_set_channel); static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -454,7 +500,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; - struct mt76_wcid *wcid = &msta->wcid; + struct mt76_wcid *wcid = &msta->deflink.wcid; u8 *wcid_keyidx = &wcid->hw_key_idx; int idx = key->keyidx, err = 0; @@ -497,22 +543,28 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } else { if (idx == *wcid_keyidx) *wcid_keyidx = -1; - goto out; + + /* For security issue we don't trigger the key deletion when + * reassociating. But we should trigger the deletion process + * to avoid using incorrect cipher after disconnection, + */ + if (vif->type != NL80211_IFTYPE_STATION || vif->cfg.assoc) + goto out; } mt76_wcid_key_setup(&dev->mt76, wcid, key); - err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, + err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->deflink.bip, key, MCU_UNI_CMD(STA_REC_UPDATE), - &msta->wcid, cmd); + &msta->deflink.wcid, cmd); if (err) goto out; if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || key->cipher == WLAN_CIPHER_SUITE_WEP40) err = mt76_connac_mcu_add_key(&dev->mt76, vif, - &mvif->wep_sta->bip, + &mvif->wep_sta->deflink.bip, key, MCU_UNI_CMD(STA_REC_UPDATE), - &mvif->wep_sta->wcid, cmd); + &mvif->wep_sta->deflink.wcid, cmd); out: mt792x_mutex_release(dev); @@ -579,11 +631,9 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - ret = mt7921_set_channel(phy); + ret = mt76_update_channel(phy->mt76); if (ret) return ret; - ieee80211_wake_queues(hw); } mt792x_mutex_acquire(dev); @@ -666,6 +716,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_PS) mt7921_mcu_uni_bss_ps(dev, vif); + if (changed & BSS_CHANGED_CQM) + mt7921_mcu_set_rssimonitor(dev, vif); + if (changed & BSS_CHANGED_ASSOC) { mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_ASSOC); @@ -675,7 +728,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ARP_FILTER) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - mt76_connac_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, + mt76_connac_mcu_update_arp_filter(&dev->mt76, &mvif->bss_conf.mt76, info); } @@ -756,13 +809,14 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->wcid.poll_list); + INIT_LIST_HEAD(&msta->deflink.wcid.poll_list); msta->vif = mvif; - msta->wcid.sta = 1; - msta->wcid.idx = idx; - msta->wcid.phy_idx = mvif->mt76.band_idx; - msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; - msta->last_txs = jiffies; + msta->deflink.wcid.sta = 1; + msta->deflink.wcid.idx = idx; + msta->deflink.wcid.phy_idx = mvif->bss_conf.mt76.band_idx; + msta->deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta->deflink.last_txs = jiffies; + msta->deflink.sta = msta; ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); if (ret) @@ -787,30 +841,35 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt7921_mac_sta_add); -void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + if (ev != MT76_STA_EVENT_ASSOC) + return 0; + mt792x_mutex_acquire(dev); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, - true, mvif->mt76.ctx); + mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.deflink.wcid, + true, mvif->bss_conf.mt76.ctx); - ewma_avg_signal_init(&msta->avg_ack_signal); + ewma_avg_signal_init(&msta->deflink.avg_ack_signal); - mt7921_mac_wtbl_update(dev, msta->wcid.idx, + mt7921_mac_wtbl_update(dev, msta->deflink.wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + memset(msta->deflink.airtime_ac, 0, sizeof(msta->deflink.airtime_ac)); mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); mt792x_mutex_release(dev); + + return 0; } -EXPORT_SYMBOL_GPL(mt7921_mac_sta_assoc); +EXPORT_SYMBOL_GPL(mt7921_mac_sta_event); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -818,27 +877,28 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); + mt7921_roc_abort_sync(dev); + mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->deflink.wcid); mt76_connac_pm_wake(&dev->mphy, &dev->pm); mt7921_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE); - mt7921_mac_wtbl_update(dev, msta->wcid.idx, + mt7921_mac_wtbl_update(dev, msta->deflink.wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); if (vif->type == NL80211_IFTYPE_STATION) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mvif->wep_sta = NULL; - ewma_rssi_init(&mvif->rssi); + ewma_rssi_init(&mvif->bss_conf.rssi); if (!sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, - &mvif->sta.wcid, false, - mvif->mt76.ctx); + &mvif->sta.deflink.wcid, false, + mvif->bss_conf.mt76.ctx); } spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); + if (!list_empty(&msta->deflink.wcid.poll_list)) + list_del_init(&msta->deflink.wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); mt7921_regd_set_6ghz_power_type(vif, false); @@ -880,12 +940,12 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_acquire(dev); switch (action) { case IEEE80211_AMPDU_RX_START: - mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, + mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn, params->buf_size); mt7921_mcu_uni_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: - mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid); mt7921_mcu_uni_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: @@ -896,16 +956,16 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); + clear_bit(tid, &msta->deflink.wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->wcid.ampdu_state); + set_bit(tid, &msta->deflink.wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); + clear_bit(tid, &msta->deflink.wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -1123,11 +1183,11 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, mt792x_mutex_acquire(dev); if (enabled) - set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->deflink.wcid.flags); else - clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->deflink.wcid.flags); - mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, + mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->deflink.wcid, MCU_UNI_CMD(STA_REC_UPDATE)); mt792x_mutex_release(dev); @@ -1139,7 +1199,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct inet6_dev *idev) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mvif->phy->dev; + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct inet6_ifaddr *ifa; struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; struct sk_buff *skb; @@ -1153,7 +1213,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct mt76_connac_arpns_tlv arpns; } req_hdr = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .arpns = { .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), @@ -1251,8 +1311,8 @@ 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->mt76.ctx); + err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.deflink.wcid, + true, mvif->bss_conf.mt76.ctx); if (err) goto out; @@ -1283,8 +1343,8 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (err) goto out; - mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false, - mvif->mt76.ctx); + mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.deflink.wcid, false, + mvif->bss_conf.mt76.ctx); out: mt792x_mutex_release(dev); @@ -1294,6 +1354,9 @@ static int mt7921_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + dev->new_ctx = ctx; return 0; } @@ -1301,21 +1364,10 @@ static void mt7921_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { -} - -static void mt7921_ctx_iter(void *priv, u8 *mac, - struct ieee80211_vif *vif) -{ - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct ieee80211_chanctx_conf *ctx = priv; - - if (ctx != mvif->mt76.ctx) - return; + struct mt792x_dev *dev = mt792x_hw_dev(hw); - if (vif->type == NL80211_IFTYPE_MONITOR) - mt7921_mcu_config_sniffer(mvif, ctx); - else - mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx); + if (dev->new_ctx == ctx) + dev->new_ctx = NULL; } static void @@ -1323,12 +1375,22 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct ieee80211_vif *vif; + struct mt792x_vif *mvif; + + if (!mctx->bss_conf) + return; + + mvif = container_of(mctx->bss_conf, struct mt792x_vif, bss_conf); + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); mt792x_mutex_acquire(phy->dev); - ieee80211_iterate_active_interfaces(phy->mt76->hw, - IEEE80211_IFACE_ITER_ACTIVE, - mt7921_ctx_iter, ctx); + if (vif->type == NL80211_IFTYPE_MONITOR) + mt7921_mcu_config_sniffer(mvif, ctx); + else + mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx); mt792x_mutex_release(phy->dev); } @@ -1342,7 +1404,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->mt76.ctx->def.chan, duration, + mt7921_set_roc(mvif->phy, mvif, mvif->bss_conf.mt76.ctx->def.chan, duration, MT7921_ROC_REQ_JOIN); mt792x_mutex_release(dev); } @@ -1356,10 +1418,105 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, mt7921_abort_roc(mvif->phy, mvif); } +static int mt7921_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, + enum ieee80211_chanctx_switch_mode mode) +{ + return mt792x_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf, + vifs->new_ctx); +} + +void mt7921_csa_work(struct work_struct *work) +{ + struct mt792x_vif *mvif; + struct mt792x_dev *dev; + struct ieee80211_vif *vif; + int ret; + + mvif = (struct mt792x_vif *)container_of(work, struct mt792x_vif, + csa_work); + dev = mvif->phy->dev; + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); + + mt792x_mutex_acquire(dev); + ret = mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, + dev->new_ctx); + mt792x_mutex_release(dev); + + ieee80211_chswitch_done(vif, !ret, 0); +} + +static int mt7921_pre_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw) +{ + if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) + return -EOPNOTSUPP; + + /* Avoid beacon loss due to the CAC(Channel Availability Check) time + * of the AP. + */ + if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef, + IEEE80211_CHAN_RADAR)) + return -EOPNOTSUPP; + + return 0; +} + +static void mt7921_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + u16 beacon_interval = vif->bss_conf.beacon_int; + + mvif->csa_timer.expires = TU_TO_EXP_TIME(beacon_interval * chsw->count); + add_timer(&mvif->csa_timer); +} + +static void mt7921_abort_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + timer_delete_sync(&mvif->csa_timer); + cancel_work_sync(&mvif->csa_work); +} + +static void mt7921_channel_switch_rx_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + u16 beacon_interval = vif->bss_conf.beacon_int; + + if (cfg80211_chandef_identical(&chsw->chandef, + &dev->new_ctx->def) && + chsw->count) { + mod_timer(&mvif->csa_timer, + TU_TO_EXP_TIME(beacon_interval * chsw->count)); + } +} + +static void mt7921_rfkill_poll(struct ieee80211_hw *hw) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int ret = 0; + + mt792x_mutex_acquire(phy->dev); + ret = mt7921_mcu_wf_rf_pin_ctrl(phy, WF_RF_PIN_POLL); + mt792x_mutex_release(phy->dev); + + wiphy_rfkill_set_hw_state(hw->wiphy, ret ? false : true); +} + const struct ieee80211_ops mt7921_ops = { .tx = mt792x_tx, .start = mt7921_start, - .stop = mt792x_stop, + .stop = mt7921_stop, .add_interface = mt7921_add_interface, .remove_interface = mt792x_remove_interface, .config = mt7921_config, @@ -1406,6 +1563,7 @@ const struct ieee80211_ops mt7921_ops = { #endif /* CONFIG_PM */ .flush = mt792x_flush, .set_sar_specs = mt7921_set_sar_specs, + .rfkill_poll = mt7921_rfkill_poll, .remain_on_channel = mt7921_remain_on_channel, .cancel_remain_on_channel = mt7921_cancel_remain_on_channel, .add_chanctx = mt7921_add_chanctx, @@ -1415,6 +1573,11 @@ const struct ieee80211_ops mt7921_ops = { .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, .mgd_prepare_tx = mt7921_mgd_prepare_tx, .mgd_complete_tx = mt7921_mgd_complete_tx, + .switch_vif_chanctx = mt7921_switch_vif_chanctx, + .pre_channel_switch = mt7921_pre_channel_switch, + .channel_switch = mt7921_channel_switch, + .abort_channel_switch = mt7921_abort_channel_switch, + .channel_switch_rx_beacon = mt7921_channel_switch_rx_beacon, }; EXPORT_SYMBOL_GPL(mt7921_ops); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index f5582477c7e4..86bd33b916a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -61,6 +61,12 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, skb_pull(skb, sizeof(*rxd)); event = (struct mt76_connac_mcu_reg_event *)skb->data; ret = (int)le32_to_cpu(event->val); + } else if (cmd == MCU_EXT_CMD(WF_RF_PIN_CTRL)) { + struct mt7921_wf_rf_pin_ctrl_event *event; + + skb_pull(skb, sizeof(*rxd)); + event = (struct mt7921_wf_rf_pin_ctrl_event *)skb->data; + ret = (int)event->result; } else { skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); } @@ -105,7 +111,7 @@ mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev, struct mt76_connac_arpns_tlv arpns; } req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .arpns = { .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), @@ -174,7 +180,7 @@ static void mt7921_mcu_connection_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_connac_beacon_loss_event *event = priv; if (mvif->idx != event->bss_idx) @@ -254,6 +260,42 @@ mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb) } static void +mt7921_mcu_rssi_monitor_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt76_connac_rssi_notify_event *event = priv; + enum nl80211_cqm_rssi_threshold_event nl_event; + s32 rssi = le32_to_cpu(event->rssi[mvif->bss_conf.mt76.idx]); + + if (!rssi) + return; + + if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) + return; + + if (rssi > vif->bss_conf.cqm_rssi_thold) + nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; + else + nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; + + ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL); +} + +static void +mt7921_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct mt76_connac_rssi_notify_event *event; + + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); + event = (struct mt76_connac_rssi_notify_event *)skb->data; + + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_mcu_rssi_monitor_iter, event); +} + +static void mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -281,6 +323,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) case MCU_EVENT_TX_DONE: mt7921_mcu_tx_done_event(dev, skb); break; + case MCU_EVENT_RSSI_NOTIFY: + mt7921_mcu_rssi_monitor_event(dev, skb); + break; default: break; } @@ -327,6 +372,7 @@ void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb) if (rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT || rxd->eid == MCU_EVENT_BSS_BEACON_LOSS || rxd->eid == MCU_EVENT_SCHED_SCAN_DONE || + rxd->eid == MCU_EVENT_RSSI_NOTIFY || rxd->eid == MCU_EVENT_SCAN_DONE || rxd->eid == MCU_EVENT_TX_DONE || rxd->eid == MCU_EVENT_DBG_MSG || @@ -346,9 +392,9 @@ int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev, struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; if (enable && !params->amsdu) - msta->wcid.amsdu = false; + msta->deflink.wcid.amsdu = false; - return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, + return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params, MCU_UNI_CMD(STA_REC_UPDATE), enable, true); } @@ -359,7 +405,7 @@ int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, { struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; - return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, + return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params, MCU_UNI_CMD(STA_REC_UPDATE), enable, false); } @@ -467,7 +513,10 @@ static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev, 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->pse_mcu_quota_max = le32_to_cpu(tx_res->pse_mcu_quota); + /* The mcu quota usage of this function itself must be taken into consideration */ + sdio->sched.pse_mcu_quota = + sdio->sched.pse_mcu_quota ? sdio->pse_mcu_quota_max : sdio->pse_mcu_quota_max - 1; 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; @@ -606,6 +655,20 @@ int mt7921_run_firmware(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_run_firmware); +int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value) +{ + struct { + u8 ctrlid; + u8 rsv[3]; + } __packed req = { + .ctrlid = value, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ID_RADIO_ON_OFF_CTRL), + &req, sizeof(req), false); +} +EXPORT_SYMBOL_GPL(mt7921_mcu_radio_led_ctrl); + int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; @@ -624,9 +687,9 @@ int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) u8 wmm_idx; u8 pad; } __packed req = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, .qos = vif->bss_conf.qos, - .wmm_idx = mvif->mt76.wmm_idx, + .wmm_idx = mvif->bss_conf.mt76.wmm_idx, }; struct mu_edca { u8 cw_min; @@ -647,15 +710,15 @@ int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) struct mu_edca edca[IEEE80211_NUM_ACS]; u8 pad3[32]; } __packed req_mu = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, .qos = vif->bss_conf.qos, - .wmm_idx = mvif->mt76.wmm_idx, + .wmm_idx = mvif->bss_conf.mt76.wmm_idx, }; static const int to_aci[] = { 1, 0, 2, 3 }; int ac, ret; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac]; + struct ieee80211_tx_queue_params *q = &mvif->bss_conf.queue_params[ac]; struct edca *e = &req.edca[to_aci[ac]]; e->aifs = cpu_to_le16(q->aifs); @@ -684,10 +747,10 @@ int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) struct ieee80211_he_mu_edca_param_ac_rec *q; struct mu_edca *e; - if (!mvif->queue_params[ac].mu_edca) + if (!mvif->bss_conf.queue_params[ac].mu_edca) break; - q = &mvif->queue_params[ac].mu_edca_param_rec; + q = &mvif->bss_conf.queue_params[ac].mu_edca_param_rec; e = &(req_mu.edca[to_aci[ac]]); e->cw_min = q->ecw_min_max & 0xf; @@ -736,7 +799,7 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, .tokenid = token_id, .reqtype = type, .maxinterval = cpu_to_le32(duration), - .bss_idx = vif->mt76.idx, + .bss_idx = vif->bss_conf.mt76.idx, .control_channel = chan->hw_value, .bw = CMD_CBW_20MHZ, .bw_from_ap = CMD_CBW_20MHZ, @@ -788,7 +851,7 @@ int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, .tag = cpu_to_le16(UNI_ROC_ABORT), .len = cpu_to_le16(sizeof(struct roc_abort_tlv)), .tokenid = token_id, - .bss_idx = vif->mt76.idx, + .bss_idx = vif->bss_conf.mt76.idx, .dbdcband = 0xff, /* auto*/ }, }; @@ -836,7 +899,7 @@ int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd) if (cmd == MCU_EXT_CMD(SET_RX_PATH) || dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + else if (phy->mt76->offchannel) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(dev->mt76.hw->wiphy, chandef, NL80211_IFTYPE_AP)) @@ -893,7 +956,7 @@ int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) } __packed ps; } __packed ps_req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .ps = { .tag = cpu_to_le16(UNI_BSS_INFO_PS), @@ -928,7 +991,7 @@ mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, } __packed bcnft; } __packed bcnft_req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .bcnft = { .tag = cpu_to_le16(UNI_BSS_INFO_BCNFT), @@ -961,7 +1024,7 @@ mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, u8 bmc_triggered_ac; u8 pad; } req = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, .aid = cpu_to_le16(vif->cfg.aid), .dtim_period = vif->bss_conf.dtim_period, .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), @@ -970,7 +1033,7 @@ mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, u8 bss_idx; u8 pad[3]; } req_hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }; int err; @@ -988,7 +1051,7 @@ int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, enum mt76_sta_info_state state) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - int rssi = -ewma_rssi_read(&mvif->rssi); + int rssi = -ewma_rssi_read(&mvif->bss_conf.rssi); struct mt76_sta_cmd_info info = { .sta = sta, .vif = vif, @@ -1001,7 +1064,7 @@ int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, struct mt792x_sta *msta; msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL; - info.wcid = msta ? &msta->wcid : &mvif->sta.wcid; + info.wcid = msta ? &msta->deflink.wcid : &mvif->sta.deflink.wcid; info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true; return mt76_connac_mcu_sta_cmd(&dev->mphy, &info); @@ -1068,7 +1131,7 @@ int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr) int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { struct { u8 band_idx; @@ -1100,12 +1163,12 @@ int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, { struct cfg80211_chan_def *chandef = &ctx->def; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; - const u8 ch_band[] = { + static const u8 ch_band[] = { [NL80211_BAND_2GHZ] = 1, [NL80211_BAND_5GHZ] = 2, [NL80211_BAND_6GHZ] = 3, }; - const u8 ch_width[] = { + static const u8 ch_width[] = { [NL80211_CHAN_WIDTH_20_NOHT] = 0, [NL80211_CHAN_WIDTH_20] = 0, [NL80211_CHAN_WIDTH_40] = 0, @@ -1136,7 +1199,7 @@ int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, } __packed tlv; } __packed req = { .hdr = { - .band_idx = vif->mt76.band_idx, + .band_idx = vif->bss_conf.mt76.band_idx, }, .tlv = { .tag = cpu_to_le16(1), @@ -1197,7 +1260,7 @@ mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, } __packed beacon_tlv; } req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .beacon_tlv = { .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), @@ -1272,7 +1335,7 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, .mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2), }; int ret, valid_cnt = 0; - u16 buf_len = 0; + u32 buf_len = 0; u8 *pos; if (!clc) @@ -1283,7 +1346,7 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, if (mt76_find_power_limits_node(&dev->mt76)) req.cap |= CLC_CAP_DTS_EN; - buf_len = le16_to_cpu(clc->len) - sizeof(*clc); + buf_len = le32_to_cpu(clc->len) - sizeof(*clc); pos = clc->data; while (buf_len > 16) { struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos; @@ -1370,6 +1433,21 @@ int mt7921_mcu_get_temperature(struct mt792x_phy *phy) sizeof(req), true); } +int mt7921_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy, u8 action) +{ + struct mt792x_dev *dev = phy->dev; + struct { + u8 action; + u8 value; + } req = { + .action = action, + .value = 0, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(WF_RF_PIN_CTRL), &req, + sizeof(req), action ? true : false); +} + int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map) { @@ -1391,3 +1469,24 @@ int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER), &data, sizeof(data), false); } + +int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct { + u8 enable; + s8 cqm_rssi_high; + s8 cqm_rssi_low; + u8 bss_idx; + u16 duration; + u8 rsv2[2]; + } __packed data = { + .enable = vif->cfg.assoc, + .cqm_rssi_high = vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst, + .cqm_rssi_low = vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst, + .bss_idx = mvif->bss_conf.mt76.idx, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(RSSI_MONITOR), + &data, sizeof(data), false); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index f9a259ee6b82..2834c6c53e58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -74,6 +74,11 @@ struct mt7921_txpwr_event { struct mt7921_txpwr txpwr; } __packed; +struct mt7921_wf_rf_pin_ctrl_event { + u8 result; + u8 value; +} __packed; + enum { TM_SWITCH_MODE, TM_SET_AT_CMD, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 1cb21133992b..c88793fcec64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -27,6 +27,13 @@ #define MCU_UNI_EVENT_ROC 0x27 #define MCU_UNI_EVENT_CLC 0x80 +#define EXT_CMD_RADIO_LED_CTRL_ENABLE 0x1 +#define EXT_CMD_RADIO_ON_LED 0x2 +#define EXT_CMD_RADIO_OFF_LED 0x3 + +#define WF_RF_PIN_INIT 0x0 +#define WF_RF_PIN_POLL 0x1 + enum { UNI_ROC_ACQUIRE, UNI_ROC_ABORT, @@ -182,6 +189,7 @@ int __mt7921_start(struct mt792x_phy *phy); int mt7921_register_device(struct mt792x_dev *dev); void mt7921_unregister_device(struct mt792x_dev *dev); int mt7921_run_firmware(struct mt792x_dev *dev); +int mt7921_set_channel(struct mt76_phy *mphy); int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, @@ -196,6 +204,8 @@ int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl); void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb); int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map); +int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value); +int mt7921_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy, u8 action); static inline u32 mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr) @@ -239,8 +249,8 @@ int mt7921_mac_init(struct mt792x_dev *dev); bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_reset_work(struct work_struct *work); @@ -267,6 +277,7 @@ int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, bool enable); void mt7921_scan_work(struct work_struct *work); void mt7921_roc_work(struct work_struct *work); +void mt7921_csa_work(struct work_struct *work); int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); void mt7921_coredump_work(struct work_struct *work); int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr); @@ -322,4 +333,6 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, enum mt7921_roc_req type, u8 token_id); int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id); +void mt7921_roc_abort_sync(struct mt792x_dev *dev); +int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index dde26f327478..a0c9df3c2cc7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -6,6 +6,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/of.h> #include "mt7921.h" #include "../mt76_connac2_mac.h" @@ -23,6 +24,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, 0x0616), .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920), + .driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM }, { }, }; @@ -39,6 +42,10 @@ static void mt7921e_unregister_device(struct mt792x_dev *dev) { int i; struct mt76_connac_pm *pm = &dev->pm; + struct ieee80211_hw *hw = mt76_hw(dev); + + if (dev->phy.chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN) + wiphy_rfkill_stop_polling(hw->wiphy); cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); @@ -216,7 +223,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev) if (ret < 0) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt792x_poll_tx); napi_enable(&dev->mt76.tx_napi); @@ -241,9 +248,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .rx_skb = mt7921_queue_rx_skb, .rx_poll_complete = mt792x_rx_poll_complete, .sta_add = mt7921_mac_sta_add, - .sta_assoc = mt7921_mac_sta_assoc, + .sta_event = mt7921_mac_sta_event, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt792x_update_channel, + .set_channel = mt7921_set_channel, }; static const struct mt792x_hif_ops mt7921_pcie_ops = { .init_reset = mt7921e_init_reset, @@ -268,9 +276,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev, struct mt76_bus_ops *bus_ops; struct mt792x_dev *dev; struct mt76_dev *mdev; + u16 cmd, chipid; u8 features; int ret; - u16 cmd; ret = pcim_enable_device(pdev); if (ret) @@ -336,6 +344,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev, bus_ops->rmw = mt7921_rmw; dev->mt76.bus = bus_ops; + if (!mt7921_disable_aspm && mt76_pci_aspm_supported(pdev)) + dev->aspm_supported = true; + ret = mt792xe_mcu_fw_pmctrl(dev); if (ret) goto err_free_dev; @@ -344,7 +355,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (ret) goto err_free_dev; - mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) | + chipid = mt7921_l1_rr(dev, MT_HW_CHIPID); + if (chipid == 0x7961 && (mt7921_l1_rr(dev, MT_HW_BOUND) & BIT(7))) + chipid = 0x7920; + mdev->rev = (chipid << 16) | (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); @@ -369,6 +383,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (ret) goto err_free_irq; + if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source")) + device_init_wakeup(dev->mt76.dev, true); + return 0; err_free_irq: @@ -386,7 +403,11 @@ static void mt7921_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); + if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source")) + device_init_wakeup(dev->mt76.dev, false); + mt7921e_unregister_device(dev); + set_bit(MT76_REMOVED, &mdev->phy.state); devm_free_irq(&pdev->dev, pdev->irq, dev); mt76_free_device(&dev->mt76); pci_free_irq_vectors(pdev); @@ -405,11 +426,20 @@ static int mt7921_pci_suspend(struct device *device) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); + mt7921_roc_abort_sync(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; - err = mt76_connac_mcu_set_hif_suspend(mdev, true); + wait_event_timeout(dev->wait, + !dev->regd_in_progress, 5 * HZ); + + err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED); + if (err < 0) + goto restore_suspend; + + err = mt76_connac_mcu_set_hif_suspend(mdev, true, true); if (err) goto restore_suspend; @@ -455,7 +485,7 @@ restore_napi: if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(&dev->mt76, false); - mt76_connac_mcu_set_hif_suspend(mdev, false); + mt76_connac_mcu_set_hif_suspend(mdev, false, true); restore_suspend: pm->suspended = false; @@ -493,12 +523,15 @@ static int mt7921_pci_resume(struct device *device) 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); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_schedule(&mdev->napi[i]); + } napi_schedule(&mdev->tx_napi); local_bh_enable(); @@ -506,10 +539,12 @@ static int mt7921_pci_resume(struct device *device) if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(&dev->mt76, false); - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + err = mt76_connac_mcu_set_hif_suspend(mdev, false, true); + if (err < 0) + goto failed; mt7921_regd_update(dev); - + err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED); failed: pm->suspended = false; @@ -538,6 +573,8 @@ static struct pci_driver mt7921_pci_driver = { module_pci_driver(mt7921_pci_driver); MODULE_DEVICE_TABLE(pci, mt7921_pci_device_table); +MODULE_FIRMWARE(MT7920_FIRMWARE_WM); +MODULE_FIRMWARE(MT7920_ROM_PATCH); MODULE_FIRMWARE(MT7921_FIRMWARE_WM); MODULE_FIRMWARE(MT7921_ROM_PATCH); MODULE_FIRMWARE(MT7922_FIRMWARE_WM); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index c866144ff061..881812ba03ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -34,9 +34,9 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (sta) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - if (time_after(jiffies, msta->last_txs + HZ / 4)) { + if (time_after(jiffies, msta->deflink.last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; + msta->deflink.last_txs = jiffies; } } @@ -64,7 +64,6 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) 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); @@ -82,9 +81,12 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) mt792x_wpdma_reset(dev, true); - local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { napi_enable(&dev->mt76.napi[i]); + } + + local_bh_disable(); + mt76_for_each_q_rx(&dev->mt76, i) { napi_schedule(&dev->mt76.napi[i]); } local_bh_enable(); @@ -115,10 +117,9 @@ int mt7921e_mac_reset(struct mt792x_dev *dev) err = __mt7921_start(&dev->phy); out: - clear_bit(MT76_RESET, &dev->mphy.state); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); + local_bh_disable(); napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index a9ce1e746b95..45b9f35aab17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -100,9 +100,10 @@ static int mt7921s_probe(struct sdio_func *func, .rx_skb = mt7921_queue_rx_skb, .rx_check = mt7921_rx_check, .sta_add = mt7921_mac_sta_add, - .sta_assoc = mt7921_mac_sta_assoc, + .sta_event = mt7921_mac_sta_event, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt792x_update_channel, + .set_channel = mt7921_set_channel, }; static const struct mt76_bus_ops mt7921s_ops = { .rr = mt76s_rr, @@ -216,6 +217,8 @@ static int mt7921s_suspend(struct device *__dev) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); + mt7921_roc_abort_sync(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; @@ -237,7 +240,7 @@ static int mt7921s_suspend(struct device *__dev) mt76s_txqs_empty(&dev->mt76), 5 * HZ); /* It is supposed that SDIO bus is idle at the point */ - err = mt76_connac_mcu_set_hif_suspend(mdev, true); + err = mt76_connac_mcu_set_hif_suspend(mdev, true, true); if (err) goto restore_worker; @@ -255,7 +258,7 @@ static int mt7921s_suspend(struct device *__dev) restore_txrx_worker: mt76_worker_enable(&mdev->sdio.net_worker); mt76_worker_enable(&mdev->sdio.txrx_worker); - mt76_connac_mcu_set_hif_suspend(mdev, false); + mt76_connac_mcu_set_hif_suspend(mdev, false, true); restore_worker: mt76_worker_enable(&mdev->tx_worker); @@ -299,7 +302,7 @@ static int mt7921s_resume(struct device *__dev) if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(mdev, false); - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + err = mt76_connac_mcu_set_hif_suspend(mdev, false, true); failed: pm->suspended = false; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index 389eb0903807..1f77cf71ca70 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -98,7 +98,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev) mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); 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); @@ -135,7 +134,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev) err = __mt7921_start(&dev->phy); out: - clear_bit(MT76_RESET, &dev->mphy.state); mt76_worker_enable(&dev->mt76.tx_worker); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 8b7c03c47598..fe9751851ff7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -21,6 +21,9 @@ static const struct usb_device_id mt7921u_device_table[] = { /* Netgear, Inc. [A8000,AXE3000] */ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM }, + /* TP-Link TXE50UH */ + { USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0107, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM }, { }, }; @@ -151,9 +154,10 @@ static int mt7921u_probe(struct usb_interface *usb_intf, .rx_skb = mt7921_queue_rx_skb, .rx_check = mt7921_rx_check, .sta_add = mt7921_mac_sta_add, - .sta_assoc = mt7921_mac_sta_assoc, + .sta_event = mt7921_mac_sta_event, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt792x_update_channel, + .set_channel = mt7921_set_channel, }; static const struct mt792x_hif_ops hif_ops = { .mcu_init = mt7921u_mcu_init, @@ -256,7 +260,7 @@ static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) pm->suspended = true; flush_work(&dev->reset_work); - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, true); if (err) goto failed; @@ -306,7 +310,7 @@ static int mt7921u_resume(struct usb_interface *intf) if (err < 0) goto failed; - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false, true); failed: pm->suspended = false; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile index d321e4ed732f..ade5e647c941 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_MT7925E) += mt7925e.o obj-$(CONFIG_MT7925U) += mt7925u.o mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o +mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o mt7925e-y := pci.o pci_mac.o pci_mcu.o mt7925u-y := usb.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c index 8f9b7a2f376c..2a83ff59a968 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c @@ -2,11 +2,172 @@ /* Copyright (C) 2023 MediaTek Inc. */ #include <linux/etherdevice.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/thermal.h> #include <linux/firmware.h> #include "mt7925.h" #include "mac.h" #include "mcu.h" +static ssize_t mt7925_thermal_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + switch (to_sensor_dev_attr(attr)->index) { + case 0: { + struct mt792x_phy *phy = dev_get_drvdata(dev); + struct mt792x_dev *mdev = phy->dev; + int temperature; + + mt792x_mutex_acquire(mdev); + temperature = mt7925_mcu_get_temperature(phy); + mt792x_mutex_release(mdev); + + if (temperature < 0) + return temperature; + /* display in millidegree Celsius */ + return sprintf(buf, "%u\n", temperature * 1000); + } + default: + return -EINVAL; + } +} +static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7925_thermal_temp, 0); + +static struct attribute *mt7925_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(mt7925_hwmon); + +static int mt7925_thermal_init(struct mt792x_phy *phy) +{ + struct wiphy *wiphy = phy->mt76->hw->wiphy; + struct device *hwmon; + const char *name; + + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7925_%s", + wiphy_name(wiphy)); + + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, + mt7925_hwmon_groups); + return PTR_ERR_OR_ZERO(hwmon); +} + +void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2) +{ + struct mt792x_phy *phy = &dev->phy; + struct mt7925_clc_rule_v2 *rule; + struct mt7925_clc *clc; + bool old = dev->has_eht, new = true; + u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2); + u8 *pos; + + if (mtcl_conf != MT792X_ACPI_MTCL_INVALID && + (((mtcl_conf >> 4) & 0x3) == 0)) { + new = false; + goto out; + } + + if (!phy->clc[MT792x_CLC_BE_CTRL]) + goto out; + + clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL]; + pos = clc->data; + + while (1) { + rule = (struct mt7925_clc_rule_v2 *)pos; + + if (rule->alpha2[0] == alpha2[0] && + rule->alpha2[1] == alpha2[1]) { + new = false; + break; + } + + /* Check the last one */ + if (rule->flag & BIT(0)) + break; + + pos += sizeof(*rule); + } + +out: + if (old == new) + return; + + dev->has_eht = new; + mt7925_set_stream_he_eht_caps(phy); +} + +static void +mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) +{ +#define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \ + (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq)) +#define MT7925_UNII_59G_IS_VALID 0x1 +#define MT7925_UNII_6G_IS_VALID 0x1e + struct ieee80211_supported_band *sband; + struct mt76_dev *mdev = &dev->mt76; + struct ieee80211_channel *ch; + u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, mdev->alpha2); + int i; + + if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) { + if ((mtcl_conf & 0x3) == 0) + dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID; + if (((mtcl_conf >> 2) & 0x3) == 0) + dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID; + } + + sband = wiphy->bands[NL80211_BAND_5GHZ]; + if (!sband) + return; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + /* UNII-4 */ + if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } + + sband = wiphy->bands[NL80211_BAND_6GHZ]; + if (!sband) + return; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + /* UNII-5/6/7/8 */ + if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) || + IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) || + IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) || + IS_UNII_INVALID(4, 6875, 7125, ch->center_freq)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } +} + +void mt7925_regd_update(struct mt792x_dev *dev) +{ + struct mt76_dev *mdev = &dev->mt76; + struct ieee80211_hw *hw = mdev->hw; + struct wiphy *wiphy = hw->wiphy; + + if (!dev->regd_change) + return; + + mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env); + mt7925_regd_channel_update(wiphy, dev); + mt7925_mcu_set_channel_domain(hw->priv); + mt7925_set_tx_sar_pwr(hw, NULL); + dev->regd_change = false; +} +EXPORT_SYMBOL_GPL(mt7925_regd_update); + static void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req) @@ -14,6 +175,7 @@ mt7925_regd_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_dev *mdev = &dev->mt76; + struct mt76_connac_pm *pm = &dev->pm; /* allow world regdom at the first boot only */ if (!memcmp(req->alpha2, "00", 2) && @@ -28,12 +190,17 @@ mt7925_regd_notifier(struct wiphy *wiphy, memcpy(mdev->alpha2, req->alpha2, 2); mdev->region = req->dfs_region; dev->country_ie_env = req->country_ie_env; + dev->regd_change = true; + if (pm->suspended) + return; + + dev->regd_in_progress = true; 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); + mt7925_regd_update(dev); mt792x_mutex_release(dev); + dev->regd_in_progress = false; + wake_up(&dev->wait); } static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev) @@ -128,6 +295,13 @@ static void mt7925_init_work(struct work_struct *work) mt76_set_stream_caps(&dev->mphy, true); mt7925_set_stream_he_eht_caps(&dev->phy); + mt792x_config_mac_addr_list(dev); + + ret = mt7925_init_mlo_caps(&dev->phy); + if (ret) { + dev_err(dev->mt76.dev, "MLO init failed\n"); + return; + } ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); @@ -142,6 +316,18 @@ static void mt7925_init_work(struct work_struct *work) return; } + ret = mt7925_thermal_init(&dev->phy); + if (ret) { + dev_err(dev->mt76.dev, "thermal init failed\n"); + return; + } + + ret = mt7925_mcu_set_thermal_protect(dev); + if (ret) { + dev_err(dev->mt76.dev, "thermal protection enable failed\n"); + return; + } + /* we support chip reset now */ dev->hw_init_done = true; @@ -159,10 +345,12 @@ int mt7925_register_device(struct mt792x_dev *dev) dev->mt76.tx_worker.fn = mt792x_tx_worker; INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work); + INIT_DELAYED_WORK(&dev->mlo_pm_work, mt7925_mlo_pm_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); + init_waitqueue_head(&dev->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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c index 1b9fbd9a140d..c871d2f9688b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -28,6 +28,7 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev) }; struct ieee80211_sta *sta; struct mt792x_sta *msta; + struct mt792x_link_sta *mlink; u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; LIST_HEAD(sta_poll_list); struct rate_info *rate; @@ -46,24 +47,25 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev) if (list_empty(&sta_poll_list)) break; - msta = list_first_entry(&sta_poll_list, - struct mt792x_sta, wcid.poll_list); + mlink = list_first_entry(&sta_poll_list, + struct mt792x_link_sta, wcid.poll_list); + msta = mlink->sta; spin_lock_bh(&dev->mt76.sta_poll_lock); - list_del_init(&msta->wcid.poll_list); + list_del_init(&mlink->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); - idx = msta->wcid.idx; + idx = mlink->wcid.idx; addr = mt7925_mac_wtbl_lmac_addr(dev, idx, MT_WTBL_AC0_CTT_OFFSET); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - u32 tx_last = msta->airtime_ac[i]; - u32 rx_last = msta->airtime_ac[i + 4]; + u32 tx_last = mlink->airtime_ac[i]; + u32 rx_last = mlink->airtime_ac[i + 4]; - msta->airtime_ac[i] = mt76_rr(dev, addr); - msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); + mlink->airtime_ac[i] = mt76_rr(dev, addr); + mlink->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); - tx_time[i] = msta->airtime_ac[i] - tx_last; - rx_time[i] = msta->airtime_ac[i + 4] - rx_last; + tx_time[i] = mlink->airtime_ac[i] - tx_last; + rx_time[i] = mlink->airtime_ac[i + 4] - rx_last; if ((tx_last | rx_last) & BIT(30)) clear = true; @@ -74,10 +76,10 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev) if (clear) { mt7925_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac)); } - if (!msta->wcid.sta) + if (!mlink->wcid.sta) continue; sta = container_of((void *)msta, struct ieee80211_sta, @@ -100,7 +102,7 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev) * we need to make sure that flags match so polling GI * from per-sta counters directly. */ - rate = &msta->wcid.rate; + rate = &mlink->wcid.rate; switch (rate->bw) { case RATE_INFO_BW_160: @@ -144,10 +146,10 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev) rssi[2] = to_rssi(GENMASK(23, 16), val); rssi[3] = to_rssi(GENMASK(31, 14), val); - msta->ack_signal = + mlink->ack_signal = mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); - ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); + ewma_avg_signal_add(&mlink->avg_ack_signal, -mlink->ack_signal); } } @@ -350,7 +352,7 @@ mt7925_mac_fill_rx_rate(struct mt792x_dev *dev, static int mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) { - u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; + u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; bool hdr_trans, unicast, insert_ccmp_hdr = false; u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info; @@ -360,12 +362,11 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) struct mt792x_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; u32 csum_status = *(u32 *)skb->cb; - u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); - struct mt792x_sta *msta = NULL; + struct mt792x_link_sta *mlink; u8 mode = 0; /* , band_idx; */ u16 seq_ctrl = 0; __le16 fc = 0; @@ -393,12 +394,8 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) status->wcid = mt792x_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - msta = container_of(status->wcid, struct mt792x_sta, wcid); - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mlink = container_of(status->wcid, struct mt792x_link_sta, wcid); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); } mt792x_get_status_freq_info(status, chfreq); @@ -418,7 +415,7 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) if (!sband->channels) return -EINVAL; - if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && + if (mt76_is_mmio(&dev->mt76) && (rxd3 & csum_mask) == csum_mask && !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -590,14 +587,25 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) seq_ctrl = le16_to_cpu(hdr->seq_ctrl); qos_ctl = *ieee80211_get_qos_ctl(hdr); } + skb_set_mac_header(skb, (unsigned char *)hdr - skb->data); } else { status->flag |= RX_FLAG_8023; } mt792x_mac_assoc_rssi(dev, skb); - if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) - mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); + if (rxv && !(status->flag & RX_FLAG_8023)) { + switch (status->encoding) { + case RX_ENC_EHT: + mt76_connac3_mac_decode_eht_radiotap(skb, rxv, mode); + break; + case RX_ENC_HE: + mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); + break; + default: + break; + } + } if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; @@ -722,13 +730,17 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0; u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - struct mt76_vif *mvif; + struct mt76_vif_link *mvif; bool beacon = !!(changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)); bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); + struct mt792x_bss_conf *mconf; + + mconf = vif ? mt792x_vif_to_link((struct mt792x_vif *)vif->drv_priv, + wcid->link_id) : NULL; + mvif = mconf ? (struct mt76_vif_link *)&mconf->mt76 : NULL; - mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; if (mvif) { omac_idx = mvif->omac_idx; wmm_idx = mvif->wmm_idx; @@ -789,8 +801,10 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, txwi[5] = cpu_to_le32(val); - val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | - FIELD_PREP(MT_TXD6_MSDU_CNT, 1); + val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1); + if (!ieee80211_vif_is_mld(vif) || + (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)) + val |= MT_TXD6_DIS_MAT; txwi[6] = cpu_to_le32(val); txwi[7] = 0; @@ -820,27 +834,53 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, } EXPORT_SYMBOL_GPL(mt7925_mac_write_txwi); -static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb, + struct mt76_wcid *wcid) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_link_sta *link_sta; + struct mt792x_link_sta *mlink; struct mt792x_sta *msta; + bool is_8023; u16 fc, tid; - u32 val; - if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) + link_sta = rcu_dereference(sta->link[wcid->link_id]); + if (!link_sta) return; - tid = le32_get_bits(txwi[1], MT_TXD1_TID); - if (tid >= 6) /* skip VO queue */ + if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he)) return; - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; + tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; + + 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; msta = (struct mt792x_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) + + if (sta->mlo && msta->deflink_id != IEEE80211_LINK_UNSPECIFIED) + mlink = rcu_dereference(msta->link[msta->deflink_id]); + else + mlink = &msta->deflink; + + if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } @@ -980,7 +1020,7 @@ out_no_skb: void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data) { - struct mt792x_sta *msta = NULL; + struct mt792x_link_sta *mlink = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; @@ -1004,23 +1044,20 @@ void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data) if (!wcid) goto out; - msta = container_of(wcid, struct mt792x_sta, wcid); + mlink = container_of(wcid, struct mt792x_link_sta, wcid); mt7925_mac_add_txs_skb(dev, wcid, pid, txs_data); if (!wcid->sta) goto out; - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); out: rcu_read_unlock(); } void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, + struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct list_head *free_list) { struct mt76_dev *mdev = &dev->mt76; @@ -1033,10 +1070,8 @@ void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t, txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); if (sta) { - struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7925_tx_check_aggr(sta, txwi); + mt7925_tx_check_aggr(sta, t->skb, wcid); wcid_idx = wcid->idx; } else { @@ -1083,7 +1118,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len) */ info = le32_to_cpu(*cur_info); if (info & MT_TXFREE_INFO_PAIR) { - struct mt792x_sta *msta; + struct mt792x_link_sta *mlink; u16 idx; idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); @@ -1092,12 +1127,8 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len) if (!sta) continue; - msta = container_of(wcid, struct mt792x_sta, wcid); - spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &mdev->sta_poll_list); - spin_unlock_bh(&mdev->sta_poll_lock); + mlink = container_of(wcid, struct mt792x_link_sta, wcid); + mt76_wcid_add_poll(&dev->mt76, &mlink->wcid); continue; } @@ -1121,7 +1152,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len) if (!txwi) continue; - mt7925_txwi_free(dev, txwi, sta, 0, &free_list); + mt7925_txwi_free(dev, txwi, sta, wcid, &free_list); } } @@ -1224,17 +1255,28 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + unsigned long valid = ieee80211_vif_is_mld(vif) ? + mvif->valid_links : BIT(0); struct mt792x_dev *dev = mvif->phy->dev; struct ieee80211_hw *hw = mt76_hw(dev); + struct ieee80211_bss_conf *bss_conf; + struct mt792x_bss_conf *mconf; + int i; if (vif->type == NL80211_IFTYPE_STATION) ieee80211_disconnect(vif, true); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); - mt7925_mcu_set_tx(dev, vif); + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); + mconf = mt792x_vif_to_link(mvif, i); + + mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76, + &mvif->sta.deflink.wcid, true); + mt7925_mcu_set_tx(dev, bss_conf); + } if (vif->type == NL80211_IFTYPE_AP) { - mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid, + mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid, true, NULL); mt7925_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_NONE); @@ -1258,6 +1300,7 @@ void mt7925_mac_reset_work(struct work_struct *work) cancel_delayed_work_sync(&dev->mphy.mac_work); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); + dev->sar_inited = false; for (i = 0; i < 10; i++) { mutex_lock(&dev->mt76.mutex); @@ -1369,9 +1412,9 @@ int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (sta) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - if (time_after(jiffies, msta->last_txs + HZ / 4)) { + if (time_after(jiffies, msta->deflink.last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; + msta->deflink.last_txs = jiffies; } } @@ -1406,7 +1449,7 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, sta = wcid_to_sta(wcid); if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7925_tx_check_aggr(sta, txwi); + mt76_connac2_tx_check_aggr(sta, txwi); skb_pull(e->skb, headroom); mt76_tx_complete_skb(mdev, e->wcid, e->skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index 125a1be3cb64..94b0099dcd41 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -130,7 +130,7 @@ mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, @@ -236,6 +236,35 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band, eht_nss->bw._160.rx_tx_mcs13_max_nss = val; } +int mt7925_init_mlo_caps(struct mt792x_phy *phy) +{ + struct wiphy *wiphy = phy->mt76->hw->wiphy; + static const u8 ext_capa_sta[] = { + [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, + }; + static struct wiphy_iftype_ext_capab ext_capab[] = { + { + .iftype = NL80211_IFTYPE_STATION, + .extended_capabilities = ext_capa_sta, + .extended_capabilities_mask = ext_capa_sta, + .extended_capabilities_len = sizeof(ext_capa_sta), + }, + }; + + if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EN)) + return 0; + + ext_capab[0].eml_capabilities = phy->eml_cap; + ext_capab[0].mld_capa_and_ops = + u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS); + + wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; + wiphy->iftype_ext_capab = ext_capab; + wiphy->num_iftype_ext_capab = ARRAY_SIZE(ext_capab); + + return 0; +} + static void __mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy, struct ieee80211_supported_band *sband, @@ -281,6 +310,7 @@ void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy) int __mt7925_start(struct mt792x_phy *phy) { struct mt76_phy *mphy = phy->mt76; + struct mt792x_dev *dev = phy->dev; int err; err = mt7925_mcu_set_channel_domain(mphy); @@ -291,9 +321,12 @@ int __mt7925_start(struct mt792x_phy *phy) if (err) return err; - err = mt7925_set_tx_sar_pwr(mphy->hw, NULL); - if (err) - return err; + if (!dev->sar_inited) { + err = mt7925_set_tx_sar_pwr(mphy->hw, NULL); + if (err) + return err; + dev->sar_inited = true; + } mt792x_mac_reset_counters(phy); set_bit(MT76_STATE_RUNNING, &mphy->state); @@ -301,6 +334,9 @@ int __mt7925_start(struct mt792x_phy *phy) ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, MT792x_WATCHDOG_TIME); + if (phy->chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN) + wiphy_rfkill_start_polling(mphy->hw->wiphy); + return 0; } EXPORT_SYMBOL_GPL(__mt7925_start); @@ -317,61 +353,89 @@ static int mt7925_start(struct ieee80211_hw *hw) return err; } -static int -mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static int mt7925_mac_link_bss_add(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf, + struct mt792x_link_sta *mlink) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct ieee80211_vif *vif = link_conf->vif; + struct mt792x_vif *mvif = mconf->vif; struct mt76_txq *mtxq; int idx, ret = 0; - mt792x_mutex_acquire(dev); + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { + mconf->mt76.idx = MT792x_MAX_INTERFACES; + } else { + mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); - mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { - ret = -ENOSPC; - goto out; + if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } } - mvif->mt76.omac_idx = mvif->mt76.idx; - mvif->phy = phy; - mvif->mt76.band_idx = 0; - mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; + mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ? + 0 : mconf->mt76.idx; + mconf->mt76.band_idx = 0xff; + mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ? + 0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; + mconf->mt76.link_idx = hweight16(mvif->valid_links); - if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) - mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; + if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) + mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; else - mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL; - - ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, - true); - if (ret) - goto out; + mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL; - dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); - phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); + dev->mt76.vif_mask |= BIT_ULL(mconf->mt76.idx); + mvif->phy->omac_mask |= BIT_ULL(mconf->mt76.omac_idx); - idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; + idx = MT792x_WTBL_RESERVED - mconf->mt76.idx; - INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); - mvif->sta.wcid.idx = idx; - mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; - mvif->sta.wcid.hw_key_idx = -1; - mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_wcid_init(&mvif->sta.wcid); + mlink->wcid.idx = idx; + mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt76_wcid_init(&mlink->wcid, 0); mt7925_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - ewma_rssi_init(&mvif->rssi); + ewma_rssi_init(&mconf->rssi); + + rcu_assign_pointer(dev->mt76.wcid[idx], &mlink->wcid); + + ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mconf->mt76, + &mlink->wcid, true); + if (ret) + goto out; - rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; mtxq->wcid = idx; } +out: + return ret; +} + +static int +mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int ret = 0; + + mt792x_mutex_acquire(dev); + + mvif->phy = phy; + mvif->bss_conf.vif = mvif; + mvif->sta.vif = mvif; + mvif->deflink_id = IEEE80211_LINK_UNSPECIFIED; + mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC; + + ret = mt7925_mac_link_bss_add(dev, &vif->bss_conf, &mvif->sta.deflink); + if (ret < 0) + goto out; + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; out: mt792x_mutex_release(dev); @@ -385,9 +449,22 @@ static void mt7925_roc_iter(void *priv, u8 *mac, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = priv; - mt7925_mcu_abort_roc(phy, mvif, phy->roc_token_id); + mt7925_mcu_abort_roc(phy, &mvif->bss_conf, phy->roc_token_id); } +void mt7925_roc_abort_sync(struct mt792x_dev *dev) +{ + struct mt792x_phy *phy = &dev->phy; + + timer_delete_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); + if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + ieee80211_iterate_interfaces(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_roc_iter, (void *)phy); +} +EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync); + void mt7925_roc_work(struct work_struct *work) { struct mt792x_phy *phy; @@ -406,23 +483,24 @@ void mt7925_roc_work(struct work_struct *work) ieee80211_remain_on_channel_expired(phy->mt76->hw); } -static int mt7925_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) +static int mt7925_abort_roc(struct mt792x_phy *phy, + struct mt792x_bss_conf *mconf) { int err = 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt792x_mutex_acquire(phy->dev); if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) - err = mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); + err = mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id); mt792x_mutex_release(phy->dev); return err; } static int mt7925_set_roc(struct mt792x_phy *phy, - struct mt792x_vif *vif, + struct mt792x_bss_conf *mconf, struct ieee80211_channel *chan, int duration, enum mt7925_roc_req type) @@ -434,7 +512,7 @@ static int mt7925_set_roc(struct mt792x_phy *phy, phy->roc_grant = false; - err = mt7925_mcu_set_roc(phy, vif, chan, duration, type, + err = mt7925_mcu_set_roc(phy, mconf, chan, duration, type, ++phy->roc_token_id); if (err < 0) { clear_bit(MT76_STATE_ROC, &phy->mt76->state); @@ -442,7 +520,34 @@ static int mt7925_set_roc(struct mt792x_phy *phy, } if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) { - mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); + mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id); + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + err = -ETIMEDOUT; + } + +out: + return err; +} + +static int mt7925_set_mlo_roc(struct mt792x_phy *phy, + struct mt792x_bss_conf *mconf, + u16 sel_links) +{ + int err; + + if (WARN_ON_ONCE(test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))) + return -EBUSY; + + phy->roc_grant = false; + + err = mt7925_mcu_set_mlo_roc(mconf, sel_links, 5, ++phy->roc_token_id); + if (err < 0) { + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + goto out; + } + + if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) { + mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id); clear_bit(MT76_STATE_ROC, &phy->mt76->state); err = -ETIMEDOUT; } @@ -462,7 +567,8 @@ static int mt7925_remain_on_channel(struct ieee80211_hw *hw, int err; mt792x_mutex_acquire(phy->dev); - err = mt7925_set_roc(phy, mvif, chan, duration, MT7925_ROC_REQ_ROC); + err = mt7925_set_roc(phy, &mvif->bss_conf, + chan, duration, MT7925_ROC_REQ_ROC); mt792x_mutex_release(phy->dev); return err; @@ -474,30 +580,31 @@ static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_phy *phy = mt792x_hw_phy(hw); - return mt7925_abort_roc(phy, mvif); + return mt7925_abort_roc(phy, &mvif->bss_conf); } -static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) +static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, int link_id) { struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; - struct mt76_wcid *wcid = &msta->wcid; - u8 *wcid_keyidx = &wcid->hw_key_idx; + struct ieee80211_bss_conf *link_conf; + struct ieee80211_link_sta *link_sta; int idx = key->keyidx, err = 0; - - /* The hardware does not support per-STA RX GTK, fallback - * to software mode for these. - */ - if ((vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT) && - (key->cipher == WLAN_CIPHER_SUITE_TKIP || - key->cipher == WLAN_CIPHER_SUITE_CCMP) && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - return -EOPNOTSUPP; + struct mt792x_link_sta *mlink; + struct mt792x_bss_conf *mconf; + struct mt76_wcid *wcid; + u8 *wcid_keyidx; + + link_conf = mt792x_vif_to_bss_conf(vif, link_id); + link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL; + mconf = mt792x_vif_to_link(mvif, link_id); + mlink = mt792x_sta_to_link(msta, link_id); + wcid = &mlink->wcid; + wcid_keyidx = &wcid->hw_key_idx; /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { @@ -521,13 +628,12 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - mt792x_mutex_acquire(dev); - - if (cmd == SET_KEY && !mvif->mt76.cipher) { + if (cmd == SET_KEY && !mconf->mt76.cipher) { struct mt792x_phy *phy = mt792x_hw_phy(hw); - mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); - mt7925_mcu_add_bss_info(phy, mvif->mt76.ctx, vif, sta, true); + mconf->mt76.cipher = mt7925_mcu_get_cipher(key->cipher); + mt7925_mcu_add_bss_info(phy, mconf->mt76.ctx, link_conf, + link_sta, true); } if (cmd == SET_KEY) @@ -540,20 +646,59 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); - err = mt7925_mcu_add_key(&dev->mt76, vif, &msta->bip, + err = mt7925_mcu_add_key(&dev->mt76, vif, &mlink->bip, key, MCU_UNI_CMD(STA_REC_UPDATE), - &msta->wcid, cmd); + &mlink->wcid, cmd, msta); if (err) goto out; if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || key->cipher == WLAN_CIPHER_SUITE_WEP40) - err = mt7925_mcu_add_key(&dev->mt76, vif, &mvif->wep_sta->bip, + err = mt7925_mcu_add_key(&dev->mt76, vif, &mvif->wep_sta->deflink.bip, key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), - &mvif->wep_sta->wcid, cmd); - + &mvif->wep_sta->deflink.wcid, cmd, msta); out: + return err; +} + +static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : + &mvif->sta; + int err; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. + */ + if ((vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + + mt792x_mutex_acquire(dev); + + if (ieee80211_vif_is_mld(vif)) { + unsigned int link_id; + unsigned long add; + + add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links; + + for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id); + if (err < 0) + break; + } + } else { + err = mt7925_set_link_key(hw, cmd, vif, sta, key, vif->bss_conf.link_id); + } + mt792x_mutex_release(dev); return err; @@ -669,12 +814,12 @@ static u8 mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool beacon, bool mcast) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_phy *mphy = hw->priv; u16 rate; u8 i, idx, ht; - rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); + rate = mt76_connac2_mac_tx_rate_val(mphy, &vif->bss_conf, beacon, mcast); ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM; if (beacon && ht) { @@ -694,166 +839,430 @@ mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return mvif->basic_rates_idx; } -static void mt7925_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u64 changed) +static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; - struct mt792x_phy *phy = mt792x_hw_phy(hw); - struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_bss_conf *link_conf; + struct mt792x_bss_conf *mconf; + u8 link_id = link_sta->link_id; + struct mt792x_link_sta *mlink; + struct mt792x_sta *msta; + struct mt76_wcid *wcid; + int ret, idx; - mt792x_mutex_acquire(dev); + msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + mlink = mt792x_sta_to_link(msta, link_id); - if (changed & BSS_CHANGED_ERP_SLOT) { - int slottime = info->use_short_slot ? 9 : 20; + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); + if (idx < 0) + return -ENOSPC; - if (slottime != phy->slottime) { - phy->slottime = slottime; - mt792x_mac_set_timeing(phy); - } - } + mconf = mt792x_vif_to_link(mvif, link_id); + mt76_wcid_init(&mlink->wcid, 0); + mlink->wcid.sta = 1; + mlink->wcid.idx = idx; + mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET; + mlink->last_txs = jiffies; + mlink->wcid.link_id = link_sta->link_id; + mlink->wcid.link_valid = !!link_sta->sta->valid_links; + mlink->sta = msta; + + wcid = &mlink->wcid; + ewma_signal_init(&wcid->rssi); + rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid); + mt76_wcid_init(wcid, 0); + ewma_avg_signal_init(&mlink->avg_ack_signal); + memset(mlink->airtime_ac, 0, + sizeof(msta->deflink.airtime_ac)); - if (changed & BSS_CHANGED_MCAST_RATE) - mvif->mcast_rates_idx = - mt7925_get_rates_table(hw, vif, false, true); + ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); + if (ret) + return ret; - if (changed & BSS_CHANGED_BASIC_RATES) - mvif->basic_rates_idx = - mt7925_get_rates_table(hw, vif, false, false); + mt7925_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - if (changed & (BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_ENABLED)) { - mvif->beacon_rates_idx = - mt7925_get_rates_table(hw, vif, true, false); + link_conf = mt792x_vif_to_bss_conf(vif, link_id); - mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, - info->enable_beacon); + /* should update bss info before STA add */ + if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + if (ieee80211_vif_is_mld(vif)) + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, link_sta != mlink->pri_link); + else + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, false); } - /* ensure that enable txcmd_mode after bss_info */ - if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) - mt7925_mcu_set_tx(dev, vif); - - if (changed & BSS_CHANGED_PS) - mt7925_mcu_uni_bss_ps(dev, vif); + if (ieee80211_vif_is_mld(vif) && + link_sta == mlink->pri_link) { + ret = mt7925_mcu_sta_update(dev, link_sta, vif, true, + MT76_STA_INFO_STATE_NONE); + if (ret) + return ret; + } else if (ieee80211_vif_is_mld(vif) && + link_sta != mlink->pri_link) { + ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif, + true, MT76_STA_INFO_STATE_ASSOC); + if (ret) + return ret; - if (changed & BSS_CHANGED_ASSOC) { - mt7925_mcu_sta_update(dev, NULL, vif, true, - MT76_STA_INFO_STATE_ASSOC); - mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); + ret = mt7925_mcu_sta_update(dev, link_sta, vif, true, + MT76_STA_INFO_STATE_ASSOC); + if (ret) + return ret; + } else { + ret = mt7925_mcu_sta_update(dev, link_sta, vif, true, + MT76_STA_INFO_STATE_NONE); + if (ret) + return ret; } - if (changed & BSS_CHANGED_ARP_FILTER) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + mt76_connac_power_save_sched(&dev->mphy, &dev->pm); + + return 0; +} - mt7925_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, info); +static int +mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, unsigned long new_links) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + unsigned int link_id; + int err = 0; + + for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_link_sta *link_sta; + struct mt792x_link_sta *mlink; + + if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) { + mlink = &msta->deflink; + msta->deflink_id = link_id; + } else { + mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL); + if (!mlink) { + err = -ENOMEM; + break; + } + } + + msta->valid_links |= BIT(link_id); + rcu_assign_pointer(msta->link[link_id], mlink); + mlink->sta = msta; + mlink->pri_link = &sta->deflink; + mlink->wcid.def_wcid = &msta->deflink.wcid; + + link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); + mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta); } - mt792x_mutex_release(dev); + return err; } int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - int ret, idx; - - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); - if (idx < 0) - return -ENOSPC; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + int err; - INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; - msta->wcid.sta = 1; - msta->wcid.idx = idx; - msta->wcid.phy_idx = mvif->mt76.band_idx; - msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; - msta->last_txs = jiffies; - - ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); - if (ret) - return ret; if (vif->type == NL80211_IFTYPE_STATION) mvif->wep_sta = msta; - mt7925_mac_wtbl_update(dev, idx, - MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + if (ieee80211_vif_is_mld(vif)) { + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; - /* should update bss info before STA add */ - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, - false); + err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links); + } else { + err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink); + } - ret = mt7925_mcu_sta_update(dev, sta, vif, true, - MT76_STA_INFO_STATE_NONE); - if (ret) - return ret; + return err; +} +EXPORT_SYMBOL_GPL(mt7925_mac_sta_add); - mt76_connac_power_save_sched(&dev->mphy, &dev->pm); +static u16 +mt7925_mac_select_links(struct mt76_dev *mdev, struct ieee80211_vif *vif) +{ + unsigned long usable_links = ieee80211_vif_usable_links(vif); + struct { + u8 link_id; + enum nl80211_band band; + } data[IEEE80211_MLD_MAX_NUM_LINKS]; + u8 link_id, i, j, n_data = 0; + u16 sel_links = 0; + + if (!ieee80211_vif_is_mld(vif)) + return 0; + + if (vif->active_links == usable_links) + return vif->active_links; + + rcu_read_lock(); + for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_bss_conf *link_conf = + rcu_dereference(vif->link_conf[link_id]); + + if (WARN_ON_ONCE(!link_conf)) + continue; - return 0; + data[n_data].link_id = link_id; + data[n_data].band = link_conf->chanreq.oper.chan->band; + n_data++; + } + rcu_read_unlock(); + + for (i = 0; i < n_data; i++) { + if (!(BIT(data[i].link_id) & vif->active_links)) + continue; + + sel_links = BIT(data[i].link_id); + + for (j = 0; j < n_data; j++) { + if (data[i].band != data[j].band) { + sel_links |= BIT(data[j].link_id); + break; + } + } + + break; + } + + return sel_links; } -EXPORT_SYMBOL_GPL(mt7925_mac_sta_add); -void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static void +mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_bss_conf *link_conf = + mt792x_vif_to_bss_conf(vif, mvif->deflink_id); + struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper; + enum nl80211_band band = chandef->chan->band, secondary_band; + + u16 sel_links = mt7925_mac_select_links(mdev, vif); + u8 secondary_link_id = __ffs(~BIT(mvif->deflink_id) & sel_links); + + if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2) + return; + + link_conf = mt792x_vif_to_bss_conf(vif, secondary_link_id); + secondary_band = link_conf->chanreq.oper.chan->band; + + if (band == NL80211_BAND_2GHZ || + (band == NL80211_BAND_5GHZ && secondary_band == NL80211_BAND_6GHZ)) { + mt7925_abort_roc(mvif->phy, &mvif->bss_conf); + + mt792x_mutex_acquire(dev); + + mt7925_set_mlo_roc(mvif->phy, &mvif->bss_conf, sel_links); + + mt792x_mutex_release(dev); + } + + ieee80211_set_active_links_async(vif, sel_links); +} + +static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct ieee80211_bss_conf *link_conf; + struct mt792x_link_sta *mlink; + struct mt792x_sta *msta; + + msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + mlink = mt792x_sta_to_link(msta, link_sta->link_id); mt792x_mutex_acquire(dev); - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, - true); + if (ieee80211_vif_is_mld(vif)) { + link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id); + } else { + link_conf = mt792x_vif_to_bss_conf(vif, vif->bss_conf.link_id); + } - ewma_avg_signal_init(&msta->avg_ack_signal); + if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + struct mt792x_bss_conf *mconf; + + mconf = mt792x_link_conf_to_mconf(link_conf); + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, true); + } - mt7925_mac_wtbl_update(dev, msta->wcid.idx, + ewma_avg_signal_init(&mlink->avg_ack_signal); + + mt7925_mac_wtbl_update(dev, mlink->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac)); - mt7925_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); + mt7925_mcu_sta_update(dev, link_sta, vif, true, MT76_STA_INFO_STATE_ASSOC); mt792x_mutex_release(dev); } -EXPORT_SYMBOL_GPL(mt7925_mac_sta_assoc); -void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int mt7925_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev) +{ + struct ieee80211_link_sta *link_sta = &sta->deflink; + + if (ev != MT76_STA_EVENT_ASSOC) + return 0; + + if (ieee80211_vif_is_mld(vif)) { + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + + link_sta = mt792x_sta_to_link_sta(vif, sta, msta->deflink_id); + mt7925_mac_set_links(mdev, vif); + } + + mt7925_mac_link_sta_assoc(mdev, vif, link_sta); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_mac_sta_event); + +static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct ieee80211_bss_conf *link_conf; + u8 link_id = link_sta->link_id; + struct mt792x_link_sta *mlink; + struct mt792x_sta *msta; + + msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + mlink = mt792x_sta_to_link(msta, link_id); - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); + mt7925_roc_abort_sync(dev); + + mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid); mt76_connac_pm_wake(&dev->mphy, &dev->pm); - mt7925_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE); - mt7925_mac_wtbl_update(dev, msta->wcid.idx, + mt7925_mcu_sta_update(dev, link_sta, vif, false, + MT76_STA_INFO_STATE_NONE); + mt7925_mac_wtbl_update(dev, mlink->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - if (vif->type == NL80211_IFTYPE_STATION) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + link_conf = mt792x_vif_to_bss_conf(vif, link_id); - mvif->wep_sta = NULL; - ewma_rssi_init(&mvif->rssi); - if (!sta->tdls) - mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, - false); + if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + struct mt792x_bss_conf *mconf; + + mconf = mt792x_link_conf_to_mconf(link_conf); + + if (ieee80211_vif_is_mld(vif)) + mt792x_mac_link_bss_remove(dev, mconf, mlink); + else + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, + link_sta, false); } spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); + if (!list_empty(&mlink->wcid.poll_list)) + list_del_init(&mlink->wcid.poll_list); spin_unlock_bh(&mdev->sta_poll_lock); mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } + +static int +mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, unsigned long old_links) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt76_dev *mdev = &dev->mt76; + struct mt76_wcid *wcid; + unsigned int link_id; + + /* clean up bss before starec */ + for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_link_sta *link_sta; + struct ieee80211_bss_conf *link_conf; + struct mt792x_bss_conf *mconf; + struct mt792x_link_sta *mlink; + + link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); + if (!link_sta) + continue; + + mlink = mt792x_sta_to_link(msta, link_id); + if (!mlink) + continue; + + link_conf = mt792x_vif_to_bss_conf(vif, link_id); + if (!link_conf) + continue; + + mconf = mt792x_link_conf_to_mconf(link_conf); + + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, + link_sta, false); + } + + for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_link_sta *link_sta; + struct mt792x_link_sta *mlink; + + link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); + if (!link_sta) + continue; + + mlink = mt792x_sta_to_link(msta, link_id); + if (!mlink) + continue; + + mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta); + + wcid = &mlink->wcid; + rcu_assign_pointer(msta->link[link_id], NULL); + msta->valid_links &= ~BIT(link_id); + mlink->sta = NULL; + mlink->pri_link = NULL; + + if (link_sta != mlink->pri_link) { + mt76_wcid_cleanup(mdev, wcid); + mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx); + } + + if (msta->deflink_id == link_id) + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; + } + + return 0; +} + +void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + unsigned long rem; + + rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0); + + mt7925_mac_sta_remove_links(dev, vif, sta, rem); + + if (ieee80211_vif_is_mld(vif)) + mt7925_mcu_del_dev(mdev, vif); + + if (vif->type == NL80211_IFTYPE_STATION) { + mvif->wep_sta = NULL; + ewma_rssi_init(&mvif->bss_conf.rssi); + } + + mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC; +} EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove); static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, u32 val) @@ -889,12 +1298,12 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_acquire(dev); switch (action) { case IEEE80211_AMPDU_RX_START: - mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, + mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn, params->buf_size); mt7925_mcu_uni_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: - mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid); mt7925_mcu_uni_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: @@ -905,16 +1314,16 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); + clear_bit(tid, &msta->deflink.wcid.ampdu_state); mt7925_mcu_uni_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->wcid.ampdu_state); + set_bit(tid, &msta->deflink.wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); + clear_bit(tid, &msta->deflink.wcid.ampdu_state); mt7925_mcu_uni_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -924,6 +1333,38 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return ret; } +static void +mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt792x_dev *dev = priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + unsigned long valid = ieee80211_vif_is_mld(vif) ? + mvif->valid_links : BIT(0); + struct ieee80211_bss_conf *bss_conf; + int i; + + if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS) + return; + + mt792x_mutex_acquire(dev); + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); + mt7925_mcu_uni_bss_ps(dev, bss_conf); + } + mt792x_mutex_release(dev); +} + +void mt7925_mlo_pm_work(struct work_struct *work) +{ + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + mlo_pm_work.work); + struct ieee80211_hw *hw = mt76_hw(dev); + + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_mlo_pm_iter, dev); +} + static bool is_valid_alpha2(const char *alpha2) { if (!alpha2) @@ -980,6 +1421,8 @@ void mt7925_scan_work(struct work_struct *work) if (!is_valid_alpha2(evt->alpha2)) break; + mt7925_regd_be_ctrl(phy->dev, evt->alpha2); + if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0') break; @@ -1155,27 +1598,38 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, bool enabled) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); + unsigned long valid = mvif->valid_links; + u8 i; mt792x_mutex_acquire(dev); - if (enabled) - set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); - else - clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0); + + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + struct mt792x_link_sta *mlink; - mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta); + mlink = mt792x_sta_to_link(msta, i); + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); + + mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i); + } mt792x_mutex_release(dev); } #if IS_ENABLED(CONFIG_IPV6) -static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct inet6_dev *idev) +static void __mt7925_ipv6_addr_change(struct ieee80211_hw *hw, + struct ieee80211_bss_conf *link_conf, + struct inet6_dev *idev) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mvif->phy->dev; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct inet6_ifaddr *ifa; struct sk_buff *skb; u8 idx = 0; @@ -1189,7 +1643,7 @@ static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; } req_hdr = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }, .arpns = { .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), @@ -1224,6 +1678,23 @@ static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work); } + +static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct inet6_dev *idev) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + unsigned long valid = ieee80211_vif_is_mld(vif) ? + mvif->valid_links : BIT(0); + struct ieee80211_bss_conf *bss_conf; + int i; + + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); + __mt7925_ipv6_addr_change(hw, bss_conf, idev); + } +} + #endif int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, @@ -1274,6 +1745,26 @@ mt7925_channel_switch_beacon(struct ieee80211_hw *hw, } static int +mt7925_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_vif_to_link(mvif, link_id); + static 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 */ + mconf->queue_params[mq_to_aci[queue]] = *params; + + return 0; +} + +static int mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { @@ -1283,12 +1774,12 @@ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_acquire(dev); - err = mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, - true); + err = mt7925_mcu_add_bss_info(&dev->phy, mvif->bss_conf.mt76.ctx, + link_conf, NULL, true); if (err) goto out; - err = mt7925_mcu_set_bss_pm(dev, vif, true); + err = mt7925_mcu_set_bss_pm(dev, link_conf, true); if (err) goto out; @@ -1310,12 +1801,12 @@ mt7925_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_acquire(dev); - err = mt7925_mcu_set_bss_pm(dev, vif, false); + err = mt7925_mcu_set_bss_pm(dev, link_conf, false); if (err) goto out; - mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, - false); + mt7925_mcu_add_bss_info(&dev->phy, mvif->bss_conf.mt76.ctx, link_conf, + NULL, false); out: mt792x_mutex_release(dev); @@ -1334,34 +1825,56 @@ mt7925_remove_chanctx(struct ieee80211_hw *hw, { } -static void mt7925_ctx_iter(void *priv, u8 *mac, - struct ieee80211_vif *vif) +static void +mt7925_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx, + u32 changed) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct ieee80211_chanctx_conf *ctx = priv; + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_bss_conf *mconf; + struct ieee80211_vif *vif; + struct mt792x_vif *mvif; - if (ctx != mvif->mt76.ctx) + if (!mctx->bss_conf) return; + mconf = mctx->bss_conf; + mvif = mconf->vif; + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); + + mt792x_mutex_acquire(phy->dev); if (vif->type == NL80211_IFTYPE_MONITOR) { mt7925_mcu_set_sniffer(mvif->phy->dev, vif, true); mt7925_mcu_config_sniffer(mvif, ctx); } else { - mt7925_mcu_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx); - } -} + if (ieee80211_vif_is_mld(vif)) { + unsigned long valid = mvif->valid_links; + u8 i; -static void -mt7925_change_chanctx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *ctx, - u32 changed) -{ - struct mt792x_phy *phy = mt792x_hw_phy(hw); + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + mconf = mt792x_vif_to_link(mvif, i); + if (mconf && mconf->mt76.ctx == ctx) + break; + } + + } else { + mconf = &mvif->bss_conf; + } + + if (mconf) { + struct ieee80211_bss_conf *link_conf; + + link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id); + mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76, + link_conf, ctx); + + if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) + mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76, + link_conf, ctx); + } + } - mt792x_mutex_acquire(phy->dev); - ieee80211_iterate_active_interfaces(phy->mt76->hw, - IEEE80211_IFACE_ITER_ACTIVE, - mt7925_ctx_iter, ctx); mt792x_mutex_release(phy->dev); } @@ -1375,7 +1888,8 @@ static void mt7925_mgd_prepare_tx(struct ieee80211_hw *hw, jiffies_to_msecs(HZ); mt792x_mutex_acquire(dev); - mt7925_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration, + mt7925_set_roc(mvif->phy, &mvif->bss_conf, + mvif->bss_conf.mt76.ctx->def.chan, duration, MT7925_ROC_REQ_JOIN); mt792x_mutex_release(dev); } @@ -1386,7 +1900,324 @@ static void mt7925_mgd_complete_tx(struct ieee80211_hw *hw, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - mt7925_abort_roc(mvif->phy, mvif); + mt7925_abort_roc(mvif->phy, &mvif->bss_conf); +} + +static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u64 changed) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + unsigned long valid = ieee80211_vif_is_mld(vif) ? + mvif->valid_links : BIT(0); + struct ieee80211_bss_conf *bss_conf; + int i; + + mt792x_mutex_acquire(dev); + + if (changed & BSS_CHANGED_ASSOC) { + mt7925_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_ASSOC); + mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); + + if (ieee80211_vif_is_mld(vif)) + mvif->mlo_pm_state = MT792x_MLO_LINK_ASSOC; + } + + if (changed & BSS_CHANGED_ARP_FILTER) { + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); + mt7925_mcu_update_arp_filter(&dev->mt76, bss_conf); + } + } + + if (changed & BSS_CHANGED_PS) { + if (hweight16(mvif->valid_links) < 2) { + /* legacy */ + bss_conf = &vif->bss_conf; + mt7925_mcu_uni_bss_ps(dev, bss_conf); + } else { + if (mvif->mlo_pm_state == MT792x_MLO_LINK_ASSOC) { + mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS_PENDING; + } else if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS) { + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); + mt7925_mcu_uni_bss_ps(dev, bss_conf); + } + } + } + } + + mt792x_mutex_release(dev); +} + +static void mt7925_link_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u64 changed) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_bss_conf *mconf; + struct ieee80211_bss_conf *link_conf; + + mconf = mt792x_vif_to_link(mvif, info->link_id); + link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id); + + mt792x_mutex_acquire(dev); + + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt7925_mcu_set_timing(phy, info); + } + } + + if (changed & BSS_CHANGED_MCAST_RATE) + mconf->mt76.mcast_rates_idx = + mt7925_get_rates_table(hw, vif, false, true); + + if (changed & BSS_CHANGED_BASIC_RATES) + mconf->mt76.basic_rates_idx = + mt7925_get_rates_table(hw, vif, false, false); + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) { + mconf->mt76.beacon_rates_idx = + mt7925_get_rates_table(hw, vif, true, false); + + mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, + info->enable_beacon); + } + + /* ensure that enable txcmd_mode after bss_info */ + if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) + mt7925_mcu_set_tx(dev, info); + + if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS_PENDING) { + /* Indicate the secondary setup done */ + mt7925_mcu_uni_bss_bcnft(dev, info, true); + + ieee80211_queue_delayed_work(hw, &dev->mlo_pm_work, 5 * HZ); + mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS; + } + + if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) + mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76, + link_conf, NULL); + + mt792x_mutex_release(dev); +} + +static int +mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u16 old_links, u16 new_links, + struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) +{ + struct mt792x_bss_conf *mconfs[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *mconf; + struct mt792x_link_sta *mlinks[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *mlink; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + unsigned long add = new_links & ~old_links; + unsigned long rem = old_links & ~new_links; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct ieee80211_bss_conf *link_conf; + unsigned int link_id; + int err; + + if (old_links == new_links) + return 0; + + mt792x_mutex_acquire(dev); + + for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) { + mconf = mt792x_vif_to_link(mvif, link_id); + mlink = mt792x_sta_to_link(&mvif->sta, link_id); + + if (!mconf || !mlink) + continue; + + if (mconf != &mvif->bss_conf) { + mt792x_mac_link_bss_remove(dev, mconf, mlink); + devm_kfree(dev->mt76.dev, mconf); + devm_kfree(dev->mt76.dev, mlink); + } + + rcu_assign_pointer(mvif->link_conf[link_id], NULL); + rcu_assign_pointer(mvif->sta.link[link_id], NULL); + } + + for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + if (!old_links) { + mvif->deflink_id = link_id; + mconf = &mvif->bss_conf; + mlink = &mvif->sta.deflink; + } else { + mconf = devm_kzalloc(dev->mt76.dev, sizeof(*mconf), + GFP_KERNEL); + mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), + GFP_KERNEL); + if (!mconf || !mlink) + return -ENOMEM; + } + + mconfs[link_id] = mconf; + mlinks[link_id] = mlink; + mconf->link_id = link_id; + mconf->vif = mvif; + mlink->wcid.link_id = link_id; + mlink->wcid.link_valid = !!vif->valid_links; + mlink->wcid.def_wcid = &mvif->sta.deflink.wcid; + } + + if (hweight16(mvif->valid_links) == 0) + mt792x_mac_link_bss_remove(dev, &mvif->bss_conf, + &mvif->sta.deflink); + + for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + mconf = mconfs[link_id]; + mlink = mlinks[link_id]; + link_conf = mt792x_vif_to_bss_conf(vif, link_id); + + rcu_assign_pointer(mvif->link_conf[link_id], mconf); + rcu_assign_pointer(mvif->sta.link[link_id], mlink); + + err = mt7925_mac_link_bss_add(dev, link_conf, mlink); + if (err < 0) + goto free; + + if (mconf != &mvif->bss_conf) { + err = mt7925_set_mlo_roc(phy, &mvif->bss_conf, + vif->active_links); + if (err < 0) + goto free; + } + } + + mvif->valid_links = new_links; + + mt792x_mutex_release(dev); + + return 0; + +free: + for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + rcu_assign_pointer(mvif->link_conf[link_id], NULL); + rcu_assign_pointer(mvif->sta.link[link_id], NULL); + + if (mconf != &mvif->bss_conf) + devm_kfree(dev->mt76.dev, mconfs[link_id]); + if (mlink != &mvif->sta.deflink) + devm_kfree(dev->mt76.dev, mlinks[link_id]); + } + + mt792x_mutex_release(dev); + + return err; +} + +static int +mt7925_change_sta_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 old_links, u16 new_links) +{ + unsigned long add = new_links & ~old_links; + unsigned long rem = old_links & ~new_links; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err = 0; + + if (old_links == new_links) + return 0; + + mt792x_mutex_acquire(dev); + + err = mt7925_mac_sta_remove_links(dev, vif, sta, rem); + if (err < 0) + goto out; + + err = mt7925_mac_sta_add_links(dev, vif, sta, add); + if (err < 0) + goto out; + +out: + mt792x_mutex_release(dev); + + return err; +} + +static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct ieee80211_bss_conf *pri_link_conf; + struct mt792x_bss_conf *mconf; + + mutex_lock(&dev->mt76.mutex); + + if (ieee80211_vif_is_mld(vif)) { + mconf = mt792x_vif_to_link(mvif, link_conf->link_id); + pri_link_conf = mt792x_vif_to_bss_conf(vif, mvif->deflink_id); + + if (vif->type == NL80211_IFTYPE_STATION && + mconf == &mvif->bss_conf) + mt7925_mcu_add_bss_info(&dev->phy, NULL, pri_link_conf, + NULL, true); + } else { + mconf = &mvif->bss_conf; + } + + mconf->mt76.ctx = ctx; + mctx->bss_conf = mconf; + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_bss_conf *mconf; + + mutex_lock(&dev->mt76.mutex); + + if (ieee80211_vif_is_mld(vif)) { + mconf = mt792x_vif_to_link(mvif, link_conf->link_id); + + if (vif->type == NL80211_IFTYPE_STATION && + mconf == &mvif->bss_conf) + mt7925_mcu_add_bss_info(&dev->phy, NULL, link_conf, + NULL, false); + } else { + mconf = &mvif->bss_conf; + } + + mctx->bss_conf = NULL; + mconf->mt76.ctx = NULL; + mutex_unlock(&dev->mt76.mutex); +} + +static void mt7925_rfkill_poll(struct ieee80211_hw *hw) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int ret; + + mt792x_mutex_acquire(phy->dev); + ret = mt7925_mcu_wf_rf_pin_ctrl(phy); + mt792x_mutex_release(phy->dev); + + wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0); } const struct ieee80211_ops mt7925_ops = { @@ -1396,9 +2227,8 @@ const struct ieee80211_ops mt7925_ops = { .add_interface = mt7925_add_interface, .remove_interface = mt792x_remove_interface, .config = mt7925_config, - .conf_tx = mt792x_conf_tx, + .conf_tx = mt7925_conf_tx, .configure_filter = mt7925_configure_filter, - .bss_info_changed = mt7925_bss_info_changed, .start_ap = mt7925_start_ap, .stop_ap = mt7925_stop_ap, .sta_state = mt76_sta_state, @@ -1429,6 +2259,8 @@ const struct ieee80211_ops mt7925_ops = { .sta_statistics = mt792x_sta_statistics, .sched_scan_start = mt7925_start_sched_scan, .sched_scan_stop = mt7925_stop_sched_scan, + CFG80211_TESTMODE_CMD(mt7925_testmode_cmd) + CFG80211_TESTMODE_DUMP(mt7925_testmode_dump) #ifdef CONFIG_PM .suspend = mt7925_suspend, .resume = mt7925_resume, @@ -1442,10 +2274,15 @@ const struct ieee80211_ops mt7925_ops = { .add_chanctx = mt7925_add_chanctx, .remove_chanctx = mt7925_remove_chanctx, .change_chanctx = mt7925_change_chanctx, - .assign_vif_chanctx = mt792x_assign_vif_chanctx, - .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, + .assign_vif_chanctx = mt7925_assign_vif_chanctx, + .unassign_vif_chanctx = mt7925_unassign_vif_chanctx, .mgd_prepare_tx = mt7925_mgd_prepare_tx, .mgd_complete_tx = mt7925_mgd_complete_tx, + .vif_cfg_changed = mt7925_vif_cfg_changed, + .link_info_changed = mt7925_link_info_changed, + .change_vif_links = mt7925_change_vif_links, + .change_sta_links = mt7925_change_sta_links, + .rfkill_poll = mt7925_rfkill_poll, }; EXPORT_SYMBOL_GPL(mt7925_ops); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index c5fd7116929b..b8542be0d945 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -39,7 +39,6 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd, } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) || cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) || cmd == MCU_UNI_CMD(STA_REC_UPDATE) || - cmd == MCU_UNI_CMD(HIF_CTRL) || cmd == MCU_UNI_CMD(OFFLOAD) || cmd == MCU_UNI_CMD(SUSPEND)) { struct mt7925_mcu_uni_event *event; @@ -121,11 +120,10 @@ int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set) EXPORT_SYMBOL_GPL(mt7925_mcu_regval); int mt7925_mcu_update_arp_filter(struct mt76_dev *dev, - struct mt76_vif *vif, - struct ieee80211_bss_conf *info) + struct ieee80211_bss_conf *link_conf) { - struct ieee80211_vif *mvif = container_of(info, struct ieee80211_vif, - bss_conf); + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct ieee80211_vif *mvif = link_conf->vif; struct sk_buff *skb; int i, len = min_t(int, mvif->cfg.arp_addr_cnt, IEEE80211_BSS_ARP_ADDR_LIST_LEN); @@ -137,7 +135,7 @@ int mt7925_mcu_update_arp_filter(struct mt76_dev *dev, struct mt7925_arpns_tlv arp; } req = { .hdr = { - .bss_idx = vif->idx, + .bss_idx = mconf->mt76.idx, }, .arp = { .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP), @@ -165,7 +163,7 @@ static int mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, bool suspend, struct cfg80211_wowlan *wowlan) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt76_dev *dev = phy->dev; struct { struct { @@ -220,7 +218,7 @@ mt7925_mcu_set_wow_pattern(struct mt76_dev *dev, u8 index, bool enable, struct cfg80211_pkt_pattern *pattern) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt7925_wow_pattern_tlv *tlv; struct sk_buff *skb; struct { @@ -275,7 +273,7 @@ static void mt7925_mcu_connection_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt7925_uni_beacon_loss_event *event = priv; if (mvif->idx != event->hdr.bss_idx) @@ -305,25 +303,26 @@ mt7925_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb) static void mt7925_mcu_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct mt7925_roc_grant_tlv *grant = priv; + if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION) + return; + if (mvif->idx != grant->bss_idx) return; mvif->band_idx = grant->dbdcband; } -static void -mt7925_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) +static void mt7925_mcu_roc_handle_grant(struct mt792x_dev *dev, + struct tlv *tlv) { struct ieee80211_hw *hw = dev->mt76.hw; struct mt7925_roc_grant_tlv *grant; - struct mt7925_mcu_rxd *rxd; int duration; - rxd = (struct mt7925_mcu_rxd *)skb->data; - grant = (struct mt7925_roc_grant_tlv *)(rxd->tlv + 4); + grant = (struct mt7925_roc_grant_tlv *)tlv; /* should never happen */ WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT)); @@ -342,6 +341,70 @@ mt7925_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) } static void +mt7925_mcu_handle_hif_ctrl_basic(struct mt792x_dev *dev, struct tlv *tlv) +{ + struct mt7925_mcu_hif_ctrl_basic_tlv *basic; + + basic = (struct mt7925_mcu_hif_ctrl_basic_tlv *)tlv; + + if (basic->hifsuspend) { + dev->hif_idle = true; + if (!(basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE && + basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)) + dev_info(dev->mt76.dev, "Hif traffic not idle.\n"); + } else { + dev->hif_resumed = true; + } + wake_up(&dev->wait); +} + +static void +mt7925_mcu_uni_hif_ctrl_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct tlv *tlv; + u32 tlv_len; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + tlv = (struct tlv *)skb->data; + tlv_len = skb->len; + + while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) { + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_HIF_CTRL_BASIC: + mt7925_mcu_handle_hif_ctrl_basic(dev, tlv); + break; + default: + break; + } + tlv_len -= le16_to_cpu(tlv->len); + tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len)); + } +} + +static void +mt7925_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct tlv *tlv; + int i = 0; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + + while (i < skb->len) { + tlv = (struct tlv *)(skb->data + i); + + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_ROC_GRANT: + mt7925_mcu_roc_handle_grant(dev, tlv); + break; + case UNI_EVENT_ROC_GRANT_SUB_LINK: + break; + } + + i += le16_to_cpu(tlv->len); + } +} + +static void mt7925_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; @@ -363,7 +426,7 @@ mt7925_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb) struct mt7925_mcu_txs_event { u8 ver; u8 rsv[3]; - u8 data[0]; + u8 data[]; } __packed * txs; struct tlv *tlv; u32 tlv_len; @@ -464,6 +527,9 @@ mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev, rxd = (struct mt7925_mcu_rxd *)skb->data; switch (rxd->eid) { + case MCU_UNI_EVENT_HIF_CTRL: + mt7925_mcu_uni_hif_ctrl_event(dev, skb); + break; case MCU_UNI_EVENT_FW_LOG_2_HOST: mt7925_mcu_uni_debug_msg_event(dev, skb); break; @@ -505,7 +571,7 @@ void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb) } static int -mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, +mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, struct ieee80211_ampdu_params *params, bool enable, bool tx) { @@ -544,9 +610,9 @@ int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev, struct mt792x_vif *mvif = msta->vif; if (enable && !params->amsdu) - msta->wcid.amsdu = false; + msta->deflink.wcid.amsdu = false; - return mt7925_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params, enable, true); } @@ -557,10 +623,58 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; struct mt792x_vif *mvif = msta->vif; - return mt7925_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params, enable, false); } +static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) +{ + struct { + u8 rsv[4]; + + __le16 tag; + __le16 len; + + __le32 addr; + __le32 valid; + u8 data[MT7925_EEPROM_BLOCK_SIZE]; + } __packed req = { + .tag = cpu_to_le16(1), + .len = cpu_to_le16(sizeof(req) - 4), + .addr = cpu_to_le32(round_down(offset, + MT7925_EEPROM_BLOCK_SIZE)), + }; + struct evt { + u8 rsv[4]; + + __le16 tag; + __le16 len; + + __le32 ver; + __le32 addr; + __le32 valid; + __le32 size; + __le32 magic_num; + __le32 type; + __le32 rsv1[4]; + u8 data[32]; + } __packed *res; + struct sk_buff *skb; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + res = (struct evt *)skb->data; + *val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE]; + + dev_kfree_skb(skb); + + return 0; +} + static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) { const struct mt76_connac2_fw_trailer *hdr; @@ -569,13 +683,21 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) struct mt76_dev *mdev = &dev->mt76; struct mt792x_phy *phy = &dev->phy; const struct firmware *fw; + u8 *clc_base = NULL, hw_encap = 0; int ret, i, len, offset = 0; - u8 *clc_base = NULL; + dev->phy.clc_chan_conf = 0xff; if (mt7925_disable_clc || mt76_is_usb(&dev->mt76)) return 0; + if (mt76_is_mmio(&dev->mt76)) { + ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap); + if (ret) + return ret; + hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP); + } + ret = request_firmware(&fw, fw_name, mdev->dev); if (ret) return ret; @@ -613,10 +735,19 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) { clc = (const struct mt7925_clc *)(clc_base + offset); + if (clc->idx >= ARRAY_SIZE(phy->clc)) + break; + /* do not init buf again if chip reset triggered */ if (phy->clc[clc->idx]) continue; + /* header content sanity */ + if ((clc->idx == MT792x_CLC_BE_CTRL && + u8_get_bits(clc->t2.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) || + u8_get_bits(clc->t0.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) + continue; + phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc, le32_to_cpu(clc->len), GFP_KERNEL); @@ -652,10 +783,46 @@ int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) int ret; ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(WSYS_CONFIG), - &req, sizeof(req), false, NULL); + &req, sizeof(req), true, NULL); return ret; } +int mt7925_mcu_get_temperature(struct mt792x_phy *phy) +{ + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + u8 _rsv2[4]; + } __packed req = { + .tag = cpu_to_le16(0x0), + .len = cpu_to_le16(sizeof(req) - 4), + }; + struct mt7925_thermal_evt { + u8 rsv[4]; + __le32 temperature; + } __packed * evt; + struct mt792x_dev *dev = phy->dev; + int temperature, ret; + struct sk_buff *skb; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(THERMAL), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + skb_pull(skb, 4 + sizeof(struct tlv)); + evt = (struct mt7925_thermal_evt *)skb->data; + + temperature = le32_to_cpu(evt->temperature); + + dev_kfree_skb(skb); + + return temperature; +} + static void mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data) { @@ -687,7 +854,20 @@ mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data) mdev->phy.chainmask = mdev->phy.antenna_mask; mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G); mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G); - dev->has_eht = cap->eht; +} + +static void +mt7925_mcu_parse_eml_cap(struct mt792x_dev *dev, char *data) +{ + struct mt7925_mcu_eml_cap { + u8 rsv[4]; + __le16 eml_cap; + u8 rsv2[6]; + } __packed * cap; + + cap = (struct mt7925_mcu_eml_cap *)data; + + dev->phy.eml_cap = le16_to_cpu(cap->eml_cap); } static int @@ -744,6 +924,12 @@ mt7925_mcu_get_nic_capability(struct mt792x_dev *dev) case MT_NIC_CAP_PHY: mt7925_mcu_parse_phy_cap(dev, tlv->data); break; + case MT_NIC_CAP_CHIP_CAP: + dev->phy.chip_cap = le64_to_cpu(*(__le64 *)tlv->data); + break; + case MT_NIC_CAP_EML_CAP: + mt7925_mcu_parse_eml_cap(dev, tlv->data); + break; default: break; } @@ -788,6 +974,23 @@ int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable) } EXPORT_SYMBOL_GPL(mt7925_mcu_set_deep_sleep); +int mt7925_mcu_set_thermal_protect(struct mt792x_dev *dev) +{ + char cmd[64]; + int ret = 0; + + snprintf(cmd, sizeof(cmd), "ThermalProtGband %d %d %d %d %d %d %d %d %d %d", + 0, 100, 90, 80, 30, 1, 1, 115, 105, 5); + ret = mt7925_mcu_chip_config(dev, cmd); + + snprintf(cmd, sizeof(cmd), "ThermalProtAband %d %d %d %d %d %d %d %d %d %d", + 1, 100, 90, 80, 30, 1, 1, 115, 105, 5); + ret |= mt7925_mcu_chip_config(dev, cmd); + + return ret; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_set_thermal_protect); + int mt7925_run_firmware(struct mt792x_dev *dev) { int err; @@ -812,8 +1015,9 @@ EXPORT_SYMBOL_GPL(mt7925_run_firmware); static void mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_link_sta *link_sta) { + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct sta_rec_hdr_trans *hdr_trans; struct mt76_wcid *wcid; struct tlv *tlv; @@ -827,7 +1031,16 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, else hdr_trans->from_ds = true; - wcid = (struct mt76_wcid *)sta->drv_priv; + if (link_sta) { + struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + struct mt792x_link_sta *mlink; + + mlink = mt792x_sta_to_link(msta, link_sta->link_id); + wcid = &mlink->wcid; + } else { + wcid = &mvif->sta.deflink.wcid; + } + if (!wcid) return; @@ -840,27 +1053,36 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + int link_id) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta = sta ? &sta->deflink : NULL; + struct mt792x_link_sta *mlink; + struct mt792x_bss_conf *mconf; struct mt792x_sta *msta; struct sk_buff *skb; msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; - skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid, + mlink = mt792x_sta_to_link(msta, link_id); + link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); + mconf = mt792x_vif_to_link(mvif, link_id); + + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76, + &mlink->wcid, MT7925_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* starec hdr trans */ - mt7925_mcu_sta_hdr_trans_tlv(skb, vif, sta); + mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta); return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); } -int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) +int mt7925_mcu_set_tx(struct mt792x_dev *dev, + struct ieee80211_bss_conf *bss_conf) { #define MCU_EDCA_AC_PARAM 0 #define WMM_AIFS_SET BIT(0) @@ -869,12 +1091,12 @@ int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) #define WMM_TXOP_SET BIT(3) #define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \ WMM_CW_MAX_SET | WMM_TXOP_SET) - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(bss_conf); struct { u8 bss_idx; u8 __rsv[3]; } __packed hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }; struct sk_buff *skb; int len = sizeof(hdr) + IEEE80211_NUM_ACS * sizeof(struct edca); @@ -887,7 +1109,7 @@ int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) skb_put_data(skb, &hdr, sizeof(hdr)); for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac]; + struct ieee80211_tx_queue_params *q = &mconf->queue_params[ac]; struct edca *e; struct tlv *tlv; @@ -895,7 +1117,7 @@ int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) e = (struct edca *)tlv; e->set = WMM_PARAM_SET; - e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS; + e->queue = ac; e->aifs = q->aifs; e->txop = cpu_to_le16(q->txop); @@ -919,63 +1141,80 @@ mt7925_mcu_sta_key_tlv(struct mt76_wcid *wcid, struct mt76_connac_sta_key_conf *sta_key_conf, struct sk_buff *skb, struct ieee80211_key_conf *key, - enum set_key_cmd cmd) + enum set_key_cmd cmd, + struct mt792x_sta *msta) { + struct mt792x_vif *mvif = msta->vif; + struct mt792x_bss_conf *mconf = mt792x_vif_to_link(mvif, wcid->link_id); struct sta_rec_sec_uni *sec; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; struct tlv *tlv; - tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); + sta = msta == &mvif->sta ? + NULL : + container_of((void *)msta, struct ieee80211_sta, drv_priv); + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V3, sizeof(*sec)); sec = (struct sta_rec_sec_uni *)tlv; - sec->add = cmd; + sec->bss_idx = mconf->mt76.idx; + sec->is_authenticator = 0; + sec->mgmt_prot = 1; /* only used in MLO mode */ + sec->wlan_idx = (u8)wcid->idx; + + if (sta) { + struct ieee80211_link_sta *link_sta; + + sec->tx_key = 1; + sec->key_type = 1; + link_sta = mt792x_sta_to_link_sta(vif, sta, wcid->link_id); + + if (link_sta) + memcpy(sec->peer_addr, link_sta->addr, ETH_ALEN); + } else { + struct ieee80211_bss_conf *link_conf; + + link_conf = mt792x_vif_to_bss_conf(vif, wcid->link_id); + + if (link_conf) + memcpy(sec->peer_addr, link_conf->bssid, ETH_ALEN); + } if (cmd == SET_KEY) { - struct sec_key_uni *sec_key; u8 cipher; - cipher = mt76_connac_mcu_get_cipher(key->cipher); - if (cipher == MCU_CIPHER_NONE) + sec->add = 1; + cipher = mt7925_mcu_get_cipher(key->cipher); + if (cipher == CONNAC3_CIPHER_NONE) return -EOPNOTSUPP; - sec_key = &sec->key[0]; - sec_key->cipher_len = sizeof(*sec_key); - - if (cipher == MCU_CIPHER_BIP_CMAC_128) { - sec_key->wlan_idx = cpu_to_le16(wcid->idx); - sec_key->cipher_id = MCU_CIPHER_AES_CCMP; - sec_key->key_id = sta_key_conf->keyidx; - sec_key->key_len = 16; - memcpy(sec_key->key, sta_key_conf->key, 16); - - sec_key = &sec->key[1]; - sec_key->wlan_idx = cpu_to_le16(wcid->idx); - sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; - sec_key->cipher_len = sizeof(*sec_key); - sec_key->key_len = 16; - memcpy(sec_key->key, key->key, 16); - sec->n_cipher = 2; + if (cipher == CONNAC3_CIPHER_BIP_CMAC_128) { + sec->cipher_id = CONNAC3_CIPHER_BIP_CMAC_128; + sec->key_id = sta_key_conf->keyidx; + sec->key_len = 32; + memcpy(sec->key, sta_key_conf->key, 16); + memcpy(sec->key + 16, key->key, 16); } else { - sec_key->wlan_idx = cpu_to_le16(wcid->idx); - sec_key->cipher_id = cipher; - sec_key->key_id = key->keyidx; - sec_key->key_len = key->keylen; - memcpy(sec_key->key, key->key, key->keylen); + sec->cipher_id = cipher; + sec->key_id = key->keyidx; + sec->key_len = key->keylen; + memcpy(sec->key, key->key, key->keylen); - if (cipher == MCU_CIPHER_TKIP) { + if (cipher == CONNAC3_CIPHER_TKIP) { /* Rx/Tx MIC keys are swapped */ - memcpy(sec_key->key + 16, key->key + 24, 8); - memcpy(sec_key->key + 24, key->key + 16, 8); + memcpy(sec->key + 16, key->key + 24, 8); + memcpy(sec->key + 24, key->key + 16, 8); } /* store key_conf for BIP batch update */ - if (cipher == MCU_CIPHER_AES_CCMP) { + if (cipher == CONNAC3_CIPHER_AES_CCMP) { memcpy(sta_key_conf->key, key->key, key->keylen); sta_key_conf->keyidx = key->keyidx; } - - sec->n_cipher = 1; } } else { - sec->n_cipher = 0; + sec->add = 0; } return 0; @@ -984,25 +1223,128 @@ mt7925_mcu_sta_key_tlv(struct mt76_wcid *wcid, 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) + struct mt76_wcid *wcid, enum set_key_cmd cmd, + struct mt792x_sta *msta) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_vif_to_link(mvif, wcid->link_id); struct sk_buff *skb; int ret; - skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, + skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, wcid, MT7925_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); - ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd); + ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd, msta); if (ret) return ret; return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true); } -int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, +int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, + int duration, u8 token_id) +{ + struct mt792x_vif *mvif = mconf->vif; + struct ieee80211_vif *vif = container_of((void *)mvif, + struct ieee80211_vif, drv_priv); + struct ieee80211_bss_conf *link_conf; + struct ieee80211_channel *chan; + const u8 ch_band[] = { + [NL80211_BAND_2GHZ] = 1, + [NL80211_BAND_5GHZ] = 2, + [NL80211_BAND_6GHZ] = 3, + }; + enum mt7925_roc_req type; + int center_ch, i = 0; + bool is_AG_band = false; + struct { + u8 id; + u8 bss_idx; + u16 tag; + struct mt792x_bss_conf *mconf; + struct ieee80211_channel *chan; + } links[2]; + + struct { + struct { + u8 rsv[4]; + } __packed hdr; + struct roc_acquire_tlv roc[2]; + } __packed req = { + .roc[0].tag = cpu_to_le16(UNI_ROC_NUM), + .roc[0].len = cpu_to_le16(sizeof(struct roc_acquire_tlv)), + .roc[1].tag = cpu_to_le16(UNI_ROC_NUM), + .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv)) + }; + + if (!mconf || hweight16(vif->valid_links) < 2 || + hweight16(sel_links) != 2) + return -EPERM; + + for (i = 0; i < ARRAY_SIZE(links); i++) { + links[i].id = i ? __ffs(~BIT(mconf->link_id) & sel_links) : + mconf->link_id; + link_conf = mt792x_vif_to_bss_conf(vif, links[i].id); + if (WARN_ON_ONCE(!link_conf)) + return -EPERM; + + links[i].chan = link_conf->chanreq.oper.chan; + if (WARN_ON_ONCE(!links[i].chan)) + return -EPERM; + + links[i].mconf = mt792x_vif_to_link(mvif, links[i].id); + links[i].tag = links[i].id == mconf->link_id ? + UNI_ROC_ACQUIRE : UNI_ROC_SUB_LINK; + + is_AG_band |= links[i].chan->band == NL80211_BAND_2GHZ; + } + + if (vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP) + type = is_AG_band ? MT7925_ROC_REQ_MLSR_AG : + MT7925_ROC_REQ_MLSR_AA; + else + type = MT7925_ROC_REQ_JOIN; + + for (i = 0; i < ARRAY_SIZE(links) && i < hweight16(vif->active_links); i++) { + if (WARN_ON_ONCE(!links[i].mconf || !links[i].chan)) + continue; + + chan = links[i].chan; + center_ch = ieee80211_frequency_to_channel(chan->center_freq); + req.roc[i].len = cpu_to_le16(sizeof(struct roc_acquire_tlv)); + req.roc[i].tag = cpu_to_le16(links[i].tag); + req.roc[i].tokenid = token_id; + req.roc[i].reqtype = type; + req.roc[i].maxinterval = cpu_to_le32(duration); + req.roc[i].bss_idx = links[i].mconf->mt76.idx; + req.roc[i].control_channel = chan->hw_value; + req.roc[i].bw = CMD_CBW_20MHZ; + req.roc[i].bw_from_ap = CMD_CBW_20MHZ; + req.roc[i].center_chan = center_ch; + req.roc[i].center_chan_from_ap = center_ch; + req.roc[i].center_chan2 = 0; + req.roc[i].center_chan2_from_ap = 0; + + /* STR : 0xfe indicates BAND_ALL with enabling DBDC + * EMLSR : 0xff indicates (BAND_AUTO) without DBDC + */ + req.roc[i].dbdcband = type == MT7925_ROC_REQ_JOIN ? 0xfe : 0xff; + + if (chan->hw_value < center_ch) + req.roc[i].sco = 1; /* SCA */ + else if (chan->hw_value > center_ch) + req.roc[i].sco = 3; /* SCB */ + + req.roc[i].band = ch_band[chan->band]; + } + + return mt76_mcu_send_msg(&mvif->phy->dev->mt76, MCU_UNI_CMD(ROC), + &req, sizeof(req), true); +} + +int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, struct ieee80211_channel *chan, int duration, enum mt7925_roc_req type, u8 token_id) { @@ -1012,25 +1354,7 @@ int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct { u8 rsv[4]; } __packed hdr; - struct roc_acquire_tlv { - __le16 tag; - __le16 len; - u8 bss_idx; - u8 tokenid; - u8 control_channel; - u8 sco; - u8 band; - u8 bw; - u8 center_chan; - u8 center_chan2; - u8 bw_from_ap; - u8 center_chan_from_ap; - u8 center_chan2_from_ap; - u8 reqtype; - __le32 maxinterval; - u8 dbdcband; - u8 rsv[3]; - } __packed roc; + struct roc_acquire_tlv roc; } __packed req = { .roc = { .tag = cpu_to_le16(UNI_ROC_ACQUIRE), @@ -1038,7 +1362,7 @@ int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, .tokenid = token_id, .reqtype = type, .maxinterval = cpu_to_le32(duration), - .bss_idx = vif->mt76.idx, + .bss_idx = mconf->mt76.idx, .control_channel = chan->hw_value, .bw = CMD_CBW_20MHZ, .bw_from_ap = CMD_CBW_20MHZ, @@ -1066,10 +1390,10 @@ int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, } return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC), - &req, sizeof(req), false); + &req, sizeof(req), true); } -int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, +int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, u8 token_id) { struct mt792x_dev *dev = phy->dev; @@ -1090,86 +1414,12 @@ int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, .tag = cpu_to_le16(UNI_ROC_ABORT), .len = cpu_to_le16(sizeof(struct roc_abort_tlv)), .tokenid = token_id, - .bss_idx = vif->mt76.idx, + .bss_idx = mconf->mt76.idx, .dbdcband = 0xff, /* auto*/ }, }; return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC), - &req, sizeof(req), false); -} - -int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag) -{ - static const u8 ch_band[] = { - [NL80211_BAND_2GHZ] = 0, - [NL80211_BAND_5GHZ] = 1, - [NL80211_BAND_6GHZ] = 2, - }; - struct mt792x_dev *dev = phy->dev; - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; - int freq1 = chandef->center_freq1; - u8 band_idx = chandef->chan->band != NL80211_BAND_2GHZ; - struct { - /* fixed field */ - u8 __rsv[4]; - - __le16 tag; - __le16 len; - u8 control_ch; - u8 center_ch; - u8 bw; - u8 tx_path_num; - u8 rx_path; /* mask or num */ - u8 switch_reason; - u8 band_idx; - u8 center_ch2; /* for 80+80 only */ - __le16 cac_case; - u8 channel_band; - u8 rsv0; - __le32 outband_freq; - u8 txpower_drop; - u8 ap_bw; - u8 ap_center_ch; - u8 rsv1[53]; - } __packed req = { - .tag = cpu_to_le16(tag), - .len = cpu_to_le16(sizeof(req) - 4), - .control_ch = chandef->chan->hw_value, - .center_ch = ieee80211_frequency_to_channel(freq1), - .bw = mt76_connac_chan_bw(chandef), - .tx_path_num = hweight8(phy->mt76->antenna_mask), - .rx_path = phy->mt76->antenna_mask, - .band_idx = band_idx, - .channel_band = ch_band[chandef->chan->band], - }; - - if (chandef->chan->band == NL80211_BAND_6GHZ) - req.channel_band = 2; - else - req.channel_band = chandef->chan->band; - - if (tag == UNI_CHANNEL_RX_PATH || - dev->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; - else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, - NL80211_IFTYPE_AP)) - req.switch_reason = CH_SWITCH_DFS; - else - req.switch_reason = CH_SWITCH_NORMAL; - - if (tag == UNI_CHANNEL_SWITCH) - req.rx_path = hweight8(req.rx_path); - - if (chandef->width == NL80211_CHAN_WIDTH_80P80) { - int freq2 = chandef->center_freq2; - - req.center_ch2 = ieee80211_frequency_to_channel(freq2); - } - - return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(CHANNEL_SWITCH), &req, sizeof(req), true); } @@ -1191,13 +1441,14 @@ int mt7925_mcu_set_eeprom(struct mt792x_dev *dev) }; return mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(EFUSE_CTRL), - &req, sizeof(req), false, NULL); + &req, sizeof(req), true, NULL); } EXPORT_SYMBOL_GPL(mt7925_mcu_set_eeprom); -int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) +int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); struct { struct { u8 bss_idx; @@ -1216,27 +1467,27 @@ int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) } __packed ps; } __packed ps_req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }, .ps = { .tag = cpu_to_le16(UNI_BSS_INFO_PS), .len = cpu_to_le16(sizeof(struct ps_tlv)), - .ps_state = vif->cfg.ps ? 2 : 0, + .ps_state = link_conf->vif->cfg.ps ? 2 : 0, }, }; - if (vif->type != NL80211_IFTYPE_STATION) + if (link_conf->vif->type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), &ps_req, sizeof(ps_req), true); } -static int -mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, - bool enable) +int +mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf, bool enable) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); struct { struct { u8 bss_idx; @@ -1253,17 +1504,17 @@ mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, } __packed bcnft; } __packed bcnft_req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }, .bcnft = { .tag = cpu_to_le16(UNI_BSS_INFO_BCNFT), .len = cpu_to_le16(sizeof(struct bcnft_tlv)), - .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), - .dtim_period = vif->bss_conf.dtim_period, + .bcn_interval = cpu_to_le16(link_conf->beacon_int), + .dtim_period = link_conf->dtim_period, }, }; - if (vif->type != NL80211_IFTYPE_STATION) + if (link_conf->vif->type != NL80211_IFTYPE_STATION) return 0; return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), @@ -1271,10 +1522,11 @@ mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, } int -mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, +mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf, bool enable) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); struct { struct { u8 bss_idx; @@ -1291,13 +1543,13 @@ mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, } __packed enable; } req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }, .enable = { .tag = cpu_to_le16(UNI_BSS_INFO_BCNFT), .len = cpu_to_le16(sizeof(struct bcnft_tlv)), - .dtim_period = vif->bss_conf.dtim_period, - .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), + .dtim_period = link_conf->dtim_period, + .bcn_interval = cpu_to_le16(link_conf->beacon_int), }, }; struct { @@ -1311,7 +1563,7 @@ mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, } __packed disable; } req1 = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mconf->mt76.idx, }, .disable = { .tag = cpu_to_le16(UNI_BSS_INFO_PM_DISABLE), @@ -1321,51 +1573,52 @@ mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, int err; err = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), - &req1, sizeof(req1), false); + &req1, sizeof(req1), true); if (err < 0 || !enable) return err; return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), - &req, sizeof(req), false); + &req, sizeof(req), true); } static void -mt7925_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7925_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { - if (!sta->deflink.he_cap.has_he) + if (!link_sta->he_cap.has_he) return; - mt76_connac_mcu_sta_he_tlv_v2(skb, sta); + mt76_connac_mcu_sta_he_tlv_v2(skb, link_sta->sta); } static void -mt7925_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7925_mcu_sta_he_6g_tlv(struct sk_buff *skb, + struct ieee80211_link_sta *link_sta) { struct sta_rec_he_6g_capa *he_6g; struct tlv *tlv; - if (!sta->deflink.he_6ghz_capa.capa) + if (!link_sta->he_6ghz_capa.capa) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G, sizeof(*he_6g)); he_6g = (struct sta_rec_he_6g_capa *)tlv; - he_6g->capa = sta->deflink.he_6ghz_capa.capa; + he_6g->capa = link_sta->he_6ghz_capa.capa; } static void -mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { struct ieee80211_eht_mcs_nss_supp *mcs_map; struct ieee80211_eht_cap_elem_fixed *elem; struct sta_rec_eht *eht; struct tlv *tlv; - if (!sta->deflink.eht_cap.has_eht) + if (!link_sta->eht_cap.has_eht) return; - mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp; - elem = &sta->deflink.eht_cap.eht_cap_elem; + mcs_map = &link_sta->eht_cap.eht_mcs_nss_supp; + elem = &link_sta->eht_cap.eht_cap_elem; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht)); @@ -1375,50 +1628,52 @@ mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info); eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]); - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20)); memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80)); memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160)); } static void -mt7925_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7925_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { struct sta_rec_ht *ht; struct tlv *tlv; - if (!sta->deflink.ht_cap.ht_supported) + if (!link_sta->ht_cap.ht_supported) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; - ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap); + ht->ht_cap = cpu_to_le16(link_sta->ht_cap.cap); } static void -mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { struct sta_rec_vht *vht; struct tlv *tlv; /* For 6G band, this tlv is necessary to let hw work normally */ - if (!sta->deflink.he_6ghz_capa.capa && !sta->deflink.vht_cap.vht_supported) + if (!link_sta->he_6ghz_capa.capa && !link_sta->vht_cap.vht_supported) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); vht = (struct sta_rec_vht *)tlv; - vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap); - vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; - vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(link_sta->vht_cap.cap); + vht->vht_rx_mcs_map = link_sta->vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = link_sta->vht_cap.vht_mcs.tx_mcs_map; } static void mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) { - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + struct mt792x_link_sta *mlink; struct sta_rec_amsdu *amsdu; struct tlv *tlv; @@ -1426,16 +1681,18 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, vif->type != NL80211_IFTYPE_AP) return; - if (!sta->deflink.agg.max_amsdu_len) + if (!link_sta->agg.max_amsdu_len) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct sta_rec_amsdu *)tlv; amsdu->max_amsdu_num = 8; amsdu->amsdu_en = true; - msta->wcid.amsdu = true; - switch (sta->deflink.agg.max_amsdu_len) { + mlink = mt792x_sta_to_link(msta, link_sta->link_id); + mlink->wcid.amsdu = true; + + switch (link_sta->agg.max_amsdu_len) { case IEEE80211_MAX_MPDU_LEN_VHT_11454: amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; @@ -1452,36 +1709,44 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, static void mt7925_mcu_sta_phy_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &mvif->mt76.ctx->def; + struct ieee80211_bss_conf *link_conf; + struct cfg80211_chan_def *chandef; + struct mt792x_bss_conf *mconf; struct sta_rec_phy *phy; struct tlv *tlv; u8 af = 0, mm = 0; - if (!sta->deflink.ht_cap.ht_supported && !sta->deflink.he_6ghz_capa.capa) - return; + link_conf = mt792x_vif_to_bss_conf(vif, link_sta->link_id); + mconf = mt792x_vif_to_link(mvif, link_sta->link_id); + chandef = mconf->mt76.ctx ? &mconf->mt76.ctx->def : + &link_conf->chanreq.oper; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy)); phy = (struct sta_rec_phy *)tlv; - phy->phy_type = mt76_connac_get_phy_mode_v2(mvif->phy->mt76, vif, chandef->chan->band, sta); - if (sta->deflink.ht_cap.ht_supported) { - af = sta->deflink.ht_cap.ampdu_factor; - mm = sta->deflink.ht_cap.ampdu_density; + phy->phy_type = mt76_connac_get_phy_mode_v2(mvif->phy->mt76, vif, + chandef->chan->band, + link_sta); + phy->basic_rate = cpu_to_le16((u16)link_conf->basic_rates); + if (link_sta->ht_cap.ht_supported) { + af = link_sta->ht_cap.ampdu_factor; + mm = link_sta->ht_cap.ampdu_density; } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { u8 vht_af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->deflink.vht_cap.cap); + link_sta->vht_cap.cap); af = max_t(u8, af, vht_af); } - if (sta->deflink.he_6ghz_capa.capa) { - af = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + if (link_sta->he_6ghz_capa.capa) { + af = le16_get_bits(link_sta->he_6ghz_capa.capa, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); - mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + mm = le16_get_bits(link_sta->he_6ghz_capa.capa, IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); } @@ -1492,7 +1757,7 @@ mt7925_mcu_sta_phy_tlv(struct sk_buff *skb, static void mt7925_mcu_sta_state_v2_tlv(struct mt76_phy *mphy, struct sk_buff *skb, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, struct ieee80211_vif *vif, u8 rcpi, u8 sta_state) { @@ -1512,28 +1777,37 @@ mt7925_mcu_sta_state_v2_tlv(struct mt76_phy *mphy, struct sk_buff *skb, state = (struct sta_rec_state_v2 *)tlv; state->state = sta_state; - if (sta->deflink.vht_cap.vht_supported) { - state->vht_opmode = sta->deflink.bandwidth; - state->vht_opmode |= sta->deflink.rx_nss << + if (link_sta->vht_cap.vht_supported) { + state->vht_opmode = link_sta->bandwidth; + state->vht_opmode |= link_sta->rx_nss << IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; } } static void mt7925_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &mvif->mt76.ctx->def; - enum nl80211_band band = chandef->chan->band; + struct ieee80211_bss_conf *link_conf; + struct cfg80211_chan_def *chandef; struct sta_rec_ra_info *ra_info; + struct mt792x_bss_conf *mconf; + enum nl80211_band band; struct tlv *tlv; u16 supp_rates; + link_conf = mt792x_vif_to_bss_conf(vif, link_sta->link_id); + mconf = mt792x_vif_to_link(mvif, link_sta->link_id); + chandef = mconf->mt76.ctx ? &mconf->mt76.ctx->def : + &link_conf->chanreq.oper; + band = chandef->chan->band; + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); ra_info = (struct sta_rec_ra_info *)tlv; - supp_rates = sta->deflink.supp_rates[band]; + supp_rates = link_sta->supp_rates[band]; if (band == NL80211_BAND_2GHZ) supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) | FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf); @@ -1542,99 +1816,155 @@ mt7925_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, ra_info->legacy = cpu_to_le16(supp_rates); - if (sta->deflink.ht_cap.ht_supported) + if (link_sta->ht_cap.ht_supported) memcpy(ra_info->rx_mcs_bitmask, - sta->deflink.ht_cap.mcs.rx_mask, + link_sta->ht_cap.mcs.rx_mask, HT_MCS_MASK_NUM); } static void +mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct wiphy *wiphy = mvif->phy->mt76->hw->wiphy; + const struct wiphy_iftype_ext_capab *ext_capa; + struct sta_rec_eht_mld *eht_mld; + struct tlv *tlv; + u16 eml_cap; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld)); + eht_mld = (struct sta_rec_eht_mld *)tlv; + eht_mld->mld_type = 0xff; + + if (!ieee80211_vif_is_mld(vif)) + return; + + ext_capa = cfg80211_get_iftype_ext_capa(wiphy, + ieee80211_vif_type_p2p(vif)); + if (!ext_capa) + return; + + eml_cap = (vif->cfg.eml_cap & (IEEE80211_EML_CAP_EMLSR_SUPP | + IEEE80211_EML_CAP_TRANSITION_TIMEOUT)) | + (ext_capa->eml_capabilities & (IEEE80211_EML_CAP_EMLSR_PADDING_DELAY | + IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY)); + + if (eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP) { + eht_mld->eml_cap[0] = u16_get_bits(eml_cap, GENMASK(7, 0)); + eht_mld->eml_cap[1] = u16_get_bits(eml_cap, GENMASK(15, 8)); + } else { + eht_mld->str_cap[0] = BIT(1); + } +} + +static void mt7925_mcu_sta_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + unsigned long valid = mvif->valid_links; + struct mt792x_bss_conf *mconf; + struct mt792x_link_sta *mlink; struct sta_rec_mld *mld; struct tlv *tlv; + int i, cnt = 0; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld)); mld = (struct sta_rec_mld *)tlv; - memcpy(mld->mac_addr, vif->addr, ETH_ALEN); - mld->primary_id = cpu_to_le16(wcid->idx); - mld->wlan_id = cpu_to_le16(wcid->idx); + memcpy(mld->mac_addr, sta->addr, ETH_ALEN); + mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx); + mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx); + mld->link_num = min_t(u8, hweight16(mvif->valid_links), 2); - /* TODO: 0 means deflink only, add secondary link(1) later */ - mld->link_num = !!(hweight8(vif->active_links) > 1); - WARN_ON_ONCE(mld->link_num); + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + if (cnt == mld->link_num) + break; + + mconf = mt792x_vif_to_link(mvif, i); + mlink = mt792x_sta_to_link(msta, i); + mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx); + mld->link[cnt++].bss_idx = mconf->mt76.idx; + + if (mlink != &msta->deflink) + mld->secondary_id = cpu_to_le16(mlink->wcid.idx); + } +} + +static void +mt7925_mcu_sta_remove_tlv(struct sk_buff *skb) +{ + struct sta_rec_remove *rem; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, 0x25, sizeof(*rem)); + rem = (struct sta_rec_remove *)tlv; + rem->action = 0; } static int mt7925_mcu_sta_cmd(struct mt76_phy *phy, struct mt76_sta_cmd_info *info) { - struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv; struct mt76_dev *dev = phy->dev; - struct wtbl_req_hdr *wtbl_hdr; - struct tlv *sta_wtbl; + struct mt792x_bss_conf *mconf; struct sk_buff *skb; - skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid, + mconf = mt792x_vif_to_link(mvif, info->wcid->link_id); + + skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid, MT7925_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); - if (info->sta || !info->offload_fw) - mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta, + if (info->enable && info->link_sta) { + mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, + info->link_sta, info->enable, info->newly); - if (info->sta && info->enable) { - mt7925_mcu_sta_phy_tlv(skb, info->vif, info->sta); - mt7925_mcu_sta_ht_tlv(skb, info->sta); - mt7925_mcu_sta_vht_tlv(skb, info->sta); - mt76_connac_mcu_sta_uapsd(skb, info->vif, info->sta); - mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->sta); - mt7925_mcu_sta_he_tlv(skb, info->sta); - mt7925_mcu_sta_he_6g_tlv(skb, info->sta); - mt7925_mcu_sta_eht_tlv(skb, info->sta); - mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif, info->sta); - mt7925_mcu_sta_state_v2_tlv(phy, skb, info->sta, + mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta); + mt7925_mcu_sta_ht_tlv(skb, info->link_sta); + mt7925_mcu_sta_vht_tlv(skb, info->link_sta); + mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta); + mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta); + mt7925_mcu_sta_he_tlv(skb, info->link_sta); + mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta); + mt7925_mcu_sta_eht_tlv(skb, info->link_sta); + mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif, + info->link_sta); + mt7925_mcu_sta_state_v2_tlv(phy, skb, info->link_sta, info->vif, info->rcpi, info->state); - mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->sta); - mt7925_mcu_sta_mld_tlv(skb, info->vif, info->sta); - } - - sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, - sizeof(struct tlv)); - wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid, - WTBL_RESET_AND_SET, - sta_wtbl, &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); + if (info->state != MT76_STA_INFO_STATE_NONE) { + mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta); + mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta); + } + } - if (info->enable) { - mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif, - info->sta, sta_wtbl, - wtbl_hdr); - mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid, - sta_wtbl, wtbl_hdr); - if (info->sta) - mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, - sta_wtbl, wtbl_hdr, - true, true); + if (!info->enable) { + mt7925_mcu_sta_remove_tlv(skb); + mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, + sizeof(struct tlv)); + } else { + mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta); } return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); } -int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, +int mt7925_mcu_sta_update(struct mt792x_dev *dev, + struct ieee80211_link_sta *link_sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - int rssi = -ewma_rssi_read(&mvif->rssi); + int rssi = -ewma_rssi_read(&mvif->bss_conf.rssi); struct mt76_sta_cmd_info info = { - .sta = sta, + .link_sta = link_sta, .vif = vif, + .link_conf = &vif->bss_conf, .enable = enable, .cmd = MCU_UNI_CMD(STA_REC_UPDATE), .state = state, @@ -1642,10 +1972,14 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, .rcpi = to_rcpi(rssi), }; struct mt792x_sta *msta; + struct mt792x_link_sta *mlink; - msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL; - info.wcid = msta ? &msta->wcid : &mvif->sta.wcid; - info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true; + if (link_sta) { + msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + mlink = mt792x_sta_to_link(msta, link_sta->link_id); + } + info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid; + info.newly = state != MT76_STA_INFO_STATE_ASSOC; return mt7925_mcu_sta_cmd(&dev->mphy, &info); } @@ -1659,8 +1993,8 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, int err = 0; if (enable) { - err = mt7925_mcu_uni_bss_bcnft(dev, vif, true); - if (err) + err = mt7925_mcu_uni_bss_bcnft(dev, &vif->bss_conf, true); + if (err < 0) return err; return mt7925_mcu_set_rxfilter(dev, 0, @@ -1668,8 +2002,8 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, MT_WF_RFCR_DROP_OTHER_BEACON); } - err = mt7925_mcu_set_bss_pm(dev, vif, false); - if (err) + err = mt7925_mcu_set_bss_pm(dev, &vif->bss_conf, false); + if (err < 0) return err; return mt7925_mcu_set_rxfilter(dev, 0, @@ -1707,8 +2041,6 @@ int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, struct mt7925_txp int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct { struct { u8 band_idx; @@ -1722,7 +2054,7 @@ int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, } __packed enable; } __packed req = { .hdr = { - .band_idx = mvif->mt76.band_idx, + .band_idx = 0, }, .enable = { .tag = cpu_to_le16(UNI_SNIFFER_ENABLE), @@ -1731,8 +2063,6 @@ int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, }, }; - mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true); - return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true); } @@ -1744,12 +2074,12 @@ int mt7925_mcu_config_sniffer(struct mt792x_vif *vif, struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &mphy->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; - const u8 ch_band[] = { + static const u8 ch_band[] = { [NL80211_BAND_2GHZ] = 1, [NL80211_BAND_5GHZ] = 2, [NL80211_BAND_6GHZ] = 3, }; - const u8 ch_width[] = { + static const u8 ch_width[] = { [NL80211_CHAN_WIDTH_20_NOHT] = 0, [NL80211_CHAN_WIDTH_20] = 0, [NL80211_CHAN_WIDTH_40] = 0, @@ -1781,7 +2111,7 @@ int mt7925_mcu_config_sniffer(struct mt792x_vif *vif, } __packed tlv; } __packed req = { .hdr = { - .band_idx = vif->mt76.band_idx, + .band_idx = 0, }, .tlv = { .tag = cpu_to_le16(UNI_SNIFFER_CONFIG), @@ -1842,7 +2172,7 @@ mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, } __packed beacon_tlv; } req = { .hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = mvif->bss_conf.mt76.idx, }, .beacon_tlv = { .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), @@ -1894,87 +2224,80 @@ mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, &req, sizeof(req), true); } -int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif, - struct ieee80211_chanctx_conf *ctx) +static +void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) { - struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : + &link_conf->chanreq.oper; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; enum nl80211_band band = chandef->chan->band; - struct mt76_dev *mdev = phy->dev; - struct { - struct { - u8 bss_idx; - u8 pad[3]; - } __packed hdr; - struct rlm_tlv { - __le16 tag; - __le16 len; - u8 control_channel; - u8 center_chan; - u8 center_chan2; - u8 bw; - u8 tx_streams; - u8 rx_streams; - u8 ht_op_info; - u8 sco; - u8 band; - u8 pad[3]; - } __packed rlm; - } __packed rlm_req = { - .hdr = { - .bss_idx = mvif->idx, - }, - .rlm = { - .tag = cpu_to_le16(UNI_BSS_INFO_RLM), - .len = cpu_to_le16(sizeof(struct rlm_tlv)), - .control_channel = chandef->chan->hw_value, - .center_chan = ieee80211_frequency_to_channel(freq1), - .center_chan2 = ieee80211_frequency_to_channel(freq2), - .tx_streams = hweight8(phy->antenna_mask), - .ht_op_info = 4, /* set HT 40M allowed */ - .rx_streams = hweight8(phy->antenna_mask), - .band = band, - }, - }; + struct bss_rlm_tlv *req; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_RLM, sizeof(*req)); + req = (struct bss_rlm_tlv *)tlv; + req->control_channel = chandef->chan->hw_value; + req->center_chan = ieee80211_frequency_to_channel(freq1); + req->center_chan2 = 0; + req->tx_streams = hweight8(phy->antenna_mask); + req->ht_op_info = 4; /* set HT 40M allowed */ + req->rx_streams = hweight8(phy->antenna_mask); + req->center_chan2 = 0; + req->sco = 0; + req->band = 1; + + switch (band) { + case NL80211_BAND_2GHZ: + req->band = 1; + break; + case NL80211_BAND_5GHZ: + req->band = 2; + break; + case NL80211_BAND_6GHZ: + req->band = 3; + break; + default: + break; + } switch (chandef->width) { case NL80211_CHAN_WIDTH_40: - rlm_req.rlm.bw = CMD_CBW_40MHZ; + req->bw = CMD_CBW_40MHZ; break; case NL80211_CHAN_WIDTH_80: - rlm_req.rlm.bw = CMD_CBW_80MHZ; + req->bw = CMD_CBW_80MHZ; break; case NL80211_CHAN_WIDTH_80P80: - rlm_req.rlm.bw = CMD_CBW_8080MHZ; + req->bw = CMD_CBW_8080MHZ; + req->center_chan2 = ieee80211_frequency_to_channel(freq2); break; case NL80211_CHAN_WIDTH_160: - rlm_req.rlm.bw = CMD_CBW_160MHZ; + req->bw = CMD_CBW_160MHZ; break; case NL80211_CHAN_WIDTH_5: - rlm_req.rlm.bw = CMD_CBW_5MHZ; + req->bw = CMD_CBW_5MHZ; break; case NL80211_CHAN_WIDTH_10: - rlm_req.rlm.bw = CMD_CBW_10MHZ; + req->bw = CMD_CBW_10MHZ; break; case NL80211_CHAN_WIDTH_20_NOHT: case NL80211_CHAN_WIDTH_20: default: - rlm_req.rlm.bw = CMD_CBW_20MHZ; - rlm_req.rlm.ht_op_info = 0; + req->bw = CMD_CBW_20MHZ; + req->ht_op_info = 0; break; } - if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan) - rlm_req.rlm.sco = 1; /* SCA */ - else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan) - rlm_req.rlm.sco = 3; /* SCB */ - - return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req, - sizeof(rlm_req), true); + if (req->control_channel < req->center_chan) + req->sco = 1; /* SCA */ + else if (req->control_channel > req->center_chan) + req->sco = 3; /* SCB */ } static struct sk_buff * -__mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len) +__mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int len) { struct bss_req_hdr hdr = { .bss_idx = mvif->idx, @@ -1990,18 +2313,70 @@ __mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len) return skb; } +static +void mt7925_mcu_bss_eht_tlv(struct sk_buff *skb, struct mt76_phy *phy, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : + &link_conf->chanreq.oper; + + struct bss_eht_tlv *req; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_EHT, sizeof(*req)); + req = (struct bss_eht_tlv *)tlv; + req->is_eth_dscb_present = chandef->punctured ? 1 : 0; + req->eht_dis_sub_chan_bitmap = cpu_to_le16(chandef->punctured); +} + +int mt7925_mcu_set_eht_pp(struct mt76_phy *phy, struct mt76_vif_link *mvif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct sk_buff *skb; + + skb = __mt7925_mcu_alloc_bss_req(phy->dev, mvif, + MT7925_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7925_mcu_bss_eht_tlv(skb, phy, link_conf, ctx); + + return mt76_mcu_skb_send_msg(phy->dev, skb, + MCU_UNI_CMD(BSS_INFO_UPDATE), true); +} + +int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct sk_buff *skb; + + skb = __mt7925_mcu_alloc_bss_req(phy->dev, mvif, + MT7925_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7925_mcu_bss_rlm_tlv(skb, phy, link_conf, ctx); + + return mt76_mcu_skb_send_msg(phy->dev, skb, + MCU_UNI_CMD(BSS_INFO_UPDATE), true); +} + static u8 mt7925_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, - enum nl80211_band band, struct ieee80211_sta *sta) + enum nl80211_band band, + struct ieee80211_link_sta *link_sta) { struct ieee80211_he_6ghz_capa *he_6ghz_capa; const struct ieee80211_sta_eht_cap *eht_cap; __le16 capa = 0; u8 mode = 0; - if (sta) { - he_6ghz_capa = &sta->deflink.he_6ghz_capa; - eht_cap = &sta->deflink.eht_cap; + if (link_sta) { + he_6ghz_capa = &link_sta->he_6ghz_capa; + eht_cap = &link_sta->eht_cap; } else { struct ieee80211_supported_band *sband; @@ -2037,43 +2412,59 @@ mt7925_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, static void mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, struct ieee80211_chanctx_conf *ctx, struct mt76_phy *phy, u16 wlan_idx, bool enable) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : - &mvif->sta; - struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; + struct ieee80211_vif *vif = link_conf->vif; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : + &link_conf->chanreq.oper; enum nl80211_band band = chandef->chan->band; struct mt76_connac_bss_basic_tlv *basic_req; - u8 idx, basic_phy; + struct mt792x_link_sta *mlink; struct tlv *tlv; int conn_type; + u8 idx; tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*basic_req)); basic_req = (struct mt76_connac_bss_basic_tlv *)tlv; - idx = mvif->mt76.omac_idx > EXT_BSSID_START ? HW_BSSID_0 : - mvif->mt76.omac_idx; + idx = mconf->mt76.omac_idx > EXT_BSSID_START ? HW_BSSID_0 : + mconf->mt76.omac_idx; basic_req->hw_bss_idx = idx; - basic_req->phymode_ext = mt7925_get_phy_mode_ext(phy, vif, band, sta); + basic_req->phymode_ext = mt7925_get_phy_mode_ext(phy, vif, band, + link_sta); - basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, sta); - basic_req->nonht_basic_phy = cpu_to_le16(basic_phy); + if (band == NL80211_BAND_2GHZ) + basic_req->nonht_basic_phy = cpu_to_le16(PHY_TYPE_ERP_INDEX); + else + basic_req->nonht_basic_phy = cpu_to_le16(PHY_TYPE_OFDM_INDEX); - memcpy(basic_req->bssid, vif->bss_conf.bssid, ETH_ALEN); - basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, sta); - basic_req->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - basic_req->dtim_period = vif->bss_conf.dtim_period; + memcpy(basic_req->bssid, link_conf->bssid, ETH_ALEN); + basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta); + basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int); + basic_req->dtim_period = link_conf->dtim_period; basic_req->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); - basic_req->sta_idx = cpu_to_le16(msta->wcid.idx); - basic_req->omac_idx = mvif->mt76.omac_idx; - basic_req->band_idx = mvif->mt76.band_idx; - basic_req->wmm_idx = mvif->mt76.wmm_idx; + basic_req->link_idx = mconf->mt76.idx; + + if (link_sta) { + struct mt792x_sta *msta; + + msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + mlink = mt792x_sta_to_link(msta, link_sta->link_id); + + } else { + mlink = &mconf->vif->sta.deflink; + } + + basic_req->sta_idx = cpu_to_le16(mlink->wcid.idx); + basic_req->omac_idx = mconf->mt76.omac_idx; + basic_req->band_idx = mconf->mt76.band_idx; + basic_req->wmm_idx = mconf->mt76.wmm_idx; basic_req->conn_state = !enable; switch (vif->type) { @@ -2105,9 +2496,11 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, } static void -mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, + struct ieee80211_bss_conf *link_conf) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct mt76_vif_link *mvif = &mconf->mt76; struct bss_sec_tlv { __le16 tag; __le16 len; @@ -2122,21 +2515,21 @@ mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) sec = (struct bss_sec_tlv *)tlv; switch (mvif->cipher) { - case MCU_CIPHER_GCMP_256: - case MCU_CIPHER_GCMP: + case CONNAC3_CIPHER_GCMP_256: + case CONNAC3_CIPHER_GCMP: sec->mode = MODE_WPA3_SAE; sec->status = 8; break; - case MCU_CIPHER_AES_CCMP: + case CONNAC3_CIPHER_AES_CCMP: sec->mode = MODE_WPA2_PSK; sec->status = 6; break; - case MCU_CIPHER_TKIP: + case CONNAC3_CIPHER_TKIP: sec->mode = MODE_WPA2_PSK; sec->status = 4; break; - case MCU_CIPHER_WEP104: - case MCU_CIPHER_WEP40: + case CONNAC3_CIPHER_WEP104: + case CONNAC3_CIPHER_WEP40: sec->mode = MODE_SHARED; sec->status = 0; break; @@ -2152,12 +2545,13 @@ mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) static void mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy, struct ieee80211_chanctx_conf *ctx, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_bss_conf *link_conf) { - struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->mt76->chandef; - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : + &link_conf->chanreq.oper; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); enum nl80211_band band = chandef->chan->band; + struct mt76_vif_link *mvif = &mconf->mt76; struct bss_rate_tlv *bmc; struct tlv *tlv; u8 idx = mvif->mcast_rates_idx ? @@ -2167,6 +2561,11 @@ mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy, bmc = (struct bss_rate_tlv *)tlv; + if (band == NL80211_BAND_2GHZ) + bmc->basic_rate = cpu_to_le16(HR_DSSS_ERP_BASIC_RATE); + else + bmc->basic_rate = cpu_to_le16(OFDM_BASIC_RATE); + bmc->short_preamble = (band == NL80211_BAND_2GHZ); bmc->bc_fixed_rate = idx; bmc->mc_fixed_rate = idx; @@ -2174,39 +2573,51 @@ mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy, static void mt7925_mcu_bss_mld_tlv(struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_bss_conf *link_conf) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - bool is_mld = ieee80211_vif_is_mld(vif); + struct ieee80211_vif *vif = link_conf->vif; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv; + struct mt792x_phy *phy = mvif->phy; struct bss_mld_tlv *mld; struct tlv *tlv; + bool is_mld; + + is_mld = ieee80211_vif_is_mld(link_conf->vif) || + (hweight16(mvif->valid_links) > 1); tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_MLD, sizeof(*mld)); mld = (struct bss_mld_tlv *)tlv; - mld->link_id = sta ? (is_mld ? vif->bss_conf.link_id : 0) : 0xff; - mld->group_mld_id = is_mld ? mvif->mt76.idx : 0xff; - mld->own_mld_id = mvif->mt76.idx + 32; + mld->link_id = is_mld ? link_conf->link_id : 0xff; + /* apply the index of the primary link */ + mld->group_mld_id = is_mld ? mvif->bss_conf.mt76.idx : 0xff; + mld->own_mld_id = mconf->mt76.idx + 32; mld->remap_idx = 0xff; - if (sta) - memcpy(mld->mac_addr, sta->addr, ETH_ALEN); + if (phy->chip_cap & MT792x_CHIP_CAP_MLO_EML_EN) { + mld->eml_enable = !!(link_conf->vif->cfg.eml_cap & + IEEE80211_EML_CAP_EMLSR_SUPP); + } else { + mld->eml_enable = 0; + } + + memcpy(mld->mac_addr, vif->addr, ETH_ALEN); } static void -mt7925_mcu_bss_qos_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +mt7925_mcu_bss_qos_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf) { struct mt76_connac_bss_qos_tlv *qos; struct tlv *tlv; tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_QBSS, sizeof(*qos)); qos = (struct mt76_connac_bss_qos_tlv *)tlv; - qos->qos = vif->bss_conf.qos; + qos->qos = link_conf->qos; } static void -mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, +mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, struct mt792x_phy *phy) { #define DEFAULT_HE_PE_DURATION 4 @@ -2215,16 +2626,16 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct bss_info_uni_he *he; struct tlv *tlv; - cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); + cap = mt76_connac_get_he_phy_cap(phy->mt76, link_conf->vif); tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); he = (struct bss_info_uni_he *)tlv; - he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; + he->he_pe_duration = link_conf->htc_trig_based_pkt_ext; if (!he->he_pe_duration) he->he_pe_duration = DEFAULT_HE_PE_DURATION; - he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th); + he->he_rts_thres = cpu_to_le16(link_conf->frame_time_rts_th); if (!he->he_rts_thres) he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES); @@ -2234,7 +2645,7 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void -mt7925_mcu_bss_color_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, +mt7925_mcu_bss_color_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, bool enable) { struct bss_info_uni_bss_color *color; @@ -2244,50 +2655,141 @@ mt7925_mcu_bss_color_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, color = (struct bss_info_uni_bss_color *)tlv; color->enable = enable ? - vif->bss_conf.he_bss_color.enabled : 0; + link_conf->he_bss_color.enabled : 0; color->bss_color = enable ? - vif->bss_conf.he_bss_color.color : 0; + link_conf->he_bss_color.color : 0; +} + +static void +mt7925_mcu_bss_ifs_tlv(struct sk_buff *skb, + struct ieee80211_bss_conf *link_conf) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv; + struct mt792x_phy *phy = mvif->phy; + struct bss_ifs_time_tlv *ifs_time; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time)); + ifs_time = (struct bss_ifs_time_tlv *)tlv; + ifs_time->slot_valid = true; + ifs_time->slot_time = cpu_to_le16(phy->slottime); +} + +int mt7925_mcu_set_timing(struct mt792x_phy *phy, + struct ieee80211_bss_conf *link_conf) +{ + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); + struct mt792x_dev *dev = phy->dev; + struct sk_buff *skb; + + skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76, + MT7925_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7925_mcu_bss_ifs_tlv(skb, link_conf); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(BSS_INFO_UPDATE), true); +} + +void mt7925_mcu_del_dev(struct mt76_dev *mdev, + struct ieee80211_vif *vif) +{ + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; + struct { + struct { + u8 omac_idx; + u8 band_idx; + __le16 pad; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 link_idx; /* hw link idx */ + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } dev_req = { + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = true, + }, + }; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_bss_basic_tlv basic; + } basic_req = { + .basic = { + .tag = cpu_to_le16(UNI_BSS_INFO_BASIC), + .len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)), + .active = true, + .conn_state = 1, + }, + }; + + dev_req.hdr.omac_idx = mvif->omac_idx; + dev_req.hdr.band_idx = mvif->band_idx; + + basic_req.hdr.bss_idx = mvif->idx; + basic_req.basic.omac_idx = mvif->omac_idx; + basic_req.basic.band_idx = mvif->band_idx; + basic_req.basic.link_idx = mvif->link_idx; + + mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), + &basic_req, sizeof(basic_req), true); + + /* recovery omac address for the legacy interface */ + memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN); + mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE), + &dev_req, sizeof(dev_req), true); } int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, struct ieee80211_chanctx_conf *ctx, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, int enable) { - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv; + struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf); struct mt792x_dev *dev = phy->dev; + struct mt792x_link_sta *mlink_bc; struct sk_buff *skb; - int err; - skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76, MT7925_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); - /* bss_basic must be first */ - mt7925_mcu_bss_basic_tlv(skb, vif, sta, ctx, phy->mt76, - mvif->sta.wcid.idx, enable); - mt7925_mcu_bss_sec_tlv(skb, vif); + mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id); - mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, vif, sta); - mt7925_mcu_bss_qos_tlv(skb, vif); - mt7925_mcu_bss_mld_tlv(skb, vif, sta); + /* bss_basic must be first */ + mt7925_mcu_bss_basic_tlv(skb, link_conf, link_sta, ctx, phy->mt76, + mlink_bc->wcid.idx, enable); + mt7925_mcu_bss_sec_tlv(skb, link_conf); + mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf); + mt7925_mcu_bss_qos_tlv(skb, link_conf); + mt7925_mcu_bss_mld_tlv(skb, link_conf); + mt7925_mcu_bss_ifs_tlv(skb, link_conf); - if (vif->bss_conf.he_support) { - mt7925_mcu_bss_he_tlv(skb, vif, phy); - mt7925_mcu_bss_color_tlv(skb, vif, enable); + if (link_conf->he_support) { + mt7925_mcu_bss_he_tlv(skb, link_conf, phy); + mt7925_mcu_bss_color_tlv(skb, link_conf, enable); } - err = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD(BSS_INFO_UPDATE), true); - if (err < 0) - return err; + if (enable) + mt7925_mcu_bss_rlm_tlv(skb, phy->mt76, link_conf, ctx); - return mt7925_mcu_set_chctx(phy->mt76, &mvif->mt76, ctx); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(BSS_INFO_UPDATE), true); } -int mt7925_mcu_set_dbdc(struct mt76_phy *phy) +int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable) { struct mt76_dev *mdev = phy->dev; @@ -2307,28 +2809,25 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy) tlv = mt76_connac_mcu_add_tlv(skb, UNI_MBMC_SETTING, sizeof(*conf)); conf = (struct mbmc_conf_tlv *)tlv; - conf->mbmc_en = 1; + conf->mbmc_en = enable; conf->band = 0; /* unused */ err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SET_DBDC_PARMS), - false); + true); return err; } -#define MT76_CONNAC_SCAN_CHANNEL_TIME 60 - int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_scan_request *scan_req) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct cfg80211_scan_request *sreq = &scan_req->req; - int n_ssids = 0, err, i, duration; + int n_ssids = 0, err, i; struct ieee80211_channel **scan_list = sreq->channels; struct mt76_dev *mdev = phy->dev; struct mt76_connac_mcu_scan_channel *chan; struct sk_buff *skb; - struct scan_hdr_tlv *hdr; struct scan_req_tlv *req; struct scan_ssid_tlv *ssid; @@ -2339,9 +2838,12 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, struct tlv *tlv; int max_len; + if (test_bit(MT76_HW_SCANNING, &phy->state)) + return -EBUSY; + max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) + - sizeof(*bssid) + sizeof(*chan_info) + - sizeof(*misc) + sizeof(*ie); + sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS + + sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie); skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); if (!skb) @@ -2359,19 +2861,13 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req->scan_type = sreq->n_ssids ? 1 : 0; req->probe_req_num = sreq->n_ssids ? 2 : 0; - duration = MT76_CONNAC_SCAN_CHANNEL_TIME; - /* increase channel time for passive scan */ - if (!sreq->n_ssids) - duration *= 2; - req->timeout_value = cpu_to_le16(sreq->n_channels * duration); - req->channel_min_dwell_time = cpu_to_le16(duration); - req->channel_dwell_time = cpu_to_le16(duration); - tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SSID, sizeof(*ssid)); ssid = (struct scan_ssid_tlv *)tlv; for (i = 0; i < sreq->n_ssids; i++) { if (!sreq->ssids[i].ssid_len) continue; + if (i > MT7925_RNR_SCAN_MAX_BSSIDS) + break; ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid, @@ -2381,10 +2877,31 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, ssid->ssid_type = n_ssids ? BIT(2) : BIT(0); ssid->ssids_num = n_ssids; - tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid)); - bssid = (struct scan_bssid_tlv *)tlv; + if (sreq->n_6ghz_params) { + u8 j; + + mt76_connac_mcu_build_rnr_scan_param(mdev, sreq); - memcpy(bssid->bssid, sreq->bssid, ETH_ALEN); + for (j = 0; j < mdev->rnr.bssid_num; j++) { + if (j > MT7925_RNR_SCAN_MAX_BSSIDS) + break; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, + sizeof(*bssid)); + bssid = (struct scan_bssid_tlv *)tlv; + + ether_addr_copy(bssid->bssid, mdev->rnr.bssid[j]); + bssid->match_ch = mdev->rnr.channel[j]; + bssid->match_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS; + bssid->match_short_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS; + } + req->scan_func |= SCAN_FUNC_RNR_SCAN; + } else { + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid)); + bssid = (struct scan_bssid_tlv *)tlv; + + ether_addr_copy(bssid->bssid, sreq->bssid); + } tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_CHANNEL, sizeof(*chan_info)); chan_info = (struct scan_chan_info_tlv *)tlv; @@ -2426,7 +2943,7 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, } err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), - false); + true); if (err < 0) clear_bit(MT76_HW_SCANNING, &phy->state); @@ -2438,7 +2955,7 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *sreq) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct ieee80211_channel **scan_list = sreq->channels; struct mt76_connac_mcu_scan_channel *chan; struct mt76_dev *mdev = phy->dev; @@ -2532,7 +3049,7 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, } return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), - false); + true); } EXPORT_SYMBOL_GPL(mt7925_mcu_sched_scan_req); @@ -2568,13 +3085,13 @@ mt7925_mcu_sched_scan_enable(struct mt76_phy *phy, clear_bit(MT76_HW_SCHED_SCANNING, &phy->state); return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), - false); + true); } int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct { struct scan_hdr { u8 seq_num; @@ -2607,7 +3124,7 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy, } return mt76_mcu_send_msg(phy->dev, MCU_UNI_CMD(SCAN_REQ), - &req, sizeof(req), false); + &req, sizeof(req), true); } EXPORT_SYMBOL_GPL(mt7925_mcu_cancel_hw_scan); @@ -2712,7 +3229,7 @@ int mt7925_mcu_set_channel_domain(struct mt76_phy *phy) memcpy(__skb_push(skb, sizeof(req)), &req, sizeof(req)); return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SET_DOMAIN_INFO), - false); + true); } EXPORT_SYMBOL_GPL(mt7925_mcu_set_channel_domain); @@ -2744,16 +3261,17 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, .idx = idx, .env = env_cap, - .acpi_conf = mt792x_acpi_get_flags(&dev->phy), }; int ret, valid_cnt = 0; - u8 i, *pos; + u8 *pos, *last_pos; if (!clc) return 0; - pos = clc->data + sizeof(*seg) * clc->nr_seg; - for (i = 0; i < clc->nr_country; i++) { + req.ver = clc->ver; + pos = clc->data + sizeof(*seg) * clc->t0.nr_seg; + last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4)); + while (pos < last_pos) { struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos; pos += sizeof(*rule); @@ -2768,6 +3286,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, memcpy(req.type, rule->type, 2); req.size = cpu_to_le16(seg->len); + dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag; skb = __mt76_mcu_msg_alloc(&dev->mt76, &req, le16_to_cpu(req.size) + sizeof(req), sizeof(req), GFP_KERNEL); @@ -2783,8 +3302,10 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, valid_cnt++; } - if (!valid_cnt) + if (!valid_cnt) { + dev->phy.clc_chan_conf = 0xff; return -ENOENT; + } return 0; } @@ -2797,6 +3318,9 @@ int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, /* submit all clc config */ for (i = 0; i < ARRAY_SIZE(phy->clc); i++) { + if (i == MT792x_CLC_BE_CTRL) + continue; + ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap, phy->clc[i], i); @@ -2845,12 +3369,28 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, if (cmd & __MCU_CMD_FIELD_UNI) { uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd; uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); - uni_txd->option = MCU_CMD_UNI_EXT_ACK; uni_txd->cid = cpu_to_le16(mcu_cmd); uni_txd->s2d_index = MCU_S2D_H2N; uni_txd->pkt_type = MCU_PKT_ID; uni_txd->seq = seq; + if (cmd & __MCU_CMD_FIELD_QUERY) + uni_txd->option = MCU_CMD_UNI_QUERY_ACK; + else + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + + if (cmd == MCU_UNI_CMD(HIF_CTRL) || + cmd == MCU_UNI_CMD(CHIP_CONFIG)) + uni_txd->option &= ~MCU_CMD_ACK; + + if (mcu_cmd == MCU_UNI_CMD_TESTMODE_CTRL || + mcu_cmd == MCU_UNI_CMD_TESTMODE_RX_STAT) { + if (cmd & __MCU_CMD_FIELD_QUERY) + uni_txd->option = 0x2; + else + uni_txd->option = 0x6; + } + goto exit; } @@ -3142,6 +3682,43 @@ int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy) return 0; } +int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy) +{ +#define UNI_CMD_RADIO_STATUS_GET 0 + struct mt792x_dev *dev = phy->dev; + struct sk_buff *skb; + int ret; + struct { + __le16 tag; + __le16 len; + u8 rsv[4]; + } __packed req = { + .tag = UNI_CMD_RADIO_STATUS_GET, + .len = cpu_to_le16(sizeof(req)), + }; + struct mt7925_radio_status_event { + __le16 tag; + __le16 len; + + u8 data; + u8 rsv[3]; + } __packed *status; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_UNI_CMD(RADIO_STATUS), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + skb_pull(skb, sizeof(struct tlv)); + status = (struct mt7925_radio_status_event *)skb->data; + ret = status->data; + + dev_kfree_skb(skb); + + return ret; +} + int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h index 3c41e21303b1..ee6fb16e83c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h @@ -104,13 +104,6 @@ enum { 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; @@ -159,6 +152,20 @@ enum { UNI_EVENT_SCAN_DONE_NLO = 3, }; +enum connac3_mcu_cipher_type { + CONNAC3_CIPHER_NONE = 0, + CONNAC3_CIPHER_WEP40 = 1, + CONNAC3_CIPHER_TKIP = 2, + CONNAC3_CIPHER_AES_CCMP = 4, + CONNAC3_CIPHER_WEP104 = 5, + CONNAC3_CIPHER_BIP_CMAC_128 = 6, + CONNAC3_CIPHER_WEP128 = 7, + CONNAC3_CIPHER_WAPI = 8, + CONNAC3_CIPHER_CCMP_256 = 10, + CONNAC3_CIPHER_GCMP = 11, + CONNAC3_CIPHER_GCMP_256 = 12, +}; + struct mt7925_mcu_scan_chinfo_event { u8 nr_chan; u8 alpha2[3]; @@ -182,6 +189,7 @@ enum { UNI_SNIFFER_CONFIG, }; +#define MT7925_RNR_SCAN_MAX_BSSIDS 10 struct scan_hdr_tlv { /* fixed field */ u8 seq_num; @@ -208,8 +216,8 @@ struct scan_req_tlv { __le16 channel_dwell_time; /* channel Dwell interval */ __le16 timeout_value; __le16 probe_delay_time; - u8 func_mask_ext; -}; + __le32 func_mask_ext; +} __packed; struct scan_ssid_tlv { __le16 tag; @@ -221,9 +229,10 @@ struct scan_ssid_tlv { * BIT(2) + ssid_type_ext BIT(0) specified SSID only */ u8 ssids_num; - u8 pad[2]; - struct mt76_connac_mcu_scan_ssid ssids[4]; -}; + u8 is_short_ssid; + u8 pad; + struct mt76_connac_mcu_scan_ssid ssids[MT7925_RNR_SCAN_MAX_BSSIDS]; +} __packed; struct scan_bssid_tlv { __le16 tag; @@ -233,8 +242,9 @@ struct scan_bssid_tlv { u8 match_ch; u8 match_ssid_ind; u8 rcpi; - u8 pad[3]; -}; + u8 match_short_ssid_ind; + u8 pad[2]; +} __packed; struct scan_chan_info_tlv { __le16 tag; @@ -250,7 +260,7 @@ struct scan_chan_info_tlv { u8 channels_num; /* valid when channel_type is 4 */ u8 pad[2]; struct mt76_connac_mcu_scan_channel channels[64]; -}; +} __packed; struct scan_ie_tlv { __le16 tag; @@ -334,7 +344,8 @@ struct bss_req_hdr { struct bss_rate_tlv { __le16 tag; __le16 len; - u8 __rsv1[4]; + u8 __rsv1[2]; + __le16 basic_rate; __le16 bc_trans; __le16 mc_trans; u8 short_preamble; @@ -351,7 +362,23 @@ struct bss_mld_tlv { u8 mac_addr[ETH_ALEN]; u8 remap_idx; u8 link_id; - u8 __rsv[2]; + u8 eml_enable; + u8 max_link_num; + u8 hybrid_mode; + u8 __rsv[3]; +} __packed; + +struct bss_eht_tlv { + __le16 tag; + __le16 len; + u8 is_eht_op_present; + u8 is_eth_dscb_present; + u8 eht_ctrl; + u8 eht_ccfs0; + u8 eht_ccfs1; + u8 pad1; + __le16 eht_dis_sub_chan_bitmap; + u8 pad2[4]; } __packed; struct sta_rec_ba_uni { @@ -382,25 +409,22 @@ struct sta_rec_eht { 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]; + u8 tx_key; + u8 key_type; + u8 is_authenticator; + u8 peer_addr[6]; + u8 bss_idx; + u8 cipher_id; + u8 key_id; + u8 key_len; + u8 wlan_idx; + u8 mgmt_prot; + u8 key[32]; + u8 key_rsc[16]; } __packed; struct sta_rec_hdr_trans { @@ -428,6 +452,48 @@ struct sta_rec_mld { } __packed link[2]; } __packed; +struct sta_rec_eht_mld { + __le16 tag; + __le16 len; + u8 nsep; + u8 mld_type; + u8 __rsv1[1]; + u8 str_cap[3]; + u8 eml_cap[3]; + u8 __rsv2[3]; +} __packed; + +struct bss_ifs_time_tlv { + __le16 tag; + __le16 len; + u8 slot_valid; + u8 sifs_valid; + u8 rifs_valid; + u8 eifs_valid; + __le16 slot_time; + __le16 sifs_time; + __le16 rifs_time; + __le16 eifs_time; + u8 eifs_cck_valid; + u8 rsv; + __le16 eifs_cck_time; +} __packed; + +struct bss_rlm_tlv { + __le16 tag; + __le16 len; + u8 control_channel; + u8 center_chan; + u8 center_chan2; + u8 bw; + u8 tx_streams; + u8 rx_streams; + u8 ht_op_info; + u8 sco; + u8 band; + u8 pad[3]; +} __packed; + #define MT7925_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct sta_rec_basic) + \ sizeof(struct sta_rec_bf) + \ @@ -440,13 +506,14 @@ struct sta_rec_mld { sizeof(struct sta_rec_bfee) + \ sizeof(struct sta_rec_phy) + \ sizeof(struct sta_rec_ra) + \ - sizeof(struct sta_rec_sec) + \ + sizeof(struct sta_rec_sec_uni) + \ 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)) + sizeof(struct tlv) * 2 + \ + sizeof(struct sta_rec_remove)) #define MT7925_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \ sizeof(struct mt76_connac_bss_basic_tlv) + \ @@ -455,6 +522,8 @@ struct sta_rec_mld { sizeof(struct bss_mld_tlv) + \ sizeof(struct bss_info_uni_he) + \ sizeof(struct bss_info_uni_bss_color) + \ + sizeof(struct bss_ifs_time_tlv) + \ + sizeof(struct bss_rlm_tlv) + \ sizeof(struct tlv)) #define MT_CONNAC3_SKU_POWER_LIMIT 449 @@ -507,9 +576,97 @@ struct mt7925_wow_pattern_tlv { u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN]; u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN]; u8 rsv[4]; +}; + +struct roc_acquire_tlv { + __le16 tag; + __le16 len; + u8 bss_idx; + u8 tokenid; + u8 control_channel; + u8 sco; + u8 band; + u8 bw; + u8 center_chan; + u8 center_chan2; + u8 bw_from_ap; + u8 center_chan_from_ap; + u8 center_chan2_from_ap; + u8 reqtype; + __le32 maxinterval; + u8 dbdcband; + u8 rsv[3]; +} __packed; + +enum ENUM_CMD_TEST_CTRL_ACT { + CMD_TEST_CTRL_ACT_SWITCH_MODE = 0, + CMD_TEST_CTRL_ACT_SET_AT = 1, + CMD_TEST_CTRL_ACT_GET_AT = 2, + CMD_TEST_CTRL_ACT_SET_AT_ENG = 3, + CMD_TEST_CTRL_ACT_GET_AT_ENG = 4, + CMD_TEST_CTRL_ACT_NUM +}; + +enum ENUM_CMD_TEST_CTRL_ACT_SWITCH_MODE_OP { + CMD_TEST_CTRL_ACT_SWITCH_MODE_NORMAL = 0, + CMD_TEST_CTRL_ACT_SWITCH_MODE_RF_TEST = 1, + CMD_TEST_CTRL_ACT_SWITCH_MODE_ICAP = 2, + CMD_TEST_CTRL_ACT_SWITCH_MODE_NUM +}; + +union testmode_data { + __le32 op_mode; + __le32 channel_freq; + u8 rf_at_info[84]; +}; + +union testmode_evt { + __le32 op_mode; + __le32 channel_freq; + u8 rf_at_info[1024]; +}; + +struct uni_cmd_testmode_ctrl { + u16 tag; + u16 length; + u8 action; + u8 reserved[3]; + union testmode_data data; +} __packed; + +struct mt7925_rftest_cmd { + u8 padding[4]; + struct uni_cmd_testmode_ctrl ctrl; } __packed; -int mt7925_mcu_set_dbdc(struct mt76_phy *phy); +static inline enum connac3_mcu_cipher_type +mt7925_mcu_get_cipher(int cipher) +{ + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return CONNAC3_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return CONNAC3_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + return CONNAC3_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_AES_CMAC: + return CONNAC3_CIPHER_BIP_CMAC_128; + case WLAN_CIPHER_SUITE_CCMP: + return CONNAC3_CIPHER_AES_CCMP; + case WLAN_CIPHER_SUITE_CCMP_256: + return CONNAC3_CIPHER_CCMP_256; + case WLAN_CIPHER_SUITE_GCMP: + return CONNAC3_CIPHER_GCMP; + case WLAN_CIPHER_SUITE_GCMP_256: + return CONNAC3_CIPHER_GCMP_256; + case WLAN_CIPHER_SUITE_SMS4: + return CONNAC3_CIPHER_WAPI; + default: + return CONNAC3_CIPHER_NONE; + } +} + +int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable); 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, @@ -520,18 +677,29 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy, struct ieee80211_vif *vif, bool enable); +void mt7925_mcu_del_dev(struct mt76_dev *mdev, + struct ieee80211_vif *vif); int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, struct ieee80211_chanctx_conf *ctx, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, int enable); +int mt7925_mcu_set_timing(struct mt792x_phy *phy, + struct ieee80211_bss_conf *link_conf); int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable); +int mt7925_mcu_set_thermal_protect(struct mt792x_dev *dev); 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, +int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif, + struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx); +int mt7925_mcu_set_eht_pp(struct mt76_phy *phy, struct mt76_vif_link *mvif, + struct ieee80211_bss_conf *link_conf, + 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); + struct ieee80211_bss_conf *link_conf); +int +mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf, bool enable); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h index 33785f526acf..1b165d0d8bd3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h @@ -27,20 +27,45 @@ #define MCU_UNI_EVENT_ROC 0x27 +#define HIF_TRAFFIC_IDLE 0x2 + +enum { + UNI_EVENT_HIF_CTRL_BASIC = 0, + UNI_EVENT_HIF_CTRL_TAG_NUM +}; + +struct mt7925_mcu_hif_ctrl_basic_tlv { + __le16 tag; + __le16 len; + u8 cid; + u8 pad[3]; + u32 status; + u8 hif_type; + u8 hif_tx_traffic_status; + u8 hif_rx_traffic_status; + u8 hifsuspend; + u8 rsv[4]; +} __packed; + enum { UNI_ROC_ACQUIRE, UNI_ROC_ABORT, + UNI_ROC_SUB_LINK = 3, UNI_ROC_NUM }; enum mt7925_roc_req { MT7925_ROC_REQ_JOIN, MT7925_ROC_REQ_ROC, + MT7925_ROC_REQ_SUB_LINK, + MT7925_ROC_REQ_MLSR_AG = 10, + MT7925_ROC_REQ_MLSR_AA, MT7925_ROC_REQ_NUM }; enum { UNI_EVENT_ROC_GRANT = 0, + UNI_EVENT_ROC_GRANT_SUB_LINK = 4, UNI_EVENT_ROC_TAG_NUM }; @@ -112,11 +137,18 @@ enum { MT7925_CLC_MAX_NUM, }; +struct mt7925_clc_rule_v2 { + u32 flag; + u8 alpha2[2]; + u8 rsv[10]; +} __packed; + struct mt7925_clc_rule { u8 alpha2[2]; u8 type[2]; u8 seg_idx; - u8 rsv[3]; + u8 flag; /* UNII4~8 ctrl flag */ + u8 rsv[2]; } __packed; struct mt7925_clc_segment { @@ -127,14 +159,26 @@ struct mt7925_clc_segment { u8 rsv2[4]; } __packed; -struct mt7925_clc { - __le32 len; - u8 idx; - u8 ver; +struct mt7925_clc_type0 { u8 nr_country; u8 type; u8 nr_seg; u8 rsv[7]; +} __packed; + +struct mt7925_clc_type2 { + u8 type; + u8 rsv[9]; +} __packed; + +struct mt7925_clc { + __le32 len; + u8 idx; + u8 ver; + union { + struct mt7925_clc_type0 t0; + struct mt7925_clc_type2 t2; + }; u8 data[]; } __packed; @@ -142,9 +186,12 @@ enum mt7925_eeprom_field { MT_EE_CHIP_ID = 0x000, MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, + MT_EE_HW_TYPE = 0xa71, __MT_EE_MAX = 0x9ff }; +#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0) + enum { TXPWR_USER, TXPWR_EEPROM, @@ -192,13 +239,15 @@ 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, +int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf, bool enable); -int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, +int mt7925_mcu_sta_update(struct mt792x_dev *dev, + struct ieee80211_link_sta *link_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_tx(struct mt792x_dev *dev, struct ieee80211_bss_conf *bss_conf); 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); @@ -208,12 +257,14 @@ 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); +void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2); +void mt7925_regd_update(struct mt792x_dev *dev); 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); +int mt7925_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev); 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); @@ -228,6 +279,7 @@ 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_mlo_caps(struct mt792x_phy *phy); int mt7925_init_debugfs(struct mt792x_dev *dev); int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, @@ -239,9 +291,11 @@ int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev, int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable); +void mt7925_mlo_pm_work(struct work_struct *work); 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); +int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, + struct ieee80211_bss_conf *link_conf); void mt7925_coredump_work(struct work_struct *work); int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, struct mt7925_txpwr *txpwr); @@ -252,7 +306,7 @@ void mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, 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 ieee80211_sta *sta, struct mt76_wcid *wcid, struct list_head *free_list); int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); @@ -271,6 +325,7 @@ 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_mcu_get_temperature(struct mt792x_phy *phy); int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -290,20 +345,31 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, 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, +int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, + int duration, u8 token_id); +int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, 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, +int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf, u8 token_id); +void mt7925_roc_abort_sync(struct mt792x_dev *dev); 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); + struct mt76_wcid *wcid, enum set_key_cmd cmd, + struct mt792x_sta *msta); 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); + struct ieee80211_sta *sta, + int link_id); +int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy); + +int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len); +int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, + struct netlink_callback *cb, void *data, int len); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c index 1fd99a856541..89dc30f7c6b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c @@ -31,6 +31,10 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev) { int i; struct mt76_connac_pm *pm = &dev->pm; + struct ieee80211_hw *hw = mt76_hw(dev); + + if (dev->phy.chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN) + wiphy_rfkill_stop_polling(hw->wiphy); cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); @@ -254,7 +258,7 @@ static int mt7925_dma_init(struct mt792x_dev *dev) if (ret < 0) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt792x_poll_tx); napi_enable(&dev->mt76.tx_napi); @@ -279,7 +283,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev, .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_event = mt7925_mac_sta_event, .sta_remove = mt7925_mac_sta_remove, .update_survey = mt792x_update_channel, }; @@ -373,6 +377,9 @@ static int mt7925_pci_probe(struct pci_dev *pdev, bus_ops->rmw = mt7925_rmw; dev->mt76.bus = bus_ops; + if (!mt7925_disable_aspm && mt76_pci_aspm_supported(pdev)) + dev->aspm_supported = true; + ret = __mt792x_mcu_fw_pmctrl(dev); if (ret) goto err_free_dev; @@ -386,6 +393,8 @@ static int mt7925_pci_probe(struct pci_dev *pdev, dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1); + ret = mt792x_wfsys_reset(dev); if (ret) goto err_free_dev; @@ -425,6 +434,7 @@ static void mt7925_pci_remove(struct pci_dev *pdev) struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); mt7925e_unregister_device(dev); + set_bit(MT76_REMOVED, &mdev->phy.state); devm_free_irq(&pdev->dev, pdev->irq, dev); mt76_free_device(&dev->mt76); pci_free_irq_vectors(pdev); @@ -436,25 +446,35 @@ static int mt7925_pci_suspend(struct device *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; + int i, err, ret; pm->suspended = true; + dev->hif_resumed = false; flush_work(&dev->reset_work); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); + mt7925_roc_abort_sync(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; + wait_event_timeout(dev->wait, + !dev->regd_in_progress, 5 * HZ); + /* 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) + mt76_connac_mcu_set_hif_suspend(mdev, true, false); + ret = wait_event_timeout(dev->wait, + dev->hif_idle, 3 * HZ); + if (!ret) { + err = -ETIMEDOUT; goto restore_suspend; + } napi_disable(&mdev->tx_napi); mt76_worker_disable(&mdev->tx_worker); @@ -474,9 +494,6 @@ static int mt7925_pci_suspend(struct device *device) /* 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); @@ -498,8 +515,11 @@ restore_napi: if (!pm->ds_enable) mt7925_mcu_set_deep_sleep(dev, false); - mt76_connac_mcu_set_hif_suspend(mdev, false); - + mt76_connac_mcu_set_hif_suspend(mdev, false, false); + ret = wait_event_timeout(dev->wait, + dev->hif_resumed, 3 * HZ); + if (!ret) + err = -ETIMEDOUT; restore_suspend: pm->suspended = false; @@ -515,8 +535,9 @@ static int mt7925_pci_resume(struct device *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; + int i, err, ret; + dev->hif_idle = false; err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto failed; @@ -536,21 +557,31 @@ static int mt7925_pci_resume(struct device *device) 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); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_schedule(&mdev->napi[i]); + } napi_schedule(&mdev->tx_napi); local_bh_enable(); - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + mt76_connac_mcu_set_hif_suspend(mdev, false, false); + ret = wait_event_timeout(dev->wait, + dev->hif_resumed, 3 * HZ); + if (!ret) { + err = -ETIMEDOUT; + goto failed; + } /* restore previous ds setting */ if (!pm->ds_enable) mt7925_mcu_set_deep_sleep(dev, false); + mt7925_regd_update(dev); failed: pm->suspended = false; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c index 9fca887977d2..4578d16bf456 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c @@ -34,9 +34,9 @@ int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (sta) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - if (time_after(jiffies, msta->last_txs + HZ / 4)) { + if (time_after(jiffies, msta->deflink.last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; + msta->deflink.last_txs = jiffies; } } @@ -60,7 +60,7 @@ void mt7925_tx_token_put(struct mt792x_dev *dev) spin_lock_bh(&dev->mt76.token_lock); idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7925_txwi_free(dev, txwi, NULL, false, NULL); + mt7925_txwi_free(dev, txwi, NULL, NULL, NULL); dev->mt76.token_count--; } spin_unlock_bh(&dev->mt76.token_lock); @@ -101,12 +101,15 @@ int mt7925e_mac_reset(struct mt792x_dev *dev) 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); + + local_bh_disable(); + mt76_for_each_q_rx(&dev->mt76, i) { + napi_schedule(&dev->mt76.napi[i]); + } napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h index 985794a40c1a..547489092c29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h @@ -28,7 +28,7 @@ #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_ENA MT_WFDMA0(0x204) #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) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7925/testmode.c new file mode 100644 index 000000000000..a3c97164ba21 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/testmode.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: ISC + +#include "mt7925.h" +#include "mcu.h" + +#define MT7925_EVT_RSP_LEN 512 + +enum mt7925_testmode_attr { + MT7925_TM_ATTR_UNSPEC, + MT7925_TM_ATTR_SET, + MT7925_TM_ATTR_QUERY, + MT7925_TM_ATTR_RSP, + + /* keep last */ + NUM_MT7925_TM_ATTRS, + MT7925_TM_ATTR_MAX = NUM_MT7925_TM_ATTRS - 1, +}; + +struct mt7925_tm_cmd { + u8 padding[4]; + struct uni_cmd_testmode_ctrl c; +} __packed; + +struct mt7925_tm_evt { + u32 param0; + u32 param1; +} __packed; + +static const struct nla_policy mt7925_tm_policy[NUM_MT7925_TM_ATTRS] = { + [MT7925_TM_ATTR_SET] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7925_tm_cmd)), + [MT7925_TM_ATTR_QUERY] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7925_tm_cmd)), +}; + +static int +mt7925_tm_set(struct mt792x_dev *dev, struct mt7925_tm_cmd *req) +{ + struct mt7925_rftest_cmd cmd; + struct mt7925_rftest_cmd *pcmd = &cmd; + bool testmode = false, normal = false; + struct mt76_connac_pm *pm = &dev->pm; + struct mt76_phy *phy = &dev->mphy; + int ret = -ENOTCONN; + + memset(pcmd, 0, sizeof(*pcmd)); + memcpy(pcmd, req, sizeof(struct mt7925_tm_cmd)); + + mutex_lock(&dev->mt76.mutex); + + if (pcmd->ctrl.action == CMD_TEST_CTRL_ACT_SWITCH_MODE) { + if (pcmd->ctrl.data.op_mode == CMD_TEST_CTRL_ACT_SWITCH_MODE_NORMAL) + normal = true; + else + testmode = true; + } + + if (testmode) { + /* Make sure testmode running on full power mode */ + pm->enable = false; + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + __mt792x_mcu_drv_pmctrl(dev); + + phy->test.state = MT76_TM_STATE_ON; + } + + if (!mt76_testmode_enabled(phy)) + goto out; + + ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(TESTMODE_CTRL), &cmd, + sizeof(cmd), false); + + if (ret) + goto out; + + if (normal) { + /* Switch back to the normal world */ + phy->test.state = MT76_TM_STATE_OFF; + pm->enable = true; + } +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static int +mt7925_tm_query(struct mt792x_dev *dev, struct mt7925_tm_cmd *req, + char *evt_resp) +{ + struct mt7925_rftest_cmd cmd; + char *pcmd = (char *)&cmd; + struct sk_buff *skb = NULL; + int ret = 1; + + memset(pcmd, 0, sizeof(*pcmd)); + memcpy(pcmd + 4, (char *)&req->c, sizeof(struct uni_cmd_testmode_ctrl)); + + if (*((uint16_t *)req->padding) == MCU_UNI_CMD_TESTMODE_CTRL) + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_QUERY(TESTMODE_CTRL), + &cmd, sizeof(cmd), true, &skb); + else if (*((uint16_t *)req->padding) == MCU_UNI_CMD_TESTMODE_RX_STAT) + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_QUERY(TESTMODE_RX_STAT), + &cmd, sizeof(cmd), true, &skb); + + if (ret) + goto out; + + memcpy((char *)evt_resp, (char *)skb->data + 8, MT7925_EVT_RSP_LEN); + +out: + dev_kfree_skb(skb); + + return ret; +} + +int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len) +{ + struct nlattr *tb[NUM_MT76_TM_ATTRS]; + struct mt76_phy *mphy = hw->priv; + struct mt792x_phy *phy = mphy->priv; + int err; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || + !(hw->conf.flags & IEEE80211_CONF_MONITOR)) + return -ENOTCONN; + + err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len, + mt76_tm_policy, NULL); + if (err) + return err; + + if (tb[MT76_TM_ATTR_DRV_DATA]) { + struct nlattr *drv_tb[NUM_MT7925_TM_ATTRS], *data; + int ret; + + data = tb[MT76_TM_ATTR_DRV_DATA]; + ret = nla_parse_nested_deprecated(drv_tb, + MT7925_TM_ATTR_MAX, + data, mt7925_tm_policy, + NULL); + if (ret) + return ret; + + data = drv_tb[MT7925_TM_ATTR_SET]; + if (data) + return mt7925_tm_set(phy->dev, nla_data(data)); + } + + return -EINVAL; +} + +int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, + struct netlink_callback *cb, void *data, int len) +{ + struct nlattr *tb[NUM_MT76_TM_ATTRS]; + struct mt76_phy *mphy = hw->priv; + struct mt792x_phy *phy = mphy->priv; + int err; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || + !(hw->conf.flags & IEEE80211_CONF_MONITOR) || + !mt76_testmode_enabled(mphy)) + return -ENOTCONN; + + if (cb->args[2]++ > 0) + return -ENOENT; + + err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len, + mt76_tm_policy, NULL); + if (err) + return err; + + if (tb[MT76_TM_ATTR_DRV_DATA]) { + struct nlattr *drv_tb[NUM_MT7925_TM_ATTRS], *data; + int ret; + + data = tb[MT76_TM_ATTR_DRV_DATA]; + ret = nla_parse_nested_deprecated(drv_tb, + MT7925_TM_ATTR_MAX, + data, mt7925_tm_policy, + NULL); + if (ret) + return ret; + + data = drv_tb[MT7925_TM_ATTR_QUERY]; + if (data) { + char evt_resp[MT7925_EVT_RSP_LEN]; + + err = mt7925_tm_query(phy->dev, nla_data(data), + evt_resp); + if (err) + return err; + + return nla_put(msg, MT7925_TM_ATTR_RSP, + sizeof(evt_resp), evt_resp); + } + } + + return -EINVAL; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c index 1e0f094fc905..4dfbc1b6cfdd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c @@ -142,7 +142,7 @@ static int mt7925u_probe(struct usb_interface *usb_intf, .rx_skb = mt7925_queue_rx_skb, .rx_check = mt7925_rx_check, .sta_add = mt7925_mac_sta_add, - .sta_assoc = mt7925_mac_sta_assoc, + .sta_event = mt7925_mac_sta_event, .sta_remove = mt7925_mac_sta_remove, .update_survey = mt792x_update_channel, }; @@ -243,14 +243,19 @@ 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; + int err, ret; pm->suspended = true; + dev->hif_resumed = false; flush_work(&dev->reset_work); - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); - if (err) + mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, false); + ret = wait_event_timeout(dev->wait, + dev->hif_idle, 3 * HZ); + if (!ret) { + err = -ETIMEDOUT; goto failed; + } mt76u_stop_rx(&dev->mt76); mt76u_stop_tx(&dev->mt76); @@ -271,8 +276,9 @@ 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; + int err, i, ret; + dev->hif_idle = false; for (i = 0; i < 10; i++) { u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT); @@ -298,7 +304,11 @@ static int mt7925u_resume(struct usb_interface *intf) if (err < 0) goto failed; - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); + mt76_connac_mcu_set_hif_suspend(&dev->mt76, false, false); + ret = wait_event_timeout(dev->wait, + dev->hif_resumed, 3 * HZ); + if (!ret) + err = -ETIMEDOUT; failed: pm->suspended = false; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 3c897b34aaa7..e0359d431eca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -26,6 +26,10 @@ #define MT792x_FW_CAP_CNM BIT(7) #define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0) +#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1) +#define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3) +#define MT792x_CHIP_CAP_MLO_EN BIT(8) +#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9) /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ #define MT792x_BASIC_RATES_TBL 11 @@ -36,10 +40,12 @@ #define MT792x_MCU_INIT_RETRY_COUNT 10 #define MT792x_WFSYS_INIT_RETRY_COUNT 2 +#define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin" #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 MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.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" @@ -64,7 +70,8 @@ struct mt792x_fw_features { enum { MT792x_CLC_POWER, - MT792x_CLC_CHAN, + MT792x_CLC_POWER_EXT, + MT792x_CLC_BE_CTRL, MT792x_CLC_MAX_NUM, }; @@ -76,13 +83,18 @@ enum mt792x_reg_power_type { MT_AP_VLP, }; +enum mt792x_mlo_pm_state { + MT792x_MLO_LINK_DISASSOC, + MT792x_MLO_LINK_ASSOC, + MT792x_MLO_CHANGED_PS_PENDING, + MT792x_MLO_CHANGED_PS, +}; + DECLARE_EWMA(avg_signal, 10, 8) -struct mt792x_sta { +struct mt792x_link_sta { struct mt76_wcid wcid; /* must be first */ - struct mt792x_vif *vif; - u32 airtime_ac[8]; int ack_signal; @@ -91,21 +103,50 @@ struct mt792x_sta { unsigned long last_txs; struct mt76_connac_sta_key_conf bip; + + struct mt792x_sta *sta; + + struct ieee80211_link_sta *pri_link; +}; + +struct mt792x_sta { + struct mt792x_link_sta deflink; /* must be first */ + struct mt792x_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; + + struct mt792x_vif *vif; + + u16 valid_links; + u8 deflink_id; }; DECLARE_EWMA(rssi, 10, 8); +struct mt792x_chanctx { + struct mt792x_bss_conf *bss_conf; +}; + +struct mt792x_bss_conf { + struct mt76_vif_link mt76; /* must be first */ + struct mt792x_vif *vif; + struct ewma_rssi rssi; + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; + unsigned int link_id; +}; + struct mt792x_vif { - struct mt76_vif mt76; /* must be first */ + struct mt792x_bss_conf bss_conf; /* must be first */ + struct mt792x_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; struct mt792x_sta sta; struct mt792x_sta *wep_sta; struct mt792x_phy *phy; + u16 valid_links; + u8 deflink_id; + enum mt792x_mlo_pm_state mlo_pm_state; - struct ewma_rssi rssi; - - struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; + struct work_struct csa_work; + struct timer_list csa_timer; }; struct mt792x_phy { @@ -137,6 +178,7 @@ struct mt792x_phy { #endif void *clc[MT792x_CLC_MAX_NUM]; u64 chip_cap; + u16 eml_cap; struct work_struct roc_work; struct timer_list roc_timer; @@ -178,6 +220,8 @@ struct mt792x_dev { struct mt76_phy mphy; }; + struct mac_address macaddr_list[8]; + const struct mt76_bus_ops *bus_ops; struct mt792x_phy phy; @@ -186,6 +230,13 @@ struct mt792x_dev { bool hw_init_done:1; bool fw_assert:1; bool has_eht:1; + bool regd_in_progress:1; + bool aspm_supported:1; + bool hif_idle:1; + bool hif_resumed:1; + bool sar_inited:1; + bool regd_change:1; + wait_queue_head_t wait; struct work_struct init_work; @@ -198,14 +249,80 @@ struct mt792x_dev { const struct mt792x_irq_map *irq_map; struct work_struct ipv6_ns_work; + struct delayed_work mlo_pm_work; /* IPv6 addresses for WoWLAN */ struct sk_buff_head ipv6_ns_list; enum environment_cap country_ie_env; u32 backup_l1; u32 backup_l2; + + struct ieee80211_chanctx_conf *new_ctx; }; +static inline struct mt792x_bss_conf * +mt792x_vif_to_link(struct mt792x_vif *mvif, u8 link_id) +{ + struct ieee80211_vif *vif; + struct mt792x_bss_conf *bss_conf; + + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); + + if (!ieee80211_vif_is_mld(vif) || + link_id >= IEEE80211_LINK_UNSPECIFIED) + return &mvif->bss_conf; + + bss_conf = rcu_dereference_protected(mvif->link_conf[link_id], + lockdep_is_held(&mvif->phy->dev->mt76.mutex)); + + return bss_conf ? bss_conf : &mvif->bss_conf; +} + +static inline struct mt792x_link_sta * +mt792x_sta_to_link(struct mt792x_sta *msta, u8 link_id) +{ + struct ieee80211_vif *vif; + + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + + if (!ieee80211_vif_is_mld(vif) || + link_id >= IEEE80211_LINK_UNSPECIFIED) + return &msta->deflink; + + return rcu_dereference_protected(msta->link[link_id], + lockdep_is_held(&msta->vif->phy->dev->mt76.mutex)); +} + +static inline struct mt792x_bss_conf * +mt792x_link_conf_to_mconf(struct ieee80211_bss_conf *link_conf) +{ + struct ieee80211_vif *vif = link_conf->vif; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + return mt792x_vif_to_link(mvif, link_conf->link_id); +} + +static inline struct ieee80211_bss_conf * +mt792x_vif_to_bss_conf(struct ieee80211_vif *vif, unsigned int link_id) +{ + if (!ieee80211_vif_is_mld(vif) || + link_id >= IEEE80211_LINK_UNSPECIFIED) + return &vif->bss_conf; + + return link_conf_dereference_protected(vif, link_id); +} + +static inline struct ieee80211_link_sta * +mt792x_sta_to_link_sta(struct ieee80211_vif *vif, struct ieee80211_sta *sta, + unsigned int link_id) +{ + if (!ieee80211_vif_is_mld(vif) || + link_id >= IEEE80211_LINK_UNSPECIFIED) + return &sta->deflink; + + return link_sta_dereference_protected(sta, link_id); +} + static inline struct mt792x_dev * mt792x_hw_dev(struct ieee80211_hw *hw) { @@ -246,7 +363,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_stop(struct ieee80211_hw *hw, bool suspend); 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); @@ -273,6 +390,7 @@ void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp); void mt792x_tx_worker(struct mt76_worker *w); void mt792x_roc_timer(struct timer_list *timer); +void mt792x_csa_timer(struct timer_list *timer); void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, @@ -320,10 +438,16 @@ mt792x_get_mac80211_ops(struct device *dev, int mt792x_init_wcid(struct mt792x_dev *dev); int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); +void mt792x_mac_link_bss_remove(struct mt792x_dev *dev, + struct mt792x_bss_conf *mconf, + struct mt792x_link_sta *mlink); +void mt792x_config_mac_addr_list(struct mt792x_dev *dev); static inline char *mt792x_ram_name(struct mt792x_dev *dev) { switch (mt76_chip(&dev->mt76)) { + case 0x7920: + return MT7920_FIRMWARE_WM; case 0x7922: return MT7922_FIRMWARE_WM; case 0x7925: @@ -336,6 +460,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev) static inline char *mt792x_patch_name(struct mt792x_dev *dev) { switch (mt76_chip(&dev->mt76)) { + case 0x7920: + return MT7920_ROM_PATCH; case 0x7922: return MT7922_ROM_PATCH; case 0x7925: @@ -359,7 +485,7 @@ 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); +void mt792xu_stop(struct ieee80211_hw *hw, bool suspend); static inline void mt792x_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, @@ -382,7 +508,7 @@ int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev); int mt792x_init_acpi_sar(struct mt792x_dev *dev); int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); u8 mt792x_acpi_get_flags(struct mt792x_phy *phy); -u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2); +u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2); #else static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev) { @@ -400,9 +526,9 @@ static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) return 0; } -static inline u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) +static inline u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) { - return 0xf; + return MT792X_ACPI_MTCL_INVALID; } #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c index e7afea87e82e..d1aebadd50aa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c @@ -4,6 +4,28 @@ #include <linux/acpi.h> #include "mt792x.h" +static const char * const cc_list_all[] = { + "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR", + "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME", + "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR", + "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY", +}; + +static const char * const cc_list_eu[] = { + "AD", "AT", "BE", "BG", "CY", "CZ", "HR", "DK", + "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE", + "IT", "LV", "LI", "LT", "LU", "MC", "MT", "NL", + "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", + "CH", +}; + +static const char * const cc_list_be[] = { + "AR", "BR", "BY", "CL", "IQ", "MX", "OM", "RU", + "RW", "VN", "KR", "UA", "", "", "", "", + "EU", "AT", "CN", "CA", "TW", "NZ", "PH", "UK", + "US", +}; + static int mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) { @@ -66,13 +88,24 @@ free: } /* MTCL : Country List Table for 6G band */ -static void +/* MTCL : Country List Table for 6G band and 11BE */ +static int mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) { - if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0) - *version = 1; + int len, ret; + + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, &len); + if (ret) + return ret; + + if (len == sizeof(struct mt792x_asar_cl)) + *version = ((struct mt792x_asar_cl *)*table)->version; + else if (len == sizeof(struct mt792x_asar_cl_v3)) + *version = ((struct mt792x_asar_cl_v3 *)*table)->version; else - *version = 2; + return -EINVAL; + + return ret; } /* MTDS : Dynamic SAR Power Table */ @@ -166,16 +199,16 @@ int mt792x_init_acpi_sar(struct mt792x_dev *dev) if (!asar) return -ENOMEM; - mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + ret = mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->countrylist); + asar->countrylist = NULL; + } - /* MTDS is mandatory. Return error if table is invalid */ ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); if (ret) { devm_kfree(dev->mt76.dev, asar->dyn); - devm_kfree(dev->mt76.dev, asar->countrylist); - devm_kfree(dev->mt76.dev, asar); - - return ret; + asar->dyn = NULL; } /* MTGS is optional */ @@ -290,7 +323,7 @@ int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; int i; - if (!phy->acpisar) + if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn) return 0; /* When ACPI SAR enabled in HW, we should apply rules for .frp @@ -349,43 +382,75 @@ u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) } EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags); -static u8 +static u32 +mt792x_acpi_get_mtcl_map_v3(int row, int column, struct mt792x_asar_cl_v3 *cl) +{ + u32 config = 0; + u8 mode_be = 0; + + mode_be = (cl->mode_be > 0x02) ? 0 : cl->mode_be; + + if (cl->version > 2 && cl->clbe[row] & BIT(column)) + config |= (mode_be & 0x3) << 4; + + return config; +} + +static u32 mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl) { - u8 config = 0; + u32 config = 0; + u8 mode_6g, mode_5g9; - if (cl->cl6g[row] & BIT(column)) - config |= (cl->mode_6g & 0x3) << 2; + mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g; + mode_5g9 = (cl->mode_5g9 > 0x01) ? 0 : cl->mode_5g9; + + if ((cl->cl6g[row] & BIT(column)) || cl->mode_6g == 0x02) + config |= (mode_6g & 0x3) << 2; if (cl->version > 1 && cl->cl5g9[row] & BIT(column)) - config |= (cl->mode_5g9 & 0x3); + config |= (mode_5g9 & 0x3); return config; } -u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) +static u32 +mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy *phy, char *alpha2) { - static const char * const cc_list_all[] = { - "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR", - "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME", - "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR", - "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY", - }; - static const char * const cc_list_eu[] = { - "AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE", - "FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT", - "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", - "PT", "RO", "MT", "SK", "SI", "ES", "CH", - }; struct mt792x_acpi_sar *sar = phy->acpisar; - struct mt792x_asar_cl *cl; + struct mt792x_asar_cl_v3 *cl = sar->countrylist_v3; int col, row, i; - if (!sar) - return 0xf; + if (sar->ver != 3) + goto out; + + if (!cl) + return MT792X_ACPI_MTCL_INVALID; + + for (i = 0; i < ARRAY_SIZE(cc_list_be); i++) { + col = 7 - i % 8; + row = i / 8; + if (!memcmp(cc_list_be[i], alpha2, 2)) + return mt792x_acpi_get_mtcl_map_v3(row, col, cl); + } + for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++) { + if (!memcmp(cc_list_eu[i], alpha2, 2)) + return mt792x_acpi_get_mtcl_map_v3(3, 7, cl); + } + +out: + /* Depends on driver */ + return 0x20; +} + +static u32 +mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy *phy, char *alpha2) +{ + struct mt792x_acpi_sar *sar = phy->acpisar; + struct mt792x_asar_cl *cl = sar->countrylist; + int col, row, i; - cl = sar->countrylist; if (!cl) - return 0xc; + return MT792X_ACPI_MTCL_INVALID; for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) { col = 7 - i % 8; @@ -400,4 +465,22 @@ u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) return mt792x_acpi_get_mtcl_map(0, 7, cl); } + +u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2) +{ + struct mt792x_acpi_sar *sar = phy->acpisar; + u32 config = 0; + + if (!sar) + return MT792X_ACPI_MTCL_INVALID; + + config = mt792x_acpi_parse_mtcl_tbl_v3(phy, alpha2); + + if (config == MT792X_ACPI_MTCL_INVALID) + return MT792X_ACPI_MTCL_INVALID; + + config |= mt792x_acpi_parse_mtcl_tbl(phy, alpha2); + + return config; +} EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h index 2298983b6342..e45dcd7fbdb1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h @@ -15,6 +15,8 @@ #define MT792x_ACPI_MTGS "MTGS" #define MT792x_ACPI_MTFG "MTFG" +#define MT792X_ACPI_MTCL_INVALID 0xffffffff + struct mt792x_asar_dyn_limit { u8 idx; u8 frp[5]; @@ -72,6 +74,17 @@ struct mt792x_asar_geo_v2 { DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl); } __packed; +struct mt792x_asar_cl_v3 { + u8 names[4]; + u8 version; + u8 mode_6g; + u8 cl6g[6]; + u8 mode_5g9; + u8 cl5g9[6]; + u8 mode_be; + u8 clbe[6]; +} __packed; + struct mt792x_asar_cl { u8 names[4]; u8 version; @@ -100,7 +113,10 @@ struct mt792x_acpi_sar { struct mt792x_asar_geo *geo; struct mt792x_asar_geo_v2 *geo_v2; }; - struct mt792x_asar_cl *countrylist; + union { + struct mt792x_asar_cl *countrylist; + struct mt792x_asar_cl_v3 *countrylist_v3; + }; struct mt792x_asar_fg *fg; }; diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index c42101aa9e45..38dd58f6e493 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -38,6 +38,10 @@ static const struct ieee80211_iface_limit if_limits_chanctx[] = { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_DEVICE) } }; @@ -45,7 +49,7 @@ static const struct ieee80211_iface_combination if_comb_chanctx[] = { { .limits = if_limits_chanctx, .n_limits = ARRAY_SIZE(if_limits_chanctx), - .max_interfaces = 2, + .max_interfaces = 3, .num_different_channels = 2, .beacon_int_infra_match = false, } @@ -59,20 +63,42 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; + u8 link_id; int qid; if (control->sta) { + struct mt792x_link_sta *mlink; struct mt792x_sta *sta; - + link_id = u32_get_bits(info->control.flags, + IEEE80211_TX_CTRL_MLO_LINK); sta = (struct mt792x_sta *)control->sta->drv_priv; - wcid = &sta->wcid; + mlink = mt792x_sta_to_link(sta, link_id); + wcid = &mlink->wcid; } if (vif && !control->sta) { struct mt792x_vif *mvif; mvif = (struct mt792x_vif *)vif->drv_priv; - wcid = &mvif->sta.wcid; + wcid = &mvif->sta.deflink.wcid; + } + + if (vif && control->sta && ieee80211_vif_is_mld(vif)) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_link_sta *link_sta; + struct ieee80211_bss_conf *conf; + + link_id = wcid->link_id; + rcu_read_lock(); + conf = rcu_dereference(vif->link_conf[link_id]); + memcpy(hdr->addr2, conf->addr, ETH_ALEN); + + link_sta = rcu_dereference(control->sta->link[link_id]); + memcpy(hdr->addr1, link_sta->addr, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_STATION) + memcpy(hdr->addr3, conf->bssid, ETH_ALEN); + rcu_read_unlock(); } if (mt76_connac_pm_ref(mphy, &dev->pm)) { @@ -91,7 +117,7 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, } EXPORT_SYMBOL_GPL(mt792x_tx); -void mt792x_stop(struct ieee80211_hw *hw) +void mt792x_stop(struct ieee80211_hw *hw, bool suspend) { struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt792x_hw_phy(hw); @@ -113,31 +139,48 @@ void mt792x_stop(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(mt792x_stop); +void mt792x_mac_link_bss_remove(struct mt792x_dev *dev, + struct mt792x_bss_conf *mconf, + struct mt792x_link_sta *mlink) +{ + struct ieee80211_vif *vif = container_of((void *)mconf->vif, + struct ieee80211_vif, drv_priv); + struct ieee80211_bss_conf *link_conf; + int idx = mlink->wcid.idx; + + link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id); + + mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid); + mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mconf->mt76, + &mlink->wcid, false); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + + dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx); + mconf->vif->phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx); + + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&mlink->wcid.poll_list)) + list_del_init(&mlink->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + mt76_wcid_cleanup(&dev->mt76, &mlink->wcid); +} +EXPORT_SYMBOL_GPL(mt792x_mac_link_bss_remove); + void mt792x_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_sta *msta = &mvif->sta; struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt792x_hw_phy(hw); - int idx = msta->wcid.idx; + struct mt792x_bss_conf *mconf; mt792x_mutex_acquire(dev); - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); - rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + mconf = mt792x_link_conf_to_mconf(&vif->bss_conf); + mt792x_mac_link_bss_remove(dev, mconf, &mvif->sta.deflink); - dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); - phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt792x_mutex_release(dev); - - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); - - mt76_wcid_cleanup(&dev->mt76, &msta->wcid); } EXPORT_SYMBOL_GPL(mt792x_remove_interface); @@ -149,7 +192,7 @@ int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* no need to update right away, we'll get BSS_CHANGED_QOS */ queue = mt76_connac_lmac_mapping(queue); - mvif->queue_params[queue] = *params; + mvif->bss_conf.queue_params[queue] = *params; return 0; } @@ -178,7 +221,7 @@ u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; + u8 omac_idx = mvif->bss_conf.mt76.omac_idx; union { u64 t64; u32 t32[2]; @@ -204,7 +247,7 @@ void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; + u8 omac_idx = mvif->bss_conf.mt76.omac_idx; union { u64 t64; u32 t32[2]; @@ -246,6 +289,14 @@ void mt792x_roc_timer(struct timer_list *timer) } EXPORT_SYMBOL_GPL(mt792x_roc_timer); +void mt792x_csa_timer(struct timer_list *timer) +{ + struct mt792x_vif *mvif = from_timer(mvif, timer, csa_timer); + + ieee80211_queue_work(mvif->phy->mt76->hw, &mvif->csa_work); +} +EXPORT_SYMBOL_GPL(mt792x_csa_timer); + void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { @@ -261,11 +312,13 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->mt76.ctx = ctx; + mvif->bss_conf.mt76.ctx = ctx; + mctx->bss_conf = &mvif->bss_conf; mutex_unlock(&dev->mt76.mutex); return 0; @@ -277,12 +330,19 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->mt76.ctx = NULL; + mctx->bss_conf = NULL; + mvif->bss_conf.mt76.ctx = NULL; mutex_unlock(&dev->mt76.mutex); + + if (vif->bss_conf.csa_active) { + timer_delete_sync(&mvif->csa_timer); + cancel_work_sync(&mvif->csa_work); + } } EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx); @@ -354,6 +414,7 @@ static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_bw_40", "v_tx_bw_80", "v_tx_bw_160", + "v_tx_bw_320", "v_tx_mcs_0", "v_tx_mcs_1", "v_tx_mcs_2", @@ -404,10 +465,10 @@ mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt76_ethtool_worker_info *wi = wi_data; - if (msta->vif->mt76.idx != wi->idx) + if (msta->vif->bss_conf.mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->wcid.stats, true); + mt76_ethtool_worker(wi, &msta->deflink.wcid.stats, true); } void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -420,7 +481,7 @@ void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, - .idx = mvif->mt76.idx, + .idx = mvif->bss_conf.mt76.idx, }; int i, ei = 0; @@ -486,7 +547,7 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, struct station_info *sinfo) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct rate_info *txrate = &msta->wcid.rate; + struct rate_info *txrate = &msta->deflink.wcid.rate; if (!txrate->legacy && !txrate->flags) return; @@ -501,19 +562,19 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, sinfo->txrate.he_dcm = txrate->he_dcm; sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; } - sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->tx_failed = msta->deflink.wcid.stats.tx_failed; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->tx_retries = msta->deflink.wcid.stats.tx_retries; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); - sinfo->ack_signal = (s8)msta->ack_signal; + sinfo->ack_signal = (s8)msta->deflink.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->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->deflink.avg_ack_signal); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); } EXPORT_SYMBOL_GPL(mt792x_sta_statistics); @@ -555,6 +616,7 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) hw->sta_data_size = sizeof(struct mt792x_sta); hw->vif_data_size = sizeof(struct mt792x_vif); + hw->chanctx_data_size = sizeof(struct mt792x_chanctx); if (dev->fw_features & MT792x_FW_CAP_CNM) { wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; @@ -570,7 +632,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_DEVICE); wiphy->max_remain_on_channel_duration = 5000; wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_scan_ssids = 4; @@ -602,6 +665,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); ieee80211_hw_set(hw, CONNECTION_MONITOR); + if (is_mt7921(&dev->mt76)) + ieee80211_hw_set(hw, CHANCTX_STA_CSA); if (dev->pm.enable) ieee80211_hw_set(hw, CONNECTION_MONITOR); @@ -684,9 +749,10 @@ mt792x_get_mac80211_ops(struct device *dev, if (!(*fw_features & MT792x_FW_CAP_CNM)) { ops->remain_on_channel = NULL; ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; + ops->add_chanctx = ieee80211_emulate_add_chanctx; + ops->remove_chanctx = ieee80211_emulate_remove_chanctx; + ops->change_chanctx = ieee80211_emulate_change_chanctx; + ops->switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx; ops->assign_vif_chanctx = NULL; ops->unassign_vif_chanctx = NULL; ops->mgd_prepare_tx = NULL; @@ -764,6 +830,10 @@ int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); + + if (dev->aspm_supported) + usleep_range(2000, 3000); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) break; @@ -862,6 +932,28 @@ int mt792x_load_firmware(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792x_load_firmware); +void mt792x_config_mac_addr_list(struct mt792x_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + struct wiphy *wiphy = hw->wiphy; + int i; + + for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) { + u8 *addr = dev->macaddr_list[i].addr; + + memcpy(addr, dev->mphy.macaddr, ETH_ALEN); + + if (!i) + continue; + + addr[0] |= BIT(1); + addr[0] ^= ((i - 1) << 2); + } + wiphy->addresses = dev->macaddr_list; + wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list); +} +EXPORT_SYMBOL_GPL(mt792x_config_mac_addr_list); + MODULE_DESCRIPTION("MediaTek MT792x core driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c index 488326ce5ed4..6f9db782338e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c @@ -12,6 +12,8 @@ irqreturn_t mt792x_irq_handler(int irq, void *dev_instance) { struct mt792x_dev *dev = dev_instance; + if (test_bit(MT76_REMOVED, &dev->mt76.phy.state)) + return IRQ_NONE; mt76_wr(dev, dev->irq_map->host_irq_enable, 0); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) @@ -123,14 +125,13 @@ static void mt792x_dma_prefetch(struct mt792x_dev *dev) 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); /* reset dma idx */ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); + if (is_mt7925(&dev->mt76)) + mt76_wr(dev, MT_WFDMA0_RST_DRX_PTR, ~0); /* configure delay interrupt */ mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); @@ -140,12 +141,20 @@ int mt792x_dma_enable(struct mt792x_dev *dev) MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + FIELD_PREP(MT_WFDMA0_GLO_CFG_DMA_SIZE, 3) | + MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK | + MT_WFDMA0_GLO_CFG_RX_WB_DDONE | MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); mt76_set(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + if (is_mt7925(&dev->mt76)) { + mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28)); + mt76_set(dev, MT_WFDMA0_INT_RX_PRI, 0x0F00); + mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00); + } mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); /* enable interrupts for TX/RX rings */ @@ -331,7 +340,7 @@ int mt792x_poll_rx(struct napi_struct *napi, int budget) struct mt792x_dev *dev; int done; - dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); + dev = mt76_priv(napi->dev); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { napi_complete(napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c index eb29434abee1..05978d9c7b91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -138,6 +138,7 @@ EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats); struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, bool unicast) { + struct mt792x_link_sta *link; struct mt792x_sta *sta; struct mt76_wcid *wcid; @@ -151,11 +152,12 @@ struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, if (!wcid->sta) return NULL; - sta = container_of(wcid, struct mt792x_sta, wcid); + link = container_of(wcid, struct mt792x_link_sta, wcid); + sta = link->sta; if (!sta->vif) return NULL; - return &sta->vif->sta.wcid; + return &sta->vif->sta.deflink.wcid; } EXPORT_SYMBOL_GPL(mt792x_rx_get_wcid); @@ -173,7 +175,7 @@ mt792x_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!ether_addr_equal(vif->addr, hdr->addr1)) return; - ewma_rssi_add(&mvif->rssi, -status->signal); + ewma_rssi_add(&mvif->bss_conf.rssi, -status->signal); } void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb) diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h index a99af23e4b56..458cfd0260b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -292,9 +292,12 @@ #define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1) #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) #define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MT_WFDMA0_GLO_CFG_DMA_SIZE GENMASK(5, 4) #define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) #define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) +#define MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK BIT(11) #define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) +#define MT_WFDMA0_GLO_CFG_RX_WB_DDONE BIT(13) #define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) @@ -322,6 +325,8 @@ #define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) #define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280) +#define MT_WFDMA0_INT_RX_PRI MT_WFDMA0(0x298) +#define MT_WFDMA0_INT_TX_PRI MT_WFDMA0(0x29c) #define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) #define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6) #define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) @@ -389,6 +394,9 @@ #define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 +#define MT_HW_EMI_CTL 0x18011100 +#define MT_HW_EMI_CTL_SLPPROT_EN BIT(1) + #define MT_PCIE_MAC_BASE 0x10000 #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c index 589a3efb9f8c..76272a03b22e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c @@ -121,44 +121,25 @@ static void mt792xu_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) static void mt792xu_dma_prefetch(struct mt792x_dev *dev) { - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_BASE_PTR_MASK, 0x80); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_BASE_PTR_MASK, 0xc0); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_BASE_PTR_MASK, 0x100); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_BASE_PTR_MASK, 0x140); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_BASE_PTR_MASK, 0x180); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_BASE_PTR_MASK, 0x280); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_BASE_PTR_MASK, 0x2c0); +#define DMA_PREFETCH_CONF(_idx_, _cnt_, _base_) \ + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL((_idx_)), \ + MT_WPDMA0_MAX_CNT_MASK | MT_WPDMA0_BASE_PTR_MASK, \ + FIELD_PREP(MT_WPDMA0_MAX_CNT_MASK, (_cnt_)) | \ + FIELD_PREP(MT_WPDMA0_BASE_PTR_MASK, (_base_))) + + DMA_PREFETCH_CONF(0, 4, 0x080); + DMA_PREFETCH_CONF(1, 4, 0x0c0); + DMA_PREFETCH_CONF(2, 4, 0x100); + DMA_PREFETCH_CONF(3, 4, 0x140); + DMA_PREFETCH_CONF(4, 4, 0x180); + DMA_PREFETCH_CONF(16, 4, 0x280); + DMA_PREFETCH_CONF(17, 4, 0x2c0); } static void mt792xu_wfdma_init(struct mt792x_dev *dev) { + int i; + mt792xu_dma_prefetch(dev); mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); @@ -169,10 +150,27 @@ static void mt792xu_wfdma_init(struct mt792x_dev *dev) MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - /* disable dmashdl */ - mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + mt76_rmw(dev, MT_DMASHDL_REFILL, MT_DMASHDL_REFILL_MASK, 0xffe00000); + mt76_clear(dev, MT_DMASHDL_PAGE, MT_DMASHDL_GROUP_SEQ_ORDER); + mt76_rmw(dev, MT_DMASHDL_PKT_MAX_SIZE, + MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE, + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) | + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 0)); + for (i = 0; i < 5; i++) + mt76_wr(dev, MT_DMASHDL_GROUP_QUOTA(i), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x3) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0xfff)); + for (i = 5; i < 16; i++) + mt76_wr(dev, MT_DMASHDL_GROUP_QUOTA(i), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x0) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x0)); + mt76_wr(dev, MT_DMASHDL_Q_MAP(0), 0x32013201); + mt76_wr(dev, MT_DMASHDL_Q_MAP(1), 0x32013201); + mt76_wr(dev, MT_DMASHDL_Q_MAP(2), 0x55555444); + mt76_wr(dev, MT_DMASHDL_Q_MAP(3), 0x55555444); + + mt76_wr(dev, MT_DMASHDL_SCHED_SET(0), 0x76540132); + mt76_wr(dev, MT_DMASHDL_SCHED_SET(1), 0xFEDCBA98); mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); } @@ -287,12 +285,12 @@ int mt792xu_init_reset(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792xu_init_reset); -void mt792xu_stop(struct ieee80211_hw *hw) +void mt792xu_stop(struct ieee80211_hw *hw, bool suspend) { struct mt792x_dev *dev = mt792x_hw_dev(hw); mt76u_stop_tx(&dev->mt76); - mt792x_stop(hw); + mt792x_stop(hw, false); } EXPORT_SYMBOL_GPL(mt792xu_stop); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c index ccab0d7b9be4..303d6e80a666 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c @@ -48,8 +48,8 @@ const struct mt7996_mem_region* mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num) { switch (mt76_chip(&dev->mt76)) { - case 0x7990: - case 0x7991: + case MT7996_DEVICE_ID: + case MT7996_DEVICE_ID_2: *num = ARRAY_SIZE(mt7996_mem_regions); return &mt7996_mem_regions[0]; default: diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 9bd953586b04..0ab827f52fd7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -51,12 +51,10 @@ static ssize_t mt7996_sys_recovery_set(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct mt7996_phy *phy = file->private_data; - struct mt7996_dev *dev = phy->dev; - bool band = phy->mt76->band_idx; - char buf[16]; + struct mt7996_dev *dev = file->private_data; + char buf[16], *sep; int ret = 0; - u16 val; + u16 band, val; if (count >= sizeof(buf)) return -EINVAL; @@ -69,21 +67,26 @@ mt7996_sys_recovery_set(struct file *file, const char __user *user_buf, else buf[count] = '\0'; - if (kstrtou16(buf, 0, &val)) + sep = strchr(buf, ','); + if (!sep) + return -EINVAL; + + *sep = 0; + if (kstrtou16(buf, 0, &band) || kstrtou16(sep + 1, 0, &val)) return -EINVAL; switch (val) { /* - * 0: grab firmware current SER state. - * 1: trigger & enable system error L1 recovery. - * 2: trigger & enable system error L2 recovery. - * 3: trigger & enable system error L3 rx abort. - * 4: trigger & enable system error L3 tx abort - * 5: trigger & enable system error L3 tx disable. - * 6: trigger & enable system error L3 bf recovery. - * 7: trigger & enable system error L4 mdp recovery. - * 8: trigger & enable system error full recovery. - * 9: trigger firmware crash. + * <band>,0: grab firmware current SER state. + * <band>,1: trigger & enable system error L1 recovery. + * <band>,2: trigger & enable system error L2 recovery. + * <band>,3: trigger & enable system error L3 rx abort. + * <band>,4: trigger & enable system error L3 tx abort + * <band>,5: trigger & enable system error L3 tx disable. + * <band>,6: trigger & enable system error L3 bf recovery. + * <band>,7: trigger & enable system error L4 mdp recovery. + * <band>,8: trigger & enable system error full recovery. + * <band>,9: trigger firmware crash. */ case UNI_CMD_SER_QUERY: ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band); @@ -126,8 +129,7 @@ static ssize_t mt7996_sys_recovery_get(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct mt7996_phy *phy = file->private_data; - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = file->private_data; char *buff; int desc = 0; ssize_t ret; @@ -141,25 +143,25 @@ mt7996_sys_recovery_get(struct file *file, char __user *user_buf, desc += scnprintf(buff + desc, bufsz - desc, "Please echo the correct value ...\n"); desc += scnprintf(buff + desc, bufsz - desc, - "0: grab firmware transient SER state\n"); + "<band>,0: grab firmware transient SER state\n"); desc += scnprintf(buff + desc, bufsz - desc, - "1: trigger system error L1 recovery\n"); + "<band>,1: trigger system error L1 recovery\n"); desc += scnprintf(buff + desc, bufsz - desc, - "2: trigger system error L2 recovery\n"); + "<band>,2: trigger system error L2 recovery\n"); desc += scnprintf(buff + desc, bufsz - desc, - "3: trigger system error L3 rx abort\n"); + "<band>,3: trigger system error L3 rx abort\n"); desc += scnprintf(buff + desc, bufsz - desc, - "4: trigger system error L3 tx abort\n"); + "<band>,4: trigger system error L3 tx abort\n"); desc += scnprintf(buff + desc, bufsz - desc, - "5: trigger system error L3 tx disable\n"); + "<band>,5: trigger system error L3 tx disable\n"); desc += scnprintf(buff + desc, bufsz - desc, - "6: trigger system error L3 bf recovery\n"); + "<band>,6: trigger system error L3 bf recovery\n"); desc += scnprintf(buff + desc, bufsz - desc, - "7: trigger system error L4 mdp recovery\n"); + "<band>,7: trigger system error L4 mdp recovery\n"); desc += scnprintf(buff + desc, bufsz - desc, - "8: trigger system error full recovery\n"); + "<band>,8: trigger system error full recovery\n"); desc += scnprintf(buff + desc, bufsz - desc, - "9: trigger firmware crash\n"); + "<band>,9: trigger firmware crash\n"); /* SER statistics */ desc += scnprintf(buff + desc, bufsz - desc, @@ -220,13 +222,27 @@ static const struct file_operations mt7996_sys_recovery_ops = { static int mt7996_radar_trigger(void *data, u64 val) { +#define RADAR_MAIN_CHAIN 1 +#define RADAR_BACKGROUND 2 struct mt7996_dev *dev = data; + struct mt7996_phy *phy = mt7996_band_phy(dev, NL80211_BAND_5GHZ); + int rdd_idx; + + if (!phy || !val || val > RADAR_BACKGROUND) + return -EINVAL; - if (val > MT_RX_SEL2) + if (val == RADAR_BACKGROUND && !dev->rdd2_phy) { + dev_err(dev->mt76.dev, "Background radar is not enabled\n"); return -EINVAL; + } + + rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND); + if (rdd_idx < 0) { + dev_err(dev->mt76.dev, "No RDD found\n"); + return -EINVAL; + } - return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, - val, 0, 0); + return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0); } DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, @@ -519,16 +535,12 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s) seq_puts(s, "\n"); } -static int -mt7996_tx_stats_show(struct seq_file *file, void *data) +static void +mt7996_tx_stats_show_phy(struct seq_file *file, struct mt7996_phy *phy) { - struct mt7996_phy *phy = file->private; - struct mt7996_dev *dev = phy->dev; struct mt76_mib_stats *mib = &phy->mib; - int i; u32 attempts, success, per; - - mutex_lock(&dev->mt76.mutex); + int i; mt7996_mac_update_stats(phy); mt7996_ampdu_stat_read_phy(phy, file); @@ -553,6 +565,23 @@ mt7996_tx_stats_show(struct seq_file *file, void *data) else seq_puts(file, "\n"); } +} + +static int +mt7996_tx_stats_show(struct seq_file *file, void *data) +{ + struct mt7996_dev *dev = file->private; + struct mt7996_phy *phy = &dev->phy; + + mutex_lock(&dev->mt76.mutex); + + mt7996_tx_stats_show_phy(file, phy); + phy = mt7996_phy2(dev); + if (phy) + mt7996_tx_stats_show_phy(file, phy); + phy = mt7996_phy3(dev); + if (phy) + mt7996_tx_stats_show_phy(file, phy); mutex_unlock(&dev->mt76.mutex); @@ -596,35 +625,58 @@ static void mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta) { struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct mt7996_dev *dev = msta->vif->phy->dev; + struct mt7996_vif *mvif = msta->vif; + struct mt7996_dev *dev = mvif->deflink.phy->dev; + struct ieee80211_link_sta *link_sta; struct seq_file *s = data; - u8 ac; + struct ieee80211_vif *vif; + unsigned int link_id; - for (ac = 0; ac < 4; ac++) { - u32 qlen, ctrl, val; - u32 idx = msta->wcid.idx >> 5; - u8 offs = msta->wcid.idx & GENMASK(4, 0); + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); - ctrl = BIT(31) | BIT(11) | (ac << 24); - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx)); + rcu_read_lock(); + + for_each_sta_active_link(vif, sta, link_sta, link_id) { + struct mt7996_sta_link *msta_link; + struct mt76_vif_link *mlink; + u8 ac; - if (val & BIT(offs)) + mlink = rcu_dereference(mvif->mt76.link[link_id]); + if (!mlink) continue; - mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx); - qlen = mt76_get_field(dev, MT_FL_Q3_CTRL, - GENMASK(11, 0)); - seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n", - sta->addr, msta->wcid.idx, - msta->vif->mt76.wmm_idx, ac, qlen); + msta_link = rcu_dereference(msta->link[link_id]); + if (!msta_link) + continue; + + for (ac = 0; ac < 4; ac++) { + u32 idx = msta_link->wcid.idx >> 5, qlen, ctrl, val; + u8 offs = msta_link->wcid.idx & GENMASK(4, 0); + + ctrl = BIT(31) | BIT(11) | (ac << 24); + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx)); + + if (val & BIT(offs)) + continue; + + mt76_wr(dev, + MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx); + qlen = mt76_get_field(dev, MT_FL_Q3_CTRL, + GENMASK(11, 0)); + seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n", + sta->addr, msta_link->wcid.idx, + mlink->wmm_idx, ac, qlen); + } } + + rcu_read_unlock(); } static int mt7996_hw_queues_show(struct seq_file *file, void *data) { - struct mt7996_phy *phy = file->private; - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = file->private; + struct mt7996_phy *phy = &dev->phy; static const struct hw_queue_map ple_queue_map[] = { { "CPU_Q0", 0, 1, MT_CTX0 }, { "CPU_Q1", 1, 1, MT_CTX0 + 1 }, @@ -680,6 +732,15 @@ mt7996_hw_queues_show(struct seq_file *file, void *data) /* iterate per-sta ple queue */ ieee80211_iterate_stations_atomic(phy->mt76->hw, mt7996_sta_hw_queue_read, file); + phy = mt7996_phy2(dev); + if (phy) + ieee80211_iterate_stations_atomic(phy->mt76->hw, + mt7996_sta_hw_queue_read, file); + phy = mt7996_phy3(dev); + if (phy) + ieee80211_iterate_stations_atomic(phy->mt76->hw, + mt7996_sta_hw_queue_read, file); + /* pse queue */ seq_puts(file, "PSE non-empty queue info:\n"); mt7996_hw_queue_read(file, ARRAY_SIZE(pse_queue_map), @@ -693,19 +754,29 @@ DEFINE_SHOW_ATTRIBUTE(mt7996_hw_queues); static int mt7996_xmit_queues_show(struct seq_file *file, void *data) { - struct mt7996_phy *phy = file->private; - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = file->private; + struct mt7996_phy *phy; struct { struct mt76_queue *q; char *queue; } queue_map[] = { - { phy->mt76->q_tx[MT_TXQ_BE], " MAIN" }, + { dev->mphy.q_tx[MT_TXQ_BE], " MAIN0" }, + { NULL, " MAIN1" }, + { NULL, " MAIN2" }, { dev->mt76.q_mcu[MT_MCUQ_WM], " MCUWM" }, { dev->mt76.q_mcu[MT_MCUQ_WA], " MCUWA" }, { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWDL" }, }; int i; + phy = mt7996_phy2(dev); + if (phy) + queue_map[1].q = phy->mt76->q_tx[MT_TXQ_BE]; + + phy = mt7996_phy3(dev); + if (phy) + queue_map[2].q = phy->mt76->q_tx[MT_TXQ_BE]; + seq_puts(file, " queue | hw-queued | head | tail |\n"); for (i = 0; i < ARRAY_SIZE(queue_map); i++) { struct mt76_queue *q = queue_map[i].q; @@ -780,20 +851,20 @@ mt7996_rf_regval_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get, mt7996_rf_regval_set, "0x%08llx\n"); -int mt7996_init_debugfs(struct mt7996_phy *phy) +int mt7996_init_debugfs(struct mt7996_dev *dev) { - struct mt7996_dev *dev = phy->dev; struct dentry *dir; - dir = mt76_register_debugfs_fops(phy->mt76, NULL); + dir = mt76_register_debugfs_fops(&dev->mphy, NULL); if (!dir) return -ENOMEM; - debugfs_create_file("hw-queues", 0400, dir, phy, + + debugfs_create_file("hw-queues", 0400, dir, dev, &mt7996_hw_queues_fops); - debugfs_create_file("xmit-queues", 0400, dir, phy, + debugfs_create_file("xmit-queues", 0400, dir, dev, &mt7996_xmit_queues_fops); - debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops); - debugfs_create_file("sys_recovery", 0600, dir, phy, + debugfs_create_file("tx_stats", 0400, dir, dev, &mt7996_tx_stats_fops); + debugfs_create_file("sys_recovery", 0600, dir, dev, &mt7996_sys_recovery_ops); debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm); debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa); @@ -807,17 +878,13 @@ int mt7996_init_debugfs(struct mt7996_phy *phy) mt7996_twt_stats); debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); - if (phy->mt76->cap.has_5ghz) { - debugfs_create_u32("dfs_hw_pattern", 0400, dir, - &dev->hw_pattern); - debugfs_create_file("radar_trigger", 0200, dir, dev, - &fops_radar_trigger); - debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, - mt7996_rdd_monitor); - } + debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); + debugfs_create_file("radar_trigger", 0200, dir, dev, + &fops_radar_trigger); + debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, + mt7996_rdd_monitor); - if (phy == &dev->phy) - dev->debugfs_dir = dir; + dev->debugfs_dir = dir; return 0; } @@ -894,7 +961,8 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file, #define LONG_PREAMBLE 1 struct ieee80211_sta *sta = file->private_data; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct mt7996_dev *dev = msta->vif->phy->dev; + struct mt7996_dev *dev = msta->vif->deflink.phy->dev; + struct mt7996_sta_link *msta_link = &msta->deflink; struct ra_rate phy = {}; char buf[100]; int ret; @@ -929,7 +997,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file, goto out; } - phy.wlan_idx = cpu_to_le16(msta->wcid.idx); + phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx); phy.gi = cpu_to_le16(gi); phy.ltf = cpu_to_le16(ltf); phy.ldpc = phy.ldpc ? 7 : 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 483ad81b6eec..c8bef0b2a144 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -55,20 +55,32 @@ static void mt7996_dma_config(struct mt7996_dev *dev) /* rx queue */ RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7996_RXQ_MCU_WM); + /* for mt7990, RX ring 1 is for SDO instead */ RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7996_RXQ_MCU_WA); - - /* mt7996: band0 and band1, mt7992: band0 */ RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7996_RXQ_BAND0); - RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN, MT7996_RXQ_MCU_WA_MAIN); + if (mt7996_has_wa(dev)) + RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN, + MT7996_RXQ_MCU_WA_MAIN); - if (is_mt7996(&dev->mt76)) { + switch (mt76_chip(&dev->mt76)) { + case MT7992_DEVICE_ID: + RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT, MT7996_RXQ_MCU_WA_EXT); + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1); + break; + case MT7990_DEVICE_ID: + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1); + RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, + MT_INT_RX_TXFREE_BAND0_MT7990, MT7990_RXQ_TXFREE0); + if (dev->hif2) + RXQ_CONFIG(MT_RXQ_TXFREE_BAND1, WFDMA0, + MT_INT_RX_TXFREE_BAND1_MT7990, MT7990_RXQ_TXFREE1); + break; + case MT7996_DEVICE_ID: + default: /* mt7996 band2 */ - RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2); RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI); - } else { - /* mt7992 band1 */ - RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1); - RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT, MT7996_RXQ_MCU_WA_EXT); + RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2); + break; } if (dev->has_rro) { @@ -104,9 +116,11 @@ static void mt7996_dma_config(struct mt7996_dev *dev) } /* mcu tx queue */ - MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM); - MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA, MT7996_TXQ_MCU_WA); MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7996_TXQ_FWDL); + MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM); + if (mt7996_has_wa(dev)) + MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA, + MT7996_TXQ_MCU_WA); } static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth) @@ -121,43 +135,62 @@ static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth) static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs) { u16 base = 0; - u8 queue; + u8 queue, val; #define PREFETCH(_depth) (__mt7996_dma_prefetch_base(&base, (_depth))) /* prefetch SRAM wrapping boundary for tx/rx ring. */ - mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x2)); - mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x2)); + /* Tx Command Rings */ + val = is_mt7996(&dev->mt76) ? 2 : 4; + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(val)); + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(val)); + if (mt7996_has_wa(dev)) + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(val)); + + /* Tx Data Rings */ mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x8)); - mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8)); - mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x2)); - mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x2)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x2)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x2)); - - queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2_WA : MT_RXQ_BAND1_WA; - mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x2)); - - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10)); + if (!is_mt7996(&dev->mt76) || dev->hif2) + mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8)); + if (is_mt7996(&dev->mt76)) + mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8)); + + /* Rx Event Rings */ + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(val)); + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(val)); + + /* Rx TxFreeDone From WA Rings */ + if (mt7996_has_wa(dev)) { + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(val)); + queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2_WA : MT_RXQ_BAND1_WA; + mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(val)); + } + /* Rx TxFreeDone From MAC Rings */ + val = is_mt7996(&dev->mt76) ? 4 : 8; + if (is_mt7990(&dev->mt76) || (is_mt7996(&dev->mt76) && dev->has_rro)) + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND0) + ofs, PREFETCH(val)); + if (is_mt7990(&dev->mt76) && dev->hif2) + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND1) + ofs, PREFETCH(val)); + else if (is_mt7996(&dev->mt76) && dev->has_rro) + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND2) + ofs, PREFETCH(val)); + + /* Rx Data Rings */ + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10)); queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2 : MT_RXQ_BAND1; - mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x10)); + mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10)); + /* Rx RRO Rings */ if (dev->has_rro) { - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs, - PREFETCH(0x10)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs, - PREFETCH(0x10)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs, - PREFETCH(0x4)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs, - PREFETCH(0x4)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs, - PREFETCH(0x4)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs, - PREFETCH(0x4)); - mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs, - PREFETCH(0x4)); + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_RRO_BAND0) + ofs, PREFETCH(0x10)); + queue = is_mt7996(&dev->mt76) ? MT_RXQ_RRO_BAND2 : MT_RXQ_RRO_BAND1; + mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10)); + + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs, PREFETCH(val)); + if (is_mt7996(&dev->mt76)) { + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs, + PREFETCH(val)); + mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs, + PREFETCH(val)); + } } #undef PREFETCH @@ -237,7 +270,8 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | + MT_WFDMA0_GLO_CFG_EXT_EN); if (dev->hif2) mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, @@ -268,6 +302,9 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) mtk_wed_device_start(wed, wed_irq_mask); } + if (!mt7996_has_wa(dev)) + irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) | + MT_INT_RX(MT_RXQ_BAND1_WA)); irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; mt7996_irq_enable(dev, irq_mask); @@ -473,12 +510,14 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; /* command to WA */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, - MT_MCUQ_ID(MT_MCUQ_WA), - MT7996_TX_MCU_RING_SIZE, - MT_MCUQ_RING_BASE(MT_MCUQ_WA)); - if (ret) - return ret; + if (mt7996_has_wa(dev)) { + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, + MT_MCUQ_ID(MT_MCUQ_WA), + MT7996_TX_MCU_RING_SIZE, + MT_MCUQ_RING_BASE(MT_MCUQ_WA)); + if (ret) + return ret; + } /* firmware download */ ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, @@ -492,16 +531,16 @@ int mt7996_dma_init(struct mt7996_dev *dev) ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], MT_RXQ_ID(MT_RXQ_MCU), MT7996_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, + MT7996_RX_MCU_BUF_SIZE, MT_RXQ_RING_BASE(MT_RXQ_MCU)); if (ret) return ret; - /* event from WA */ + /* event from WA, or SDO event for mt7990 */ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], MT_RXQ_ID(MT_RXQ_MCU_WA), MT7996_RX_MCU_RING_SIZE_WA, - MT_RX_BUF_SIZE, + MT7996_RX_MCU_BUF_SIZE, MT_RXQ_RING_BASE(MT_RXQ_MCU_WA)); if (ret) return ret; @@ -526,13 +565,41 @@ int mt7996_dma_init(struct mt7996_dev *dev) dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed; } - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA], - MT_RXQ_ID(MT_RXQ_MAIN_WA), - MT7996_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, - MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA)); - if (ret) - return ret; + if (mt7996_has_wa(dev)) { + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA], + MT_RXQ_ID(MT_RXQ_MAIN_WA), + MT7996_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA)); + if (ret) + return ret; + } else { + if (mtk_wed_device_active(wed)) { + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0], + MT_RXQ_ID(MT_RXQ_TXFREE_BAND0), + MT7996_RX_MCU_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0)); + if (ret) + return ret; + } + + if (!mt7996_has_wa(dev) && dev->hif2) { + if (mtk_wed_device_active(wed)) { + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1].flags = MT_WED_Q_TXFREE; + dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1].wed = wed; + } + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1], + MT_RXQ_ID(MT_RXQ_TXFREE_BAND1), + MT7996_RX_MCU_RING_SIZE, + MT7996_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND1)); + if (ret) + return ret; + } if (mt7996_band_valid(dev, MT_BAND2)) { /* rx data queue for mt7996 band2 */ @@ -572,14 +639,16 @@ int mt7996_dma_init(struct mt7996_dev *dev) return ret; /* tx free notify event from WA for mt7992 band1 */ - rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs; - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA], - MT_RXQ_ID(MT_RXQ_BAND1_WA), - MT7996_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, - rx_base); - if (ret) - return ret; + if (mt7996_has_wa(dev)) { + rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA], + MT_RXQ_ID(MT_RXQ_BAND1_WA), + MT7996_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, + rx_base); + if (ret) + return ret; + } } if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) && @@ -640,7 +709,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) if (ret < 0) return ret; - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7996_poll_tx); napi_enable(&dev->mt76.tx_napi); @@ -694,7 +763,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force) mtk_wed_device_dma_reset(&dev->mt76.mmio.wed); mt7996_dma_disable(dev, force); - mt76_dma_wed_reset(&dev->mt76); + mt76_wed_dma_reset(&dev->mt76); /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c index 4a8237118287..87c6192b6384 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c @@ -13,10 +13,12 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev) u16 val = get_unaligned_le16(eeprom); switch (val) { - case 0x7990: + case MT7996_DEVICE_ID: return is_mt7996(&dev->mt76) ? 0 : -EINVAL; - case 0x7992: + case MT7992_DEVICE_ID: return is_mt7992(&dev->mt76) ? 0 : -EINVAL; + case MT7990_DEVICE_ID: + return is_mt7990(&dev->mt76) ? 0 : -EINVAL; default: return -EINVAL; } @@ -25,17 +27,112 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev) static char *mt7996_eeprom_name(struct mt7996_dev *dev) { switch (mt76_chip(&dev->mt76)) { - case 0x7990: - return MT7996_EEPROM_DEFAULT; - case 0x7992: - return MT7992_EEPROM_DEFAULT; + case MT7992_DEVICE_ID: + switch (dev->var.type) { + case MT7992_VAR_TYPE_23: + if (dev->var.fem == MT7996_FEM_INT) + return MT7992_EEPROM_DEFAULT_23_INT; + return MT7992_EEPROM_DEFAULT_23; + case MT7992_VAR_TYPE_44: + default: + if (dev->var.fem == MT7996_FEM_INT) + return MT7992_EEPROM_DEFAULT_INT; + if (dev->var.fem == MT7996_FEM_MIX) + return MT7992_EEPROM_DEFAULT_MIX; + return MT7992_EEPROM_DEFAULT; + } + case MT7990_DEVICE_ID: + if (dev->var.fem == MT7996_FEM_INT) + return MT7990_EEPROM_DEFAULT_INT; + return MT7990_EEPROM_DEFAULT; + case MT7996_DEVICE_ID: + default: + switch (dev->var.type) { + case MT7996_VAR_TYPE_233: + if (dev->var.fem == MT7996_FEM_INT) + return MT7996_EEPROM_DEFAULT_233_INT; + return MT7996_EEPROM_DEFAULT_233; + case MT7996_VAR_TYPE_444: + default: + if (dev->var.fem == MT7996_FEM_INT) + return MT7996_EEPROM_DEFAULT_INT; + return MT7996_EEPROM_DEFAULT; + } + } +} + +static void +mt7996_eeprom_parse_stream(const u8 *eeprom, u8 band_idx, u8 *path, + u8 *rx_path, u8 *nss) +{ + switch (band_idx) { + case MT_BAND1: + *path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1, + eeprom[MT_EE_WIFI_CONF + 2]); + *rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1, + eeprom[MT_EE_WIFI_CONF + 3]); + *nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1, + eeprom[MT_EE_WIFI_CONF + 5]); + break; + case MT_BAND2: + *path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2, + eeprom[MT_EE_WIFI_CONF + 2]); + *rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2, + eeprom[MT_EE_WIFI_CONF + 4]); + *nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2, + eeprom[MT_EE_WIFI_CONF + 5]); + break; default: - return MT7996_EEPROM_DEFAULT; + *path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0, + eeprom[MT_EE_WIFI_CONF + 1]); + *rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0, + eeprom[MT_EE_WIFI_CONF + 3]); + *nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0, + eeprom[MT_EE_WIFI_CONF + 4]); + break; } } +static bool mt7996_eeprom_variant_valid(struct mt7996_dev *dev, const u8 *def) +{ +#define FEM_INT 0 +#define FEM_EXT 3 + u8 *eeprom = dev->mt76.eeprom.data, fem[2]; + int i; + + for (i = 0; i < 2; i++) + fem[i] = u8_get_bits(eeprom[MT_EE_WIFI_CONF + 6 + i], + MT_EE_WIFI_PA_LNA_CONFIG); + + if (dev->var.fem == MT7996_FEM_EXT && + !(fem[0] == FEM_EXT && fem[1] == FEM_EXT)) + return false; + else if (dev->var.fem == MT7996_FEM_INT && + !(fem[0] == FEM_INT && fem[1] == FEM_INT)) + return false; + else if (dev->var.fem == MT7996_FEM_MIX && + !(fem[0] == FEM_INT && fem[1] == FEM_EXT)) + return false; + + for (i = 0; i < __MT_MAX_BAND; i++) { + u8 path, rx_path, nss; + u8 def_path, def_rx_path, def_nss; + + if (!dev->mt76.phys[i]) + continue; + + mt7996_eeprom_parse_stream(eeprom, i, &path, &rx_path, &nss); + mt7996_eeprom_parse_stream(def, i, &def_path, &def_rx_path, + &def_nss); + if (path > def_path || rx_path > def_rx_path || nss > def_nss) + return false; + } + + return true; +} + static int -mt7996_eeprom_load_default(struct mt7996_dev *dev) +mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default) { u8 *eeprom = dev->mt76.eeprom.data; const struct firmware *fw = NULL; @@ -51,6 +148,10 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev) goto out; } + if (!use_default && mt7996_eeprom_variant_valid(dev, fw->data)) + goto out; + + dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n"); memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE); dev->flash_mode = true; @@ -62,43 +163,68 @@ out: static int mt7996_eeprom_load(struct mt7996_dev *dev) { + bool use_default = false; int ret; ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE); if (ret < 0) return ret; - if (ret) { + if (ret && !mt7996_check_eeprom(dev)) { dev->flash_mode = true; - } else { - u8 free_block_num; - u32 block_num, i; + goto out; + } + + if (!dev->flash_mode) { u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE; + u32 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size); + u8 free_block_num; + int i; + memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE); ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num); if (ret < 0) return ret; /* efuse info isn't enough */ - if (free_block_num >= 59) - return -EINVAL; - - /* read eeprom data from efuse */ - block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size); - for (i = 0; i < block_num; i++) { - ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size); - if (ret < 0) - return ret; + if (free_block_num >= 59) { + use_default = true; + goto out; + } + + /* check if eeprom data from fw is valid */ + if (mt7996_mcu_get_eeprom(dev, 0, NULL, 0) || + mt7996_check_eeprom(dev)) { + use_default = true; + goto out; + } + + /* read eeprom data from fw */ + for (i = 1; i < block_num; i++) { + u32 len = eeprom_blk_size; + + if (i == block_num - 1) + len = MT7996_EEPROM_SIZE % eeprom_blk_size; + ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size, + NULL, len); + if (ret && ret != -EINVAL) { + use_default = true; + goto out; + } } } - return mt7996_check_eeprom(dev); +out: + return mt7996_eeprom_check_or_use_default(dev, use_default); } -static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev) +static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_phy *phy, + u8 *path, u8 *rx_path, u8 *nss) { #define MODE_HE_ONLY BIT(0) #define WTBL_SIZE_GROUP GENMASK(31, 28) +#define STREAM_CAP(_offs) ((cap & (0x7 << (_offs))) >> (_offs)) + struct mt7996_dev *dev = phy->dev; u32 cap = 0; int ret; @@ -107,13 +233,17 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev) return ret; if (cap) { + u8 band_offs = phy->mt76->band_idx * 3; + dev->has_eht = !(cap & MODE_HE_ONLY); dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP); + *nss = min_t(u8, *nss, STREAM_CAP(1 + band_offs)); + *path = min_t(u8, *path, STREAM_CAP(10 + band_offs)); + *rx_path = min_t(u8, *rx_path, STREAM_CAP(19 + band_offs)); } - if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4 || - is_mt7992(&dev->mt76)) - dev->wtbl_size_group = 2; /* set default */ + if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4) + dev->wtbl_size_group = is_mt7996(&dev->mt76) ? 4 : 2; return 0; } @@ -163,32 +293,10 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) int max_path = 5, max_nss = 4; int ret; - switch (band_idx) { - case MT_BAND1: - path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1, - eeprom[MT_EE_WIFI_CONF + 2]); - rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1, - eeprom[MT_EE_WIFI_CONF + 3]); - nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1, - eeprom[MT_EE_WIFI_CONF + 5]); - break; - case MT_BAND2: - path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2, - eeprom[MT_EE_WIFI_CONF + 2]); - rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2, - eeprom[MT_EE_WIFI_CONF + 4]); - nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2, - eeprom[MT_EE_WIFI_CONF + 5]); - break; - default: - path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0, - eeprom[MT_EE_WIFI_CONF + 1]); - rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0, - eeprom[MT_EE_WIFI_CONF + 3]); - nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0, - eeprom[MT_EE_WIFI_CONF + 4]); - break; - } + mt7996_eeprom_parse_stream(eeprom, band_idx, &path, &rx_path, &nss); + ret = mt7996_eeprom_parse_efuse_hw_cap(phy, &path, &rx_path, &nss); + if (ret) + return ret; if (!path || path > max_path) path = max_path; @@ -202,16 +310,14 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) phy->has_aux_rx = true; mphy->antenna_mask = BIT(nss) - 1; + phy->orig_antenna_mask = mphy->antenna_mask; mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx]; + phy->orig_chainmask = mphy->chainmask; dev->chainmask |= mphy->chainmask; if (band_idx < MT_BAND2) dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] + hweight16(mphy->chainmask); - ret = mt7996_eeprom_parse_efuse_hw_cap(dev); - if (ret) - return ret; - return mt7996_eeprom_parse_band_config(phy); } @@ -220,15 +326,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev) int ret; ret = mt7996_eeprom_load(dev); - if (ret < 0) { - if (ret != -EINVAL) - return ret; - - dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n"); - ret = mt7996_eeprom_load_default(dev); - if (ret) - return ret; - } + if (ret < 0) + return ret; ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy); if (ret < 0) @@ -278,3 +377,30 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band) return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta; } + +bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case MT7996_DEVICE_ID: + if (dev->var.type == MT7996_VAR_TYPE_233) + return false; + break; + case MT7992_DEVICE_ID: + if (dev->var.type == MT7992_VAR_TYPE_23) + return false; + break; + case MT7990_DEVICE_ID: { + u8 path, rx_path, nss, *eeprom = dev->mt76.eeprom.data; + + mt7996_eeprom_parse_stream(eeprom, MT_BAND1, &path, &rx_path, &nss); + /* Disable background radar capability in 3T3R */ + if (path == 3 || rx_path == 3) + return false; + break; + } + default: + return false; + } + + return true; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h index 412d6e2f8014..7a771ca2434c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h @@ -40,6 +40,8 @@ enum mt7996_eeprom_field { #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0) #define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3) +#define MT_EE_WIFI_PA_LNA_CONFIG GENMASK(1, 0) + #define MT_EE_RATE_DELTA_MASK GENMASK(5, 0) #define MT_EE_RATE_DELTA_SIGN BIT(6) #define MT_EE_RATE_DELTA_EN BIT(7) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 0cf0d1fe420a..a9599c286328 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -14,11 +14,30 @@ #include "coredump.h" #include "eeprom.h" +static const struct ieee80211_iface_limit if_limits_global = { + .max = MT7996_MAX_INTERFACES * MT7996_MAX_RADIOS, + .types = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC) + | BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif +}; + +static const struct ieee80211_iface_combination if_comb_global = { + .limits = &if_limits_global, + .n_limits = 1, + .max_interfaces = MT7996_MAX_INTERFACES * MT7996_MAX_RADIOS, + .num_different_channels = MT7996_MAX_RADIOS, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160), +}; + static const struct ieee80211_iface_limit if_limits[] = { { - .max = 1, - .types = BIT(NL80211_IFTYPE_ADHOC) - }, { .max = 16, .types = BIT(NL80211_IFTYPE_AP) #ifdef CONFIG_MAC80211_MESH @@ -30,19 +49,18 @@ static const struct ieee80211_iface_limit if_limits[] = { } }; -static const struct ieee80211_iface_combination if_comb[] = { - { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = MT7996_MAX_INTERFACES, - .num_different_channels = 1, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40) | - BIT(NL80211_CHAN_WIDTH_80) | - BIT(NL80211_CHAN_WIDTH_160), - } +static const struct ieee80211_iface_combination if_comb = { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = MT7996_MAX_INTERFACES, + .num_different_channels = 1, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160), + .beacon_int_min_gcd = 100, }; static ssize_t mt7996_thermal_temp_show(struct device *dev, @@ -84,7 +102,7 @@ static ssize_t mt7996_thermal_temp_store(struct device *dev, return ret; mutex_lock(&phy->dev->mt76.mutex); - val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130); + val = DIV_ROUND_CLOSEST(clamp_val(val, 40 * 1000, 130 * 1000), 1000); /* add a safety margin ~10 */ if ((i - 1 == MT7996_CRIT_TEMP_IDX && @@ -179,28 +197,35 @@ static const struct thermal_cooling_device_ops mt7996_thermal_ops = { static void mt7996_unregister_thermal(struct mt7996_phy *phy) { struct wiphy *wiphy = phy->mt76->hw->wiphy; + char name[sizeof("cooling_deviceXXX")]; if (!phy->cdev) return; - sysfs_remove_link(&wiphy->dev.kobj, "cooling_device"); + snprintf(name, sizeof(name), "cooling_device%d", phy->mt76->band_idx); + sysfs_remove_link(&wiphy->dev.kobj, name); thermal_cooling_device_unregister(phy->cdev); } static int mt7996_thermal_init(struct mt7996_phy *phy) { struct wiphy *wiphy = phy->mt76->hw->wiphy; + char cname[sizeof("cooling_deviceXXX")]; struct thermal_cooling_device *cdev; struct device *hwmon; const char *name; - name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s", - wiphy_name(wiphy)); + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s.%d", + wiphy_name(wiphy), phy->mt76->band_idx); + if (!name) + return -ENOMEM; + + snprintf(cname, sizeof(cname), "cooling_device%d", phy->mt76->band_idx); cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops); if (!IS_ERR(cdev)) { if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj, - "cooling_device") < 0) + cname) < 0) thermal_cooling_device_unregister(cdev); else phy->cdev = cdev; @@ -292,8 +317,8 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy, struct ieee80211_supported_band *sband) { struct mt7996_dev *dev = phy->dev; - int i, nss = hweight16(phy->mt76->chainmask); - int nss_delta = mt76_tx_power_nss_delta(nss); + int i, n_chains = hweight16(phy->mt76->chainmask); + int path_delta = mt76_tx_power_path_delta(n_chains); int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band); struct mt76_power_limits limits; @@ -305,7 +330,7 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy, target_power = mt76_get_rate_power_limits(phy->mt76, chan, &limits, target_power); - target_power += nss_delta; + target_power += path_delta; target_power = DIV_ROUND_UP(target_power, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); @@ -332,32 +357,95 @@ mt7996_regd_notifier(struct wiphy *wiphy, { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mt7996_phy *phy; memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; - if (dev->mt76.region == NL80211_DFS_UNSET) - mt7996_mcu_rdd_background_enable(phy, NULL); + mt7996_for_each_phy(dev, phy) { + if (dev->mt76.region == NL80211_DFS_UNSET) + mt7996_mcu_rdd_background_enable(phy, NULL); - mt7996_init_txpower(phy); + mt7996_init_txpower(phy); + phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; + mt7996_dfs_init_radar_detector(phy); + } +} + +static void +mt7996_init_wiphy_band(struct ieee80211_hw *hw, struct mt7996_phy *phy) +{ + struct mt7996_dev *dev = phy->dev; + struct wiphy *wiphy = hw->wiphy; + int n_radios = hw->wiphy->n_radio; + struct wiphy_radio_freq_range *freq = &dev->radio_freqs[n_radios]; + struct wiphy_radio *radio = &dev->radios[n_radios]; - phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; - mt7996_dfs_init_radar_detector(phy); + phy->slottime = 9; + phy->beacon_rate = -1; + + if (phy->mt76->cap.has_2ghz) { + phy->mt76->sband_2g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + phy->mt76->sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_2; + freq->start_freq = 2400000; + freq->end_freq = 2500000; + } else if (phy->mt76->cap.has_5ghz) { + phy->mt76->sband_5g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + + phy->mt76->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_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + phy->mt76->sband_5g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_1; + + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + freq->start_freq = 5000000; + freq->end_freq = 5900000; + } else if (phy->mt76->cap.has_6ghz) { + freq->start_freq = 5900000; + freq->end_freq = 7200000; + } else { + return; + } + + dev->radio_phy[n_radios] = phy; + radio->freq_range = freq; + radio->n_freq_range = 1; + radio->iface_combinations = &if_comb; + radio->n_iface_combinations = 1; + hw->wiphy->n_radio++; + + wiphy->available_antennas_rx |= phy->mt76->chainmask; + wiphy->available_antennas_tx |= phy->mt76->chainmask; + + mt76_set_stream_caps(phy->mt76, true); + mt7996_set_stream_vht_txbf_caps(phy); + mt7996_set_stream_he_eht_caps(phy); + mt7996_init_txpower(phy); } static void mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt76_dev *mdev = &phy->dev->mt76; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt76_dev *mdev = &dev->mt76; struct wiphy *wiphy = hw->wiphy; - u16 max_subframes = phy->dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT : - IEEE80211_MAX_AMPDU_BUF_HE; + u16 max_subframes = dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT : + IEEE80211_MAX_AMPDU_BUF_HE; hw->queues = 4; hw->max_rx_aggregation_subframes = max_subframes; hw->max_tx_aggregation_subframes = max_subframes; + if (is_mt7990(mdev) && dev->has_eht) + hw->max_tx_aggregation_subframes = 512; + hw->netdev_features = NETIF_F_RXCSUM; if (mtk_wed_device_active(wed)) hw->netdev_features |= NETIF_F_HW_TC; @@ -365,14 +453,15 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) hw->radiotap_timestamp.units_pos = IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; - phy->slottime = 9; - phy->beacon_rate = -1; - hw->sta_data_size = sizeof(struct mt7996_sta); hw->vif_data_size = sizeof(struct mt7996_vif); + hw->chanctx_data_size = sizeof(struct mt76_chanctx); + + wiphy->iface_combinations = &if_comb_global; + wiphy->n_iface_combinations = 1; + + wiphy->radio = dev->radios; - wiphy->iface_combinations = if_comb; - 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; @@ -389,57 +478,31 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); - if (!mdev->dev->of_node || - !of_property_read_bool(mdev->dev->of_node, - "mediatek,disable-radar-background")) + if (mt7996_eeprom_has_background_radar(dev) && + (!mdev->dev->of_node || + !of_property_read_bool(mdev->dev->of_node, + "mediatek,disable-radar-background"))) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RADAR_BACKGROUND); ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); - ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); hw->max_tx_fragments = 4; - if (phy->mt76->cap.has_2ghz) { - phy->mt76->sband_2g.sband.ht_cap.cap |= - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_MAX_AMSDU; - phy->mt76->sband_2g.sband.ht_cap.ampdu_density = - IEEE80211_HT_MPDU_DENSITY_2; - } - - if (phy->mt76->cap.has_5ghz) { - phy->mt76->sband_5g.sband.ht_cap.cap |= - IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_MAX_AMSDU; - - phy->mt76->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_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; - phy->mt76->sband_5g.sband.ht_cap.ampdu_density = - IEEE80211_HT_MPDU_DENSITY_1; - - ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); - } - /* 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; + dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness; + dev->mphy.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); - mt7996_init_txpower(phy); + wiphy->max_scan_ssids = 4; + wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; - wiphy->available_antennas_rx = phy->mt76->antenna_mask; - wiphy->available_antennas_tx = phy->mt76->antenna_mask; + mt7996_init_wiphy_band(hw, &dev->phy); } static void @@ -458,6 +521,10 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band) mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band), MT_WF_RMAC_MIB_QOS23_BACKOFF); + /* clear backoff time for Tx duration */ + mt76_clear(dev, MT_WTBLOFF_ACR(band), + MT_WTBLOFF_ADM_BACKOFFTIME); + /* clear backoff time and set software compensation for OBSS time */ mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET; set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) | @@ -493,7 +560,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev) void mt7996_mac_init(struct mt7996_dev *dev) { -#define HIF_TXD_V2_1 4 +#define HIF_TXD_V2_1 0x21 int i; mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); @@ -507,11 +574,6 @@ void mt7996_mac_init(struct mt7996_dev *dev) mt76_rmw_field(dev, i, MT_LED_GPIO_SEL_MASK, 4); } - /* txs report queue */ - mt76_rmw_field(dev, MT_DMA_TCRF1(0), MT_DMA_TCRF1_QIDX, 0); - mt76_rmw_field(dev, MT_DMA_TCRF1(1), MT_DMA_TCRF1_QIDX, 6); - mt76_rmw_field(dev, MT_DMA_TCRF1(2), MT_DMA_TCRF1_QIDX, 0); - /* rro module init */ if (is_mt7996(&dev->mt76)) mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2); @@ -561,18 +623,15 @@ int mt7996_txbf_init(struct mt7996_dev *dev) return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE); } -static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, - enum mt76_band_id band) +static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band) { + struct mt7996_phy *phy; struct mt76_phy *mphy; u32 mac_ofs, hif1_ofs = 0; int ret; struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - if (!mt7996_band_valid(dev, band) || band == MT_BAND0) - return 0; - - if (phy) + if (!mt7996_band_valid(dev, band)) return 0; if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) { @@ -580,7 +639,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, wed = &dev->mt76.mmio.wed_hif2; } - mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band); + mphy = mt76_alloc_radio_phy(&dev->mt76, sizeof(*phy), band); if (!mphy) return -ENOMEM; @@ -611,7 +670,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, mt76_eeprom_override(mphy); /* init wiphy according to mphy and phy */ - mt7996_init_wiphy(mphy->hw, wed); + mt7996_init_wiphy_band(mphy->hw, phy); ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band), MT7996_TX_RING_SIZE, @@ -625,14 +684,6 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, if (ret) goto error; - ret = mt7996_thermal_init(phy); - if (ret) - goto error; - - ret = mt7996_init_debugfs(phy); - if (ret) - goto error; - if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) { u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2; @@ -644,24 +695,14 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy, error: mphy->dev->phys[band] = NULL; - ieee80211_free_hw(mphy->hw); return ret; } static void -mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band) +mt7996_unregister_phy(struct mt7996_phy *phy) { - struct mt76_phy *mphy; - - if (!phy) - return; - - mt7996_unregister_thermal(phy); - - mphy = phy->dev->mt76.phys[band]; - mt76_unregister_phy(mphy); - ieee80211_free_hw(mphy->hw); - phy->dev->mt76.phys[band] = NULL; + if (phy) + mt7996_unregister_thermal(phy); } static void mt7996_init_work(struct work_struct *work) @@ -888,6 +929,79 @@ out: #endif } +static int mt7996_variant_type_init(struct mt7996_dev *dev) +{ + u32 val = mt76_rr(dev, MT_PAD_GPIO); + u8 var_type; + + switch (mt76_chip(&dev->mt76)) { + case MT7996_DEVICE_ID: + if (val & MT_PAD_GPIO_2ADIE_TBTC) + var_type = MT7996_VAR_TYPE_233; + else + var_type = MT7996_VAR_TYPE_444; + break; + case MT7992_DEVICE_ID: + if (val & MT_PAD_GPIO_ADIE_SINGLE) + var_type = MT7992_VAR_TYPE_23; + else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992)) + var_type = MT7992_VAR_TYPE_44; + else + return -EINVAL; + break; + case MT7990_DEVICE_ID: + var_type = MT7990_VAR_TYPE_23; + break; + default: + return -EINVAL; + } + + dev->var.type = var_type; + return 0; +} + +static int mt7996_variant_fem_init(struct mt7996_dev *dev) +{ +#define MT7976C_EFUSE_OFFSET 0x470 + u8 buf[MT7996_EEPROM_BLOCK_SIZE], idx, adie_idx, adie_comb; + u32 regval, val = mt76_rr(dev, MT_PAD_GPIO); + u16 adie_id, adie_ver; + bool is_7976c; + int ret; + + if (is_mt7992(&dev->mt76)) { + adie_idx = (val & MT_PAD_GPIO_ADIE_SINGLE) ? 0 : 1; + adie_comb = u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992); + } else { + adie_idx = 0; + adie_comb = u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB); + } + + ret = mt7996_mcu_rf_regval(dev, MT_ADIE_CHIP_ID(adie_idx), ®val, false); + if (ret) + return ret; + + ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf)); + if (ret && ret != -EINVAL) + return ret; + + adie_ver = u32_get_bits(regval, MT_ADIE_VERSION_MASK); + idx = MT7976C_EFUSE_OFFSET % MT7996_EEPROM_BLOCK_SIZE; + is_7976c = adie_ver == 0x8a10 || adie_ver == 0x8b00 || + adie_ver == 0x8c10 || buf[idx] == 0xc; + + adie_id = u32_get_bits(regval, MT_ADIE_CHIP_ID_MASK); + if (adie_id == 0x7975 || adie_id == 0x7979 || + (adie_id == 0x7976 && is_7976c)) + dev->var.fem = MT7996_FEM_INT; + else if (adie_id == 0x7977 && adie_comb == 1) + dev->var.fem = MT7996_FEM_MIX; + else + dev->var.fem = MT7996_FEM_EXT; + + return 0; +} + static int mt7996_init_hardware(struct mt7996_dev *dev) { int ret, idx; @@ -903,6 +1017,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev) INIT_LIST_HEAD(&dev->wed_rro.poll_list); spin_lock_init(&dev->wed_rro.lock); + ret = mt7996_variant_type_init(dev); + if (ret) + return ret; + ret = mt7996_dma_init(dev); if (ret) return ret; @@ -917,6 +1035,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev) if (ret) return ret; + ret = mt7996_variant_fem_init(dev); + if (ret) + return ret; + ret = mt7996_eeprom_init(dev); if (ret < 0) return ret; @@ -946,8 +1068,12 @@ void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy) cap = &phy->mt76->sband_5g.sband.vht_cap.cap; *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | - FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, sts - 1); + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; + + if (is_mt7992(phy->mt76->dev)) + *cap |= FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, 4); + else + *cap |= FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, 3); *cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | @@ -963,10 +1089,12 @@ void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy) static void mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, - struct ieee80211_sta_he_cap *he_cap, int vif) + struct ieee80211_sta_he_cap *he_cap, int vif, + enum nl80211_band band) { struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem; int sts = hweight16(phy->mt76->chainmask); + bool non_2g = band != NL80211_BAND_2GHZ; u8 c; #ifdef CONFIG_MAC80211_MESH @@ -988,13 +1116,18 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK; c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | - IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; elem->phy_cap_info[2] |= c; - c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | - IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 | - IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4; + c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; + + if (is_mt7992(phy->mt76->dev)) + c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 | + (IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 * non_2g); + else + c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 | + (IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 * non_2g); + elem->phy_cap_info[4] |= c; /* do not support NG16 due to spec D4.0 changes subcarrier idx */ @@ -1012,24 +1145,31 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3; - if (vif != NL80211_IFTYPE_AP) + if (!(vif == NL80211_IFTYPE_AP || vif == NL80211_IFTYPE_STATION)) return; elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; - elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, sts - 1) | - FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK, - sts - 1); + (FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK, + sts - 1) * non_2g); + elem->phy_cap_info[5] |= c; + if (vif != NL80211_IFTYPE_AP) + return; + + elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; + c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; - c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ | - IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; + c = 0; + if (non_2g) + c |= IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ | + IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; elem->phy_cap_info[7] |= c; } @@ -1070,6 +1210,9 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, he_cap_elem->phy_cap_info[2] = IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; + he_cap_elem->phy_cap_info[7] = + IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; + switch (iftype) { case NL80211_IFTYPE_AP: he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES; @@ -1109,8 +1252,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; he_cap_elem->phy_cap_info[7] |= - IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | - IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; + IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP; he_cap_elem->phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | @@ -1133,12 +1275,12 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); - mt7996_set_stream_he_txbf_caps(phy, he_cap, iftype); + mt7996_set_stream_he_txbf_caps(phy, he_cap, iftype, band); memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band); } else { he_cap_elem->phy_cap_info[9] |= u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, @@ -1180,68 +1322,77 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, eht_cap_elem->mac_cap_info[0] = IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | - IEEE80211_EHT_MAC_CAP0_OM_CONTROL; + IEEE80211_EHT_MAC_CAP0_OM_CONTROL | + u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454, + IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK); + + eht_cap_elem->mac_cap_info[1] |= + IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK; eht_cap_elem->phy_cap_info[0] = - IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; - val = max_t(u8, sts - 1, 3); + /* Set the maximum capability regardless of the antenna configuration. */ + val = is_mt7992(phy->mt76->dev) ? 4 : 3; eht_cap_elem->phy_cap_info[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(val, GENMASK(2, 1)), - IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | - u8_encode_bits(val, - IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) | - u8_encode_bits(val, - IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK); eht_cap_elem->phy_cap_info[2] = - u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) | - u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK) | - u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK); + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK); + + if (band != NL80211_BAND_2GHZ) { + eht_cap_elem->phy_cap_info[1] |= + u8_encode_bits(val, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK); + + eht_cap_elem->phy_cap_info[2] |= + u8_encode_bits(sts - 1, + IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK); + } + + if (band == NL80211_BAND_6GHZ) { + eht_cap_elem->phy_cap_info[0] |= + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; + + eht_cap_elem->phy_cap_info[1] |= + u8_encode_bits(val, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); + + eht_cap_elem->phy_cap_info[2] |= + u8_encode_bits(sts - 1, + IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK); + } eht_cap_elem->phy_cap_info[3] = IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK; + IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK; eht_cap_elem->phy_cap_info[4] = + IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | u8_encode_bits(min_t(int, sts - 1, 2), IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK); eht_cap_elem->phy_cap_info[5] = - IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US, IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) | - u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)), + u8_encode_bits(u8_get_bits(1, GENMASK(1, 0)), IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK); val = width == NL80211_CHAN_WIDTH_320 ? 0xf : width == NL80211_CHAN_WIDTH_160 ? 0x7 : width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1; eht_cap_elem->phy_cap_info[6] = - u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)), - IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) | u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK); - eht_cap_elem->phy_cap_info[7] = - IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | - IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | - IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | - IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | - IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | - IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; - val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) | u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX); #define SET_EHT_MAX_NSS(_bw, _val) do { \ @@ -1252,8 +1403,34 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, SET_EHT_MAX_NSS(80, val); SET_EHT_MAX_NSS(160, val); - SET_EHT_MAX_NSS(320, val); + if (band == NL80211_BAND_6GHZ) + SET_EHT_MAX_NSS(320, val); #undef SET_EHT_MAX_NSS + + if (iftype != NL80211_IFTYPE_AP) + return; + + eht_cap_elem->phy_cap_info[3] |= + IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK; + + eht_cap_elem->phy_cap_info[7] = + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ; + + if (band == NL80211_BAND_2GHZ) + return; + + eht_cap_elem->phy_cap_info[7] |= + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ; + + if (band != NL80211_BAND_6GHZ) + return; + + eht_cap_elem->phy_cap_info[7] |= + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; } static void @@ -1304,6 +1481,7 @@ void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy) int mt7996_register_device(struct mt7996_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7996_phy *phy; int ret; dev->phy.dev = dev; @@ -1325,28 +1503,27 @@ int mt7996_register_device(struct mt7996_dev *dev) mt7996_init_wiphy(hw, &dev->mt76.mmio.wed); - ret = mt76_register_device(&dev->mt76, true, mt76_rates, - ARRAY_SIZE(mt76_rates)); + ret = mt7996_register_phy(dev, MT_BAND1); if (ret) return ret; - ret = mt7996_thermal_init(&dev->phy); + ret = mt7996_register_phy(dev, MT_BAND2); if (ret) return ret; - ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1); + ret = mt76_register_device(&dev->mt76, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); if (ret) return ret; - ret = mt7996_register_phy(dev, mt7996_phy3(dev), MT_BAND2); - if (ret) - return ret; + mt7996_for_each_phy(dev, phy) + mt7996_thermal_init(phy); ieee80211_queue_work(mt76_hw(dev), &dev->init_work); dev->recovery.hw_init_done = true; - ret = mt7996_init_debugfs(&dev->phy); + ret = mt7996_init_debugfs(dev); if (ret) goto error; @@ -1365,8 +1542,8 @@ error: void mt7996_unregister_device(struct mt7996_dev *dev) { cancel_work_sync(&dev->wed_rro.work); - mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2); - mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1); + mt7996_unregister_phy(mt7996_phy3(dev)); + mt7996_unregister_phy(mt7996_phy2(dev)); mt7996_unregister_thermal(&dev->phy); mt7996_coredump_unregister(dev); mt76_unregister_device(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 53258488d49f..0dbd4662bc84 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -53,26 +53,48 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = { }; static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, - u16 idx, bool unicast) + u16 idx, u8 band_idx) { - struct mt7996_sta *sta; + struct mt7996_sta_link *msta_link; + struct mt7996_sta *msta; + struct mt7996_vif *mvif; struct mt76_wcid *wcid; + int i; if (idx >= ARRAY_SIZE(dev->mt76.wcid)) return NULL; wcid = rcu_dereference(dev->mt76.wcid[idx]); - if (unicast || !wcid) - return wcid; + if (!wcid) + return NULL; - if (!wcid->sta) + if (!mt7996_band_valid(dev, band_idx)) return NULL; - sta = container_of(wcid, struct mt7996_sta, wcid); - if (!sta->vif) + if (wcid->phy_idx == band_idx) + return wcid; + + msta_link = container_of(wcid, struct mt7996_sta_link, wcid); + msta = msta_link->sta; + if (!msta || !msta->vif) return NULL; - return &sta->vif->sta.wcid; + mvif = msta->vif; + for (i = 0; i < ARRAY_SIZE(mvif->mt76.link); i++) { + struct mt76_vif_link *mlink; + + mlink = rcu_dereference(mvif->mt76.link[i]); + if (!mlink) + continue; + + if (mlink->band_idx != band_idx) + continue; + + msta_link = rcu_dereference(msta->link[i]); + break; + } + + return &msta_link->wcid; } bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask) @@ -100,10 +122,13 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) [IEEE80211_AC_VI] = 4, [IEEE80211_AC_VO] = 6 }; + struct mt7996_sta_link *msta_link; + struct mt76_vif_link *mlink; struct ieee80211_sta *sta; struct mt7996_sta *msta; u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; LIST_HEAD(sta_poll_list); + struct mt76_wcid *wcid; int i; spin_lock_bh(&dev->mt76.sta_poll_lock); @@ -123,25 +148,28 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } - msta = list_first_entry(&sta_poll_list, - struct mt7996_sta, wcid.poll_list); - list_del_init(&msta->wcid.poll_list); + msta_link = list_first_entry(&sta_poll_list, + struct mt7996_sta_link, + wcid.poll_list); + msta = msta_link->sta; + wcid = &msta_link->wcid; + list_del_init(&wcid->poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); - idx = msta->wcid.idx; + idx = wcid->idx; /* refresh peer's airtime reporting */ addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - u32 tx_last = msta->airtime_ac[i]; - u32 rx_last = msta->airtime_ac[i + 4]; + u32 tx_last = msta_link->airtime_ac[i]; + u32 rx_last = msta_link->airtime_ac[i + 4]; - msta->airtime_ac[i] = mt76_rr(dev, addr); - msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); + msta_link->airtime_ac[i] = mt76_rr(dev, addr); + msta_link->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); - tx_time[i] = msta->airtime_ac[i] - tx_last; - rx_time[i] = msta->airtime_ac[i + 4] - rx_last; + tx_time[i] = msta_link->airtime_ac[i] - tx_last; + rx_time[i] = msta_link->airtime_ac[i + 4] - rx_last; if ((tx_last | rx_last) & BIT(30)) clear = true; @@ -152,10 +180,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) if (clear) { mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + memset(msta_link->airtime_ac, 0, + sizeof(msta_link->airtime_ac)); } - if (!msta->wcid.sta) + if (!wcid->sta) continue; sta = container_of((void *)msta, struct ieee80211_sta, @@ -181,28 +210,23 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) rssi[2] = to_rssi(GENMASK(23, 16), val); rssi[3] = to_rssi(GENMASK(31, 14), val); - msta->ack_signal = - mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); + mlink = rcu_dereference(msta->vif->mt76.link[wcid->link_id]); + if (mlink) { + struct mt76_phy *mphy = mt76_vif_link_phy(mlink); - ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); + if (mphy) + msta_link->ack_signal = + mt76_rx_signal(mphy->antenna_mask, + rssi); + } + + ewma_avg_signal_add(&msta_link->avg_ack_signal, + -msta_link->ack_signal); } rcu_read_unlock(); } -void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - u32 addr; - - addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5); - if (enable) - mt76_set(dev, addr, BIT(5)); - else - mt76_clear(dev, addr, BIT(5)); -} - /* The HW does not translate the mac header to 802.3 for mesh point */ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) { @@ -435,7 +459,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); - u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; + u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM; u32 csum_status = *(u32 *)skb->cb; u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP; bool is_mesh = (rxd0 & mesh_mask) == mesh_mask; @@ -474,15 +498,15 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); - status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); + status->wcid = mt7996_rx_get_wcid(dev, idx, band_idx); if (status->wcid) { - msta = container_of(status->wcid, struct mt7996_sta, wcid); - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + struct mt7996_sta_link *msta_link; + + msta_link = container_of(status->wcid, struct mt7996_sta_link, + wcid); + msta = msta_link->sta; + mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid); } status->freq = mphy->chandef.chan->center_freq; @@ -497,7 +521,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, if (!sband->channels) return -EINVAL; - if ((rxd0 & csum_mask) == csum_mask && + if ((rxd3 & csum_mask) == csum_mask && !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -623,6 +647,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; } + /* IEEE 802.11 fragmentation can only be applied to unicast frames. + * Hence, drop fragments with multicast/broadcast RA. + * This check fixes vulnerabilities, like CVE-2020-26145. + */ + if ((ieee80211_has_morefrags(fc) || seq_ctrl & IEEE80211_SCTL_FRAG) && + FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) != MT_RXD3_NORMAL_U2M) + return -EINVAL; + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; if (hdr_trans && ieee80211_has_morefrags(fc)) { if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap)) @@ -679,14 +711,25 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, if (ieee80211_has_a4(fc) && is_mesh && status->amsdu) *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; } + skb_set_mac_header(skb, (unsigned char *)hdr - skb->data); } else { status->flag |= RX_FLAG_8023; mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, *info); } - if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) - mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); + if (rxv && !(status->flag & RX_FLAG_8023)) { + switch (status->encoding) { + case RX_ENC_EHT: + mt76_connac3_mac_decode_eht_radiotap(skb, rxv, mode); + break; + case RX_ENC_HE: + mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); + break; + default: + break; + } + } if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr) return 0; @@ -710,9 +753,8 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi, u32 val; if (wcid->sta) { - struct ieee80211_sta *sta; + struct ieee80211_sta *sta = wcid_to_sta(wcid); - sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); wmm = sta->wme; } @@ -732,27 +774,36 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi, FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); txwi[2] |= cpu_to_le32(val); + + if (wcid->amsdu) + txwi[3] |= cpu_to_le32(MT_TXD3_HW_AMSDU); } static void mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct ieee80211_key_conf *key) + struct sk_buff *skb, + struct ieee80211_key_conf *key, + struct mt76_wcid *wcid) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); bool multicast = is_multicast_ether_addr(hdr->addr1); u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - __le16 fc = hdr->frame_control; + __le16 fc = hdr->frame_control, sc = hdr->seq_ctrl; + u16 seqno = le16_to_cpu(sc); u8 fc_type, fc_stype; u32 val; if (ieee80211_is_action(fc) && mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { + if (is_mt7990(&dev->mt76)) + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TID_ADDBA, tid)); tid = MT_TX_ADDBA; - else if (ieee80211_is_mgmt(hdr->frame_control)) + } else if (ieee80211_is_mgmt(hdr->frame_control)) { tid = MT_TX_NORMAL; + } val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | FIELD_PREP(MT_TXD1_HDR_INFO, @@ -763,8 +814,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, info->flags & IEEE80211_TX_CTL_USE_MINRATE) val |= MT_TXD1_FIXED_RATE; - if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && - key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) { val |= MT_TXD1_BIP; txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); } @@ -777,6 +827,15 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + if (ieee80211_has_morefrags(fc) && ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_FIRST); + else if (ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_MID); + else if (!ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_LAST); + else + val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_NONE); + txwi[2] |= cpu_to_le32(val); txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); @@ -785,9 +844,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); } - if (info->flags & IEEE80211_TX_CTL_INJECTED) { - u16 seqno = le16_to_cpu(hdr->seq_ctrl); + if (multicast && ieee80211_vif_is_mld(info->control.vif)) { + val = MT_TXD3_SN_VALID | + FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); + txwi[3] |= cpu_to_le32(val); + } + if (info->flags & IEEE80211_TX_CTL_INJECTED) { if (ieee80211_is_back_req(hdr->frame_control)) { struct ieee80211_bar *bar; @@ -800,6 +863,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, txwi[3] |= cpu_to_le32(val); txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); } + + if (ieee80211_vif_is_mld(info->control.vif) && + (multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))) + txwi[5] |= cpu_to_le32(MT_TXD5_FL); + + if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) && + ieee80211_vif_is_mld(info->control.vif)) { + txwi[5] |= cpu_to_le32(MT_TXD5_FL); + txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT); + } + + if (!wcid->sta && ieee80211_is_mgmt(fc)) + txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT); } void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, @@ -807,12 +883,15 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - struct mt76_vif *mvif; + struct mt76_vif_link *mlink = NULL; + struct mt7996_vif *mvif; + unsigned int link_id; u16 tx_count = 15; u32 val; bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | @@ -820,11 +899,20 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, bool beacon = !!(changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc); - mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; - if (mvif) { - omac_idx = mvif->omac_idx; - wmm_idx = mvif->wmm_idx; - band_idx = mvif->band_idx; + if (wcid != &dev->mt76.global_wcid) + link_id = wcid->link_id; + else + link_id = u32_get_bits(info->control.flags, + IEEE80211_TX_CTRL_MLO_LINK); + + mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; + if (mvif) + mlink = rcu_dereference(mvif->mt76.link[link_id]); + + if (mlink) { + omac_idx = mlink->omac_idx; + wmm_idx = mlink->wmm_idx; + band_idx = mlink->band_idx; } if (inband_disc) { @@ -862,8 +950,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, val |= MT_TXD3_PROTECT_FRAME; if (info->flags & IEEE80211_TX_CTL_NO_ACK) val |= MT_TXD3_NO_ACK; - if (wcid->amsdu) - val |= MT_TXD3_HW_AMSDU; txwi[3] = cpu_to_le32(val); txwi[4] = 0; @@ -873,46 +959,71 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, val |= MT_TXD5_TX_STATUS_HOST; txwi[5] = cpu_to_le32(val); - val = MT_TXD6_DIS_MAT | MT_TXD6_DAS; + val = MT_TXD6_DAS; + if (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) + val |= MT_TXD6_DIS_MAT; + if (is_mt7996(&dev->mt76)) val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1); - else + else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control)) val |= FIELD_PREP(MT_TXD6_MSDU_CNT_V2, 1); + txwi[6] = cpu_to_le32(val); txwi[7] = 0; if (is_8023) mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid); else - mt7996_mac_write_txwi_80211(dev, txwi, skb, key); + mt7996_mac_write_txwi_80211(dev, txwi, skb, key, wcid); if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool mcast = ieee80211_is_data(hdr->frame_control) && is_multicast_ether_addr(hdr->addr1); u8 idx = MT7996_BASIC_RATES_TBL; - if (mvif) { - if (mcast && mvif->mcast_rates_idx) - idx = mvif->mcast_rates_idx; - else if (beacon && mvif->beacon_rates_idx) - idx = mvif->beacon_rates_idx; + if (mlink) { + if (mcast && mlink->mcast_rates_idx) + idx = mlink->mcast_rates_idx; + else if (beacon && mlink->beacon_rates_idx) + idx = mlink->beacon_rates_idx; else - idx = mvif->basic_rates_idx; + idx = mlink->basic_rates_idx; } val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW; + if (mcast) + val |= MT_TXD6_DIS_MAT; txwi[6] |= cpu_to_le32(val); txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); } } +static bool +mt7996_tx_use_mgmt(struct mt7996_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (ieee80211_is_mgmt(hdr->frame_control)) + return true; + + /* for SDO to bypass specific data frame */ + if (!mt7996_has_wa(dev)) { + if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) + return true; + + if (ieee80211_has_a4(hdr->frame_control) && + !ieee80211_is_data_present(hdr->frame_control)) + return true; + } + + return false; +} + int mt7996_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 ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; @@ -937,8 +1048,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, - pid, qid, 0); + memset(txwi_ptr, 0, MT_TXD_SIZE); + /* Transmit non qos data by 802.11 header and need to fill txd by host*/ + if (!is_8023 || pid >= MT_PACKET_ID_FIRST) + mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, + pid, qid, 0); txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { @@ -955,19 +1069,27 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, } txp->fw.nbuf = nbuf; - txp->fw.flags = - cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD); + txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST); + + if (!is_8023 || pid >= MT_PACKET_ID_FIRST) + txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD); if (!key) txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); - if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) + if (!is_8023 && mt7996_tx_use_mgmt(dev, tx_info->skb)) txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); if (vif) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif_link *mlink = NULL; + + if (wcid->offchannel) + mlink = rcu_dereference(mvif->mt76.offchannel_link); + if (!mlink) + mlink = &mvif->deflink.mt76; - txp->fw.bss_idx = mvif->mt76.idx; + txp->fw.bss_idx = mlink->idx; } txp->fw.token = cpu_to_le16(id); @@ -1009,9 +1131,10 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) static void 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; + struct mt7996_sta_link *msta_link; + struct mt7996_sta *msta; u16 fc, tid; if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) @@ -1040,7 +1163,9 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb) return; msta = (struct mt7996_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) + msta_link = &msta->deflink; + + if (!test_and_set_bit(tid, &msta_link->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } @@ -1090,6 +1215,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) void *end = data + len; bool wake = false; u16 total, count = 0; + u8 ver; /* clean DMA queues and unmap buffers first */ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); @@ -1103,7 +1229,8 @@ 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) < 5)) + ver = le32_get_bits(tx_free[1], MT_TXFREE1_VER); + if (WARN_ON_ONCE(ver < 5)) return; total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); @@ -1118,21 +1245,23 @@ 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 mt7996_sta_link *msta_link; u16 idx; idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); wcid = rcu_dereference(dev->mt76.wcid[idx]); sta = wcid_to_sta(wcid); if (!sta) - continue; - - msta = container_of(wcid, struct mt7996_sta, wcid); - spin_lock_bh(&mdev->sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, - &mdev->sta_poll_list); - spin_unlock_bh(&mdev->sta_poll_lock); + goto next; + + msta_link = container_of(wcid, struct mt7996_sta_link, + wcid); + mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid); +next: + /* ver 7 has a new DW with pair = 1, skip it */ + if (ver == 7 && ((void *)(cur_info + 1) < end) && + (le32_to_cpu(*(cur_info + 1)) & MT_TXFREE_INFO_PAIR)) + cur_info++; continue; } else if (info & MT_TXFREE_INFO_HEADER) { u32 tx_retries = 0, tx_failed = 0; @@ -1188,32 +1317,35 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, struct ieee80211_tx_info *info; struct sk_buff_head list; struct rate_info rate = {}; - struct sk_buff *skb; + struct sk_buff *skb = NULL; bool cck = false; u32 txrate, txs, mode, stbc; txs = le32_to_cpu(txs_data[0]); mt76_tx_status_lock(mdev, &list); - skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); - if (skb) { - info = IEEE80211_SKB_CB(skb); - if (!(txs & MT_TXS0_ACK_ERROR_MASK)) - info->flags |= IEEE80211_TX_STAT_ACK; + /* only report MPDU TXS */ + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == 0) { + skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); + if (skb) { + info = IEEE80211_SKB_CB(skb); + if (!(txs & MT_TXS0_ACK_ERROR_MASK)) + info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ampdu_len = 1; - info->status.ampdu_ack_len = - !!(info->flags & IEEE80211_TX_STAT_ACK); + info->status.ampdu_len = 1; + info->status.ampdu_ack_len = + !!(info->flags & IEEE80211_TX_STAT_ACK); - info->status.rates[0].idx = -1; + 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); + sta = wcid_to_sta(wcid); tid = FIELD_GET(MT_TXS0_TID, txs); ieee80211_refresh_tx_agg_session_timer(sta, tid); } @@ -1327,7 +1459,7 @@ out: static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) { - struct mt7996_sta *msta = NULL; + struct mt7996_sta_link *msta_link; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; @@ -1348,17 +1480,13 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) if (!wcid) goto out; - msta = container_of(wcid, struct mt7996_sta, wcid); - mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data); if (!wcid->sta) goto out; - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (list_empty(&msta->wcid.poll_list)) - list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); + msta_link = container_of(wcid, struct mt7996_sta_link, wcid); + mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid); out: rcu_read_unlock(); @@ -1385,7 +1513,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) mt7996_mac_tx_free(dev, data, len); return false; case PKT_TYPE_TXS: - for (rxd += 4; rxd + 8 <= end; rxd += 8) + for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) mt7996_mac_add_txs(dev, rxd); return false; case PKT_TYPE_RX_FW_MONITOR: @@ -1428,7 +1556,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, mt7996_mcu_rx_event(dev, skb); break; case PKT_TYPE_TXS: - for (rxd += 4; rxd + 8 <= end; rxd += 8) + for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) mt7996_mac_add_txs(dev, rxd); dev_kfree_skb(skb); break; @@ -1580,7 +1708,7 @@ mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: - mt7996_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); + mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf); break; default: break; @@ -1651,14 +1779,10 @@ mt7996_mac_restart(struct mt7996_dev *dev) set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); - if (phy2) { + if (phy2) set_bit(MT76_RESET, &phy2->mt76->state); - set_bit(MT76_MCU_RESET, &phy2->mt76->state); - } - if (phy3) { + if (phy3) set_bit(MT76_RESET, &phy3->mt76->state); - set_bit(MT76_MCU_RESET, &phy3->mt76->state); - } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); @@ -1685,7 +1809,6 @@ mt7996_mac_restart(struct mt7996_dev *dev) mt7996_dma_reset(dev, true); - local_bh_disable(); mt76_for_each_q_rx(mdev, i) { if (mtk_wed_device_active(&dev->mt76.mmio.wed) && mt76_queue_is_wed_rro(&mdev->q_rx[i])) @@ -1693,10 +1816,11 @@ mt7996_mac_restart(struct mt7996_dev *dev) if (mdev->q_rx[i].ndesc) { napi_enable(&dev->mt76.napi[i]); + local_bh_disable(); napi_schedule(&dev->mt76.napi[i]); + local_bh_enable(); } } - local_bh_enable(); clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); @@ -1729,19 +1853,19 @@ mt7996_mac_restart(struct mt7996_dev *dev) ret = mt7996_txbf_init(dev); if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { - ret = mt7996_run(dev->mphy.hw); + ret = mt7996_run(&dev->phy); if (ret) goto out; } if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) { - ret = mt7996_run(phy2->mt76->hw); + ret = mt7996_run(phy2); if (ret) goto out; } if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) { - ret = mt7996_run(phy3->mt76->hw); + ret = mt7996_run(phy3); if (ret) goto out; } @@ -1754,8 +1878,8 @@ out: if (phy3) clear_bit(MT76_RESET, &phy3->mt76->state); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); + local_bh_disable(); napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); @@ -1948,23 +2072,23 @@ void mt7996_mac_reset_work(struct work_struct *work) if (phy3) clear_bit(MT76_RESET, &phy3->mt76->state); - local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { if (mtk_wed_device_active(&dev->mt76.mmio.wed) && mt76_queue_is_wed_rro(&dev->mt76.q_rx[i])) continue; napi_enable(&dev->mt76.napi[i]); + local_bh_disable(); napi_schedule(&dev->mt76.napi[i]); + local_bh_enable(); } - local_bh_enable(); tasklet_schedule(&dev->mt76.irq_tasklet); mt76_worker_enable(&dev->mt76.tx_worker); - local_bh_disable(); napi_enable(&dev->mt76.tx_napi); + local_bh_disable(); napi_schedule(&dev->mt76.tx_napi); local_bh_enable(); @@ -2229,38 +2353,70 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy) void mt7996_mac_sta_rc_work(struct work_struct *work) { struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work); + struct ieee80211_bss_conf *link_conf; + struct ieee80211_link_sta *link_sta; + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + struct mt76_vif_link *mlink; struct ieee80211_sta *sta; struct ieee80211_vif *vif; struct mt7996_sta *msta; - u32 changed; + struct mt7996_vif *mvif; LIST_HEAD(list); + u32 changed; + u8 link_id; + rcu_read_lock(); spin_lock_bh(&dev->mt76.sta_poll_lock); list_splice_init(&dev->sta_rc_list, &list); while (!list_empty(&list)) { - msta = list_first_entry(&list, struct mt7996_sta, rc_list); - list_del_init(&msta->rc_list); - changed = msta->changed; - msta->changed = 0; + msta_link = list_first_entry(&list, struct mt7996_sta_link, + rc_list); + list_del_init(&msta_link->rc_list); + + changed = msta_link->changed; + msta_link->changed = 0; + + sta = wcid_to_sta(&msta_link->wcid); + link_id = msta_link->wcid.link_id; + msta = msta_link->sta; + mvif = msta->vif; + vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); + + mlink = rcu_dereference(mvif->mt76.link[link_id]); + if (!mlink) + continue; + + link_sta = rcu_dereference(sta->link[link_id]); + if (!link_sta) + continue; + + link_conf = rcu_dereference(vif->link_conf[link_id]); + if (!link_conf) + continue; + spin_unlock_bh(&dev->mt76.sta_poll_lock); - sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); - vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + link = (struct mt7996_vif_link *)mlink; if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | IEEE80211_RC_NSS_CHANGED | IEEE80211_RC_BW_CHANGED)) - mt7996_mcu_add_rate_ctrl(dev, vif, sta, true); + mt7996_mcu_add_rate_ctrl(dev, vif, link_conf, + link_sta, link, msta_link, + true); if (changed & IEEE80211_RC_SMPS_CHANGED) - mt7996_mcu_set_fixed_field(dev, vif, sta, NULL, + mt7996_mcu_set_fixed_field(dev, link_sta, link, + msta_link, NULL, RATE_PARAM_MMPS_UPDATE); spin_lock_bh(&dev->mt76.sta_poll_lock); } spin_unlock_bh(&dev->mt76.sta_poll_lock); + rcu_read_unlock(); } void mt7996_mac_work(struct work_struct *work) @@ -2298,16 +2454,15 @@ void mt7996_mac_work(struct work_struct *work) static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy) { struct mt7996_dev *dev = phy->dev; + int rdd_idx = mt7996_get_rdd_idx(phy, false); + + if (rdd_idx < 0) + return; - if (phy->rdd_state & BIT(0)) - mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0, - MT_RX_SEL0, 0); - if (phy->rdd_state & BIT(1)) - mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1, - MT_RX_SEL0, 0); + mt7996_mcu_rdd_cmd(dev, RDD_STOP, rdd_idx, 0); } -static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain) +static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx) { int err, region; @@ -2324,44 +2479,30 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain) break; } - err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain, - MT_RX_SEL0, region); + err = mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region); if (err < 0) return err; - return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, - MT_RX_SEL0, 1); + return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, rdd_idx, 1); } static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy) { - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; struct mt7996_dev *dev = phy->dev; - u8 band_idx = phy->mt76->band_idx; - int err; + int err, rdd_idx; - /* start CAC */ - err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx, - MT_RX_SEL0, 0); - if (err < 0) - return err; + rdd_idx = mt7996_get_rdd_idx(phy, false); + if (rdd_idx < 0) + return -EINVAL; - err = mt7996_dfs_start_rdd(dev, band_idx); + /* start CAC */ + err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, rdd_idx, 0); if (err < 0) return err; - phy->rdd_state |= BIT(band_idx); - - if (chandef->width == NL80211_CHAN_WIDTH_160 || - chandef->width == NL80211_CHAN_WIDTH_80P80) { - err = mt7996_dfs_start_rdd(dev, 1); - if (err < 0) - return err; + err = mt7996_dfs_start_rdd(dev, rdd_idx); - phy->rdd_state |= BIT(1); - } - - return 0; + return err; } static int @@ -2402,12 +2543,12 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) { struct mt7996_dev *dev = phy->dev; enum mt76_dfs_state dfs_state, prev_state; - int err; + int err, rdd_idx = mt7996_get_rdd_idx(phy, false); prev_state = phy->mt76->dfs_state; dfs_state = mt76_phy_dfs_state(phy->mt76); - if (prev_state == dfs_state) + if (prev_state == dfs_state || rdd_idx < 0) return 0; if (prev_state == MT_DFS_STATE_UNKNOWN) @@ -2431,8 +2572,7 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) if (dfs_state == MT_DFS_STATE_CAC) return 0; - err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, - phy->mt76->band_idx, MT_RX_SEL0, 0); + err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, rdd_idx, 0); if (err < 0) { phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; return err; @@ -2442,8 +2582,7 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) return 0; stop: - err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, - phy->mt76->band_idx, MT_RX_SEL0, 0); + err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, rdd_idx, 0); if (err < 0) return err; @@ -2527,6 +2666,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) return 0; } +static bool +mt7996_mac_twt_param_equal(struct mt7996_sta_link *msta_link, + struct ieee80211_twt_params *twt_agrt) +{ + u16 type = le16_to_cpu(twt_agrt->req_type); + u8 exp; + int i; + + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); + for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) { + struct mt7996_twt_flow *f; + + if (!(msta_link->twt.flowid_mask & BIT(i))) + continue; + + f = &msta_link->twt.flow[i]; + if (f->duration == twt_agrt->min_twt_dur && + f->mantissa == twt_agrt->mantissa && + f->exp == exp && + f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && + f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && + f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) + return true; + } + + return false; +} + void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt) @@ -2534,12 +2701,12 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct ieee80211_twt_params *twt_agrt = (void *)twt->params; + struct mt7996_sta_link *msta_link = &msta->deflink; u16 req_type = le16_to_cpu(twt_agrt->req_type); enum ieee80211_twt_setup_cmd sta_setup_cmd; struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_twt_flow *flow; - int flowid, table_id; - u8 exp; + u8 flowid, table_id, exp; if (mt7996_mac_check_twt_req(twt)) goto out; @@ -2549,21 +2716,32 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT) goto unlock; - if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) + if (hweight8(msta_link->twt.flowid_mask) == + ARRAY_SIZE(msta_link->twt.flow)) + goto unlock; + + if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) { + setup_cmd = TWT_SETUP_CMD_DICTATE; + twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR; + goto unlock; + } + + if (mt7996_mac_twt_param_equal(msta_link, twt_agrt)) goto unlock; - flowid = ffs(~msta->twt.flowid_mask) - 1; - le16p_replace_bits(&twt_agrt->req_type, flowid, - IEEE80211_TWT_REQTYPE_FLOWID); + flowid = ffs(~msta_link->twt.flowid_mask) - 1; + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); + twt_agrt->req_type |= le16_encode_bits(flowid, + IEEE80211_TWT_REQTYPE_FLOWID); table_id = ffs(~dev->twt.table_mask) - 1; exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); - flow = &msta->twt.flow[flowid]; + flow = &msta_link->twt.flow[flowid]; memset(flow, 0, sizeof(*flow)); INIT_LIST_HEAD(&flow->list); - flow->wcid = msta->wcid.idx; + flow->wcid = msta_link->wcid.idx; flow->table_id = table_id; flow->id = flowid; flow->duration = twt_agrt->min_twt_dur; @@ -2581,7 +2759,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, flow->sched = true; flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow); - curr_tsf = __mt7996_get_tsf(hw, msta->vif); + curr_tsf = __mt7996_get_tsf(hw, &msta->vif->deflink); div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem); flow_tsf = curr_tsf + interval - rem; twt_agrt->twt = cpu_to_le64(flow_tsf); @@ -2590,44 +2768,45 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, } flow->tsf = le64_to_cpu(twt_agrt->twt); - if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) + if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow, + MCU_TWT_AGRT_ADD)) goto unlock; setup_cmd = TWT_SETUP_CMD_ACCEPT; dev->twt.table_mask |= BIT(table_id); - msta->twt.flowid_mask |= BIT(flowid); + msta_link->twt.flowid_mask |= BIT(flowid); dev->twt.n_agrt++; unlock: mutex_unlock(&dev->mt76.mutex); out: - le16p_replace_bits(&twt_agrt->req_type, setup_cmd, - IEEE80211_TWT_REQTYPE_SETUP_CMD); - twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | - (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); + twt_agrt->req_type |= + le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); + twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED; } void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, - struct mt7996_sta *msta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, u8 flowid) { struct mt7996_twt_flow *flow; lockdep_assert_held(&dev->mt76.mutex); - if (flowid >= ARRAY_SIZE(msta->twt.flow)) + if (flowid >= ARRAY_SIZE(msta_link->twt.flow)) return; - if (!(msta->twt.flowid_mask & BIT(flowid))) + if (!(msta_link->twt.flowid_mask & BIT(flowid))) return; - flow = &msta->twt.flow[flowid]; - if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, - MCU_TWT_AGRT_DELETE)) + flow = &msta_link->twt.flow[flowid]; + if (mt7996_mcu_twt_agrt_update(dev, link, flow, MCU_TWT_AGRT_DELETE)) return; list_del_init(&flow->list); - msta->twt.flowid_mask &= ~BIT(flowid); + msta_link->twt.flowid_mask &= ~BIT(flowid); dev->twt.table_mask &= ~BIT(flow->table_id); dev->twt.n_agrt--; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 51deea84b642..78ae9f5cb176 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -7,68 +7,44 @@ #include "mcu.h" #include "mac.h" -static bool mt7996_dev_running(struct mt7996_dev *dev) +int mt7996_run(struct mt7996_phy *phy) { - struct mt7996_phy *phy; - - if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) - return true; - - phy = mt7996_phy2(dev); - if (phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) - return true; - - phy = mt7996_phy3(dev); - - return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); -} - -int mt7996_run(struct ieee80211_hw *hw) -{ - struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - bool running; + struct mt7996_dev *dev = phy->dev; int ret; - running = mt7996_dev_running(dev); - if (!running) { - ret = mt7996_mcu_set_hdr_trans(dev, true); - if (ret) - goto out; - } - mt7996_mac_enable_nf(dev, phy->mt76->band_idx); ret = mt7996_mcu_set_rts_thresh(phy, 0x92b); if (ret) - goto out; + return ret; ret = mt7996_mcu_set_radio_en(phy, true); if (ret) - goto out; + return ret; ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); if (ret) - goto out; + return ret; ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX); if (ret) - goto out; + return ret; ret = mt7996_mcu_set_thermal_protect(phy, true); if (ret) - goto out; + return ret; set_bit(MT76_STATE_RUNNING, &phy->mt76->state); - ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + ieee80211_queue_delayed_work(dev->mphy.hw, &phy->mt76->mac_work, MT7996_WATCHDOG_TIME); - if (!running) + if (!phy->counter_reset) { mt7996_mac_reset_counters(phy); + phy->counter_reset = true; + } -out: - return ret; + return 0; } static int mt7996_start(struct ieee80211_hw *hw) @@ -79,16 +55,25 @@ static int mt7996_start(struct ieee80211_hw *hw) flush_work(&dev->init_work); mutex_lock(&dev->mt76.mutex); - ret = mt7996_run(hw); + ret = mt7996_mcu_set_hdr_trans(dev, true); + if (!ret && is_mt7992(&dev->mt76)) { + u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI); + + ret = mt7996_mcu_cp_support(dev, queue); + } mutex_unlock(&dev->mt76.mutex); return ret; } -static void mt7996_stop(struct ieee80211_hw *hw) +static void mt7996_stop_phy(struct mt7996_phy *phy) { - struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mt7996_dev *dev; + + if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) + return; + + dev = phy->dev; cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -101,6 +86,10 @@ static void mt7996_stop(struct ieee80211_hw *hw) mutex_unlock(&dev->mt76.mutex); } +static void mt7996_stop(struct ieee80211_hw *hw, bool suspend) +{ +} + static inline int get_free_idx(u32 mask, u8 start, u8 end) { return ffs(~mask & GENMASK(end, start)); @@ -149,73 +138,178 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) return -1; } -static void mt7996_init_bitrate_mask(struct ieee80211_vif *vif) +static void +mt7996_init_bitrate_mask(struct ieee80211_vif *vif, struct mt7996_vif_link *mlink) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; int i; - for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { - mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; - mvif->bitrate_mask.control[i].he_gi = 0xff; - mvif->bitrate_mask.control[i].he_ltf = 0xff; - mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); - memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff, - sizeof(mvif->bitrate_mask.control[i].ht_mcs)); - memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff, - sizeof(mvif->bitrate_mask.control[i].vht_mcs)); - memset(mvif->bitrate_mask.control[i].he_mcs, 0xff, - sizeof(mvif->bitrate_mask.control[i].he_mcs)); + for (i = 0; i < ARRAY_SIZE(mlink->bitrate_mask.control); i++) { + mlink->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; + mlink->bitrate_mask.control[i].he_gi = 0xff; + mlink->bitrate_mask.control[i].he_ltf = 0xff; + mlink->bitrate_mask.control[i].legacy = GENMASK(31, 0); + memset(mlink->bitrate_mask.control[i].ht_mcs, 0xff, + sizeof(mlink->bitrate_mask.control[i].ht_mcs)); + memset(mlink->bitrate_mask.control[i].vht_mcs, 0xff, + sizeof(mlink->bitrate_mask.control[i].vht_mcs)); + memset(mlink->bitrate_mask.control[i].he_mcs, 0xff, + sizeof(mlink->bitrate_mask.control[i].he_mcs)); } } -static int mt7996_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int +mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt76_txq *mtxq; - u8 band_idx = phy->mt76->band_idx; - int idx, ret = 0; + int idx = key->keyidx; + unsigned int link_id; + unsigned long links; + + if (key->link_id >= 0) + links = BIT(key->link_id); + else if (sta && sta->valid_links) + links = sta->valid_links; + else if (vif->valid_links) + links = vif->valid_links; + else + links = BIT(0); - mutex_lock(&dev->mt76.mutex); + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + u8 *wcid_keyidx; + int err; - if (vif->type == NL80211_IFTYPE_MONITOR && - is_zero_ether_addr(vif->addr)) - phy->monitor_vif = vif; + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; - mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= mt7996_max_interface_num(dev)) { - ret = -ENOSPC; - goto out; + if (sta) { + struct mt7996_sta *msta; + + msta = (struct mt7996_sta *)sta->drv_priv; + msta_link = mt76_dereference(msta->link[link_id], + &dev->mt76); + if (!msta_link) + continue; + + if (!msta_link->wcid.sta) + return -EOPNOTSUPP; + } else { + msta_link = &link->msta_link; + } + wcid_keyidx = &msta_link->wcid.hw_key_idx; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + if (key->keyidx == 6 || key->keyidx == 7) { + wcid_keyidx = &msta_link->wcid.hw_key_idx2; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + } + break; + default: + break; + } + + if (cmd == SET_KEY && !sta && !link->mt76.cipher) { + struct ieee80211_bss_conf *link_conf; + + link_conf = link_conf_dereference_protected(vif, + link_id); + if (!link_conf) + link_conf = &vif->bss_conf; + + link->mt76.cipher = + mt76_connac_mcu_get_cipher(key->cipher); + mt7996_mcu_add_bss_info(link->phy, vif, link_conf, + &link->mt76, msta_link, true); + } + + if (cmd == SET_KEY) { + *wcid_keyidx = idx; + } else { + if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + continue; + } + + mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key); + + if (key->keyidx == 6 || key->keyidx == 7) { + err = mt7996_mcu_bcn_prot_enable(dev, link, + msta_link, key); + if (err) + return err; + } + + err = mt7996_mcu_add_key(&dev->mt76, vif, key, + MCU_WMWA_UNI_CMD(STA_REC_UPDATE), + &msta_link->wcid, cmd); + if (err) + return err; } + return 0; +} + +static void +mt7996_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key, + void *data) +{ + if (sta) + return; + + WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, key)); +} + +int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink) +{ + struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76); + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_sta_link *msta_link = &link->msta_link; + struct mt7996_phy *phy = mphy->priv; + struct mt7996_dev *dev = phy->dev; + u8 band_idx = phy->mt76->band_idx; + struct mt76_txq *mtxq; + int idx, ret; + + mlink->idx = __ffs64(~dev->mt76.vif_mask); + if (mlink->idx >= mt7996_max_interface_num(dev)) + return -ENOSPC; + idx = get_omac_idx(vif->type, phy->omac_mask); - if (idx < 0) { - ret = -ENOSPC; - goto out; - } - mvif->mt76.omac_idx = idx; - mvif->phy = phy; - mvif->mt76.band_idx = band_idx; - mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; + if (idx < 0) + return -ENOSPC; + + link->phy = phy; + mlink->omac_idx = idx; + mlink->band_idx = band_idx; + mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3; + mlink->wcid = &msta_link->wcid; + mlink->wcid->offchannel = mlink->offchannel; - ret = mt7996_mcu_add_dev_info(phy, vif, true); + ret = mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, true); if (ret) - goto out; + return ret; - dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); - phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); + dev->mt76.vif_mask |= BIT_ULL(mlink->idx); + phy->omac_mask |= BIT_ULL(mlink->omac_idx); - idx = MT7996_WTBL_RESERVED - mvif->mt76.idx; + idx = MT7996_WTBL_RESERVED - mlink->idx; - INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); - mvif->sta.wcid.idx = idx; - mvif->sta.wcid.phy_idx = band_idx; - mvif->sta.wcid.hw_key_idx = -1; - mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_wcid_init(&mvif->sta.wcid); + INIT_LIST_HEAD(&msta_link->rc_list); + msta_link->wcid.idx = idx; + msta_link->wcid.link_id = link_conf->link_id; + msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt76_wcid_init(&msta_link->wcid, band_idx); mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -226,75 +320,214 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, } if (vif->type != NL80211_IFTYPE_AP && - (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) + (!mlink->omac_idx || mlink->omac_idx > 3)) vif->offload_flags = 0; - vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) - mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; + mlink->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; else - mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL; + mlink->basic_rates_idx = MT7996_BASIC_RATES_TBL; + + mt7996_init_bitrate_mask(vif, link); - mt7996_init_bitrate_mask(vif); + mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, true); + /* defer the first STA_REC of BMC entry to BSS_CHANGED_BSSID for STA + * interface, since firmware only records BSSID when the entry is new + */ + if (vif->type != NL80211_IFTYPE_STATION) + mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL, + CONN_STATE_PORT_SECURE, true); + rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid); - mt7996_mcu_add_bss_info(phy, vif, true); - mt7996_mcu_add_sta(dev, vif, NULL, true); - rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL); -out: - mutex_unlock(&dev->mt76.mutex); + if (mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED) + mvif->mt76.deflink_id = link_conf->link_id; - return ret; + return 0; } -static void mt7996_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink) { + struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_sta *msta = &mvif->sta; - struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - int idx = msta->wcid.idx; - - mt7996_mcu_add_sta(dev, vif, NULL, false); - mt7996_mcu_add_bss_info(phy, vif, false); + struct mt7996_sta_link *msta_link = &link->msta_link; + struct mt7996_phy *phy = mphy->priv; + struct mt7996_dev *dev = phy->dev; + int idx = msta_link->wcid.idx; - if (vif == phy->monitor_vif) - phy->monitor_vif = NULL; + mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL, + CONN_STATE_DISCONNECT, false); + mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false); - mt7996_mcu_add_dev_info(phy, vif, false); + mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - mutex_lock(&dev->mt76.mutex); - dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); - phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); - mutex_unlock(&dev->mt76.mutex); + if (mvif->mt76.deflink_id == link_conf->link_id) { + struct ieee80211_bss_conf *iter; + unsigned int link_id; + + mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED; + for_each_vif_active_link(vif, iter, link_id) { + if (link_id != IEEE80211_LINK_UNSPECIFIED) { + mvif->mt76.deflink_id = link_id; + break; + } + } + } + + dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx); + phy->omac_mask &= ~BIT_ULL(mlink->omac_idx); spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); + if (!list_empty(&msta_link->wcid.poll_list)) + list_del_init(&msta_link->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); - mt76_wcid_cleanup(&dev->mt76, &msta->wcid); + mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid); } -int mt7996_set_channel(struct mt7996_phy *phy) +static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy) { struct mt7996_dev *dev = phy->dev; - int ret; + u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | + MT_WF_RFCR1_DROP_BF_POLL | + MT_WF_RFCR1_DROP_BA | + MT_WF_RFCR1_DROP_CFEND | + MT_WF_RFCR1_DROP_CFACK; + u32 filter = phy->rxfilter; - cancel_delayed_work_sync(&phy->mt76->mac_work); + if (filter & MT_WF_RFCR_DROP_OTHER_UC) { + filter |= MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | + MT_WF_RFCR_DROP_CTL_RSV | + MT_WF_RFCR_DROP_FCSFAIL; + } + + mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), filter); + if (filter & MT_WF_RFCR_DROP_CTL_RSV) + mt76_set(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); + else + mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); +} + +static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled) +{ + struct mt7996_dev *dev; + + if (!phy) + return; + + dev = phy->dev; + + if (enabled == !(phy->rxfilter & MT_WF_RFCR_DROP_OTHER_UC)) + return; + + if (!enabled) + phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + else + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + + mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx), + MT_DMA_DCR0_RXD_G5_EN, enabled); + mt7996_phy_set_rxfilter(phy); + mt7996_mcu_set_sniffer_mode(phy, enabled); +} + +static int mt7996_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + struct mt7996_dev *dev = mt7996_hw_dev(hw); + int i, err = 0; mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &phy->mt76->state); - mt76_set_channel(phy->mt76); + for (i = 0; i < MT7996_MAX_RADIOS; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + + if (!phy || !(wdev->radio_mask & BIT(i)) || + test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) + continue; + + err = mt7996_run(phy); + if (err) + goto out; + + if (vif->type == NL80211_IFTYPE_MONITOR) + mt7996_set_monitor(phy, true); + } + + mt76_vif_init(vif, &mvif->mt76); + + vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; + mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED; + +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} + +struct mt7996_radio_data { + u32 active_mask; + u32 monitor_mask; +}; + +static void mt7996_remove_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + struct mt7996_radio_data *rdata = data; + + rdata->active_mask |= wdev->radio_mask; + if (vif->type == NL80211_IFTYPE_MONITOR) + rdata->monitor_mask |= wdev->radio_mask; +} + +static void mt7996_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_radio_data rdata = {}; + int i; + + ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter, + &rdata); + mt76_vif_cleanup(&dev->mt76, vif); + + for (i = 0; i < MT7996_MAX_RADIOS; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + + if (!phy) + continue; + if (!(rdata.monitor_mask & BIT(i))) + mt7996_set_monitor(phy, false); + if (!(rdata.active_mask & BIT(i))) + mt7996_stop_phy(phy); + } +} + +int mt7996_set_channel(struct mt76_phy *mphy) +{ + struct mt7996_phy *phy = mphy->priv; + int ret; ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH); if (ret) goto out; + ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); + if (ret) + goto out; + + ret = mt7996_mcu_set_txpower_sku(phy); + if (ret) + goto out; + ret = mt7996_dfs_init_radar_detector(phy); mt7996_mac_cca_stats_reset(phy); @@ -302,13 +535,7 @@ int mt7996_set_channel(struct mt7996_phy *phy) phy->noise = 0; out: - clear_bit(MT76_RESET, &phy->mt76->state); - mutex_unlock(&dev->mt76.mutex); - - mt76_txq_schedule_all(phy->mt76); - - ieee80211_queue_delayed_work(phy->mt76->hw, - &phy->mt76->mac_work, + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, MT7996_WATCHDOG_TIME); return ret; @@ -319,14 +546,8 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv : - &mvif->sta; - struct mt76_wcid *wcid = &msta->wcid; - u8 *wcid_keyidx = &wcid->hw_key_idx; - int idx = key->keyidx; - int err = 0; + int err; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -340,49 +561,31 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { - case WLAN_CIPHER_SUITE_AES_CMAC: - wcid_keyidx = &wcid->hw_key_idx2; - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; - break; case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP_256: case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_SMS4: + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: - break; + if (key->keyidx == 6 || key->keyidx == 7) + break; + fallthrough; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: default: return -EOPNOTSUPP; } - mutex_lock(&dev->mt76.mutex); - - if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) { - mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); - mt7996_mcu_add_bss_info(phy, vif, true); - } - - if (cmd == SET_KEY) { - *wcid_keyidx = idx; - } else { - if (idx == *wcid_keyidx) - *wcid_keyidx = -1; - goto out; - } + if (!mt7996_vif_link_phy(&mvif->deflink)) + return 0; /* defer until after link add */ - mt76_wcid_key_setup(&dev->mt76, wcid, key); - - if (key->keyidx == 6 || key->keyidx == 7) - err = mt7996_mcu_bcn_prot_enable(dev, vif, key); - else - err = mt7996_mcu_add_key(&dev->mt76, vif, key, - MCU_WMWA_UNI_CMD(STA_REC_UPDATE), - &msta->wcid, cmd); -out: + mutex_lock(&dev->mt76.mutex); + err = mt7996_set_hw_key(hw, cmd, vif, sta, key); mutex_unlock(&dev->mt76.mutex); return err; @@ -390,42 +593,6 @@ out: static int mt7996_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - int ret; - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - ret = mt7996_set_channel(phy); - if (ret) - return ret; - ieee80211_wake_queues(hw); - } - - if (changed & (IEEE80211_CONF_CHANGE_POWER | - IEEE80211_CONF_CHANGE_CHANNEL)) { - ret = mt7996_mcu_set_txpower_sku(phy); - if (ret) - return ret; - } - - mutex_lock(&dev->mt76.mutex); - - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); - - if (!enabled) - phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; - else - phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - - mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx), - MT_DMA_DCR0_RXD_G5_EN, enabled); - mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter); - } - - mutex_unlock(&dev->mt76.mutex); - return 0; } @@ -434,8 +601,9 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - const u8 mq_to_aci[] = { + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_vif_link *mlink = mt7996_vif_link(dev, vif, link_id); + static const u8 mq_to_aci[] = { [IEEE80211_AC_VO] = 3, [IEEE80211_AC_VI] = 2, [IEEE80211_AC_BE] = 0, @@ -443,7 +611,7 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, }; /* firmware uses access class index */ - mvif->queue_params[mq_to_aci[queue]] = *params; + mlink->queue_params[mq_to_aci[queue]] = *params; /* no need to update right away, we'll get BSS_CHANGED_QOS */ return 0; @@ -455,34 +623,18 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | - MT_WF_RFCR1_DROP_BF_POLL | - MT_WF_RFCR1_DROP_BA | - MT_WF_RFCR1_DROP_CFEND | - MT_WF_RFCR1_DROP_CFACK; + struct mt7996_phy *phy; + u32 filter_mask = 0, filter_set = 0; u32 flags = 0; -#define MT76_FILTER(_flag, _hw) do { \ - flags |= *total_flags & FIF_##_flag; \ - phy->rxfilter &= ~(_hw); \ - phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ +#define MT76_FILTER(_flag, _hw) do { \ + flags |= *total_flags & FIF_##_flag; \ + filter_mask |= (_hw); \ + filter_set |= !(flags & FIF_##_flag) * (_hw); \ } while (0) mutex_lock(&dev->mt76.mutex); - phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); - MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | MT_WF_RFCR_DROP_A3_BSSID); @@ -491,57 +643,69 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw, MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | MT_WF_RFCR_DROP_RTS | - MT_WF_RFCR_DROP_CTL_RSV | - MT_WF_RFCR_DROP_NDPA); + MT_WF_RFCR_DROP_CTL_RSV); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter); - if (*total_flags & FIF_CONTROL) - mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); - else - mt76_set(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); + mt7996_for_each_phy(dev, phy) { + phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI | + filter_mask); + phy->rxfilter |= filter_set; + mt7996_phy_set_rxfilter(phy); + } mutex_unlock(&dev->mt76.mutex); } -static void -mt7996_update_bss_color(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct cfg80211_he_bss_color *bss_color) +static int +mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, int *dbm) { + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink); struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct wireless_dev *wdev; + int n_chains, delta, i; - switch (vif->type) { - case NL80211_IFTYPE_AP: { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + if (!phy) { + wdev = ieee80211_vif_to_wdev(vif); + for (i = 0; i < hw->wiphy->n_radio; i++) + if (wdev->radio_mask & BIT(i)) + phy = dev->radio_phy[i]; - if (mvif->mt76.omac_idx > HW_BSSID_MAX) - return; - fallthrough; - } - case NL80211_IFTYPE_STATION: - mt7996_mcu_update_bss_color(dev, vif, bss_color); - break; - default: - break; + if (!phy) + return -EINVAL; } + + n_chains = hweight16(phy->mt76->chainmask); + delta = mt76_tx_power_path_delta(n_chains); + *dbm = DIV_ROUND_UP(phy->mt76->txpower_cur + delta, 2); + + return 0; } static u8 -mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf, bool beacon, bool mcast) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; - struct mt76_phy *mphy = hw->priv; + struct mt7996_dev *dev = phy->dev; + struct mt76_vif_link *mvif = mt76_vif_conf_link(&dev->mt76, conf->vif, conf); u16 rate; u8 i, idx; - rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); + rate = mt76_connac2_mac_tx_rate_val(phy->mt76, conf, beacon, mcast); if (beacon) { - struct mt7996_phy *phy = mphy->priv; - /* odd index for driver, even index for firmware */ idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx; if (phy->beacon_rate != rate) @@ -559,12 +723,11 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static void -mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +mt7996_update_mu_group(struct ieee80211_hw *hw, struct mt7996_vif_link *link, struct ieee80211_bss_conf *info) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = mt7996_hw_dev(hw); - u8 band = mvif->mt76.band_idx; + u8 band = link->mt76.band_idx; u32 *mu; mu = (u32 *)info->mu_group.membership; @@ -578,72 +741,127 @@ mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]); } -static void mt7996_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u64 changed) +static void +mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 changed) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; - struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); mutex_lock(&dev->mt76.mutex); + if ((changed & BSS_CHANGED_ASSOC) && vif->cfg.assoc) { + struct ieee80211_bss_conf *link_conf; + unsigned long link_id; + + for_each_vif_active_link(vif, link_conf, link_id) { + struct mt7996_vif_link *link; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + if (!link->phy) + continue; + + mt7996_mcu_add_bss_info(link->phy, vif, link_conf, + &link->mt76, &link->msta_link, + true); + mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL, + CONN_STATE_PORT_SECURE, + !!(changed & BSS_CHANGED_BSSID)); + } + } + + mutex_unlock(&dev->mt76.mutex); +} + +static void +mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u64 changed) +{ + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_vif_link *link; + struct mt7996_phy *phy; + struct mt76_phy *mphy; + + mutex_lock(&dev->mt76.mutex); + + link = mt7996_vif_conf_link(dev, vif, info); + if (!link) + goto out; + + mphy = mt76_vif_link_phy(&link->mt76); + if (!mphy) + goto out; + + phy = mphy->priv; + /* 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 && !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); + mt7996_mcu_add_bss_info(phy, vif, info, &link->mt76, + &link->msta_link, true); + mt7996_mcu_add_sta(dev, info, NULL, link, NULL, + CONN_STATE_PORT_SECURE, + !!(changed & BSS_CHANGED_BSSID)); } - if (changed & BSS_CHANGED_ERP_CTS_PROT) - mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot); - if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; if (slottime != phy->slottime) { phy->slottime = slottime; - mt7996_mcu_set_timing(phy, vif); + mt7996_mcu_set_timing(phy, vif, info); } } if (changed & BSS_CHANGED_MCAST_RATE) - mvif->mcast_rates_idx = - mt7996_get_rates_table(hw, vif, false, true); + link->mt76.mcast_rates_idx = + mt7996_get_rates_table(phy, info, false, true); if (changed & BSS_CHANGED_BASIC_RATES) - mvif->basic_rates_idx = - mt7996_get_rates_table(hw, vif, false, false); + link->mt76.basic_rates_idx = + mt7996_get_rates_table(phy, info, false, false); /* ensure that enable txcmd_mode after bss_info */ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) - mt7996_mcu_set_tx(dev, vif); + mt7996_mcu_set_tx(dev, vif, info); if (changed & BSS_CHANGED_HE_OBSS_PD) - mt7996_mcu_add_obss_spr(phy, vif, &info->he_obss_pd); - - if (changed & BSS_CHANGED_HE_BSS_COLOR) - mt7996_update_bss_color(hw, vif, &info->he_bss_color); + mt7996_mcu_add_obss_spr(phy, link, &info->he_obss_pd); + + if (changed & BSS_CHANGED_HE_BSS_COLOR) { + if ((vif->type == NL80211_IFTYPE_AP && + link->mt76.omac_idx <= HW_BSSID_MAX) || + vif->type == NL80211_IFTYPE_STATION) + mt7996_mcu_update_bss_color(dev, &link->mt76, + &info->he_bss_color); + } if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) { - mvif->beacon_rates_idx = - mt7996_get_rates_table(hw, vif, true, false); + link->mt76.beacon_rates_idx = + mt7996_get_rates_table(phy, info, true, false); - mt7996_mcu_add_beacon(hw, vif, info->enable_beacon); + mt7996_mcu_add_beacon(hw, vif, info); } if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)) - mt7996_mcu_beacon_inband_discov(dev, vif, changed); + mt7996_mcu_beacon_inband_discov(dev, info, link, changed); if (changed & BSS_CHANGED_MU_GROUPS) - mt7996_update_mu_group(hw, vif, info); + mt7996_update_mu_group(hw, link, info); + if (changed & BSS_CHANGED_TXPOWER && + info->txpower != phy->txpower) { + phy->txpower = info->txpower; + mt7996_mcu_set_txpower_sku(phy); + } + +out: mutex_unlock(&dev->mt76.mutex); } @@ -655,64 +873,332 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw, struct mt7996_dev *dev = mt7996_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7996_mcu_add_beacon(hw, vif, true); + mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf); mutex_unlock(&dev->mt76.mutex); } -int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int +mt7996_mac_sta_init_link(struct mt7996_dev *dev, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, unsigned int link_id) { - struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + struct ieee80211_sta *sta = link_sta->sta; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - u8 band_idx = mvif->phy->mt76->band_idx; - int ret, idx; + struct mt7996_phy *phy = link->phy; + struct mt7996_sta_link *msta_link; + int idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA); if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->rc_list); - INIT_LIST_HEAD(&msta->wcid.poll_list); - msta->vif = mvif; - msta->wcid.sta = 1; - msta->wcid.idx = idx; - msta->wcid.phy_idx = band_idx; - msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; + if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) { + int i; - ewma_avg_signal_init(&msta->avg_ack_signal); + msta_link = &msta->deflink; + msta->deflink_id = link_id; - mt7996_mac_wtbl_update(dev, idx, + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { + struct mt76_txq *mtxq; + + if (!sta->txq[i]) + continue; + + mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; + mtxq->wcid = idx; + } + } else { + msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL); + if (!msta_link) + return -ENOMEM; + } + + INIT_LIST_HEAD(&msta_link->rc_list); + INIT_LIST_HEAD(&msta_link->wcid.poll_list); + msta_link->sta = msta; + msta_link->wcid.sta = 1; + msta_link->wcid.idx = idx; + msta_link->wcid.link_id = link_id; + + ewma_avg_signal_init(&msta_link->avg_ack_signal); + ewma_signal_init(&msta_link->wcid.rssi); + + rcu_assign_pointer(msta->link[link_id], msta_link); + + mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + mt7996_mcu_add_sta(dev, link_conf, link_sta, link, msta_link, + CONN_STATE_DISCONNECT, true); + + rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid); + mt76_wcid_init(&msta_link->wcid, phy->mt76->band_idx); + + return 0; +} + +static void +mt7996_mac_sta_deinit_link(struct mt7996_dev *dev, + struct mt7996_sta_link *msta_link) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++) + mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, i); + + mt7996_mac_wtbl_update(dev, msta_link->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - ret = mt7996_mcu_add_sta(dev, vif, sta, true); - if (ret) - return ret; + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta_link->wcid.poll_list)) + list_del_init(&msta_link->wcid.poll_list); + if (!list_empty(&msta_link->rc_list)) + list_del_init(&msta_link->rc_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid); + mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx); +} + +static void +mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta, + unsigned long links) +{ + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt76_dev *mdev = &dev->mt76; + unsigned int link_id; + + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct mt7996_sta_link *msta_link = NULL; + + msta_link = rcu_replace_pointer(msta->link[link_id], msta_link, + lockdep_is_held(&mdev->mutex)); + if (!msta_link) + continue; + + mt7996_mac_sta_deinit_link(dev, msta_link); + if (msta->deflink_id == link_id) { + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; + continue; + } + + kfree_rcu(msta_link, rcu_head); + } +} + +static int +mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, unsigned long new_links) +{ + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + unsigned int link_id; + int err = 0; + + for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_bss_conf *link_conf; + struct ieee80211_link_sta *link_sta; + struct mt7996_vif_link *link; - return mt7996_mcu_add_rate_ctrl(dev, vif, sta, false); + if (rcu_access_pointer(msta->link[link_id])) + continue; + + link_conf = link_conf_dereference_protected(vif, link_id); + if (!link_conf) { + err = -EINVAL; + goto error_unlink; + } + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) { + err = -EINVAL; + goto error_unlink; + } + + link_sta = link_sta_dereference_protected(sta, link_id); + if (!link_sta) { + err = -EINVAL; + goto error_unlink; + } + + err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link, + link_id); + if (err) + goto error_unlink; + } + + return 0; + +error_unlink: + mt7996_mac_sta_remove_links(dev, sta, new_links); + + return err; } -void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int +mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 old_links, + u16 new_links) { + struct mt7996_dev *dev = mt7996_hw_dev(hw); + unsigned long add = new_links & ~old_links; + unsigned long rem = old_links & ~new_links; + int ret; + + mutex_lock(&dev->mt76.mutex); + + mt7996_mac_sta_remove_links(dev, sta, rem); + ret = mt7996_mac_sta_add_links(dev, vif, sta, add); + + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static int +mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_dev *mdev = mphy->dev; struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - int i; + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + unsigned long links = sta->mlo ? sta->valid_links : BIT(0); + int err; - mt7996_mcu_add_sta(dev, vif, sta, false); + mutex_lock(&mdev->mutex); - mt7996_mac_wtbl_update(dev, msta->wcid.idx, - MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; + msta->vif = mvif; + err = mt7996_mac_sta_add_links(dev, vif, sta, links); + if (!err) + mphy->num_sta++; + + mutex_unlock(&mdev->mutex); + + return err; +} - for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) - mt7996_mac_twt_teardown_flow(dev, msta, i); +static int +mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum mt76_sta_event ev) +{ + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + unsigned long links = sta->valid_links; + struct ieee80211_link_sta *link_sta; + unsigned int link_id; + + for_each_sta_active_link(vif, sta, link_sta, link_id) { + struct ieee80211_bss_conf *link_conf; + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + int i, err; + + link_conf = link_conf_dereference_protected(vif, link_id); + if (!link_conf) + continue; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); + if (!msta_link) + continue; + + switch (ev) { + case MT76_STA_EVENT_ASSOC: + err = mt7996_mcu_add_sta(dev, link_conf, link_sta, + link, msta_link, + CONN_STATE_CONNECT, true); + if (err) + return err; + + err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf, + link_sta, link, + msta_link, false); + if (err) + return err; + + msta_link->wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta_link->wcid.sta = 1; + break; + case MT76_STA_EVENT_AUTHORIZE: + err = mt7996_mcu_add_sta(dev, link_conf, link_sta, + link, msta_link, + CONN_STATE_PORT_SECURE, false); + if (err) + return err; + break; + case MT76_STA_EVENT_DISASSOC: + for (i = 0; i < ARRAY_SIZE(msta_link->twt.flow); i++) + mt7996_mac_twt_teardown_flow(dev, link, + msta_link, i); + + if (sta->mlo && links == BIT(link_id)) /* last link */ + mt7996_mcu_teardown_mld_sta(dev, link, + msta_link); + else + mt7996_mcu_add_sta(dev, link_conf, link_sta, + link, msta_link, + CONN_STATE_DISCONNECT, false); + msta_link->wcid.sta_disabled = 1; + msta_link->wcid.sta = 0; + links = links & ~BIT(link_id); + break; + } + } - spin_lock_bh(&mdev->sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); - if (!list_empty(&msta->rc_list)) - list_del_init(&msta->rc_list); - spin_unlock_bh(&mdev->sta_poll_lock); + return 0; +} + +static void +mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_dev *mdev = mphy->dev; + struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + unsigned long links = sta->mlo ? sta->valid_links : BIT(0); + + mutex_lock(&mdev->mutex); + + mt7996_mac_sta_remove_links(dev, sta, links); + mphy->num_sta--; + + mutex_unlock(&mdev->mutex); +} + +static int +mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + struct mt76_phy *mphy = mt76_vif_phy(hw, vif); + struct mt7996_dev *dev = mt7996_hw_dev(hw); + enum mt76_sta_event ev; + + if (!mphy) + return -EINVAL; + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) + return mt7996_mac_sta_add(mphy, vif, sta); + + if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST) + mt7996_mac_sta_remove(mphy, vif, sta); + + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) + ev = MT76_STA_EVENT_ASSOC; + else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) + ev = MT76_STA_EVENT_AUTHORIZE; + else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) + ev = MT76_STA_EVENT_DISASSOC; + else + return 0; + + return mt7996_mac_sta_event(dev, vif, sta, ev); } static void mt7996_tx(struct ieee80211_hw *hw, @@ -724,32 +1210,63 @@ static void mt7996_tx(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; + u8 link_id = u32_get_bits(info->control.flags, + IEEE80211_TX_CTRL_MLO_LINK); - if (control->sta) { - struct mt7996_sta *sta; + rcu_read_lock(); - sta = (struct mt7996_sta *)control->sta->drv_priv; - wcid = &sta->wcid; - } + if (vif) { + struct mt7996_vif *mvif = (void *)vif->drv_priv; + struct mt76_vif_link *mlink; - if (vif && !control->sta) { - struct mt7996_vif *mvif; + mlink = rcu_dereference(mvif->mt76.link[link_id]); + if (mlink && mlink->wcid) + wcid = mlink->wcid; + + if (mvif->mt76.roc_phy && + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) { + mphy = mvif->mt76.roc_phy; + if (mphy->roc_link) + wcid = mphy->roc_link->wcid; + } else { + mphy = mt76_vif_link_phy(&mvif->deflink.mt76); + } + } - mvif = (struct mt7996_vif *)vif->drv_priv; - wcid = &mvif->sta.wcid; + if (!mphy) { + ieee80211_free_txskb(hw, skb); + goto unlock; } + if (control->sta) { + struct mt7996_sta *msta = (void *)control->sta->drv_priv; + struct mt7996_sta_link *msta_link; + + msta_link = rcu_dereference(msta->link[link_id]); + if (msta_link) + wcid = &msta_link->wcid; + } mt76_tx(mphy, control->sta, wcid, skb); +unlock: + rcu_read_unlock(); } static int mt7996_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); - int ret; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + int i, ret = 0; + + mutex_lock(&dev->mt76.mutex); - mutex_lock(&phy->dev->mt76.mutex); - ret = mt7996_mcu_set_rts_thresh(phy, val); - mutex_unlock(&phy->dev->mt76.mutex); + for (i = 0; i < hw->wiphy->n_radio; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + + ret = mt7996_mcu_set_rts_thresh(phy, val); + if (ret) + break; + } + + mutex_unlock(&dev->mt76.mutex); return ret; } @@ -761,11 +1278,13 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action = params->action; struct mt7996_dev *dev = mt7996_hw_dev(hw); struct ieee80211_sta *sta = params->sta; - struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct ieee80211_txq *txq = sta->txq[params->tid]; + struct ieee80211_link_sta *link_sta; u16 tid = params->tid; u16 ssn = params->ssn; struct mt76_txq *mtxq; + unsigned int link_id; int ret = 0; if (!txq) @@ -774,93 +1293,108 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mtxq = (struct mt76_txq *)txq->drv_priv; mutex_lock(&dev->mt76.mutex); - switch (action) { - case IEEE80211_AMPDU_RX_START: - mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, - params->buf_size); - ret = mt7996_mcu_add_rx_ba(dev, params, true); - break; - case IEEE80211_AMPDU_RX_STOP: - mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); - ret = mt7996_mcu_add_rx_ba(dev, params, false); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - mtxq->aggr = true; - mtxq->send_bar = false; - ret = mt7996_mcu_add_tx_ba(dev, params, true); - break; - case IEEE80211_AMPDU_TX_STOP_FLUSH: - case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: - mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); - ret = mt7996_mcu_add_tx_ba(dev, params, false); - break; - case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->wcid.ampdu_state); - ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; - break; - case IEEE80211_AMPDU_TX_STOP_CONT: - mtxq->aggr = false; - clear_bit(tid, &msta->wcid.ampdu_state); - ret = mt7996_mcu_add_tx_ba(dev, params, false); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); - break; + + for_each_sta_active_link(vif, sta, link_sta, link_id) { + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); + if (!msta_link) + continue; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid, + ssn, params->buf_size); + ret = mt7996_mcu_add_rx_ba(dev, params, link, true); + break; + case IEEE80211_AMPDU_RX_STOP: + mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid); + ret = mt7996_mcu_add_rx_ba(dev, params, link, false); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mtxq->aggr = true; + mtxq->send_bar = false; + ret = mt7996_mcu_add_tx_ba(dev, params, link, + msta_link, true); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mtxq->aggr = false; + clear_bit(tid, &msta_link->wcid.ampdu_state); + ret = mt7996_mcu_add_tx_ba(dev, params, link, + msta_link, false); + break; + case IEEE80211_AMPDU_TX_START: + set_bit(tid, &msta_link->wcid.ampdu_state); + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + clear_bit(tid, &msta_link->wcid.ampdu_state); + ret = mt7996_mcu_add_tx_ba(dev, params, link, + msta_link, false); + break; + } + + if (ret) + break; } - mutex_unlock(&dev->mt76.mutex); - return ret; -} + if (action == IEEE80211_AMPDU_TX_STOP_CONT) + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); -static int -mt7996_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, - IEEE80211_STA_NONE); -} + mutex_unlock(&dev->mt76.mutex); -static int -mt7996_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, - IEEE80211_STA_NOTEXIST); + return ret; } static int mt7996_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt76_mib_stats *mib = &phy->mib; + int i; mutex_lock(&dev->mt76.mutex); - stats->dot11RTSSuccessCount = mib->rts_cnt; - stats->dot11RTSFailureCount = mib->rts_retries_cnt; - stats->dot11FCSErrorCount = mib->fcs_err_cnt; - stats->dot11ACKFailureCount = mib->ack_fail_cnt; + memset(stats, 0, sizeof(*stats)); + for (i = 0; i < hw->wiphy->n_radio; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + struct mt76_mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount += mib->rts_cnt; + stats->dot11RTSFailureCount += mib->rts_retries_cnt; + stats->dot11FCSErrorCount += mib->fcs_err_cnt; + stats->dot11ACKFailureCount += mib->ack_fail_cnt; + } mutex_unlock(&dev->mt76.mutex); return 0; } -u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif) +u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mt7996_phy *phy = link->phy; union { u64 t64; u32 t32[2]; } tsf; u16 n; + if (!phy) + return 0; + lockdep_assert_held(&dev->mt76.mutex); - n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 - : mvif->mt76.omac_idx; + n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : link->mt76.omac_idx; /* TSF software read */ mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, MT_LPON_TCR_SW_READ); @@ -878,7 +1412,7 @@ mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) u64 ret; mutex_lock(&dev->mt76.mutex); - ret = __mt7996_get_tsf(hw, mvif); + ret = __mt7996_get_tsf(hw, &mvif->deflink); mutex_unlock(&dev->mt76.mutex); return ret; @@ -890,7 +1424,8 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mt7996_vif_link *link; + struct mt7996_phy *phy; union { u64 t64; u32 t32[2]; @@ -899,14 +1434,23 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); - n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 - : mvif->mt76.omac_idx; + link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id); + if (!link) + goto unlock; + + n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : link->mt76.omac_idx; + phy = link->phy; + if (!phy) + goto unlock; + mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]); /* TSF software overwrite */ mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, MT_LPON_TCR_SW_WRITE); +unlock: mutex_unlock(&dev->mt76.mutex); } @@ -916,7 +1460,8 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); + struct mt7996_vif_link *link; + struct mt7996_phy *phy; union { u64 t64; u32 t32[2]; @@ -925,26 +1470,37 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); - n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 - : mvif->mt76.omac_idx; + link = mt7996_vif_link(dev, vif, mvif->mt76.deflink_id); + if (!link) + goto unlock; + + phy = link->phy; + if (!phy) + goto unlock; + + n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : link->mt76.omac_idx; mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]); /* TSF software adjust*/ mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, MT_LPON_TCR_SW_ADJUST); +unlock: mutex_unlock(&dev->mt76.mutex); } static void mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_phy *phy; mutex_lock(&dev->mt76.mutex); - phy->coverage_class = max_t(s16, coverage_class, 0); - mt7996_mac_set_coverage_class(phy); + mt7996_for_each_phy(dev, phy) { + phy->coverage_class = max_t(s16, coverage_class, 0); + mt7996_mac_set_coverage_class(phy); + } mutex_unlock(&dev->mt76.mutex); } @@ -952,33 +1508,34 @@ static int mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - int max_nss = hweight8(hw->wiphy->available_antennas_tx); - u8 band_idx = phy->mt76->band_idx, shift = dev->chainshift[band_idx]; + int i; - if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + if (tx_ant != rx_ant) return -EINVAL; - if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) - tx_ant = BIT(ffs(tx_ant) - 1) - 1; + for (i = 0; i < hw->wiphy->n_radio; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + + if (!(tx_ant & phy->orig_chainmask)) + return -EINVAL; + } mutex_lock(&dev->mt76.mutex); - phy->mt76->antenna_mask = tx_ant; + for (i = 0; i < hw->wiphy->n_radio; i++) { + struct mt7996_phy *phy = dev->radio_phy[i]; + u8 band_idx = phy->mt76->band_idx; + u8 shift = dev->chainshift[band_idx]; - /* restore to the origin chainmask which might have auxiliary path */ - if (hweight8(tx_ant) == max_nss && band_idx < MT_BAND2) - phy->mt76->chainmask = ((dev->chainmask >> shift) & - (BIT(dev->chainshift[band_idx + 1] - shift) - 1)) << shift; - else if (hweight8(tx_ant) == max_nss) - phy->mt76->chainmask = (dev->chainmask >> shift) << shift; - else - phy->mt76->chainmask = tx_ant << shift; + phy->mt76->chainmask = tx_ant & phy->orig_chainmask; + phy->mt76->antenna_mask = (phy->mt76->chainmask >> shift) & + phy->orig_antenna_mask; - mt76_set_stream_caps(phy->mt76, true); - mt7996_set_stream_vht_txbf_caps(phy); - mt7996_set_stream_he_eht_caps(phy); - mt7996_mcu_set_txpower_sku(phy); + mt76_set_stream_caps(phy->mt76, true); + mt7996_set_stream_vht_txbf_caps(phy); + mt7996_set_stream_he_eht_caps(phy); + mt7996_mcu_set_txpower_sku(phy); + } mutex_unlock(&dev->mt76.mutex); @@ -990,9 +1547,10 @@ 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_dev *dev = mt7996_hw_dev(hw); struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct rate_info *txrate = &msta->wcid.rate; + struct mt7996_sta_link *msta_link = &msta->deflink; + struct rate_info *txrate = &msta_link->wcid.rate; if (txrate->legacy || txrate->flags) { if (txrate->legacy) { @@ -1012,55 +1570,67 @@ 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->tx_failed = msta_link->wcid.stats.tx_failed; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->tx_retries = msta_link->wcid.stats.tx_retries; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); - sinfo->ack_signal = (s8)msta->ack_signal; + sinfo->ack_signal = (s8)msta_link->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->avg_ack_signal = + -(s8)ewma_avg_signal_read(&msta_link->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; + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + sinfo->tx_bytes = msta_link->wcid.stats.tx_bytes; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); - sinfo->rx_bytes = msta->wcid.stats.rx_bytes; + sinfo->rx_bytes = msta_link->wcid.stats.rx_bytes; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); - sinfo->tx_packets = msta->wcid.stats.tx_packets; + sinfo->tx_packets = msta_link->wcid.stats.tx_packets; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); - sinfo->rx_packets = msta->wcid.stats.rx_packets; + sinfo->rx_packets = msta_link->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) +static void mt7996_link_rate_ctrl_update(void *data, struct ieee80211_sta *sta) { struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct mt7996_dev *dev = msta->vif->phy->dev; + struct mt7996_dev *dev = msta->vif->deflink.phy->dev; + struct mt7996_sta_link *msta_link; u32 *changed = data; + rcu_read_lock(); + + msta_link = rcu_dereference(msta->link[msta->deflink_id]); + if (!msta_link) + goto out; + spin_lock_bh(&dev->mt76.sta_poll_lock); - msta->changed |= *changed; - if (list_empty(&msta->rc_list)) - list_add_tail(&msta->rc_list, &dev->sta_rc_list); + + msta_link->changed |= *changed; + if (list_empty(&msta_link->rc_list)) + list_add_tail(&msta_link->rc_list, &dev->sta_rc_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); +out: + rcu_read_unlock(); } -static void mt7996_sta_rc_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - u32 changed) +static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + u32 changed) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct ieee80211_sta *sta = link_sta->sta; - mt7996_sta_rc_work(&changed, sta); + mt7996_link_rate_ctrl_update(&changed, sta); ieee80211_queue_work(hw, &dev->rc_work); } @@ -1068,12 +1638,11 @@ static int mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { + struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_dev *dev = phy->dev; u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; - mvif->bitrate_mask = *mask; + mvif->deflink.bitrate_mask = *mask; /* if multiple rates across different preambles are given we can * reconfigure this info with all peers using sta_rec command with @@ -1083,7 +1652,8 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT * then multiple MCS setting (MCS 4,5,6) is not supported. */ - ieee80211_iterate_stations_atomic(hw, mt7996_sta_rc_work, &changed); + ieee80211_iterate_stations_atomic(hw, mt7996_link_rate_ctrl_update, + &changed); ieee80211_queue_work(hw, &dev->rc_work); return 0; @@ -1094,15 +1664,37 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool enabled) { - struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct ieee80211_link_sta *link_sta; + unsigned int link_id; - if (enabled) - set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); - else - clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + mutex_lock(&dev->mt76.mutex); + + for_each_sta_active_link(vif, sta, link_sta, link_id) { + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); + if (!msta_link) + continue; + + if (enabled) + set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags); + else + clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags); - mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta); + if (!msta_link->wcid.sta) + continue; + + mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link); + } + + mutex_unlock(&dev->mt76.mutex); } static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw, @@ -1110,15 +1702,39 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool enabled) { - struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct ieee80211_link_sta *link_sta; + unsigned int link_id; - if (enabled) - set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); - else - clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + mutex_lock(&dev->mt76.mutex); - mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta); + for_each_sta_active_link(vif, sta, link_sta, link_id) { + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); + if (!msta_link) + continue; + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, + &msta_link->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, + &msta_link->wcid.flags); + + if (!msta_link->wcid.sta) + continue; + + mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link); + } + + mutex_unlock(&dev->mt76.mutex); } static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { @@ -1250,11 +1866,12 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) { struct mt76_ethtool_worker_info *wi = wi_data; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_sta_link *msta_link = &msta->deflink; - if (msta->vif->mt76.idx != wi->idx) + if (msta->vif->deflink.mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->wcid.stats, true); + mt76_ethtool_worker(wi, &msta_link->wcid.stats, true); } static @@ -1263,16 +1880,19 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw, struct ethtool_stats *stats, u64 *data) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink); struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, - .idx = mvif->mt76.idx, + .idx = mvif->deflink.mt76.idx, }; /* See mt7996_ampdu_stat_read_phy, etc */ int i, ei = 0; + if (!phy) + return; + mutex_lock(&dev->mt76.mutex); mt7996_mac_update_stats(phy); @@ -1355,10 +1975,12 @@ mt7996_twt_teardown_request(struct ieee80211_hw *hw, u8 flowid) { struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_sta_link *msta_link = &msta->deflink; + struct mt7996_vif_link *link = &msta->vif->deflink; struct mt7996_dev *dev = mt7996_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7996_mac_twt_teardown_flow(dev, msta, flowid); + mt7996_mac_twt_teardown_flow(dev, link, msta_link, flowid); mutex_unlock(&dev->mt76.mutex); } @@ -1366,11 +1988,18 @@ static int mt7996_set_radar_background(struct ieee80211_hw *hw, struct cfg80211_chan_def *chandef) { - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_dev *dev = phy->dev; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + struct mt7996_phy *phy; int ret = -EINVAL; bool running; + if (chandef) + phy = mt7996_band_phy(dev, chandef->chan->band); + else + phy = dev->rdd2_phy; + if (!phy) + return -EINVAL; + mutex_lock(&dev->mt76.mutex); if (dev->mt76.region == NL80211_DFS_UNSET) @@ -1422,8 +2051,27 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw, struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; + struct mt76_vif_link *mlink; + struct mt7996_phy *phy; + + mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]); + if (!mlink) + return -EIO; + + msta_link = rcu_dereference(msta->link[msta->deflink_id]); + if (!msta_link) + return -EIO; + + if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA) + return -EIO; + + link = (struct mt7996_vif_link *)mlink; + phy = mt7996_vif_link_phy(link); + if (!phy) + return -ENODEV; if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2) wed = &dev->mt76.mmio.wed_hif2; @@ -1431,15 +2079,12 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw, if (!mtk_wed_device_active(wed)) return -ENODEV; - if (msta->wcid.idx > MT7996_WTBL_STA) - return -EIO; - path->type = DEV_PATH_MTK_WDMA; path->dev = ctx->dev; path->mtk_wdma.wdma_idx = wed->wdma_idx; - path->mtk_wdma.bss = mvif->mt76.idx; + path->mtk_wdma.bss = mlink->idx; path->mtk_wdma.queue = 0; - path->mtk_wdma.wcid = msta->wcid.idx; + path->mtk_wdma.wcid = msta_link->wcid.idx; path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed); ctx->dev = NULL; @@ -1449,7 +2094,21 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw, #endif +static int +mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u16 old_links, u16 new_links, + struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) +{ + return 0; +} + const struct ieee80211_ops mt7996_ops = { + .add_chanctx = mt76_add_chanctx, + .remove_chanctx = mt76_remove_chanctx, + .change_chanctx = mt76_change_chanctx, + .assign_vif_chanctx = mt76_assign_vif_chanctx, + .unassign_vif_chanctx = mt76_unassign_vif_chanctx, + .switch_vif_chanctx = mt76_switch_vif_chanctx, .tx = mt7996_tx, .start = mt7996_start, .stop = mt7996_stop, @@ -1458,19 +2117,21 @@ const struct ieee80211_ops mt7996_ops = { .config = mt7996_config, .conf_tx = mt7996_conf_tx, .configure_filter = mt7996_configure_filter, - .bss_info_changed = mt7996_bss_info_changed, - .sta_add = mt7996_sta_add, - .sta_remove = mt7996_sta_remove, + .vif_cfg_changed = mt7996_vif_cfg_changed, + .link_info_changed = mt7996_link_info_changed, + .sta_state = mt7996_sta_state, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, - .sta_rc_update = mt7996_sta_rc_update, + .link_sta_rc_update = mt7996_link_sta_rc_update, .set_key = mt7996_set_key, .ampdu_action = mt7996_ampdu_action, .set_rts_threshold = mt7996_set_rts_threshold, .wake_tx_queue = mt76_wake_tx_queue, - .sw_scan_start = mt76_sw_scan, - .sw_scan_complete = mt76_sw_scan_complete, + .hw_scan = mt76_hw_scan, + .cancel_hw_scan = mt76_cancel_hw_scan, + .remain_on_channel = mt76_remain_on_channel, + .cancel_remain_on_channel = mt76_cancel_remain_on_channel, .release_buffered_frames = mt76_release_buffered_frames, - .get_txpower = mt76_get_txpower, + .get_txpower = mt7996_get_txpower, .channel_switch_beacon = mt7996_channel_switch_beacon, .get_stats = mt7996_get_stats, .get_et_sset_count = mt7996_get_et_sset_count, @@ -1495,6 +2156,8 @@ const struct ieee80211_ops mt7996_ops = { .set_radar_background = mt7996_set_radar_background, #ifdef CONFIG_NET_MEDIATEK_SOC_WED .net_fill_forward_path = mt7996_net_fill_forward_path, - .net_setup_tc = mt76_net_setup_tc, + .net_setup_tc = mt76_wed_net_setup_tc, #endif + .change_vif_links = mt7996_change_vif_links, + .change_sta_links = mt7996_mac_sta_change_links, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 699be57309c2..f0adc0b4b8b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -13,12 +13,27 @@ #define fw_name(_dev, name, ...) ({ \ char *_fw; \ switch (mt76_chip(&(_dev)->mt76)) { \ - case 0x7992: \ - _fw = MT7992_##name; \ + case MT7992_DEVICE_ID: \ + switch ((_dev)->var.type) { \ + case MT7992_VAR_TYPE_23: \ + _fw = MT7992_##name##_23; \ + break; \ + default: \ + _fw = MT7992_##name; \ + } \ break; \ - case 0x7990: \ + case MT7990_DEVICE_ID: \ + _fw = MT7990_##name; \ + break; \ + case MT7996_DEVICE_ID: \ default: \ - _fw = MT7996_##name; \ + switch ((_dev)->var.type) { \ + case MT7996_VAR_TYPE_233: \ + _fw = MT7996_##name##_233; \ + break; \ + default: \ + _fw = MT7996_##name; \ + } \ break; \ } \ _fw; \ @@ -106,13 +121,13 @@ mt7996_mcu_get_sta_nss(u16 mcs_map) } static void -mt7996_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, - u16 mcs_map) +mt7996_mcu_set_sta_he_mcs(struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + __le16 *he_mcs, u16 mcs_map) { - struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band; - const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs; - int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; + int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss; + enum nl80211_band band = link->phy->mt76->chandef.chan->band; + const u16 *mask = link->bitrate_mask.control[band].he_mcs; for (nss = 0; nss < max_nss; nss++) { int mcs; @@ -155,11 +170,11 @@ mt7996_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, } static void -mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, - const u16 *mask) +mt7996_mcu_set_sta_vht_mcs(struct ieee80211_link_sta *link_sta, + __le16 *vht_mcs, const u16 *mask) { - u16 mcs, mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); - int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; + u16 mcs, mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map); + int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss; for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) { switch (mcs_map & 0x3) { @@ -181,13 +196,13 @@ mt7996_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, } static void -mt7996_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs, - const u8 *mask) +mt7996_mcu_set_sta_ht_mcs(struct ieee80211_link_sta *link_sta, + u8 *ht_mcs, const u8 *mask) { - int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; + int nss, max_nss = link_sta->rx_nss > 3 ? 4 : link_sta->rx_nss; for (nss = 0; nss < max_nss; nss++) - ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss]; + ht_mcs[nss] = link_sta->ht_cap.mcs.rx_mask[nss] & mask[nss]; } static int @@ -253,7 +268,7 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd); txd = (__le32 *)skb_push(skb, txd_len); - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state) && mt7996_has_wa(dev)) qid = MT_MCUQ_WA; else qid = MT_MCUQ_WM; @@ -323,8 +338,12 @@ exit: int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) { struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; __le32 args[3]; - } req = { + } __packed req = { .args = { cpu_to_le32(a1), cpu_to_le32(a2), @@ -332,7 +351,16 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) }, }; - return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), false); + if (mt7996_has_wa(dev)) + return mt76_mcu_send_msg(&dev->mt76, cmd, &req.args, + sizeof(req.args), false); + + req.tag = cpu_to_le16(cmd == MCU_WA_PARAM_CMD(QUERY) ? UNI_CMD_SDO_QUERY : + UNI_CMD_SDO_SET); + req.len = cpu_to_le16(sizeof(req) - 4); + + return mt76_mcu_send_msg(&dev->mt76, MCU_WA_UNI_CMD(SDO), &req, + sizeof(req), false); } static void @@ -341,7 +369,7 @@ mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION) return; - ieee80211_csa_finish(vif); + ieee80211_csa_finish(vif, 0); } static void @@ -352,23 +380,32 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) r = (struct mt7996_mcu_rdd_report *)skb->data; - if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) - return; - - if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2) + switch (r->rdd_idx) { + case MT_RDD_IDX_BAND2: + mphy = dev->mt76.phys[MT_BAND2]; + break; + case MT_RDD_IDX_BAND1: + mphy = dev->mt76.phys[MT_BAND1]; + break; + case MT_RDD_IDX_BACKGROUND: + if (!dev->rdd2_phy) + return; mphy = dev->rdd2_phy->mt76; - else - mphy = dev->mt76.phys[r->band_idx]; + break; + default: + dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx); + return; + } if (!mphy) return; - if (r->band_idx == MT_RX_SEL2) + if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) cfg80211_background_radar_event(mphy->hw->wiphy, &dev->rdd2_chandef, GFP_ATOMIC); else - ieee80211_radar_detected(mphy->hw); + ieee80211_radar_detected(mphy->hw, NULL); dev->hw_pattern++; } @@ -418,7 +455,7 @@ mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION) return; - ieee80211_color_change_finish(vif); + ieee80211_color_change_finish(vif, 0); } static void @@ -732,20 +769,16 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb) static struct tlv * mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len) { - struct tlv *ptlv, tlv = { - .tag = cpu_to_le16(tag), - .len = cpu_to_le16(len), - }; + struct tlv *ptlv = skb_put_zero(skb, len); - ptlv = skb_put(skb, len); - memcpy(ptlv, &tlv, sizeof(tlv)); + ptlv->tag = cpu_to_le16(tag); + ptlv->len = cpu_to_le16(len); return ptlv; } static void -mt7996_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct mt7996_phy *phy) +mt7996_mcu_bss_rfch_tlv(struct sk_buff *skb, struct mt7996_phy *phy) { static const u8 rlm_ch_band[] = { [NL80211_BAND_2GHZ] = 1, @@ -775,8 +808,7 @@ mt7996_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void -mt7996_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct mt7996_phy *phy) +mt7996_mcu_bss_ra_tlv(struct sk_buff *skb, struct mt7996_phy *phy) { struct bss_ra_tlv *ra; struct tlv *tlv; @@ -789,6 +821,7 @@ mt7996_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, static void mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, struct mt7996_phy *phy) { #define DEFAULT_HE_PE_DURATION 4 @@ -802,11 +835,11 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); he = (struct bss_info_uni_he *)tlv; - he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; + he->he_pe_duration = link_conf->htc_trig_based_pkt_ext; if (!he->he_pe_duration) he->he_pe_duration = DEFAULT_HE_PE_DURATION; - he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th); + he->he_rts_thres = cpu_to_le16(link_conf->frame_time_rts_th); if (!he->he_rts_thres) he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES); @@ -816,34 +849,36 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void -mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct mt7996_phy *phy, int enable) +mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, + bool enable) { struct bss_info_uni_mbssid *mbssid; struct tlv *tlv; + if (!link_conf->bssid_indicator && enable) + return; + 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; + if (enable) { + mbssid->max_indicator = link_conf->bssid_indicator; + mbssid->mbss_idx = link_conf->bssid_index; mbssid->tx_bss_omac_idx = 0; } } static void -mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, +mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt76_vif_link *mlink, struct mt7996_phy *phy) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct bss_rate_tlv *bmc; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; struct tlv *tlv; - u8 idx = mvif->mcast_rates_idx ? - mvif->mcast_rates_idx : mvif->basic_rates_idx; + u8 idx = mlink->mcast_rates_idx ? + mlink->mcast_rates_idx : mlink->basic_rates_idx; tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc)); @@ -867,9 +902,8 @@ mt7996_mcu_bss_txcmd_tlv(struct sk_buff *skb, bool en) } static void -mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct mt76_vif_link *mlink) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct bss_mld_tlv *mld; struct tlv *tlv; @@ -877,33 +911,28 @@ mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) mld = (struct bss_mld_tlv *)tlv; mld->group_mld_id = 0xff; - mld->own_mld_id = mvif->mt76.idx; + mld->own_mld_id = mlink->idx; mld->remap_idx = 0xff; } static void -mt7996_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +mt7996_mcu_bss_sec_tlv(struct sk_buff *skb, struct mt76_vif_link *mlink) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct bss_sec_tlv *sec; struct tlv *tlv; tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_SEC, sizeof(*sec)); sec = (struct bss_sec_tlv *)tlv; - sec->cipher = mvif->cipher; + sec->cipher = mlink->cipher; } static int -mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, - bool bssid, bool enable) +mt7996_mcu_muar_config(struct mt7996_dev *dev, struct mt76_vif_link *mlink, + const u8 *addr, bool bssid, bool enable) { #define UNI_MUAR_ENTRY 2 - struct mt7996_dev *dev = phy->dev; - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START; - const u8 *addr = vif->addr; - + u32 idx = mlink->omac_idx - REPEATER_BSSID_START; struct { struct { u8 band; @@ -920,7 +949,7 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, u8 addr[ETH_ALEN]; u8 __rsv[2]; } __packed req = { - .hdr.band = phy->mt76->band_idx, + .hdr.band = mlink->band_idx, .tag = cpu_to_le16(UNI_MUAR_ENTRY), .len = cpu_to_le16(sizeof(req) - sizeof(req.hdr)), .smesh = false, @@ -928,9 +957,6 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, .entry_add = true, }; - if (bssid) - addr = vif->bss_conf.bssid; - if (enable) memcpy(req.addr, addr, ETH_ALEN); @@ -939,10 +965,8 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, } static void -mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct mt7996_phy *phy) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_phy *phy = mvif->phy; struct bss_ifs_time_tlv *ifs_time; struct tlv *tlv; bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; @@ -969,15 +993,16 @@ mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) static int mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mvif, struct mt76_phy *phy, u16 wlan_idx, bool enable) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct cfg80211_chan_def *chandef = &phy->chandef; struct mt76_connac_bss_basic_tlv *bss; u32 type = CONNECTION_INFRA_AP; u16 sta_wlan_idx = wlan_idx; + struct ieee80211_sta *sta; struct tlv *tlv; int idx; @@ -989,9 +1014,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, case NL80211_IFTYPE_STATION: if (enable) { rcu_read_lock(); - if (!sta) - sta = ieee80211_find_sta(vif, - vif->bss_conf.bssid); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ if (sta) { struct mt76_wcid *wcid; @@ -1014,8 +1037,8 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*bss)); bss = (struct mt76_connac_bss_basic_tlv *)tlv; - bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - bss->dtim_period = vif->bss_conf.dtim_period; + bss->bcn_interval = cpu_to_le16(link_conf->beacon_int); + bss->dtim_period = link_conf->dtim_period; bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); bss->sta_idx = cpu_to_le16(sta_wlan_idx); bss->conn_type = cpu_to_le32(type); @@ -1033,19 +1056,19 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, return 0; } - memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); - bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + memcpy(bss->bssid, link_conf->bssid, ETH_ALEN); + bss->bcn_interval = cpu_to_le16(link_conf->beacon_int); bss->dtim_period = vif->bss_conf.dtim_period; bss->phymode = mt76_connac_get_phy_mode(phy, vif, chandef->chan->band, NULL); - bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, vif, + bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, &vif->bss_conf, chandef->chan->band); return 0; } static struct sk_buff * -__mt7996_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len) +__mt7996_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int len) { struct bss_req_hdr hdr = { .bss_idx = mvif->idx, @@ -1061,71 +1084,73 @@ __mt7996_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len) return skb; } -int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, - struct ieee80211_vif *vif, int enable) +int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink, + struct mt7996_sta_link *msta_link, int enable) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = phy->dev; struct sk_buff *skb; - if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) { - mt7996_mcu_muar_config(phy, vif, false, enable); - mt7996_mcu_muar_config(phy, vif, true, enable); + if (mlink->omac_idx >= REPEATER_BSSID_START) { + mt7996_mcu_muar_config(dev, mlink, link_conf->addr, false, enable); + mt7996_mcu_muar_config(dev, mlink, link_conf->bssid, true, enable); } - skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, MT7996_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* bss_basic must be first */ - mt7996_mcu_bss_basic_tlv(skb, vif, NULL, phy->mt76, - mvif->sta.wcid.idx, enable); - mt7996_mcu_bss_sec_tlv(skb, vif); + mt7996_mcu_bss_basic_tlv(skb, vif, link_conf, mlink, phy->mt76, + msta_link->wcid.idx, enable); + mt7996_mcu_bss_sec_tlv(skb, mlink); if (vif->type == NL80211_IFTYPE_MONITOR) goto out; if (enable) { - mt7996_mcu_bss_rfch_tlv(skb, vif, phy); - mt7996_mcu_bss_bmc_tlv(skb, vif, phy); - mt7996_mcu_bss_ra_tlv(skb, vif, phy); + mt7996_mcu_bss_rfch_tlv(skb, phy); + mt7996_mcu_bss_bmc_tlv(skb, mlink, phy); + mt7996_mcu_bss_ra_tlv(skb, phy); mt7996_mcu_bss_txcmd_tlv(skb, true); - mt7996_mcu_bss_ifs_timing_tlv(skb, vif); + mt7996_mcu_bss_ifs_timing_tlv(skb, phy); if (vif->bss_conf.he_support) - mt7996_mcu_bss_he_tlv(skb, vif, phy); + mt7996_mcu_bss_he_tlv(skb, vif, link_conf, phy); /* this tag is necessary no matter if the vif is MLD */ - mt7996_mcu_bss_mld_tlv(skb, vif); + mt7996_mcu_bss_mld_tlv(skb, mlink); } - mt7996_mcu_bss_mbssid_tlv(skb, vif, phy, enable); + mt7996_mcu_bss_mbssid_tlv(skb, link_conf, enable); out: return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } -int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = phy->dev; + struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf); struct sk_buff *skb; - skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, MT7996_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); - mt7996_mcu_bss_ifs_timing_tlv(skb, vif); + mt7996_mcu_bss_ifs_timing_tlv(skb, phy); return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } static int -mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif, +mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif, struct ieee80211_ampdu_params *params, bool enable, bool tx) { @@ -1157,37 +1182,34 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif, /** starec & wtbl **/ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev, struct ieee80211_ampdu_params *params, - bool enable) + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, bool enable) { - struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv; - struct mt7996_vif *mvif = msta->vif; - if (enable && !params->amsdu) - msta->wcid.amsdu = false; + msta_link->wcid.amsdu = false; - return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, true); + return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, true); } int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, struct ieee80211_ampdu_params *params, - bool enable) + struct mt7996_vif_link *link, bool enable) { - struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv; - struct mt7996_vif *mvif = msta->vif; - - return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, false); + return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, false); } static void -mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7996_mcu_sta_he_tlv(struct sk_buff *skb, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link) { - struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct ieee80211_he_cap_elem *elem = &link_sta->he_cap.he_cap_elem; struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he_v2 *he; struct tlv *tlv; int i = 0; - if (!sta->deflink.he_cap.has_he) + if (!link_sta->he_cap.has_he) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_V2, sizeof(*he)); @@ -1199,21 +1221,21 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) he->he_phy_cap[i] = elem->phy_cap_info[i]; } - mcs_map = sta->deflink.he_cap.he_mcs_nss_supp; - switch (sta->deflink.bandwidth) { + mcs_map = link_sta->he_cap.he_mcs_nss_supp; + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: if (elem->phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) - mt7996_mcu_set_sta_he_mcs(sta, + mt7996_mcu_set_sta_he_mcs(link_sta, link, &he->max_nss_mcs[CMD_HE_MCS_BW8080], le16_to_cpu(mcs_map.rx_mcs_80p80)); - mt7996_mcu_set_sta_he_mcs(sta, + mt7996_mcu_set_sta_he_mcs(link_sta, link, &he->max_nss_mcs[CMD_HE_MCS_BW160], le16_to_cpu(mcs_map.rx_mcs_160)); fallthrough; default: - mt7996_mcu_set_sta_he_mcs(sta, + mt7996_mcu_set_sta_he_mcs(link_sta, link, &he->max_nss_mcs[CMD_HE_MCS_BW80], le16_to_cpu(mcs_map.rx_mcs_80)); break; @@ -1223,33 +1245,38 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) } static void -mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, + struct ieee80211_link_sta *link_sta) { struct sta_rec_he_6g_capa *he_6g; struct tlv *tlv; - if (!sta->deflink.he_6ghz_capa.capa) + if (!link_sta->he_6ghz_capa.capa) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G, sizeof(*he_6g)); he_6g = (struct sta_rec_he_6g_capa *)tlv; - he_6g->capa = sta->deflink.he_6ghz_capa.capa; + he_6g->capa = link_sta->he_6ghz_capa.capa; } static void -mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, + struct ieee80211_link_sta *link_sta) { + struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv; + struct ieee80211_vif *vif = container_of((void *)msta->vif, + struct ieee80211_vif, drv_priv); struct ieee80211_eht_mcs_nss_supp *mcs_map; struct ieee80211_eht_cap_elem_fixed *elem; struct sta_rec_eht *eht; struct tlv *tlv; - if (!sta->deflink.eht_cap.has_eht) + if (!link_sta->eht_cap.has_eht) return; - mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp; - elem = &sta->deflink.eht_cap.eht_cap_elem; + mcs_map = &link_sta->eht_cap.eht_mcs_nss_supp; + elem = &link_sta->eht_cap.eht_cap_elem; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht)); @@ -1259,55 +1286,65 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info); eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]); - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) - memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20)); + if (vif->type != NL80211_IFTYPE_STATION && + (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & + (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) { + memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, + sizeof(eht->mcs_map_bw20)); + return; + } + memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80)); memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160)); memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320)); } static void -mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { struct sta_rec_ht_uni *ht; struct tlv *tlv; - if (!sta->deflink.ht_cap.ht_supported) + if (!link_sta->ht_cap.ht_supported) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht_uni *)tlv; - ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap); - ht->ampdu_param = u8_encode_bits(sta->deflink.ht_cap.ampdu_factor, + ht->ht_cap = cpu_to_le16(link_sta->ht_cap.cap); + ht->ampdu_param = u8_encode_bits(link_sta->ht_cap.ampdu_factor, IEEE80211_HT_AMPDU_PARM_FACTOR) | - u8_encode_bits(sta->deflink.ht_cap.ampdu_density, + u8_encode_bits(link_sta->ht_cap.ampdu_density, IEEE80211_HT_AMPDU_PARM_DENSITY); } static void -mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta) { struct sta_rec_vht *vht; struct tlv *tlv; /* For 6G band, this tlv is necessary to let hw work normally */ - if (!sta->deflink.he_6ghz_capa.capa && !sta->deflink.vht_cap.vht_supported) + if (!link_sta->he_6ghz_capa.capa && !link_sta->vht_cap.vht_supported) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); vht = (struct sta_rec_vht *)tlv; - vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap); - vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; - vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(link_sta->vht_cap.cap); + vht->vht_rx_mcs_map = link_sta->vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = link_sta->vht_cap.vht_mcs.tx_mcs_map; } static void mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct mt7996_sta_link *msta_link) { - struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct sta_rec_amsdu *amsdu; struct tlv *tlv; @@ -1316,16 +1353,16 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, vif->type != NL80211_IFTYPE_AP) return; - if (!sta->deflink.agg.max_amsdu_len) + if (!link_sta->agg.max_amsdu_len) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct sta_rec_amsdu *)tlv; amsdu->max_amsdu_num = 8; amsdu->amsdu_en = true; - msta->wcid.amsdu = true; + msta_link->wcid.amsdu = true; - switch (sta->deflink.agg.max_amsdu_len) { + switch (link_sta->agg.max_amsdu_len) { case IEEE80211_MAX_MPDU_LEN_VHT_11454: amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; @@ -1342,30 +1379,31 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, static void mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta) { - struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct ieee80211_he_cap_elem *elem = &link_sta->he_cap.he_cap_elem; struct sta_rec_muru *muru; struct tlv *tlv; - if (vif->type != NL80211_IFTYPE_STATION && - vif->type != NL80211_IFTYPE_AP) + if (link_conf->vif->type != NL80211_IFTYPE_STATION && + link_conf->vif->type != NL80211_IFTYPE_AP) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); muru = (struct sta_rec_muru *)tlv; - muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer || - vif->bss_conf.he_mu_beamformer || - vif->bss_conf.vht_mu_beamformer || - vif->bss_conf.vht_mu_beamformee; + muru->cfg.mimo_dl_en = link_conf->eht_mu_beamformer || + link_conf->he_mu_beamformer || + link_conf->vht_mu_beamformer || + link_conf->vht_mu_beamformee; muru->cfg.ofdma_dl_en = true; - if (sta->deflink.vht_cap.vht_supported) + if (link_sta->vht_cap.vht_supported) muru->mimo_dl.vht_mu_bfee = - !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); - if (!sta->deflink.he_cap.has_he) + if (!link_sta->he_cap.has_he) return; muru->mimo_dl.partial_bw_dl_mimo = @@ -1396,49 +1434,50 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, } static inline bool -mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool bfee) +mt7996_is_ebf_supported(struct mt7996_phy *phy, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, bool bfee) { int sts = hweight16(phy->mt76->chainmask); - if (vif->type != NL80211_IFTYPE_STATION && - vif->type != NL80211_IFTYPE_AP) + if (link_conf->vif->type != NL80211_IFTYPE_STATION && + link_conf->vif->type != NL80211_IFTYPE_AP) return false; if (!bfee && sts < 2) return false; - if (sta->deflink.eht_cap.has_eht) { - struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + if (link_sta->eht_cap.has_eht) { + struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap; struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; if (bfee) - return vif->bss_conf.eht_su_beamformee && - EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); - else - return vif->bss_conf.eht_su_beamformer && + return link_conf->eht_su_beamformee && EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); + else + return link_conf->eht_su_beamformer && + EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); } - if (sta->deflink.he_cap.has_he) { - struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; + if (link_sta->he_cap.has_he) { + struct ieee80211_he_cap_elem *pe = &link_sta->he_cap.he_cap_elem; if (bfee) - return vif->bss_conf.he_su_beamformee && + return link_conf->he_su_beamformee && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); else - return vif->bss_conf.he_su_beamformer && + return link_conf->he_su_beamformer && HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } - if (sta->deflink.vht_cap.vht_supported) { - u32 cap = sta->deflink.vht_cap.cap; + if (link_sta->vht_cap.vht_supported) { + u32 cap = link_sta->vht_cap.cap; if (bfee) - return vif->bss_conf.vht_su_beamformee && + return link_conf->vht_su_beamformee && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); else - return vif->bss_conf.vht_su_beamformer && + return link_conf->vht_su_beamformer && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); } @@ -1446,19 +1485,24 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, } static void -mt7996_mcu_sta_sounding_rate(struct sta_rec_bf *bf) +mt7996_mcu_sta_sounding_rate(struct sta_rec_bf *bf, struct mt7996_phy *phy) { bf->sounding_phy = MT_PHY_TYPE_OFDM; bf->ndp_rate = 0; /* mcs0 */ - bf->ndpa_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ + if (is_mt7996(phy->mt76->dev)) + bf->ndpa_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ + else + bf->ndpa_rate = MT7992_CFEND_RATE_DEFAULT; /* ofdm 6m */ + bf->rept_poll_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ } static void -mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy, - struct sta_rec_bf *bf) +mt7996_mcu_sta_bfer_ht(struct ieee80211_link_sta *link_sta, + struct mt7996_phy *phy, struct sta_rec_bf *bf, + bool explicit) { - struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs; + struct ieee80211_mcs_info *mcs = &link_sta->ht_cap.mcs; u8 n = 0; bf->tx_mode = MT_PHY_TYPE_HT; @@ -1476,14 +1520,16 @@ mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy, bf->nrow = hweight8(phy->mt76->antenna_mask) - 1; bf->ncol = min_t(u8, bf->nrow, n); - bf->ibf_ncol = n; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, n); } static void -mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, - struct sta_rec_bf *bf, bool explicit) +mt7996_mcu_sta_bfer_vht(struct ieee80211_link_sta *link_sta, + struct mt7996_phy *phy, struct sta_rec_bf *bf, + bool explicit) { - struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap; + struct ieee80211_sta_vht_cap *pc = &link_sta->vht_cap; struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap; u16 mcs_map = le16_to_cpu(pc->vht_mcs.rx_mcs_map); u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); @@ -1494,7 +1540,7 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, if (explicit) { u8 sts, snd_dim; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); sts = FIELD_GET(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, pc->cap); @@ -1502,25 +1548,26 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, vc->cap); bf->nrow = min_t(u8, min_t(u8, snd_dim, sts), tx_ant); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, bf->ncol); - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) bf->nrow = 1; } else { bf->nrow = tx_ant; bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = nss_mcs; + bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) bf->ibf_nrow = 1; } } static void -mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, - struct mt7996_phy *phy, struct sta_rec_bf *bf) +mt7996_mcu_sta_bfer_he(struct ieee80211_link_sta *link_sta, + struct ieee80211_vif *vif, struct mt7996_phy *phy, + struct sta_rec_bf *bf, bool explicit) { - struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_sta_he_cap *pc = &link_sta->he_cap; struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; const struct ieee80211_sta_he_cap *vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); @@ -1529,9 +1576,12 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); u8 snd_dim, sts; + if (!vc) + return; + bf->tx_mode = MT_PHY_TYPE_HE_SU; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); bf->trigger_su = HE_PHY(CAP6_TRIG_SU_BEAMFORMING_FB, pe->phy_cap_info[6]); @@ -1543,9 +1593,10 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, pe->phy_cap_info[4]); bf->nrow = min_t(u8, snd_dim, sts); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); - if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160) + if (link_sta->bandwidth != IEEE80211_STA_RX_BW_160) return; /* go over for 160MHz and 80p80 */ @@ -1577,10 +1628,11 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, } static void -mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, - struct mt7996_phy *phy, struct sta_rec_bf *bf) +mt7996_mcu_sta_bfer_eht(struct ieee80211_link_sta *link_sta, + struct ieee80211_vif *vif, struct mt7996_phy *phy, + struct sta_rec_bf *bf, bool explicit) { - struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap; struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; const struct ieee80211_sta_eht_cap *vc = @@ -1592,7 +1644,7 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, bf->tx_mode = MT_PHY_TYPE_EHT_MU; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); bf->trigger_su = EHT_PHY(CAP3_TRIG_SU_BF_FDBK, pe->phy_cap_info[3]); bf->trigger_mu = EHT_PHY(CAP3_TRIG_MU_BF_PART_BW_FDBK, pe->phy_cap_info[3]); @@ -1601,12 +1653,13 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, (EHT_PHY(CAP1_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[1]) << 1); bf->nrow = min_t(u8, snd_dim, sts); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); - if (sta->deflink.bandwidth < IEEE80211_STA_RX_BW_160) + if (link_sta->bandwidth < IEEE80211_STA_RX_BW_160) return; - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_160MHZ_MASK, ve->phy_cap_info[2]); sts = EHT_PHY(CAP1_BEAMFORMEE_SS_160MHZ_MASK, pe->phy_cap_info[1]); @@ -1634,14 +1687,19 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, static void mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_phy *phy = mvif->phy; - int tx_ant = hweight8(phy->mt76->chainmask) - 1; +#define EBF_MODE BIT(0) +#define IBF_MODE BIT(1) +#define BF_MAT_ORDER 4 + struct ieee80211_vif *vif = link_conf->vif; + struct mt7996_phy *phy = link->phy; + int tx_ant = hweight16(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; - const u8 matrix[4][4] = { + static const u8 matrix[BF_MAT_ORDER][BF_MAT_ORDER] = { {0, 0, 0, 0}, {1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */ {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */ @@ -1649,47 +1707,57 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, }; bool ebf; - if (!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) + if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he)) return; - ebf = mt7996_is_ebf_supported(phy, vif, sta, false); + ebf = mt7996_is_ebf_supported(phy, link_conf, link_sta, false); if (!ebf && !dev->ibf) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); bf = (struct sta_rec_bf *)tlv; - /* he/eht: eBF only, in accordance with spec + /* he/eht: eBF only, except mt7992 that has 5T on 5GHz also supports iBF * vht: support eBF and iBF * ht: iBF only, since mac80211 lacks of eBF support */ - if (sta->deflink.eht_cap.has_eht && ebf) - mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf); - else if (sta->deflink.he_cap.has_he && ebf) - mt7996_mcu_sta_bfer_he(sta, vif, phy, bf); - else if (sta->deflink.vht_cap.vht_supported) - mt7996_mcu_sta_bfer_vht(sta, phy, bf, ebf); - else if (sta->deflink.ht_cap.ht_supported) - mt7996_mcu_sta_bfer_ht(sta, phy, bf); + if (link_sta->eht_cap.has_eht) + mt7996_mcu_sta_bfer_eht(link_sta, vif, link->phy, bf, ebf); + else if (link_sta->he_cap.has_he) + mt7996_mcu_sta_bfer_he(link_sta, vif, link->phy, bf, ebf); + else if (link_sta->vht_cap.vht_supported) + mt7996_mcu_sta_bfer_vht(link_sta, link->phy, bf, ebf); + else if (link_sta->ht_cap.ht_supported) + mt7996_mcu_sta_bfer_ht(link_sta, link->phy, bf, ebf); else return; - bf->bf_cap = ebf ? ebf : dev->ibf << 1; - bf->bw = sta->deflink.bandwidth; - bf->ibf_dbw = sta->deflink.bandwidth; + bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0); + if (is_mt7992(&dev->mt76) && tx_ant == 4) + bf->bf_cap |= IBF_MODE; + + bf->bw = link_sta->bandwidth; + bf->ibf_dbw = link_sta->bandwidth; bf->ibf_nrow = tx_ant; - if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) - bf->ibf_timeout = 0x48; + if (link_sta->eht_cap.has_eht || link_sta->he_cap.has_he) + bf->ibf_timeout = is_mt7996(&dev->mt76) ? MT7996_IBF_TIMEOUT : + MT7992_IBF_TIMEOUT; + else if (!ebf && link_sta->bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) + bf->ibf_timeout = MT7996_IBF_TIMEOUT_LEGACY; else - bf->ibf_timeout = 0x18; + bf->ibf_timeout = MT7996_IBF_TIMEOUT; - if (ebf && bf->nrow != tx_ant) - bf->mem_20m = matrix[tx_ant][bf->ncol]; - else - bf->mem_20m = matrix[bf->nrow][bf->ncol]; + if (bf->ncol < BF_MAT_ORDER) { + if (ebf) + bf->mem_20m = tx_ant < BF_MAT_ORDER ? + matrix[tx_ant][bf->ncol] : 0; + else + bf->mem_20m = bf->nrow < BF_MAT_ORDER ? + matrix[bf->nrow][bf->ncol] : 0; + } - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: case IEEE80211_STA_RX_BW_80: bf->mem_total = bf->mem_20m * 2; @@ -1705,31 +1773,32 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, static void mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_phy *phy = mvif->phy; + struct mt7996_phy *phy = link->phy; int tx_ant = hweight8(phy->mt76->antenna_mask) - 1; struct sta_rec_bfee *bfee; struct tlv *tlv; u8 nrow = 0; - if (!(sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he)) + if (!(link_sta->vht_cap.vht_supported || link_sta->he_cap.has_he)) return; - if (!mt7996_is_ebf_supported(phy, vif, sta, true)) + if (!mt7996_is_ebf_supported(phy, link_conf, link_sta, true)) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee)); bfee = (struct sta_rec_bfee *)tlv; - if (sta->deflink.he_cap.has_he) { - struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; + if (link_sta->he_cap.has_he) { + struct ieee80211_he_cap_elem *pe = &link_sta->he_cap.he_cap_elem; nrow = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, pe->phy_cap_info[5]); - } else if (sta->deflink.vht_cap.vht_supported) { - struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap; + } else if (link_sta->vht_cap.vht_supported) { + struct ieee80211_sta_vht_cap *pc = &link_sta->vht_cap; nrow = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK, pc->cap); @@ -1740,6 +1809,18 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb, } static void +mt7996_mcu_sta_tx_proc_tlv(struct sk_buff *skb) +{ + struct sta_rec_tx_proc *tx_proc; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_TX_PROC, sizeof(*tx_proc)); + + tx_proc = (struct sta_rec_tx_proc *)tlv; + tx_proc->flag = cpu_to_le32(0); +} + +static void mt7996_mcu_sta_hdrt_tlv(struct mt7996_dev *dev, struct sk_buff *skb) { struct sta_rec_hdrt *hdrt; @@ -1753,11 +1834,9 @@ mt7996_mcu_sta_hdrt_tlv(struct mt7996_dev *dev, struct sk_buff *skb) static void mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_vif *vif, struct mt76_wcid *wcid) { struct sta_rec_hdr_trans *hdr_trans; - struct mt76_wcid *wcid; struct tlv *tlv; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HDR_TRANS, sizeof(*hdr_trans)); @@ -1769,7 +1848,6 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb, else hdr_trans->from_ds = true; - wcid = (struct mt76_wcid *)sta->drv_priv; if (!wcid) return; @@ -1827,18 +1905,19 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, MCU_WM_UNI_CMD(RA), true); } -int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *data, u32 field) +int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, + 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_uni *phy = data; struct sta_rec_ra_fixed_uni *ra; struct sk_buff *skb; struct tlv *tlv; - skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid, + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, + &msta_link->wcid, MT7996_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -1857,7 +1936,7 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif ra->phy = *phy; break; case RATE_PARAM_MMPS_UPDATE: - ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode); + ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode); break; default: break; @@ -1869,12 +1948,13 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif } static int -mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link) { - 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; + struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef; + struct cfg80211_bitrate_mask *mask = &link->bitrate_mask; enum nl80211_band band = chandef->chan->band; struct sta_phy_uni phy = {}; int ret, nrates = 0; @@ -1895,11 +1975,11 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif } \ } while (0) - if (sta->deflink.he_cap.has_he) { + if (link_sta->he_cap.has_he) { __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1); - } else if (sta->deflink.vht_cap.vht_supported) { + } else if (link_sta->vht_cap.vht_supported) { __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0); - } else if (sta->deflink.ht_cap.ht_supported) { + } else if (link_sta->ht_cap.ht_supported) { __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0); } else { nrates = hweight32(mask->control[band].legacy); @@ -1916,7 +1996,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif /* fixed single rate */ if (nrates == 1) { - ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy, + ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, + msta_link, &phy, RATE_PARAM_FIXED_MCS); if (ret) return ret; @@ -1925,20 +2006,20 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif /* 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) + addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7); + if (link_sta->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, + ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, + msta_link, &phy, RATE_PARAM_FIXED_GI); if (ret) return ret; @@ -1946,7 +2027,8 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif /* fixed HE_LTF */ if (mask->control[band].he_ltf != GENMASK(7, 0)) { - ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy, + ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, + msta_link, &phy, RATE_PARAM_FIXED_HE_LTF); if (ret) return ret; @@ -1957,29 +2039,32 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif static void mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, - struct ieee80211_vif *vif, struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt76_phy *mphy = mvif->phy->mt76; +#define INIT_RCPI 180 + struct mt76_phy *mphy = link->phy->mt76; struct cfg80211_chan_def *chandef = &mphy->chandef; - struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask; + struct cfg80211_bitrate_mask *mask = &link->bitrate_mask; + u32 cap = link_sta->sta->wme ? STA_CAP_WMM : 0; enum nl80211_band band = chandef->chan->band; struct sta_rec_ra_uni *ra; struct tlv *tlv; - u32 supp_rate = sta->deflink.supp_rates[band]; - u32 cap = sta->wme ? STA_CAP_WMM : 0; + u32 supp_rate = link_sta->supp_rates[band]; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); ra = (struct sta_rec_ra_uni *)tlv; ra->valid = true; ra->auto_rate = true; - ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta); + ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, link_sta); ra->channel = chandef->chan->hw_value; - ra->bw = (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ? - CMD_CBW_320MHZ : sta->deflink.bandwidth; + ra->bw = (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ? + CMD_CBW_320MHZ : link_sta->bandwidth; ra->phy.bw = ra->bw; - ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode); + ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode); if (supp_rate) { supp_rate &= mask->control[band].legacy; @@ -1999,75 +2084,79 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, } } - if (sta->deflink.ht_cap.ht_supported) { + if (link_sta->ht_cap.ht_supported) { ra->supp_mode |= MODE_HT; - ra->af = sta->deflink.ht_cap.ampdu_factor; - ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); + ra->af = link_sta->ht_cap.ampdu_factor; + ra->ht_gf = !!(link_sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); cap |= STA_CAP_HT; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) cap |= STA_CAP_SGI_20; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) cap |= STA_CAP_SGI_40; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC) cap |= STA_CAP_TX_STBC; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (vif->bss_conf.ht_ldpc && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) + if (link_conf->ht_ldpc && + (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; - mt7996_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, + mt7996_mcu_set_sta_ht_mcs(link_sta, ra->ht_mcs, mask->control[band].ht_mcs); ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { u8 af; ra->supp_mode |= MODE_VHT; af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->deflink.vht_cap.cap); + link_sta->vht_cap.cap); ra->af = max_t(u8, ra->af, af); cap |= STA_CAP_VHT; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) cap |= STA_CAP_VHT_SGI_80; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) cap |= STA_CAP_VHT_SGI_160; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC) cap |= STA_CAP_VHT_TX_STBC; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (vif->bss_conf.vht_ldpc && - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) + if ((vif->type != NL80211_IFTYPE_AP || link_conf->vht_ldpc) && + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; - mt7996_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, + mt7996_mcu_set_sta_vht_mcs(link_sta, ra->supp_vht_mcs, mask->control[band].vht_mcs); } - if (sta->deflink.he_cap.has_he) { + if (link_sta->he_cap.has_he) { ra->supp_mode |= MODE_HE; cap |= STA_CAP_HE; - if (sta->deflink.he_6ghz_capa.capa) - ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + if (link_sta->he_6ghz_capa.capa) + ra->af = le16_get_bits(link_sta->he_6ghz_capa.capa, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); } ra->sta_cap = cpu_to_le32(cap); + + memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi)); } -int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool changed) +int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, bool changed) { - 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, + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, + &msta_link->wcid, MT7996_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2077,19 +2166,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif, * update sta_rec_he here. */ if (changed) - mt7996_mcu_sta_he_tlv(skb, sta); + mt7996_mcu_sta_he_tlv(skb, link_sta, link); /* sta_rec_ra accommodates BW, NSS and only MCS range format * i.e 0-{7,8,9} for VHT. */ - mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); + mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link); 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); + return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link); } static int @@ -2098,6 +2187,7 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif, { #define MT_STA_BSS_GROUP 1 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_sta_link *msta_link; struct mt7996_sta *msta; struct { u8 __rsv1[4]; @@ -2113,67 +2203,154 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif, .tag = cpu_to_le16(UNI_VOW_DRR_CTRL), .len = cpu_to_le16(sizeof(req) - 4), .action = cpu_to_le32(MT_STA_BSS_GROUP), - .val = cpu_to_le32(mvif->mt76.idx % 16), + .val = cpu_to_le32(mvif->deflink.mt76.idx % 16), }; - msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta; - req.wlan_idx = cpu_to_le16(msta->wcid.idx); + msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL; + msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link; + req.wlan_idx = cpu_to_le16(msta_link->wcid.idx); return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req, sizeof(req), true); } -int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable) +static void +mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + struct ieee80211_sta *sta) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_sta *msta; + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + unsigned long links = sta->valid_links; + unsigned int nlinks = hweight16(links); + struct mld_setup_link *mld_setup_link; + struct sta_rec_mld_setup *mld_setup; + struct mt7996_sta_link *msta_link; + struct ieee80211_vif *vif; + unsigned int link_id; + struct tlv *tlv; + + msta_link = mt76_dereference(msta->link[msta->deflink_id], &dev->mt76); + if (!msta_link) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, + sizeof(struct sta_rec_mld_setup) + + sizeof(struct mld_setup_link) * nlinks); + + mld_setup = (struct sta_rec_mld_setup *)tlv; + memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN); + mld_setup->setup_wcid = cpu_to_le16(msta_link->wcid.idx); + mld_setup->primary_id = cpu_to_le16(msta_link->wcid.idx); + + if (nlinks > 1) { + link_id = __ffs(links & ~BIT(msta->deflink_id)); + msta_link = mt76_dereference(msta->link[msta->deflink_id], + &dev->mt76); + if (!msta_link) + return; + } + mld_setup->seconed_id = cpu_to_le16(msta_link->wcid.idx); + mld_setup->link_num = nlinks; + + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + mld_setup_link = (struct mld_setup_link *)mld_setup->link_info; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + struct mt7996_vif_link *link; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); + if (!msta_link) + continue; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link) + continue; + + mld_setup_link->wcid = cpu_to_le16(msta_link->wcid.idx); + mld_setup_link->bss_idx = link->mt76.idx; + mld_setup_link++; + } +} + +static void +mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + struct ieee80211_sta *sta) +{ + struct sta_rec_eht_mld *eht_mld; + struct tlv *tlv; + int i; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld)); + eht_mld = (struct sta_rec_eht_mld *)tlv; + + for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++) + eht_mld->str_cap[i] = 0x7; +} + +int mt7996_mcu_add_sta(struct mt7996_dev *dev, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, + int conn_state, bool newly) +{ + struct mt76_wcid *wcid = msta_link ? &msta_link->wcid : link->mt76.wcid; + struct ieee80211_sta *sta = link_sta ? link_sta->sta : NULL; struct sk_buff *skb; int ret; - msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta; - - skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid, + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, wcid, MT7996_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* starec basic */ - mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable, - !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); - if (!enable) + mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, link_conf, link_sta, + conn_state, newly); + + if (conn_state == CONN_STATE_DISCONNECT) goto out; + /* starec hdr trans */ + mt7996_mcu_sta_hdr_trans_tlv(dev, skb, link_conf->vif, wcid); + /* starec tx proc */ + mt7996_mcu_sta_tx_proc_tlv(skb); + /* tag order is in accordance with firmware dependency. */ - if (sta) { + if (link_sta) { /* starec hdrt mode */ mt7996_mcu_sta_hdrt_tlv(dev, skb); - /* starec bfer */ - mt7996_mcu_sta_bfer_tlv(dev, skb, vif, sta); + if (conn_state == CONN_STATE_CONNECT) { + /* starec bfer */ + mt7996_mcu_sta_bfer_tlv(dev, skb, link_conf, link_sta, + link); + /* starec bfee */ + mt7996_mcu_sta_bfee_tlv(dev, skb, link_conf, link_sta, + link); + } /* starec ht */ - mt7996_mcu_sta_ht_tlv(skb, sta); + mt7996_mcu_sta_ht_tlv(skb, link_sta); /* starec vht */ - mt7996_mcu_sta_vht_tlv(skb, sta); + mt7996_mcu_sta_vht_tlv(skb, link_sta); /* starec uapsd */ - mt76_connac_mcu_sta_uapsd(skb, vif, sta); + mt76_connac_mcu_sta_uapsd(skb, link_conf->vif, sta); /* starec amsdu */ - mt7996_mcu_sta_amsdu_tlv(dev, skb, vif, sta); + mt7996_mcu_sta_amsdu_tlv(dev, skb, link_conf->vif, link_sta, + msta_link); /* starec he */ - mt7996_mcu_sta_he_tlv(skb, sta); + mt7996_mcu_sta_he_tlv(skb, link_sta, link); /* starec he 6g*/ - mt7996_mcu_sta_he_6g_tlv(skb, sta); + mt7996_mcu_sta_he_6g_tlv(skb, link_sta); /* starec eht */ - mt7996_mcu_sta_eht_tlv(skb, sta); + mt7996_mcu_sta_eht_tlv(skb, link_sta); /* starec muru */ - mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta); - /* starec bfee */ - mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta); - /* starec hdr trans */ - mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta); + mt7996_mcu_sta_muru_tlv(dev, skb, link_conf, link_sta); + + if (sta->mlo) { + mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta); + mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta); + } } - ret = mt7996_mcu_add_group(dev, vif, sta); + ret = mt7996_mcu_add_group(dev, link_conf->vif, sta); if (ret) { dev_kfree_skb(skb); return ret; @@ -2183,6 +2360,24 @@ out: MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); } +int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link) +{ + struct sk_buff *skb; + + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, + &msta_link->wcid, + MT7996_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, sizeof(struct tlv)); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); +} + static int mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid, struct sk_buff *skb, @@ -2232,7 +2427,7 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; struct sk_buff *skb; int ret; @@ -2248,17 +2443,18 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true); } -static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif, - u8 *pn) +static int mt7996_mcu_get_pn(struct mt7996_dev *dev, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, u8 *pn) { #define TSC_TYPE_BIGTK_PN 2 - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct sta_rec_pn_info *pn_info; struct sk_buff *skb, *rskb; struct tlv *tlv; int ret; - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, + &msta_link->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2282,10 +2478,11 @@ static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif, return 0; } -int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif, +int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, struct ieee80211_key_conf *key) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_mcu_bcn_prot_tlv *bcn_prot; struct sk_buff *skb; struct tlv *tlv; @@ -2294,7 +2491,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif sizeof(struct mt7996_mcu_bcn_prot_tlv); int ret; - skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len); + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, len); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2302,7 +2499,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv; - ret = mt7996_mcu_get_pn(dev, vif, pn); + ret = mt7996_mcu_get_pn(dev, link, msta_link, pn); if (ret) { dev_kfree_skb(skb); return ret; @@ -2334,11 +2531,12 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } -int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, - struct ieee80211_vif *vif, bool enable) + +int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink, bool enable) { struct mt7996_dev *dev = phy->dev; - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct { struct req_hdr { u8 omac_idx; @@ -2354,8 +2552,8 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, } __packed tlv; } data = { .hdr = { - .omac_idx = mvif->mt76.omac_idx, - .band_idx = mvif->mt76.band_idx, + .omac_idx = mlink->omac_idx, + .band_idx = mlink->band_idx, }, .tlv = { .tag = cpu_to_le16(DEV_INFO_ACTIVE), @@ -2364,18 +2562,18 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, }, }; - if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) - return mt7996_mcu_muar_config(phy, vif, false, enable); + if (mlink->omac_idx >= REPEATER_BSSID_START) + return mt7996_mcu_muar_config(dev, mlink, link_conf->addr, false, enable); - memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + memcpy(data.tlv.omac_addr, link_conf->addr, ETH_ALEN); return mt76_mcu_send_msg(&dev->mt76, MCU_WMWA_UNI_CMD(DEV_INFO_UPDATE), &data, sizeof(data), true); } static void -mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, - struct sk_buff *skb, - struct ieee80211_mutable_offsets *offs) +mt7996_mcu_beacon_cntdwn(struct sk_buff *rskb, struct sk_buff *skb, + struct ieee80211_mutable_offsets *offs, + bool csa) { struct bss_bcn_cntdwn_tlv *info; struct tlv *tlv; @@ -2384,7 +2582,7 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, if (!offs->cntdwn_counter_offs[0]) return; - tag = vif->bss_conf.csa_active ? UNI_BSS_INFO_BCN_CSA : UNI_BSS_INFO_BCN_BCC; + tag = csa ? UNI_BSS_INFO_BCN_CSA : UNI_BSS_INFO_BCN_BCC; tlv = mt7996_mcu_add_uni_tlv(rskb, tag, sizeof(*info)); @@ -2394,16 +2592,13 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, 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 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; @@ -2446,7 +2641,8 @@ mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, } static void -mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, +mt7996_mcu_beacon_cont(struct mt7996_dev *dev, + struct ieee80211_bss_conf *link_conf, struct sk_buff *rskb, struct sk_buff *skb, struct bss_bcn_content_tlv *bcn, struct ieee80211_mutable_offsets *offs) @@ -2460,9 +2656,9 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, if (offs->cntdwn_counter_offs[0]) { u16 offset = offs->cntdwn_counter_offs[0]; - if (vif->bss_conf.csa_active) + if (link_conf->csa_active) bcn->csa_ie_pos = cpu_to_le16(offset - 4); - if (vif->bss_conf.color_change_active) + if (link_conf->color_change_active) bcn->bcc_ie_pos = cpu_to_le16(offset - 3); } @@ -2473,92 +2669,106 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } -int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int en) +int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf); struct ieee80211_mutable_offsets offs; struct ieee80211_tx_info *info; struct sk_buff *skb, *rskb; struct tlv *tlv; struct bss_bcn_content_tlv *bcn; - int len; + int len, extra_len = 0; - if (vif->bss_conf.nontransmitted) + if (link_conf->nontransmitted) return 0; - rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + if (!mlink) + return -EINVAL; + + rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, MT7996_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) return PTR_ERR(rskb); - skb = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!skb) { + skb = ieee80211_beacon_get_template(hw, vif, &offs, link_conf->link_id); + if (link_conf->enable_beacon && !skb) { dev_kfree_skb(rskb); return -EINVAL; } - 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; - } + if (skb) { + 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; + } - info = IEEE80211_SKB_CB(skb); - info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); + extra_len = skb->len; + } - len = sizeof(*bcn) + MT_TXD_SIZE + skb->len; + len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4); 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) + bcn->enable = link_conf->enable_beacon; + if (!bcn->enable) goto out; - mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); - mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs); - mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs); + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mlink->band_idx); + + mt7996_mcu_beacon_cont(dev, link_conf, rskb, skb, bcn, &offs); + if (link_conf->bssid_indicator) + mt7996_mcu_beacon_mbss(rskb, skb, bcn, &offs); + mt7996_mcu_beacon_cntdwn(rskb, skb, &offs, link_conf->csa_active); out: dev_kfree_skb(skb); - return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, + return mt76_mcu_skb_send_msg(&dev->mt76, rskb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, - struct ieee80211_vif *vif, u32 changed) + struct ieee80211_bss_conf *link_conf, + struct mt7996_vif_link *link, u32 changed) { #define OFFLOAD_TX_MODE_SU BIT(0) #define OFFLOAD_TX_MODE_MU BIT(1) + struct ieee80211_vif *vif = link_conf->vif; struct ieee80211_hw *hw = mt76_hw(dev); - struct mt7996_phy *phy = mt7996_hw_phy(hw); - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; - enum nl80211_band band = chandef->chan->band; + struct mt7996_phy *phy = link->phy; struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct bss_inband_discovery_tlv *discov; struct ieee80211_tx_info *info; struct sk_buff *rskb, *skb = NULL; + struct cfg80211_chan_def *chandef; + enum nl80211_band band; struct tlv *tlv; u8 *buf, interval; int len; - if (vif->bss_conf.nontransmitted) + if (!phy) + return -EINVAL; + + chandef = &phy->mt76->chandef; + band = chandef->chan->band; + + if (link_conf->nontransmitted) return 0; - rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, MT7996_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) return PTR_ERR(rskb); if (changed & BSS_CHANGED_FILS_DISCOVERY && - vif->bss_conf.fils_discovery.max_interval) { - interval = vif->bss_conf.fils_discovery.max_interval; + link_conf->fils_discovery.max_interval) { + interval = link_conf->fils_discovery.max_interval; skb = ieee80211_get_fils_discovery_tmpl(hw, vif); } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && - vif->bss_conf.unsol_bcast_probe_resp_interval) { - interval = vif->bss_conf.unsol_bcast_probe_resp_interval; + link_conf->unsol_bcast_probe_resp_interval) { + interval = link_conf->unsol_bcast_probe_resp_interval; skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); } @@ -2579,8 +2789,7 @@ 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); - len = sizeof(*discov) + MT_TXD_SIZE + skb->len; - + len = ALIGN(sizeof(*discov) + MT_TXD_SIZE + skb->len, 4); tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len); discov = (struct bss_inband_discovery_tlv *)tlv; @@ -2821,6 +3030,9 @@ static int mt7996_load_ram(struct mt7996_dev *dev) if (ret) return ret; + if (!mt7996_has_wa(dev)) + return 0; + ret = __mt7996_load_ram(dev, "DSP", fw_name(dev, FIRMWARE_DSP), MT7996_RAM_TYPE_DSP); if (ret) @@ -2831,10 +3043,9 @@ static int mt7996_load_ram(struct mt7996_dev *dev) } static int -mt7996_firmware_state(struct mt7996_dev *dev, bool wa) +mt7996_firmware_state(struct mt7996_dev *dev, u8 fw_state) { - u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, - wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD); + u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, fw_state); if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, state, 1000)) { @@ -2866,13 +3077,14 @@ mt7996_mcu_restart(struct mt76_dev *dev) static int mt7996_load_firmware(struct mt7996_dev *dev) { + u8 fw_state; int ret; /* make sure fw is download state */ - if (mt7996_firmware_state(dev, false)) { + if (mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD)) { /* restart firmware once */ mt7996_mcu_restart(&dev->mt76); - ret = mt7996_firmware_state(dev, false); + ret = mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD); if (ret) { dev_err(dev->mt76.dev, "Firmware is not ready for download\n"); @@ -2888,7 +3100,8 @@ static int mt7996_load_firmware(struct mt7996_dev *dev) if (ret) return ret; - ret = mt7996_firmware_state(dev, true); + fw_state = mt7996_has_wa(dev) ? FW_STATE_RDY : FW_STATE_NORMAL_TRX; + ret = mt7996_firmware_state(dev, fw_state); if (ret) return ret; @@ -3026,13 +3239,15 @@ int mt7996_mcu_init_firmware(struct mt7996_dev *dev) if (ret) return ret; - ret = mt7996_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, 0); - if (ret) - return ret; + if (mt7996_has_wa(dev)) { + ret = mt7996_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, 0); + if (ret) + return ret; - ret = mt7996_mcu_set_mwds(dev, 1); - if (ret) - return ret; + ret = mt7996_mcu_set_mwds(dev, 1); + if (ret) + return ret; + } ret = mt7996_mcu_init_rx_airtime(dev); if (ret) @@ -3058,7 +3273,7 @@ int mt7996_mcu_init(struct mt7996_dev *dev) void mt7996_mcu_exit(struct mt7996_dev *dev) { mt7996_mcu_restart(&dev->mt76); - if (mt7996_firmware_state(dev, false)) { + if (mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD)) { dev_err(dev->mt76.dev, "Failed to exit mcu\n"); goto out; } @@ -3107,7 +3322,8 @@ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans) MCU_WM_UNI_CMD(RX_HDR_TRANS), true); } -int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif) +int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) { #define MCU_EDCA_AC_PARAM 0 #define WMM_AIFS_SET BIT(0) @@ -3116,12 +3332,12 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif) #define WMM_TXOP_SET BIT(3) #define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \ WMM_CW_MAX_SET | WMM_TXOP_SET) - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf); struct { u8 bss_idx; u8 __rsv[3]; } __packed hdr = { - .bss_idx = mvif->mt76.idx, + .bss_idx = link->mt76.idx, }; struct sk_buff *skb; int len = sizeof(hdr) + IEEE80211_NUM_ACS * sizeof(struct edca); @@ -3134,7 +3350,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif) skb_put_data(skb, &hdr, sizeof(hdr)); for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac]; + struct ieee80211_tx_queue_params *q = &link->queue_params[ac]; struct edca *e; struct tlv *tlv; @@ -3344,11 +3560,10 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef) { struct mt7996_dev *dev = phy->dev; - int err, region; + int err, region, rdd_idx = mt7996_get_rdd_idx(phy, true); if (!chandef) { /* disable offchain */ - err = mt7996_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, - 0, 0); + err = mt7996_mcu_rdd_cmd(dev, RDD_STOP, rdd_idx, 0); if (err) return err; @@ -3374,8 +3589,7 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy, break; } - return mt7996_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, - 0, region); + return mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region); } int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) @@ -3425,7 +3639,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL || + else if (phy->mt76->offchannel || phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, @@ -3508,7 +3722,7 @@ int mt7996_mcu_set_eeprom(struct mt7996_dev *dev) &req, sizeof(req), true); } -int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset) +int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len) { struct { u8 _rsv[4]; @@ -3537,15 +3751,21 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset) valid = le32_to_cpu(*(__le32 *)(skb->data + 16)); if (valid) { u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12)); - u8 *buf = (u8 *)dev->mt76.eeprom.data + addr; - skb_pull(skb, 64); - memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE); + if (!buf) + buf = (u8 *)dev->mt76.eeprom.data + addr; + if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE) + buf_len = MT7996_EEPROM_BLOCK_SIZE; + + skb_pull(skb, 48); + memcpy(buf, skb->data, buf_len); + } else { + ret = -EINVAL; } dev_kfree_skb(skb); - return 0; + return ret; } int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num) @@ -3626,6 +3846,13 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) { + enum { + IDX_TX_TIME, + IDX_RX_TIME, + IDX_OBSS_AIRTIME, + IDX_NON_WIFI_TIME, + IDX_NUM + }; struct { struct { u8 band; @@ -3635,16 +3862,15 @@ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) __le16 tag; __le16 len; __le32 offs; - } data[4]; + } data[IDX_NUM]; } __packed req = { .hdr.band = phy->mt76->band_idx, }; - /* strict order */ static const u32 offs[] = { - UNI_MIB_TX_TIME, - UNI_MIB_RX_TIME, - UNI_MIB_OBSS_AIRTIME, - UNI_MIB_NON_WIFI_TIME, + [IDX_TX_TIME] = UNI_MIB_TX_TIME, + [IDX_RX_TIME] = UNI_MIB_RX_TIME, + [IDX_OBSS_AIRTIME] = UNI_MIB_OBSS_AIRTIME, + [IDX_NON_WIFI_TIME] = UNI_MIB_NON_WIFI_TIME, }; struct mt76_channel_state *state = phy->mt76->chan_state; struct mt76_channel_state *state_ts = &phy->state_ts; @@ -3653,7 +3879,7 @@ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) struct sk_buff *skb; int i, ret; - for (i = 0; i < 4; i++) { + for (i = 0; i < IDX_NUM; i++) { req.data[i].tag = cpu_to_le16(UNI_CMD_MIB_DATA); req.data[i].len = cpu_to_le16(sizeof(req.data[i])); req.data[i].offs = cpu_to_le32(offs[i]); @@ -3672,17 +3898,24 @@ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) goto out; #define __res_u64(s) le64_to_cpu(res[s].data) - state->cc_tx += __res_u64(1) - state_ts->cc_tx; - state->cc_bss_rx += __res_u64(2) - state_ts->cc_bss_rx; - state->cc_rx += __res_u64(2) + __res_u64(3) - state_ts->cc_rx; - state->cc_busy += __res_u64(0) + __res_u64(1) + __res_u64(2) + __res_u64(3) - + state->cc_tx += __res_u64(IDX_TX_TIME) - state_ts->cc_tx; + state->cc_bss_rx += __res_u64(IDX_RX_TIME) - state_ts->cc_bss_rx; + state->cc_rx += __res_u64(IDX_RX_TIME) + + __res_u64(IDX_OBSS_AIRTIME) - + state_ts->cc_rx; + state->cc_busy += __res_u64(IDX_TX_TIME) + + __res_u64(IDX_RX_TIME) + + __res_u64(IDX_OBSS_AIRTIME) + + __res_u64(IDX_NON_WIFI_TIME) - state_ts->cc_busy; - out: - state_ts->cc_tx = __res_u64(1); - state_ts->cc_bss_rx = __res_u64(2); - state_ts->cc_rx = __res_u64(2) + __res_u64(3); - state_ts->cc_busy = __res_u64(0) + __res_u64(1) + __res_u64(2) + __res_u64(3); + state_ts->cc_tx = __res_u64(IDX_TX_TIME); + state_ts->cc_bss_rx = __res_u64(IDX_RX_TIME); + state_ts->cc_rx = __res_u64(IDX_RX_TIME) + __res_u64(IDX_OBSS_AIRTIME); + state_ts->cc_busy = __res_u64(IDX_TX_TIME) + + __res_u64(IDX_RX_TIME) + + __res_u64(IDX_OBSS_AIRTIME) + + __res_u64(IDX_NON_WIFI_TIME); #undef __res_u64 dev_kfree_skb(skb); @@ -3721,6 +3954,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy) } __packed * res; struct sk_buff *skb; int ret; + u32 temp; ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL), &req, sizeof(req), true, &skb); @@ -3728,8 +3962,10 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy) return ret; res = (void *)skb->data; + temp = le32_to_cpu(res->temperature); + dev_kfree_skb(skb); - return le32_to_cpu(res->temperature); + return temp; } int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state) @@ -3885,8 +4121,9 @@ 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 = 3; - req_mod_en->bf_bitmap = GENMASK(2, 0); + req_mod_en->bf_num = mt7996_band_valid(dev, MT_BAND2) ? 3 : 2; + req_mod_en->bf_bitmap = mt7996_band_valid(dev, MT_BAND2) ? + GENMASK(2, 0) : GENMASK(1, 0); break; } default: @@ -3974,12 +4211,12 @@ mt7996_mcu_set_obss_spr_pd(struct mt7996_phy *phy, } static int -mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy, struct ieee80211_vif *vif, +mt7996_mcu_set_obss_spr_siga(struct mt7996_phy *phy, + struct mt7996_vif_link *link, struct ieee80211_he_obss_pd *he_obss_pd) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_dev *dev = phy->dev; - u8 omac = mvif->mt76.omac_idx; + u8 omac = link->mt76.omac_idx; struct { u8 band_idx; u8 __rsv[3]; @@ -4051,7 +4288,8 @@ mt7996_mcu_set_obss_spr_bitmap(struct mt7996_phy *phy, sizeof(req), true); } -int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif, +int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, + struct mt7996_vif_link *link, struct ieee80211_he_obss_pd *he_obss_pd) { int ret; @@ -4085,7 +4323,7 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif, return ret; /* Set SR prohibit */ - ret = mt7996_mcu_set_obss_spr_siga(phy, vif, he_obss_pd); + ret = mt7996_mcu_set_obss_spr_siga(phy, link, he_obss_pd); if (ret) return ret; @@ -4093,16 +4331,16 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif, return mt7996_mcu_set_obss_spr_bitmap(phy, he_obss_pd); } -int mt7996_mcu_update_bss_color(struct mt7996_dev *dev, struct ieee80211_vif *vif, +int mt7996_mcu_update_bss_color(struct mt7996_dev *dev, + struct mt76_vif_link *mlink, struct cfg80211_he_bss_color *he_bss_color) { int len = sizeof(struct bss_req_hdr) + sizeof(struct bss_color_tlv); - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct bss_color_tlv *bss_color; struct sk_buff *skb; struct tlv *tlv; - skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len); + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, len); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -4121,7 +4359,7 @@ int mt7996_mcu_update_bss_color(struct mt7996_dev *dev, struct ieee80211_vif *vi #define TWT_AGRT_PROTECT BIT(2) int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, - struct mt7996_vif *mvif, + struct mt7996_vif_link *link, struct mt7996_twt_flow *flow, int cmd) { @@ -4152,12 +4390,12 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, .len = cpu_to_le16(sizeof(req) - 4), .tbl_idx = flow->table_id, .cmd = cmd, - .own_mac_idx = mvif->mt76.omac_idx, + .own_mac_idx = link->mt76.omac_idx, .flowid = flow->id, .peer_id = cpu_to_le16(flow->wcid), .duration = flow->duration, - .bss = mvif->mt76.idx, - .bss_idx = mvif->mt76.idx, + .bss = link->mt76.idx, + .bss_idx = link->mt76.idx, .start_tsf = cpu_to_le64(flow->tsf), .mantissa = flow->mantissa, .exponent = flow->exp, @@ -4218,8 +4456,7 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable) &req, sizeof(req), true); } -int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, - u8 rx_sel, u8 val) +int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val) { struct { u8 _rsv[4]; @@ -4236,8 +4473,7 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, .tag = cpu_to_le16(UNI_RDD_CTRL_PARM), .len = cpu_to_le16(sizeof(req) - 4), .ctrl = cmd, - .rdd_idx = index, - .rdd_rx_sel = rx_sel, + .rdd_idx = rdd_idx, .val = val, }; @@ -4247,22 +4483,19 @@ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - struct mt7996_sta *msta; struct sk_buff *skb; - msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta; - - skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid, + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, + &msta_link->wcid, MT7996_STA_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* starec hdr trans */ - mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta); + mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, &msta_link->wcid); return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); } @@ -4440,12 +4673,32 @@ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id) sizeof(req), true); } +int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled) +{ + struct mt7996_dev *dev = phy->dev; + struct { + u8 band_idx; + u8 _rsv[3]; + __le16 tag; + __le16 len; + u8 enable; + u8 _pad[3]; + } __packed req = { + .band_idx = phy->mt76->band_idx, + .tag = 0, + .len = cpu_to_le16(sizeof(req) - 4), + .enable = enabled, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(SNIFFER), &req, + sizeof(req), true); +} + int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) { #define TX_POWER_LIMIT_TABLE_RATE 0 struct mt7996_dev *dev = phy->dev; struct mt76_phy *mphy = phy->mt76; - struct ieee80211_hw *hw = mphy->hw; struct tx_power_limit_table_ctrl { u8 __rsv1[4]; @@ -4456,7 +4709,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) u8 band_idx; } __packed req = { .tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL), - .len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4), + .len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4), .power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL, .power_limit_type = TX_POWER_LIMIT_TABLE_RATE, .band_idx = phy->mt76->band_idx, @@ -4465,13 +4718,13 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) struct sk_buff *skb; int i, tx_power; - tx_power = mt7996_get_power_bound(phy, hw->conf.power_level); + tx_power = mt76_get_power_bound(mphy, phy->txpower); tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, &la, tx_power); mphy->txpower_cur = tx_power; skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - sizeof(req) + MT7996_SKU_RATE_NUM); + sizeof(req) + MT7996_SKU_PATH_NUM); if (!skb) return -ENOMEM; @@ -4495,6 +4748,41 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) /* eht */ skb_put_data(skb, &la.eht[0], sizeof(la.eht)); + /* padding */ + skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WM_UNI_CMD(TXPOWER), true); } + +int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode) +{ + __le32 cp_mode; + + if (mode < mt76_connac_lmac_mapping(IEEE80211_AC_BE) || + mode > mt76_connac_lmac_mapping(IEEE80211_AC_VO)) + return -EINVAL; + + if (!mt7996_has_wa(dev)) { + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + u8 cp_mode; + u8 rsv[3]; + } __packed req = { + .tag = cpu_to_le16(UNI_CMD_SDO_CP_MODE), + .len = cpu_to_le16(sizeof(req) - 4), + .cp_mode = mode, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_WA_UNI_CMD(SDO), + &req, sizeof(req), false); + } + + cp_mode = cpu_to_le32(mode); + + return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(CP_SUPPORT), + &cp_mode, sizeof(cp_mode), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index 36cacc495c75..130ea95626d5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -69,7 +69,7 @@ struct mt7996_mcu_rdd_report { __le16 tag; __le16 len; - u8 band_idx; + u8 rdd_idx; u8 long_detected; u8 constant_prf_detected; u8 staggered_prf_detected; @@ -625,6 +625,35 @@ struct sta_rec_hdr_trans { u8 mesh; } __packed; +struct sta_rec_mld_setup { + __le16 tag; + __le16 len; + u8 mld_addr[ETH_ALEN]; + __le16 primary_id; + __le16 seconed_id; + __le16 setup_wcid; + u8 link_num; + u8 info; + u8 __rsv[2]; + u8 link_info[]; +} __packed; + +struct sta_rec_eht_mld { + __le16 tag; + __le16 len; + u8 nsep; + u8 __rsv1[2]; + u8 str_cap[__MT_MAX_BAND]; + __le16 eml_cap; + u8 __rsv2[4]; +} __packed; + +struct mld_setup_link { + __le16 wcid; + u8 bss_idx; + u8 __rsv; +} __packed; + struct hdr_trans_en { __le16 tag; __le16 len; @@ -798,29 +827,20 @@ enum { sizeof(struct sta_rec_eht) + \ sizeof(struct sta_rec_hdrt) + \ sizeof(struct sta_rec_hdr_trans) + \ + sizeof(struct sta_rec_mld_setup) + \ + sizeof(struct mld_setup_link) * 3 + \ + sizeof(struct sta_rec_eht_mld) + \ 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 + \ + 4 + MT_TXD_SIZE + \ sizeof(struct bss_bcn_cntdwn_tlv) + \ sizeof(struct bss_bcn_mbss_tlv)) -#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \ +#define MT7996_MAX_BSS_OFFLOAD_SIZE 2048 +#define MT7996_MAX_BEACON_SIZE (MT7996_MAX_BSS_OFFLOAD_SIZE - \ MT7996_BEACON_UPDATE_SIZE) -static inline s8 -mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower) -{ - struct mt76_phy *mphy = phy->mt76; - int n_chains = hweight16(mphy->chainmask); - - txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2); - txpower -= mt76_tx_power_nss_delta(n_chains); - - return txpower; -} - enum { UNI_BAND_CONFIG_RADIO_ENABLE, UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08, @@ -908,7 +928,8 @@ enum { UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE, UNI_CMD_SER_SET_RECOVER_L3_BF, UNI_CMD_SER_SET_RECOVER_L4_MDP, - UNI_CMD_SER_SET_RECOVER_FULL, + UNI_CMD_SER_SET_RECOVER_FROM_ETH, + UNI_CMD_SER_SET_RECOVER_FULL = 8, UNI_CMD_SER_SET_SYSTEM_ASSERT, /* action */ UNI_CMD_SER_ENABLE = 1, @@ -917,6 +938,12 @@ enum { }; enum { + UNI_CMD_SDO_SET = 1, + UNI_CMD_SDO_QUERY, + UNI_CMD_SDO_CP_MODE = 6, +}; + +enum { MT7996_SEC_MODE_PLAIN, MT7996_SEC_MODE_AES, MT7996_SEC_MODE_SCRAMBLE, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 9f2abfa273c9..30b40f4a91be 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -54,6 +54,17 @@ static const u32 mt7996_offs[] = { [MIB_BSCR7] = 0x9e8, [MIB_BSCR17] = 0xa10, [MIB_TRDR1] = 0xa28, + [HIF_REMAP_L1] = 0x24, + [HIF_REMAP_BASE_L1] = 0x130000, + [HIF_REMAP_L2] = 0x1b4, + [HIF_REMAP_BASE_L2] = 0x1000, + [CBTOP1_PHY_END] = 0x77ffffff, + [INFRA_MCU_END] = 0x7c3fffff, + [WTBLON_WDUCR] = 0x370, + [WTBL_UPDATE] = 0x380, + [WTBL_ITCR] = 0x3b0, + [WTBL_ITCR0] = 0x3b8, + [WTBL_ITCR1] = 0x3bc, }; static const u32 mt7992_offs[] = { @@ -80,6 +91,54 @@ static const u32 mt7992_offs[] = { [MIB_BSCR7] = 0xae4, [MIB_BSCR17] = 0xb0c, [MIB_TRDR1] = 0xb24, + [HIF_REMAP_L1] = 0x8, + [HIF_REMAP_BASE_L1] = 0x40000, + [HIF_REMAP_L2] = 0x1b4, + [HIF_REMAP_BASE_L2] = 0x1000, + [CBTOP1_PHY_END] = 0x77ffffff, + [INFRA_MCU_END] = 0x7c3fffff, + [WTBLON_WDUCR] = 0x370, + [WTBL_UPDATE] = 0x380, + [WTBL_ITCR] = 0x3b0, + [WTBL_ITCR0] = 0x3b8, + [WTBL_ITCR1] = 0x3bc, +}; + +static const u32 mt7990_offs[] = { + [MIB_RVSR0] = 0x800, + [MIB_RVSR1] = 0x804, + [MIB_BTSCR5] = 0x868, + [MIB_BTSCR6] = 0x878, + [MIB_RSCR1] = 0x890, + [MIB_RSCR27] = 0xa38, + [MIB_RSCR28] = 0xa3c, + [MIB_RSCR29] = 0xa40, + [MIB_RSCR30] = 0xa44, + [MIB_RSCR31] = 0xa48, + [MIB_RSCR33] = 0xa50, + [MIB_RSCR35] = 0xa58, + [MIB_RSCR36] = 0xa5c, + [MIB_BSCR0] = 0xbb8, + [MIB_BSCR1] = 0xbbc, + [MIB_BSCR2] = 0xbc0, + [MIB_BSCR3] = 0xbc4, + [MIB_BSCR4] = 0xbc8, + [MIB_BSCR5] = 0xbcc, + [MIB_BSCR6] = 0xbd0, + [MIB_BSCR7] = 0xbd4, + [MIB_BSCR17] = 0xbfc, + [MIB_TRDR1] = 0xc14, + [HIF_REMAP_L1] = 0x8, + [HIF_REMAP_BASE_L1] = 0x40000, + [HIF_REMAP_L2] = 0x1b8, + [HIF_REMAP_BASE_L2] = 0x110000, + [CBTOP1_PHY_END] = 0x7fffffff, + [INFRA_MCU_END] = 0x7cffffff, + [WTBLON_WDUCR] = 0x400, + [WTBL_UPDATE] = 0x410, + [WTBL_ITCR] = 0x440, + [WTBL_ITCR0] = 0x448, + [WTBL_ITCR1] = 0x44c, }; static const struct __map mt7996_reg_map[] = { @@ -135,15 +194,83 @@ static const struct __map mt7996_reg_map[] = { { 0x0, 0x0, 0x0 }, /* imply end of search */ }; +static const struct __map mt7990_reg_map[] = { + {0x54000000, 0x02000, 0x1000}, /* WFDMA_0 (PCIE0 MCU DMA0) */ + {0x55000000, 0x03000, 0x1000}, /* WFDMA_1 (PCIE0 MCU DMA1) */ + {0x56000000, 0x04000, 0x1000}, /* WFDMA_2 (Reserved) */ + {0x57000000, 0x05000, 0x1000}, /* WFDMA_3 (MCU wrap CR) */ + {0x58000000, 0x06000, 0x1000}, /* WFDMA_4 (PCIE1 MCU DMA0 (MEM_DMA)) */ + {0x59000000, 0x07000, 0x1000}, /* WFDMA_5 (PCIE1 MCU DMA1) */ + {0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */ + {0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */ + {0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */ + {0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */ + {0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */ + {0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + {0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */ + {0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */ + {0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */ + {0x820cc000, 0xa5000, 0x2000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + {0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP (WF_UWTBL) */ + {0x81030000, 0xae000, 0x100}, /* WFSYS_AON part 1 */ + {0x81031000, 0xae100, 0x100}, /* WFSYS_AON part 2 */ + {0x81032000, 0xae200, 0x100}, /* WFSYS_AON part 3 */ + {0x81033000, 0xae300, 0x100}, /* WFSYS_AON part 4 */ + {0x81034000, 0xae400, 0x100}, /* WFSYS_AON part 5 */ + {0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */ + {0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */ + {0x81040000, 0x120000, 0x1000}, /* WF_MCU_CFG_ON */ + {0x81050000, 0x121000, 0x1000}, /* WF_MCU_EINT */ + {0x81060000, 0x122000, 0x1000}, /* WF_MCU_GPT */ + {0x81070000, 0x123000, 0x1000}, /* WF_MCU_WDT */ + {0x80010000, 0x124000, 0x1000}, /* WF_AXIDMA */ + {0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma for from CODA flow use */ + {0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top for from CODA flow use */ + {0x20020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */ + {0x20060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */ + {0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */ + {0x70020000, 0x1f0000, 0x9000}, /* PCIE remapping (AP2CONN) */ + {0x0, 0x0, 0x0}, /* imply end of search */ +}; + static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr) { u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); + u32 l1_mask, val; - dev->reg_l1_backup = 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)); + if (is_mt7996(&dev->mt76)) { + l1_mask = MT_HIF_REMAP_L1_MASK_7996; + val = FIELD_PREP(MT_HIF_REMAP_L1_MASK_7996, base); + } else { + l1_mask = MT_HIF_REMAP_L1_MASK; + val = FIELD_PREP(MT_HIF_REMAP_L1_MASK, base); + } + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1, l1_mask, val); /* use read to push write */ dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1); @@ -152,39 +279,45 @@ static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr) static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr) { - u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); - u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + u32 offset, base, l2_mask, val; - dev->reg_l2_backup = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2); - dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2, - MT_HIF_REMAP_L2_MASK, - FIELD_PREP(MT_HIF_REMAP_L2_MASK, base)); + if (is_mt7990(&dev->mt76)) { + offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_7990, addr); + base = FIELD_GET(MT_HIF_REMAP_L2_BASE_7990, addr); + l2_mask = MT_HIF_REMAP_L2_MASK_7990; + val = FIELD_PREP(MT_HIF_REMAP_L2_MASK_7990, base); + } else { + offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); + base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + l2_mask = MT_HIF_REMAP_L2_MASK; + val = FIELD_PREP(MT_HIF_REMAP_L2_MASK, base); + } + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2, l2_mask, val); /* use read to push write */ dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2); return MT_HIF_REMAP_BASE_L2 + offset; } -static void mt7996_reg_remap_restore(struct mt7996_dev *dev) +static u32 mt7996_reg_map_cbtop(struct mt7996_dev *dev, u32 addr) { - /* remap to ori status */ - if (unlikely(dev->reg_l1_backup)) { - dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->reg_l1_backup); - dev->reg_l1_backup = 0; - } + u32 offset = FIELD_GET(MT_HIF_REMAP_CBTOP_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_CBTOP_BASE, addr); - if (dev->reg_l2_backup) { - dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->reg_l2_backup); - dev->reg_l2_backup = 0; - } + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_CBTOP, + MT_HIF_REMAP_CBTOP_MASK, + FIELD_PREP(MT_HIF_REMAP_CBTOP_MASK, base)); + /* use read to push write */ + dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_CBTOP); + + return MT_HIF_REMAP_BASE_CBTOP + offset; } static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr) { int i; - mt7996_reg_remap_restore(dev); - if (addr < 0x100000) return addr; @@ -195,28 +328,36 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr) continue; ofs = addr - dev->reg.map[i].phys; - if (ofs > dev->reg.map[i].size) + if (ofs >= dev->reg.map[i].size) continue; return dev->reg.map[i].mapped + ofs; } + return 0; +} + +static u32 __mt7996_reg_remap_addr(struct mt7996_dev *dev, u32 addr) +{ if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) || (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) || (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END)) return mt7996_reg_map_l1(dev, addr); - if (dev_is_pci(dev->mt76.dev) && - ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || - addr >= MT_CBTOP2_PHY_START)) - return mt7996_reg_map_l1(dev, addr); - /* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */ if (addr >= MT_INFRA_MCU_START && addr <= MT_INFRA_MCU_END) { addr = addr - MT_INFRA_MCU_START + MT_INFRA_BASE; return mt7996_reg_map_l1(dev, addr); } + if (dev_is_pci(dev->mt76.dev) && + ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || + addr >= MT_CBTOP2_PHY_START)) { + if (is_mt7990(&dev->mt76)) + return mt7996_reg_map_cbtop(dev, addr); + return mt7996_reg_map_l1(dev, addr); + } + return mt7996_reg_map_l2(dev, addr); } @@ -225,28 +366,60 @@ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset, { u32 addr = __mt7996_reg_addr(dev, offset); - memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len); + if (addr) { + memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len); + return; + } + + spin_lock_bh(&dev->reg_lock); + memcpy_fromio(buf, dev->mt76.mmio.regs + + __mt7996_reg_remap_addr(dev, offset), len); + spin_unlock_bh(&dev->reg_lock); } static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset) { struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + u32 addr = __mt7996_reg_addr(dev, offset), val; + + if (addr) + return dev->bus_ops->rr(mdev, addr); + + spin_lock_bh(&dev->reg_lock); + val = dev->bus_ops->rr(mdev, __mt7996_reg_remap_addr(dev, offset)); + spin_unlock_bh(&dev->reg_lock); - return dev->bus_ops->rr(mdev, __mt7996_reg_addr(dev, offset)); + return val; } static void mt7996_wr(struct mt76_dev *mdev, u32 offset, u32 val) { struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + u32 addr = __mt7996_reg_addr(dev, offset); + + if (addr) { + dev->bus_ops->wr(mdev, addr, val); + return; + } - dev->bus_ops->wr(mdev, __mt7996_reg_addr(dev, offset), val); + spin_lock_bh(&dev->reg_lock); + dev->bus_ops->wr(mdev, __mt7996_reg_remap_addr(dev, offset), val); + spin_unlock_bh(&dev->reg_lock); } static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) { struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); + u32 addr = __mt7996_reg_addr(dev, offset); + + if (addr) + return dev->bus_ops->rmw(mdev, addr, mask, val); - return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val); + spin_lock_bh(&dev->reg_lock); + val = dev->bus_ops->rmw(mdev, __mt7996_reg_remap_addr(dev, offset), mask, val); + spin_unlock_bh(&dev->reg_lock); + + return val; } #ifdef CONFIG_NET_MEDIATEK_SOC_WED @@ -262,7 +435,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed) if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state)) return -EBUSY; - ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1, + ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH, mphy->band_idx); if (ret) goto out; @@ -304,6 +477,9 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.base = devm_ioremap(dev->mt76.dev, pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); + if (!wed->wlan.base) + return -ENOMEM; + wed->wlan.phy_base = pci_resource_start(pci_dev, 0); if (hif2) { @@ -331,7 +507,7 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) + MT7996_RXQ_BAND0 * MT_RING_SIZE; - wed->wlan.id = 0x7991; + wed->wlan.id = MT7996_DEVICE_ID_2; wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1; } else { wed->wlan.hw_rro = dev->has_rro; /* default on */ @@ -391,13 +567,13 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.amsdu_max_len = 1536; wed->wlan.init_buf = mt7996_wed_init_buf; - wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf; - wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf; - wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; - wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; + wed->wlan.init_rx_buf = mt76_wed_init_rx_buf; + wed->wlan.release_rx_buf = mt76_wed_release_rx_buf; + wed->wlan.offload_enable = mt76_wed_offload_enable; + wed->wlan.offload_disable = mt76_wed_offload_disable; if (!hif2) { wed->wlan.reset = mt7996_mmio_wed_reset; - wed->wlan.reset_complete = mt76_mmio_wed_reset_complete; + wed->wlan.reset_complete = mt76_wed_reset_complete; } if (mtk_wed_device_attach(wed)) @@ -421,20 +597,27 @@ static int mt7996_mmio_init(struct mt76_dev *mdev, dev = container_of(mdev, struct mt7996_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); + spin_lock_init(&dev->reg_lock); switch (device_id) { - case 0x7990: + case MT7996_DEVICE_ID: dev->reg.base = mt7996_reg_base; dev->reg.offs_rev = mt7996_offs; dev->reg.map = mt7996_reg_map; dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map); break; - case 0x7992: + case MT7992_DEVICE_ID: dev->reg.base = mt7996_reg_base; dev->reg.offs_rev = mt7992_offs; dev->reg.map = mt7996_reg_map; dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map); break; + case MT7990_DEVICE_ID: + dev->reg.base = mt7996_reg_base; + dev->reg.offs_rev = mt7990_offs; + dev->reg.map = mt7990_reg_map; + dev->reg.map_size = ARRAY_SIZE(mt7990_reg_map); + break; default: return -EINVAL; } @@ -499,7 +682,7 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); struct mtk_wed_device *wed = &dev->mt76.mmio.wed; struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2; - u32 i, intr, mask, intr1; + u32 i, intr, mask, intr1 = 0; if (dev->hif2 && mtk_wed_device_active(wed_hif2)) { mtk_wed_device_irq_set_mask(wed_hif2, 0); @@ -585,6 +768,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp), + .link_data_size = sizeof(struct mt7996_vif_link), .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_AMSDU_OFFLOAD | MT_DRV_HW_MGMT_TXQ, @@ -597,9 +781,10 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, .rx_skb = mt7996_queue_rx_skb, .rx_check = mt7996_rx_check, .rx_poll_complete = mt7996_rx_poll_complete, - .sta_add = mt7996_mac_sta_add, - .sta_remove = mt7996_mac_sta_remove, .update_survey = mt7996_update_channel, + .set_channel = mt7996_set_channel, + .vif_link_add = mt7996_vif_link_add, + .vif_link_remove = mt7996_vif_link_remove, }; struct mt7996_dev *dev; struct mt76_dev *mdev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index bc73bcb47bf0..1ad6bc046f7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -11,9 +11,10 @@ #include "../mt76_connac.h" #include "regs.h" +#define MT7996_MAX_RADIOS 3 #define MT7996_MAX_INTERFACES 19 /* per-band */ #define MT7996_MAX_WMM_SETS 4 -#define MT7996_WTBL_BMC_SIZE (is_mt7992(&dev->mt76) ? 32 : 64) +#define MT7996_WTBL_BMC_SIZE (is_mt7996(&dev->mt76) ? 64 : 32) #define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1) #define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \ mt7996_max_interface_num(dev)) @@ -28,19 +29,56 @@ #define MT7996_RX_RING_SIZE 1536 #define MT7996_RX_MCU_RING_SIZE 512 #define MT7996_RX_MCU_RING_SIZE_WA 1024 +/* scatter-gather of mcu event is not supported in connac3 */ +#define MT7996_RX_MCU_BUF_SIZE (2048 + \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + +#define MT7996_DEVICE_ID 0x7990 +#define MT7996_DEVICE_ID_2 0x7991 +#define MT7992_DEVICE_ID 0x7992 +#define MT7992_DEVICE_ID_2 0x799a +#define MT7990_DEVICE_ID 0x7993 +#define MT7990_DEVICE_ID_2 0x799b #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin" #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin" #define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin" #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin" +#define MT7996_FIRMWARE_WA_233 "mediatek/mt7996/mt7996_wa_233.bin" +#define MT7996_FIRMWARE_WM_233 "mediatek/mt7996/mt7996_wm_233.bin" +#define MT7996_FIRMWARE_DSP_233 MT7996_FIRMWARE_DSP +#define MT7996_ROM_PATCH_233 "mediatek/mt7996/mt7996_rom_patch_233.bin" + #define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin" #define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin" #define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin" #define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin" +#define MT7992_FIRMWARE_WA_23 "mediatek/mt7996/mt7992_wa_23.bin" +#define MT7992_FIRMWARE_WM_23 "mediatek/mt7996/mt7992_wm_23.bin" +#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin" +#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin" + +#define MT7990_FIRMWARE_WA "" +#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin" +#define MT7990_FIRMWARE_DSP "" +#define MT7990_ROM_PATCH "mediatek/mt7996/mt7990_rom_patch.bin" + #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin" +#define MT7996_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7996_eeprom_2i5i6i.bin" +#define MT7996_EEPROM_DEFAULT_233 "mediatek/mt7996/mt7996_eeprom_233.bin" +#define MT7996_EEPROM_DEFAULT_233_INT "mediatek/mt7996/mt7996_eeprom_233_2i5i6i.bin" + #define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin" +#define MT7992_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7992_eeprom_2i5i.bin" +#define MT7992_EEPROM_DEFAULT_MIX "mediatek/mt7996/mt7992_eeprom_2i5e.bin" +#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin" +#define MT7992_EEPROM_DEFAULT_23_INT "mediatek/mt7996/mt7992_eeprom_23_2i5i.bin" + +#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin" +#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin" + #define MT7996_EEPROM_SIZE 7680 #define MT7996_EEPROM_BLOCK_SIZE 16 #define MT7996_TOKEN_SIZE 16384 @@ -48,11 +86,19 @@ #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ +#define MT7996_IBF_MAX_NC 2 +#define MT7996_IBF_TIMEOUT 0x18 +#define MT7996_IBF_TIMEOUT_LEGACY 0x48 + +#define MT7992_CFEND_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7992_IBF_TIMEOUT 0xff #define MT7996_SKU_RATE_NUM 417 +#define MT7996_SKU_PATH_NUM 494 #define MT7996_MAX_TWT_AGRT 16 #define MT7996_MAX_STA_TWT_AGRT 8 +#define MT7996_MIN_TWT_DUR 64 #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3) /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ @@ -93,6 +139,26 @@ enum mt7996_ram_type { MT7996_RAM_TYPE_DSP, }; +enum mt7996_var_type { + MT7996_VAR_TYPE_444, + MT7996_VAR_TYPE_233, +}; + +enum mt7992_var_type { + MT7992_VAR_TYPE_44, + MT7992_VAR_TYPE_23, +}; + +enum mt7990_var_type { + MT7990_VAR_TYPE_23, +}; + +enum mt7996_fem_type { + MT7996_FEM_EXT, + MT7996_FEM_INT, + MT7996_FEM_MIX, +}; + enum mt7996_txq_id { MT7996_TXQ_FWDL = 16, MT7996_TXQ_MCU_WM, @@ -121,6 +187,8 @@ enum mt7996_rxq_id { MT7996_RXQ_TXFREE1 = 9, MT7996_RXQ_TXFREE2 = 7, MT7996_RXQ_RRO_IND = 0, + MT7990_RXQ_TXFREE0 = 6, + MT7990_RXQ_TXFREE1 = 7, }; struct mt7996_twt_flow { @@ -141,10 +209,10 @@ struct mt7996_twt_flow { DECLARE_EWMA(avg_signal, 10, 8) -struct mt7996_sta { +struct mt7996_sta_link { struct mt76_wcid wcid; /* must be first */ - struct mt7996_vif *vif; + struct mt7996_sta *sta; struct list_head rc_list; u32 airtime_ac[8]; @@ -160,18 +228,33 @@ struct mt7996_sta { u8 flowid_mask; struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT]; } twt; + + struct rcu_head rcu_head; }; -struct mt7996_vif { - struct mt76_vif mt76; /* must be first */ +struct mt7996_sta { + struct mt7996_sta_link deflink; /* must be first */ + struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; + u8 deflink_id; + + struct mt7996_vif *vif; +}; + +struct mt7996_vif_link { + struct mt76_vif_link mt76; /* must be first */ - struct mt7996_sta sta; + struct mt7996_sta_link msta_link; struct mt7996_phy *phy; struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; struct cfg80211_bitrate_mask bitrate_mask; }; +struct mt7996_vif { + struct mt7996_vif_link deflink; /* must be first */ + struct mt76_vif_data mt76; +}; + /* crash-dump */ struct mt7996_crash_data { guid_t guid; @@ -209,8 +292,6 @@ struct mt7996_phy { struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; - struct ieee80211_vif *monitor_vif; - struct thermal_cooling_device *cdev; u8 cdev_state; u8 throttle_state; @@ -224,17 +305,20 @@ struct mt7996_phy { s16 coverage_class; u8 slottime; - u8 rdd_state; - u16 beacon_rate; u32 rx_ampdu_ts; u32 ampdu_ref; + int txpower; struct mt76_mib_stats mib; struct mt76_channel_state state_ts; + u16 orig_chainmask; + u16 orig_antenna_mask; + bool has_aux_rx; + bool counter_reset; }; struct mt7996_dev { @@ -243,6 +327,10 @@ struct mt7996_dev { struct mt76_phy mphy; }; + struct mt7996_phy *radio_phy[MT7996_MAX_RADIOS]; + struct wiphy_radio radios[MT7996_MAX_RADIOS]; + struct wiphy_radio_freq_range radio_freqs[MT7996_MAX_RADIOS]; + struct mt7996_hif *hif2; struct mt7996_reg_desc reg; u8 q_id[MT7996_MAX_QUEUE]; @@ -320,14 +408,17 @@ struct mt7996_dev { struct rchan *relay_fwlog; struct { - u8 table_mask; + u16 table_mask; u8 n_agrt; } twt; - u32 reg_l1_backup; - u32 reg_l2_backup; + spinlock_t reg_lock; u8 wtbl_size_group; + struct { + u8 type:4; + u8 fem:4; + } var; }; enum { @@ -337,10 +428,10 @@ enum { __MT_WFDMA_MAX, }; -enum { - MT_RX_SEL0, - MT_RX_SEL1, - MT_RX_SEL2, /* monitor chain */ +enum rdd_idx { + MT_RDD_IDX_BAND2, /* RDD idx for band idx 2 */ + MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */ + MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */ }; enum mt7996_rdd_cmd { @@ -359,12 +450,19 @@ enum mt7996_rdd_cmd { RDD_IRQ_OFF, }; -static inline struct mt7996_phy * -mt7996_hw_phy(struct ieee80211_hw *hw) +static inline int +mt7996_get_rdd_idx(struct mt7996_phy *phy, bool is_background) { - struct mt76_phy *phy = hw->priv; + if (!phy->mt76->cap.has_5ghz) + return -1; - return phy->priv; + if (is_background) + return MT_RDD_IDX_BACKGROUND; + + if (phy->mt76->band_idx == MT_BAND2) + return MT_RDD_IDX_BAND2; + + return MT_RDD_IDX_BAND1; } static inline struct mt7996_dev * @@ -401,17 +499,53 @@ mt7996_phy3(struct mt7996_dev *dev) static inline bool mt7996_band_valid(struct mt7996_dev *dev, u8 band) { - if (is_mt7992(&dev->mt76)) + if (!is_mt7996(&dev->mt76)) return band <= MT_BAND1; - /* tri-band support */ - if (band <= MT_BAND2 && - mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1) - return true; + return band <= MT_BAND2; +} + +static inline struct mt7996_phy * +mt7996_band_phy(struct mt7996_dev *dev, enum nl80211_band band) +{ + struct mt76_phy *mphy; - return band == MT_BAND0 || band == MT_BAND2; + mphy = dev->mt76.band_phys[band]; + if (!mphy) + return NULL; + + return mphy->priv; } +static inline struct mt7996_vif_link * +mt7996_vif_link(struct mt7996_dev *dev, struct ieee80211_vif *vif, int link_id) +{ + return (struct mt7996_vif_link *)mt76_vif_link(&dev->mt76, vif, link_id); +} + +static inline struct mt7996_phy * +mt7996_vif_link_phy(struct mt7996_vif_link *link) +{ + struct mt76_phy *mphy = mt76_vif_link_phy(&link->mt76); + + if (!mphy) + return NULL; + + return mphy->priv; +} + +static inline struct mt7996_vif_link * +mt7996_vif_conf_link(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + return (struct mt7996_vif_link *)mt76_vif_conf_link(&dev->mt76, vif, + link_conf); +} + +#define mt7996_for_each_phy(dev, phy) \ + for (int __i = 0; __i < ARRAY_SIZE((dev)->radio_phy); __i++) \ + if (((phy) = (dev)->radio_phy[__i]) != NULL) + extern const struct ieee80211_ops mt7996_ops; extern struct pci_driver mt7996_pci_driver; extern struct pci_driver mt7996_hif_driver; @@ -420,14 +554,21 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, void __iomem *mem_base, u32 device_id); void mt7996_wfsys_reset(struct mt7996_dev *dev); irqreturn_t mt7996_irq_handler(int irq, void *dev_instance); -u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif); +u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link); int mt7996_register_device(struct mt7996_dev *dev); void mt7996_unregister_device(struct mt7996_dev *dev); +int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink); +void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink); int mt7996_eeprom_init(struct mt7996_dev *dev); int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy); int mt7996_eeprom_get_target_power(struct mt7996_dev *dev, struct ieee80211_channel *chan); s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band); +bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev); int mt7996_dma_init(struct mt7996_dev *dev); void mt7996_dma_reset(struct mt7996_dev *dev, bool force); void mt7996_dma_prefetch(struct mt7996_dev *dev); @@ -438,44 +579,66 @@ int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, void mt7996_init_txpower(struct mt7996_phy *phy); int mt7996_txbf_init(struct mt7996_dev *dev); void mt7996_reset(struct mt7996_dev *dev); -int mt7996_run(struct ieee80211_hw *hw); +int mt7996_run(struct mt7996_phy *phy); int mt7996_mcu_init(struct mt7996_dev *dev); int mt7996_mcu_init_firmware(struct mt7996_dev *dev); int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, - struct mt7996_vif *mvif, + struct mt7996_vif_link *link, struct mt7996_twt_flow *flow, int cmd); -int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, - struct ieee80211_vif *vif, bool enable); -int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, - struct ieee80211_vif *vif, int enable); -int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable); +int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink, bool enable); +int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt76_vif_link *mlink, + struct mt7996_sta_link *msta_link, int enable); +int mt7996_mcu_add_sta(struct mt7996_dev *dev, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, + int conn_state, bool newly); +int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link); int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev, struct ieee80211_ampdu_params *params, - bool add); + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, bool enable); int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, struct ieee80211_ampdu_params *params, - bool add); -int mt7996_mcu_update_bss_color(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct mt7996_vif_link *link, bool enable); +int mt7996_mcu_update_bss_color(struct mt7996_dev *dev, + struct mt76_vif_link *mlink, struct cfg80211_he_bss_color *he_bss_color); int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int enable); + struct ieee80211_bss_conf *link_conf); int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, - struct ieee80211_vif *vif, u32 changed); -int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct mt7996_vif_link *link, u32 changed); +int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, + struct mt7996_vif_link *link, struct ieee80211_he_obss_pd *he_obss_pd); -int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool changed); -int mt7996_set_channel(struct mt7996_phy *phy); +int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, bool changed); +int mt7996_set_channel(struct mt76_phy *mphy); int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag); -int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif); +int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, void *data, u16 version); -int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *data, u32 field); +int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, + void *data, u32 field); int mt7996_mcu_set_eeprom(struct mt7996_dev *dev); -int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset); +int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len); int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num); int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap); int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band); @@ -487,14 +650,14 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, const struct mt7996_dfs_pattern *pattern); int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable); int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val); -int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif); +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch); int mt7996_mcu_get_temperature(struct mt7996_phy *phy); int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state); int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable); int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy); -int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, - u8 rx_sel, u8 val); +int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val); int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef); int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx, @@ -510,6 +673,7 @@ 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); int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id); +int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled); static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev) { @@ -559,30 +723,30 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy) return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx); } +static inline bool mt7996_has_wa(struct mt7996_dev *dev) +{ + return !is_mt7990(&dev->mt76); +} + void mt7996_mac_init(struct mt7996_dev *dev); u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw); bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask); void mt7996_mac_reset_counters(struct mt7996_phy *phy); void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy); void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band); -void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, - struct ieee80211_vif *vif, bool enable); void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed); void mt7996_mac_set_coverage_class(struct mt7996_phy *phy); -int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); void mt7996_mac_work(struct work_struct *work); void mt7996_mac_reset_work(struct work_struct *work); void mt7996_mac_dump_work(struct work_struct *work); void mt7996_mac_sta_rc_work(struct work_struct *work); void mt7996_mac_update_stats(struct mt7996_phy *phy); void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, - struct mt7996_sta *msta, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, u8 flowid); void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, struct ieee80211_sta *sta, @@ -601,17 +765,21 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy); void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy); void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy); void mt7996_update_channel(struct mt76_phy *mphy); -int mt7996_init_debugfs(struct mt7996_phy *phy); +int mt7996_init_debugfs(struct mt7996_dev *dev); void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len); bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len); int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd); -int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif, +int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link, struct ieee80211_key_conf *key); int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link); +int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode); #ifdef CONFIG_MAC80211_DEBUGFS void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c index 04056181368a..19e99bc1c6c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -16,14 +16,16 @@ static DEFINE_SPINLOCK(hif_lock); static u32 hif_idx; static const struct pci_device_id mt7996_pci_device_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) }, - { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID) }, { }, }; static const struct pci_device_id mt7996_hif_device_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) }, - { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2) }, { }, }; @@ -63,8 +65,9 @@ static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev) { hif_idx++; - if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) && - !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL)) + if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2, NULL) && + !pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2, NULL) && + !pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2, NULL)) return NULL; writel(hif_idx | MT_PCIE_RECOG_ID_SEM, @@ -121,7 +124,9 @@ static int mt7996_pci_probe(struct pci_dev *pdev, mt76_pci_disable_aspm(pdev); - if (id->device == 0x7991 || id->device == 0x799a) + if (id->device == MT7996_DEVICE_ID_2 || + id->device == MT7992_DEVICE_ID_2 || + id->device == MT7990_DEVICE_ID_2) return mt7996_pci_hif2_probe(pdev); dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], @@ -256,3 +261,5 @@ MODULE_FIRMWARE(MT7992_FIRMWARE_WA); MODULE_FIRMWARE(MT7992_FIRMWARE_WM); MODULE_FIRMWARE(MT7992_FIRMWARE_DSP); MODULE_FIRMWARE(MT7992_ROM_PATCH); +MODULE_FIRMWARE(MT7990_FIRMWARE_WM); +MODULE_FIRMWARE(MT7990_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 47b429d8bfbe..e942c0058731 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -64,6 +64,17 @@ enum offs_rev { MIB_BSCR7, MIB_BSCR17, MIB_TRDR1, + HIF_REMAP_L1, + HIF_REMAP_BASE_L1, + HIF_REMAP_L2, + HIF_REMAP_BASE_L2, + CBTOP1_PHY_END, + INFRA_MCU_END, + WTBLON_WDUCR, + WTBL_UPDATE, + WTBL_ITCR, + WTBL_ITCR0, + WTBL_ITCR1, __MT_OFFS_MAX, }; @@ -175,6 +186,9 @@ enum offs_rev { #define MT_WTBLOFF_RSCR_RCPI_MODE GENMASK(31, 30) #define MT_WTBLOFF_RSCR_RCPI_PARAM GENMASK(25, 24) +#define MT_WTBLOFF_ACR(_band) MT_WTBLOFF(_band, 0x010) +#define MT_WTBLOFF_ADM_BACKOFFTIME BIT(29) + /* ETBF: band 0(0x820ea000), band 1(0x820fa000), band 2(0x830ea000) */ #define MT_WF_ETBF_BASE(_band) __BASE(WF_ETBF_BASE, (_band)) #define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) @@ -288,19 +302,19 @@ enum offs_rev { /* WTBLON TOP */ #define MT_WTBLON_TOP_BASE 0x820d4000 #define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(__OFFS(WTBLON_WDUCR)) #define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0) -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380) +#define MT_WTBL_UPDATE MT_WTBLON_TOP(__OFFS(WTBL_UPDATE)) #define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0) #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14) #define MT_WTBL_UPDATE_BUSY BIT(31) -#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0) +#define MT_WTBL_ITCR MT_WTBLON_TOP(__OFFS(WTBL_ITCR)) #define MT_WTBL_ITCR_WR BIT(16) #define MT_WTBL_ITCR_EXEC BIT(31) -#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8) -#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc) +#define MT_WTBL_ITDR0 MT_WTBLON_TOP(__OFFS(WTBL_ITCR0)) +#define MT_WTBL_ITDR1 MT_WTBLON_TOP(__OFFS(WTBL_ITCR1)) #define MT_WTBL_SPE_IDX_SEL BIT(6) /* WTBL */ @@ -480,7 +494,7 @@ enum offs_rev { #define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \ MT_MCUQ_ID(q) * 0x4) -#define MT_RXQ_BAND1_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \ +#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \ MT_RXQ_ID(q) * 0x4) #define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \ MT_TXQ_ID(q) * 0x4) @@ -501,6 +515,8 @@ enum offs_rev { #define MT_INT_RX_DONE_WA_TRI BIT(3) #define MT_INT_RX_TXFREE_MAIN BIT(17) #define MT_INT_RX_TXFREE_TRI BIT(15) +#define MT_INT_RX_TXFREE_BAND0_MT7990 BIT(14) +#define MT_INT_RX_TXFREE_BAND1_MT7990 BIT(15) #define MT_INT_RX_DONE_BAND2_EXT BIT(23) #define MT_INT_RX_TXFREE_EXT BIT(26) #define MT_INT_MCU_CMD BIT(29) @@ -573,27 +589,39 @@ enum offs_rev { #define MT_MCU_CMD_WDT_MASK GENMASK(31, 30) /* l1/l2 remap */ -#define MT_HIF_REMAP_L1 0x155024 -#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16) +#define CONN_BUS_CR_VON_BASE 0x155000 +#define MT_HIF_REMAP_L1 (CONN_BUS_CR_VON_BASE + __OFFS(HIF_REMAP_L1)) +#define MT_HIF_REMAP_L1_MASK_7996 GENMASK(31, 16) +#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0) #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_BASE_L1 __OFFS(HIF_REMAP_BASE_L1) -#define MT_HIF_REMAP_L2 0x1b4 +#define MT_HIF_REMAP_L2 __OFFS(HIF_REMAP_L2) #define MT_HIF_REMAP_L2_MASK GENMASK(19, 0) #define MT_HIF_REMAP_L2_OFFSET GENMASK(11, 0) #define MT_HIF_REMAP_L2_BASE GENMASK(31, 12) -#define MT_HIF_REMAP_BASE_L2 0x1000 +#define MT_HIF_REMAP_L2_MASK_7990 GENMASK(15, 0) +#define MT_HIF_REMAP_L2_OFFSET_7990 GENMASK(15, 0) +#define MT_HIF_REMAP_L2_BASE_7990 GENMASK(31, 16) +#define MT_HIF_REMAP_BASE_L2 __OFFS(HIF_REMAP_BASE_L2) + +/* for mt7990 only */ +#define MT_HIF_REMAP_CBTOP 0x1f6554 +#define MT_HIF_REMAP_CBTOP_MASK GENMASK(15, 0) +#define MT_HIF_REMAP_CBTOP_OFFSET GENMASK(15, 0) +#define MT_HIF_REMAP_CBTOP_BASE GENMASK(31, 16) +#define MT_HIF_REMAP_BASE_CBTOP 0x1c0000 #define MT_INFRA_BASE 0x18000000 #define MT_WFSYS0_PHY_START 0x18400000 #define MT_WFSYS1_PHY_START 0x18800000 #define MT_WFSYS1_PHY_END 0x18bfffff #define MT_CBTOP1_PHY_START 0x70000000 -#define MT_CBTOP1_PHY_END 0x77ffffff +#define MT_CBTOP1_PHY_END __OFFS(CBTOP1_PHY_END) #define MT_CBTOP2_PHY_START 0xf0000000 #define MT_INFRA_MCU_START 0x7c000000 -#define MT_INFRA_MCU_END 0x7c3fffff +#define MT_INFRA_MCU_END __OFFS(INFRA_MCU_END) /* FW MODE SYNC */ #define MT_FW_ASSERT_CNT 0x02208274 @@ -660,8 +688,17 @@ enum offs_rev { #define MT_TOP_MISC MT_TOP(0xf0) #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) +/* ADIE */ +#define MT_ADIE_CHIP_ID(_idx) (0x0f00002c + ((_idx) << 28)) +#define MT_ADIE_VERSION_MASK GENMASK(15, 0) +#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16) + #define MT_PAD_GPIO 0x700056f0 #define MT_PAD_GPIO_ADIE_COMB GENMASK(16, 15) +#define MT_PAD_GPIO_2ADIE_TBTC BIT(19) +/* for mt7992 */ +#define MT_PAD_GPIO_ADIE_COMB_7992 GENMASK(17, 16) +#define MT_PAD_GPIO_ADIE_SINGLE BIT(15) #define MT_HW_REV 0x70010204 #define MT_HW_REV1 0x8a00 diff --git a/drivers/net/wireless/mediatek/mt76/pci.c b/drivers/net/wireless/mediatek/mt76/pci.c index 4c1c159fbb62..b5031ca7f73f 100644 --- a/drivers/net/wireless/mediatek/mt76/pci.c +++ b/drivers/net/wireless/mediatek/mt76/pci.c @@ -45,3 +45,26 @@ void mt76_pci_disable_aspm(struct pci_dev *pdev) aspm_conf); } EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm); + +bool mt76_pci_aspm_supported(struct pci_dev *pdev) +{ + struct pci_dev *parent = pdev->bus->self; + u16 aspm_conf, parent_aspm_conf = 0; + bool result = true; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf); + aspm_conf &= PCI_EXP_LNKCTL_ASPMC; + if (parent) { + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, + &parent_aspm_conf); + parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC; + } + + if (!aspm_conf && (!parent || !parent_aspm_conf)) { + /* aspm already disabled */ + result = false; + } + + return result; +} +EXPORT_SYMBOL_GPL(mt76_pci_aspm_supported); diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c new file mode 100644 index 000000000000..9b20ccbeb8cf --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/scan.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> + */ +#include "mt76.h" + +static void mt76_scan_complete(struct mt76_dev *dev, bool abort) +{ + struct mt76_phy *phy = dev->scan.phy; + struct cfg80211_scan_info info = { + .aborted = abort, + }; + + if (!phy) + return; + + clear_bit(MT76_SCANNING, &phy->state); + + if (dev->scan.chan && phy->main_chandef.chan) + mt76_set_channel(phy, &phy->main_chandef, false); + mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink); + memset(&dev->scan, 0, sizeof(dev->scan)); + ieee80211_scan_completed(phy->hw, &info); +} + +void mt76_abort_scan(struct mt76_dev *dev) +{ + cancel_delayed_work_sync(&dev->scan_work); + mt76_scan_complete(dev, true); +} + +static void +mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) +{ + struct cfg80211_scan_request *req = dev->scan.req; + struct ieee80211_vif *vif = dev->scan.vif; + struct mt76_vif_link *mvif = dev->scan.mlink; + enum nl80211_band band = dev->scan.chan->band; + struct mt76_phy *phy = dev->scan.phy; + struct ieee80211_tx_info *info; + struct sk_buff *skb; + + skb = ieee80211_probereq_get(phy->hw, vif->addr, ssid->ssid, + ssid->ssid_len, req->ie_len); + if (!skb) + return; + + if (is_unicast_ether_addr(req->bssid)) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + ether_addr_copy(hdr->addr1, req->bssid); + ether_addr_copy(hdr->addr3, req->bssid); + } + + if (req->ie_len) + skb_put_data(skb, req->ie, req->ie_len); + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + rcu_read_lock(); + + if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { + ieee80211_free_txskb(phy->hw, skb); + goto out; + } + + info = IEEE80211_SKB_CB(skb); + if (req->no_cck) + info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE; + info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; + + mt76_tx(phy, NULL, mvif->wcid, skb); + +out: + rcu_read_unlock(); +} + +void mt76_scan_work(struct work_struct *work) +{ + struct mt76_dev *dev = container_of(work, struct mt76_dev, + scan_work.work); + struct cfg80211_scan_request *req = dev->scan.req; + struct cfg80211_chan_def chandef = {}; + struct mt76_phy *phy = dev->scan.phy; + int duration = HZ / 9; /* ~110 ms */ + int i; + + if (dev->scan.chan_idx >= req->n_channels) { + mt76_scan_complete(dev, false); + return; + } + + if (dev->scan.chan && phy->num_sta) { + dev->scan.chan = NULL; + mt76_set_channel(phy, &phy->main_chandef, false); + goto out; + } + + dev->scan.chan = req->channels[dev->scan.chan_idx++]; + cfg80211_chandef_create(&chandef, dev->scan.chan, NL80211_CHAN_HT20); + mt76_set_channel(phy, &chandef, true); + + if (!req->n_ssids || + chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) + goto out; + + duration = HZ / 16; /* ~60 ms */ + local_bh_disable(); + for (i = 0; i < req->n_ssids; i++) + mt76_scan_send_probe(dev, &req->ssids[i]); + local_bh_enable(); + +out: + if (!duration) + return; + + if (dev->scan.chan) + duration = max_t(int, duration, + msecs_to_jiffies(req->duration + + (req->duration >> 5))); + + ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, duration); +} + +int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *req) +{ + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_vif_link *mlink; + int ret = 0; + + if (hw->wiphy->n_radio > 1) { + phy = dev->band_phys[req->req.channels[0]->band]; + if (!phy) + return -EINVAL; + } + + mutex_lock(&dev->mutex); + + if (dev->scan.req || phy->roc_vif) { + ret = -EBUSY; + goto out; + } + + mlink = mt76_get_vif_phy_link(phy, vif); + if (IS_ERR(mlink)) { + ret = PTR_ERR(mlink); + goto out; + } + + memset(&dev->scan, 0, sizeof(dev->scan)); + dev->scan.req = &req->req; + dev->scan.vif = vif; + dev->scan.phy = phy; + dev->scan.mlink = mlink; + ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, 0); + +out: + mutex_unlock(&dev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_hw_scan); + +void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt76_phy *phy = hw->priv; + + mt76_abort_scan(phy->dev); +} +EXPORT_SYMBOL_GPL(mt76_cancel_hw_scan); diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 3e88798df017..8e9576747052 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -499,7 +499,8 @@ static void mt76s_tx_status_data(struct mt76_worker *worker) dev = container_of(sdio, struct mt76_dev, sdio); while (true) { - if (test_bit(MT76_REMOVED, &dev->phy.state)) + if (test_bit(MT76_RESET, &dev->phy.state) || + test_bit(MT76_REMOVED, &dev->phy.state)) break; if (!dev->drv->tx_status_data(dev, &update)) @@ -514,13 +515,14 @@ static void mt76s_tx_status_data(struct mt76_worker *worker) } static int -mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, +mt76s_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { struct mt76_tx_info tx_info = { .skb = skb, }; + struct mt76_dev *dev = phy->dev; int err, len = skb->len; u16 idx = q->head; @@ -548,10 +550,7 @@ static int mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info) { - int ret = -ENOSPC, len = skb->len, pad; - - if (q->queued == q->ndesc) - goto error; + int ret, len = skb->len, pad; pad = round_up(skb->len, 4) - skb->len; ret = mt76_skb_adjust_pad(skb, pad); @@ -560,6 +559,12 @@ mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, spin_lock_bh(&q->lock); + if (q->queued == q->ndesc) { + ret = -ENOSPC; + spin_unlock_bh(&q->lock); + goto error; + } + q->entry[q->head].buf_sz = len; q->entry[q->head].skb = skb; diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c index ddd8c0cc744d..0a927a7313a6 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c @@ -46,6 +46,10 @@ static int mt76s_refill_sched_quota(struct mt76_dev *dev, u32 *data) return 0; sdio->sched.pse_mcu_quota += pse_mcu_quota; + if (sdio->pse_mcu_quota_max && + sdio->sched.pse_mcu_quota > sdio->pse_mcu_quota_max) { + sdio->sched.pse_mcu_quota = sdio->pse_mcu_quota_max; + } sdio->sched.pse_data_quota += pse_data_quota; sdio->sched.ple_data_quota += ple_data_quota; diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 4644dace9bb3..ca4feccf38ca 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -53,7 +53,7 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy) q->queued < q->ndesc / 2) { int ret; - ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb), + ret = dev->queue_ops->tx_queue_skb(phy, q, qid, skb_get(skb), wcid, NULL); if (ret < 0) break; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 1809b03292c3..513916469ca2 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags, return; /* Tx status can be unreliable. if it fails, mark the frame as ACKed */ - if (flags & MT_TX_CB_TXS_FAILED) { + if (flags & MT_TX_CB_TXS_FAILED && + (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) { info->status.rates[0].count = 0; info->status.rates[0].idx = -1; info->flags |= IEEE80211_TX_STAT_ACK; @@ -308,11 +309,14 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb, int idx; non_aql = !info->tx_time_est; - idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta); + idx = dev->queue_ops->tx_queue_skb(phy, q, qid, skb, wcid, sta); if (idx < 0 || !sta) return idx; wcid = (struct mt76_wcid *)sta->drv_priv; + if (!wcid->sta) + return idx; + q->entry[idx].wcid = wcid->idx; if (!non_aql) @@ -330,6 +334,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct sk_buff_head *head; if (mt76_testmode_enabled(phy)) { ieee80211_free_txskb(phy->hw, skb); @@ -345,9 +350,15 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); - spin_lock_bh(&wcid->tx_pending.lock); - __skb_queue_tail(&wcid->tx_pending, skb); - spin_unlock_bh(&wcid->tx_pending.lock); + if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || + (info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) + head = &wcid->tx_offchannel; + else + head = &wcid->tx_pending; + + spin_lock_bh(&head->lock); + __skb_queue_tail(head, skb); + spin_unlock_bh(&head->lock); spin_lock_bh(&phy->tx_lock); if (list_empty(&wcid->tx_list)) @@ -478,8 +489,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, return idx; do { - if (test_bit(MT76_RESET, &phy->state)) - return -EBUSY; + if (test_bit(MT76_RESET, &phy->state) || phy->offchannel) + break; if (stop || mt76_txq_stopped(q)) break; @@ -512,24 +523,16 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, static int mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) { - struct mt76_queue *q = phy->q_tx[qid]; struct mt76_dev *dev = phy->dev; struct ieee80211_txq *txq; struct mt76_txq *mtxq; struct mt76_wcid *wcid; + struct mt76_queue *q; int ret = 0; while (1) { int n_frames = 0; - if (test_bit(MT76_RESET, &phy->state)) - return -EBUSY; - - if (dev->queue_ops->tx_cleanup && - q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) { - dev->queue_ops->tx_cleanup(dev, q, false); - } - txq = ieee80211_next_txq(phy->hw, qid); if (!txq) break; @@ -539,6 +542,16 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags)) continue; + phy = mt76_dev_phy(dev, wcid->phy_idx); + if (test_bit(MT76_RESET, &phy->state) || phy->offchannel) + continue; + + q = phy->q_tx[qid]; + if (dev->queue_ops->tx_cleanup && + q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) { + dev->queue_ops->tx_cleanup(dev, q, false); + } + if (mtxq->send_bar && mtxq->aggr) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct ieee80211_sta *sta = txq->sta; @@ -586,7 +599,8 @@ 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) +mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, + struct sk_buff_head *head) { struct mt76_dev *dev = phy->dev; struct ieee80211_sta *sta; @@ -594,8 +608,8 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid) struct sk_buff *skb; int ret = 0; - spin_lock(&wcid->tx_pending.lock); - while ((skb = skb_peek(&wcid->tx_pending)) != NULL) { + spin_lock(&head->lock); + while ((skb = skb_peek(head)) != 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); @@ -607,13 +621,13 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid) qid = MT_TXQ_PSD; q = phy->q_tx[qid]; - if (mt76_txq_stopped(q)) { + if (mt76_txq_stopped(q) || test_bit(MT76_RESET, &phy->state)) { ret = -1; break; } - __skb_unlink(skb, &wcid->tx_pending); - spin_unlock(&wcid->tx_pending.lock); + __skb_unlink(skb, head); + spin_unlock(&head->lock); sta = wcid_to_sta(wcid); spin_lock(&q->lock); @@ -621,15 +635,17 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid) dev->queue_ops->kick(dev, q); spin_unlock(&q->lock); - spin_lock(&wcid->tx_pending.lock); + spin_lock(&head->lock); } - spin_unlock(&wcid->tx_pending.lock); + spin_unlock(&head->lock); return ret; } static void mt76_txq_schedule_pending(struct mt76_phy *phy) { + LIST_HEAD(tx_list); + if (list_empty(&phy->tx_list)) return; @@ -637,22 +653,27 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy) rcu_read_lock(); spin_lock(&phy->tx_lock); - while (!list_empty(&phy->tx_list)) { - struct mt76_wcid *wcid = NULL; + list_splice_init(&phy->tx_list, &tx_list); + while (!list_empty(&tx_list)) { + struct mt76_wcid *wcid; int ret; - wcid = list_first_entry(&phy->tx_list, struct mt76_wcid, tx_list); + wcid = list_first_entry(&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); + ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel); + if (ret >= 0 && !phy->offchannel) + ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending); spin_lock(&phy->tx_lock); - if (ret) { - if (list_empty(&wcid->tx_list)) - list_add_tail(&wcid->tx_list, &phy->tx_list); + if (!skb_queue_empty(&wcid->tx_pending) && + !skb_queue_empty(&wcid->tx_offchannel) && + list_empty(&wcid->tx_list)) + list_add_tail(&wcid->tx_list, &phy->tx_list); + + if (ret < 0) break; - } } spin_unlock(&phy->tx_lock); @@ -662,9 +683,14 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy) void mt76_txq_schedule_all(struct mt76_phy *phy) { + struct mt76_phy *main_phy = &phy->dev->phy; int i; mt76_txq_schedule_pending(phy); + + if (phy != main_phy && phy->hw == main_phy->hw) + return; + for (i = 0; i <= MT_TXQ_BK; i++) mt76_txq_schedule(phy, i); } @@ -675,6 +701,7 @@ void mt76_tx_worker_run(struct mt76_dev *dev) struct mt76_phy *phy; int i; + mt76_txq_schedule_all(&dev->phy); for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { phy = dev->phys[i]; if (!phy) @@ -730,9 +757,6 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; - if (!test_bit(MT76_STATE_RUNNING, &phy->state)) - return; - mt76_worker_schedule(&dev->tx_worker); } EXPORT_SYMBOL_GPL(mt76_wake_tx_queue); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 5a0bcb5071bd..f9e67b8c3b3c 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -33,9 +33,9 @@ int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, ret = usb_control_msg(udev, pipe, req, req_type, val, offset, buf, len, MT_VEND_REQ_TOUT_MS); - if (ret == -ENODEV) + if (ret == -ENODEV || ret == -EPROTO) set_bit(MT76_REMOVED, &dev->phy.state); - if (ret >= 0 || ret == -ENODEV) + if (ret >= 0 || ret == -ENODEV || ret == -EPROTO) return ret; usleep_range(5000, 10000); } @@ -767,7 +767,7 @@ static void mt76u_status_worker(struct mt76_worker *w) if (!test_bit(MT76_STATE_RUNNING, &dev->phy.state)) return; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { + for (i = 0; i <= MT_TXQ_PSD; i++) { q = dev->phy.q_tx[i]; if (!q) continue; @@ -850,13 +850,14 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, } static int -mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, +mt76u_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { struct mt76_tx_info tx_info = { .skb = skb, }; + struct mt76_dev *dev = phy->dev; u16 idx = q->head; int err; @@ -872,9 +873,8 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, if (err < 0) return err; - mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx), - q->entry[idx].urb, mt76u_complete_tx, - &q->entry[idx]); + mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q->ep, q->entry[idx].urb, + mt76u_complete_tx, &q->entry[idx]); q->head = (q->head + 1) % q->ndesc; q->entry[idx].skb = tx_info.skb; @@ -906,9 +906,13 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) } } -static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac) +static void +mt76u_ac_to_hwq(struct mt76_dev *dev, struct mt76_queue *q, u8 qid) { - if (mt76_chip(dev) == 0x7663) { + u8 ac = qid < IEEE80211_NUM_ACS ? qid : IEEE80211_AC_BE; + + switch (mt76_chip(dev)) { + case 0x7663: { static const u8 lmac_queue_map[] = { /* ac to lmac mapping */ [IEEE80211_AC_BK] = 0, @@ -917,33 +921,36 @@ static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac) [IEEE80211_AC_VO] = 4, }; - if (WARN_ON(ac >= ARRAY_SIZE(lmac_queue_map))) - return 1; /* BE */ - - return lmac_queue_map[ac]; + q->hw_idx = lmac_queue_map[ac]; + q->ep = q->hw_idx + 1; + break; + } + case 0x7961: + case 0x7925: + q->hw_idx = mt76_ac_to_hwq(ac); + q->ep = qid == MT_TXQ_PSD ? MT_EP_OUT_HCCA : q->hw_idx + 1; + break; + default: + q->hw_idx = mt76_ac_to_hwq(ac); + q->ep = q->hw_idx + 1; + break; } - - return mt76_ac_to_hwq(ac); } static int mt76u_alloc_tx(struct mt76_dev *dev) { - struct mt76_queue *q; - int i, j, err; + int i; for (i = 0; i <= MT_TXQ_PSD; i++) { - if (i >= IEEE80211_NUM_ACS) { - dev->phy.q_tx[i] = dev->phy.q_tx[0]; - continue; - } + struct mt76_queue *q; + int j, err; q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); if (!q) return -ENOMEM; spin_lock_init(&q->lock); - q->hw_idx = mt76u_ac_to_hwq(dev, i); - + mt76u_ac_to_hwq(dev, q, i); dev->phy.q_tx[i] = q; q->entry = devm_kcalloc(dev->dev, @@ -969,7 +976,7 @@ static void mt76u_free_tx(struct mt76_dev *dev) mt76_worker_teardown(&dev->usb.status_worker); - for (i = 0; i < IEEE80211_NUM_ACS; i++) { + for (i = 0; i <= MT_TXQ_PSD; i++) { struct mt76_queue *q; int j; @@ -999,7 +1006,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) dev_err(dev->dev, "timed out waiting for pending tx\n"); - for (i = 0; i < IEEE80211_NUM_ACS; i++) { + for (i = 0; i <= MT_TXQ_PSD; i++) { q = dev->phy.q_tx[i]; if (!q) continue; @@ -1013,7 +1020,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) /* On device removal we maight queue skb's, but mt76u_tx_kick() * will fail to submit urb, cleanup those skb's manually. */ - for (i = 0; i < IEEE80211_NUM_ACS; i++) { + for (i = 0; i <= MT_TXQ_PSD; i++) { q = dev->phy.q_tx[i]; if (!q) continue; diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index d6c01a2dd198..95b3dc96e4c4 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -64,7 +64,7 @@ int mt76_wcid_alloc(u32 *mask, int size) } EXPORT_SYMBOL_GPL(mt76_wcid_alloc); -int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) +int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) { struct mt76_wcid *wcid; int i, j, min_rssi = 0; @@ -75,20 +75,16 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { u32 mask = dev->wcid_mask[i]; - u32 phy_mask = dev->wcid_phy_mask[i]; if (!mask) continue; - for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) { + for (j = i * 32; mask; j++, mask >>= 1) { if (!(mask & 1)) continue; - if (!!(phy_mask & 1) != ext_phy) - continue; - wcid = rcu_dereference(dev->wcid[j]); - if (!wcid) + if (!wcid || wcid->phy_idx != phy_idx) continue; spin_lock(&dev->rx_lock); diff --git a/drivers/net/wireless/mediatek/mt76/wed.c b/drivers/net/wireless/mediatek/mt76/wed.c new file mode 100644 index 000000000000..f89e4537555c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/wed.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include "mt76.h" +#include "dma.h" + +void mt76_wed_release_rx_buf(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + int i; + + for (i = 0; i < dev->rx_token_size; i++) { + struct mt76_txwi_cache *t; + + t = mt76_rx_token_release(dev, i); + if (!t || !t->ptr) + continue; + + mt76_put_page_pool_buf(t->ptr, false); + t->ptr = NULL; + + mt76_put_rxwi(dev, t); + } + + mt76_free_pending_rxwi(dev); +} +EXPORT_SYMBOL_GPL(mt76_wed_release_rx_buf); + +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + int i, len = SKB_WITH_OVERHEAD(q->buf_size); + struct mt76_txwi_cache *t = NULL; + + for (i = 0; i < size; i++) { + enum dma_data_direction dir; + dma_addr_t addr; + u32 offset; + int token; + void *buf; + + t = mt76_get_rxwi(dev); + if (!t) + goto unmap; + + buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); + if (!buf) + goto unmap; + + addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; + dir = page_pool_get_dma_dir(q->page_pool); + dma_sync_single_for_device(dev->dma_dev, addr, len, dir); + + desc->buf0 = cpu_to_le32(addr); + token = mt76_rx_token_consume(dev, buf, t, addr); + if (token < 0) { + mt76_put_page_pool_buf(buf, false); + goto unmap; + } + + token = FIELD_PREP(MT_DMA_CTL_TOKEN, token); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32); +#endif + desc->token |= cpu_to_le32(token); + desc++; + } + + return 0; + +unmap: + if (t) + mt76_put_rxwi(dev, t); + mt76_wed_release_rx_buf(wed); + + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(mt76_wed_init_rx_buf); + +int mt76_wed_offload_enable(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + spin_lock_bh(&dev->token_lock); + dev->token_size = wed->wlan.token_start; + spin_unlock_bh(&dev->token_lock); + + return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ); +} +EXPORT_SYMBOL_GPL(mt76_wed_offload_enable); + +int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) +{ + int ret = 0, type, ring; + u16 flags; + + if (!q || !q->ndesc) + return -EINVAL; + + flags = q->flags; + if (!q->wed || !mtk_wed_device_active(q->wed)) + q->flags &= ~MT_QFLAG_WED; + + if (!(q->flags & MT_QFLAG_WED)) + return 0; + + type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags); + ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags); + + switch (type) { + case MT76_WED_Q_TX: + ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs, + reset); + if (!ret) + q->wed_regs = q->wed->tx_ring[ring].reg_base; + break; + case MT76_WED_Q_TXFREE: + /* WED txfree queue needs ring to be initialized before setup */ + q->flags = 0; + mt76_dma_queue_reset(dev, q); + mt76_dma_rx_fill(dev, q, false); + + ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); + if (!ret) + q->wed_regs = q->wed->txfree_ring.reg_base; + break; + case MT76_WED_Q_RX: + ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs, + reset); + if (!ret) + q->wed_regs = q->wed->rx_ring[ring].reg_base; + break; + case MT76_WED_RRO_Q_DATA: + q->flags &= ~MT_QFLAG_WED; + __mt76_dma_queue_reset(dev, q, false); + mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs); + q->head = q->ndesc - 1; + q->queued = q->head; + break; + case MT76_WED_RRO_Q_MSDU_PG: + q->flags &= ~MT_QFLAG_WED; + __mt76_dma_queue_reset(dev, q, false); + mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs); + q->head = q->ndesc - 1; + q->queued = q->head; + break; + case MT76_WED_RRO_Q_IND: + q->flags &= ~MT_QFLAG_WED; + mt76_dma_queue_reset(dev, q); + mt76_dma_rx_fill(dev, q, false); + mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs); + break; + default: + ret = -EINVAL; + break; + } + q->flags = flags; + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_wed_dma_setup); +#endif /*CONFIG_NET_MEDIATEK_SOC_WED */ + +void mt76_wed_offload_disable(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + spin_lock_bh(&dev->token_lock); + dev->token_size = dev->drv->token_size; + spin_unlock_bh(&dev->token_lock); +} +EXPORT_SYMBOL_GPL(mt76_wed_offload_disable); + +void mt76_wed_reset_complete(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + complete(&dev->mmio.wed_reset_complete); +} +EXPORT_SYMBOL_GPL(mt76_wed_reset_complete); + +int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct net_device *netdev, enum tc_setup_type type, + void *type_data) +{ + struct mt76_phy *phy = hw->priv; + struct mtk_wed_device *wed = &phy->dev->mmio.wed; + + if (!mtk_wed_device_active(wed)) + return -EOPNOTSUPP; + + return mtk_wed_device_setup_tc(wed, netdev, type, type_data); +} +EXPORT_SYMBOL_GPL(mt76_wed_net_setup_tc); + +void mt76_wed_dma_reset(struct mt76_dev *dev) +{ + struct mt76_mmio *mmio = &dev->mmio; + + if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state)) + return; + + complete(&mmio->wed_reset); + + if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ)) + dev_err(dev->dev, "wed reset complete timeout\n"); +} +EXPORT_SYMBOL_GPL(mt76_wed_dma_reset); |