mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 09:02:21 -04:00
Merge tag 'mt76-next-2026-03-23' of https://github.com/nbd168/wireless
Felix Fietkau says: =================== mt76 patches for 7.1 - fixes - mt7996/mt7925 MLO fixes/improvements - mt7996 NPU support - mt7996 external EEPROM support =================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -88,6 +88,9 @@ void mt76_change_chanctx(struct ieee80211_hw *hw,
|
||||
IEEE80211_CHANCTX_CHANGE_RADAR)))
|
||||
return;
|
||||
|
||||
if (phy->roc_vif)
|
||||
mt76_abort_roc(phy);
|
||||
|
||||
cancel_delayed_work_sync(&phy->mac_work);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
@@ -155,8 +158,6 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -173,15 +174,8 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
if (!mlink)
|
||||
goto out;
|
||||
|
||||
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
|
||||
rcu_assign_pointer(mvif->link[link_id], NULL);
|
||||
|
||||
dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
|
||||
mlink->ctx = NULL;
|
||||
|
||||
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
@@ -254,6 +248,8 @@ int mt76_switch_vif_chanctx(struct ieee80211_hw *hw,
|
||||
continue;
|
||||
|
||||
mlink->ctx = vifs->new_ctx;
|
||||
if (mlink->beacon_mon_interval)
|
||||
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -324,9 +320,11 @@ void mt76_roc_complete(struct mt76_phy *phy)
|
||||
|
||||
if (mlink)
|
||||
mlink->mvif->roc_phy = NULL;
|
||||
if (phy->main_chandef.chan &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
if (phy->chanctx && phy->main_chandef.chan && phy->offchannel &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state)) {
|
||||
__mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
mt76_offchannel_notify(phy, false);
|
||||
}
|
||||
mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);
|
||||
phy->roc_vif = NULL;
|
||||
phy->roc_link = NULL;
|
||||
@@ -364,12 +362,15 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct mt76_phy *phy = hw->priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt76_vif_link *mlink;
|
||||
bool offchannel;
|
||||
int ret = 0;
|
||||
|
||||
phy = dev->band_phys[chan->band];
|
||||
if (!phy)
|
||||
return -EINVAL;
|
||||
|
||||
cancel_delayed_work_sync(&phy->mac_work);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (phy->roc_vif || dev->scan.phy == phy ||
|
||||
@@ -387,8 +388,18 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
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);
|
||||
|
||||
offchannel = mt76_offchannel_chandef(phy, chan, &chandef);
|
||||
if (offchannel)
|
||||
mt76_offchannel_notify(phy, true);
|
||||
ret = __mt76_set_channel(phy, &chandef, offchannel);
|
||||
if (ret) {
|
||||
mlink->mvif->roc_phy = NULL;
|
||||
phy->roc_vif = NULL;
|
||||
phy->roc_link = NULL;
|
||||
mt76_put_vif_phy_link(phy, vif, mlink);
|
||||
goto out;
|
||||
}
|
||||
ieee80211_ready_on_channel(hw);
|
||||
ieee80211_queue_delayed_work(phy->hw, &phy->roc_work,
|
||||
msecs_to_jiffies(duration));
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include "mt76.h"
|
||||
#include "dma.h"
|
||||
#include "mt76_connac.h"
|
||||
|
||||
static struct mt76_txwi_cache *
|
||||
mt76_alloc_txwi(struct mt76_dev *dev)
|
||||
@@ -188,16 +189,18 @@ mt76_dma_queue_magic_cnt_init(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
Q_WRITE(q, desc_base, q->desc_dma);
|
||||
if ((q->flags & MT_QFLAG_WED_RRO_EN) && !mt76_npu_device_active(dev))
|
||||
if ((q->flags & MT_QFLAG_WED_RRO_EN) &&
|
||||
(!is_mt7992(dev) || !mt76_npu_device_active(dev)))
|
||||
Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
|
||||
else
|
||||
Q_WRITE(q, ring_size, q->ndesc);
|
||||
|
||||
if (mt76_queue_is_npu_tx(q)) {
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
}
|
||||
|
||||
Q_WRITE(q, desc_base, q->desc_dma);
|
||||
q->head = Q_READ(q, dma_idx);
|
||||
q->tail = q->head;
|
||||
}
|
||||
@@ -663,6 +666,8 @@ mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
if (!t)
|
||||
goto free_skb;
|
||||
|
||||
t->phy_idx = phy->band_idx;
|
||||
t->qid = qid;
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
skb->prev = skb->next = NULL;
|
||||
@@ -874,7 +879,16 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
if (!mt76_queue_is_wed_rro(q))
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
mt76_queue_is_wed_rro(q))
|
||||
continue;
|
||||
|
||||
if (mt76_npu_device_active(dev) &&
|
||||
mt76_queue_is_wed_rro(q))
|
||||
continue;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_rxdmad_c(q) &&
|
||||
!mt76_queue_is_wed_rro_ind(q))
|
||||
mt76_put_page_pool_buf(buf, false);
|
||||
} while (1);
|
||||
|
||||
@@ -915,6 +929,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
mt76_queue_is_wed_rro(q))
|
||||
return;
|
||||
|
||||
if (mt76_npu_device_active(dev) &&
|
||||
mt76_queue_is_wed_rro(q))
|
||||
return;
|
||||
|
||||
if (mt76_queue_is_npu_txfree(q))
|
||||
return;
|
||||
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
if (mt76_queue_is_npu(q))
|
||||
mt76_npu_fill_rx_queue(dev, q);
|
||||
@@ -1168,10 +1189,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
||||
mt76_for_each_q_rx(dev, i) {
|
||||
struct mt76_queue *q = &dev->q_rx[i];
|
||||
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
mt76_queue_is_wed_rro(q))
|
||||
continue;
|
||||
|
||||
netif_napi_del(&dev->napi[i]);
|
||||
mt76_dma_rx_cleanup(dev, q);
|
||||
|
||||
|
||||
@@ -174,7 +174,9 @@ void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
static inline void
|
||||
mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
dev->queue_ops->reset_q(dev, q, true);
|
||||
bool reset_idx = q && !mt76_queue_is_npu_tx(q);
|
||||
|
||||
dev->queue_ops->reset_q(dev, q, reset_idx);
|
||||
if (mtk_wed_device_active(&dev->mmio.wed))
|
||||
mt76_wed_dma_setup(dev, q, true);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include "mt76.h"
|
||||
#include "mt76_connac.h"
|
||||
|
||||
enum mt76_sku_type {
|
||||
MT76_SKU_RATE,
|
||||
MT76_SKU_BACKOFF,
|
||||
MT76_SKU_BACKOFF_BF_OFFSET,
|
||||
};
|
||||
|
||||
static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
|
||||
{
|
||||
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_find_channel_node);
|
||||
|
||||
|
||||
static s8
|
||||
mt76_get_txs_delta(struct device_node *np, u8 nss)
|
||||
{
|
||||
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss)
|
||||
return be32_to_cpu(val[nss - 1]);
|
||||
}
|
||||
|
||||
static inline u8 mt76_backoff_n_chains(struct mt76_dev *dev, u8 idx)
|
||||
{
|
||||
/* 0:1T1ss, 1:2T1ss, ..., 14:5T5ss */
|
||||
static const u8 connac3_table[] = {
|
||||
1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
|
||||
static const u8 connac2_table[] = {
|
||||
1, 2, 3, 4, 2, 3, 4, 3, 4, 4, 0, 0, 0, 0, 0};
|
||||
|
||||
if (idx >= ARRAY_SIZE(connac3_table))
|
||||
return 0;
|
||||
|
||||
return is_mt799x(dev) ? connac3_table[idx] : connac2_table[idx];
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
|
||||
s8 target_power, s8 nss_delta, s8 *max_power)
|
||||
mt76_apply_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
|
||||
const s8 *data, s8 target_power, s8 nss_delta,
|
||||
s8 *max_power, int n_chains, enum mt76_sku_type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
|
||||
return;
|
||||
|
||||
for (i = 0; i < pwr_len; i++) {
|
||||
pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
|
||||
u8 backoff_chain_idx = i;
|
||||
int backoff_n_chains;
|
||||
s8 backoff_delta;
|
||||
s8 delta;
|
||||
|
||||
switch (type) {
|
||||
case MT76_SKU_RATE:
|
||||
delta = 0;
|
||||
backoff_delta = 0;
|
||||
backoff_n_chains = 0;
|
||||
break;
|
||||
case MT76_SKU_BACKOFF_BF_OFFSET:
|
||||
backoff_chain_idx += 1;
|
||||
fallthrough;
|
||||
case MT76_SKU_BACKOFF:
|
||||
delta = mt76_tx_power_path_delta(n_chains);
|
||||
backoff_n_chains = mt76_backoff_n_chains(dev, backoff_chain_idx);
|
||||
backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
pwr[i] = min_t(s8, target_power + delta - backoff_delta, data[i] + nss_delta);
|
||||
|
||||
/* used for padding, doesn't need to be considered */
|
||||
if (data[i] >= S8_MAX - 1)
|
||||
continue;
|
||||
|
||||
/* only consider backoff value for the configured chain number */
|
||||
if (type != MT76_SKU_RATE && n_chains != backoff_n_chains)
|
||||
continue;
|
||||
|
||||
*max_power = max(*max_power, pwr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
|
||||
const s8 *data, size_t len, s8 target_power,
|
||||
s8 nss_delta)
|
||||
mt76_apply_multi_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
|
||||
s8 pwr_num, const s8 *data, size_t len,
|
||||
s8 target_power, s8 nss_delta, s8 *max_power,
|
||||
int n_chains, enum mt76_sku_type type)
|
||||
{
|
||||
static const int connac2_backoff_ru_idx = 2;
|
||||
int i, cur;
|
||||
s8 max_power = -128;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
|
||||
if (len < pwr_len + 1)
|
||||
break;
|
||||
|
||||
mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
|
||||
target_power, nss_delta, &max_power);
|
||||
/* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS
|
||||
* corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss,
|
||||
* 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss).
|
||||
*
|
||||
* For beamforming tables:
|
||||
* - In connac2, beamforming entries for BW20~BW160 and OFDM
|
||||
* do not include 1T1ss.
|
||||
* - In connac3, beamforming entries for BW20~BW160 and RU
|
||||
* include 1T1ss, but OFDM beamforming does not include 1T1ss.
|
||||
*
|
||||
* Non-beamforming and RU entries for both connac2 and connac3
|
||||
* include 1T1ss.
|
||||
*/
|
||||
if (!is_mt799x(dev) && type == MT76_SKU_BACKOFF &&
|
||||
i > connac2_backoff_ru_idx)
|
||||
type = MT76_SKU_BACKOFF_BF_OFFSET;
|
||||
|
||||
mt76_apply_array_limit(dev, pwr + pwr_len * i, pwr_len, data + 1,
|
||||
target_power, nss_delta, max_power,
|
||||
n_chains, type);
|
||||
if (--cur > 0)
|
||||
continue;
|
||||
|
||||
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
|
||||
struct device_node *np;
|
||||
const s8 *val;
|
||||
char name[16];
|
||||
u32 mcs_rates = dev->drv->mcs_rates;
|
||||
u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
|
||||
char band;
|
||||
size_t len;
|
||||
s8 max_power = 0;
|
||||
s8 max_power_backoff = -127;
|
||||
s8 max_power = -127;
|
||||
s8 txs_delta;
|
||||
int n_chains = hweight16(phy->chainmask);
|
||||
s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains);
|
||||
|
||||
if (!mcs_rates)
|
||||
mcs_rates = 10;
|
||||
|
||||
memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
|
||||
memset(&dest->path, 0, sizeof(dest->path));
|
||||
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
|
||||
txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
|
||||
|
||||
val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
|
||||
mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
|
||||
target_power, txs_delta, &max_power);
|
||||
mt76_apply_array_limit(dev, dest->cck, ARRAY_SIZE(dest->cck), val,
|
||||
target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "rates-ofdm",
|
||||
&len, ARRAY_SIZE(dest->ofdm));
|
||||
mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
|
||||
target_power, txs_delta, &max_power);
|
||||
val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
|
||||
mt76_apply_array_limit(dev, dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
|
||||
target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
|
||||
mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
|
||||
ARRAY_SIZE(dest->mcs), val, len,
|
||||
target_power, txs_delta);
|
||||
val = mt76_get_of_array_s8(np, "rates-mcs", &len, ARRAY_SIZE(dest->mcs[0]) + 1);
|
||||
mt76_apply_multi_array_limit(dev, dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
|
||||
ARRAY_SIZE(dest->mcs), val, len, target_power,
|
||||
txs_delta, &max_power, n_chains, MT76_SKU_RATE);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
|
||||
mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
|
||||
ARRAY_SIZE(dest->ru), val, len,
|
||||
target_power, txs_delta);
|
||||
val = mt76_get_of_array_s8(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
|
||||
mt76_apply_multi_array_limit(dev, dest->ru[0], ARRAY_SIZE(dest->ru[0]),
|
||||
ARRAY_SIZE(dest->ru), val, len, target_power,
|
||||
txs_delta, &max_power, n_chains, MT76_SKU_RATE);
|
||||
|
||||
max_power_backoff = max_power;
|
||||
val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));
|
||||
mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
|
||||
target_power_combine, txs_delta, &max_power_backoff);
|
||||
mt76_apply_array_limit(dev, dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
|
||||
target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));
|
||||
mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
|
||||
target_power_combine, txs_delta, &max_power_backoff);
|
||||
mt76_apply_array_limit(dev, dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
|
||||
target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));
|
||||
mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
|
||||
target_power_combine, txs_delta, &max_power_backoff);
|
||||
mt76_apply_array_limit(dev, dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
|
||||
target_power, txs_delta, &max_power, n_chains,
|
||||
MT76_SKU_BACKOFF_BF_OFFSET);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);
|
||||
mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
|
||||
ARRAY_SIZE(dest->path.ru), val, len,
|
||||
target_power_combine, txs_delta);
|
||||
mt76_apply_multi_array_limit(dev, dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
|
||||
ARRAY_SIZE(dest->path.ru), val, len, target_power,
|
||||
txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
|
||||
|
||||
val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
|
||||
mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
|
||||
ARRAY_SIZE(dest->path.ru_bf), val, len,
|
||||
target_power_combine, txs_delta);
|
||||
mt76_apply_multi_array_limit(dev, dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
|
||||
ARRAY_SIZE(dest->path.ru_bf), val, len, target_power,
|
||||
txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
|
||||
|
||||
return max_power;
|
||||
}
|
||||
|
||||
@@ -726,6 +726,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
|
||||
INIT_LIST_HEAD(&dev->rxwi_cache);
|
||||
dev->token_size = dev->drv->token_size;
|
||||
INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work);
|
||||
spin_lock_init(&dev->scan_lock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
|
||||
skb_queue_head_init(&dev->rx_skb[i]);
|
||||
@@ -970,6 +971,9 @@ bool mt76_has_tx_pending(struct mt76_phy *phy)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (atomic_read(&phy->mgmt_tx_pending))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_has_tx_pending);
|
||||
@@ -1030,9 +1034,10 @@ int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
|
||||
int timeout = HZ / 5;
|
||||
int ret;
|
||||
|
||||
set_bit(MT76_RESET, &phy->state);
|
||||
|
||||
mt76_worker_disable(&dev->tx_worker);
|
||||
mt76_txq_schedule_pending(phy);
|
||||
|
||||
set_bit(MT76_RESET, &phy->state);
|
||||
wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
|
||||
mt76_update_survey(phy);
|
||||
|
||||
@@ -1716,6 +1721,16 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
|
||||
idr_destroy(&wcid->pktid);
|
||||
|
||||
/* Remove from sta_poll_list to prevent list corruption after reset.
|
||||
* Without this, mt76_reset_device() reinitializes sta_poll_list but
|
||||
* leaves wcid->poll_list with stale pointers, causing list corruption
|
||||
* when mt76_wcid_add_poll() checks list_empty().
|
||||
*/
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
if (!list_empty(&wcid->poll_list))
|
||||
list_del_init(&wcid->poll_list);
|
||||
spin_unlock_bh(&dev->sta_poll_lock);
|
||||
|
||||
spin_lock_bh(&phy->tx_lock);
|
||||
|
||||
if (!list_empty(&wcid->tx_list))
|
||||
@@ -2121,3 +2136,214 @@ u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links)
|
||||
return sel_links;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_select_links);
|
||||
|
||||
struct mt76_offchannel_cb_data {
|
||||
struct mt76_phy *phy;
|
||||
bool offchannel;
|
||||
};
|
||||
|
||||
static void
|
||||
mt76_offchannel_send_nullfunc(struct mt76_offchannel_cb_data *data,
|
||||
struct ieee80211_vif *vif, int link_id)
|
||||
{
|
||||
struct mt76_phy *phy = data->phy;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct mt76_wcid *wcid;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ieee80211_nullfunc_get(phy->hw, vif, link_id, true);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (data->offchannel)
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
|
||||
|
||||
skb->priority = 7;
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
|
||||
|
||||
if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb,
|
||||
phy->main_chandef.chan->band,
|
||||
&sta))
|
||||
return;
|
||||
|
||||
if (sta)
|
||||
wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
else
|
||||
wcid = ((struct mt76_vif_link *)vif->drv_priv)->wcid;
|
||||
|
||||
if (link_id >= 0) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->control.flags &= ~IEEE80211_TX_CTRL_MLO_LINK;
|
||||
info->control.flags |=
|
||||
u32_encode_bits(link_id, IEEE80211_TX_CTRL_MLO_LINK);
|
||||
}
|
||||
|
||||
mt76_tx(phy, sta, wcid, skb);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_offchannel_notify_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_offchannel_cb_data *data = _data;
|
||||
struct mt76_vif_link *mlink;
|
||||
struct mt76_vif_data *mvif;
|
||||
int link_id;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return;
|
||||
|
||||
mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
mvif = mlink->mvif;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif)) {
|
||||
if (mt76_vif_link_phy(mlink) == data->phy) {
|
||||
if (!data->offchannel && mlink->beacon_mon_interval)
|
||||
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
|
||||
mt76_offchannel_send_nullfunc(data, vif, -1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (link_id == mvif->deflink_id)
|
||||
mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
else
|
||||
mlink = rcu_dereference(mvif->link[link_id]);
|
||||
if (!mlink)
|
||||
continue;
|
||||
if (mt76_vif_link_phy(mlink) != data->phy)
|
||||
continue;
|
||||
|
||||
if (!data->offchannel && mlink->beacon_mon_interval)
|
||||
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
|
||||
|
||||
mt76_offchannel_send_nullfunc(data, vif, link_id);
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_offchannel_notify(struct mt76_phy *phy, bool offchannel)
|
||||
{
|
||||
struct mt76_offchannel_cb_data data = {
|
||||
.phy = phy,
|
||||
.offchannel = offchannel,
|
||||
};
|
||||
|
||||
if (!phy->num_sta)
|
||||
return;
|
||||
|
||||
local_bh_disable();
|
||||
ieee80211_iterate_active_interfaces_atomic(phy->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
mt76_offchannel_notify_iter, &data);
|
||||
local_bh_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_offchannel_notify);
|
||||
|
||||
struct mt76_rx_beacon_data {
|
||||
struct mt76_phy *phy;
|
||||
const u8 *bssid;
|
||||
};
|
||||
|
||||
static void mt76_rx_beacon_iter(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_rx_beacon_data *data = _data;
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_vif_data *mvif = mlink->mvif;
|
||||
int link_id;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return;
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
if (link_id == mvif->deflink_id)
|
||||
mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
else
|
||||
mlink = rcu_dereference(mvif->link[link_id]);
|
||||
if (!mlink || !mlink->beacon_mon_interval)
|
||||
continue;
|
||||
|
||||
if (mt76_vif_link_phy(mlink) != data->phy)
|
||||
continue;
|
||||
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (!link_conf)
|
||||
continue;
|
||||
|
||||
if (!ether_addr_equal(link_conf->bssid, data->bssid) &&
|
||||
(!link_conf->nontransmitted ||
|
||||
!ether_addr_equal(link_conf->transmitter_bssid,
|
||||
data->bssid)))
|
||||
continue;
|
||||
|
||||
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_rx_beacon(struct mt76_phy *phy, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
|
||||
struct mt76_rx_beacon_data data = {
|
||||
.phy = phy,
|
||||
.bssid = hdr->addr3,
|
||||
};
|
||||
|
||||
mt76_scan_rx_beacon(phy->dev, phy->chandef.chan);
|
||||
|
||||
if (!phy->num_sta)
|
||||
return;
|
||||
|
||||
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_ONLY_MONITOR))
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(phy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76_rx_beacon_iter, &data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_rx_beacon);
|
||||
|
||||
static void mt76_beacon_mon_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_phy *phy = data;
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_vif_data *mvif = mlink->mvif;
|
||||
int link_id;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return;
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (link_id == mvif->deflink_id)
|
||||
mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
else
|
||||
mlink = rcu_dereference(mvif->link[link_id]);
|
||||
if (!mlink || !mlink->beacon_mon_interval)
|
||||
continue;
|
||||
|
||||
if (mt76_vif_link_phy(mlink) != phy)
|
||||
continue;
|
||||
|
||||
if (time_after(jiffies,
|
||||
READ_ONCE(mlink->beacon_mon_last) +
|
||||
MT76_BEACON_MON_MAX_MISS * mlink->beacon_mon_interval))
|
||||
ieee80211_beacon_loss(vif);
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_beacon_mon_check(struct mt76_phy *phy)
|
||||
{
|
||||
if (phy->offchannel)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(phy->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76_beacon_mon_iter, phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_beacon_mon_check);
|
||||
|
||||
@@ -98,7 +98,7 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
/* orig skb might be needed for retry, mcu_skb_send_msg consumes it */
|
||||
if (orig_skb)
|
||||
skb_get(orig_skb);
|
||||
ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
|
||||
ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, wait_resp ? &seq : NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
FIELD_PREP(MT_QFLAG_WED_RING, _n))
|
||||
#define MT_NPU_Q_TX(_n) __MT_NPU_Q(MT76_WED_Q_TX, _n)
|
||||
#define MT_NPU_Q_RX(_n) __MT_NPU_Q(MT76_WED_Q_RX, _n)
|
||||
#define MT_NPU_Q_TXFREE(_n) (FIELD_PREP(MT_QFLAG_WED_TYPE, MT76_WED_Q_TXFREE) | \
|
||||
FIELD_PREP(MT_QFLAG_WED_RING, _n))
|
||||
|
||||
struct mt76_dev;
|
||||
struct mt76_phy;
|
||||
@@ -362,6 +364,7 @@ enum mt76_wcid_flags {
|
||||
};
|
||||
|
||||
#define MT76_N_WCIDS 1088
|
||||
#define MT76_BEACON_MON_MAX_MISS 7
|
||||
|
||||
/* stored in ieee80211_tx_info::hw_queue */
|
||||
#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
|
||||
@@ -448,6 +451,7 @@ struct mt76_txwi_cache {
|
||||
};
|
||||
|
||||
u8 qid;
|
||||
u8 phy_idx;
|
||||
};
|
||||
|
||||
struct mt76_rx_tid {
|
||||
@@ -540,7 +544,6 @@ struct mt76_driver_ops {
|
||||
u32 survey_flags;
|
||||
u16 txwi_size;
|
||||
u16 token_size;
|
||||
u8 mcs_rates;
|
||||
|
||||
unsigned int link_data_size;
|
||||
|
||||
@@ -831,6 +834,8 @@ struct mt76_vif_link {
|
||||
u8 mcast_rates_idx;
|
||||
u8 beacon_rates_idx;
|
||||
bool offchannel;
|
||||
unsigned long beacon_mon_last;
|
||||
u16 beacon_mon_interval;
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
struct mt76_wcid *wcid;
|
||||
struct mt76_vif_data *mvif;
|
||||
@@ -859,6 +864,8 @@ struct mt76_phy {
|
||||
struct list_head tx_list;
|
||||
struct mt76_queue *q_tx[__MT_TXQ_MAX];
|
||||
|
||||
atomic_t mgmt_tx_pending;
|
||||
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct cfg80211_chan_def main_chandef;
|
||||
bool offchannel;
|
||||
@@ -1002,6 +1009,7 @@ struct mt76_dev {
|
||||
u32 rxfilter;
|
||||
|
||||
struct delayed_work scan_work;
|
||||
spinlock_t scan_lock;
|
||||
struct {
|
||||
struct cfg80211_scan_request *req;
|
||||
struct ieee80211_channel *chan;
|
||||
@@ -1009,6 +1017,8 @@ struct mt76_dev {
|
||||
struct mt76_vif_link *mlink;
|
||||
struct mt76_phy *phy;
|
||||
int chan_idx;
|
||||
bool beacon_wait;
|
||||
bool beacon_received;
|
||||
} scan;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
@@ -1518,6 +1528,7 @@ void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);
|
||||
void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);
|
||||
void mt76_txq_schedule_all(struct mt76_phy *phy);
|
||||
void mt76_txq_schedule_pending(struct mt76_phy *phy);
|
||||
void mt76_tx_worker_run(struct mt76_dev *dev);
|
||||
void mt76_tx_worker(struct mt76_worker *w);
|
||||
void mt76_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
@@ -1596,6 +1607,9 @@ int mt76_get_rate(struct mt76_dev *dev,
|
||||
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_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan);
|
||||
void mt76_rx_beacon(struct mt76_phy *phy, struct sk_buff *skb);
|
||||
void mt76_beacon_mon_check(struct mt76_phy *phy);
|
||||
void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const u8 *mac);
|
||||
void mt76_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
@@ -1649,6 +1663,9 @@ void mt76_npu_txdesc_cleanup(struct mt76_queue *q, int index);
|
||||
int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data);
|
||||
int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
|
||||
u32 direction, u32 i_count_addr,
|
||||
u32 o_status_addr, u32 o_count_addr);
|
||||
#else
|
||||
static inline void mt76_npu_check_ppe(struct mt76_dev *dev,
|
||||
struct sk_buff *skb, u32 info)
|
||||
@@ -1707,6 +1724,13 @@ static inline int mt76_npu_net_setup_tc(struct ieee80211_hw *hw,
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
|
||||
u32 direction, u32 i_count_addr,
|
||||
u32 o_status_addr, u32 o_count_addr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_MT76_NPU */
|
||||
|
||||
static inline bool mt76_npu_device_active(struct mt76_dev *dev)
|
||||
@@ -1775,6 +1799,18 @@ 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);
|
||||
|
||||
static inline bool
|
||||
mt76_offchannel_chandef(struct mt76_phy *phy, struct ieee80211_channel *chan,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
cfg80211_chandef_create(chandef, chan, NL80211_CHAN_HT20);
|
||||
if (phy->main_chandef.chan != chan)
|
||||
return true;
|
||||
|
||||
*chandef = phy->main_chandef;
|
||||
return false;
|
||||
}
|
||||
int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
|
||||
bool offchannel);
|
||||
void mt76_scan_work(struct work_struct *work);
|
||||
@@ -1786,6 +1822,7 @@ 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);
|
||||
void mt76_offchannel_notify(struct mt76_phy *phy, bool offchannel);
|
||||
|
||||
/* usb */
|
||||
static inline bool mt76u_urb_error(struct urb *urb)
|
||||
@@ -1993,6 +2030,14 @@ static inline bool mt76_queue_is_npu_rx(struct mt76_queue *q)
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_npu_txfree(struct mt76_queue *q)
|
||||
{
|
||||
if (q->flags & MT_QFLAG_WED)
|
||||
return false;
|
||||
|
||||
return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
|
||||
}
|
||||
|
||||
struct mt76_txwi_cache *
|
||||
mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
|
||||
int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
|
||||
|
||||
@@ -1167,21 +1167,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
|
||||
|
||||
void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
|
||||
u32 addr;
|
||||
|
||||
addr = mt7615_mac_wtbl_addr(dev, mvif->sta.wcid.idx) + 3 * 4;
|
||||
|
||||
if (enable)
|
||||
mt76_set(dev, addr, MT_WTBL_W3_RTS);
|
||||
else
|
||||
mt76_clear(dev, addr, MT_WTBL_W3_RTS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
|
||||
|
||||
static int
|
||||
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key,
|
||||
|
||||
@@ -583,9 +583,6 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7615_mac_enable_rtscts(dev, vif, info->use_cts_prot);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
mt7615_mcu_add_bss_info(phy, vif, NULL, true);
|
||||
mt7615_mcu_sta_add(phy, vif, NULL, true);
|
||||
@@ -598,6 +595,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
|
||||
|
||||
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7615_mcu_set_protection(phy, vif, info->ht_operation_mode,
|
||||
info->use_cts_prot);
|
||||
|
||||
if (changed & BSS_CHANGED_PS)
|
||||
mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);
|
||||
|
||||
|
||||
@@ -2564,3 +2564,50 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
u8 ht_mode, bool use_cts_prot)
|
||||
{
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
struct {
|
||||
u8 prot_idx;
|
||||
u8 band;
|
||||
u8 rsv[2];
|
||||
|
||||
bool long_nav;
|
||||
bool prot_mm;
|
||||
bool prot_gf;
|
||||
bool prot_bw40;
|
||||
bool prot_rifs;
|
||||
bool prot_bw80;
|
||||
bool prot_bw160;
|
||||
u8 prot_erp_mask;
|
||||
} __packed req = {
|
||||
.prot_idx = 0x2,
|
||||
.band = phy != &dev->phy,
|
||||
};
|
||||
|
||||
switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
|
||||
req.prot_mm = true;
|
||||
req.prot_gf = true;
|
||||
fallthrough;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
||||
req.prot_bw40 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
|
||||
req.prot_gf = true;
|
||||
|
||||
if (use_cts_prot) {
|
||||
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
|
||||
u8 i = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->mt76.omac_idx;
|
||||
|
||||
req.prot_erp_mask = BIT(i);
|
||||
}
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PROTECT_CTRL), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
|
||||
@@ -467,8 +467,6 @@ void mt7615_mac_reset_counters(struct mt7615_phy *phy);
|
||||
void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
|
||||
void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable);
|
||||
void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);
|
||||
void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
void mt7615_mac_sta_poll(struct mt7615_dev *dev);
|
||||
int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
@@ -523,7 +521,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);
|
||||
int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
|
||||
int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
|
||||
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
|
||||
|
||||
int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
u8 ht_mode, bool use_cts_prot);
|
||||
int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *chan, int duration);
|
||||
|
||||
|
||||
@@ -455,8 +455,6 @@ enum mt7615_reg_base {
|
||||
#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)
|
||||
#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20)
|
||||
|
||||
#define MT_WTBL_W3_RTS BIT(22)
|
||||
|
||||
#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)
|
||||
#define MT_WTBL_W5_SHORT_GI_20 BIT(8)
|
||||
#define MT_WTBL_W5_SHORT_GI_40 BIT(9)
|
||||
|
||||
@@ -182,14 +182,20 @@ static inline bool is_mt7920(struct mt76_dev *dev)
|
||||
return mt76_chip(dev) == 0x7920;
|
||||
}
|
||||
|
||||
static inline bool is_mt7902(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7902;
|
||||
}
|
||||
|
||||
static inline bool is_mt7922(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7922;
|
||||
}
|
||||
|
||||
static inline bool is_mt7921(struct mt76_dev *dev)
|
||||
static inline bool is_connac2(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev);
|
||||
return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev) ||
|
||||
is_mt7902(dev);
|
||||
}
|
||||
|
||||
static inline bool is_mt7663(struct mt76_dev *dev)
|
||||
@@ -271,6 +277,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
|
||||
case 0x7961:
|
||||
case 0x7920:
|
||||
case 0x7922:
|
||||
case 0x7902:
|
||||
case 0x7925:
|
||||
case 0x7663:
|
||||
case 0x7622:
|
||||
|
||||
@@ -173,7 +173,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_AMSDU_LAST |
|
||||
@@ -217,7 +217,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
|
||||
u32 last_mask;
|
||||
int i;
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
|
||||
if (is_mt7663(dev) || is_connac2(dev) || is_mt7925(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_MSDU_LAST;
|
||||
@@ -309,7 +309,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
chandef = mvif->ctx ? &mvif->ctx->def : &mphy->chandef;
|
||||
band = chandef->chan->band;
|
||||
|
||||
if (is_mt7921(mphy->dev)) {
|
||||
if (is_connac2(mphy->dev)) {
|
||||
rateidx = ffs(conf->basic_rates) - 1;
|
||||
goto legacy;
|
||||
}
|
||||
@@ -548,7 +548,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
if (!is_mt7921(dev))
|
||||
if (!is_connac2(dev))
|
||||
val |= MT_TXD1_VTA;
|
||||
if (phy_idx || band_idx)
|
||||
val |= MT_TXD1_TGID;
|
||||
@@ -557,7 +557,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
txwi[2] = 0;
|
||||
|
||||
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
|
||||
if (!is_mt7921(dev))
|
||||
if (!is_connac2(dev))
|
||||
val |= MT_TXD3_SW_POWER_MGMT;
|
||||
if (key)
|
||||
val |= MT_TXD3_PROTECT_FRAME;
|
||||
@@ -599,7 +599,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
txwi[6] |= cpu_to_le32(val);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
||||
|
||||
if (!is_mt7921(dev)) {
|
||||
if (!is_connac2(dev)) {
|
||||
u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);
|
||||
|
||||
if (!spe_idx)
|
||||
@@ -831,7 +831,7 @@ mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb
|
||||
};
|
||||
struct ieee80211_radiotap_he_mu *he_mu;
|
||||
|
||||
if (is_mt7921(dev)) {
|
||||
if (is_connac2(dev)) {
|
||||
mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);
|
||||
mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);
|
||||
}
|
||||
@@ -1047,7 +1047,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
|
||||
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
|
||||
gi = FIELD_GET(MT_PRXV_HT_SGI, v0);
|
||||
*mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
if (is_mt7921(dev))
|
||||
if (is_connac2(dev))
|
||||
dcm = !!(idx & MT_PRXV_TX_DCM);
|
||||
else
|
||||
dcm = FIELD_GET(MT_PRXV_DCM, v0);
|
||||
@@ -1153,8 +1153,10 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
return;
|
||||
|
||||
wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
if (!test_and_set_bit(tid, &wcid->ampdu_state))
|
||||
ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||
if (!test_and_set_bit(tid, &wcid->ampdu_state)) {
|
||||
if (ieee80211_start_tx_ba_session(sta, tid, 0))
|
||||
clear_bit(tid, &wcid->ampdu_state);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
|
||||
|
||||
@@ -1207,5 +1209,11 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev)
|
||||
}
|
||||
spin_unlock_bh(&dev->token_lock);
|
||||
idr_destroy(&dev->token);
|
||||
|
||||
for (id = 0; id < __MT_MAX_BAND; id++) {
|
||||
struct mt76_phy *phy = dev->phys[id];
|
||||
if (phy)
|
||||
atomic_set(&phy->mgmt_tx_pending, 0);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include "mt76_connac2_mac.h"
|
||||
#include "mt76_connac_mcu.h"
|
||||
#include "mt792x_regs.h"
|
||||
|
||||
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
|
||||
{
|
||||
@@ -65,7 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
|
||||
int cmd;
|
||||
|
||||
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
|
||||
(is_mt7921(dev) && addr == 0x900000) ||
|
||||
(is_connac2(dev) && addr == 0x900000) ||
|
||||
(is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
|
||||
(is_mt799x(dev) && addr == 0x900000))
|
||||
cmd = MCU_CMD(PATCH_START_REQ);
|
||||
@@ -402,7 +403,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (vif->p2p && !is_mt7921(dev))
|
||||
if (vif->p2p && !is_connac2(dev))
|
||||
conn_type = CONNECTION_P2P_GC;
|
||||
else
|
||||
conn_type = CONNECTION_INFRA_STA;
|
||||
@@ -410,7 +411,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
basic->aid = cpu_to_le16(link_sta->sta->aid);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->p2p && !is_mt7921(dev))
|
||||
if (vif->p2p && !is_connac2(dev))
|
||||
conn_type = CONNECTION_P2P_GO;
|
||||
else
|
||||
conn_type = CONNECTION_INFRA_AP;
|
||||
@@ -874,7 +875,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
struct sta_rec_vht *vht;
|
||||
int len;
|
||||
|
||||
len = is_mt7921(dev) ? sizeof(*vht) : sizeof(*vht) - 4;
|
||||
len = is_connac2(dev) ? sizeof(*vht) : sizeof(*vht) - 4;
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len);
|
||||
vht = (struct sta_rec_vht *)tlv;
|
||||
vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);
|
||||
@@ -885,7 +886,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
/* starec uapsd */
|
||||
mt76_connac_mcu_sta_uapsd(skb, vif, sta);
|
||||
|
||||
if (!is_mt7921(dev))
|
||||
if (!is_connac2(dev))
|
||||
return;
|
||||
|
||||
if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)
|
||||
@@ -1295,8 +1296,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
wtbl_hdr);
|
||||
|
||||
ret = mt76_connac_mcu_sta_wed_update(dev, skb);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);
|
||||
if (ret)
|
||||
@@ -1309,8 +1312,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);
|
||||
|
||||
ret = mt76_connac_mcu_sta_wed_update(dev, skb);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
|
||||
}
|
||||
@@ -1774,7 +1779,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req->ssid_type_ext = n_ssids ? BIT(0) : 0;
|
||||
req->ssids_num = n_ssids;
|
||||
|
||||
duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
|
||||
duration = is_connac2(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
|
||||
/* increase channel time for passive scan */
|
||||
if (!sreq->n_ssids)
|
||||
duration *= 2;
|
||||
@@ -1817,7 +1822,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req->ies_len = cpu_to_le16(sreq->ie_len);
|
||||
}
|
||||
|
||||
if (is_mt7921(phy->dev))
|
||||
if (is_connac2(phy->dev))
|
||||
req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
|
||||
|
||||
memcpy(req->bssid, sreq->bssid, ETH_ALEN);
|
||||
@@ -1893,7 +1898,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
get_random_mask_addr(addr, sreq->mac_addr,
|
||||
sreq->mac_addr_mask);
|
||||
}
|
||||
if (is_mt7921(phy->dev)) {
|
||||
if (is_connac2(phy->dev)) {
|
||||
req->mt7921.bss_idx = mvif->idx;
|
||||
req->mt7921.delay = cpu_to_le32(sreq->delay);
|
||||
}
|
||||
@@ -2033,7 +2038,7 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
|
||||
struct mt76_power_limits *limits,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
int max_power = is_mt7921(dev) ? 127 : 63;
|
||||
int max_power = is_connac2(dev) ? 127 : 63;
|
||||
int i, offset = sizeof(limits->cck);
|
||||
|
||||
memset(sku, max_power, MT_SKU_POWER_LIMIT);
|
||||
@@ -2061,7 +2066,7 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
|
||||
offset += 12;
|
||||
}
|
||||
|
||||
if (!is_mt7921(dev))
|
||||
if (!is_connac2(dev))
|
||||
return;
|
||||
|
||||
/* he */
|
||||
@@ -2117,7 +2122,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
int sku_len, batch_len = is_mt7921(dev) ? 8 : 16;
|
||||
int sku_len, batch_len = is_connac2(dev) ? 8 : 16;
|
||||
static const u8 chan_list_2ghz[] = {
|
||||
1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14
|
||||
@@ -2158,7 +2163,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
if (!limits)
|
||||
return -ENOMEM;
|
||||
|
||||
sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
|
||||
sku_len = is_connac2(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
|
||||
tx_power = 2 * phy->hw->conf.power_level;
|
||||
if (!tx_power)
|
||||
tx_power = 127;
|
||||
@@ -2242,6 +2247,9 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
false);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
/* read a CR to avoid PSE buffer underflow */
|
||||
mt76_connac_mcu_reg_rr(dev, MT_PSE_BASE);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2764,12 +2772,16 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
return PTR_ERR(skb);
|
||||
|
||||
ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_sta_wed_update(dev, skb);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
|
||||
}
|
||||
@@ -3072,7 +3084,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
if ((!is_connac2(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
|
||||
@@ -628,6 +628,13 @@ struct sta_rec_tx_proc {
|
||||
__le32 flag;
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_eml_op {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 link_bitmap;
|
||||
u8 link_ant_num[3];
|
||||
} __packed;
|
||||
|
||||
/* wtbl_rec */
|
||||
|
||||
struct wtbl_req_hdr {
|
||||
@@ -796,6 +803,7 @@ struct wtbl_raw {
|
||||
sizeof(struct sta_rec_he_6g_capa) + \
|
||||
sizeof(struct sta_rec_pn_info) + \
|
||||
sizeof(struct sta_rec_tx_proc) + \
|
||||
sizeof(struct sta_rec_eml_op) + \
|
||||
sizeof(struct tlv) + \
|
||||
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
|
||||
|
||||
@@ -832,6 +840,7 @@ enum {
|
||||
STA_REC_PN_INFO = 0x26,
|
||||
STA_REC_KEY_V3 = 0x27,
|
||||
STA_REC_HDRT = 0x28,
|
||||
STA_REC_EML_OP = 0x29,
|
||||
STA_REC_HDR_TRANS = 0x2B,
|
||||
STA_REC_MAX_NUM
|
||||
};
|
||||
@@ -1308,7 +1317,9 @@ enum {
|
||||
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
|
||||
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
|
||||
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
|
||||
MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
|
||||
MCU_UNI_CMD_RADIO_STATUS = 0x80,
|
||||
MCU_UNI_CMD_MLD = 0x82,
|
||||
MCU_UNI_CMD_SDO = 0x88,
|
||||
};
|
||||
|
||||
@@ -1363,6 +1374,7 @@ enum {
|
||||
UNI_BSS_INFO_BASIC = 0,
|
||||
UNI_BSS_INFO_RA = 1,
|
||||
UNI_BSS_INFO_RLM = 2,
|
||||
UNI_BSS_INFO_PROTECT_INFO = 3,
|
||||
UNI_BSS_INFO_BSS_COLOR = 4,
|
||||
UNI_BSS_INFO_HE_BASIC = 5,
|
||||
UNI_BSS_INFO_11V_MBSSID = 6,
|
||||
@@ -1383,6 +1395,7 @@ enum {
|
||||
UNI_BSS_INFO_MLD = 26,
|
||||
UNI_BSS_INFO_PM_DISABLE = 27,
|
||||
UNI_BSS_INFO_EHT = 30,
|
||||
UNI_BSS_INFO_MLD_LINK_OP = 36,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1865,7 +1878,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa)
|
||||
|
||||
ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
|
||||
DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;
|
||||
if (is_mt7921(dev) || is_mt7925(dev))
|
||||
if (is_connac2(dev) || is_mt7925(dev))
|
||||
ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
|
||||
DL_CONFIG_ENCRY_MODE_SEL : 0;
|
||||
ret |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
|
||||
@@ -534,6 +534,7 @@ void mt76x02_reconfig_complete(struct ieee80211_hw *hw,
|
||||
return;
|
||||
|
||||
clear_bit(MT76_RESTART, &dev->mphy.state);
|
||||
ieee80211_wake_queues(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_reconfig_complete);
|
||||
|
||||
|
||||
@@ -1294,6 +1294,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
|
||||
|
||||
void mt7915_unregister_device(struct mt7915_dev *dev)
|
||||
{
|
||||
cancel_work_sync(&dev->dump_work);
|
||||
mt7915_unregister_ext_phy(dev);
|
||||
mt7915_coredump_unregister(dev);
|
||||
mt7915_unregister_thermal(&dev->phy);
|
||||
|
||||
@@ -232,19 +232,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void mt7915_mac_enable_rtscts(struct mt7915_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
u32 addr;
|
||||
|
||||
addr = mt7915_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5);
|
||||
if (enable)
|
||||
mt76_set(dev, addr, BIT(5));
|
||||
else
|
||||
mt76_clear(dev, addr, BIT(5));
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
|
||||
struct mt7915_sta *msta, struct sk_buff *skb,
|
||||
|
||||
@@ -68,7 +68,7 @@ int mt7915_run(struct ieee80211_hw *hw)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,
|
||||
ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, MT7915_RTS_LEN_THRES,
|
||||
phy->mt76->band_idx);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -633,8 +633,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (set_sta == 1)
|
||||
mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
|
||||
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7915_mcu_set_protection(phy, vif, info->ht_operation_mode,
|
||||
info->use_cts_prot);
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_SLOT) {
|
||||
int slottime = 9;
|
||||
@@ -851,8 +852,10 @@ int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);
|
||||
|
||||
case MT76_STA_EVENT_DISASSOC:
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
|
||||
mt7915_mac_twt_teardown_flow(dev, msta, i);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
|
||||
msta->wcid.sta_disabled = 1;
|
||||
|
||||
@@ -1765,8 +1765,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
}
|
||||
out:
|
||||
ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_EXT_CMD(STA_REC_UPDATE), true);
|
||||
@@ -3954,6 +3956,68 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
u8 ht_mode, bool use_cts_prot)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int len = sizeof(struct sta_req_hdr) + sizeof(struct bss_info_prot);
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct bss_info_prot *prot;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
enum {
|
||||
PROT_NONMEMBER = BIT(1),
|
||||
PROT_20MHZ = BIT(2),
|
||||
PROT_NONHT_MIXED = BIT(3),
|
||||
PROT_LEGACY_ERP = BIT(5),
|
||||
PROT_NONGF_STA = BIT(7),
|
||||
};
|
||||
u32 rts_threshold;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||
NULL, len);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_PROTECT_INFO,
|
||||
sizeof(*prot));
|
||||
prot = (struct bss_info_prot *)tlv;
|
||||
|
||||
switch (ht_mode & IEEE80211_HT_OP_MODE_PROTECTION) {
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
|
||||
prot->prot_mode = cpu_to_le32(PROT_NONMEMBER);
|
||||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
||||
prot->prot_mode = cpu_to_le32(PROT_20MHZ);
|
||||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
|
||||
prot->prot_mode = cpu_to_le32(PROT_NONHT_MIXED);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
|
||||
prot->prot_mode |= cpu_to_le32(PROT_NONGF_STA);
|
||||
|
||||
if (use_cts_prot)
|
||||
prot->prot_mode |= cpu_to_le32(PROT_LEGACY_ERP);
|
||||
|
||||
/* reuse current RTS setting */
|
||||
rts_threshold = phy->mt76->hw->wiphy->rts_threshold;
|
||||
if (rts_threshold == (u32)-1)
|
||||
prot->rts_len_thres = cpu_to_le32(MT7915_RTS_LEN_THRES);
|
||||
else
|
||||
prot->rts_len_thres = cpu_to_le32(rts_threshold);
|
||||
|
||||
prot->rts_pkt_thres = 0x2;
|
||||
|
||||
prot->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);
|
||||
if (!prot->he_rts_thres)
|
||||
prot->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct cfg80211_he_bss_color *he_bss_color)
|
||||
{
|
||||
|
||||
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery {
|
||||
__le16 prob_rsp_len;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct bss_info_prot {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le32 prot_type;
|
||||
__le32 prot_mode;
|
||||
__le32 rts_len_thres;
|
||||
__le16 he_rts_thres;
|
||||
u8 rts_pkt_thres;
|
||||
u8 rsv[5];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
BSS_INFO_BCN_CSA,
|
||||
BSS_INFO_BCN_BCC,
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
#define MT7915_CRIT_TEMP 110
|
||||
#define MT7915_MAX_TEMP 120
|
||||
|
||||
#define MT7915_RTS_LEN_THRES 0x92b
|
||||
|
||||
struct mt7915_vif;
|
||||
struct mt7915_sta;
|
||||
struct mt7915_dfs_pulse;
|
||||
@@ -473,6 +475,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v
|
||||
u32 changed);
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int enable, u32 changed);
|
||||
int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
u8 ht_mode, bool use_cts_prot);
|
||||
int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_he_obss_pd *he_obss_pd);
|
||||
int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
|
||||
@@ -302,7 +302,9 @@ int mt7921_register_device(struct mt792x_dev *dev)
|
||||
dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
|
||||
dev->pm.stats.last_wake_event = jiffies;
|
||||
dev->pm.stats.last_doze_event = jiffies;
|
||||
if (!mt76_is_usb(&dev->mt76)) {
|
||||
|
||||
if (!mt76_is_usb(&dev->mt76) &&
|
||||
!is_mt7902(&dev->mt76)) {
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
|
||||
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return;
|
||||
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_roc_iter, (void *)phy);
|
||||
cancel_work(&phy->roc_work);
|
||||
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_roc_iter, (void *)phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
|
||||
|
||||
@@ -387,10 +390,11 @@ void mt7921_roc_work(struct work_struct *work)
|
||||
phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
|
||||
roc_work);
|
||||
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return;
|
||||
|
||||
mt792x_mutex_acquire(phy->dev);
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) {
|
||||
mt792x_mutex_release(phy->dev);
|
||||
return;
|
||||
}
|
||||
ieee80211_iterate_active_interfaces(phy->mt76->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_roc_iter, phy);
|
||||
@@ -796,7 +800,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add)
|
||||
}
|
||||
|
||||
out:
|
||||
mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env);
|
||||
if (vif->bss_conf.chanreq.oper.chan->band == NL80211_BAND_6GHZ)
|
||||
mt7921_regd_update(dev);
|
||||
}
|
||||
|
||||
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
@@ -807,6 +812,9 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
int ret, idx;
|
||||
|
||||
if (sta->aid > MT7921_MAX_AID)
|
||||
return -ENOENT;
|
||||
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
|
||||
if (idx < 0)
|
||||
return -ENOSPC;
|
||||
@@ -850,6 +858,9 @@ int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
if (sta->aid > MT7921_MAX_AID)
|
||||
return -ENOENT;
|
||||
|
||||
if (ev != MT76_STA_EVENT_ASSOC)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1353,6 +1353,9 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
u16 len = le16_to_cpu(rule->len);
|
||||
u16 offset = len + sizeof(*rule);
|
||||
|
||||
if (buf_len < offset)
|
||||
break;
|
||||
|
||||
pos += offset;
|
||||
buf_len -= offset;
|
||||
if (rule->alpha2[0] != alpha2[0] ||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "../mt792x.h"
|
||||
#include "regs.h"
|
||||
|
||||
#define MT7921_MAX_AID 20
|
||||
|
||||
#define MT7921_TX_RING_SIZE 2048
|
||||
#define MT7921_TX_MCU_RING_SIZE 256
|
||||
#define MT7921_TX_FWDL_RING_SIZE 128
|
||||
@@ -15,6 +17,9 @@
|
||||
#define MT7921_RX_MCU_RING_SIZE 8
|
||||
#define MT7921_RX_MCU_WA_RING_SIZE 512
|
||||
|
||||
/* MT7902 Rx Ring0 is for both Rx Event and Tx Done Event */
|
||||
#define MT7902_RX_MCU_RING_SIZE 512
|
||||
|
||||
#define MT7921_EEPROM_SIZE 3584
|
||||
#define MT7921_TOKEN_SIZE 8192
|
||||
|
||||
@@ -117,6 +122,17 @@ enum mt7921_rxq_id {
|
||||
MT7921_RXQ_MCU_WM = 0,
|
||||
};
|
||||
|
||||
/* MT7902 assigns its MCU-WM TXQ at index 15 */
|
||||
enum mt7902_txq_id {
|
||||
MT7902_TXQ_MCU_WM = 15,
|
||||
};
|
||||
|
||||
struct mt7921_dma_layout {
|
||||
u8 mcu_wm_txq;
|
||||
u16 mcu_rxdone_ring_size;
|
||||
bool has_mcu_wa;
|
||||
};
|
||||
|
||||
enum {
|
||||
MT7921_CLC_POWER,
|
||||
MT7921_CLC_CHAN,
|
||||
|
||||
@@ -26,6 +26,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
|
||||
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),
|
||||
.driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7902),
|
||||
.driver_data = (kernel_ulong_t)MT7902_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -167,8 +169,29 @@ static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
|
||||
|
||||
static int mt7921_dma_init(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt7921_dma_layout layout = {
|
||||
/* General case: MT7921 / MT7922 /MT7920 */
|
||||
.mcu_wm_txq = MT7921_TXQ_MCU_WM,
|
||||
.mcu_rxdone_ring_size = MT7921_RX_MCU_RING_SIZE,
|
||||
.has_mcu_wa = true,
|
||||
};
|
||||
bool is_mt7902;
|
||||
int ret;
|
||||
|
||||
is_mt7902 = mt7921_l1_rr(dev, MT_HW_CHIPID) == 0x7902;
|
||||
|
||||
/*
|
||||
* MT7902 special case:
|
||||
* - MCU-WM TXQ uses index 15
|
||||
* - RX Ring0 is larger and shared for event/TX-done
|
||||
* - MT7902 does not use the MCU_WA ring
|
||||
*/
|
||||
if (is_mt7902) {
|
||||
layout.mcu_wm_txq = MT7902_TXQ_MCU_WM;
|
||||
layout.mcu_rxdone_ring_size = MT7902_RX_MCU_RING_SIZE;
|
||||
layout.has_mcu_wa = false;
|
||||
}
|
||||
|
||||
mt76_dma_attach(&dev->mt76);
|
||||
|
||||
ret = mt792x_dma_disable(dev, true);
|
||||
@@ -185,7 +208,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev)
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
|
||||
|
||||
/* command to WM */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, layout.mcu_wm_txq,
|
||||
MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -199,18 +222,20 @@ static int mt7921_dma_init(struct mt792x_dev *dev)
|
||||
/* event from WM before firmware download */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
|
||||
MT7921_RXQ_MCU_WM,
|
||||
MT7921_RX_MCU_RING_SIZE,
|
||||
layout.mcu_rxdone_ring_size,
|
||||
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Change mcu queue after firmware download */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
|
||||
MT7921_RXQ_MCU_WM,
|
||||
MT7921_RX_MCU_WA_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (layout.has_mcu_wa) {
|
||||
/* Change mcu queue after firmware download */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
|
||||
MT7921_RXQ_MCU_WM,
|
||||
MT7921_RX_MCU_WA_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rx data */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
|
||||
@@ -276,6 +301,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
struct mt76_bus_ops *bus_ops;
|
||||
struct mt792x_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
void __iomem *regs;
|
||||
u16 cmd, chipid;
|
||||
u8 features;
|
||||
int ret;
|
||||
@@ -284,10 +310,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
|
||||
if (!(cmd & PCI_COMMAND_MEMORY)) {
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
@@ -321,11 +343,29 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
pci_set_drvdata(pdev, mdev);
|
||||
|
||||
regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &mt7921_pcie_ops;
|
||||
dev->irq_map = &irq_map;
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
mt76_mmio_init(&dev->mt76, regs);
|
||||
|
||||
if (id->device == 0x7902) {
|
||||
struct mt792x_irq_map *map;
|
||||
|
||||
/* MT7902 needs a mutable copy because wm2_complete_mask differs */
|
||||
map = devm_kmemdup(&pdev->dev, &irq_map,
|
||||
sizeof(irq_map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->rx.wm2_complete_mask = 0;
|
||||
dev->irq_map = map;
|
||||
}
|
||||
|
||||
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
|
||||
|
||||
dev->phy.dev = dev;
|
||||
@@ -579,6 +619,8 @@ MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7921_ROM_PATCH);
|
||||
MODULE_FIRMWARE(MT7922_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7922_ROM_PATCH);
|
||||
MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7902_ROM_PATCH);
|
||||
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver");
|
||||
|
||||
@@ -71,9 +71,9 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
}
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt76_connac2_tx_token_put(&dev->mt76);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
static const struct sdio_device_id mt7921s_table[] = {
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901),
|
||||
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7902),
|
||||
.driver_data = (kernel_ulong_t)MT7902_FIRMWARE_WM },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@@ -317,6 +319,8 @@ static int mt7921s_resume(struct device *__dev)
|
||||
MODULE_DEVICE_TABLE(sdio, mt7921s_table);
|
||||
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7921_ROM_PATCH);
|
||||
MODULE_FIRMWARE(MT7902_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7902_ROM_PATCH);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume);
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ int mt7925_mac_init(struct mt792x_dev *dev)
|
||||
|
||||
mt7925_mac_init_basic_rates(dev);
|
||||
|
||||
memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mac_init);
|
||||
|
||||
@@ -804,8 +804,8 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
txwi[5] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD6_DAS | FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
|
||||
if (!ieee80211_vif_is_mld(vif) ||
|
||||
(q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0))
|
||||
if (vif && (!ieee80211_vif_is_mld(vif) ||
|
||||
(q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)))
|
||||
val |= MT_TXD6_DIS_MAT;
|
||||
txwi[6] = cpu_to_le32(val);
|
||||
txwi[7] = 0;
|
||||
@@ -846,11 +846,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,
|
||||
bool is_8023;
|
||||
u16 fc, tid;
|
||||
|
||||
if (!sta)
|
||||
return;
|
||||
|
||||
link_sta = rcu_dereference(sta->link[wcid->link_id]);
|
||||
if (!link_sta)
|
||||
return;
|
||||
|
||||
if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
|
||||
if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
@@ -882,8 +885,10 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,
|
||||
else
|
||||
mlink = &msta->deflink;
|
||||
|
||||
if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state))
|
||||
ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||
if (!test_and_set_bit(tid, &mlink->wcid.ampdu_state)) {
|
||||
if (ieee80211_start_tx_ba_session(sta, tid, 0))
|
||||
clear_bit(tid, &mlink->wcid.ampdu_state);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -1280,7 +1285,8 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,
|
||||
true, NULL);
|
||||
mt7925_mcu_sta_update(dev, NULL, vif, true,
|
||||
mt7925_mcu_sta_update(dev, NULL, vif,
|
||||
&mvif->sta.deflink, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);
|
||||
}
|
||||
|
||||
@@ -245,6 +245,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
{
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
static const u8 ext_capa_sta[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
@@ -438,6 +439,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
|
||||
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
||||
INIT_WORK(&mvif->csa_work, mt7925_csa_work);
|
||||
timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0);
|
||||
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
@@ -457,12 +461,16 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return;
|
||||
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7925_roc_iter, (void *)phy);
|
||||
|
||||
cancel_work(&phy->roc_work);
|
||||
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7925_roc_iter, (void *)phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync);
|
||||
|
||||
@@ -541,7 +549,7 @@ static int mt7925_set_mlo_roc(struct mt792x_phy *phy,
|
||||
|
||||
phy->roc_grant = false;
|
||||
|
||||
err = mt7925_mcu_set_mlo_roc(mconf, sel_links, 5, ++phy->roc_token_id);
|
||||
err = mt7925_mcu_set_mlo_roc(phy, mconf, sel_links, 5, ++phy->roc_token_id);
|
||||
if (err < 0) {
|
||||
clear_bit(MT76_STATE_ROC, &phy->mt76->state);
|
||||
goto out;
|
||||
@@ -586,7 +594,8 @@ static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
|
||||
static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, int link_id)
|
||||
struct ieee80211_key_conf *key, int link_id,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
@@ -595,7 +604,6 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
int idx = key->keyidx, err = 0;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt76_wcid *wcid;
|
||||
u8 *wcid_keyidx;
|
||||
@@ -603,7 +611,6 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, link_id);
|
||||
link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL;
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
wcid = &mlink->wcid;
|
||||
wcid_keyidx = &wcid->hw_key_idx;
|
||||
|
||||
@@ -671,6 +678,7 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :
|
||||
&mvif->sta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
int err;
|
||||
|
||||
/* The hardware does not support per-STA RX GTK, fallback
|
||||
@@ -692,12 +700,16 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links;
|
||||
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id,
|
||||
mlink);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = mt7925_set_link_key(hw, cmd, vif, sta, key, vif->bss_conf.link_id);
|
||||
mlink = mt792x_sta_to_link(msta, vif->bss_conf.link_id);
|
||||
err = mt7925_set_link_key(hw, cmd, vif, sta, key,
|
||||
vif->bss_conf.link_id, mlink);
|
||||
}
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
@@ -842,20 +854,24 @@ mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
u8 link_id = link_sta->link_id;
|
||||
struct mt792x_link_sta *mlink;
|
||||
bool wcid_published = false;
|
||||
struct mt792x_sta *msta;
|
||||
struct mt76_wcid *wcid;
|
||||
bool pm_woken = false;
|
||||
int ret, idx;
|
||||
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
|
||||
if (WARN_ON_ONCE(!mlink))
|
||||
return -EINVAL;
|
||||
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
|
||||
if (idx < 0)
|
||||
@@ -874,14 +890,15 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
wcid = &mlink->wcid;
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);
|
||||
mt76_wcid_init(wcid, 0);
|
||||
wcid_published = true;
|
||||
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)
|
||||
return ret;
|
||||
goto out_wcid;
|
||||
pm_woken = true;
|
||||
|
||||
mt7925_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -890,41 +907,125 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
||||
|
||||
/* should update bss info before STA add */
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
|
||||
link_conf, link_sta, link_sta != mlink->pri_link);
|
||||
else
|
||||
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
|
||||
link_conf, link_sta, false);
|
||||
struct mt792x_link_sta *mlink_bc;
|
||||
|
||||
mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
ret = mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
|
||||
link_conf, link_sta,
|
||||
mlink_bc->wcid.idx, mlink->wcid.idx,
|
||||
link_sta != mlink->pri_link);
|
||||
if (ret)
|
||||
goto out_pm;
|
||||
} else {
|
||||
ret = mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
|
||||
link_conf, link_sta,
|
||||
mlink_bc->wcid.idx, mlink->wcid.idx,
|
||||
false);
|
||||
if (ret)
|
||||
goto out_pm;
|
||||
}
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mld(vif) &&
|
||||
link_sta == mlink->pri_link) {
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif,
|
||||
mlink, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_pm;
|
||||
} else if (ieee80211_vif_is_mld(vif) &&
|
||||
link_sta != mlink->pri_link) {
|
||||
ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,
|
||||
true, MT76_STA_INFO_STATE_ASSOC);
|
||||
if (ret)
|
||||
return ret;
|
||||
struct mt792x_link_sta *pri_mlink;
|
||||
struct mt76_wcid *pri_wcid;
|
||||
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
|
||||
/* alternative lookup via def_wcid */
|
||||
pri_wcid = mlink->wcid.def_wcid;
|
||||
|
||||
pri_mlink = pri_wcid ?
|
||||
container_of(pri_wcid, struct mt792x_link_sta, wcid) :
|
||||
NULL;
|
||||
|
||||
if (WARN_ON_ONCE(!pri_mlink)) {
|
||||
ret = -EINVAL;
|
||||
goto out_pm;
|
||||
}
|
||||
|
||||
ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,
|
||||
pri_mlink, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_pm;
|
||||
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif,
|
||||
mlink, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
if (ret)
|
||||
goto out_pm;
|
||||
} else {
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
|
||||
ret = mt7925_mcu_sta_update(dev, link_sta, vif,
|
||||
mlink, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_pm;
|
||||
}
|
||||
|
||||
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
|
||||
|
||||
return 0;
|
||||
|
||||
out_pm:
|
||||
if (pm_woken)
|
||||
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
|
||||
out_wcid:
|
||||
if (wcid_published) {
|
||||
u16 idx = wcid->idx;
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
mt76_wcid_cleanup(mdev, wcid);
|
||||
mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Host-only unwind for sta_add_links() failures.
|
||||
*
|
||||
* If add_links fail due to MCU/firmware timeouts; calling the full remove
|
||||
* path would send more firmware commands and may hang again. So only rollback
|
||||
* host-published state here (msta->link/valid_links, dev->mt76.wcid[idx]) and
|
||||
* free mlink objects (RCU-safe). Firmware state is left for reset/recovery.
|
||||
*/
|
||||
static void
|
||||
mt7925_mac_sta_unwind_links_host(struct mt792x_dev *dev,
|
||||
struct ieee80211_sta *sta,
|
||||
unsigned long links)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
unsigned int link_id;
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt792x_link_sta *mlink;
|
||||
u16 idx;
|
||||
|
||||
mlink = rcu_replace_pointer(msta->link[link_id], NULL,
|
||||
lockdep_is_held(&dev->mt76.mutex));
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
msta->valid_links &= ~BIT(link_id);
|
||||
if (msta->deflink_id == link_id)
|
||||
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
|
||||
idx = mlink->wcid.idx;
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
|
||||
mt76_wcid_mask_clear(dev->mt76.wcid_mask, idx);
|
||||
|
||||
if (mlink != &msta->deflink)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -932,34 +1033,50 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, unsigned long new_links)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
unsigned long added_links = 0;
|
||||
unsigned int link_id;
|
||||
int err = 0;
|
||||
|
||||
for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
bool is_deflink = false;
|
||||
|
||||
if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
|
||||
mlink = &msta->deflink;
|
||||
msta->deflink_id = link_id;
|
||||
is_deflink = true;
|
||||
} else {
|
||||
mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL);
|
||||
mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
|
||||
if (!mlink) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msta->valid_links |= BIT(link_id);
|
||||
rcu_assign_pointer(msta->link[link_id], mlink);
|
||||
mlink->sta = msta;
|
||||
mlink->pri_link = &sta->deflink;
|
||||
mlink->wcid.def_wcid = &msta->deflink.wcid;
|
||||
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta);
|
||||
err = mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta, mlink);
|
||||
if (err) {
|
||||
if (!is_deflink)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_deflink)
|
||||
msta->deflink_id = link_id;
|
||||
|
||||
rcu_assign_pointer(msta->link[link_id], mlink);
|
||||
msta->valid_links |= BIT(link_id);
|
||||
|
||||
added_links |= BIT(link_id);
|
||||
}
|
||||
|
||||
if (err && added_links)
|
||||
mt7925_mac_sta_unwind_links_host(dev, sta, added_links);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -981,7 +1098,8 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
|
||||
err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);
|
||||
} else {
|
||||
err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink);
|
||||
err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink,
|
||||
&msta->deflink);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -1030,11 +1148,11 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev,
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_sta *msta;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id);
|
||||
} else {
|
||||
@@ -1055,7 +1173,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));
|
||||
|
||||
mt7925_mcu_sta_update(dev, link_sta, vif, true, MT76_STA_INFO_STATE_ASSOC);
|
||||
mt7925_mcu_sta_update(dev, link_sta, vif, mlink, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
@@ -1083,23 +1202,21 @@ EXPORT_SYMBOL_GPL(mt7925_mac_sta_event);
|
||||
|
||||
static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt76_wcid *wcid = &mlink->wcid;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
u8 link_id = link_sta->link_id;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_sta *msta;
|
||||
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
u16 idx = wcid->idx;
|
||||
|
||||
mt7925_roc_abort_sync(dev);
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, wcid);
|
||||
mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
|
||||
mt7925_mcu_sta_update(dev, link_sta, vif, false,
|
||||
mt7925_mcu_sta_update(dev, link_sta, vif, mlink, false,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
mt7925_mac_wtbl_update(dev, mlink->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -1123,6 +1240,10 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
|
||||
list_del_init(&mlink->wcid.poll_list);
|
||||
spin_unlock_bh(&mdev->sta_poll_lock);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
mt76_wcid_cleanup(mdev, wcid);
|
||||
mt76_wcid_mask_clear(mdev->wcid_mask, idx);
|
||||
|
||||
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
|
||||
}
|
||||
|
||||
@@ -1132,7 +1253,6 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_wcid *wcid;
|
||||
unsigned int link_id;
|
||||
|
||||
/* clean up bss before starec */
|
||||
@@ -1171,22 +1291,19 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
mlink = rcu_replace_pointer(msta->link[link_id], NULL,
|
||||
lockdep_is_held(&mdev->mutex));
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta);
|
||||
|
||||
wcid = &mlink->wcid;
|
||||
rcu_assign_pointer(msta->link[link_id], NULL);
|
||||
msta->valid_links &= ~BIT(link_id);
|
||||
mlink->sta = NULL;
|
||||
mlink->pri_link = NULL;
|
||||
|
||||
if (link_sta != mlink->pri_link) {
|
||||
mt76_wcid_cleanup(mdev, wcid);
|
||||
mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);
|
||||
}
|
||||
mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta, mlink);
|
||||
|
||||
if (mlink != &msta->deflink)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
|
||||
if (msta->deflink_id == link_id)
|
||||
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
@@ -1323,10 +1440,18 @@ void mt7925_mlo_pm_work(struct work_struct *work)
|
||||
void mt7925_scan_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_phy *phy;
|
||||
struct mt792x_dev *dev;
|
||||
struct mt76_connac_pm *pm;
|
||||
|
||||
phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,
|
||||
scan_work.work);
|
||||
|
||||
dev = phy->dev;
|
||||
pm = &dev->pm;
|
||||
|
||||
if (pm->suspended)
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
@@ -1544,8 +1669,10 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);
|
||||
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, i);
|
||||
mlink = mt792x_sta_to_link(msta, i);
|
||||
|
||||
if (enabled)
|
||||
@@ -1556,7 +1683,7 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
if (!mlink->wcid.sta)
|
||||
continue;
|
||||
|
||||
mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);
|
||||
mt7925_mcu_wtbl_update_hdr_trans(dev, vif, mconf, mlink);
|
||||
}
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
@@ -1716,7 +1843,8 @@ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7925_mcu_sta_update(dev, NULL, vif, true,
|
||||
err = mt7925_mcu_sta_update(dev, NULL, vif,
|
||||
&mvif->sta.deflink, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
@@ -1749,6 +1877,10 @@ static int
|
||||
mt7925_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;
|
||||
}
|
||||
|
||||
@@ -1756,6 +1888,11 @@ static void
|
||||
mt7925_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
|
||||
@@ -1850,7 +1987,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
mt7925_mcu_sta_update(dev, NULL, vif, true,
|
||||
mt7925_mcu_sta_update(dev, NULL, vif,
|
||||
&mvif->sta.deflink, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
|
||||
|
||||
@@ -1894,10 +2032,8 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->link_id);
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
@@ -1939,10 +2075,6 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
|
||||
mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
|
||||
mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
|
||||
link_conf, NULL);
|
||||
|
||||
if (changed & BSS_CHANGED_CQM)
|
||||
mt7925_mcu_set_rssimonitor(dev, vif);
|
||||
|
||||
@@ -2144,6 +2276,11 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mctx->bss_conf = NULL;
|
||||
mconf->mt76.ctx = NULL;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (link_conf->csa_active) {
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
|
||||
@@ -2158,6 +2295,121 @@ static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);
|
||||
}
|
||||
|
||||
static int mt7925_switch_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode)
|
||||
{
|
||||
return mt7925_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf,
|
||||
vifs->new_ctx);
|
||||
}
|
||||
|
||||
void mt7925_csa_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_vif *mvif;
|
||||
struct mt792x_dev *dev;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
u8 link_id, roc_rtype;
|
||||
int ret = 0;
|
||||
|
||||
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);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
if (!dev->new_ctx)
|
||||
return;
|
||||
|
||||
link_id = 0;
|
||||
mconf = &mvif->bss_conf;
|
||||
link_conf = &vif->bss_conf;
|
||||
roc_rtype = MT7925_ROC_REQ_JOIN;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_set_roc(mvif->phy, mconf, dev->new_ctx->def.chan,
|
||||
4000, roc_rtype);
|
||||
mt792x_mutex_release(dev);
|
||||
if (!ret) {
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76, link_conf,
|
||||
dev->new_ctx);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
mt7925_abort_roc(mvif->phy, mconf);
|
||||
}
|
||||
|
||||
ieee80211_chswitch_done(vif, !ret, link_id);
|
||||
}
|
||||
|
||||
static int mt7925_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
{
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
|
||||
IEEE80211_CHAN_DISABLED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7925_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;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
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 mt7925_abort_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
|
||||
static void mt7925_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;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7925_ops = {
|
||||
.tx = mt792x_tx,
|
||||
.start = mt7925_start,
|
||||
@@ -2221,6 +2473,12 @@ const struct ieee80211_ops mt7925_ops = {
|
||||
.change_vif_links = mt7925_change_vif_links,
|
||||
.change_sta_links = mt7925_change_sta_links,
|
||||
.rfkill_poll = mt7925_rfkill_poll,
|
||||
|
||||
.switch_vif_chanctx = mt7925_switch_vif_chanctx,
|
||||
.pre_channel_switch = mt7925_pre_channel_switch,
|
||||
.channel_switch = mt7925_channel_switch,
|
||||
.abort_channel_switch = mt7925_abort_channel_switch,
|
||||
.channel_switch_rx_beacon = mt7925_channel_switch_rx_beacon,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt7925_ops);
|
||||
|
||||
|
||||
@@ -1066,9 +1066,8 @@ EXPORT_SYMBOL_GPL(mt7925_run_firmware);
|
||||
static void
|
||||
mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct sta_rec_hdr_trans *hdr_trans;
|
||||
struct mt76_wcid *wcid;
|
||||
struct tlv *tlv;
|
||||
@@ -1082,19 +1081,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
|
||||
else
|
||||
hdr_trans->from_ds = true;
|
||||
|
||||
if (link_sta) {
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
wcid = &mlink->wcid;
|
||||
} else {
|
||||
wcid = &mvif->sta.deflink.wcid;
|
||||
}
|
||||
|
||||
if (!wcid)
|
||||
if (WARN_ON_ONCE(!mlink))
|
||||
return;
|
||||
|
||||
wcid = &mlink->wcid;
|
||||
|
||||
hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
|
||||
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
|
||||
hdr_trans->to_ds = true;
|
||||
@@ -1104,30 +1095,18 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
|
||||
|
||||
int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
int link_id)
|
||||
struct mt792x_bss_conf *mconf,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct ieee80211_link_sta *link_sta = sta ? &sta->deflink : NULL;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_sta *msta;
|
||||
struct sk_buff *skb;
|
||||
|
||||
msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,
|
||||
&mlink->wcid,
|
||||
MT7925_STA_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
/* starec hdr trans */
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta);
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, vif, mlink);
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
}
|
||||
@@ -1288,14 +1267,16 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
return PTR_ERR(skb);
|
||||
|
||||
ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd, msta);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
int duration, u8 token_id)
|
||||
int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
u16 sel_links, int duration, u8 token_id)
|
||||
{
|
||||
struct mt792x_vif *mvif = mconf->vif;
|
||||
struct ieee80211_vif *vif = container_of((void *)mvif,
|
||||
@@ -1330,6 +1311,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
.roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv))
|
||||
};
|
||||
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
|
||||
if (!mconf || hweight16(vif->valid_links) < 2 ||
|
||||
hweight16(sel_links) != 2)
|
||||
return -EPERM;
|
||||
@@ -1352,7 +1335,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
is_AG_band |= links[i].chan->band == NL80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
if (vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP)
|
||||
if (!(wiphy->iftype_ext_capab[0].mld_capa_and_ops &
|
||||
IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS))
|
||||
type = is_AG_band ? MT7925_ROC_REQ_MLSR_AG :
|
||||
MT7925_ROC_REQ_MLSR_AA;
|
||||
else
|
||||
@@ -1721,10 +1705,9 @@ mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
|
||||
static void
|
||||
mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct sta_rec_amsdu *amsdu;
|
||||
struct tlv *tlv;
|
||||
|
||||
@@ -1740,7 +1723,6 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
|
||||
amsdu->max_amsdu_num = 8;
|
||||
amsdu->amsdu_en = true;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
mlink->wcid.amsdu = true;
|
||||
|
||||
switch (link_sta->agg.max_amsdu_len) {
|
||||
@@ -1911,36 +1893,53 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,
|
||||
|
||||
static void
|
||||
mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt792x_bss_conf *mconf,
|
||||
struct mt792x_link_sta *mlink)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
unsigned long valid = mvif->valid_links;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_dev *dev = mvif->phy->dev;
|
||||
struct mt792x_bss_conf *mconf_pri;
|
||||
struct sta_rec_mld *mld;
|
||||
struct tlv *tlv;
|
||||
int i, cnt = 0;
|
||||
u8 cnt = 0;
|
||||
|
||||
/* Primary link always uses driver's deflink WCID. */
|
||||
mconf_pri = (msta->deflink_id != IEEE80211_LINK_UNSPECIFIED) ?
|
||||
mt792x_vif_to_link(mvif, msta->deflink_id) : NULL;
|
||||
|
||||
/* If caller is operating on deflink, reuse its mconf as primary. */
|
||||
if (!mconf_pri && mlink == &msta->deflink)
|
||||
mconf_pri = mconf;
|
||||
|
||||
if (!mconf_pri) {
|
||||
dev_warn_ratelimited(dev->mt76.dev,
|
||||
"mt7925: MLD_TLV_LINK skip (no primary mconf) sta=%pM\n",
|
||||
sta->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld));
|
||||
mld = (struct sta_rec_mld *)tlv;
|
||||
memcpy(mld->mac_addr, sta->addr, ETH_ALEN);
|
||||
|
||||
mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx);
|
||||
mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
|
||||
mld->link_num = min_t(u8, hweight16(mvif->valid_links), 2);
|
||||
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
if (cnt == mld->link_num)
|
||||
break;
|
||||
/* Always encode primary link first. */
|
||||
mld->link[cnt].wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
|
||||
mld->link[cnt++].bss_idx = mconf_pri->mt76.idx;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, i);
|
||||
mlink = mt792x_sta_to_link(msta, i);
|
||||
/* Optionally encode the currently-updated secondary link. */
|
||||
if (mlink && mlink != &msta->deflink && mconf) {
|
||||
mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
|
||||
mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx);
|
||||
mld->link[cnt++].bss_idx = mconf->mt76.idx;
|
||||
|
||||
if (mlink != &msta->deflink)
|
||||
mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
|
||||
}
|
||||
|
||||
mld->link_num = cnt;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1961,10 +1960,12 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
|
||||
mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid,
|
||||
MT7925_STA_UPDATE_MAX_SIZE);
|
||||
@@ -1982,7 +1983,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
|
||||
mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);
|
||||
mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta, mlink);
|
||||
mt7925_mcu_sta_he_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
|
||||
@@ -1993,7 +1994,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
info->state);
|
||||
|
||||
if (info->state != MT76_STA_INFO_STATE_NONE) {
|
||||
mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);
|
||||
mt7925_mcu_sta_mld_tlv(skb, info->vif,
|
||||
info->link_sta->sta,
|
||||
mconf, mlink);
|
||||
|
||||
mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);
|
||||
}
|
||||
}
|
||||
@@ -2003,7 +2007,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,
|
||||
sizeof(struct tlv));
|
||||
} else {
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
|
||||
if (!info->link_sta)
|
||||
mlink = &mvif->sta.deflink;
|
||||
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, mlink);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
@@ -2011,7 +2018,9 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
|
||||
int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_vif *vif, bool enable,
|
||||
struct ieee80211_vif *vif,
|
||||
struct mt792x_link_sta *mlink,
|
||||
bool enable,
|
||||
enum mt76_sta_info_state state)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
@@ -2026,14 +2035,8 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
.offload_fw = true,
|
||||
.rcpi = to_rcpi(rssi),
|
||||
};
|
||||
struct mt792x_sta *msta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
if (link_sta) {
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
}
|
||||
info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
|
||||
info.wcid = &mlink->wcid;
|
||||
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
|
||||
|
||||
return mt7925_mcu_sta_cmd(&dev->mphy, &info);
|
||||
@@ -2470,7 +2473,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct mt76_phy *phy, u16 wlan_idx,
|
||||
struct mt76_phy *phy,
|
||||
u16 bmc_tx_wlan_idx,
|
||||
u16 sta_wlan_idx,
|
||||
bool enable)
|
||||
{
|
||||
struct ieee80211_vif *vif = link_conf->vif;
|
||||
@@ -2479,7 +2484,6 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
&link_conf->chanreq.oper;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct mt76_connac_bss_basic_tlv *basic_req;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct tlv *tlv;
|
||||
int conn_type;
|
||||
u8 idx;
|
||||
@@ -2503,20 +2507,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta);
|
||||
basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int);
|
||||
basic_req->dtim_period = link_conf->dtim_period;
|
||||
basic_req->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
|
||||
basic_req->bmc_tx_wlan_idx = cpu_to_le16(bmc_tx_wlan_idx);
|
||||
basic_req->link_idx = mconf->mt76.idx;
|
||||
|
||||
if (link_sta) {
|
||||
struct mt792x_sta *msta;
|
||||
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
|
||||
} else {
|
||||
mlink = &mconf->vif->sta.deflink;
|
||||
}
|
||||
|
||||
basic_req->sta_idx = cpu_to_le16(mlink->wcid.idx);
|
||||
basic_req->sta_idx = cpu_to_le16(sta_wlan_idx);
|
||||
basic_req->omac_idx = mconf->mt76.omac_idx;
|
||||
basic_req->band_idx = mconf->mt76.band_idx;
|
||||
basic_req->wmm_idx = mconf->mt76.wmm_idx;
|
||||
@@ -2823,16 +2816,16 @@ void mt7925_mcu_del_dev(struct mt76_dev *mdev,
|
||||
&dev_req, sizeof(dev_req), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
int enable)
|
||||
int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
u16 bmc_tx_wlan_idx,
|
||||
u16 sta_wlan_idx,
|
||||
int enable)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
|
||||
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
struct mt792x_link_sta *mlink_bc;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76,
|
||||
@@ -2840,11 +2833,9 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
|
||||
|
||||
/* bss_basic must be first */
|
||||
mt7925_mcu_bss_basic_tlv(skb, link_conf, link_sta, ctx, phy->mt76,
|
||||
mlink_bc->wcid.idx, enable);
|
||||
bmc_tx_wlan_idx, sta_wlan_idx, enable);
|
||||
mt7925_mcu_bss_sec_tlv(skb, link_conf);
|
||||
mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf);
|
||||
mt7925_mcu_bss_qos_tlv(skb, link_conf);
|
||||
@@ -2865,6 +2856,33 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
int enable)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
|
||||
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
struct mt792x_link_sta *mlink_bc;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
|
||||
|
||||
if (link_sta) {
|
||||
struct mt792x_sta *msta = (void *)link_sta->sta->drv_priv;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
if (WARN_ON(!mlink))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
mlink = &mconf->vif->sta.deflink;
|
||||
}
|
||||
|
||||
return mt7925_mcu_add_bss_info_sta(phy, ctx, link_conf, link_sta,
|
||||
mlink_bc->wcid.idx, mlink->wcid.idx, enable);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
|
||||
{
|
||||
struct mt76_dev *mdev = phy->dev;
|
||||
@@ -3375,7 +3393,6 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
u8 rsvd[64];
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(0x3),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
|
||||
.idx = idx,
|
||||
.env = env_cap,
|
||||
@@ -3404,6 +3421,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
memcpy(req.type, rule->type, 2);
|
||||
|
||||
req.size = cpu_to_le16(seg->len);
|
||||
req.len = cpu_to_le16(sizeof(req) + seg->len - 4);
|
||||
dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;
|
||||
skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,
|
||||
le16_to_cpu(req.size) + sizeof(req),
|
||||
@@ -3727,7 +3745,7 @@ mt7925_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2));
|
||||
tx_power_tlv->n_chan = num_ch;
|
||||
tx_power_tlv->tag = cpu_to_le16(0x1);
|
||||
tx_power_tlv->len = cpu_to_le16(sizeof(*tx_power_tlv));
|
||||
tx_power_tlv->len = cpu_to_le16(msg_len);
|
||||
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
|
||||
@@ -693,6 +693,13 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
int enable);
|
||||
int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
u16 bmc_tx_wlan_idx,
|
||||
u16 sta_wlan_idx,
|
||||
int enable);
|
||||
int mt7925_mcu_set_timing(struct mt792x_phy *phy,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
|
||||
|
||||
@@ -250,7 +250,9 @@ int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev,
|
||||
bool enable);
|
||||
int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_vif *vif, bool enable,
|
||||
struct ieee80211_vif *vif,
|
||||
struct mt792x_link_sta *mlink,
|
||||
bool enable,
|
||||
enum mt76_sta_info_state state);
|
||||
int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
|
||||
int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_bss_conf *bss_conf);
|
||||
@@ -298,6 +300,7 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
void mt7925_mlo_pm_work(struct work_struct *work);
|
||||
void mt7925_scan_work(struct work_struct *work);
|
||||
void mt7925_roc_work(struct work_struct *work);
|
||||
void mt7925_csa_work(struct work_struct *work);
|
||||
int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
void mt7925_coredump_work(struct work_struct *work);
|
||||
@@ -349,8 +352,8 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,
|
||||
int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);
|
||||
int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
enum environment_cap env_cap);
|
||||
int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links,
|
||||
int duration, u8 token_id);
|
||||
int mt7925_mcu_set_mlo_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
u16 sel_links, int duration, u8 token_id);
|
||||
int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_bss_conf *mconf,
|
||||
struct ieee80211_channel *chan, int duration,
|
||||
enum mt7925_roc_req type, u8 token_id);
|
||||
@@ -367,8 +370,8 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);
|
||||
int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
int link_id);
|
||||
struct mt792x_bss_conf *mconf,
|
||||
struct mt792x_link_sta *mlink);
|
||||
int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy);
|
||||
|
||||
int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
@@ -232,7 +232,8 @@ int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2)
|
||||
dev->regd_user)
|
||||
return -EINVAL;
|
||||
|
||||
if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
|
||||
if ((mdev->alpha2[0] && mdev->alpha2[0] != '0') &&
|
||||
(mdev->alpha2[1] && mdev->alpha2[1] != '0'))
|
||||
return 0;
|
||||
|
||||
/* do not need to update the same country twice */
|
||||
|
||||
@@ -41,11 +41,13 @@
|
||||
#define MT792x_MCU_INIT_RETRY_COUNT 10
|
||||
#define MT792x_WFSYS_INIT_RETRY_COUNT 2
|
||||
|
||||
#define MT7902_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7902_1.bin"
|
||||
#define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin"
|
||||
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
|
||||
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
|
||||
#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
|
||||
|
||||
#define MT7902_ROM_PATCH "mediatek/WIFI_MT7902_patch_mcu_1_1_hdr.bin"
|
||||
#define MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
|
||||
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
|
||||
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
|
||||
@@ -95,6 +97,7 @@ DECLARE_EWMA(avg_signal, 10, 8)
|
||||
|
||||
struct mt792x_link_sta {
|
||||
struct mt76_wcid wcid; /* must be first */
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
u32 airtime_ac[8];
|
||||
|
||||
@@ -448,6 +451,8 @@ void mt792x_config_mac_addr_list(struct mt792x_dev *dev);
|
||||
static inline char *mt792x_ram_name(struct mt792x_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7902:
|
||||
return MT7902_FIRMWARE_WM;
|
||||
case 0x7920:
|
||||
return MT7920_FIRMWARE_WM;
|
||||
case 0x7922:
|
||||
@@ -462,6 +467,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
|
||||
static inline char *mt792x_patch_name(struct mt792x_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7902:
|
||||
return MT7902_ROM_PATCH;
|
||||
case 0x7920:
|
||||
return MT7920_ROM_PATCH;
|
||||
case 0x7922:
|
||||
|
||||
@@ -151,7 +151,7 @@ void mt792x_stop(struct ieee80211_hw *hw, bool suspend)
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
if (is_mt7921(&dev->mt76)) {
|
||||
if (is_connac2(&dev->mt76)) {
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
|
||||
mt792x_mutex_release(dev);
|
||||
@@ -691,9 +691,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
|
||||
|
||||
if (is_mt7921(&dev->mt76)) {
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
}
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
|
||||
|
||||
if (dev->pm.enable)
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
@@ -927,6 +926,13 @@ int mt792x_load_firmware(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mt76_connac_mcu_restart(&dev->mt76);
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC_FW_STATE,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 1000))
|
||||
dev_warn(dev->mt76.dev,
|
||||
"MCU is not ready for firmware download\n");
|
||||
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -103,6 +103,22 @@ static void mt792x_dma_prefetch(struct mt792x_dev *dev)
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
|
||||
} else if (is_mt7902(&dev->mt76)) {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
|
||||
/* tx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0140, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0180, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x01c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x0200, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x0240, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x0280, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x02c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0300, 0x4));
|
||||
} else {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
|
||||
@@ -356,7 +372,7 @@ EXPORT_SYMBOL_GPL(mt792x_poll_rx);
|
||||
|
||||
int mt792x_wfsys_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140;
|
||||
u32 addr = is_connac2(&dev->mt76) ? 0x18000140 : 0x7c000140;
|
||||
|
||||
mt76_clear(dev, addr, WFSYS_SW_RST_B);
|
||||
msleep(50);
|
||||
|
||||
@@ -375,7 +375,7 @@ void mt792x_pm_power_save_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (!mt792x_mcu_fw_pmctrl(dev)) {
|
||||
cancel_delayed_work_sync(&mphy->mac_work);
|
||||
cancel_delayed_work(&mphy->mac_work);
|
||||
return;
|
||||
}
|
||||
out:
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
|
||||
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
|
||||
|
||||
#define MT_PSE_BASE 0x820c8000
|
||||
|
||||
/* TMAC: band 0(0x21000), band 1(0xa1000) */
|
||||
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
|
||||
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
|
||||
@@ -390,6 +392,10 @@
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
|
||||
|
||||
#define MT7925_CBTOP_RGU_WF_SUBSYS_RST 0x70028600
|
||||
#define MT7925_WFSYS_INIT_DONE_ADDR 0x184c1604
|
||||
#define MT7925_WFSYS_INIT_DONE 0x00001d1e
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_CHIPID 0x70010200
|
||||
#define MT_HW_REV 0x70010204
|
||||
|
||||
@@ -206,6 +206,33 @@ static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset)
|
||||
mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
|
||||
}
|
||||
|
||||
struct mt792xu_wfsys_desc {
|
||||
u32 rst_reg;
|
||||
u32 done_reg;
|
||||
u32 done_mask;
|
||||
u32 done_val;
|
||||
u32 delay_ms;
|
||||
bool need_status_sel;
|
||||
};
|
||||
|
||||
static const struct mt792xu_wfsys_desc mt7921_wfsys_desc = {
|
||||
.rst_reg = MT_CBTOP_RGU_WF_SUBSYS_RST,
|
||||
.done_reg = MT_UDMA_CONN_INFRA_STATUS,
|
||||
.done_mask = MT_UDMA_CONN_WFSYS_INIT_DONE,
|
||||
.done_val = MT_UDMA_CONN_WFSYS_INIT_DONE,
|
||||
.delay_ms = 0,
|
||||
.need_status_sel = true,
|
||||
};
|
||||
|
||||
static const struct mt792xu_wfsys_desc mt7925_wfsys_desc = {
|
||||
.rst_reg = MT7925_CBTOP_RGU_WF_SUBSYS_RST,
|
||||
.done_reg = MT7925_WFSYS_INIT_DONE_ADDR,
|
||||
.done_mask = U32_MAX,
|
||||
.done_val = MT7925_WFSYS_INIT_DONE,
|
||||
.delay_ms = 20,
|
||||
.need_status_sel = false,
|
||||
};
|
||||
|
||||
int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
|
||||
{
|
||||
int err;
|
||||
@@ -236,25 +263,33 @@ EXPORT_SYMBOL_GPL(mt792xu_dma_init);
|
||||
|
||||
int mt792xu_wfsys_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
const struct mt792xu_wfsys_desc *desc = is_mt7925(&dev->mt76) ?
|
||||
&mt7925_wfsys_desc :
|
||||
&mt7921_wfsys_desc;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
mt792xu_epctl_rst_opt(dev, false);
|
||||
|
||||
val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
|
||||
val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
mt792xu_uhw_wr(&dev->mt76, desc->rst_reg, val);
|
||||
|
||||
usleep_range(10, 20);
|
||||
if (desc->delay_ms)
|
||||
msleep(desc->delay_ms);
|
||||
else
|
||||
usleep_range(10, 20);
|
||||
|
||||
val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val = mt792xu_uhw_rr(&dev->mt76, desc->rst_reg);
|
||||
val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
mt792xu_uhw_wr(&dev->mt76, desc->rst_reg, val);
|
||||
|
||||
if (desc->need_status_sel)
|
||||
mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
|
||||
|
||||
mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
|
||||
for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {
|
||||
val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
|
||||
if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
|
||||
val = mt792xu_uhw_rr(&dev->mt76, desc->done_reg);
|
||||
if ((val & desc->done_mask) == desc->done_val)
|
||||
break;
|
||||
|
||||
msleep(100);
|
||||
|
||||
@@ -226,14 +226,23 @@ mt7996_radar_trigger(void *data, u64 val)
|
||||
#define RADAR_BACKGROUND 2
|
||||
struct mt7996_dev *dev = data;
|
||||
struct mt7996_phy *phy = mt7996_band_phy(dev, NL80211_BAND_5GHZ);
|
||||
int rdd_idx;
|
||||
struct cfg80211_chan_def *chandef;
|
||||
int rdd_idx, ret;
|
||||
|
||||
if (!phy || !val || val > RADAR_BACKGROUND)
|
||||
return -EINVAL;
|
||||
|
||||
if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {
|
||||
dev_err(dev->mt76.dev, "Background radar is not enabled\n");
|
||||
return -EINVAL;
|
||||
if (test_bit(MT76_SCANNING, &phy->mt76->state))
|
||||
return -EBUSY;
|
||||
|
||||
if (val == RADAR_BACKGROUND) {
|
||||
if (!dev->rdd2_phy || !cfg80211_chandef_valid(&dev->rdd2_chandef)) {
|
||||
dev_err(dev->mt76.dev, "Background radar is not enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
chandef = &dev->rdd2_chandef;
|
||||
} else {
|
||||
chandef = &phy->mt76->chandef;
|
||||
}
|
||||
|
||||
rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND);
|
||||
@@ -242,6 +251,11 @@ mt7996_radar_trigger(void *data, u64 val)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = cfg80211_chandef_dfs_required(dev->mt76.hw->wiphy, chandef,
|
||||
NL80211_IFTYPE_AP);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0);
|
||||
}
|
||||
|
||||
@@ -626,13 +640,18 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_vif *mvif = msta->vif;
|
||||
struct mt7996_dev *dev = mvif->deflink.phy->dev;
|
||||
struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct seq_file *s = data;
|
||||
struct ieee80211_vif *vif;
|
||||
struct mt7996_dev *dev;
|
||||
unsigned int link_id;
|
||||
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
|
||||
dev = phy->dev;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -979,13 +998,17 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file,
|
||||
#define LONG_PREAMBLE 1
|
||||
struct ieee80211_link_sta *link_sta = file->private_data;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv;
|
||||
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct mt7996_phy *link_phy = mt7996_vif_link_phy(&msta->vif->deflink);
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct ra_rate phy = {};
|
||||
struct mt7996_dev *dev;
|
||||
char buf[100];
|
||||
int ret;
|
||||
u16 gi, ltf;
|
||||
|
||||
if (!link_phy)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1008,6 +1031,7 @@ static ssize_t mt7996_link_sta_fixed_rate_set(struct file *file,
|
||||
* spe - off: 0, on: 1
|
||||
* ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
|
||||
*/
|
||||
dev = link_phy->dev;
|
||||
if (sscanf(buf, "%hhu %hhu %hhu %hhu %hu %hhu %hhu %hhu %hhu %hu",
|
||||
&phy.mode, &phy.bw, &phy.mcs, &phy.nss, &gi,
|
||||
&phy.preamble, &phy.stbc, &phy.ldpc, &phy.spe, <f) != 10) {
|
||||
|
||||
@@ -128,15 +128,27 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
|
||||
|
||||
/* data tx queue */
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
|
||||
if (dev->hif2) {
|
||||
/* default bn1:ring19 bn2:ring21 */
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2,
|
||||
MT7996_TXQ_BAND2);
|
||||
if (mt76_npu_device_active(&dev->mt76)) {
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND2,
|
||||
MT7996_TXQ_BAND2);
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND0,
|
||||
MT7996_TXQ_BAND0);
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
} else {
|
||||
/* default bn1:ring19 bn2:ring21 */
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
|
||||
MT7996_TXQ_BAND0);
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2,
|
||||
MT7996_TXQ_BAND2);
|
||||
}
|
||||
} else {
|
||||
/* single pcie bn0/1:ring18 bn2:ring19 */
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
|
||||
MT7996_TXQ_BAND0);
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
}
|
||||
@@ -350,6 +362,9 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
|
||||
if (!mt7996_has_wa(dev) || mt76_npu_device_active(&dev->mt76))
|
||||
irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) |
|
||||
MT_INT_RX(MT_RXQ_BAND1_WA));
|
||||
if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
|
||||
irq_mask &= ~(MT_INT_RX(MT_RXQ_TXFREE_BAND0) |
|
||||
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2));
|
||||
irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
|
||||
|
||||
mt7996_irq_enable(dev, irq_mask);
|
||||
@@ -430,39 +445,48 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
|
||||
MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 |
|
||||
MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
|
||||
|
||||
if (is_mt7996(&dev->mt76))
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
|
||||
else
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
if (mt76_npu_device_active(&dev->mt76))
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_BAND0_PCIE1);
|
||||
else
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
|
||||
} else {
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_BAND1_PCIE1);
|
||||
}
|
||||
|
||||
/* AXI read outstanding number */
|
||||
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
|
||||
MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
|
||||
|
||||
if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
|
||||
(dev->hif2->speed == PCIE_SPEED_5_0GT &&
|
||||
dev->hif2->width < PCIE_LNK_X2)) {
|
||||
mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
|
||||
WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
0x1));
|
||||
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
|
||||
MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
0x1));
|
||||
} else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
|
||||
(dev->hif2->speed == PCIE_SPEED_8_0GT &&
|
||||
dev->hif2->width < PCIE_LNK_X2)) {
|
||||
mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
|
||||
WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
0x2));
|
||||
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
|
||||
MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
0x2));
|
||||
if (!is_mt7996(&dev->mt76) ||
|
||||
!mt76_npu_device_active(&dev->mt76)) {
|
||||
if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
|
||||
(dev->hif2->speed == PCIE_SPEED_5_0GT &&
|
||||
dev->hif2->width < PCIE_LNK_X2)) {
|
||||
mt76_rmw(dev,
|
||||
WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
|
||||
WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
0x1));
|
||||
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
|
||||
MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
0x1));
|
||||
} else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
|
||||
(dev->hif2->speed == PCIE_SPEED_8_0GT &&
|
||||
dev->hif2->width < PCIE_LNK_X2)) {
|
||||
mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
|
||||
WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
|
||||
0x2));
|
||||
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
|
||||
MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
|
||||
0x2));
|
||||
}
|
||||
}
|
||||
|
||||
/* WFDMA rx threshold */
|
||||
@@ -497,7 +521,7 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
|
||||
int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
u32 irq_mask;
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
@@ -524,7 +548,8 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
|
||||
true);
|
||||
}
|
||||
goto start_hw_rro;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ind cmd */
|
||||
@@ -545,10 +570,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&mdev->mmio.wed))
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
|
||||
|
||||
size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
|
||||
? MT7996_NPU_RX_RING_SIZE / 4 : MT7996_RX_RING_SIZE;
|
||||
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
|
||||
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_MSDU_PAGE_SIZE,
|
||||
size, MT7996_RX_MSDU_PAGE_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -560,10 +587,12 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&mdev->mmio.wed))
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
|
||||
|
||||
size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
|
||||
? MT7996_NPU_RX_RING_SIZE / 2 : MT7996_RX_RING_SIZE;
|
||||
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
|
||||
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_MSDU_PAGE_SIZE,
|
||||
size, MT7996_RX_MSDU_PAGE_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -576,52 +605,60 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&mdev->mmio.wed))
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
|
||||
|
||||
size = is_mt7996(mdev) && mt76_npu_device_active(mdev)
|
||||
? MT7996_NPU_RX_RING_SIZE : MT7996_RX_RING_SIZE;
|
||||
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
|
||||
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_MSDU_PAGE_SIZE,
|
||||
size, MT7996_RX_MSDU_PAGE_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
start_hw_rro:
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed)) {
|
||||
irq_mask = mdev->mmio.irqmask |
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7996_dma_rro_start(struct mt7996_dev *dev)
|
||||
{
|
||||
u32 irq_mask;
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
irq_mask = dev->mt76.mmio.irqmask |
|
||||
MT_INT_TX_DONE_BAND2;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
|
||||
mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);
|
||||
mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, irq_mask,
|
||||
false);
|
||||
mt7996_irq_enable(dev, irq_mask);
|
||||
} else {
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,
|
||||
mt76_dma_rx_poll);
|
||||
} else {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,
|
||||
mt76_dma_rx_poll);
|
||||
}
|
||||
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,
|
||||
mt76_dma_rx_poll);
|
||||
} else {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_IND,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,
|
||||
mt76_dma_rx_poll);
|
||||
}
|
||||
|
||||
if (!mt76_npu_device_active(&dev->mt76))
|
||||
mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
|
||||
return;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,
|
||||
mt76_dma_rx_poll);
|
||||
} else {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,
|
||||
mt76_dma_rx_poll);
|
||||
}
|
||||
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,
|
||||
mt76_dma_rx_poll);
|
||||
} else {
|
||||
mt76_queue_rx_init(dev, MT_RXQ_RRO_IND,
|
||||
mt76_dma_rx_poll);
|
||||
mt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,
|
||||
mt76_dma_rx_poll);
|
||||
}
|
||||
|
||||
if (!mt76_npu_device_active(&dev->mt76))
|
||||
mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
|
||||
}
|
||||
|
||||
int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
@@ -642,11 +679,16 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
mt7996_dma_disable(dev, true);
|
||||
|
||||
/* init tx queue */
|
||||
ret = mt7996_init_tx_queues(&dev->phy,
|
||||
MT_TXQ_ID(dev->mphy.band_idx),
|
||||
MT7996_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(0),
|
||||
wed);
|
||||
if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
|
||||
ret = mt7996_init_tx_queues(&dev->phy, MT_TXQ_ID(0),
|
||||
MT7996_NPU_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(0) + hif1_ofs,
|
||||
NULL);
|
||||
else
|
||||
ret = mt7996_init_tx_queues(&dev->phy,
|
||||
MT_TXQ_ID(dev->mphy.band_idx),
|
||||
MT7996_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(0), wed);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -714,6 +756,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
(is_mt7992(&dev->mt76)))) {
|
||||
dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
|
||||
} else if (is_mt7992(&dev->mt76) &&
|
||||
mt76_npu_device_active(&dev->mt76)) {
|
||||
dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_NPU_Q_TXFREE(0);
|
||||
}
|
||||
|
||||
if (mt7996_has_wa(dev)) {
|
||||
@@ -846,6 +891,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
/* tx free notify event from WA for band0 */
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
|
||||
} else if (mt76_npu_device_active(&dev->mt76)) {
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_NPU_Q_TXFREE(0);
|
||||
}
|
||||
|
||||
ret = mt76_queue_alloc(dev,
|
||||
@@ -859,16 +906,21 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
}
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND2)) {
|
||||
u32 size;
|
||||
|
||||
/* rx rro data queue for band2 */
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
|
||||
MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
|
||||
if (mtk_wed_device_active(wed) &&
|
||||
mtk_wed_get_rx_capa(wed))
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
|
||||
|
||||
size = is_mt7996(&dev->mt76) &&
|
||||
mt76_npu_device_active(&dev->mt76)
|
||||
? MT7996_NPU_RX_RING_SIZE : MT7996_RX_RING_SIZE;
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_BAND2),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
size, MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -33,6 +33,8 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
|
||||
if (dev->var.fem == MT7996_FEM_INT)
|
||||
return MT7992_EEPROM_DEFAULT_23_INT;
|
||||
return MT7992_EEPROM_DEFAULT_23;
|
||||
case MT7992_VAR_TYPE_24:
|
||||
return MT7992_EEPROM_DEFAULT_24;
|
||||
case MT7992_VAR_TYPE_44:
|
||||
default:
|
||||
if (dev->var.fem == MT7996_FEM_INT)
|
||||
@@ -153,7 +155,7 @@ mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default)
|
||||
|
||||
dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
|
||||
memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);
|
||||
dev->flash_mode = true;
|
||||
dev->eeprom_mode = EEPROM_MODE_DEFAULT_BIN;
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
@@ -163,26 +165,31 @@ mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default)
|
||||
|
||||
static int mt7996_eeprom_load(struct mt7996_dev *dev)
|
||||
{
|
||||
u32 eeprom_blk_size, block_num;
|
||||
bool use_default = false;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret && !mt7996_check_eeprom(dev)) {
|
||||
dev->flash_mode = true;
|
||||
dev->eeprom_mode = EEPROM_MODE_FLASH;
|
||||
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);
|
||||
memset(dev->mt76.eeprom.data, 0, MT7996_EEPROM_SIZE);
|
||||
if (mt7996_has_ext_eeprom(dev)) {
|
||||
/* external eeprom mode */
|
||||
dev->eeprom_mode = EEPROM_MODE_EXT;
|
||||
eeprom_blk_size = MT7996_EXT_EEPROM_BLOCK_SIZE;
|
||||
} else {
|
||||
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);
|
||||
/* efuse mode */
|
||||
dev->eeprom_mode = EEPROM_MODE_EFUSE;
|
||||
eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;
|
||||
ret = mt7996_mcu_get_efuse_free_block(dev, &free_block_num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -191,27 +198,29 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
|
||||
use_default = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if eeprom data from fw is valid */
|
||||
if (mt7996_mcu_get_eeprom(dev, 0, NULL, 0) ||
|
||||
mt7996_check_eeprom(dev)) {
|
||||
/* check if eeprom data from fw is valid */
|
||||
if (mt7996_mcu_get_eeprom(dev, 0, NULL, eeprom_blk_size,
|
||||
dev->eeprom_mode) ||
|
||||
mt7996_check_eeprom(dev)) {
|
||||
use_default = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* read eeprom data from fw */
|
||||
block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);
|
||||
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, dev->eeprom_mode);
|
||||
if (ret && ret != -EINVAL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -385,7 +394,8 @@ bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev)
|
||||
return false;
|
||||
break;
|
||||
case MT7992_DEVICE_ID:
|
||||
if (dev->var.type == MT7992_VAR_TYPE_23)
|
||||
if (dev->var.type == MT7992_VAR_TYPE_23 ||
|
||||
dev->var.type == MT7992_VAR_TYPE_24)
|
||||
return false;
|
||||
break;
|
||||
case MT7990_DEVICE_ID: {
|
||||
|
||||
@@ -34,6 +34,20 @@ static const struct ieee80211_iface_combination if_comb_global = {
|
||||
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_global_7992 = {
|
||||
.limits = &if_limits_global,
|
||||
.n_limits = 1,
|
||||
.max_interfaces = 32,
|
||||
.num_different_channels = MT7996_MAX_RADIOS - 1,
|
||||
.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_limit if_limits[] = {
|
||||
@@ -85,6 +99,7 @@ static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = {
|
||||
.extended_capabilities_mask = if_types_ext_capa_ap,
|
||||
.extended_capabilities_len = sizeof(if_types_ext_capa_ap),
|
||||
.mld_capa_and_ops =
|
||||
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_FREQ_SEP_TYPE_IND, 1) |
|
||||
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
|
||||
MT7996_MAX_RADIOS - 1),
|
||||
},
|
||||
@@ -485,7 +500,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
hw->vif_data_size = sizeof(struct mt7996_vif);
|
||||
hw->chanctx_data_size = sizeof(struct mt76_chanctx);
|
||||
|
||||
wiphy->iface_combinations = &if_comb_global;
|
||||
wiphy->iface_combinations = is_mt7996(&dev->mt76) ? &if_comb_global :
|
||||
&if_comb_global_7992;
|
||||
wiphy->n_iface_combinations = 1;
|
||||
|
||||
wiphy->radio = dev->radios;
|
||||
@@ -521,8 +537,10 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
@@ -592,7 +610,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
|
||||
void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
{
|
||||
#define HIF_TXD_V2_1 0x21
|
||||
int i;
|
||||
int i, rx_path_type;
|
||||
|
||||
mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
|
||||
|
||||
@@ -606,11 +624,16 @@ void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
}
|
||||
|
||||
/* rro module init */
|
||||
if (dev->hif2)
|
||||
if (dev->hif2) {
|
||||
if (mt76_npu_device_active(&dev->mt76))
|
||||
rx_path_type = is_mt7996(&dev->mt76) ? 6 : 8;
|
||||
else
|
||||
rx_path_type = is_mt7996(&dev->mt76) ? 2 : 7;
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
|
||||
is_mt7996(&dev->mt76) ? 2 : 7);
|
||||
else
|
||||
rx_path_type);
|
||||
} else {
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);
|
||||
}
|
||||
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
u16 timeout;
|
||||
@@ -668,8 +691,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||
return 0;
|
||||
|
||||
if (dev->hif2 &&
|
||||
((is_mt7996(&dev->mt76) && band == MT_BAND2) ||
|
||||
(is_mt7992(&dev->mt76) && band == MT_BAND1))) {
|
||||
((is_mt7992(&dev->mt76) && band == MT_BAND1) ||
|
||||
(is_mt7996(&dev->mt76) && band == MT_BAND2 &&
|
||||
!mt76_npu_device_active(&dev->mt76)))) {
|
||||
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
wed = &dev->mt76.mmio.wed_hif2;
|
||||
}
|
||||
@@ -709,14 +733,19 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||
/* init wiphy according to mphy and phy */
|
||||
mt7996_init_wiphy_band(mphy->hw, phy);
|
||||
|
||||
if (is_mt7996(&dev->mt76) && !dev->hif2 && band == MT_BAND1) {
|
||||
if (is_mt7996(&dev->mt76) &&
|
||||
((band == MT_BAND1 && !dev->hif2) ||
|
||||
(band == MT_BAND2 && mt76_npu_device_active(&dev->mt76)))) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= MT_TXQ_PSD; i++)
|
||||
mphy->q_tx[i] = dev->mt76.phys[MT_BAND0]->q_tx[0];
|
||||
mphy->q_tx[i] = dev->mt76.phys[band - 1]->q_tx[0];
|
||||
} else {
|
||||
ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band),
|
||||
MT7996_TX_RING_SIZE,
|
||||
int size = is_mt7996(&dev->mt76) &&
|
||||
mt76_npu_device_active(&dev->mt76)
|
||||
? MT7996_NPU_TX_RING_SIZE / 2 : MT7996_TX_RING_SIZE;
|
||||
|
||||
ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band), size,
|
||||
MT_TXQ_RING_BASE(band) + hif1_ofs,
|
||||
wed);
|
||||
if (ret)
|
||||
@@ -756,15 +785,41 @@ static void mt7996_init_work(struct work_struct *work)
|
||||
mt7996_mcu_set_eeprom(dev);
|
||||
mt7996_mac_init(dev);
|
||||
mt7996_txbf_init(dev);
|
||||
|
||||
if (!is_mt7990(&dev->mt76))
|
||||
mt7996_mcu_set_dup_wtbl(dev);
|
||||
}
|
||||
|
||||
void mt7996_wfsys_reset(struct mt7996_dev *dev)
|
||||
{
|
||||
mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
if (!is_mt7990(&dev->mt76)) {
|
||||
mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
msleep(20);
|
||||
|
||||
mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
msleep(20);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dev->recovery.hw_full_reset)
|
||||
return;
|
||||
|
||||
mt76_set(dev, MT_WF_SUBSYS_RST,
|
||||
MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT |
|
||||
MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT |
|
||||
MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT);
|
||||
mt76_rmw(dev, MT_WF_SUBSYS_RST,
|
||||
MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE,
|
||||
u32_encode_bits(0x20, MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE));
|
||||
mt76_clear(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK);
|
||||
mt76_set(dev, MT_WF_SUBSYS_RST, MT_WF_SUBSYS_RST_WHOLE_PATH_RST);
|
||||
msleep(20);
|
||||
|
||||
mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
msleep(20);
|
||||
if (mt76_poll(dev, MT_WF_L05_RST, MT_WF_L05_RST_WF_RST_MASK, 0x1a, 1000))
|
||||
return;
|
||||
|
||||
dev_err(dev->mt76.dev, "wfsys reset fail\n");
|
||||
}
|
||||
|
||||
static void mt7996_rro_hw_init_v3(struct mt7996_dev *dev)
|
||||
@@ -842,8 +897,7 @@ void mt7996_rro_hw_init(struct mt7996_dev *dev)
|
||||
}
|
||||
} else {
|
||||
/* set emul 3.0 function */
|
||||
mt76_wr(dev, MT_RRO_3_0_EMU_CONF,
|
||||
MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||
mt76_set(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||
|
||||
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,
|
||||
dev->wed_rro.addr_elem[0].phy_addr);
|
||||
@@ -935,6 +989,12 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||
addr++;
|
||||
}
|
||||
|
||||
if (is_mt7996(&dev->mt76) &&
|
||||
mt76_npu_device_active(&dev->mt76))
|
||||
mt76_npu_send_txrx_addr(&dev->mt76, 0, i,
|
||||
dev->wed_rro.addr_elem[i].phy_addr,
|
||||
0, 0);
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) {
|
||||
@@ -995,6 +1055,10 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||
addr++;
|
||||
}
|
||||
|
||||
if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76))
|
||||
mt76_npu_send_txrx_addr(&dev->mt76, 1, 0,
|
||||
dev->wed_rro.session.phy_addr, 0, 0);
|
||||
|
||||
mt7996_rro_hw_init(dev);
|
||||
|
||||
return mt7996_dma_rro_init(dev);
|
||||
@@ -1081,8 +1145,12 @@ static void mt7996_wed_rro_work(struct work_struct *work)
|
||||
list);
|
||||
list_del_init(&e->list);
|
||||
|
||||
if (mt76_npu_device_active(&dev->mt76))
|
||||
if (mt76_npu_device_active(&dev->mt76)) {
|
||||
if (is_mt7996(&dev->mt76))
|
||||
mt76_npu_send_txrx_addr(&dev->mt76, 3, e->id,
|
||||
0, 0, 0);
|
||||
goto reset_session;
|
||||
}
|
||||
|
||||
for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
|
||||
void *ptr = dev->wed_rro.session.ptr;
|
||||
@@ -1129,7 +1197,7 @@ static int mt7996_variant_type_init(struct mt7996_dev *dev)
|
||||
else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992))
|
||||
var_type = MT7992_VAR_TYPE_44;
|
||||
else
|
||||
return -EINVAL;
|
||||
var_type = MT7992_VAR_TYPE_24;
|
||||
break;
|
||||
case MT7990_DEVICE_ID:
|
||||
var_type = MT7990_VAR_TYPE_23;
|
||||
@@ -1163,7 +1231,8 @@ static int mt7996_variant_fem_init(struct mt7996_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf));
|
||||
ret = mt7996_mcu_get_eeprom(dev, MT7976C_EFUSE_OFFSET, buf, sizeof(buf),
|
||||
EEPROM_MODE_EFUSE);
|
||||
if (ret && ret != -EINVAL)
|
||||
return ret;
|
||||
|
||||
@@ -1696,6 +1765,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt7996_dma_rro_start(dev);
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
@@ -1726,6 +1797,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||
|
||||
void mt7996_unregister_device(struct mt7996_dev *dev)
|
||||
{
|
||||
cancel_work_sync(&dev->dump_work);
|
||||
cancel_work_sync(&dev->wed_rro.work);
|
||||
mt7996_unregister_phy(mt7996_phy3(dev));
|
||||
mt7996_unregister_phy(mt7996_phy2(dev));
|
||||
|
||||
@@ -13,45 +13,6 @@
|
||||
|
||||
#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
|
||||
|
||||
static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
|
||||
.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
|
||||
.radar_pattern = {
|
||||
[5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 },
|
||||
[6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 },
|
||||
[7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 },
|
||||
[8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 },
|
||||
[9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 },
|
||||
[10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 },
|
||||
[11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 },
|
||||
[12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mt7996_dfs_radar_spec fcc_radar_specs = {
|
||||
.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
|
||||
.radar_pattern = {
|
||||
[0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
|
||||
[1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
|
||||
[2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
|
||||
[3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
|
||||
[4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mt7996_dfs_radar_spec jp_radar_specs = {
|
||||
.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
|
||||
.radar_pattern = {
|
||||
[0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 },
|
||||
[1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 },
|
||||
[2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 },
|
||||
[3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 },
|
||||
[4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 },
|
||||
[13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 },
|
||||
[14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 },
|
||||
[15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
||||
u16 idx, u8 band_idx)
|
||||
{
|
||||
@@ -527,7 +488,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
|
||||
!(csum_status & (BIT(0) | BIT(2) | BIT(3))))
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)
|
||||
if (rxd3 & MT_RXD3_NORMAL_FCS_ERR)
|
||||
status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
|
||||
@@ -700,6 +661,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
|
||||
|
||||
hdr = mt76_skb_get_hdr(skb);
|
||||
fc = hdr->frame_control;
|
||||
if (ieee80211_is_beacon(fc))
|
||||
mt76_rx_beacon(mphy, skb);
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
u8 *qos = ieee80211_get_qos_ctl(hdr);
|
||||
|
||||
@@ -1139,10 +1102,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
* req
|
||||
*/
|
||||
if (le32_to_cpu(ptr[7]) & MT_TXD7_MAC_TXD) {
|
||||
u32 val;
|
||||
u32 val, mac_txp_size = sizeof(struct mt76_connac_hw_txp);
|
||||
|
||||
ptr = (__le32 *)(txwi + MT_TXD_SIZE);
|
||||
memset((void *)ptr, 0, sizeof(struct mt76_connac_fw_txp));
|
||||
memset((void *)ptr, 0, mac_txp_size);
|
||||
|
||||
val = FIELD_PREP(MT_TXP0_TOKEN_ID0, id) |
|
||||
MT_TXP0_TOKEN_ID0_VALID_MASK;
|
||||
@@ -1161,6 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
tx_info->buf[1].addr >> 32);
|
||||
#endif
|
||||
ptr[3] = cpu_to_le32(val);
|
||||
|
||||
tx_info->buf[0].len = MT_TXD_SIZE + mac_txp_size;
|
||||
} else {
|
||||
struct mt76_connac_txp_common *txp;
|
||||
|
||||
@@ -1270,8 +1235,9 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,
|
||||
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
|
||||
return;
|
||||
|
||||
if (!test_and_set_bit(tid, &wcid->ampdu_state))
|
||||
ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);
|
||||
if (!test_and_set_bit(tid, &wcid->ampdu_state) &&
|
||||
ieee80211_start_tx_ba_session(link_sta->sta, tid, 0))
|
||||
clear_bit(tid, &wcid->ampdu_state);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2203,9 +2169,14 @@ mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt7996_phy *link_phy;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link || link->phy != phy)
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
link_phy = mt7996_vif_link_phy(link);
|
||||
if (link_phy != phy)
|
||||
continue;
|
||||
|
||||
mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf,
|
||||
@@ -2248,6 +2219,12 @@ void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
}
|
||||
spin_unlock_bh(&dev->mt76.token_lock);
|
||||
idr_destroy(&dev->mt76.token);
|
||||
|
||||
for (id = 0; id < __MT_MAX_BAND; id++) {
|
||||
struct mt76_phy *phy = dev->mt76.phys[id];
|
||||
if (phy)
|
||||
atomic_set(&phy->mgmt_tx_pending, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2395,23 +2372,8 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)
|
||||
struct mt7996_dev *dev = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msta->link); i++) {
|
||||
struct mt7996_sta_link *msta_link = NULL;
|
||||
|
||||
msta_link = rcu_replace_pointer(msta->link[i], msta_link,
|
||||
lockdep_is_held(&dev->mt76.mutex));
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
mt7996_mac_sta_deinit_link(dev, msta_link);
|
||||
|
||||
if (msta->deflink_id == i) {
|
||||
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
continue;
|
||||
}
|
||||
|
||||
kfree_rcu(msta_link, rcu_head);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(msta->link); i++)
|
||||
mt7996_mac_sta_remove_link(dev, sta, i, true);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2544,6 +2506,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
mtk_wed_device_stop(&dev->mt76.mmio.wed);
|
||||
|
||||
mt7996_npu_hw_stop(dev);
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
@@ -2564,14 +2527,19 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
if (mt76_npu_device_active(&dev->mt76) &&
|
||||
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
if (mt76_queue_is_npu_txfree(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
}
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mt7996_npu_hw_stop(dev);
|
||||
|
||||
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
|
||||
|
||||
if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
|
||||
@@ -2591,7 +2559,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
mt7996_dma_start(dev, false, false);
|
||||
|
||||
if (!is_mt7996(&dev->mt76) && dev->mt76.hwrro_mode == MT76_HWRRO_V3)
|
||||
mt76_wr(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||
mt76_set(dev, MT_RRO_3_0_EMU_CONF, MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
u32 wed_irq_mask = MT_INT_TX_DONE_BAND2 |
|
||||
@@ -2610,6 +2578,8 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
MT_INT_TX_RX_DONE_EXT);
|
||||
}
|
||||
|
||||
__mt7996_npu_hw_init(dev);
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
mt7996_for_each_phy(dev, phy)
|
||||
clear_bit(MT76_RESET, &phy->mt76->state);
|
||||
@@ -2619,6 +2589,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
if (mt76_npu_device_active(&dev->mt76) &&
|
||||
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
if (mt76_queue_is_npu_txfree(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
local_bh_disable();
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
@@ -2639,8 +2616,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt7996_npu_hw_init(dev);
|
||||
|
||||
mt7996_for_each_phy(dev, phy)
|
||||
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
@@ -2737,6 +2712,11 @@ void mt7996_reset(struct mt7996_dev *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA) {
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
}
|
||||
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
wake_up(&dev->reset_wait);
|
||||
}
|
||||
@@ -2955,6 +2935,7 @@ void mt7996_mac_work(struct work_struct *work)
|
||||
|
||||
mutex_unlock(&mphy->dev->mutex);
|
||||
|
||||
mt76_beacon_mon_check(mphy);
|
||||
mt76_tx_status_check(mphy->dev, false);
|
||||
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
@@ -2974,7 +2955,7 @@ static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy)
|
||||
|
||||
static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
|
||||
{
|
||||
int err, region;
|
||||
int region;
|
||||
|
||||
switch (dev->mt76.region) {
|
||||
case NL80211_DFS_ETSI:
|
||||
@@ -2989,11 +2970,7 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, rdd_idx, 1);
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
|
||||
}
|
||||
|
||||
static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
|
||||
@@ -3015,40 +2992,6 @@ static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_dfs_init_radar_specs(struct mt7996_phy *phy)
|
||||
{
|
||||
const struct mt7996_dfs_radar_spec *radar_specs;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
int err, i;
|
||||
|
||||
switch (dev->mt76.region) {
|
||||
case NL80211_DFS_FCC:
|
||||
radar_specs = &fcc_radar_specs;
|
||||
err = mt7996_mcu_set_fcc5_lpn(dev, 8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
case NL80211_DFS_ETSI:
|
||||
radar_specs = &etsi_radar_specs;
|
||||
break;
|
||||
case NL80211_DFS_JP:
|
||||
radar_specs = &jp_radar_specs;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {
|
||||
err = mt7996_mcu_set_radar_th(dev, i,
|
||||
&radar_specs->radar_pattern[i]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th);
|
||||
}
|
||||
|
||||
int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
@@ -3068,10 +3011,6 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
|
||||
goto stop;
|
||||
|
||||
if (prev_state <= MT_DFS_STATE_DISABLED) {
|
||||
err = mt7996_dfs_init_radar_specs(phy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt7996_dfs_start_radar_detector(phy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -37,9 +37,4 @@ struct mt7996_dfs_pattern {
|
||||
u32 min_stgpr_diff;
|
||||
} __packed;
|
||||
|
||||
struct mt7996_dfs_radar_spec {
|
||||
struct mt7996_dfs_pulse pulse_th;
|
||||
struct mt7996_dfs_pattern radar_pattern[16];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,7 +56,7 @@ static int mt7996_start(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
ret = mt7996_mcu_set_hdr_trans(dev, true);
|
||||
if (!ret && is_mt7992(&dev->mt76)) {
|
||||
if (!ret && !is_mt7996(&dev->mt76)) {
|
||||
u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);
|
||||
|
||||
ret = mt7996_mcu_cp_support(dev, queue);
|
||||
@@ -79,6 +79,7 @@ static void mt7996_stop_phy(struct mt7996_phy *phy)
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mt7996_mcu_rdd_resume_tx(phy);
|
||||
mt7996_mcu_set_radio_en(phy, false);
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
@@ -238,10 +239,13 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
link_conf = &vif->bss_conf;
|
||||
|
||||
if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
|
||||
struct mt7996_phy *phy = mt7996_vif_link_phy(link);
|
||||
|
||||
link->mt76.cipher =
|
||||
mt76_connac_mcu_get_cipher(key->cipher);
|
||||
mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
|
||||
&link->mt76, msta_link, true);
|
||||
if (phy)
|
||||
mt7996_mcu_add_bss_info(phy, vif, link_conf,
|
||||
&link->mt76, msta_link, true);
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY)
|
||||
@@ -300,9 +304,16 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
.cmd = SET_KEY,
|
||||
.link_id = link_conf->link_id,
|
||||
};
|
||||
struct mt76_txq *mtxq;
|
||||
int mld_idx, idx, ret;
|
||||
|
||||
if ((mvif->mt76.valid_links & BIT(link_conf->link_id)) &&
|
||||
!mlink->offchannel) {
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
return mt7996_mcu_mld_link_oper(dev, link_conf, link,
|
||||
true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mlink->idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mlink->idx >= mt7996_max_interface_num(dev))
|
||||
return -ENOSPC;
|
||||
@@ -316,7 +327,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
return -ENOSPC;
|
||||
|
||||
link->mld_idx = mld_idx;
|
||||
link->phy = phy;
|
||||
mlink->omac_idx = idx;
|
||||
mlink->band_idx = band_idx;
|
||||
mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;
|
||||
@@ -343,11 +353,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
mt7996_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_AP &&
|
||||
(!mlink->omac_idx || mlink->omac_idx > 3))
|
||||
vif->offload_flags = 0;
|
||||
@@ -370,13 +375,81 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
|
||||
ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
|
||||
|
||||
if (!mlink->wcid->offchannel &&
|
||||
mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)
|
||||
mvif->mt76.deflink_id = link_conf->link_id;
|
||||
if (!mlink->wcid->offchannel) {
|
||||
if (vif->txq &&
|
||||
mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED) {
|
||||
struct mt76_txq *mtxq;
|
||||
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mvif->mt76.deflink_id = link_conf->link_id;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
mvif->mt76.valid_links |= BIT(link_conf->link_id);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
|
||||
if (vif->cfg.assoc && link_conf->beacon_int) {
|
||||
mlink->beacon_mon_interval =
|
||||
msecs_to_jiffies(ieee80211_tu_to_usec(
|
||||
link_conf->beacon_int) / 1000);
|
||||
WRITE_ONCE(mlink->beacon_mon_last, jiffies);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7996_vif_link_destroy(struct mt7996_phy *phy,
|
||||
struct mt7996_vif_link *link,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_sta_link *msta_link = &link->msta_link;
|
||||
unsigned int link_id = msta_link->wcid.link_id;
|
||||
struct mt76_vif_link *mlink = &link->mt76;
|
||||
struct mt7996_key_iter_data it = {
|
||||
.cmd = SET_KEY,
|
||||
.link_id = link_id,
|
||||
};
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
int idx = msta_link->wcid.idx;
|
||||
|
||||
if (!link_conf)
|
||||
link_conf = &vif->bss_conf;
|
||||
|
||||
if (!mlink->wcid->offchannel)
|
||||
ieee80211_iter_keys(phy->mt76->hw, vif, mt7996_key_iter, &it);
|
||||
|
||||
mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
|
||||
CONN_STATE_DISCONNECT, false);
|
||||
mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
|
||||
mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
|
||||
dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
|
||||
if (!mlink->wcid->offchannel)
|
||||
mvif->mt76.valid_links &= ~BIT(link_id);
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (!list_empty(&msta_link->wcid.poll_list))
|
||||
list_del_init(&msta_link->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
|
||||
|
||||
if (mlink != (struct mt76_vif_link *)vif->drv_priv &&
|
||||
!mlink->wcid->offchannel) {
|
||||
rcu_assign_pointer(mlink->mvif->link[link_id], NULL);
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt76_vif_link *mlink)
|
||||
@@ -384,49 +457,43 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
struct mt7996_vif_link *link = container_of(mlink, struct mt7996_vif_link, mt76);
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_sta_link *msta_link = &link->msta_link;
|
||||
unsigned int link_id = msta_link->wcid.link_id;
|
||||
struct mt7996_phy *phy = mphy->priv;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
struct mt7996_key_iter_data it = {
|
||||
.cmd = SET_KEY,
|
||||
.link_id = link_conf->link_id,
|
||||
};
|
||||
int idx = msta_link->wcid.idx;
|
||||
|
||||
if (!mlink->wcid->offchannel)
|
||||
ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
|
||||
/* Hw requires to destroy active links tearing down the interface, so
|
||||
* postpone it removing the interface.
|
||||
*/
|
||||
if (mlink->wcid->offchannel) {
|
||||
mt7996_vif_link_destroy(phy, link, vif, link_conf);
|
||||
} else {
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
mt7996_mcu_mld_reconf_stop_link(phy->dev, vif,
|
||||
BIT(link_id));
|
||||
mt7996_mcu_mld_link_oper(phy->dev, link_conf, link,
|
||||
false);
|
||||
}
|
||||
|
||||
mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
|
||||
CONN_STATE_DISCONNECT, false);
|
||||
mt7996_mcu_add_bss_info(phy, vif, link_conf, mlink, msta_link, false);
|
||||
if (vif->txq && mvif->mt76.deflink_id == link_id) {
|
||||
struct ieee80211_bss_conf *iter;
|
||||
struct mt76_txq *mtxq;
|
||||
|
||||
mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, false);
|
||||
mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
/* Primary link will be removed, look for a new one */
|
||||
for_each_vif_active_link(vif, iter, link_id) {
|
||||
if (link_id == msta_link->wcid.link_id)
|
||||
continue;
|
||||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
link = mt7996_vif_link(phy->dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (!mlink->wcid->offchannel &&
|
||||
mvif->mt76.deflink_id == link_conf->link_id) {
|
||||
struct ieee80211_bss_conf *iter;
|
||||
unsigned int link_id;
|
||||
|
||||
mvif->mt76.deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
for_each_vif_active_link(vif, iter, link_id) {
|
||||
if (link_id != IEEE80211_LINK_UNSPECIFIED) {
|
||||
mtxq->wcid = link->msta_link.wcid.idx;
|
||||
mvif->mt76.deflink_id = link_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mlink->idx);
|
||||
dev->mld_idx_mask &= ~BIT_ULL(link->mld_idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mlink->omac_idx);
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (!list_empty(&msta_link->wcid.poll_list))
|
||||
list_del_init(&msta_link->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
|
||||
}
|
||||
|
||||
static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)
|
||||
@@ -472,6 +539,8 @@ static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled)
|
||||
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),
|
||||
MT_DMA_DCR0_RXD_G5_EN, enabled);
|
||||
mt76_rmw_field(dev, MT_MDP_DCR0,
|
||||
MT_MDP_DCR0_RX_HDR_TRANS_EN, !enabled);
|
||||
mt7996_phy_set_rxfilter(phy);
|
||||
mt7996_mcu_set_sniffer_mode(phy, enabled);
|
||||
}
|
||||
@@ -530,10 +599,29 @@ static void mt7996_remove_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
static void mt7996_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
unsigned long rem_links = mvif->mt76.valid_links;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_radio_data rdata = {};
|
||||
unsigned int link_id;
|
||||
int i;
|
||||
|
||||
/* Remove all active links */
|
||||
for_each_set_bit(link_id, &rem_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
phy = __mt7996_phy(dev, link->msta_link.wcid.phy_idx);
|
||||
if (!phy)
|
||||
continue;
|
||||
|
||||
mt7996_vif_link_destroy(phy, link, vif, NULL);
|
||||
}
|
||||
|
||||
ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,
|
||||
&rdata);
|
||||
mt76_vif_cleanup(&dev->mt76, vif);
|
||||
@@ -811,15 +899,24 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (!link->phy)
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
link->mt76.beacon_mon_interval =
|
||||
msecs_to_jiffies(ieee80211_tu_to_usec(
|
||||
link_conf->beacon_int) / 1000);
|
||||
WRITE_ONCE(link->mt76.beacon_mon_last, jiffies);
|
||||
}
|
||||
|
||||
phy = mt7996_vif_link_phy(link);
|
||||
if (!phy)
|
||||
continue;
|
||||
|
||||
mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
|
||||
mt7996_mcu_add_bss_info(phy, vif, link_conf,
|
||||
&link->mt76, &link->msta_link,
|
||||
true);
|
||||
mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL,
|
||||
@@ -828,6 +925,20 @@ mt7996_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
}
|
||||
|
||||
if ((changed & BSS_CHANGED_ASSOC) && !vif->cfg.assoc &&
|
||||
vif->type == NL80211_IFTYPE_STATION) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned long link_id;
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (link)
|
||||
link->mt76.beacon_mon_interval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
@@ -864,6 +975,10 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
!!(changed & BSS_CHANGED_BSSID));
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7996_mcu_set_protection(phy, link, info->ht_operation_mode,
|
||||
info->use_cts_prot);
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_SLOT) {
|
||||
int slottime = info->use_short_slot ? 9 : 20;
|
||||
|
||||
@@ -927,12 +1042,84 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy = mt7996_band_phy(dev, chandef->chan->band);
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf, vif->bss_conf.enable_beacon);
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt7996_phy *link_phy;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
link_phy = mt7996_vif_link_phy(link);
|
||||
if (link_phy != phy)
|
||||
continue;
|
||||
|
||||
/* Reset beacon when channel switch triggered during CAC to let
|
||||
* FW correctly perform CSA countdown
|
||||
*/
|
||||
if (!cfg80211_reg_can_beacon(hw->wiphy, &phy->mt76->chandef,
|
||||
vif->type))
|
||||
mt7996_mcu_add_beacon(hw, vif, link_conf, false);
|
||||
|
||||
mt7996_mcu_add_beacon(hw, vif, link_conf, true);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy = mt7996_band_phy(dev, chandef->chan->band);
|
||||
struct mt7996_vif_link *link;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
link = mt7996_vif_conf_link(dev, vif, link_conf);
|
||||
if (!link)
|
||||
goto out;
|
||||
|
||||
ret = mt7996_mcu_update_bss_rfch(phy, link);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ieee80211_iterate_stations_mtx(hw, mt7996_mcu_update_sta_rec_bw, link);
|
||||
|
||||
ret = mt7996_mcu_rdd_resume_tx(phy);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_sta_init_txq_wcid(struct ieee80211_sta *sta, int idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
|
||||
struct mt76_txq *mtxq;
|
||||
|
||||
if (!sta->txq[i])
|
||||
continue;
|
||||
|
||||
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
@@ -941,30 +1128,22 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
||||
{
|
||||
struct ieee80211_sta *sta = link_sta->sta;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_phy *phy = link->phy;
|
||||
struct mt7996_phy *phy = mt7996_vif_link_phy(link);
|
||||
struct mt7996_sta_link *msta_link;
|
||||
int idx;
|
||||
|
||||
if (!phy)
|
||||
return -EINVAL;
|
||||
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
|
||||
if (idx < 0)
|
||||
return -ENOSPC;
|
||||
|
||||
if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
|
||||
int i;
|
||||
|
||||
msta_link = &msta->deflink;
|
||||
msta->deflink_id = link_id;
|
||||
msta->seclink_id = msta->deflink_id;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
|
||||
struct mt76_txq *mtxq;
|
||||
|
||||
if (!sta->txq[i])
|
||||
continue;
|
||||
|
||||
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
mt7996_sta_init_txq_wcid(sta, idx);
|
||||
} else {
|
||||
msta_link = kzalloc_obj(*msta_link);
|
||||
if (!msta_link)
|
||||
@@ -1000,9 +1179,17 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
|
||||
struct ieee80211_sta *sta,
|
||||
unsigned int link_id, bool flush)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
if (!msta_link)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (!list_empty(&msta_link->wcid.poll_list))
|
||||
list_del_init(&msta_link->wcid.poll_list);
|
||||
@@ -1011,49 +1198,59 @@ void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
|
||||
mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, unsigned long links)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
unsigned int link_id;
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt7996_sta_link *msta_link = NULL;
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt76_phy *mphy;
|
||||
|
||||
msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
|
||||
lockdep_is_held(&mdev->mutex));
|
||||
if (!msta_link)
|
||||
continue;
|
||||
if (msta_link->wcid.link_valid) {
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
mt7996_mac_sta_deinit_link(dev, msta_link);
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
phy = __mt7996_phy(dev, msta_link->wcid.phy_idx);
|
||||
if (phy)
|
||||
phy->mt76->num_sta--;
|
||||
|
||||
mphy = mt76_vif_link_phy(&link->mt76);
|
||||
if (!mphy)
|
||||
continue;
|
||||
|
||||
mphy->num_sta--;
|
||||
if (msta->deflink_id == link_id) {
|
||||
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
continue;
|
||||
} else if (msta->seclink_id == link_id) {
|
||||
msta->seclink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
}
|
||||
if (msta->seclink_id == link_id) {
|
||||
/* no secondary link available */
|
||||
msta->seclink_id = msta->deflink_id;
|
||||
} else {
|
||||
struct mt7996_sta_link *msta_seclink;
|
||||
|
||||
kfree_rcu(msta_link, rcu_head);
|
||||
/* switch to the secondary link */
|
||||
msta_seclink = mt76_dereference(
|
||||
msta->link[msta->seclink_id],
|
||||
&dev->mt76);
|
||||
if (msta_seclink) {
|
||||
msta->deflink_id = msta->seclink_id;
|
||||
mt7996_sta_init_txq_wcid(sta,
|
||||
msta_seclink->wcid.idx);
|
||||
}
|
||||
}
|
||||
} else if (msta->seclink_id == link_id) {
|
||||
msta->seclink_id = msta->deflink_id;
|
||||
}
|
||||
msta_link->wcid.link_valid = false;
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
rcu_assign_pointer(msta->link[link_id], NULL);
|
||||
rcu_assign_pointer(dev->mt76.wcid[msta_link->wcid.idx], NULL);
|
||||
mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
|
||||
if (msta_link != &msta->deflink)
|
||||
kfree_rcu(msta_link, rcu_head);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, unsigned long links,
|
||||
bool flush)
|
||||
{
|
||||
unsigned int link_id;
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS)
|
||||
mt7996_mac_sta_remove_link(dev, sta, link_id, flush);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1067,11 +1264,15 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt76_phy *mphy;
|
||||
|
||||
if (rcu_access_pointer(msta->link[link_id]))
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
if (msta_link) {
|
||||
msta_link->wcid.link_valid = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
link_conf = link_conf_dereference_protected(vif, link_id);
|
||||
if (!link_conf) {
|
||||
@@ -1108,7 +1309,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
|
||||
error_unlink:
|
||||
mt7996_mac_sta_remove_links(dev, vif, sta, new_links);
|
||||
mt7996_mac_sta_remove_links(dev, vif, sta, new_links, true);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1125,7 +1326,7 @@ mt7996_mac_sta_change_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mt7996_mac_sta_remove_links(dev, vif, sta, rem);
|
||||
mt7996_mac_sta_remove_links(dev, vif, sta, rem, false);
|
||||
ret = mt7996_mac_sta_add_links(dev, vif, sta, add);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
@@ -1234,10 +1435,12 @@ static void
|
||||
mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
unsigned long links = sta->valid_links ? sta->valid_links : BIT(0);
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
int i;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt7996_mac_sta_remove_links(dev, vif, sta, links);
|
||||
for (i = 0; i < ARRAY_SIZE(msta->link); i++)
|
||||
mt7996_mac_sta_remove_link(dev, sta, i, true);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
@@ -1489,8 +1692,8 @@ mt7996_get_stats(struct ieee80211_hw *hw,
|
||||
|
||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link)
|
||||
{
|
||||
struct mt7996_phy *phy = mt7996_vif_link_phy(link);
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy = link->phy;
|
||||
union {
|
||||
u64 t64;
|
||||
u32 t32[2];
|
||||
@@ -1549,7 +1752,7 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
n = link->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
|
||||
: link->mt76.omac_idx;
|
||||
phy = link->phy;
|
||||
phy = mt7996_vif_link_phy(link);
|
||||
if (!phy)
|
||||
goto unlock;
|
||||
|
||||
@@ -1583,7 +1786,7 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (!link)
|
||||
goto unlock;
|
||||
|
||||
phy = link->phy;
|
||||
phy = mt7996_vif_link_phy(link);
|
||||
if (!phy)
|
||||
goto unlock;
|
||||
|
||||
@@ -1713,9 +1916,14 @@ static void mt7996_link_rate_ctrl_update(void *data,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
{
|
||||
struct mt7996_sta *msta = msta_link->sta;
|
||||
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct mt7996_phy *phy = mt7996_vif_link_phy(&msta->vif->deflink);
|
||||
struct mt7996_dev *dev;
|
||||
u32 *changed = data;
|
||||
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
dev = phy->dev;
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
msta_link->changed |= *changed;
|
||||
@@ -2204,6 +2412,10 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
path->mtk_wdma.wdma_idx = wed->wdma_idx;
|
||||
else
|
||||
#endif
|
||||
if (is_mt7996(&dev->mt76) && mt76_npu_device_active(&dev->mt76) &&
|
||||
msta_link->wcid.phy_idx == MT_BAND2)
|
||||
path->mtk_wdma.wdma_idx = 1;
|
||||
else
|
||||
path->mtk_wdma.wdma_idx = link->mt76.band_idx;
|
||||
path->mtk_wdma.bss = link->mt76.idx;
|
||||
path->mtk_wdma.queue = 0;
|
||||
@@ -2275,6 +2487,21 @@ mt7996_reconfig_complete(struct ieee80211_hw *hw,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_set_eml_op_mode(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_eml_params *eml_params)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
ret = mt7996_mcu_set_emlsr_mode(dev, vif, sta, eml_params);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7996_ops = {
|
||||
.add_chanctx = mt76_add_chanctx,
|
||||
.remove_chanctx = mt76_remove_chanctx,
|
||||
@@ -2306,6 +2533,7 @@ const struct ieee80211_ops mt7996_ops = {
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
.get_txpower = mt7996_get_txpower,
|
||||
.channel_switch_beacon = mt7996_channel_switch_beacon,
|
||||
.post_channel_switch = mt7996_post_channel_switch,
|
||||
.get_stats = mt7996_get_stats,
|
||||
.get_et_sset_count = mt7996_get_et_sset_count,
|
||||
.get_et_stats = mt7996_get_et_stats,
|
||||
@@ -2337,4 +2565,5 @@ const struct ieee80211_ops mt7996_ops = {
|
||||
.change_vif_links = mt7996_change_vif_links,
|
||||
.change_sta_links = mt7996_mac_sta_change_links,
|
||||
.reconfig_complete = mt7996_reconfig_complete,
|
||||
.set_eml_op_mode = mt7996_set_eml_op_mode,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,8 +25,8 @@ struct mt7996_mcu_rxd {
|
||||
};
|
||||
|
||||
struct mt7996_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 __rsv[3];
|
||||
__le16 cid;
|
||||
u8 __rsv[2];
|
||||
__le32 status; /* 0: success, others: fail */
|
||||
} __packed;
|
||||
|
||||
@@ -52,12 +52,10 @@ struct mt7996_mcu_thermal_enable {
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_csa_notify {
|
||||
struct mt7996_mcu_rxd rxd;
|
||||
|
||||
struct mt7996_mcu_countdown_notify {
|
||||
u8 omac_idx;
|
||||
u8 csa_count;
|
||||
u8 band_idx;
|
||||
u8 count;
|
||||
u8 csa_failure_reason; /* 0: success, 1: beacon disabled */
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
@@ -147,7 +145,7 @@ struct mt7996_mcu_background_chain_ctrl {
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_eeprom {
|
||||
struct mt7996_mcu_eeprom_update {
|
||||
u8 _rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
@@ -157,6 +155,43 @@ struct mt7996_mcu_eeprom {
|
||||
__le16 buf_len;
|
||||
} __packed;
|
||||
|
||||
union eeprom_data {
|
||||
struct {
|
||||
__le32 data_len;
|
||||
DECLARE_FLEX_ARRAY(u8, data);
|
||||
} ext_eeprom;
|
||||
DECLARE_FLEX_ARRAY(u8, efuse);
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_eeprom_info {
|
||||
u8 _rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_eeprom_access {
|
||||
struct mt7996_mcu_eeprom_info info;
|
||||
union eeprom_data eeprom;
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_eeprom_access_event {
|
||||
u8 _rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le32 version;
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
__le32 size;
|
||||
__le32 magic_no;
|
||||
__le32 type;
|
||||
__le32 rsv[4];
|
||||
union eeprom_data eeprom;
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_phy_rx_info {
|
||||
u8 category;
|
||||
u8 rate;
|
||||
@@ -414,7 +449,16 @@ struct bss_bcn_cntdwn_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 cnt;
|
||||
u8 rsv[3];
|
||||
union {
|
||||
struct {
|
||||
bool static_pp;
|
||||
bool abort;
|
||||
} csa;
|
||||
struct {
|
||||
bool abort;
|
||||
} cca;
|
||||
};
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
struct bss_bcn_mbss_tlv {
|
||||
@@ -474,6 +518,24 @@ struct bss_mld_tlv {
|
||||
u8 __rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct bss_prot_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le32 prot_mode;
|
||||
} __packed;
|
||||
|
||||
struct bss_mld_link_op_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 group_mld_id;
|
||||
u8 own_mld_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 remap_idx;
|
||||
u8 link_operation;
|
||||
u8 link_id;
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_ht_uni {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -647,6 +709,28 @@ struct mld_setup_link {
|
||||
u8 __rsv;
|
||||
} __packed;
|
||||
|
||||
struct mld_req_hdr {
|
||||
u8 ver;
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
u8 mld_idx;
|
||||
u8 flag;
|
||||
u8 rsv[3];
|
||||
u8 buf[];
|
||||
} __packed;
|
||||
|
||||
struct mld_reconf_stop_link {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le16 link_bitmap;
|
||||
u8 rsv[2];
|
||||
u8 bss_idx[16];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
UNI_CMD_MLD_RECONF_AP_REM_TIMER = 0x03,
|
||||
UNI_CMD_MLD_RECONF_STOP_LINK = 0x04,
|
||||
};
|
||||
|
||||
struct hdr_trans_en {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -791,6 +875,11 @@ enum {
|
||||
UNI_CHANNEL_RX_PATH,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_CHIP_CONFIG_NIC_CAPA = 3,
|
||||
UNI_CHIP_CONFIG_DUP_WTBL = 4,
|
||||
};
|
||||
|
||||
#define MT7996_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \
|
||||
sizeof(struct mt76_connac_bss_basic_tlv) + \
|
||||
sizeof(struct bss_rlm_tlv) + \
|
||||
@@ -837,6 +926,7 @@ enum {
|
||||
enum {
|
||||
UNI_BAND_CONFIG_RADIO_ENABLE,
|
||||
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
|
||||
UNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -856,6 +946,10 @@ enum {
|
||||
UNI_EFUSE_BUFFER_RD,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_EXT_EEPROM_ACCESS = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_VOW_DRR_CTRL,
|
||||
UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
#define MT7996_RX_RING_SIZE 1536
|
||||
#define MT7996_RX_MCU_RING_SIZE 512
|
||||
#define MT7996_RX_MCU_RING_SIZE_WA 1024
|
||||
#define MT7996_NPU_TX_RING_SIZE 1024
|
||||
#define MT7996_NPU_RX_RING_SIZE 1024
|
||||
#define MT7996_NPU_TXD_SIZE 3
|
||||
|
||||
/* scatter-gather of mcu event is not supported in connac3 */
|
||||
#define MT7996_RX_MCU_BUF_SIZE (2048 + \
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||
@@ -60,6 +64,11 @@
|
||||
#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
|
||||
#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
|
||||
|
||||
#define MT7992_FIRMWARE_WA_24 "mediatek/mt7996/mt7992_wa_24.bin"
|
||||
#define MT7992_FIRMWARE_WM_24 "mediatek/mt7996/mt7992_wm_24.bin"
|
||||
#define MT7992_FIRMWARE_DSP_24 "mediatek/mt7996/mt7992_dsp_24.bin"
|
||||
#define MT7992_ROM_PATCH_24 "mediatek/mt7996/mt7992_rom_patch_24.bin"
|
||||
|
||||
#define MT7990_FIRMWARE_WA ""
|
||||
#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
|
||||
#define MT7990_FIRMWARE_DSP ""
|
||||
@@ -75,12 +84,14 @@
|
||||
#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 MT7992_EEPROM_DEFAULT_24 "mediatek/mt7996/mt7992_eeprom_24_2i5i.bin"
|
||||
|
||||
#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"
|
||||
#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"
|
||||
|
||||
#define MT7996_EEPROM_SIZE 7680
|
||||
#define MT7996_EEPROM_BLOCK_SIZE 16
|
||||
#define MT7996_EXT_EEPROM_BLOCK_SIZE 1024
|
||||
#define MT7996_TOKEN_SIZE 16384
|
||||
#define MT7996_HW_TOKEN_SIZE 8192
|
||||
|
||||
@@ -153,6 +164,7 @@ enum mt7996_var_type {
|
||||
enum mt7992_var_type {
|
||||
MT7992_VAR_TYPE_44,
|
||||
MT7992_VAR_TYPE_23,
|
||||
MT7992_VAR_TYPE_24,
|
||||
};
|
||||
|
||||
enum mt7990_var_type {
|
||||
@@ -165,6 +177,18 @@ enum mt7996_fem_type {
|
||||
MT7996_FEM_MIX,
|
||||
};
|
||||
|
||||
enum mt7996_eeprom_mode {
|
||||
EEPROM_MODE_DEFAULT_BIN,
|
||||
EEPROM_MODE_EFUSE,
|
||||
EEPROM_MODE_FLASH,
|
||||
EEPROM_MODE_EXT,
|
||||
};
|
||||
|
||||
#define MT7996_EFUSE_BASE_OFFS_ADIE0 0x400
|
||||
#define MT7996_EFUSE_BASE_OFFS_ADIE1 0x1e00
|
||||
#define MT7996_EFUSE_BASE_OFFS_ADIE2 0x1200
|
||||
#define MT7992_EFUSE_BASE_OFFS_ADIE1 0x1200
|
||||
|
||||
enum mt7996_txq_id {
|
||||
MT7996_TXQ_FWDL = 16,
|
||||
MT7996_TXQ_MCU_WM,
|
||||
@@ -252,8 +276,6 @@ struct mt7996_vif_link {
|
||||
struct mt76_vif_link mt76; /* must be first */
|
||||
|
||||
struct mt7996_sta_link msta_link;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
struct cfg80211_bitrate_mask bitrate_mask;
|
||||
|
||||
u8 mld_idx;
|
||||
@@ -377,6 +399,7 @@ struct mt7996_phy {
|
||||
|
||||
bool has_aux_rx;
|
||||
bool counter_reset;
|
||||
bool rdd_tx_paused;
|
||||
};
|
||||
|
||||
struct mt7996_dev {
|
||||
@@ -436,7 +459,7 @@ struct mt7996_dev {
|
||||
|
||||
u32 hw_pattern;
|
||||
|
||||
bool flash_mode:1;
|
||||
u8 eeprom_mode;
|
||||
bool has_eht:1;
|
||||
|
||||
struct {
|
||||
@@ -473,6 +496,8 @@ struct mt7996_dev {
|
||||
struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];
|
||||
} wed_rro;
|
||||
|
||||
dma_addr_t npu_txd_addr[2 * MT7996_NPU_TXD_SIZE];
|
||||
|
||||
bool ibf;
|
||||
u8 fw_debug_wm;
|
||||
u8 fw_debug_wa;
|
||||
@@ -669,6 +694,8 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt76_vif_link *mlink,
|
||||
struct mt7996_sta_link *msta_link, int enable);
|
||||
int mt7996_mcu_update_bss_rfch(struct mt7996_phy *phy,
|
||||
struct mt7996_vif_link *link);
|
||||
int mt7996_mcu_add_sta(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
@@ -678,6 +705,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
|
||||
int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta);
|
||||
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
@@ -707,8 +735,9 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
void *data, u8 link_id, u32 field);
|
||||
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
|
||||
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_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
|
||||
enum mt7996_eeprom_mode mode);
|
||||
int mt7996_mcu_get_efuse_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);
|
||||
int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);
|
||||
@@ -719,6 +748,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_protection(struct mt7996_phy *phy, struct mt7996_vif_link *link,
|
||||
u8 ht_mode, bool use_cts_prot);
|
||||
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);
|
||||
@@ -726,6 +757,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
|
||||
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
|
||||
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_rdd_resume_tx(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
|
||||
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
@@ -743,6 +775,13 @@ 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);
|
||||
int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_mld_reconf_stop_link(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
u16 removed_links);
|
||||
int mt7996_mcu_mld_link_oper(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt7996_vif_link *link, bool add);
|
||||
|
||||
static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)
|
||||
{
|
||||
@@ -802,6 +841,11 @@ static inline bool mt7996_has_wa(struct mt7996_dev *dev)
|
||||
return !is_mt7990(&dev->mt76);
|
||||
}
|
||||
|
||||
static inline bool mt7996_has_ext_eeprom(struct mt7996_dev *dev)
|
||||
{
|
||||
return !is_mt7996(&dev->mt76);
|
||||
}
|
||||
|
||||
void mt7996_mac_init(struct mt7996_dev *dev);
|
||||
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
|
||||
@@ -823,8 +867,9 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
u8 flowid);
|
||||
void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
void mt7996_mac_sta_remove_link(struct mt7996_dev *dev,
|
||||
struct ieee80211_sta *sta,
|
||||
unsigned int link_id, bool flush);
|
||||
void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_twt_setup *twt);
|
||||
@@ -861,6 +906,10 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
|
||||
int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_eml_params *eml_params);
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir);
|
||||
@@ -877,12 +926,19 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
|
||||
#endif
|
||||
|
||||
int mt7996_dma_rro_init(struct mt7996_dev *dev);
|
||||
void mt7996_dma_rro_start(struct mt7996_dev *dev);
|
||||
|
||||
#ifdef CONFIG_MT7996_NPU
|
||||
int __mt7996_npu_hw_init(struct mt7996_dev *dev);
|
||||
int mt7996_npu_hw_init(struct mt7996_dev *dev);
|
||||
int mt7996_npu_hw_stop(struct mt7996_dev *dev);
|
||||
int mt7996_npu_rx_queues_init(struct mt7996_dev *dev);
|
||||
#else
|
||||
static inline int __mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -8,55 +8,20 @@
|
||||
|
||||
#include "mt7996.h"
|
||||
|
||||
static int mt7996_npu_offload_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
static int mt7992_npu_txrx_offload_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
|
||||
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
|
||||
u32 val, hif1_ofs = 0, dma_addr;
|
||||
u32 dma_addr;
|
||||
int i, err;
|
||||
|
||||
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
|
||||
(val >> 16) & 0xffff, val & 0xffff);
|
||||
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
|
||||
dev->mt76.mmio.npu_type, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe port type\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (dev->hif2)
|
||||
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
|
||||
for (i = MT_BAND0; i < MT_BAND2; i++) {
|
||||
dma_addr = phy_addr;
|
||||
if (i)
|
||||
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90 +
|
||||
hif1_ofs;
|
||||
else
|
||||
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
|
||||
|
||||
err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, i, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_RX_RING_SIZE, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc size\n");
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -97,10 +62,173 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev,
|
||||
phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rro_ack_sn desc addr\n");
|
||||
"failed setting NPU wlan tx desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7996_npu_txrx_offload_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
|
||||
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
|
||||
u32 dma_addr;
|
||||
int err;
|
||||
|
||||
/* npu rx rro ring0 */
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_RX_RING_SIZE, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* npu rx rro ring1 */
|
||||
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* msdu pg 2GHz */
|
||||
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0) + 0xa0;
|
||||
err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 5, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_NPU_RX_RING_SIZE / 4, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* msdu pg 5GHz */
|
||||
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1) + 0xb0;
|
||||
err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 6, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_NPU_RX_RING_SIZE / 2, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* msdu pg 6GHz */
|
||||
dma_addr = phy_addr + MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2) + 0xc0;
|
||||
err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 7, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_NPU_RX_RING_SIZE, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ind cmd ring */
|
||||
err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
phy_addr + MT_RXQ_RRO_IND_RING_BASE,
|
||||
GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 8, WLAN_FUNC_SET_WAIT_DESC,
|
||||
MT7996_RX_RING_SIZE, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan rx desc size\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 3, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
|
||||
phy_addr + MT_RRO_ACK_SN_CTRL, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan tx desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* npu tx */
|
||||
dma_addr = phy_addr + MT_TXQ_RING_BASE(1) + 0x120;
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan tx desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dma_addr = phy_addr + MT_TXQ_RING_BASE(0) + 0x150 + hif1_ofs;
|
||||
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan tx desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7996_npu_offload_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_NPU_VERSION,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev, "failed getting NPU fw version\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(dev->mt76.dev, "NPU version: %0d.%d\n",
|
||||
(val >> 16) & 0xffff, val & 0xffff);
|
||||
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
|
||||
dev->mt76.mmio.npu_type, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe port type\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (is_mt7996(&dev->mt76))
|
||||
err = mt7996_npu_txrx_offload_init(dev, npu);
|
||||
else
|
||||
err = mt7992_npu_txrx_offload_init(dev, npu);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
|
||||
MT7996_HW_TOKEN_SIZE, GFP_KERNEL);
|
||||
if (err)
|
||||
@@ -111,6 +239,41 @@ static int mt7996_npu_offload_init(struct mt7996_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7992_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
|
||||
{
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
err = mt76_npu_get_msg(npu, 0, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retrieving NPU wlan rx ring0 addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retrieving NPU wlan rx ring1 addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retrieving NPU wlan rxdmad_c ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
|
||||
{
|
||||
u32 val;
|
||||
@@ -125,80 +288,107 @@ static int mt7996_npu_rxd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 1, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
err = mt76_npu_get_msg(npu, 2, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan rx ring1 addr\n");
|
||||
"failed retriving NPU wlan rx ring2 addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND1].regs->desc_base);
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 9, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
/* msdu pg ring */
|
||||
err = mt76_npu_get_msg(npu, 10, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan rxdmad_c ring addr\n");
|
||||
"failed retriving NPU wlan msdu pg ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_RXDMAD_C].regs->desc_base);
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND0].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 11, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan msdu pg ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND1].regs->desc_base);
|
||||
|
||||
err = mt76_npu_get_msg(npu, 12, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan msdu pg ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_MSDU_PAGE_BAND2].regs->desc_base);
|
||||
|
||||
/* ind_cmd ring */
|
||||
err = mt76_npu_get_msg(npu, 8, WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan ind_cmd ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.q_rx[MT_RXQ_RRO_IND].regs->desc_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
|
||||
{
|
||||
int i, err;
|
||||
const enum mt76_band_id band_list[] = {
|
||||
MT_BAND0,
|
||||
is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND1,
|
||||
};
|
||||
int i, index = 0;
|
||||
|
||||
for (i = MT_BAND0; i < MT_BAND2; i++) {
|
||||
dma_addr_t dma_addr;
|
||||
BUILD_BUG_ON(ARRAY_SIZE(band_list) * 3 !=
|
||||
ARRAY_SIZE(dev->npu_txd_addr));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(band_list); i++) {
|
||||
int err, band = band_list[i], phy_id;
|
||||
u32 val;
|
||||
|
||||
err = mt76_npu_get_msg(npu, i + 5,
|
||||
err = mt76_npu_get_msg(npu, band + 5,
|
||||
WLAN_FUNC_GET_WAIT_RXDESC_BASE,
|
||||
&val, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed retriving NPU wlan tx ring addr\n");
|
||||
"failed retrieving NPU wlan tx ring addr\n");
|
||||
return err;
|
||||
}
|
||||
writel(val, &dev->mt76.phys[i]->q_tx[0]->regs->desc_base);
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
256 * MT7996_TX_RING_SIZE,
|
||||
&dma_addr, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
phy_id = is_mt7996(&dev->mt76) ? band == MT_BAND0 ? 1 : 0
|
||||
: band;
|
||||
writel(val, &dev->mt76.phys[phy_id]->q_tx[0]->regs->desc_base);
|
||||
|
||||
err = mt76_npu_send_msg(npu, i,
|
||||
err = mt76_npu_send_msg(npu, band,
|
||||
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
|
||||
dma_addr, GFP_KERNEL);
|
||||
dev->npu_txd_addr[index++], GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan queue buf addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
256 * MT7996_TX_RING_SIZE,
|
||||
&dma_addr, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
err = mt76_npu_send_msg(npu, i + 5,
|
||||
err = mt76_npu_send_msg(npu, band + 5,
|
||||
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
|
||||
dma_addr, GFP_KERNEL);
|
||||
dev->npu_txd_addr[index++],
|
||||
GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan tx buf addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
|
||||
&dma_addr, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
err = mt76_npu_send_msg(npu, i + 10,
|
||||
err = mt76_npu_send_msg(npu, band + 10,
|
||||
WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
|
||||
dma_addr, GFP_KERNEL);
|
||||
dev->npu_txd_addr[index++],
|
||||
GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan tx buf base\n");
|
||||
@@ -212,8 +402,9 @@ static int mt7996_npu_txd_init(struct mt7996_dev *dev, struct airoha_npu *npu)
|
||||
static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN_WA];
|
||||
int qid = is_mt7996(&dev->mt76) ? MT_RXQ_TXFREE_BAND0 : MT_RXQ_MAIN_WA;
|
||||
phys_addr_t phy_addr = dev->mt76.mmio.phy_addr;
|
||||
struct mt76_queue *q = &dev->mt76.q_rx[qid];
|
||||
int err;
|
||||
|
||||
err = mt76_npu_send_msg(npu, 0,
|
||||
@@ -233,7 +424,8 @@ static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
phy_addr += MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA) + 0x20;
|
||||
phy_addr += MT_RXQ_RING_BASE(qid);
|
||||
phy_addr += is_mt7996(&dev->mt76) ? 0x90 : 0x20;
|
||||
err = mt76_npu_send_msg(npu, 10, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
phy_addr, GFP_KERNEL);
|
||||
if (err)
|
||||
@@ -242,11 +434,54 @@ static int mt7996_npu_rx_event_init(struct mt7996_dev *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7996_npu_set_pcie_addr(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
u32 hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
|
||||
dma_addr_t dma_addr = dev->mt76.mmio.phy_addr;
|
||||
int err;
|
||||
|
||||
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0) + 0x80;
|
||||
err = mt76_npu_send_msg(npu, 0, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dma_addr = dev->mt76.mmio.phy_addr + hif1_ofs;
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + 0x60;
|
||||
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
} else {
|
||||
dma_addr += MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + 0x90;
|
||||
err = mt76_npu_send_msg(npu, 1, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
dma_addr, GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (err)
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7996_npu_tx_done_init(struct mt7996_dev *dev,
|
||||
struct airoha_npu *npu)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* rro ring cpu idx */
|
||||
err = mt76_npu_send_msg(npu, 15, WLAN_FUNC_SET_WAIT_PCIE_ADDR,
|
||||
0, GFP_KERNEL);
|
||||
if (err) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"failed setting NPU wlan PCIe desc addr\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt76_npu_send_msg(npu, 2, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
|
||||
0, GFP_KERNEL);
|
||||
if (err) {
|
||||
@@ -278,40 +513,79 @@ int mt7996_npu_rx_queues_init(struct mt7996_dev *dev)
|
||||
&dev->mt76.q_rx[MT_RXQ_NPU1]);
|
||||
}
|
||||
|
||||
int mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
int __mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
{
|
||||
struct airoha_npu *npu;
|
||||
int i, err = 0;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
int i, err;
|
||||
|
||||
npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
|
||||
if (!npu)
|
||||
goto unlock;
|
||||
return 0;
|
||||
|
||||
err = mt7996_npu_offload_init(dev, npu);
|
||||
if (err)
|
||||
goto unlock;
|
||||
return err;
|
||||
|
||||
if (is_mt7996(&dev->mt76))
|
||||
err = mt7996_npu_rxd_init(dev, npu);
|
||||
else
|
||||
err = mt7992_npu_rxd_init(dev, npu);
|
||||
|
||||
err = mt7996_npu_rxd_init(dev, npu);
|
||||
if (err)
|
||||
goto unlock;
|
||||
return err;
|
||||
|
||||
err = mt7996_npu_txd_init(dev, npu);
|
||||
if (err)
|
||||
goto unlock;
|
||||
return err;
|
||||
|
||||
err = mt7996_npu_rx_event_init(dev, npu);
|
||||
if (err)
|
||||
goto unlock;
|
||||
return err;
|
||||
|
||||
err = mt7996_npu_set_pcie_addr(dev, npu);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt7996_npu_tx_done_init(dev, npu);
|
||||
if (err)
|
||||
goto unlock;
|
||||
return err;
|
||||
|
||||
for (i = MT_RXQ_NPU0; i <= MT_RXQ_NPU1; i++)
|
||||
airoha_npu_wlan_enable_irq(npu, i - MT_RXQ_NPU0);
|
||||
unlock:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(dev->npu_txd_addr) % 3);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->npu_txd_addr); i += 3) {
|
||||
int band = i && is_mt7996(&dev->mt76) ? MT_BAND2 : MT_BAND0;
|
||||
u32 size = is_mt7996(&dev->mt76) ? band == MT_BAND2
|
||||
? MT7996_NPU_TX_RING_SIZE
|
||||
: MT7996_NPU_RX_RING_SIZE / 2
|
||||
: MT7996_TX_RING_SIZE;
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
|
||||
&dev->npu_txd_addr[i], GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * size,
|
||||
&dev->npu_txd_addr[i + 1],
|
||||
GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dmam_alloc_coherent(dev->mt76.dma_dev, 256 * 1024,
|
||||
&dev->npu_txd_addr[i + 2],
|
||||
GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
err = __mt7996_npu_hw_init(dev);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return err;
|
||||
@@ -320,33 +594,38 @@ int mt7996_npu_hw_init(struct mt7996_dev *dev)
|
||||
int mt7996_npu_hw_stop(struct mt7996_dev *dev)
|
||||
{
|
||||
struct airoha_npu *npu;
|
||||
int i, err;
|
||||
int i, err = 0;
|
||||
u32 info;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
npu = rcu_dereference_protected(dev->mt76.mmio.npu, &dev->mt76.mutex);
|
||||
if (!npu)
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
err = mt76_npu_send_msg(npu, 4, WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
|
||||
0, GFP_KERNEL);
|
||||
if (err)
|
||||
return err;
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
err = mt76_npu_get_msg(npu, 3, WLAN_FUNC_GET_WAIT_NPU_INFO,
|
||||
&info, GFP_KERNEL);
|
||||
if (err)
|
||||
continue;
|
||||
if (!err && !info)
|
||||
break;
|
||||
|
||||
if (info) {
|
||||
err = -ETIMEDOUT;
|
||||
continue;
|
||||
}
|
||||
err = -ETIMEDOUT;
|
||||
usleep_range(10000, 15000);
|
||||
}
|
||||
|
||||
if (!err)
|
||||
err = mt76_npu_send_msg(npu, 6,
|
||||
WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
|
||||
0, GFP_KERNEL);
|
||||
else
|
||||
dev_err(dev->mt76.dev, "npu stop failed\n");
|
||||
unlock:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,9 @@ enum offs_rev {
|
||||
#define MT_MDP_BASE 0x820cc000
|
||||
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
|
||||
|
||||
#define MT_MDP_DCR0 MT_MDP(0x800)
|
||||
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
|
||||
|
||||
#define MT_MDP_DCR2 MT_MDP(0x8e8)
|
||||
#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
|
||||
|
||||
@@ -733,7 +736,15 @@ enum offs_rev {
|
||||
#define MT_HW_REV 0x70010204
|
||||
#define MT_HW_REV1 0x8a00
|
||||
|
||||
#define MT_WF_L05_RST 0x70028550
|
||||
#define MT_WF_L05_RST_WF_RST_MASK GENMASK(4, 0)
|
||||
|
||||
#define MT_WF_SUBSYS_RST 0x70028600
|
||||
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST BIT(0)
|
||||
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT BIT(5)
|
||||
#define MT_WF_SUBSYS_RST_BYPASS_WFDMA_SLP_PROT BIT(6)
|
||||
#define MT_WF_SUBSYS_RST_BYPASS_WFDMA2_SLP_PROT BIT(16)
|
||||
#define MT_WF_SUBSYS_RST_WHOLE_PATH_RST_REVERT_CYCLE GENMASK(15, 8)
|
||||
|
||||
/* PCIE MAC */
|
||||
#define MT_PCIE_MAC_BASE 0x74030000
|
||||
|
||||
@@ -390,6 +390,36 @@ int mt76_npu_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_npu_net_setup_tc);
|
||||
|
||||
int mt76_npu_send_txrx_addr(struct mt76_dev *dev, int ifindex,
|
||||
u32 direction, u32 i_count_addr,
|
||||
u32 o_status_addr, u32 o_count_addr)
|
||||
{
|
||||
struct {
|
||||
__le32 dir;
|
||||
__le32 in_count_addr;
|
||||
__le32 out_status_addr;
|
||||
__le32 out_count_addr;
|
||||
} info = {
|
||||
.dir = cpu_to_le32(direction),
|
||||
.in_count_addr = cpu_to_le32(i_count_addr),
|
||||
.out_status_addr = cpu_to_le32(o_status_addr),
|
||||
.out_count_addr = cpu_to_le32(o_count_addr),
|
||||
};
|
||||
struct airoha_npu *npu;
|
||||
int err = -ENODEV;
|
||||
|
||||
rcu_read_lock();
|
||||
npu = rcu_dereference(dev->mmio.npu);
|
||||
if (npu)
|
||||
err = airoha_npu_wlan_send_msg(npu, ifindex,
|
||||
WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
|
||||
&info, sizeof(info), GFP_ATOMIC);
|
||||
rcu_read_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_npu_send_txrx_addr);
|
||||
|
||||
void mt76_npu_disable_irqs(struct mt76_dev *dev)
|
||||
{
|
||||
struct airoha_npu *npu;
|
||||
@@ -420,10 +450,6 @@ int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type)
|
||||
struct airoha_npu *npu;
|
||||
int err = 0;
|
||||
|
||||
/* NPU offloading is only supported by MT7992 */
|
||||
if (!is_mt7992(dev))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
npu = airoha_npu_get(dev->dev);
|
||||
@@ -456,7 +482,8 @@ int mt76_npu_init(struct mt76_dev *dev, phys_addr_t phy_addr, int type)
|
||||
dev->mmio.phy_addr = phy_addr;
|
||||
dev->mmio.npu_type = type;
|
||||
/* NPU offloading requires HW-RRO for RX packet reordering. */
|
||||
dev->hwrro_mode = MT76_HWRRO_V3_1;
|
||||
dev->hwrro_mode = is_mt7996(dev) ? MT76_HWRRO_V3 : MT76_HWRRO_V3_1;
|
||||
dev->rx_token_size = 32768;
|
||||
|
||||
rcu_assign_pointer(dev->mmio.npu, npu);
|
||||
rcu_assign_pointer(dev->mmio.ppe_dev, ppe_dev);
|
||||
|
||||
@@ -16,9 +16,11 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
|
||||
|
||||
clear_bit(MT76_SCANNING, &phy->state);
|
||||
|
||||
if (dev->scan.chan && phy->main_chandef.chan &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state)) {
|
||||
mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
mt76_offchannel_notify(phy, false);
|
||||
}
|
||||
mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
|
||||
memset(&dev->scan, 0, sizeof(dev->scan));
|
||||
if (!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
@@ -27,6 +29,10 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
|
||||
|
||||
void mt76_abort_scan(struct mt76_dev *dev)
|
||||
{
|
||||
spin_lock_bh(&dev->scan_lock);
|
||||
dev->scan.beacon_wait = false;
|
||||
spin_unlock_bh(&dev->scan_lock);
|
||||
|
||||
cancel_delayed_work_sync(&dev->scan_work);
|
||||
mt76_scan_complete(dev, true);
|
||||
}
|
||||
@@ -79,6 +85,27 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void mt76_scan_rx_beacon(struct mt76_dev *dev, struct ieee80211_channel *chan)
|
||||
{
|
||||
struct mt76_phy *phy;
|
||||
|
||||
spin_lock(&dev->scan_lock);
|
||||
|
||||
if (!dev->scan.beacon_wait || dev->scan.beacon_received ||
|
||||
dev->scan.chan != chan)
|
||||
goto out;
|
||||
|
||||
phy = dev->scan.phy;
|
||||
if (!phy)
|
||||
goto out;
|
||||
|
||||
dev->scan.beacon_received = true;
|
||||
ieee80211_queue_delayed_work(phy->hw, &dev->scan_work, 0);
|
||||
|
||||
out:
|
||||
spin_unlock(&dev->scan_lock);
|
||||
}
|
||||
|
||||
void mt76_scan_work(struct work_struct *work)
|
||||
{
|
||||
struct mt76_dev *dev = container_of(work, struct mt76_dev,
|
||||
@@ -87,35 +114,60 @@ void mt76_scan_work(struct work_struct *work)
|
||||
struct cfg80211_chan_def chandef = {};
|
||||
struct mt76_phy *phy = dev->scan.phy;
|
||||
int duration = HZ / 9; /* ~110 ms */
|
||||
bool beacon_rx, offchannel = true;
|
||||
int i;
|
||||
|
||||
if (!phy || !req)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->scan_lock);
|
||||
beacon_rx = dev->scan.beacon_wait && dev->scan.beacon_received;
|
||||
dev->scan.beacon_wait = false;
|
||||
spin_unlock_bh(&dev->scan_lock);
|
||||
|
||||
if (beacon_rx)
|
||||
goto probe;
|
||||
|
||||
if (dev->scan.chan_idx >= req->n_channels) {
|
||||
mt76_scan_complete(dev, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->scan.chan && phy->num_sta) {
|
||||
if (dev->scan.chan && phy->num_sta && phy->offchannel) {
|
||||
dev->scan.chan = NULL;
|
||||
mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
mt76_offchannel_notify(phy, 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);
|
||||
offchannel = mt76_offchannel_chandef(phy, dev->scan.chan, &chandef);
|
||||
|
||||
if (!req->n_ssids ||
|
||||
chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
|
||||
if (offchannel)
|
||||
mt76_offchannel_notify(phy, true);
|
||||
mt76_set_channel(phy, &chandef, offchannel);
|
||||
|
||||
if (!req->n_ssids)
|
||||
goto out;
|
||||
|
||||
duration = HZ / 16; /* ~60 ms */
|
||||
if (chandef.chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) {
|
||||
spin_lock_bh(&dev->scan_lock);
|
||||
dev->scan.beacon_received = false;
|
||||
dev->scan.beacon_wait = true;
|
||||
spin_unlock_bh(&dev->scan_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
probe:
|
||||
if (phy->offchannel)
|
||||
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 (dev->scan.chan)
|
||||
if (dev->scan.chan && phy->offchannel)
|
||||
duration = max_t(int, duration,
|
||||
msecs_to_jiffies(req->duration +
|
||||
(req->duration >> 5)));
|
||||
|
||||
@@ -227,7 +227,9 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_sta *sta;
|
||||
int pending;
|
||||
int i;
|
||||
|
||||
if (!wcid || info->tx_time_est)
|
||||
return;
|
||||
@@ -235,6 +237,17 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
pending = atomic_dec_return(&wcid->non_aql_packets);
|
||||
if (pending < 0)
|
||||
atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
|
||||
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta || pending != MT_MAX_NON_AQL_PKT - 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
|
||||
if (!sta->txq[i])
|
||||
continue;
|
||||
|
||||
ieee80211_schedule_txq(dev->hw, sta->txq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
|
||||
@@ -542,6 +555,9 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
|
||||
continue;
|
||||
|
||||
if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
|
||||
continue;
|
||||
|
||||
phy = mt76_dev_phy(dev, wcid->phy_idx);
|
||||
if (test_bit(MT76_RESET, &phy->state) || phy->offchannel)
|
||||
continue;
|
||||
@@ -616,7 +632,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
||||
|
||||
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_data_present(hdr->frame_control) &&
|
||||
(!ieee80211_is_bufferable_mmpdu(skb) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
head == &wcid->tx_offchannel))
|
||||
@@ -644,7 +660,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
{
|
||||
LIST_HEAD(tx_list);
|
||||
int ret = 0;
|
||||
@@ -850,9 +866,15 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
|
||||
token = idr_alloc(&dev->token, *ptxwi, dev->token_start,
|
||||
dev->token_start + dev->token_size,
|
||||
GFP_ATOMIC);
|
||||
if (token >= dev->token_start)
|
||||
if (token >= dev->token_start) {
|
||||
dev->token_count++;
|
||||
|
||||
if ((*ptxwi)->qid == MT_TXQ_PSD) {
|
||||
struct mt76_phy *mphy = mt76_dev_phy(dev, (*ptxwi)->phy_idx);
|
||||
atomic_inc(&mphy->mgmt_tx_pending);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
token >= dev->mmio.wed.wlan.token_start)
|
||||
@@ -897,6 +919,12 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
|
||||
if (txwi) {
|
||||
dev->token_count--;
|
||||
|
||||
if (txwi->qid == MT_TXQ_PSD) {
|
||||
struct mt76_phy *mphy = mt76_dev_phy(dev, txwi->phy_idx);
|
||||
if (atomic_dec_and_test(&mphy->mgmt_tx_pending))
|
||||
wake_up(&dev->tx_wait);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
token >= dev->mmio.wed.wlan.token_start &&
|
||||
|
||||
@@ -403,12 +403,18 @@ mt7601u_upload_firmware(struct mt7601u_dev *dev, const struct mt76_fw *fw)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char * const mt7601u_fw_paths[] = {
|
||||
"mediatek/" MT7601U_FIRMWARE,
|
||||
MT7601U_FIRMWARE,
|
||||
};
|
||||
|
||||
static int mt7601u_load_firmware(struct mt7601u_dev *dev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct mt76_fw_header *hdr;
|
||||
int len, ret;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
|
||||
MT_USB_DMA_CFG_TX_BULK_EN));
|
||||
@@ -416,7 +422,14 @@ static int mt7601u_load_firmware(struct mt7601u_dev *dev)
|
||||
if (firmware_running(dev))
|
||||
return firmware_request_cache(dev->dev, MT7601U_FIRMWARE);
|
||||
|
||||
ret = request_firmware(&fw, MT7601U_FIRMWARE, dev->dev);
|
||||
/* Try loading firmware from multiple locations */
|
||||
fw = NULL;
|
||||
for (i = 0; i < MT7601U_FIRMWARE_PATHS; i++) {
|
||||
ret = request_firmware(&fw, mt7601u_fw_paths[i], dev->dev);
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mt7601u.h"
|
||||
|
||||
#define MT7601U_FIRMWARE "mt7601u.bin"
|
||||
#define MT7601U_FIRMWARE_PATHS ARRAY_SIZE(mt7601u_fw_paths)
|
||||
|
||||
#define MT_VEND_REQ_MAX_RETRY 10
|
||||
#define MT_VEND_REQ_TOUT_MS 300
|
||||
|
||||
Reference in New Issue
Block a user