mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-13 07:20:14 -04:00
Merge tag 'mt76-for-kvalo-2025-01-14' of https://github.com/nbd168/wireless
mt76 patches for 6.14 - mlo fixes for mt792x - single wiphy multiband support for mt7996 - mt7915 stability fixes
This commit is contained in:
@@ -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 wed.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
|
||||
|
||||
406
drivers/net/wireless/mediatek/mt76/channel.c
Normal file
406
drivers/net/wireless/mediatek/mt76/channel.c
Normal file
@@ -0,0 +1,406 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
|
||||
return;
|
||||
|
||||
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);
|
||||
@@ -631,7 +631,8 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
static int
|
||||
mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool allow_direct)
|
||||
{
|
||||
int len = SKB_WITH_OVERHEAD(q->buf_size);
|
||||
@@ -640,8 +641,6 @@ int 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;
|
||||
@@ -674,6 +673,19 @@ int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (frames || mt76_queue_is_wed_rx(q))
|
||||
mt76_dma_kick_queue(dev, q);
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool allow_direct)
|
||||
{
|
||||
int frames;
|
||||
|
||||
if (!q->ndesc)
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
frames = mt76_dma_rx_fill_buf(dev, q, allow_direct);
|
||||
spin_unlock_bh(&q->lock);
|
||||
|
||||
return frames;
|
||||
@@ -796,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
|
||||
@@ -969,7 +981,7 @@ mt76_dma_init(struct mt76_dev *dev,
|
||||
|
||||
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);
|
||||
mt76_dma_rx_fill_buf(dev, &dev->q_rx[i], false);
|
||||
napi_enable(&dev->napi[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -480,6 +487,28 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -552,9 +581,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;
|
||||
@@ -690,6 +721,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]);
|
||||
@@ -712,7 +744,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;
|
||||
@@ -784,6 +816,22 @@ void mt76_free_device(struct mt76_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
|
||||
{
|
||||
struct sk_buff *skb = phy->rx_amsdu[q].head;
|
||||
@@ -929,16 +977,13 @@ void mt76_update_survey(struct mt76_phy *phy)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_update_survey);
|
||||
|
||||
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)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
int timeout = HZ / 5;
|
||||
int ret;
|
||||
|
||||
cancel_delayed_work_sync(&phy->mac_work);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
set_bit(MT76_RESET, &phy->state);
|
||||
|
||||
mt76_worker_disable(&dev->tx_worker);
|
||||
@@ -954,17 +999,30 @@ int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
|
||||
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));
|
||||
mt76_worker_enable(&dev->tx_worker);
|
||||
|
||||
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;
|
||||
@@ -976,37 +1034,59 @@ int mt76_update_channel(struct mt76_phy *phy)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1021,7 +1101,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)
|
||||
@@ -1462,21 +1542,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;
|
||||
|
||||
@@ -1489,16 +1568,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);
|
||||
}
|
||||
|
||||
@@ -1511,13 +1592,17 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
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_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST)
|
||||
mt76_sta_remove(dev, vif, sta);
|
||||
mt76_sta_remove(phy, vif, sta);
|
||||
|
||||
if (!dev->drv->sta_event)
|
||||
return 0;
|
||||
@@ -1553,14 +1638,19 @@ 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);
|
||||
|
||||
@@ -1595,13 +1685,29 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
|
||||
|
||||
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);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm)
|
||||
{
|
||||
struct mt76_phy *phy = hw->priv;
|
||||
int n_chains = hweight16(phy->chainmask);
|
||||
int delta = mt76_tx_power_nss_delta(n_chains);
|
||||
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_nss_delta(n_chains);
|
||||
*dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2);
|
||||
|
||||
return 0;
|
||||
@@ -1776,10 +1882,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;
|
||||
@@ -1808,30 +1918,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)
|
||||
{
|
||||
@@ -1892,7 +1978,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;
|
||||
@@ -1906,3 +1992,15 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
|
||||
return MT_DFS_STATE_ACTIVE;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_phy_dfs_state);
|
||||
|
||||
void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_vif_data *mvif = mlink->mvif;
|
||||
|
||||
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_vif_cleanup);
|
||||
|
||||
@@ -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;
|
||||
@@ -497,6 +499,8 @@ 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);
|
||||
|
||||
@@ -528,6 +532,15 @@ struct mt76_driver_ops {
|
||||
|
||||
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 {
|
||||
@@ -636,6 +649,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;
|
||||
@@ -753,7 +767,7 @@ struct mt76_testmode_data {
|
||||
} rx_stats;
|
||||
};
|
||||
|
||||
struct mt76_vif {
|
||||
struct mt76_vif_link {
|
||||
u8 idx;
|
||||
u8 omac_idx;
|
||||
u8 band_idx;
|
||||
@@ -763,7 +777,19 @@ 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_phy *roc_phy;
|
||||
u16 valid_links;
|
||||
u8 deflink_id;
|
||||
};
|
||||
|
||||
struct mt76_phy {
|
||||
@@ -772,6 +798,7 @@ struct mt76_phy {
|
||||
void *priv;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int num_sta;
|
||||
u8 band_idx;
|
||||
|
||||
spinlock_t tx_lock;
|
||||
@@ -779,8 +806,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;
|
||||
@@ -825,6 +859,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;
|
||||
|
||||
@@ -880,7 +915,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;
|
||||
|
||||
@@ -909,6 +943,16 @@ struct mt76_dev {
|
||||
|
||||
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 {
|
||||
@@ -1036,6 +1080,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, \
|
||||
@@ -1156,6 +1204,10 @@ static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
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);
|
||||
@@ -1165,6 +1217,8 @@ 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);
|
||||
@@ -1191,8 +1245,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)
|
||||
@@ -1423,12 +1475,12 @@ 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);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm);
|
||||
@@ -1447,11 +1499,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,
|
||||
@@ -1497,8 +1576,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)
|
||||
@@ -1734,7 +1823,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
|
||||
|
||||
@@ -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;
|
||||
@@ -1793,7 +1788,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
@@ -463,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;
|
||||
|
||||
@@ -1249,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);
|
||||
|
||||
@@ -1271,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;
|
||||
|
||||
@@ -865,8 +865,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
mvif->sta_added = true;
|
||||
}
|
||||
conn_state = enable ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT;
|
||||
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, vif, link_sta,
|
||||
conn_state, new_entry);
|
||||
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);
|
||||
@@ -1113,7 +1113,7 @@ 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->bss_conf,
|
||||
return mt76_connac_mcu_uni_add_dev(phy->mt76, &vif->bss_conf, &mvif->mt76,
|
||||
&mvif->sta.wcid, enable);
|
||||
}
|
||||
|
||||
@@ -1700,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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -191,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;
|
||||
}
|
||||
@@ -230,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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -225,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;
|
||||
}
|
||||
@@ -253,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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -405,7 +405,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);
|
||||
|
||||
@@ -427,7 +427,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);
|
||||
|
||||
@@ -231,7 +231,8 @@ void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv,
|
||||
EHT_PREP(DATA0_PE_DISAMBIGUITY_OM, PE_DISAMBIG, rxv[5]) |
|
||||
EHT_PREP(DATA0_LDPC_EXTRA_SYM_OM, LDPC_EXT_SYM, rxv[4]);
|
||||
|
||||
eht->data[7] |= le32_encode_bits(status->nss, IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
|
||||
/* 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) |
|
||||
@@ -240,7 +241,7 @@ void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv,
|
||||
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, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O);
|
||||
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);
|
||||
|
||||
@@ -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:
|
||||
@@ -493,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;
|
||||
@@ -569,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;
|
||||
|
||||
@@ -1162,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,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 +232,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)
|
||||
@@ -273,7 +273,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 = {
|
||||
@@ -329,7 +329,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;
|
||||
@@ -369,10 +369,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_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;
|
||||
@@ -390,8 +391,8 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
!is_zero_ether_addr(vif->bss_conf.bssid)) {
|
||||
memcpy(basic->peer_addr, vif->bss_conf.bssid, ETH_ALEN);
|
||||
!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);
|
||||
@@ -497,7 +498,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;
|
||||
@@ -545,7 +546,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;
|
||||
@@ -849,7 +850,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;
|
||||
@@ -1041,7 +1042,7 @@ 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;
|
||||
@@ -1049,6 +1050,9 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
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);
|
||||
@@ -1057,7 +1061,7 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
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,
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
link_sta, conn_state,
|
||||
info->newly);
|
||||
if (info->sta && info->enable)
|
||||
@@ -1137,10 +1141,10 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ba_tlv);
|
||||
|
||||
int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
struct mt76_vif_link *mvif,
|
||||
struct mt76_wcid *wcid,
|
||||
bool enable)
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)bss_conf->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct {
|
||||
struct {
|
||||
@@ -1202,6 +1206,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;
|
||||
@@ -1263,7 +1270,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)
|
||||
{
|
||||
@@ -1364,7 +1371,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;
|
||||
@@ -1375,9 +1382,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) {
|
||||
@@ -1401,7 +1408,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;
|
||||
@@ -1450,7 +1457,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;
|
||||
@@ -1538,7 +1545,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;
|
||||
@@ -1664,7 +1671,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
|
||||
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);
|
||||
@@ -1770,7 +1777,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;
|
||||
@@ -1796,7 +1803,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;
|
||||
@@ -2208,7 +2215,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,
|
||||
@@ -2251,7 +2258,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 {
|
||||
@@ -2318,7 +2325,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;
|
||||
@@ -2359,7 +2366,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;
|
||||
@@ -2385,7 +2392,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;
|
||||
@@ -2414,7 +2421,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;
|
||||
@@ -2445,7 +2452,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 {
|
||||
@@ -2477,7 +2484,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 {
|
||||
@@ -2527,7 +2534,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 {
|
||||
@@ -2559,7 +2566,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);
|
||||
|
||||
@@ -2686,7 +2693,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;
|
||||
|
||||
@@ -2708,7 +2715,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;
|
||||
@@ -2732,7 +2739,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;
|
||||
|
||||
@@ -1043,12 +1043,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,
|
||||
@@ -1251,6 +1253,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 {
|
||||
@@ -1756,6 +1759,7 @@ struct mt76_sta_cmd_info {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
bool offload_fw;
|
||||
bool enable;
|
||||
@@ -1876,10 +1880,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,
|
||||
@@ -1901,7 +1905,7 @@ mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len)
|
||||
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
|
||||
int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
|
||||
void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
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,
|
||||
@@ -1938,13 +1942,14 @@ void mt76_connac_mcu_sta_ba_tlv(struct sk_buff *skb,
|
||||
bool enable, bool tx);
|
||||
int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
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,
|
||||
@@ -1975,7 +1980,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);
|
||||
@@ -1988,7 +1993,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,
|
||||
@@ -2014,7 +2019,7 @@ 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_link_sta *sta);
|
||||
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);
|
||||
|
||||
int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
@@ -2022,7 +2027,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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -423,7 +423,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
/* 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;
|
||||
@@ -170,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -512,6 +515,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) |
|
||||
@@ -1114,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,
|
||||
@@ -1239,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);
|
||||
|
||||
@@ -333,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;
|
||||
@@ -927,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;
|
||||
}
|
||||
|
||||
@@ -1040,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();
|
||||
@@ -1163,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))
|
||||
@@ -1388,6 +1377,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
|
||||
@@ -1442,9 +1433,11 @@ 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;
|
||||
|
||||
@@ -1474,6 +1467,9 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
|
||||
|
||||
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;
|
||||
|
||||
@@ -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)
|
||||
@@ -246,16 +247,15 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev));
|
||||
if (idx < 0)
|
||||
return -ENOSPC;
|
||||
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);
|
||||
@@ -366,8 +366,12 @@ 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 (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.
|
||||
@@ -619,8 +623,9 @@ 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);
|
||||
@@ -631,7 +636,11 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
|
||||
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;
|
||||
@@ -758,6 +767,57 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
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)
|
||||
{
|
||||
@@ -786,6 +846,7 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
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:
|
||||
|
||||
@@ -194,6 +194,25 @@ 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)
|
||||
@@ -208,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);
|
||||
}
|
||||
|
||||
@@ -1678,7 +1699,7 @@ 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, link_sta,
|
||||
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 && conn_state != CONN_STATE_DISCONNECT) {
|
||||
@@ -2388,7 +2409,7 @@ 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 = 3,
|
||||
.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,
|
||||
@@ -3150,8 +3171,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;
|
||||
|
||||
@@ -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,7 +486,7 @@ 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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -137,6 +137,13 @@ 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;
|
||||
|
||||
@@ -227,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));
|
||||
|
||||
@@ -216,11 +216,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
|
||||
if (status->wcid) {
|
||||
mlink = container_of(status->wcid, struct mt792x_link_sta, wcid);
|
||||
msta = container_of(mlink, struct mt792x_sta, deflink);
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->wcid.poll_list,
|
||||
&dev->mt76.sta_poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
|
||||
}
|
||||
|
||||
mt792x_get_status_freq_info(status, chfreq);
|
||||
@@ -479,10 +475,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data)
|
||||
if (!wcid->sta)
|
||||
goto out;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->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();
|
||||
@@ -529,11 +522,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
||||
continue;
|
||||
|
||||
mlink = container_of(wcid, struct mt792x_link_sta, wcid);
|
||||
spin_lock_bh(&mdev->sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->wcid.poll_list,
|
||||
&mdev->sta_poll_list);
|
||||
spin_unlock_bh(&mdev->sta_poll_lock);
|
||||
mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -647,6 +636,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
|
||||
ieee80211_disconnect(vif, 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);
|
||||
|
||||
|
||||
@@ -147,7 +147,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,
|
||||
@@ -252,6 +252,11 @@ int __mt7921_start(struct mt792x_phy *phy)
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt7921_start);
|
||||
@@ -308,6 +313,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
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->bss_conf,
|
||||
&mvif->bss_conf.mt76,
|
||||
&mvif->sta.deflink.wcid, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -319,10 +325,8 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
|
||||
INIT_LIST_HEAD(&mvif->sta.deflink.wcid.poll_list);
|
||||
mvif->sta.deflink.wcid.idx = idx;
|
||||
mvif->sta.deflink.wcid.phy_idx = mvif->bss_conf.mt76.band_idx;
|
||||
mvif->sta.deflink.wcid.hw_key_idx = -1;
|
||||
mvif->sta.deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_wcid_init(&mvif->sta.deflink.wcid);
|
||||
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);
|
||||
@@ -338,6 +342,9 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
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);
|
||||
|
||||
@@ -360,9 +367,9 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev)
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
ieee80211_iterate_active_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_roc_iter, (void *)phy);
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_roc_iter, (void *)phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
|
||||
|
||||
@@ -531,7 +538,13 @@ 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);
|
||||
@@ -858,6 +871,7 @@ 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;
|
||||
|
||||
mt7921_roc_abort_sync(dev);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->deflink.wcid);
|
||||
mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
|
||||
@@ -1334,6 +1348,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;
|
||||
}
|
||||
|
||||
@@ -1341,6 +1358,10 @@ static void
|
||||
mt7921_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
if (dev->new_ctx == ctx)
|
||||
dev->new_ctx = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1391,6 +1412,101 @@ 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;
|
||||
|
||||
del_timer_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,
|
||||
@@ -1441,6 +1557,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,
|
||||
@@ -1450,6 +1567,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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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)
|
||||
@@ -507,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;
|
||||
@@ -1122,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;
|
||||
@@ -1424,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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
#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,
|
||||
@@ -202,6 +205,7 @@ 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)
|
||||
@@ -273,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);
|
||||
|
||||
@@ -42,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);
|
||||
@@ -435,7 +439,7 @@ static int mt7921_pci_suspend(struct device *device)
|
||||
if (err < 0)
|
||||
goto restore_suspend;
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
|
||||
err = mt76_connac_mcu_set_hif_suspend(mdev, true, true);
|
||||
if (err)
|
||||
goto restore_suspend;
|
||||
|
||||
@@ -481,7 +485,7 @@ static int mt7921_pci_suspend(struct device *device)
|
||||
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;
|
||||
@@ -532,7 +536,7 @@ 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;
|
||||
|
||||
|
||||
@@ -240,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;
|
||||
|
||||
@@ -258,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);
|
||||
@@ -302,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;
|
||||
|
||||
|
||||
@@ -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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -257,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;
|
||||
|
||||
@@ -307,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;
|
||||
|
||||
|
||||
@@ -57,6 +57,22 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
|
||||
mt7925_hwmon_groups);
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
void mt7925_regd_update(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_hw *hw = mdev->hw;
|
||||
|
||||
if (!dev->regd_change)
|
||||
return;
|
||||
|
||||
mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env);
|
||||
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)
|
||||
@@ -64,6 +80,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) &&
|
||||
@@ -78,12 +95,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)
|
||||
@@ -178,6 +200,7 @@ 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) {
|
||||
@@ -225,6 +248,7 @@ int mt7925_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);
|
||||
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);
|
||||
|
||||
@@ -49,7 +49,7 @@ static void mt7925_mac_sta_poll(struct mt792x_dev *dev)
|
||||
break;
|
||||
mlink = list_first_entry(&sta_poll_list,
|
||||
struct mt792x_link_sta, wcid.poll_list);
|
||||
msta = container_of(mlink, struct mt792x_sta, deflink);
|
||||
msta = mlink->sta;
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
list_del_init(&mlink->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
@@ -395,11 +395,7 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
|
||||
|
||||
if (status->wcid) {
|
||||
mlink = container_of(status->wcid, struct mt792x_link_sta, wcid);
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->wcid.poll_list,
|
||||
&dev->mt76.sta_poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
|
||||
}
|
||||
|
||||
mt792x_get_status_freq_info(status, chfreq);
|
||||
@@ -734,7 +730,7 @@ 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 |
|
||||
@@ -743,7 +739,7 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
|
||||
mconf = vif ? mt792x_vif_to_link((struct mt792x_vif *)vif->drv_priv,
|
||||
wcid->link_id) : NULL;
|
||||
mvif = mconf ? (struct mt76_vif *)&mconf->mt76 : NULL;
|
||||
mvif = mconf ? (struct mt76_vif_link *)&mconf->mt76 : NULL;
|
||||
|
||||
if (mvif) {
|
||||
omac_idx = mvif->omac_idx;
|
||||
@@ -1054,10 +1050,7 @@ void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
|
||||
if (!wcid->sta)
|
||||
goto out;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->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();
|
||||
@@ -1135,11 +1128,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
||||
continue;
|
||||
|
||||
mlink = container_of(wcid, struct mt792x_link_sta, wcid);
|
||||
spin_lock_bh(&mdev->sta_poll_lock);
|
||||
if (list_empty(&mlink->wcid.poll_list))
|
||||
list_add_tail(&mlink->wcid.poll_list,
|
||||
&mdev->sta_poll_list);
|
||||
spin_unlock_bh(&mdev->sta_poll_lock);
|
||||
mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1271,6 +1260,7 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,
|
||||
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)
|
||||
@@ -1278,8 +1268,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,
|
||||
|
||||
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,
|
||||
mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76,
|
||||
&mvif->sta.deflink.wcid, true);
|
||||
mt7925_mcu_set_tx(dev, bss_conf);
|
||||
}
|
||||
@@ -1309,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);
|
||||
|
||||
@@ -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,
|
||||
@@ -310,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);
|
||||
@@ -320,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);
|
||||
@@ -365,29 +369,22 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx;
|
||||
mconf->mt76.band_idx = 0xff;
|
||||
mconf->mt76.wmm_idx = mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
|
||||
if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
|
||||
mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4;
|
||||
else
|
||||
mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL;
|
||||
|
||||
ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf,
|
||||
&mlink->wcid, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
dev->mt76.vif_mask |= BIT_ULL(mconf->mt76.idx);
|
||||
mvif->phy->omac_mask |= BIT_ULL(mconf->mt76.omac_idx);
|
||||
|
||||
idx = MT792x_WTBL_RESERVED - mconf->mt76.idx;
|
||||
|
||||
INIT_LIST_HEAD(&mlink->wcid.poll_list);
|
||||
mlink->wcid.idx = idx;
|
||||
mlink->wcid.phy_idx = mconf->mt76.band_idx;
|
||||
mlink->wcid.hw_key_idx = -1;
|
||||
mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_wcid_init(&mlink->wcid);
|
||||
mt76_wcid_init(&mlink->wcid, 0);
|
||||
|
||||
mt7925_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -395,6 +392,12 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
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;
|
||||
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = idx;
|
||||
@@ -801,12 +804,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) {
|
||||
@@ -837,6 +840,7 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
u8 link_id = link_sta->link_id;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_sta *msta;
|
||||
struct mt76_wcid *wcid;
|
||||
int ret, idx;
|
||||
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
@@ -847,14 +851,22 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
return -ENOSPC;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
INIT_LIST_HEAD(&mlink->wcid.poll_list);
|
||||
mt76_wcid_init(&mlink->wcid, 0);
|
||||
mlink->wcid.sta = 1;
|
||||
mlink->wcid.idx = idx;
|
||||
mlink->wcid.phy_idx = mconf->mt76.band_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));
|
||||
|
||||
ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
if (ret)
|
||||
@@ -866,9 +878,14 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, link_id);
|
||||
|
||||
/* should update bss info before STA add */
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls)
|
||||
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
|
||||
link_conf, link_sta, false);
|
||||
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);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mld(vif) &&
|
||||
link_sta == mlink->pri_link) {
|
||||
@@ -904,7 +921,6 @@ 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;
|
||||
struct mt76_wcid *wcid;
|
||||
unsigned int link_id;
|
||||
int err = 0;
|
||||
|
||||
@@ -921,14 +937,6 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
wcid = &mlink->wcid;
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);
|
||||
mt76_wcid_init(wcid);
|
||||
ewma_avg_signal_init(&mlink->avg_ack_signal);
|
||||
memset(mlink->airtime_ac, 0,
|
||||
sizeof(msta->deflink.airtime_ac));
|
||||
}
|
||||
|
||||
msta->valid_links |= BIT(link_id);
|
||||
@@ -1141,8 +1149,7 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
|
||||
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, false);
|
||||
mt792x_mac_link_bss_remove(dev, mconf, mlink);
|
||||
}
|
||||
|
||||
spin_lock_bh(&mdev->sta_poll_lock);
|
||||
@@ -1185,7 +1192,6 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
if (link_sta != mlink->pri_link) {
|
||||
mt76_wcid_cleanup(mdev, wcid);
|
||||
mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);
|
||||
mt76_wcid_mask_clear(mdev->wcid_phy_mask, wcid->idx);
|
||||
}
|
||||
|
||||
if (msta->deflink_id == link_id)
|
||||
@@ -1200,12 +1206,45 @@ void mt7925_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;
|
||||
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 = {
|
||||
.hdr = {
|
||||
.omac_idx = 0,
|
||||
.band_idx = 0,
|
||||
},
|
||||
.tlv = {
|
||||
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
|
||||
.len = cpu_to_le16(sizeof(struct req_tlv)),
|
||||
.active = true,
|
||||
},
|
||||
};
|
||||
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_set_dbdc(&dev->mphy, false);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
@@ -1250,22 +1289,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,
|
||||
params->buf_size);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, true);
|
||||
mt7925_mcu_uni_rx_ba(dev, vif, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_rx_ba(dev, vif, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7925_mcu_uni_tx_ba(dev, params, true);
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
@@ -1274,7 +1313,7 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
@@ -1895,6 +1934,13 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7925_mcu_set_tx(dev, info);
|
||||
|
||||
if (changed & BSS_CHANGED_BSSID) {
|
||||
if (ieee80211_vif_is_mld(vif) &&
|
||||
hweight16(mvif->valid_links) == 2)
|
||||
/* Indicate the secondary setup done */
|
||||
mt7925_mcu_uni_bss_bcnft(dev, info, true);
|
||||
}
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
@@ -1946,6 +1992,8 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
GFP_KERNEL);
|
||||
mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),
|
||||
GFP_KERNEL);
|
||||
if (!mconf || !mlink)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mconfs[link_id] = mconf;
|
||||
@@ -1974,6 +2022,8 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
goto free;
|
||||
|
||||
if (mconf != &mvif->bss_conf) {
|
||||
mt7925_mcu_set_bss_pm(dev, link_conf, true);
|
||||
|
||||
err = mt7925_set_mlo_roc(phy, &mvif->bss_conf,
|
||||
vif->active_links);
|
||||
if (err < 0)
|
||||
@@ -2071,18 +2121,16 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
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,
|
||||
mt7925_mcu_add_bss_info(&dev->phy, NULL, link_conf,
|
||||
NULL, false);
|
||||
} else {
|
||||
mconf = &mvif->bss_conf;
|
||||
|
||||
@@ -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;
|
||||
@@ -123,10 +122,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_regval);
|
||||
int mt7925_mcu_update_arp_filter(struct mt76_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct ieee80211_vif *mvif = container_of((void *)link_conf->vif,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
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);
|
||||
@@ -166,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 {
|
||||
@@ -221,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 {
|
||||
@@ -276,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)
|
||||
@@ -306,7 +303,7 @@ 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)
|
||||
@@ -343,6 +340,51 @@ static void mt7925_mcu_roc_handle_grant(struct mt792x_dev *dev,
|
||||
jiffies + msecs_to_jiffies(duration));
|
||||
}
|
||||
|
||||
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) {
|
||||
if (basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE &&
|
||||
basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)
|
||||
/* success */
|
||||
dev->hif_idle = true;
|
||||
else
|
||||
/* busy */
|
||||
/* invalid */
|
||||
dev->hif_idle = false;
|
||||
} 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)
|
||||
{
|
||||
@@ -388,7 +430,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;
|
||||
@@ -489,6 +531,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;
|
||||
@@ -530,11 +575,11 @@ 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 mt76_wcid *wcid,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx)
|
||||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
|
||||
struct sta_rec_ba_uni *ba;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
@@ -562,28 +607,60 @@ mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
|
||||
|
||||
/** starec & wtbl **/
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct mt76_wcid *wcid;
|
||||
u8 link_id, ret;
|
||||
|
||||
if (enable && !params->amsdu)
|
||||
msta->deflink.wcid.amsdu = false;
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
wcid = &mlink->wcid;
|
||||
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, true);
|
||||
if (enable && !params->amsdu)
|
||||
mlink->wcid.amsdu = false;
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
|
||||
enable, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct mt76_wcid *wcid;
|
||||
u8 link_id, ret;
|
||||
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, false);
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
wcid = &mlink->wcid;
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
|
||||
enable, false);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
||||
@@ -638,7 +715,7 @@ 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))
|
||||
if (clc->idx >= ARRAY_SIZE(phy->clc))
|
||||
break;
|
||||
|
||||
/* do not init buf again if chip reset triggered */
|
||||
@@ -823,7 +900,7 @@ mt7925_mcu_get_nic_capability(struct mt792x_dev *dev)
|
||||
mt7925_mcu_parse_phy_cap(dev, tlv->data);
|
||||
break;
|
||||
case MT_NIC_CAP_CHIP_CAP:
|
||||
memcpy(&dev->phy.chip_cap, (void *)skb->data, sizeof(u64));
|
||||
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);
|
||||
@@ -1153,7 +1230,12 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
u8 rsv[4];
|
||||
} __packed hdr;
|
||||
struct roc_acquire_tlv roc[2];
|
||||
} __packed req;
|
||||
} __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)
|
||||
@@ -1200,6 +1282,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
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
|
||||
@@ -1215,7 +1299,7 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
}
|
||||
|
||||
return mt76_mcu_send_msg(&mvif->phy->dev->mt76, MCU_UNI_CMD(ROC),
|
||||
&req, sizeof(req), false);
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
@@ -1264,7 +1348,7 @@ int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
}
|
||||
|
||||
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_bss_conf *mconf,
|
||||
@@ -1294,7 +1378,7 @@ int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
|
||||
&req, sizeof(req), false);
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_eeprom(struct mt792x_dev *dev)
|
||||
@@ -1357,7 +1441,7 @@ int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
|
||||
&ps_req, sizeof(ps_req), true);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf, bool enable)
|
||||
{
|
||||
@@ -1447,12 +1531,12 @@ mt7925_mcu_set_bss_pm(struct mt792x_dev *dev,
|
||||
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
|
||||
@@ -1770,7 +1854,7 @@ 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 mt76_vif_link *mvif = (struct mt76_vif_link *)info->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
@@ -1783,7 +1867,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
|
||||
CONN_STATE_DISCONNECT;
|
||||
if (info->link_sta)
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif,
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
conn_state, info->newly);
|
||||
if (info->link_sta && info->enable) {
|
||||
@@ -1837,7 +1921,7 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
|
||||
return PTR_ERR(skb);
|
||||
|
||||
if (info->enable)
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif,
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
info->enable, info->newly);
|
||||
|
||||
@@ -1883,6 +1967,7 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
struct mt76_sta_cmd_info info = {
|
||||
.link_sta = link_sta,
|
||||
.vif = vif,
|
||||
.link_conf = &vif->bss_conf,
|
||||
.enable = enable,
|
||||
.cmd = MCU_UNI_CMD(STA_REC_UPDATE),
|
||||
.state = state,
|
||||
@@ -1898,7 +1983,11 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
}
|
||||
info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
|
||||
info.newly = link_sta ? state != MT76_STA_INFO_STATE_ASSOC : true;
|
||||
|
||||
if (link_sta)
|
||||
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
|
||||
else
|
||||
info.newly = state == MT76_STA_INFO_STATE_ASSOC ? false : true;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
err = mt7925_mcu_mlo_sta_cmd(&dev->mphy, &info);
|
||||
@@ -1914,32 +2003,21 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
||||
{
|
||||
#define MT7925_FIF_BIT_CLR BIT(1)
|
||||
#define MT7925_FIF_BIT_SET BIT(0)
|
||||
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 err = 0;
|
||||
int i;
|
||||
|
||||
if (enable) {
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
bss_conf = mt792x_vif_to_bss_conf(vif, i);
|
||||
err = mt7925_mcu_uni_bss_bcnft(dev, bss_conf, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
err = mt7925_mcu_uni_bss_bcnft(dev, &vif->bss_conf, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt7925_mcu_set_rxfilter(dev, 0,
|
||||
MT7925_FIF_BIT_SET,
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
}
|
||||
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
bss_conf = mt792x_vif_to_bss_conf(vif, i);
|
||||
err = mt7925_mcu_set_bss_pm(dev, bss_conf, false);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = mt7925_mcu_set_bss_pm(dev, &vif->bss_conf, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt7925_mcu_set_rxfilter(dev, 0,
|
||||
MT7925_FIF_BIT_CLR,
|
||||
@@ -1976,8 +2054,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;
|
||||
@@ -1991,7 +2067,7 @@ int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
} __packed enable;
|
||||
} __packed req = {
|
||||
.hdr = {
|
||||
.band_idx = mvif->bss_conf.mt76.band_idx,
|
||||
.band_idx = 0,
|
||||
},
|
||||
.enable = {
|
||||
.tag = cpu_to_le16(UNI_SNIFFER_ENABLE),
|
||||
@@ -2050,7 +2126,7 @@ int mt7925_mcu_config_sniffer(struct mt792x_vif *vif,
|
||||
} __packed tlv;
|
||||
} __packed req = {
|
||||
.hdr = {
|
||||
.band_idx = vif->bss_conf.mt76.band_idx,
|
||||
.band_idx = 0,
|
||||
},
|
||||
.tlv = {
|
||||
.tag = cpu_to_le16(UNI_SNIFFER_CONFIG),
|
||||
@@ -2179,11 +2255,27 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
|
||||
req = (struct bss_rlm_tlv *)tlv;
|
||||
req->control_channel = chandef->chan->hw_value;
|
||||
req->center_chan = ieee80211_frequency_to_channel(freq1);
|
||||
req->center_chan2 = ieee80211_frequency_to_channel(freq2);
|
||||
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->band = band;
|
||||
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:
|
||||
@@ -2194,6 +2286,7 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
req->bw = CMD_CBW_8080MHZ;
|
||||
req->center_chan2 = ieee80211_frequency_to_channel(freq2);
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
req->bw = CMD_CBW_160MHZ;
|
||||
@@ -2219,7 +2312,7 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -2235,7 +2328,7 @@ __mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len)
|
||||
return skb;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -2388,7 +2481,7 @@ mt7925_mcu_bss_sec_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
struct mt76_vif *mvif = &mconf->mt76;
|
||||
struct mt76_vif_link *mvif = &mconf->mt76;
|
||||
struct bss_sec_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -2439,7 +2532,7 @@ mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy,
|
||||
&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 *mvif = &mconf->mt76;
|
||||
struct mt76_vif_link *mvif = &mconf->mt76;
|
||||
struct bss_rate_tlv *bmc;
|
||||
struct tlv *tlv;
|
||||
u8 idx = mvif->mcast_rates_idx ?
|
||||
@@ -2463,6 +2556,7 @@ static void
|
||||
mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
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 bss_mld_tlv *mld;
|
||||
@@ -2483,7 +2577,7 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
|
||||
mld->eml_enable = !!(link_conf->vif->cfg.eml_cap &
|
||||
IEEE80211_EML_CAP_EMLSR_SUPP);
|
||||
|
||||
memcpy(mld->mac_addr, link_conf->addr, ETH_ALEN);
|
||||
memcpy(mld->mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2614,7 +2708,7 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
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;
|
||||
|
||||
@@ -2634,7 +2728,7 @@ 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),
|
||||
@@ -2643,14 +2737,12 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy)
|
||||
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;
|
||||
@@ -2686,14 +2778,6 @@ 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++) {
|
||||
@@ -2765,7 +2849,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;
|
||||
@@ -2901,7 +2985,7 @@ mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
|
||||
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;
|
||||
|
||||
@@ -616,7 +616,7 @@ mt7925_mcu_get_cipher(int cipher)
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_dbdc(struct mt76_phy *phy);
|
||||
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,
|
||||
@@ -637,10 +637,13 @@ int mt7925_mcu_set_timing(struct mt792x_phy *phy,
|
||||
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
|
||||
int mt7925_mcu_set_channel_domain(struct mt76_phy *phy);
|
||||
int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable);
|
||||
int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,
|
||||
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_rate_txpower(struct mt76_phy *phy);
|
||||
int mt7925_mcu_update_arp_filter(struct mt76_dev *dev,
|
||||
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
|
||||
|
||||
@@ -27,6 +27,26 @@
|
||||
|
||||
#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,
|
||||
@@ -215,6 +235,7 @@ 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_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);
|
||||
@@ -242,9 +263,11 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
void mt7925_scan_work(struct work_struct *work);
|
||||
|
||||
@@ -442,9 +442,10 @@ 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);
|
||||
@@ -455,14 +456,21 @@ static int mt7925_pci_suspend(struct device *device)
|
||||
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);
|
||||
@@ -506,8 +514,11 @@ static int mt7925_pci_suspend(struct device *device)
|
||||
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;
|
||||
|
||||
@@ -523,8 +534,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;
|
||||
@@ -553,12 +565,19 @@ static int mt7925_pci_resume(struct device *device)
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
|
||||
#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
|
||||
#define MT792x_CHIP_CAP_MLO_EVT_EN BIT(2)
|
||||
#define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3)
|
||||
|
||||
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
|
||||
#define MT792x_BASIC_RATES_TBL 11
|
||||
@@ -116,7 +117,7 @@ struct mt792x_chanctx {
|
||||
};
|
||||
|
||||
struct mt792x_bss_conf {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
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];
|
||||
@@ -133,6 +134,9 @@ struct mt792x_vif {
|
||||
struct mt792x_phy *phy;
|
||||
u16 valid_links;
|
||||
u8 deflink_id;
|
||||
|
||||
struct work_struct csa_work;
|
||||
struct timer_list csa_timer;
|
||||
};
|
||||
|
||||
struct mt792x_phy {
|
||||
@@ -206,6 +210,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;
|
||||
|
||||
@@ -216,6 +222,10 @@ struct mt792x_dev {
|
||||
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;
|
||||
@@ -235,12 +245,15 @@ struct mt792x_dev {
|
||||
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);
|
||||
|
||||
@@ -248,8 +261,10 @@ mt792x_vif_to_link(struct mt792x_vif *mvif, u8 link_id)
|
||||
link_id >= IEEE80211_LINK_UNSPECIFIED)
|
||||
return &mvif->bss_conf;
|
||||
|
||||
return rcu_dereference_protected(mvif->link_conf[link_id],
|
||||
lockdep_is_held(&mvif->phy->dev->mt76.mutex));
|
||||
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 *
|
||||
@@ -364,6 +379,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,
|
||||
@@ -414,6 +430,7 @@ 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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -147,7 +151,8 @@ void mt792x_mac_link_bss_remove(struct mt792x_dev *dev,
|
||||
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, &mlink->wcid, false);
|
||||
mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mconf->mt76,
|
||||
&mlink->wcid, false);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
@@ -284,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)
|
||||
{
|
||||
@@ -325,6 +338,11 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mctx->bss_conf = NULL;
|
||||
mvif->bss_conf.mt76.ctx = NULL;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (vif->bss_conf.csa_active) {
|
||||
del_timer_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx);
|
||||
|
||||
@@ -614,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;
|
||||
@@ -646,6 +665,7 @@ 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);
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
|
||||
if (dev->pm.enable)
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
@@ -911,6 +931,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>");
|
||||
|
||||
@@ -153,7 +153,7 @@ struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
|
||||
return NULL;
|
||||
|
||||
link = container_of(wcid, struct mt792x_link_sta, wcid);
|
||||
sta = container_of(link, struct mt792x_sta, deflink);
|
||||
sta = link->sta;
|
||||
if (!sta->vif)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -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,
|
||||
@@ -524,16 +526,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);
|
||||
@@ -558,6 +556,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);
|
||||
|
||||
@@ -601,7 +616,7 @@ 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_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct seq_file *s = data;
|
||||
u8 ac;
|
||||
|
||||
@@ -621,15 +636,15 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
|
||||
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->vif->deflink.mt76.wmm_idx, ac, qlen);
|
||||
}
|
||||
}
|
||||
|
||||
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 },
|
||||
@@ -685,6 +700,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),
|
||||
@@ -698,19 +722,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;
|
||||
@@ -785,20 +819,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);
|
||||
@@ -812,17 +846,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;
|
||||
}
|
||||
@@ -899,7 +929,7 @@ 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 ra_rate phy = {};
|
||||
char buf[100];
|
||||
int ret;
|
||||
|
||||
@@ -25,17 +25,108 @@ 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;
|
||||
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 0x7990:
|
||||
default:
|
||||
return MT7996_EEPROM_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:
|
||||
*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 +142,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 +157,68 @@ mt7996_eeprom_load_default(struct mt7996_dev *dev)
|
||||
|
||||
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;
|
||||
u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
|
||||
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;
|
||||
if (free_block_num >= 59) {
|
||||
use_default = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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 +227,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 +287,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;
|
||||
@@ -203,15 +305,12 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
|
||||
|
||||
mphy->antenna_mask = BIT(nss) - 1;
|
||||
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 +319,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -14,6 +14,28 @@
|
||||
#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 = 16,
|
||||
@@ -27,20 +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),
|
||||
.beacon_int_min_gcd = 100,
|
||||
}
|
||||
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,
|
||||
@@ -82,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 &&
|
||||
@@ -177,28 +197,32 @@ 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);
|
||||
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;
|
||||
@@ -330,28 +354,88 @@ 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);
|
||||
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->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);
|
||||
|
||||
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||
mt7996_dfs_init_radar_detector(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;
|
||||
@@ -363,14 +447,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;
|
||||
@@ -387,57 +472,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_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
|
||||
@@ -456,6 +515,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) |
|
||||
@@ -554,18 +617,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) {
|
||||
@@ -573,7 +633,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;
|
||||
|
||||
@@ -604,7 +664,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,
|
||||
@@ -618,14 +678,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;
|
||||
|
||||
@@ -637,24 +689,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)
|
||||
@@ -881,6 +923,76 @@ static void mt7996_wed_rro_work(struct work_struct *work)
|
||||
#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 0x7990:
|
||||
if (val & MT_PAD_GPIO_2ADIE_TBTC)
|
||||
var_type = MT7996_VAR_TYPE_233;
|
||||
else
|
||||
var_type = MT7996_VAR_TYPE_444;
|
||||
break;
|
||||
case 0x7992:
|
||||
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;
|
||||
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;
|
||||
@@ -896,6 +1008,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;
|
||||
@@ -910,6 +1026,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;
|
||||
@@ -960,10 +1080,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
|
||||
@@ -993,10 +1115,10 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
|
||||
|
||||
if (is_mt7996(phy->mt76->dev))
|
||||
c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
|
||||
(IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 * non_2g);
|
||||
else
|
||||
c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 |
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5;
|
||||
(IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 * non_2g);
|
||||
|
||||
elem->phy_cap_info[4] |= c;
|
||||
|
||||
@@ -1022,8 +1144,9 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
|
||||
|
||||
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)
|
||||
@@ -1035,8 +1158,10 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1077,6 +1202,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;
|
||||
@@ -1116,8 +1244,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 |
|
||||
@@ -1140,12 +1267,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,
|
||||
@@ -1187,7 +1314,9 @@ 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->phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
@@ -1202,13 +1331,20 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
|
||||
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);
|
||||
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_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] |=
|
||||
@@ -1230,21 +1366,20 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
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] =
|
||||
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);
|
||||
|
||||
val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) |
|
||||
@@ -1270,8 +1405,13 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
|
||||
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_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ;
|
||||
|
||||
if (band != NL80211_BAND_6GHZ)
|
||||
@@ -1330,6 +1470,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;
|
||||
@@ -1351,28 +1492,27 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||
|
||||
mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
|
||||
|
||||
ret = mt7996_register_phy(dev, MT_BAND1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7996_register_phy(dev, MT_BAND2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7996_thermal_init(&dev->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
|
||||
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;
|
||||
|
||||
@@ -1391,8 +1531,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||
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);
|
||||
|
||||
@@ -72,7 +72,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
||||
if (!sta->vif)
|
||||
return NULL;
|
||||
|
||||
return &sta->vif->sta.wcid;
|
||||
return &sta->vif->deflink.sta.wcid;
|
||||
}
|
||||
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
|
||||
@@ -182,7 +182,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
rssi[3] = to_rssi(GENMASK(31, 14), val);
|
||||
|
||||
msta->ack_signal =
|
||||
mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
|
||||
mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
|
||||
|
||||
ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
|
||||
}
|
||||
@@ -196,7 +196,7 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
u32 addr;
|
||||
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5);
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->deflink.sta.wcid.idx, 5);
|
||||
if (enable)
|
||||
mt76_set(dev, addr, BIT(5));
|
||||
else
|
||||
@@ -478,11 +478,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
|
||||
|
||||
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);
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
|
||||
}
|
||||
|
||||
status->freq = mphy->chandef.chan->center_freq;
|
||||
@@ -679,14 +675,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;
|
||||
@@ -819,12 +826,13 @@ 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 *mvif;
|
||||
u16 tx_count = 15;
|
||||
u32 val;
|
||||
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
@@ -832,7 +840,7 @@ 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;
|
||||
mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
|
||||
if (mvif) {
|
||||
omac_idx = mvif->omac_idx;
|
||||
wmm_idx = mvif->wmm_idx;
|
||||
@@ -886,8 +894,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
|
||||
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;
|
||||
|
||||
@@ -897,7 +906,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
|
||||
|
||||
if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
|
||||
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;
|
||||
@@ -977,7 +985,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
if (vif) {
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
|
||||
txp->fw.bss_idx = mvif->mt76.idx;
|
||||
txp->fw.bss_idx = mvif->deflink.mt76.idx;
|
||||
}
|
||||
|
||||
txp->fw.token = cpu_to_le16(id);
|
||||
@@ -1138,11 +1146,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
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);
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
|
||||
continue;
|
||||
} else if (info & MT_TXFREE_INFO_HEADER) {
|
||||
u32 tx_retries = 0, tx_failed = 0;
|
||||
@@ -1368,10 +1372,7 @@ static void mt7996_mac_add_txs(struct mt7996_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();
|
||||
@@ -1593,7 +1594,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;
|
||||
@@ -1738,19 +1739,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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -177,7 +177,7 @@ 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;
|
||||
@@ -605,6 +605,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,
|
||||
@@ -618,9 +619,12 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
.rx_check = mt7996_rx_check,
|
||||
.rx_poll_complete = mt7996_rx_poll_complete,
|
||||
.sta_add = mt7996_mac_sta_add,
|
||||
.sta_event = mt7996_mac_sta_event,
|
||||
.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;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#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)
|
||||
@@ -34,13 +35,32 @@
|
||||
#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 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 MT7996_EEPROM_SIZE 7680
|
||||
#define MT7996_EEPROM_BLOCK_SIZE 16
|
||||
#define MT7996_TOKEN_SIZE 16384
|
||||
@@ -48,6 +68,12 @@
|
||||
|
||||
#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
|
||||
@@ -95,6 +121,22 @@ 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 mt7996_fem_type {
|
||||
MT7996_FEM_EXT,
|
||||
MT7996_FEM_INT,
|
||||
MT7996_FEM_MIX,
|
||||
};
|
||||
|
||||
enum mt7996_txq_id {
|
||||
MT7996_TXQ_FWDL = 16,
|
||||
MT7996_TXQ_MCU_WM,
|
||||
@@ -164,8 +206,8 @@ struct mt7996_sta {
|
||||
} twt;
|
||||
};
|
||||
|
||||
struct mt7996_vif {
|
||||
struct mt76_vif mt76; /* must be first */
|
||||
struct mt7996_vif_link {
|
||||
struct mt76_vif_link mt76; /* must be first */
|
||||
|
||||
struct mt7996_sta sta;
|
||||
struct mt7996_phy *phy;
|
||||
@@ -174,6 +216,11 @@ struct mt7996_vif {
|
||||
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;
|
||||
@@ -211,8 +258,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;
|
||||
@@ -232,11 +277,15 @@ struct mt7996_phy {
|
||||
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
int txpower;
|
||||
|
||||
struct mt76_mib_stats mib;
|
||||
struct mt76_channel_state state_ts;
|
||||
|
||||
u16 orig_chainmask;
|
||||
|
||||
bool has_aux_rx;
|
||||
bool counter_reset;
|
||||
};
|
||||
|
||||
struct mt7996_dev {
|
||||
@@ -245,6 +294,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];
|
||||
@@ -329,6 +382,10 @@ struct mt7996_dev {
|
||||
spinlock_t reg_lock;
|
||||
|
||||
u8 wtbl_size_group;
|
||||
struct {
|
||||
u8 type:4;
|
||||
u8 fem:4;
|
||||
} var;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -360,14 +417,6 @@ enum mt7996_rdd_cmd {
|
||||
RDD_IRQ_OFF,
|
||||
};
|
||||
|
||||
static inline struct mt7996_phy *
|
||||
mt7996_hw_phy(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76_phy *phy = hw->priv;
|
||||
|
||||
return phy->priv;
|
||||
}
|
||||
|
||||
static inline struct mt7996_dev *
|
||||
mt7996_hw_dev(struct ieee80211_hw *hw)
|
||||
{
|
||||
@@ -405,14 +454,69 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
|
||||
if (is_mt7992(&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_BAND0 || band == MT_BAND2;
|
||||
return band <= MT_BAND2;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt7996_has_background_radar(struct mt7996_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7990:
|
||||
if (dev->var.type == MT7996_VAR_TYPE_233)
|
||||
return false;
|
||||
break;
|
||||
case 0x7992:
|
||||
if (dev->var.type == MT7992_VAR_TYPE_23)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline struct mt7996_phy *
|
||||
mt7996_band_phy(struct mt7996_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
struct mt76_phy *mphy;
|
||||
|
||||
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;
|
||||
@@ -424,6 +528,12 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
|
||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
|
||||
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,
|
||||
@@ -439,29 +549,33 @@ 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_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_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, int enable);
|
||||
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enable, bool newly);
|
||||
struct mt76_vif_link *mlink,
|
||||
struct ieee80211_sta *sta, int conn_state, bool newly);
|
||||
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool add);
|
||||
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,
|
||||
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,
|
||||
@@ -470,13 +584,14 @@ 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 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_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);
|
||||
@@ -488,7 +603,8 @@ 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);
|
||||
@@ -511,6 +627,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)
|
||||
{
|
||||
@@ -575,6 +692,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
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);
|
||||
int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum mt76_sta_event ev);
|
||||
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);
|
||||
@@ -602,7 +721,7 @@ 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,
|
||||
|
||||
@@ -175,6 +175,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))
|
||||
@@ -660,8 +663,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
|
||||
|
||||
168
drivers/net/wireless/mediatek/mt76/scan.c
Normal file
168
drivers/net/wireless/mediatek/mt76/scan.c
Normal file
@@ -0,0 +1,168 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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))
|
||||
mt76_tx(phy, NULL, mvif->wcid, skb);
|
||||
else
|
||||
ieee80211_free_txskb(phy->hw, skb);
|
||||
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);
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -489,7 +489,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
|
||||
do {
|
||||
if (test_bit(MT76_RESET, &phy->state) || phy->offchannel)
|
||||
return -EBUSY;
|
||||
break;
|
||||
|
||||
if (stop || mt76_txq_stopped(q))
|
||||
break;
|
||||
@@ -522,24 +522,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) || phy->offchannel)
|
||||
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;
|
||||
@@ -549,6 +541,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;
|
||||
@@ -578,7 +580,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (qid >= 4 || phy->offchannel)
|
||||
if (qid >= 4)
|
||||
return;
|
||||
|
||||
local_bh_disable();
|
||||
@@ -680,9 +682,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);
|
||||
}
|
||||
@@ -693,6 +700,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)
|
||||
@@ -748,9 +756,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user