mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-05 01:14:43 -04:00
Merge tag 'mt76-next-2025-09-15' of https://github.com/nbd168/wireless
Felix Fietkau says: =================== mt76 patches for 6.18 - fixes - mt7996 MLO support - mt7996 hw restart improvements =================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -173,6 +173,8 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
|
||||
if (ackp == IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
|
||||
return;
|
||||
|
||||
if (wcid->def_wcid)
|
||||
wcid = wcid->def_wcid;
|
||||
tid = rcu_dereference(wcid->aggr[tidno]);
|
||||
if (!tid)
|
||||
return;
|
||||
|
||||
@@ -314,21 +314,24 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
kfree(mlink);
|
||||
}
|
||||
|
||||
static void mt76_roc_complete(struct mt76_phy *phy)
|
||||
void mt76_roc_complete(struct mt76_phy *phy)
|
||||
{
|
||||
struct mt76_vif_link *mlink = phy->roc_link;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
|
||||
if (!phy->roc_vif)
|
||||
return;
|
||||
|
||||
if (mlink)
|
||||
mlink->mvif->roc_phy = NULL;
|
||||
if (phy->main_chandef.chan)
|
||||
if (phy->main_chandef.chan &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);
|
||||
phy->roc_vif = NULL;
|
||||
phy->roc_link = NULL;
|
||||
ieee80211_remain_on_channel_expired(phy->hw);
|
||||
if (!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
ieee80211_remain_on_channel_expired(phy->hw);
|
||||
}
|
||||
|
||||
void mt76_roc_complete_work(struct work_struct *work)
|
||||
@@ -351,6 +354,7 @@ void mt76_abort_roc(struct mt76_phy *phy)
|
||||
mt76_roc_complete(phy);
|
||||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_abort_roc);
|
||||
|
||||
int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *chan, int duration,
|
||||
@@ -368,7 +372,8 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (phy->roc_vif || dev->scan.phy == phy) {
|
||||
if (phy->roc_vif || dev->scan.phy == phy ||
|
||||
test_bit(MT76_MCU_RESET, &dev->phy.state)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -185,6 +185,37 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
|
||||
|
||||
static void
|
||||
mt76_dma_queue_magic_cnt_init(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
if (!mt76_queue_is_wed_rro(q))
|
||||
return;
|
||||
|
||||
q->magic_cnt = 0;
|
||||
if (mt76_queue_is_wed_rro_ind(q)) {
|
||||
struct mt76_wed_rro_desc *rro_desc;
|
||||
u32 data1 = FIELD_PREP(RRO_IND_DATA1_MAGIC_CNT_MASK,
|
||||
MT_DMA_WED_IND_CMD_CNT - 1);
|
||||
int i;
|
||||
|
||||
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
|
||||
for (i = 0; i < q->ndesc; i++) {
|
||||
struct mt76_wed_rro_ind *cmd;
|
||||
|
||||
cmd = (struct mt76_wed_rro_ind *)&rro_desc[i];
|
||||
cmd->data1 = cpu_to_le32(data1);
|
||||
}
|
||||
} else if (mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
struct mt76_rro_rxdmad_c *dmad = (void *)q->desc;
|
||||
u32 data3 = FIELD_PREP(RRO_RXDMAD_DATA3_MAGIC_CNT_MASK,
|
||||
MT_DMA_MAGIC_CNT - 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
dmad[i].data3 = cpu_to_le32(data3);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
@@ -197,13 +228,14 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
q->tail = q->head;
|
||||
}
|
||||
|
||||
void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool reset_idx)
|
||||
void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool reset_idx)
|
||||
{
|
||||
if (!q || !q->ndesc)
|
||||
return;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_ind(q)) {
|
||||
if (!mt76_queue_is_wed_rro_ind(q) &&
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
int i;
|
||||
|
||||
/* clear descriptors */
|
||||
@@ -211,27 +243,26 @@ void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
}
|
||||
|
||||
mt76_dma_queue_magic_cnt_init(dev, q);
|
||||
if (reset_idx) {
|
||||
Q_WRITE(q, cpu_idx, 0);
|
||||
if (mt76_queue_is_emi(q))
|
||||
*q->emi_cpu_idx = 0;
|
||||
else
|
||||
Q_WRITE(q, cpu_idx, 0);
|
||||
Q_WRITE(q, dma_idx, 0);
|
||||
}
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
}
|
||||
|
||||
void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
__mt76_dma_queue_reset(dev, q, true);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct mt76_queue_buf *buf, void *data)
|
||||
{
|
||||
struct mt76_queue_entry *entry = &q->entry[q->head];
|
||||
struct mt76_txwi_cache *txwi = NULL;
|
||||
u32 buf1 = 0, ctrl, info = 0;
|
||||
struct mt76_desc *desc;
|
||||
int idx = q->head;
|
||||
u32 buf1 = 0, ctrl;
|
||||
int rx_token;
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q)) {
|
||||
@@ -240,6 +271,9 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
|
||||
data = &rro_desc[q->head];
|
||||
goto done;
|
||||
} else if (mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
data = &q->desc[q->head];
|
||||
goto done;
|
||||
}
|
||||
|
||||
desc = &q->desc[q->head];
|
||||
@@ -248,7 +282,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
buf1 = FIELD_PREP(MT_DMA_CTL_SDP0_H, buf->addr >> 32);
|
||||
#endif
|
||||
|
||||
if (mt76_queue_is_wed_rx(q)) {
|
||||
if (mt76_queue_is_wed_rx(q) || mt76_queue_is_wed_rro_data(q)) {
|
||||
txwi = mt76_get_rxwi(dev);
|
||||
if (!txwi)
|
||||
return -ENOMEM;
|
||||
@@ -261,12 +295,26 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
|
||||
ctrl |= MT_DMA_CTL_TO_HOST;
|
||||
|
||||
txwi->qid = q - dev->q_rx;
|
||||
}
|
||||
|
||||
if (mt76_queue_is_wed_rro_msdu_pg(q) &&
|
||||
dev->drv->rx_rro_add_msdu_page) {
|
||||
if (dev->drv->rx_rro_add_msdu_page(dev, q, buf->addr, data))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (q->flags & MT_QFLAG_WED_RRO_EN) {
|
||||
info |= FIELD_PREP(MT_DMA_MAGIC_MASK, q->magic_cnt);
|
||||
if ((q->head + 1) == q->ndesc)
|
||||
q->magic_cnt = (q->magic_cnt + 1) % MT_DMA_MAGIC_CNT;
|
||||
}
|
||||
|
||||
WRITE_ONCE(desc->buf0, cpu_to_le32(buf->addr));
|
||||
WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
|
||||
WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
|
||||
WRITE_ONCE(desc->info, 0);
|
||||
WRITE_ONCE(desc->info, cpu_to_le32(info));
|
||||
|
||||
done:
|
||||
entry->dma_addr[0] = buf->addr;
|
||||
@@ -375,7 +423,10 @@ static void
|
||||
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
wmb();
|
||||
Q_WRITE(q, cpu_idx, q->head);
|
||||
if (mt76_queue_is_emi(q))
|
||||
*q->emi_cpu_idx = cpu_to_le16(q->head);
|
||||
else
|
||||
Q_WRITE(q, cpu_idx, q->head);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -418,16 +469,62 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
|
||||
wake_up(&dev->tx_wait);
|
||||
}
|
||||
|
||||
static void *
|
||||
mt76_dma_get_rxdmad_c_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int *len, bool *more)
|
||||
{
|
||||
struct mt76_queue_entry *e = &q->entry[idx];
|
||||
struct mt76_rro_rxdmad_c *dmad = e->buf;
|
||||
u32 data1 = le32_to_cpu(dmad->data1);
|
||||
u32 data2 = le32_to_cpu(dmad->data2);
|
||||
struct mt76_txwi_cache *t;
|
||||
u16 rx_token_id;
|
||||
u8 ind_reason;
|
||||
void *buf;
|
||||
|
||||
rx_token_id = FIELD_GET(RRO_RXDMAD_DATA2_RX_TOKEN_ID_MASK, data2);
|
||||
t = mt76_rx_token_release(dev, rx_token_id);
|
||||
if (!t)
|
||||
return ERR_PTR(-EAGAIN);
|
||||
|
||||
q = &dev->q_rx[t->qid];
|
||||
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
|
||||
SKB_WITH_OVERHEAD(q->buf_size),
|
||||
page_pool_get_dma_dir(q->page_pool));
|
||||
|
||||
if (len)
|
||||
*len = FIELD_GET(RRO_RXDMAD_DATA1_SDL0_MASK, data1);
|
||||
if (more)
|
||||
*more = !FIELD_GET(RRO_RXDMAD_DATA1_LS_MASK, data1);
|
||||
|
||||
buf = t->ptr;
|
||||
ind_reason = FIELD_GET(RRO_RXDMAD_DATA2_IND_REASON_MASK, data2);
|
||||
if (ind_reason == MT_DMA_WED_IND_REASON_REPEAT ||
|
||||
ind_reason == MT_DMA_WED_IND_REASON_OLDPKT) {
|
||||
mt76_put_page_pool_buf(buf, false);
|
||||
buf = ERR_PTR(-EAGAIN);
|
||||
}
|
||||
t->ptr = NULL;
|
||||
t->dma_addr = 0;
|
||||
|
||||
mt76_put_rxwi(dev, t);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void *
|
||||
mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
int *len, u32 *info, bool *more, bool *drop)
|
||||
int *len, u32 *info, bool *more, bool *drop, bool flush)
|
||||
{
|
||||
struct mt76_queue_entry *e = &q->entry[idx];
|
||||
struct mt76_desc *desc = &q->desc[idx];
|
||||
u32 ctrl, desc_info, buf1;
|
||||
void *buf = e->buf;
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q))
|
||||
if (mt76_queue_is_wed_rro_rxdmad_c(q) && !flush)
|
||||
buf = mt76_dma_get_rxdmad_c_buf(dev, q, idx, len, more);
|
||||
|
||||
if (mt76_queue_is_wed_rro(q))
|
||||
goto done;
|
||||
|
||||
ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
|
||||
@@ -482,20 +579,50 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
|
||||
if (!q->queued)
|
||||
return NULL;
|
||||
|
||||
if (mt76_queue_is_wed_rro_data(q))
|
||||
return NULL;
|
||||
if (mt76_queue_is_wed_rro_data(q) || mt76_queue_is_wed_rro_msdu_pg(q))
|
||||
goto done;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_ind(q)) {
|
||||
if (mt76_queue_is_wed_rro_ind(q)) {
|
||||
struct mt76_wed_rro_ind *cmd;
|
||||
u8 magic_cnt;
|
||||
|
||||
if (flush)
|
||||
goto done;
|
||||
|
||||
cmd = q->entry[idx].buf;
|
||||
magic_cnt = FIELD_GET(RRO_IND_DATA1_MAGIC_CNT_MASK,
|
||||
le32_to_cpu(cmd->data1));
|
||||
if (magic_cnt != q->magic_cnt)
|
||||
return NULL;
|
||||
|
||||
if (q->tail == q->ndesc - 1)
|
||||
q->magic_cnt = (q->magic_cnt + 1) % MT_DMA_WED_IND_CMD_CNT;
|
||||
} else if (mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
struct mt76_rro_rxdmad_c *dmad;
|
||||
u16 magic_cnt;
|
||||
|
||||
if (flush)
|
||||
goto done;
|
||||
|
||||
dmad = q->entry[idx].buf;
|
||||
magic_cnt = FIELD_GET(RRO_RXDMAD_DATA3_MAGIC_CNT_MASK,
|
||||
le32_to_cpu(dmad->data3));
|
||||
if (magic_cnt != q->magic_cnt)
|
||||
return NULL;
|
||||
|
||||
if (q->tail == q->ndesc - 1)
|
||||
q->magic_cnt = (q->magic_cnt + 1) % MT_DMA_MAGIC_CNT;
|
||||
} else {
|
||||
if (flush)
|
||||
q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
q->tail = (q->tail + 1) % q->ndesc;
|
||||
q->queued--;
|
||||
|
||||
return mt76_dma_get_buf(dev, q, idx, len, info, more, drop);
|
||||
return mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -646,7 +773,8 @@ mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
void *buf = NULL;
|
||||
int offset;
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q))
|
||||
if (mt76_queue_is_wed_rro_ind(q) ||
|
||||
mt76_queue_is_wed_rro_rxdmad_c(q))
|
||||
goto done;
|
||||
|
||||
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
|
||||
@@ -676,9 +804,6 @@ int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
{
|
||||
int frames;
|
||||
|
||||
if (!q->ndesc)
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
frames = mt76_dma_rx_fill_buf(dev, q, allow_direct);
|
||||
spin_unlock_bh(&q->lock);
|
||||
@@ -708,19 +833,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (!q->desc)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q)) {
|
||||
struct mt76_wed_rro_desc *rro_desc;
|
||||
int i;
|
||||
|
||||
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
|
||||
for (i = 0; i < q->ndesc; i++) {
|
||||
struct mt76_wed_rro_ind *cmd;
|
||||
|
||||
cmd = (struct mt76_wed_rro_ind *)&rro_desc[i];
|
||||
cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1;
|
||||
}
|
||||
}
|
||||
|
||||
mt76_dma_queue_magic_cnt_init(dev, q);
|
||||
size = q->ndesc * sizeof(*q->entry);
|
||||
q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
|
||||
if (!q->entry)
|
||||
@@ -740,7 +853,10 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
return 0;
|
||||
}
|
||||
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
/* HW specific driver is supposed to reset brand-new EMI queues since
|
||||
* it needs to set cpu index pointer.
|
||||
*/
|
||||
mt76_dma_queue_reset(dev, q, !mt76_queue_is_emi(q));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -783,7 +899,8 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
if (!q->ndesc)
|
||||
return;
|
||||
|
||||
if (!mt76_queue_is_wed_rro_ind(q)) {
|
||||
if (!mt76_queue_is_wed_rro_ind(q) &&
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
@@ -843,8 +960,9 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
bool allow_direct = !mt76_queue_is_wed_rx(q);
|
||||
bool more;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
|
||||
mt76_queue_is_wed_tx_free(q)) {
|
||||
if ((q->flags & MT_QFLAG_WED_RRO_EN) ||
|
||||
(IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
|
||||
mt76_queue_is_wed_tx_free(q))) {
|
||||
dma_idx = Q_READ(q, dma_idx);
|
||||
check_ddone = true;
|
||||
}
|
||||
@@ -866,6 +984,20 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
if (PTR_ERR(data) == -EAGAIN) {
|
||||
done++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q) && dev->drv->rx_rro_ind_process)
|
||||
dev->drv->rx_rro_ind_process(dev, data);
|
||||
|
||||
if (mt76_queue_is_wed_rro(q) &&
|
||||
!mt76_queue_is_wed_rro_rxdmad_c(q)) {
|
||||
done++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (drop)
|
||||
goto free_frag;
|
||||
|
||||
@@ -943,6 +1075,15 @@ int mt76_dma_rx_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_dma_rx_poll);
|
||||
|
||||
static void
|
||||
mt76_dma_rx_queue_init(struct mt76_dev *dev, enum mt76_rxq_id qid,
|
||||
int (*poll)(struct napi_struct *napi, int budget))
|
||||
{
|
||||
netif_napi_add(dev->napi_dev, &dev->napi[qid], poll);
|
||||
mt76_dma_rx_fill_buf(dev, &dev->q_rx[qid], false);
|
||||
napi_enable(&dev->napi[qid]);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_init(struct mt76_dev *dev,
|
||||
int (*poll)(struct napi_struct *napi, int budget))
|
||||
@@ -975,9 +1116,10 @@ mt76_dma_init(struct mt76_dev *dev,
|
||||
init_completion(&dev->mmio.wed_reset_complete);
|
||||
|
||||
mt76_for_each_q_rx(dev, i) {
|
||||
netif_napi_add(dev->napi_dev, &dev->napi[i], poll);
|
||||
mt76_dma_rx_fill_buf(dev, &dev->q_rx[i], false);
|
||||
napi_enable(&dev->napi[i]);
|
||||
if (mt76_queue_is_wed_rro(&dev->q_rx[i]))
|
||||
continue;
|
||||
|
||||
mt76_dma_rx_queue_init(dev, i, poll);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -990,6 +1132,7 @@ static const struct mt76_queue_ops mt76_dma_ops = {
|
||||
.tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
|
||||
.tx_queue_skb = mt76_dma_tx_queue_skb,
|
||||
.tx_cleanup = mt76_dma_tx_cleanup,
|
||||
.rx_queue_init = mt76_dma_rx_queue_init,
|
||||
.rx_cleanup = mt76_dma_rx_cleanup,
|
||||
.rx_reset = mt76_dma_rx_reset,
|
||||
.kick = mt76_dma_kick_queue,
|
||||
|
||||
@@ -31,7 +31,12 @@
|
||||
#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
|
||||
#define MT_DMA_CTL_VER_MASK BIT(7)
|
||||
|
||||
#define MT_DMA_RRO_EN BIT(13)
|
||||
#define MT_DMA_SDP0 GENMASK(15, 0)
|
||||
#define MT_DMA_TOKEN_ID GENMASK(31, 16)
|
||||
#define MT_DMA_MAGIC_MASK GENMASK(31, 28)
|
||||
#define MT_DMA_RRO_EN BIT(13)
|
||||
|
||||
#define MT_DMA_MAGIC_CNT 16
|
||||
|
||||
#define MT_DMA_WED_IND_CMD_CNT 8
|
||||
#define MT_DMA_WED_IND_REASON GENMASK(15, 12)
|
||||
@@ -53,6 +58,21 @@ struct mt76_wed_rro_desc {
|
||||
__le32 buf1;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* data1 */
|
||||
#define RRO_RXDMAD_DATA1_LS_MASK BIT(30)
|
||||
#define RRO_RXDMAD_DATA1_SDL0_MASK GENMASK(29, 16)
|
||||
/* data2 */
|
||||
#define RRO_RXDMAD_DATA2_RX_TOKEN_ID_MASK GENMASK(31, 16)
|
||||
#define RRO_RXDMAD_DATA2_IND_REASON_MASK GENMASK(15, 12)
|
||||
/* data3 */
|
||||
#define RRO_RXDMAD_DATA3_MAGIC_CNT_MASK GENMASK(31, 28)
|
||||
struct mt76_rro_rxdmad_c {
|
||||
__le32 data0;
|
||||
__le32 data1;
|
||||
__le32 data2;
|
||||
__le32 data3;
|
||||
};
|
||||
|
||||
enum mt76_qsel {
|
||||
MT_QSEL_MGMT,
|
||||
MT_QSEL_HCCA,
|
||||
@@ -81,14 +101,13 @@ void mt76_dma_attach(struct mt76_dev *dev);
|
||||
void mt76_dma_cleanup(struct mt76_dev *dev);
|
||||
int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool allow_direct);
|
||||
void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool reset_idx);
|
||||
void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool reset_idx);
|
||||
|
||||
static inline void
|
||||
mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
dev->queue_ops->reset_q(dev, q);
|
||||
dev->queue_ops->reset_q(dev, q, true);
|
||||
if (mtk_wed_device_active(&dev->mmio.wed))
|
||||
mt76_wed_dma_setup(dev, q, true);
|
||||
}
|
||||
|
||||
@@ -163,13 +163,16 @@ static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len)
|
||||
return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
mt76_eeprom_override(struct mt76_phy *phy)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct device_node *np = dev->dev->of_node;
|
||||
int err;
|
||||
|
||||
of_get_mac_address(np, phy->macaddr);
|
||||
err = of_get_mac_address(np, phy->macaddr);
|
||||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
if (!is_valid_ether_addr(phy->macaddr)) {
|
||||
eth_random_addr(phy->macaddr);
|
||||
@@ -177,6 +180,8 @@ mt76_eeprom_override(struct mt76_phy *phy)
|
||||
"Invalid MAC address, using random address %pM\n",
|
||||
phy->macaddr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_eeprom_override);
|
||||
|
||||
|
||||
@@ -824,6 +824,9 @@ static void mt76_reset_phy(struct mt76_phy *phy)
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
phy->num_sta = 0;
|
||||
phy->chanctx = NULL;
|
||||
mt76_roc_complete(phy);
|
||||
}
|
||||
|
||||
void mt76_reset_device(struct mt76_dev *dev)
|
||||
@@ -844,6 +847,8 @@ void mt76_reset_device(struct mt76_dev *dev)
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
mt76_abort_scan(dev);
|
||||
|
||||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
dev->vif_mask = 0;
|
||||
@@ -1235,6 +1240,8 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
mstat = *((struct mt76_rx_status *)skb->cb);
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
skb->priority = mstat.qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
||||
status->flag = mstat.flag;
|
||||
status->freq = mstat.freq;
|
||||
status->enc_flags = mstat.enc_flags;
|
||||
@@ -2060,3 +2067,55 @@ void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif)
|
||||
mt76_abort_roc(mvif->roc_phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_vif_cleanup);
|
||||
|
||||
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links)
|
||||
{
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct {
|
||||
u8 link_id;
|
||||
enum nl80211_band band;
|
||||
} data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
unsigned int link_id;
|
||||
int i, n_data = 0;
|
||||
u16 sel_links = 0;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return 0;
|
||||
|
||||
if (vif->active_links == usable_links)
|
||||
return vif->active_links;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (WARN_ON_ONCE(!link_conf))
|
||||
continue;
|
||||
|
||||
data[n_data].link_id = link_id;
|
||||
data[n_data].band = link_conf->chanreq.oper.chan->band;
|
||||
n_data++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
for (i = 0; i < n_data; i++) {
|
||||
int j;
|
||||
|
||||
if (!(BIT(data[i].link_id) & vif->active_links))
|
||||
continue;
|
||||
|
||||
sel_links = BIT(data[i].link_id);
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (data[i].band != data[j].band) {
|
||||
sel_links |= BIT(data[j].link_id);
|
||||
if (hweight16(sel_links) == max_active_links)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return sel_links;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_select_links);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define MT_QFLAG_WED BIT(5)
|
||||
#define MT_QFLAG_WED_RRO BIT(6)
|
||||
#define MT_QFLAG_WED_RRO_EN BIT(7)
|
||||
#define MT_QFLAG_EMI_EN BIT(8)
|
||||
|
||||
#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
|
||||
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
|
||||
@@ -45,6 +46,7 @@
|
||||
#define MT_WED_RRO_Q_DATA(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n)
|
||||
#define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n)
|
||||
#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
|
||||
#define MT_WED_RRO_Q_RXDMAD_C __MT_WED_RRO_Q(MT76_WED_RRO_Q_RXDMAD_C, 0)
|
||||
|
||||
struct mt76_dev;
|
||||
struct mt76_phy;
|
||||
@@ -71,6 +73,13 @@ enum mt76_wed_type {
|
||||
MT76_WED_RRO_Q_DATA,
|
||||
MT76_WED_RRO_Q_MSDU_PG,
|
||||
MT76_WED_RRO_Q_IND,
|
||||
MT76_WED_RRO_Q_RXDMAD_C,
|
||||
};
|
||||
|
||||
enum mt76_hwrro_mode {
|
||||
MT76_HWRRO_OFF,
|
||||
MT76_HWRRO_V3,
|
||||
MT76_HWRRO_V3_1,
|
||||
};
|
||||
|
||||
struct mt76_bus_ops {
|
||||
@@ -129,6 +138,7 @@ enum mt76_rxq_id {
|
||||
MT_RXQ_TXFREE_BAND1,
|
||||
MT_RXQ_TXFREE_BAND2,
|
||||
MT_RXQ_RRO_IND,
|
||||
MT_RXQ_RRO_RXDMAD_C,
|
||||
__MT_RXQ_MAX
|
||||
};
|
||||
|
||||
@@ -232,6 +242,9 @@ struct mt76_queue {
|
||||
|
||||
u8 buf_offset;
|
||||
u16 flags;
|
||||
u8 magic_cnt;
|
||||
|
||||
__le16 *emi_cpu_idx;
|
||||
|
||||
struct mtk_wed_device *wed;
|
||||
u32 wed_regs;
|
||||
@@ -286,11 +299,15 @@ struct mt76_queue_ops {
|
||||
void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool flush);
|
||||
|
||||
void (*rx_queue_init)(struct mt76_dev *dev, enum mt76_rxq_id qid,
|
||||
int (*poll)(struct napi_struct *napi, int budget));
|
||||
|
||||
void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
|
||||
void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
|
||||
void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool reset_idx);
|
||||
};
|
||||
|
||||
enum mt76_phy_type {
|
||||
@@ -398,15 +415,16 @@ struct mt76_txq {
|
||||
bool aggr;
|
||||
};
|
||||
|
||||
/* data0 */
|
||||
#define RRO_IND_DATA0_IND_REASON_MASK GENMASK(31, 28)
|
||||
#define RRO_IND_DATA0_START_SEQ_MASK GENMASK(27, 16)
|
||||
#define RRO_IND_DATA0_SEQ_ID_MASK GENMASK(11, 0)
|
||||
/* data1 */
|
||||
#define RRO_IND_DATA1_MAGIC_CNT_MASK GENMASK(31, 29)
|
||||
#define RRO_IND_DATA1_IND_COUNT_MASK GENMASK(12, 0)
|
||||
struct mt76_wed_rro_ind {
|
||||
u32 se_id : 12;
|
||||
u32 rsv : 4;
|
||||
u32 start_sn : 12;
|
||||
u32 ind_reason : 4;
|
||||
u32 ind_cnt : 13;
|
||||
u32 win_sz : 3;
|
||||
u32 rsv2 : 13;
|
||||
u32 magic_cnt : 3;
|
||||
__le32 data0;
|
||||
__le32 data1;
|
||||
};
|
||||
|
||||
struct mt76_txwi_cache {
|
||||
@@ -417,6 +435,8 @@ struct mt76_txwi_cache {
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
u8 qid;
|
||||
};
|
||||
|
||||
struct mt76_rx_tid {
|
||||
@@ -533,6 +553,10 @@ struct mt76_driver_ops {
|
||||
|
||||
void (*rx_poll_complete)(struct mt76_dev *dev, enum mt76_rxq_id q);
|
||||
|
||||
void (*rx_rro_ind_process)(struct mt76_dev *dev, void *data);
|
||||
int (*rx_rro_add_msdu_page)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
dma_addr_t p, void *data);
|
||||
|
||||
void (*sta_ps)(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
bool ps);
|
||||
|
||||
@@ -910,6 +934,7 @@ struct mt76_dev {
|
||||
struct mt76_queue q_rx[__MT_RXQ_MAX];
|
||||
const struct mt76_queue_ops *queue_ops;
|
||||
int tx_dma_idx[4];
|
||||
enum mt76_hwrro_mode hwrro_mode;
|
||||
|
||||
struct mt76_worker tx_worker;
|
||||
struct napi_struct tx_napi;
|
||||
@@ -1214,6 +1239,7 @@ static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mphy), __VA_ARGS__)
|
||||
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_init(dev, ...) (dev)->mt76.queue_ops->rx_queue_init(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__)
|
||||
@@ -1268,7 +1294,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
|
||||
s8 *val, int len);
|
||||
|
||||
int mt76_eeprom_init(struct mt76_dev *dev, int len);
|
||||
void mt76_eeprom_override(struct mt76_phy *phy);
|
||||
int mt76_eeprom_override(struct mt76_phy *phy);
|
||||
int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len);
|
||||
int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep,
|
||||
const char *cell_name, int len);
|
||||
@@ -1617,6 +1643,7 @@ int mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef,
|
||||
void mt76_scan_work(struct work_struct *work);
|
||||
void mt76_abort_scan(struct mt76_dev *dev);
|
||||
void mt76_roc_complete_work(struct work_struct *work);
|
||||
void mt76_roc_complete(struct mt76_phy *phy);
|
||||
void mt76_abort_roc(struct mt76_phy *phy);
|
||||
struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif);
|
||||
@@ -1782,21 +1809,34 @@ static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_wed_rro_rxdmad_c(struct mt76_queue *q)
|
||||
{
|
||||
return mt76_queue_is_wed_rro(q) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_RXDMAD_C;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q)
|
||||
{
|
||||
return mt76_queue_is_wed_rro(q) &&
|
||||
(FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA ||
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_MSDU_PG);
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_wed_rro_msdu_pg(struct mt76_queue *q)
|
||||
{
|
||||
return mt76_queue_is_wed_rro(q) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) ==
|
||||
MT76_WED_RRO_Q_MSDU_PG;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
|
||||
{
|
||||
if (!(q->flags & MT_QFLAG_WED))
|
||||
return false;
|
||||
|
||||
return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX ||
|
||||
mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q);
|
||||
return (q->flags & MT_QFLAG_WED) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
|
||||
}
|
||||
|
||||
static inline bool mt76_queue_is_emi(struct mt76_queue *q)
|
||||
{
|
||||
return q->flags & MT_QFLAG_EMI_EN;
|
||||
}
|
||||
|
||||
struct mt76_txwi_cache *
|
||||
@@ -1872,6 +1912,7 @@ mt76_vif_init(struct ieee80211_vif *vif, struct mt76_vif_data *mvif)
|
||||
}
|
||||
|
||||
void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif);
|
||||
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links);
|
||||
|
||||
static inline struct mt76_vif_link *
|
||||
mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)
|
||||
|
||||
@@ -182,7 +182,6 @@ int mt7603_eeprom_init(struct mt7603_dev *dev)
|
||||
dev->mphy.antenna_mask = 1;
|
||||
|
||||
dev->mphy.chainmask = dev->mphy.antenna_mask;
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
return 0;
|
||||
return mt76_eeprom_override(&dev->mphy);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ mt76_wmac_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
error:
|
||||
ieee80211_free_hw(mt76_hw(dev));
|
||||
mt76_free_device(mdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -351,8 +351,6 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
|
||||
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
|
||||
ETH_ALEN);
|
||||
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
return 0;
|
||||
return mt76_eeprom_override(&dev->mphy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_eeprom_init);
|
||||
|
||||
@@ -570,7 +570,10 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
|
||||
ETH_ALEN);
|
||||
mphy->macaddr[0] |= 2;
|
||||
mphy->macaddr[0] ^= BIT(7);
|
||||
mt76_eeprom_override(mphy);
|
||||
|
||||
ret = mt76_eeprom_override(mphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* second phy can only handle 5 GHz */
|
||||
mphy->cap.has_5ghz = true;
|
||||
|
||||
@@ -294,6 +294,13 @@ enum tx_frag_idx {
|
||||
#define MT_TXP_BUF_LEN GENMASK(11, 0)
|
||||
#define MT_TXP_DMA_ADDR_H GENMASK(15, 12)
|
||||
|
||||
#define MT_TXP0_TOKEN_ID0 GENMASK(14, 0)
|
||||
#define MT_TXP0_TOKEN_ID0_VALID_MASK BIT(15)
|
||||
|
||||
#define MT_TXP1_TID_ADDBA GENMASK(14, 12)
|
||||
#define MT_TXP3_ML0_MASK BIT(15)
|
||||
#define MT_TXP3_DMA_ADDR_H GENMASK(13, 12)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(14)
|
||||
#define MT_TX_RATE_NSS GENMASK(13, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
|
||||
@@ -1662,6 +1662,31 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (enable && vif->bss_conf.bssid_indicator) {
|
||||
struct {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct bss_info_uni_mbssid mbssid;
|
||||
} mbssid_req = {
|
||||
.hdr = {
|
||||
.bss_idx = mvif->idx,
|
||||
},
|
||||
.mbssid = {
|
||||
.tag = cpu_to_le16(UNI_BSS_INFO_11V_MBSSID),
|
||||
.len = cpu_to_le16(sizeof(struct bss_info_uni_mbssid)),
|
||||
.max_indicator = vif->bss_conf.bssid_indicator,
|
||||
.mbss_idx = vif->bss_conf.bssid_index,
|
||||
},
|
||||
};
|
||||
|
||||
err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE),
|
||||
&mbssid_req, sizeof(mbssid_req), true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return mt76_connac_mcu_uni_set_chctx(phy, mvif, ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
|
||||
|
||||
@@ -332,7 +332,11 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
|
||||
|
||||
memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
|
||||
ETH_ALEN);
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
err = mt76_eeprom_override(&dev->mphy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76x02_mac_setaddr(dev, dev->mphy.macaddr);
|
||||
|
||||
mt76x0_set_chip_cap(dev);
|
||||
|
||||
@@ -499,7 +499,9 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev)
|
||||
|
||||
mt76x02_eeprom_parse_hw_cap(dev);
|
||||
mt76x2_eeprom_get_macaddr(dev);
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
ret = mt76_eeprom_override(&dev->mphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev->mphy.macaddr[0] &= ~BIT(1);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -624,13 +624,13 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
|
||||
}
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
if (mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i], true);
|
||||
}
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
@@ -284,9 +284,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
|
||||
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
|
||||
ETH_ALEN);
|
||||
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
return 0;
|
||||
return mt76_eeprom_override(&dev->mphy);
|
||||
}
|
||||
|
||||
int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
|
||||
@@ -50,9 +50,9 @@ enum mt7915_eeprom_field {
|
||||
#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16)
|
||||
#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16)
|
||||
#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16)
|
||||
#define MT_EE_CAL_GROUP_SIZE_7981 (144 * MT_EE_CAL_UNIT + 16)
|
||||
#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT)
|
||||
#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT)
|
||||
#define MT_EE_CAL_DPD_SIZE_V2_7981 (102 * MT_EE_CAL_UNIT) /* no 6g dpd data */
|
||||
|
||||
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF0_RX_PATH GENMASK(5, 3)
|
||||
@@ -180,6 +180,8 @@ mt7915_get_cal_group_size(struct mt7915_dev *dev)
|
||||
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
|
||||
return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G :
|
||||
MT_EE_CAL_GROUP_SIZE_7916;
|
||||
} else if (is_mt7981(&dev->mt76)) {
|
||||
return MT_EE_CAL_GROUP_SIZE_7981;
|
||||
} else if (mt7915_check_adie(dev, false)) {
|
||||
return MT_EE_CAL_GROUP_SIZE_7976;
|
||||
} else {
|
||||
@@ -192,8 +194,6 @@ mt7915_get_cal_dpd_size(struct mt7915_dev *dev)
|
||||
{
|
||||
if (is_mt7915(&dev->mt76))
|
||||
return MT_EE_CAL_DPD_SIZE_V1;
|
||||
else if (is_mt7981(&dev->mt76))
|
||||
return MT_EE_CAL_DPD_SIZE_V2_7981;
|
||||
else
|
||||
return MT_EE_CAL_DPD_SIZE_V2;
|
||||
}
|
||||
|
||||
@@ -702,7 +702,9 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
|
||||
mphy->macaddr[0] |= 2;
|
||||
mphy->macaddr[0] ^= BIT(7);
|
||||
}
|
||||
mt76_eeprom_override(mphy);
|
||||
ret = mt76_eeprom_override(mphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* init wiphy according to mphy and phy */
|
||||
mt7915_init_wiphy(phy);
|
||||
|
||||
@@ -3052,30 +3052,15 @@ static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw)
|
||||
/* 5G BW160 */
|
||||
5250, 5570, 5815
|
||||
};
|
||||
static const u16 freq_list_v2_7981[] = {
|
||||
/* 5G BW20 */
|
||||
5180, 5200, 5220, 5240,
|
||||
5260, 5280, 5300, 5320,
|
||||
5500, 5520, 5540, 5560,
|
||||
5580, 5600, 5620, 5640,
|
||||
5660, 5680, 5700, 5720,
|
||||
5745, 5765, 5785, 5805,
|
||||
5825, 5845, 5865, 5885,
|
||||
/* 5G BW160 */
|
||||
5250, 5570, 5815
|
||||
};
|
||||
const u16 *freq_list = freq_list_v1;
|
||||
int n_freqs = ARRAY_SIZE(freq_list_v1);
|
||||
int idx;
|
||||
const u16 *freq_list;
|
||||
int idx, n_freqs;
|
||||
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
if (is_mt7981(&dev->mt76)) {
|
||||
freq_list = freq_list_v2_7981;
|
||||
n_freqs = ARRAY_SIZE(freq_list_v2_7981);
|
||||
} else {
|
||||
freq_list = freq_list_v2;
|
||||
n_freqs = ARRAY_SIZE(freq_list_v2);
|
||||
}
|
||||
freq_list = freq_list_v2;
|
||||
n_freqs = ARRAY_SIZE(freq_list_v2);
|
||||
} else {
|
||||
freq_list = freq_list_v1;
|
||||
n_freqs = ARRAY_SIZE(freq_list_v1);
|
||||
}
|
||||
|
||||
if (freq < 4000) {
|
||||
|
||||
@@ -189,7 +189,9 @@ static int __mt7921_init_hardware(struct mt792x_dev *dev)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
ret = mt76_eeprom_override(&dev->mphy);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7921_mcu_set_eeprom(dev);
|
||||
if (ret)
|
||||
|
||||
@@ -135,6 +135,8 @@ mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
||||
if (is_mt7922(phy->mt76->dev)) {
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
he_cap_elem->phy_cap_info[4] |=
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
|
||||
he_cap_elem->phy_cap_info[8] |=
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
|
||||
|
||||
@@ -21,6 +21,9 @@ static const struct usb_device_id mt7921u_device_table[] = {
|
||||
/* Netgear, Inc. [A8000,AXE3000] */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
/* Netgear, Inc. A7500 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9065, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
/* TP-Link TXE50UH */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0107, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
|
||||
@@ -249,7 +249,9 @@ static int __mt7925_init_hardware(struct mt792x_dev *dev)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
ret = mt76_eeprom_override(&dev->mphy);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7925_mcu_set_eeprom(dev);
|
||||
if (ret)
|
||||
|
||||
@@ -1300,7 +1300,6 @@ void mt7925_mac_reset_work(struct work_struct *work)
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
dev->sar_inited = false;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
@@ -1329,6 +1328,10 @@ void mt7925_mac_reset_work(struct work_struct *work)
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7925_vif_connect_iter, NULL);
|
||||
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt7925_mcu_set_clc(dev, "00", ENVIRON_INDOOR);
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
void mt7925_coredump_work(struct work_struct *work)
|
||||
|
||||
@@ -240,6 +240,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
{
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
static const u8 ext_capa_sta[] = {
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
static struct wiphy_iftype_ext_capab ext_capab[] = {
|
||||
@@ -310,7 +311,6 @@ void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy)
|
||||
int __mt7925_start(struct mt792x_phy *phy)
|
||||
{
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
int err;
|
||||
|
||||
err = mt7925_mcu_set_channel_domain(mphy);
|
||||
@@ -321,13 +321,6 @@ int __mt7925_start(struct mt792x_phy *phy)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!dev->sar_inited) {
|
||||
err = mt7925_set_tx_sar_pwr(mphy->hw, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
dev->sar_inited = true;
|
||||
}
|
||||
|
||||
mt792x_mac_reset_counters(phy);
|
||||
set_bit(MT76_STATE_RUNNING, &mphy->state);
|
||||
|
||||
@@ -987,56 +980,6 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
|
||||
|
||||
static u16
|
||||
mt7925_mac_select_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
||||
{
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct {
|
||||
u8 link_id;
|
||||
enum nl80211_band band;
|
||||
} data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
u8 link_id, i, j, n_data = 0;
|
||||
u16 sel_links = 0;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return 0;
|
||||
|
||||
if (vif->active_links == usable_links)
|
||||
return vif->active_links;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_conf =
|
||||
rcu_dereference(vif->link_conf[link_id]);
|
||||
|
||||
if (WARN_ON_ONCE(!link_conf))
|
||||
continue;
|
||||
|
||||
data[n_data].link_id = link_id;
|
||||
data[n_data].band = link_conf->chanreq.oper.chan->band;
|
||||
n_data++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
for (i = 0; i < n_data; i++) {
|
||||
if (!(BIT(data[i].link_id) & vif->active_links))
|
||||
continue;
|
||||
|
||||
sel_links = BIT(data[i].link_id);
|
||||
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (data[i].band != data[j].band) {
|
||||
sel_links |= BIT(data[j].link_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sel_links;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -1047,7 +990,7 @@ mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
||||
struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
|
||||
enum nl80211_band band = chandef->chan->band, secondary_band;
|
||||
|
||||
u16 sel_links = mt7925_mac_select_links(mdev, vif);
|
||||
u16 sel_links = mt76_select_links(vif, 2);
|
||||
u8 secondary_link_id = __ffs(~BIT(mvif->deflink_id) & sel_links);
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2)
|
||||
@@ -1731,13 +1674,7 @@ static int mt7925_set_sar_specs(struct ieee80211_hw *hw,
|
||||
int err;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
err = mt7925_mcu_set_clc(dev, dev->mt76.alpha2,
|
||||
dev->country_ie_env);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = mt7925_set_tx_sar_pwr(hw, sar);
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
return err;
|
||||
|
||||
@@ -759,7 +759,6 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt7925_mcu_set_clc(dev, "00", ENVIRON_INDOOR);
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
@@ -2621,6 +2620,25 @@ mt7925_mcu_bss_qos_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf
|
||||
qos->qos = link_conf->qos;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf,
|
||||
bool enable)
|
||||
{
|
||||
struct bss_info_uni_mbssid *mbssid;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!enable && !link_conf->bssid_indicator)
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_11V_MBSSID,
|
||||
sizeof(*mbssid));
|
||||
|
||||
mbssid = (struct bss_info_uni_mbssid *)tlv;
|
||||
mbssid->max_indicator = link_conf->bssid_indicator;
|
||||
mbssid->mbss_idx = link_conf->bssid_index;
|
||||
mbssid->tx_bss_omac_idx = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf,
|
||||
struct mt792x_phy *phy)
|
||||
@@ -2787,8 +2805,10 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
mt7925_mcu_bss_color_tlv(skb, link_conf, enable);
|
||||
}
|
||||
|
||||
if (enable)
|
||||
if (enable) {
|
||||
mt7925_mcu_bss_rlm_tlv(skb, phy->mt76, link_conf, ctx);
|
||||
mt7925_mcu_bss_mbssid_tlv(skb, link_conf, enable);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
@@ -3703,6 +3723,8 @@ mt7925_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
|
||||
int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy)
|
||||
{
|
||||
struct mt76_dev *mdev = phy->dev;
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(mdev->hw);
|
||||
int err;
|
||||
|
||||
if (phy->cap.has_2ghz) {
|
||||
@@ -3719,7 +3741,7 @@ int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (phy->cap.has_6ghz) {
|
||||
if (phy->cap.has_6ghz && dev->phy.clc_chan_conf) {
|
||||
err = mt7925_mcu_rate_txpower_band(phy,
|
||||
NL80211_BAND_6GHZ);
|
||||
if (err < 0)
|
||||
|
||||
@@ -529,7 +529,7 @@ static int mt7925_pci_suspend(struct device *device)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7925_pci_resume(struct device *device)
|
||||
static int _mt7925_pci_resume(struct device *device, bool restore)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
@@ -569,6 +569,9 @@ static int mt7925_pci_resume(struct device *device)
|
||||
napi_schedule(&mdev->tx_napi);
|
||||
local_bh_enable();
|
||||
|
||||
if (restore)
|
||||
goto failed;
|
||||
|
||||
mt76_connac_mcu_set_hif_suspend(mdev, false, false);
|
||||
ret = wait_event_timeout(dev->wait,
|
||||
dev->hif_resumed, 3 * HZ);
|
||||
@@ -585,7 +588,7 @@ static int mt7925_pci_resume(struct device *device)
|
||||
failed:
|
||||
pm->suspended = false;
|
||||
|
||||
if (err < 0)
|
||||
if (err < 0 || restore)
|
||||
mt792x_reset(&dev->mt76);
|
||||
|
||||
return err;
|
||||
@@ -596,7 +599,24 @@ static void mt7925_pci_shutdown(struct pci_dev *pdev)
|
||||
mt7925_pci_remove(pdev);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mt7925_pm_ops, mt7925_pci_suspend, mt7925_pci_resume);
|
||||
static int mt7925_pci_resume(struct device *device)
|
||||
{
|
||||
return _mt7925_pci_resume(device, false);
|
||||
}
|
||||
|
||||
static int mt7925_pci_restore(struct device *device)
|
||||
{
|
||||
return _mt7925_pci_resume(device, true);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mt7925_pm_ops = {
|
||||
.suspend = pm_sleep_ptr(mt7925_pci_suspend),
|
||||
.resume = pm_sleep_ptr(mt7925_pci_resume),
|
||||
.freeze = pm_sleep_ptr(mt7925_pci_suspend),
|
||||
.thaw = pm_sleep_ptr(mt7925_pci_resume),
|
||||
.poweroff = pm_sleep_ptr(mt7925_pci_suspend),
|
||||
.restore = pm_sleep_ptr(mt7925_pci_restore),
|
||||
};
|
||||
|
||||
static struct pci_driver mt7925_pci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
static const struct usb_device_id mt7925u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7925, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
/* Netgear, Inc. A9000 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9072, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
@@ -234,7 +234,6 @@ struct mt792x_dev {
|
||||
bool aspm_supported:1;
|
||||
bool hif_idle:1;
|
||||
bool hif_resumed:1;
|
||||
bool sar_inited:1;
|
||||
bool regd_change:1;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
|
||||
@@ -689,8 +689,12 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
|
||||
if (is_mt7921(&dev->mt76))
|
||||
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);
|
||||
}
|
||||
|
||||
if (dev->pm.enable)
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
|
||||
@@ -181,13 +181,13 @@ mt792x_dma_reset(struct mt792x_dev *dev, bool force)
|
||||
|
||||
/* reset hw queues */
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
|
||||
mt76_queue_reset(dev, dev->mphy.q_tx[i], true);
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i], true);
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
|
||||
ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
|
||||
idx -= MT_TXQ_ID(0);
|
||||
|
||||
if (phy->mt76->band_idx == MT_BAND2)
|
||||
if (wed == &dev->mt76.mmio.wed_hif2)
|
||||
flags = MT_WED_Q_TX(0);
|
||||
else
|
||||
flags = MT_WED_Q_TX(idx);
|
||||
@@ -83,36 +83,74 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->has_rro) {
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
/* band0 */
|
||||
RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
|
||||
MT7996_RXQ_RRO_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
|
||||
MT7996_RXQ_MSDU_PG_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
|
||||
MT7996_RXQ_TXFREE0);
|
||||
/* band1 */
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
|
||||
MT7996_RXQ_MSDU_PG_BAND1);
|
||||
/* band2 */
|
||||
RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
|
||||
MT7996_RXQ_RRO_BAND2);
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
|
||||
MT7996_RXQ_MSDU_PG_BAND2);
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
|
||||
MT7996_RXQ_TXFREE2);
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3)
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0,
|
||||
MT_INT_RX_DONE_MSDU_PG_BAND0,
|
||||
MT7996_RXQ_MSDU_PG_BAND0);
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0,
|
||||
MT_INT_RX_TXFREE_MAIN, MT7996_RXQ_TXFREE0);
|
||||
/* band1 */
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0,
|
||||
MT_INT_RX_DONE_MSDU_PG_BAND1,
|
||||
MT7996_RXQ_MSDU_PG_BAND1);
|
||||
/* band2 */
|
||||
RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0,
|
||||
MT_INT_RX_DONE_RRO_BAND2,
|
||||
MT7996_RXQ_RRO_BAND2);
|
||||
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0,
|
||||
MT_INT_RX_DONE_MSDU_PG_BAND2,
|
||||
MT7996_RXQ_MSDU_PG_BAND2);
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0,
|
||||
MT_INT_RX_TXFREE_TRI, MT7996_RXQ_TXFREE2);
|
||||
} else {
|
||||
RXQ_CONFIG(MT_RXQ_RRO_BAND1, WFDMA0,
|
||||
MT_INT_RX_DONE_RRO_BAND1,
|
||||
MT7996_RXQ_RRO_BAND1);
|
||||
}
|
||||
|
||||
RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
|
||||
MT7996_RXQ_RRO_IND);
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3)
|
||||
RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0,
|
||||
MT_INT_RX_DONE_RRO_IND,
|
||||
MT7996_RXQ_RRO_IND);
|
||||
else
|
||||
RXQ_CONFIG(MT_RXQ_RRO_RXDMAD_C, WFDMA0,
|
||||
MT_INT_RX_DONE_RRO_RXDMAD_C,
|
||||
MT7996_RXQ_RRO_RXDMAD_C);
|
||||
}
|
||||
|
||||
/* data tx queue */
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
|
||||
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);
|
||||
} else {
|
||||
/* single pcie bn0/1:ring18 bn2:ring19 */
|
||||
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
}
|
||||
} else {
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
|
||||
if (dev->hif2) {
|
||||
/* bn0:ring18 bn1:ring21 */
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
|
||||
MT7996_TXQ_BAND0);
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND2,
|
||||
MT7996_TXQ_BAND2);
|
||||
} else {
|
||||
/* single pcie bn0:ring18 bn1:ring19 */
|
||||
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0,
|
||||
MT7996_TXQ_BAND0);
|
||||
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1,
|
||||
MT7996_TXQ_BAND1);
|
||||
}
|
||||
}
|
||||
|
||||
/* mcu tx queue */
|
||||
@@ -166,11 +204,12 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
|
||||
|
||||
/* Rx TxFreeDone From MAC Rings */
|
||||
val = is_mt7996(&dev->mt76) ? 4 : 8;
|
||||
if (is_mt7990(&dev->mt76) || (is_mt7996(&dev->mt76) && dev->has_rro))
|
||||
if ((is_mt7996(&dev->mt76) && mt7996_has_hwrro(dev)) ||
|
||||
is_mt7990(&dev->mt76))
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND0) + ofs, PREFETCH(val));
|
||||
if (is_mt7990(&dev->mt76) && dev->hif2)
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND1) + ofs, PREFETCH(val));
|
||||
else if (is_mt7996(&dev->mt76) && dev->has_rro)
|
||||
else if (is_mt7996(&dev->mt76) && mt7996_has_hwrro(dev))
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND2) + ofs, PREFETCH(val));
|
||||
|
||||
/* Rx Data Rings */
|
||||
@@ -179,7 +218,7 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10));
|
||||
|
||||
/* Rx RRO Rings */
|
||||
if (dev->has_rro) {
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_RRO_BAND0) + ofs, PREFETCH(0x10));
|
||||
queue = is_mt7996(&dev->mt76) ? MT_RXQ_RRO_BAND2 : MT_RXQ_RRO_BAND1;
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10));
|
||||
@@ -288,11 +327,14 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
|
||||
if (mt7996_band_valid(dev, MT_BAND0))
|
||||
irq_mask |= MT_INT_BAND0_RX_DONE;
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND1))
|
||||
if (mt7996_band_valid(dev, MT_BAND1)) {
|
||||
irq_mask |= MT_INT_BAND1_RX_DONE;
|
||||
if (is_mt7992(&dev->mt76) && dev->hif2)
|
||||
irq_mask |= MT_INT_RX_TXFREE_BAND1_EXT;
|
||||
}
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND2))
|
||||
irq_mask |= MT_INT_BAND2_RX_DONE;
|
||||
irq_mask |= MT_INT_BAND2_RX_DONE | MT_INT_TX_RX_DONE_EXT;
|
||||
|
||||
if (mtk_wed_device_active(wed) && wed_reset) {
|
||||
u32 wed_irq_mask = irq_mask;
|
||||
@@ -378,13 +420,48 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
|
||||
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
|
||||
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_PDMA_BAND |
|
||||
MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
|
||||
MT_WFDMA_HOST_CONFIG_PDMA_BAND);
|
||||
|
||||
mt76_clear(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_BAND0_PCIE1 |
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
/* WFDMA rx threshold */
|
||||
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH + hif1_ofs, 0xc000c);
|
||||
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH + hif1_ofs, 0x10008);
|
||||
@@ -397,27 +474,58 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
|
||||
* so, redirect pcie0 rx ring3 interrupt to pcie1
|
||||
*/
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
|
||||
dev->has_rro)
|
||||
mt7996_has_hwrro(dev)) {
|
||||
u32 intr = is_mt7996(&dev->mt76) ?
|
||||
MT_WFDMA0_RX_INT_SEL_RING6 :
|
||||
MT_WFDMA0_RX_INT_SEL_RING9 |
|
||||
MT_WFDMA0_RX_INT_SEL_RING5;
|
||||
|
||||
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
|
||||
MT_WFDMA0_RX_INT_SEL_RING6);
|
||||
else
|
||||
intr);
|
||||
} else {
|
||||
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
|
||||
MT_WFDMA0_RX_INT_SEL_RING3);
|
||||
}
|
||||
}
|
||||
|
||||
mt7996_dma_start(dev, reset, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
u32 irq_mask;
|
||||
int ret;
|
||||
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
/* rxdmad_c */
|
||||
mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].flags = MT_WED_RRO_Q_RXDMAD_C;
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed))
|
||||
mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].wed = &mdev->mmio.wed;
|
||||
else
|
||||
mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].flags |= MT_QFLAG_EMI_EN;
|
||||
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_RXDMAD_C),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RRO_AP_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* We need to set cpu idx pointer before resetting the EMI
|
||||
* queues.
|
||||
*/
|
||||
mdev->q_rx[MT_RXQ_RRO_RXDMAD_C].emi_cpu_idx =
|
||||
&dev->wed_rro.emi_rings_cpu.ptr->ring[0].idx;
|
||||
mt76_queue_reset(dev, &mdev->q_rx[MT_RXQ_RRO_RXDMAD_C], true);
|
||||
goto start_hw_rro;
|
||||
}
|
||||
|
||||
/* ind cmd */
|
||||
mdev->q_rx[MT_RXQ_RRO_IND].flags = MT_WED_RRO_Q_IND;
|
||||
mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed;
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&mdev->mmio.wed))
|
||||
mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed;
|
||||
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_IND],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_IND),
|
||||
MT7996_RX_RING_SIZE,
|
||||
@@ -428,7 +536,9 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
/* rx msdu page queue for band0 */
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags =
|
||||
MT_WED_RRO_Q_MSDU_PG(0) | MT_QFLAG_WED_RRO_EN;
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
|
||||
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;
|
||||
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,
|
||||
@@ -437,11 +547,13 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND1)) {
|
||||
if (mt7996_band_valid(dev, MT_BAND1) && is_mt7996(&dev->mt76)) {
|
||||
/* rx msdu page queue for band1 */
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags =
|
||||
MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN;
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
|
||||
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;
|
||||
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,
|
||||
@@ -455,7 +567,9 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
/* rx msdu page queue for band2 */
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags =
|
||||
MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN;
|
||||
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
|
||||
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;
|
||||
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,
|
||||
@@ -465,15 +579,42 @@ int mt7996_dma_rro_init(struct mt7996_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE |
|
||||
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);
|
||||
mt7996_irq_enable(dev, irq_mask);
|
||||
start_hw_rro:
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed)) {
|
||||
irq_mask = mdev->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);
|
||||
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);
|
||||
}
|
||||
mt7996_irq_enable(dev, MT_INT_RRO_RX_DONE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
|
||||
|
||||
int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
{
|
||||
@@ -560,7 +701,9 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
return ret;
|
||||
|
||||
/* tx free notify event from WA for band0 */
|
||||
if (mtk_wed_device_active(wed) && !dev->has_rro) {
|
||||
if (mtk_wed_device_active(wed) &&
|
||||
((is_mt7996(&dev->mt76) && !mt7996_has_hwrro(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;
|
||||
}
|
||||
@@ -615,7 +758,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
/* tx free notify event from WA for mt7996 band2
|
||||
* use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
|
||||
*/
|
||||
if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) {
|
||||
if (mtk_wed_device_active(wed_hif2) && !mt7996_has_hwrro(dev)) {
|
||||
dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2;
|
||||
}
|
||||
@@ -630,6 +773,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
} else if (mt7996_band_valid(dev, MT_BAND1)) {
|
||||
/* rx data queue for mt7992 band1 */
|
||||
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs;
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
|
||||
dev->mt76.q_rx[MT_RXQ_BAND1].flags = MT_WED_Q_RX(1);
|
||||
dev->mt76.q_rx[MT_RXQ_BAND1].wed = wed;
|
||||
}
|
||||
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1),
|
||||
MT7996_RX_RING_SIZE,
|
||||
@@ -641,6 +789,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
/* tx free notify event from WA for mt7992 band1 */
|
||||
if (mt7996_has_wa(dev)) {
|
||||
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs;
|
||||
if (mtk_wed_device_active(wed_hif2)) {
|
||||
dev->mt76.q_rx[MT_RXQ_BAND1_WA].flags =
|
||||
MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_BAND1_WA].wed = wed_hif2;
|
||||
}
|
||||
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1_WA),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
@@ -651,12 +805,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
|
||||
dev->has_rro) {
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
/* rx rro data queue for band0 */
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags =
|
||||
MT_WED_RRO_Q_DATA(0) | MT_QFLAG_WED_RRO_EN;
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed;
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed;
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_BAND0),
|
||||
MT7996_RX_RING_SIZE,
|
||||
@@ -665,23 +819,44 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* 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;
|
||||
if (is_mt7992(&dev->mt76)) {
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND1].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_BAND1].wed = wed;
|
||||
ret = mt76_queue_alloc(dev,
|
||||
&dev->mt76.q_rx[MT_RXQ_RRO_BAND1],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_BAND1),
|
||||
MT7996_RX_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND1) + hif1_ofs);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
|
||||
MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = mt76_queue_alloc(dev,
|
||||
&dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
|
||||
MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND2)) {
|
||||
/* 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;
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
|
||||
if (mtk_wed_device_active(wed) &&
|
||||
mtk_wed_get_rx_capa(wed))
|
||||
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
|
||||
MT_RXQ_ID(MT_RXQ_RRO_BAND2),
|
||||
MT7996_RX_RING_SIZE,
|
||||
@@ -752,6 +927,10 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
if (mt7996_has_hwrro(dev) &&
|
||||
!mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
mt7996_rro_msdu_page_map_free(dev);
|
||||
|
||||
/* reset wfsys */
|
||||
if (force)
|
||||
mt7996_wfsys_reset(dev);
|
||||
@@ -775,21 +954,32 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
|
||||
}
|
||||
|
||||
for (i = 0; i < __MT_MCUQ_MAX; i++)
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
|
||||
mt76_queue_reset(dev, dev->mt76.q_mcu[i], true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
if (mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]) ||
|
||||
mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
|
||||
continue;
|
||||
struct mt76_queue *q = &dev->mt76.q_rx[i];
|
||||
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
if (mt76_queue_is_wed_rro(q) ||
|
||||
mt76_queue_is_wed_tx_free(q)) {
|
||||
if (force && mt76_queue_is_wed_rro_data(q))
|
||||
mt76_queue_reset(dev, q, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mt76_queue_reset(dev, q, true);
|
||||
}
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && force &&
|
||||
(mt76_queue_is_wed_rro_ind(&dev->mt76.q_rx[i]) ||
|
||||
mt76_queue_is_wed_rro_msdu_pg(&dev->mt76.q_rx[i])))
|
||||
continue;
|
||||
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
}
|
||||
|
||||
mt7996_dma_enable(dev, !force);
|
||||
}
|
||||
|
||||
@@ -334,9 +334,8 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
|
||||
return ret;
|
||||
|
||||
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN);
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
return 0;
|
||||
return mt76_eeprom_override(&dev->mphy);
|
||||
}
|
||||
|
||||
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
|
||||
|
||||
@@ -63,6 +63,33 @@ static const struct ieee80211_iface_combination if_comb = {
|
||||
.beacon_int_min_gcd = 100,
|
||||
};
|
||||
|
||||
static const u8 if_types_ext_capa_ap[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
|
||||
static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = {
|
||||
{
|
||||
.iftype = NL80211_IFTYPE_AP,
|
||||
.extended_capabilities = if_types_ext_capa_ap,
|
||||
.extended_capabilities_mask = if_types_ext_capa_ap,
|
||||
.extended_capabilities_len = sizeof(if_types_ext_capa_ap),
|
||||
.eml_capabilities = IEEE80211_EML_CAP_EMLSR_SUPP,
|
||||
.mld_capa_and_ops =
|
||||
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
|
||||
MT7996_MAX_RADIOS - 1),
|
||||
}, {
|
||||
.iftype = NL80211_IFTYPE_STATION,
|
||||
.extended_capabilities = if_types_ext_capa_ap,
|
||||
.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_MAX_SIMUL_LINKS,
|
||||
MT7996_MAX_RADIOS - 1),
|
||||
},
|
||||
};
|
||||
|
||||
static ssize_t mt7996_thermal_temp_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -383,6 +410,7 @@ mt7996_init_wiphy_band(struct ieee80211_hw *hw, struct mt7996_phy *phy)
|
||||
|
||||
phy->slottime = 9;
|
||||
phy->beacon_rate = -1;
|
||||
phy->rxfilter = MT_WF_RFCR_DROP_OTHER_UC;
|
||||
|
||||
if (phy->mt76->cap.has_2ghz) {
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||
@@ -463,8 +491,11 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
wiphy->radio = dev->radios;
|
||||
|
||||
wiphy->reg_notifier = mt7996_regd_notifier;
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
|
||||
WIPHY_FLAG_SUPPORTS_MLO;
|
||||
wiphy->mbssid_max_interfaces = 16;
|
||||
wiphy->iftype_ext_capab = iftypes_ext_capa;
|
||||
wiphy->num_iftype_ext_capab = ARRAY_SIZE(iftypes_ext_capa);
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
@@ -575,19 +606,21 @@ void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
}
|
||||
|
||||
/* rro module init */
|
||||
if (is_mt7996(&dev->mt76))
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
|
||||
else
|
||||
if (dev->hif2)
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
|
||||
dev->hif2 ? 7 : 0);
|
||||
is_mt7996(&dev->mt76) ? 2 : 7);
|
||||
else
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);
|
||||
|
||||
if (dev->has_rro) {
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
u16 timeout;
|
||||
|
||||
timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128;
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE,
|
||||
is_mt7996(&dev->mt76) ? 1 : 2);
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH,
|
||||
!is_mt7996(&dev->mt76));
|
||||
} else {
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
|
||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
|
||||
@@ -634,7 +667,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||
if (!mt7996_band_valid(dev, band))
|
||||
return 0;
|
||||
|
||||
if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) {
|
||||
if (dev->hif2 &&
|
||||
((is_mt7996(&dev->mt76) && band == MT_BAND2) ||
|
||||
(is_mt7992(&dev->mt76) && band == MT_BAND1))) {
|
||||
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
wed = &dev->mt76.mmio.wed_hif2;
|
||||
}
|
||||
@@ -667,17 +702,26 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||
if (band == MT_BAND2)
|
||||
mphy->macaddr[0] ^= BIT(6);
|
||||
}
|
||||
mt76_eeprom_override(mphy);
|
||||
ret = mt76_eeprom_override(mphy);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* init wiphy according to mphy and phy */
|
||||
mt7996_init_wiphy_band(mphy->hw, phy);
|
||||
ret = mt7996_init_tx_queues(mphy->priv,
|
||||
MT_TXQ_ID(band),
|
||||
MT7996_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(band) + hif1_ofs,
|
||||
wed);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (is_mt7996(&dev->mt76) && !dev->hif2 && band == MT_BAND1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= MT_TXQ_PSD; i++)
|
||||
mphy->q_tx[i] = dev->mt76.phys[MT_BAND0]->q_tx[0];
|
||||
} else {
|
||||
ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band),
|
||||
MT7996_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(band) + hif1_ofs,
|
||||
wed);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = mt76_register_phy(mphy, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
@@ -685,10 +729,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
|
||||
goto error;
|
||||
|
||||
if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
|
||||
u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
|
||||
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
|
||||
mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask);
|
||||
mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TX_RX_DONE_EXT);
|
||||
mtk_wed_device_start(&dev->mt76.mmio.wed_hif2,
|
||||
MT_INT_TX_RX_DONE_EXT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -724,30 +767,151 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static void mt7996_rro_hw_init_v3(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
u32 session_id;
|
||||
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
|
||||
wed->wlan.ind_cmd.win_size =
|
||||
ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
|
||||
if (is_mt7996(&dev->mt76))
|
||||
wed->wlan.ind_cmd.particular_sid =
|
||||
MT7996_RRO_MAX_SESSION;
|
||||
else
|
||||
wed->wlan.ind_cmd.particular_sid = 1;
|
||||
wed->wlan.ind_cmd.particular_se_phys =
|
||||
dev->wed_rro.session.phy_addr;
|
||||
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
|
||||
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
|
||||
}
|
||||
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
|
||||
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
|
||||
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
|
||||
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
|
||||
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
|
||||
} else {
|
||||
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0);
|
||||
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1, 0);
|
||||
}
|
||||
|
||||
/* particular session configure */
|
||||
/* use max session idx + 1 as particular session id */
|
||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
|
||||
|
||||
session_id = is_mt7996(&dev->mt76) ? MT7996_RRO_MAX_SESSION : 1;
|
||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
|
||||
MT_RRO_PARTICULAR_CONFG_EN |
|
||||
FIELD_PREP(MT_RRO_PARTICULAR_SID, session_id));
|
||||
}
|
||||
|
||||
void mt7996_rro_hw_init(struct mt7996_dev *dev)
|
||||
{
|
||||
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
|
||||
int i;
|
||||
|
||||
if (!mt7996_has_hwrro(dev))
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&dev->wed_rro.page_cache);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.page_map); i++)
|
||||
INIT_LIST_HEAD(&dev->wed_rro.page_map[i]);
|
||||
|
||||
if (!is_mt7996(&dev->mt76)) {
|
||||
reg = MT_RRO_MSDU_PG_SEG_ADDR0;
|
||||
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
mt76_clear(dev, MT_RRO_3_0_EMU_CONF,
|
||||
MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||
mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG,
|
||||
MT_RRO_3_1_GLOBAL_CONFIG_RXDMAD_SEL);
|
||||
if (!mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG,
|
||||
MT_RRO_3_1_GLOBAL_CONFIG_RX_DIDX_WR_EN |
|
||||
MT_RRO_3_1_GLOBAL_CONFIG_RX_CIDX_RD_EN);
|
||||
mt76_wr(dev, MT_RRO_RX_RING_AP_CIDX_ADDR,
|
||||
dev->wed_rro.emi_rings_cpu.phy_addr >> 4);
|
||||
mt76_wr(dev, MT_RRO_RX_RING_AP_DIDX_ADDR,
|
||||
dev->wed_rro.emi_rings_dma.phy_addr >> 4);
|
||||
}
|
||||
} else {
|
||||
/* set emul 3.0 function */
|
||||
mt76_wr(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);
|
||||
}
|
||||
|
||||
mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG,
|
||||
MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN);
|
||||
|
||||
/* setup Msdu page address */
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||
mt76_wr(dev, reg,
|
||||
dev->wed_rro.msdu_pg[i].phy_addr >> 4);
|
||||
reg += 4;
|
||||
}
|
||||
} else {
|
||||
/* TODO: remove line after WM has set */
|
||||
mt76_clear(dev, WF_RRO_AXI_MST_CFG,
|
||||
WF_RRO_AXI_MST_CFG_DIDX_OK);
|
||||
|
||||
/* setup BA bitmap cache address */
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
|
||||
dev->wed_rro.ba_bitmap[0].phy_addr);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
|
||||
dev->wed_rro.ba_bitmap[1].phy_addr);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
|
||||
|
||||
/* Setup Address element address */
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
|
||||
mt76_wr(dev, reg,
|
||||
dev->wed_rro.addr_elem[i].phy_addr >> 4);
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
/* Setup Address element address - separate address segment
|
||||
* mode.
|
||||
*/
|
||||
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
|
||||
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
|
||||
}
|
||||
|
||||
mt7996_rro_hw_init_v3(dev);
|
||||
|
||||
/* interrupt enable */
|
||||
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
|
||||
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
|
||||
}
|
||||
|
||||
static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||
{
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
|
||||
u32 val = FIELD_PREP(WED_RRO_ADDR_SIGNATURE_MASK, 0xff);
|
||||
struct mt7996_wed_rro_addr *addr;
|
||||
void *ptr;
|
||||
int i;
|
||||
|
||||
if (!dev->has_rro)
|
||||
if (!mt7996_has_hwrro(dev))
|
||||
return 0;
|
||||
|
||||
if (!mtk_wed_device_active(wed))
|
||||
return 0;
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3) {
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
MT7996_RRO_BA_BITMAP_CR_SIZE,
|
||||
&dev->wed_rro.ba_bitmap[i].phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
MT7996_RRO_BA_BITMAP_CR_SIZE,
|
||||
&dev->wed_rro.ba_bitmap[i].phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->wed_rro.ba_bitmap[i].ptr = ptr;
|
||||
dev->wed_rro.ba_bitmap[i].ptr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
|
||||
@@ -766,12 +930,53 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||
|
||||
addr = dev->wed_rro.addr_elem[i].ptr;
|
||||
for (j = 0; j < MT7996_RRO_WINDOW_MAX_SIZE; j++) {
|
||||
addr->signature = 0xff;
|
||||
addr->data = cpu_to_le32(val);
|
||||
addr++;
|
||||
}
|
||||
|
||||
wed->wlan.ind_cmd.addr_elem_phys[i] =
|
||||
dev->wed_rro.addr_elem[i].phy_addr;
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
|
||||
mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) {
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
|
||||
wed->wlan.ind_cmd.addr_elem_phys[i] =
|
||||
dev->wed_rro.addr_elem[i].phy_addr;
|
||||
}
|
||||
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
MT7996_RRO_MSDU_PG_SIZE_PER_CR,
|
||||
&dev->wed_rro.msdu_pg[i].phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->wed_rro.msdu_pg[i].ptr = ptr;
|
||||
|
||||
memset(dev->wed_rro.msdu_pg[i].ptr, 0,
|
||||
MT7996_RRO_MSDU_PG_SIZE_PER_CR);
|
||||
}
|
||||
|
||||
if (dev->mt76.hwrro_mode == MT76_HWRRO_V3_1) {
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
sizeof(dev->wed_rro.emi_rings_cpu.ptr),
|
||||
&dev->wed_rro.emi_rings_cpu.phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->wed_rro.emi_rings_cpu.ptr = ptr;
|
||||
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
sizeof(dev->wed_rro.emi_rings_dma.ptr),
|
||||
&dev->wed_rro.emi_rings_dma.phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->wed_rro.emi_rings_dma.ptr = ptr;
|
||||
}
|
||||
|
||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||
@@ -784,69 +989,20 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||
dev->wed_rro.session.ptr = ptr;
|
||||
addr = dev->wed_rro.session.ptr;
|
||||
for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
|
||||
addr->signature = 0xff;
|
||||
addr->data = cpu_to_le32(val);
|
||||
addr++;
|
||||
}
|
||||
|
||||
/* rro hw init */
|
||||
/* TODO: remove line after WM has set */
|
||||
mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
|
||||
mt7996_rro_hw_init(dev);
|
||||
|
||||
/* setup BA bitmap cache address */
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
|
||||
dev->wed_rro.ba_bitmap[0].phy_addr);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
|
||||
dev->wed_rro.ba_bitmap[1].phy_addr);
|
||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
|
||||
|
||||
/* setup Address element address */
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
|
||||
mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4);
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
/* setup Address element address - separate address segment mode */
|
||||
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
|
||||
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
|
||||
|
||||
wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
|
||||
wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
|
||||
wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
|
||||
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
|
||||
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
|
||||
|
||||
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
|
||||
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
|
||||
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
|
||||
|
||||
/* particular session configure */
|
||||
/* use max session idx + 1 as particular session id */
|
||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
|
||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
|
||||
MT_RRO_PARTICULAR_CONFG_EN |
|
||||
FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION));
|
||||
|
||||
/* interrupt enable */
|
||||
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
|
||||
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
|
||||
|
||||
/* rro ind cmd queue init */
|
||||
return mt7996_dma_rro_init(dev);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mt7996_wed_rro_free(struct mt7996_dev *dev)
|
||||
{
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
int i;
|
||||
|
||||
if (!dev->has_rro)
|
||||
return;
|
||||
|
||||
if (!mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
if (!mt7996_has_hwrro(dev))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
|
||||
@@ -870,6 +1026,16 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev)
|
||||
dev->wed_rro.addr_elem[i].phy_addr);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||
if (!dev->wed_rro.msdu_pg[i].ptr)
|
||||
continue;
|
||||
|
||||
dmam_free_coherent(dev->mt76.dma_dev,
|
||||
MT7996_RRO_MSDU_PG_SIZE_PER_CR,
|
||||
dev->wed_rro.msdu_pg[i].ptr,
|
||||
dev->wed_rro.msdu_pg[i].phy_addr);
|
||||
}
|
||||
|
||||
if (!dev->wed_rro.session.ptr)
|
||||
return;
|
||||
|
||||
@@ -878,12 +1044,11 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev)
|
||||
sizeof(struct mt7996_wed_rro_addr),
|
||||
dev->wed_rro.session.ptr,
|
||||
dev->wed_rro.session.phy_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mt7996_wed_rro_work(struct work_struct *work)
|
||||
{
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
u32 val = FIELD_PREP(WED_RRO_ADDR_SIGNATURE_MASK, 0xff);
|
||||
struct mt7996_dev *dev;
|
||||
LIST_HEAD(list);
|
||||
|
||||
@@ -920,13 +1085,12 @@ static void mt7996_wed_rro_work(struct work_struct *work)
|
||||
MT7996_RRO_WINDOW_MAX_LEN;
|
||||
reset:
|
||||
elem = ptr + elem_id * sizeof(*elem);
|
||||
elem->signature = 0xff;
|
||||
elem->data |= cpu_to_le32(val);
|
||||
}
|
||||
mt7996_mcu_wed_rro_reset_sessions(dev, e->id);
|
||||
out:
|
||||
kfree(e);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mt7996_variant_type_init(struct mt7996_dev *dev)
|
||||
@@ -1321,7 +1485,6 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
eht_cap->has_eht = true;
|
||||
|
||||
eht_cap_elem->mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454,
|
||||
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
|
||||
@@ -1551,6 +1714,9 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
|
||||
mt7996_mcu_exit(dev);
|
||||
mt7996_tx_token_put(dev);
|
||||
mt7996_dma_cleanup(dev);
|
||||
if (mt7996_has_hwrro(dev) &&
|
||||
!mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
mt7996_rro_msdu_page_map_free(dev);
|
||||
tasklet_disable(&dev->mt76.irq_tasklet);
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -138,6 +138,28 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_own_mld_idx(u64 mask, bool group_mld)
|
||||
{
|
||||
u8 start = group_mld ? 0 : 16;
|
||||
u8 end = group_mld ? 15 : 63;
|
||||
int idx;
|
||||
|
||||
idx = get_free_idx(mask, start, end);
|
||||
if (idx)
|
||||
return idx - 1;
|
||||
|
||||
/* If the 16-63 range is not available, perform another lookup in the
|
||||
* range 0-15
|
||||
*/
|
||||
if (!group_mld) {
|
||||
idx = get_free_idx(mask, 0, 15);
|
||||
if (idx)
|
||||
return idx - 1;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_init_bitrate_mask(struct ieee80211_vif *vif, struct mt7996_vif_link *mlink)
|
||||
{
|
||||
@@ -160,112 +182,105 @@ mt7996_init_bitrate_mask(struct ieee80211_vif *vif, struct mt7996_vif_link *mlin
|
||||
static int
|
||||
mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
unsigned int link_id, struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
int idx = key->keyidx;
|
||||
unsigned int link_id;
|
||||
unsigned long links;
|
||||
u8 *wcid_keyidx;
|
||||
bool is_bigtk;
|
||||
int err;
|
||||
|
||||
if (key->link_id >= 0)
|
||||
links = BIT(key->link_id);
|
||||
else if (sta && sta->valid_links)
|
||||
links = sta->valid_links;
|
||||
else if (vif->valid_links)
|
||||
links = vif->valid_links;
|
||||
else
|
||||
links = BIT(0);
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
return 0;
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
u8 *wcid_keyidx;
|
||||
int err;
|
||||
if (!mt7996_vif_link_phy(link))
|
||||
return 0;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
if (sta) {
|
||||
struct mt7996_sta *msta;
|
||||
|
||||
if (sta) {
|
||||
struct mt7996_sta *msta;
|
||||
msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
msta_link = mt76_dereference(msta->link[link_id],
|
||||
&dev->mt76);
|
||||
if (!msta_link)
|
||||
return 0;
|
||||
|
||||
msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
msta_link = mt76_dereference(msta->link[link_id],
|
||||
&dev->mt76);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
if (!msta_link->wcid.sta)
|
||||
return -EOPNOTSUPP;
|
||||
} else {
|
||||
msta_link = &link->msta_link;
|
||||
}
|
||||
wcid_keyidx = &msta_link->wcid.hw_key_idx;
|
||||
|
||||
if (!msta_link->wcid.sta)
|
||||
return -EOPNOTSUPP;
|
||||
} else {
|
||||
msta_link = &link->msta_link;
|
||||
is_bigtk = key->keyidx == 6 || key->keyidx == 7;
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
if (is_bigtk) {
|
||||
wcid_keyidx = &msta_link->wcid.hw_key_idx2;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
|
||||
}
|
||||
wcid_keyidx = &msta_link->wcid.hw_key_idx;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
if (key->keyidx == 6 || key->keyidx == 7) {
|
||||
wcid_keyidx = &msta_link->wcid.hw_key_idx2;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
link_conf = link_conf_dereference_protected(vif,
|
||||
link_id);
|
||||
if (!link_conf)
|
||||
link_conf = &vif->bss_conf;
|
||||
|
||||
link->mt76.cipher =
|
||||
mt76_connac_mcu_get_cipher(key->cipher);
|
||||
mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
|
||||
&link->mt76, msta_link, true);
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
*wcid_keyidx = idx;
|
||||
} else {
|
||||
if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
|
||||
|
||||
if (key->keyidx == 6 || key->keyidx == 7) {
|
||||
err = mt7996_mcu_bcn_prot_enable(dev, link,
|
||||
msta_link, key);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt7996_mcu_add_key(&dev->mt76, vif, key,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
||||
&msta_link->wcid, cmd);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
link_conf = link_conf_dereference_protected(vif, link_id);
|
||||
if (!link_conf)
|
||||
link_conf = &vif->bss_conf;
|
||||
|
||||
if (cmd == SET_KEY && !sta && !link->mt76.cipher) {
|
||||
link->mt76.cipher =
|
||||
mt76_connac_mcu_get_cipher(key->cipher);
|
||||
mt7996_mcu_add_bss_info(link->phy, vif, link_conf,
|
||||
&link->mt76, msta_link, true);
|
||||
}
|
||||
|
||||
if (cmd == SET_KEY)
|
||||
*wcid_keyidx = idx;
|
||||
else if (idx == *wcid_keyidx)
|
||||
*wcid_keyidx = -1;
|
||||
|
||||
if (cmd != SET_KEY && sta)
|
||||
return 0;
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
|
||||
|
||||
err = mt7996_mcu_add_key(&dev->mt76, vif, key,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
||||
&msta_link->wcid, cmd);
|
||||
|
||||
/* remove and add beacon in order to enable beacon protection */
|
||||
if (cmd == SET_KEY && is_bigtk && link_conf->enable_beacon) {
|
||||
mt7996_mcu_add_beacon(hw, vif, link_conf, false);
|
||||
mt7996_mcu_add_beacon(hw, vif, link_conf, true);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct mt7996_key_iter_data {
|
||||
enum set_key_cmd cmd;
|
||||
unsigned int link_id;
|
||||
};
|
||||
|
||||
static void
|
||||
mt7996_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct mt7996_key_iter_data *it = data;
|
||||
|
||||
if (sta)
|
||||
return;
|
||||
|
||||
WARN_ON(mt7996_set_hw_key(hw, SET_KEY, vif, NULL, key));
|
||||
WARN_ON(mt7996_set_hw_key(hw, it->cmd, vif, NULL, it->link_id, key));
|
||||
}
|
||||
|
||||
int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
@@ -278,8 +293,12 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
struct mt7996_phy *phy = mphy->priv;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
u8 band_idx = phy->mt76->band_idx;
|
||||
struct mt7996_key_iter_data it = {
|
||||
.cmd = SET_KEY,
|
||||
.link_id = link_conf->link_id,
|
||||
};
|
||||
struct mt76_txq *mtxq;
|
||||
int idx, ret;
|
||||
int mld_idx, idx, ret;
|
||||
|
||||
mlink->idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mlink->idx >= mt7996_max_interface_num(dev))
|
||||
@@ -289,6 +308,17 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
if (idx < 0)
|
||||
return -ENOSPC;
|
||||
|
||||
if (!dev->mld_idx_mask) { /* first link in the group */
|
||||
mvif->mld_group_idx = get_own_mld_idx(dev->mld_idx_mask, true);
|
||||
mvif->mld_remap_idx = get_free_idx(dev->mld_remap_idx_mask,
|
||||
0, 15);
|
||||
}
|
||||
|
||||
mld_idx = get_own_mld_idx(dev->mld_idx_mask, false);
|
||||
if (mld_idx < 0)
|
||||
return -ENOSPC;
|
||||
|
||||
link->mld_idx = mld_idx;
|
||||
link->phy = phy;
|
||||
mlink->omac_idx = idx;
|
||||
mlink->band_idx = band_idx;
|
||||
@@ -301,6 +331,11 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
|
||||
dev->mt76.vif_mask |= BIT_ULL(mlink->idx);
|
||||
if (!dev->mld_idx_mask) {
|
||||
dev->mld_idx_mask |= BIT_ULL(mvif->mld_group_idx);
|
||||
dev->mld_remap_idx_mask |= BIT_ULL(mvif->mld_remap_idx);
|
||||
}
|
||||
dev->mld_idx_mask |= BIT_ULL(link->mld_idx);
|
||||
phy->omac_mask |= BIT_ULL(mlink->omac_idx);
|
||||
|
||||
idx = MT7996_WTBL_RESERVED - mlink->idx;
|
||||
@@ -339,7 +374,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
CONN_STATE_PORT_SECURE, true);
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
|
||||
|
||||
ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, NULL);
|
||||
ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
|
||||
|
||||
if (mvif->mt76.deflink_id == IEEE80211_LINK_UNSPECIFIED)
|
||||
mvif->mt76.deflink_id = link_conf->link_id;
|
||||
@@ -356,8 +391,14 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
struct mt7996_sta_link *msta_link = &link->msta_link;
|
||||
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;
|
||||
|
||||
ieee80211_iter_keys(mphy->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);
|
||||
@@ -380,7 +421,13 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
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 (!(dev->mld_idx_mask & ~BIT_ULL(mvif->mld_group_idx))) {
|
||||
/* last link */
|
||||
dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
|
||||
dev->mld_remap_idx_mask &= ~BIT_ULL(mvif->mld_remap_idx);
|
||||
}
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (!list_empty(&msta_link->wcid.poll_list))
|
||||
@@ -551,8 +598,9 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
int err;
|
||||
unsigned int link_id;
|
||||
unsigned long links;
|
||||
int err = 0;
|
||||
|
||||
/* The hardware does not support per-STA RX GTK, fallback
|
||||
* to software mode for these.
|
||||
@@ -586,11 +634,22 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!mt7996_vif_link_phy(&mvif->deflink))
|
||||
return 0; /* defer until after link add */
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
err = mt7996_set_hw_key(hw, cmd, vif, sta, key);
|
||||
|
||||
if (key->link_id >= 0)
|
||||
links = BIT(key->link_id);
|
||||
else if (sta && sta->valid_links)
|
||||
links = sta->valid_links;
|
||||
else if (vif->valid_links)
|
||||
links = vif->valid_links;
|
||||
else
|
||||
links = BIT(0);
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
err = mt7996_set_hw_key(hw, cmd, vif, sta, link_id, key);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return err;
|
||||
@@ -850,7 +909,7 @@ mt7996_link_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
link->mt76.beacon_rates_idx =
|
||||
mt7996_get_rates_table(phy, info, true, false);
|
||||
|
||||
mt7996_mcu_add_beacon(hw, vif, info);
|
||||
mt7996_mcu_add_beacon(hw, vif, info, info->enable_beacon);
|
||||
}
|
||||
|
||||
if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
@@ -878,7 +937,7 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf);
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf, vif->bss_conf.enable_beacon);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
@@ -925,6 +984,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
||||
msta_link->wcid.sta = 1;
|
||||
msta_link->wcid.idx = idx;
|
||||
msta_link->wcid.link_id = link_id;
|
||||
msta_link->wcid.def_wcid = &msta->deflink.wcid;
|
||||
|
||||
ewma_avg_signal_init(&msta_link->avg_ack_signal);
|
||||
ewma_signal_init(&msta_link->wcid.rssi);
|
||||
@@ -941,18 +1001,9 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, i);
|
||||
|
||||
mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
if (!list_empty(&msta_link->wcid.poll_list))
|
||||
list_del_init(&msta_link->wcid.poll_list);
|
||||
@@ -982,6 +1033,9 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
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)
|
||||
@@ -1036,16 +1090,17 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
goto error_unlink;
|
||||
}
|
||||
|
||||
err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
|
||||
link_id);
|
||||
if (err)
|
||||
goto error_unlink;
|
||||
|
||||
mphy = mt76_vif_link_phy(&link->mt76);
|
||||
if (!mphy) {
|
||||
err = -EINVAL;
|
||||
goto error_unlink;
|
||||
}
|
||||
|
||||
err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link,
|
||||
link_id);
|
||||
if (err)
|
||||
goto error_unlink;
|
||||
|
||||
mphy->num_sta++;
|
||||
}
|
||||
|
||||
@@ -1179,6 +1234,24 @@ mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_set_active_links(struct ieee80211_vif *vif)
|
||||
{
|
||||
u16 active_links;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
active_links = mt76_select_links(vif, MT7996_MAX_RADIOS);
|
||||
if (hweight16(active_links) < 2)
|
||||
return;
|
||||
|
||||
ieee80211_set_active_links_async(vif, active_links);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
|
||||
@@ -1196,16 +1269,18 @@ mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
mt7996_mac_sta_remove(dev, vif, sta);
|
||||
|
||||
if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC)
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
mt7996_set_active_links(vif);
|
||||
ev = MT76_STA_EVENT_ASSOC;
|
||||
else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED)
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
ev = MT76_STA_EVENT_AUTHORIZE;
|
||||
else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH)
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH) {
|
||||
ev = MT76_STA_EVENT_DISASSOC;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mt7996_mac_sta_event(dev, vif, sta, ev);
|
||||
}
|
||||
@@ -1214,28 +1289,61 @@ static void mt7996_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct ieee80211_sta *sta = control->sta;
|
||||
struct mt7996_sta *msta = sta ? (void *)sta->drv_priv : NULL;
|
||||
struct mt76_phy *mphy = hw->priv;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt7996_vif *mvif = vif ? (void *)vif->drv_priv : NULL;
|
||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||
u8 link_id = u32_get_bits(info->control.flags,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (vif) {
|
||||
struct mt7996_vif *mvif = (void *)vif->drv_priv;
|
||||
/* Use primary link_id if the value from mac80211 is set to
|
||||
* IEEE80211_LINK_UNSPECIFIED.
|
||||
*/
|
||||
if (link_id == IEEE80211_LINK_UNSPECIFIED) {
|
||||
if (msta)
|
||||
link_id = msta->deflink_id;
|
||||
else if (mvif)
|
||||
link_id = mvif->mt76.deflink_id;
|
||||
}
|
||||
|
||||
if (vif && ieee80211_vif_is_mld(vif)) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
if (msta) {
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
|
||||
link_sta = rcu_dereference(sta->link[link_id]);
|
||||
if (!link_sta)
|
||||
link_sta = rcu_dereference(sta->link[msta->deflink_id]);
|
||||
|
||||
if (link_sta) {
|
||||
memcpy(hdr->addr1, link_sta->addr, ETH_ALEN);
|
||||
if (ether_addr_equal(sta->addr, hdr->addr3))
|
||||
memcpy(hdr->addr3, link_sta->addr, ETH_ALEN);
|
||||
}
|
||||
}
|
||||
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (link_conf) {
|
||||
memcpy(hdr->addr2, link_conf->addr, ETH_ALEN);
|
||||
if (ether_addr_equal(vif->addr, hdr->addr3))
|
||||
memcpy(hdr->addr3, link_conf->addr, ETH_ALEN);
|
||||
}
|
||||
}
|
||||
|
||||
if (mvif) {
|
||||
struct mt76_vif_link *mlink = &mvif->deflink.mt76;
|
||||
|
||||
if (link_id < IEEE80211_LINK_UNSPECIFIED)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
|
||||
if (!mlink) {
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mlink->wcid)
|
||||
wcid = mlink->wcid;
|
||||
|
||||
@@ -1254,8 +1362,7 @@ static void mt7996_tx(struct ieee80211_hw *hw,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (control->sta && link_id < IEEE80211_LINK_UNSPECIFIED) {
|
||||
struct mt7996_sta *msta = (void *)control->sta->drv_priv;
|
||||
if (msta && link_id < IEEE80211_LINK_UNSPECIFIED) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
@@ -1292,16 +1399,13 @@ static int
|
||||
mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
enum ieee80211_ampdu_mlme_action action = params->action;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct ieee80211_txq *txq = sta->txq[params->tid];
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
u16 tid = params->tid;
|
||||
u16 ssn = params->ssn;
|
||||
struct mt76_txq *mtxq;
|
||||
unsigned int link_id;
|
||||
int ret = 0;
|
||||
|
||||
if (!txq)
|
||||
@@ -1311,59 +1415,42 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta_link->wcid, tid,
|
||||
ssn, params->buf_size);
|
||||
ret = mt7996_mcu_add_rx_ba(dev, params, link, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, tid);
|
||||
ret = mt7996_mcu_add_rx_ba(dev, params, link, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, link,
|
||||
msta_link, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta_link->wcid.ampdu_state);
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, link,
|
||||
msta_link, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta_link->wcid.ampdu_state);
|
||||
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta_link->wcid.ampdu_state);
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, link,
|
||||
msta_link, false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (action == IEEE80211_AMPDU_TX_STOP_CONT)
|
||||
switch (params->action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
/* Since packets belonging to the same TID can be split over
|
||||
* multiple links, store the AMPDU state for reordering in the
|
||||
* primary link
|
||||
*/
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid,
|
||||
ssn, params->buf_size);
|
||||
ret = mt7996_mcu_add_rx_ba(dev, params, vif, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);
|
||||
ret = mt7996_mcu_add_rx_ba(dev, params, vif, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, vif, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, vif, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
ret = mt7996_mcu_add_tx_ba(dev, params, vif, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
@@ -1617,19 +1704,13 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7996_link_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
|
||||
static void mt7996_link_rate_ctrl_update(void *data,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_sta *msta = msta_link->sta;
|
||||
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
u32 *changed = data;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
msta_link = rcu_dereference(msta->link[msta->deflink_id]);
|
||||
if (!msta_link)
|
||||
goto out;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
msta_link->changed |= *changed;
|
||||
@@ -1637,8 +1718,6 @@ static void mt7996_link_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
|
||||
list_add_tail(&msta_link->rc_list, &dev->sta_rc_list);
|
||||
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
|
||||
@@ -1646,11 +1725,32 @@ static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
u32 changed)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct ieee80211_sta *sta = link_sta->sta;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
mt7996_link_rate_ctrl_update(&changed, sta);
|
||||
ieee80211_queue_work(hw, &dev->rc_work);
|
||||
rcu_read_lock();
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_sta->link_id]);
|
||||
if (msta_link) {
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
|
||||
mt7996_link_rate_ctrl_update(&changed, msta_link);
|
||||
ieee80211_queue_work(hw, &dev->rc_work);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void mt7996_sta_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
u32 *changed = data;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[msta->deflink_id]);
|
||||
if (msta_link)
|
||||
mt7996_link_rate_ctrl_update(&changed, msta_link);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1671,7 +1771,7 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
* - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
|
||||
* then multiple MCS setting (MCS 4,5,6) is not supported.
|
||||
*/
|
||||
ieee80211_iterate_stations_atomic(hw, mt7996_link_rate_ctrl_update,
|
||||
ieee80211_iterate_stations_atomic(hw, mt7996_sta_rate_ctrl_update,
|
||||
&changed);
|
||||
ieee80211_queue_work(hw, &dev->rc_work);
|
||||
|
||||
@@ -2072,9 +2172,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
struct mt76_vif_link *mlink;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]);
|
||||
if (!mlink)
|
||||
@@ -2087,12 +2185,9 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
|
||||
return -EIO;
|
||||
|
||||
link = (struct mt7996_vif_link *)mlink;
|
||||
phy = mt7996_vif_link_phy(link);
|
||||
if (!phy)
|
||||
return -ENODEV;
|
||||
|
||||
if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
|
||||
if (dev->hif2 &&
|
||||
((is_mt7996(&dev->mt76) && msta_link->wcid.phy_idx == MT_BAND2) ||
|
||||
(is_mt7992(&dev->mt76) && msta_link->wcid.phy_idx == MT_BAND1)))
|
||||
wed = &dev->mt76.mmio.wed_hif2;
|
||||
|
||||
if (!mtk_wed_device_active(wed))
|
||||
@@ -2105,7 +2200,11 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
path->mtk_wdma.queue = 0;
|
||||
path->mtk_wdma.wcid = msta_link->wcid.idx;
|
||||
|
||||
path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
|
||||
if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU) &&
|
||||
mtk_wed_is_amsdu_supported(wed))
|
||||
path->mtk_wdma.amsdu = msta_link->wcid.amsdu;
|
||||
else
|
||||
path->mtk_wdma.amsdu = 0;
|
||||
ctx->dev = NULL;
|
||||
|
||||
return 0;
|
||||
@@ -2121,6 +2220,19 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_reconfig_complete(struct ieee80211_hw *hw,
|
||||
enum ieee80211_reconfig_type reconfig_type)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
mt7996_for_each_phy(dev, phy)
|
||||
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
|
||||
MT7996_WATCHDOG_TIME);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7996_ops = {
|
||||
.add_chanctx = mt76_add_chanctx,
|
||||
.remove_chanctx = mt76_remove_chanctx,
|
||||
@@ -2179,4 +2291,5 @@ const struct ieee80211_ops mt7996_ops = {
|
||||
#endif
|
||||
.change_vif_links = mt7996_change_vif_links,
|
||||
.change_sta_links = mt7996_mac_sta_change_links,
|
||||
.reconfig_complete = mt7996_reconfig_complete,
|
||||
};
|
||||
|
||||
@@ -242,6 +242,30 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
|
||||
{
|
||||
mdev->mcu.timeout = 5 * HZ;
|
||||
|
||||
if (!(cmd & __MCU_CMD_FIELD_UNI))
|
||||
return;
|
||||
|
||||
switch (FIELD_GET(__MCU_CMD_FIELD_ID, cmd)) {
|
||||
case MCU_UNI_CMD_THERMAL:
|
||||
case MCU_UNI_CMD_TWT:
|
||||
case MCU_UNI_CMD_GET_MIB_INFO:
|
||||
case MCU_UNI_CMD_STA_REC_UPDATE:
|
||||
case MCU_UNI_CMD_BSS_INFO_UPDATE:
|
||||
mdev->mcu.timeout = 2 * HZ;
|
||||
return;
|
||||
case MCU_UNI_CMD_EFUSE_CTRL:
|
||||
mdev->mcu.timeout = 20 * HZ;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq)
|
||||
@@ -255,7 +279,7 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
u32 val;
|
||||
u8 seq;
|
||||
|
||||
mdev->mcu.timeout = 20 * HZ;
|
||||
mt7996_mcu_set_timeout(mdev, cmd);
|
||||
|
||||
seq = ++dev->mt76.mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
@@ -660,7 +684,7 @@ mt7996_mcu_wed_rro_event(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7996_mcu_wed_rro_event *event = (void *)skb->data;
|
||||
|
||||
if (!dev->has_rro)
|
||||
if (!mt7996_has_hwrro(dev))
|
||||
return;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7996_mcu_rxd) + 4);
|
||||
@@ -899,17 +923,28 @@ mt7996_mcu_bss_txcmd_tlv(struct sk_buff *skb, bool en)
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct mt76_vif_link *mlink)
|
||||
mt7996_mcu_bss_mld_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt7996_vif_link *link)
|
||||
{
|
||||
struct ieee80211_vif *vif = link_conf->vif;
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct bss_mld_tlv *mld;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_MLD, sizeof(*mld));
|
||||
|
||||
mld = (struct bss_mld_tlv *)tlv;
|
||||
mld->group_mld_id = 0xff;
|
||||
mld->own_mld_id = mlink->idx;
|
||||
mld->remap_idx = 0xff;
|
||||
mld->own_mld_id = link->mld_idx;
|
||||
mld->link_id = link_conf->link_id;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
mld->group_mld_id = mvif->mld_group_idx;
|
||||
mld->remap_idx = mvif->mld_remap_idx;
|
||||
memcpy(mld->mac_addr, vif->addr, ETH_ALEN);
|
||||
} else {
|
||||
mld->group_mld_id = 0xff;
|
||||
mld->remap_idx = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1108,6 +1143,8 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
|
||||
if (enable) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
mt7996_mcu_bss_rfch_tlv(skb, phy);
|
||||
mt7996_mcu_bss_bmc_tlv(skb, mlink, phy);
|
||||
mt7996_mcu_bss_ra_tlv(skb, phy);
|
||||
@@ -1118,7 +1155,8 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
mt7996_mcu_bss_he_tlv(skb, vif, link_conf, phy);
|
||||
|
||||
/* this tag is necessary no matter if the vif is MLD */
|
||||
mt7996_mcu_bss_mld_tlv(skb, mlink);
|
||||
link = container_of(mlink, struct mt7996_vif_link, mt76);
|
||||
mt7996_mcu_bss_mld_tlv(skb, link_conf, link);
|
||||
}
|
||||
|
||||
mt7996_mcu_bss_mbssid_tlv(skb, link_conf, enable);
|
||||
@@ -1149,9 +1187,8 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
static int
|
||||
mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx)
|
||||
struct mt76_wcid *wcid, bool enable, bool tx)
|
||||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
|
||||
struct sta_rec_ba_uni *ba;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
@@ -1170,7 +1207,7 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif,
|
||||
ba->ba_en = enable << params->tid;
|
||||
ba->amsdu = params->amsdu;
|
||||
ba->tid = params->tid;
|
||||
ba->ba_rdd_rro = !tx && enable && dev->has_rro;
|
||||
ba->ba_rdd_rro = !tx && enable && mt7996_has_hwrro(dev);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
@@ -1179,20 +1216,67 @@ mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif_link *mvif,
|
||||
/** starec & wtbl **/
|
||||
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, bool enable)
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
if (enable && !params->amsdu)
|
||||
msta_link->wcid.amsdu = false;
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
int ret = 0;
|
||||
|
||||
return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, true);
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (enable && !params->amsdu)
|
||||
msta_link->wcid.amsdu = false;
|
||||
|
||||
ret = mt7996_mcu_sta_ba(dev, &link->mt76, params,
|
||||
&msta_link->wcid, enable, true);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
struct mt7996_vif_link *link, bool enable)
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
return mt7996_mcu_sta_ba(dev, &link->mt76, params, enable, false);
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
int ret = 0;
|
||||
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
ret = mt7996_mcu_sta_ba(dev, &link->mt76, params,
|
||||
&msta_link->wcid, enable, false);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1753,19 +1837,6 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
||||
bf->mem_20m = bf->nrow < BF_MAT_ORDER ?
|
||||
matrix[bf->nrow][bf->ncol] : 0;
|
||||
}
|
||||
|
||||
switch (link_sta->bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
bf->mem_total = bf->mem_20m * 2;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
bf->mem_total = bf->mem_20m;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2265,13 +2336,10 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
mt7996_mcu_add_group(struct mt7996_dev *dev, struct mt7996_vif_link *link,
|
||||
struct mt76_wcid *wcid)
|
||||
{
|
||||
#define MT_STA_BSS_GROUP 1
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_sta *msta;
|
||||
struct {
|
||||
u8 __rsv1[4];
|
||||
|
||||
@@ -2286,13 +2354,10 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
.tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
.action = cpu_to_le32(MT_STA_BSS_GROUP),
|
||||
.val = cpu_to_le32(mvif->deflink.mt76.idx % 16),
|
||||
.val = cpu_to_le32(link->mt76.idx % 16),
|
||||
.wlan_idx = cpu_to_le16(wcid->idx),
|
||||
};
|
||||
|
||||
msta = sta ? (struct mt7996_sta *)sta->drv_priv : NULL;
|
||||
msta_link = msta ? &msta->deflink : &mvif->deflink.msta_link;
|
||||
req.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
@@ -2432,7 +2497,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt7996_mcu_add_group(dev, link_conf->vif, sta);
|
||||
ret = mt7996_mcu_add_group(dev, link, wcid);
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
@@ -2467,41 +2532,58 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
struct sta_rec_sec_uni *sec;
|
||||
struct sec_key_uni *sec_key;
|
||||
struct tlv *tlv;
|
||||
u8 cipher;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
|
||||
sec = (struct sta_rec_sec_uni *)tlv;
|
||||
sec->add = cmd;
|
||||
sec->add = 0;
|
||||
sec->n_cipher = 1;
|
||||
sec_key = &sec->key[0];
|
||||
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
|
||||
sec_key->key_id = key->keyidx;
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
struct sec_key_uni *sec_key;
|
||||
u8 cipher;
|
||||
if (cmd != SET_KEY)
|
||||
return 0;
|
||||
|
||||
cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
if (cipher == MCU_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
if (cipher == MCU_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sec_key = &sec->key[0];
|
||||
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
|
||||
sec_key->mgmt_prot = 0;
|
||||
sec_key->cipher_id = cipher;
|
||||
sec_key->cipher_len = sizeof(*sec_key);
|
||||
sec_key->key_id = key->keyidx;
|
||||
sec_key->key_len = key->keylen;
|
||||
sec_key->need_resp = 0;
|
||||
memcpy(sec_key->key, key->key, key->keylen);
|
||||
sec_key->mgmt_prot = 0;
|
||||
sec_key->cipher_id = cipher;
|
||||
sec_key->cipher_len = sizeof(*sec_key);
|
||||
sec_key->key_len = key->keylen;
|
||||
sec_key->need_resp = 0;
|
||||
memcpy(sec_key->key, key->key, key->keylen);
|
||||
|
||||
if (cipher == MCU_CIPHER_TKIP) {
|
||||
/* Rx/Tx MIC keys are swapped */
|
||||
memcpy(sec_key->key + 16, key->key + 24, 8);
|
||||
memcpy(sec_key->key + 24, key->key + 16, 8);
|
||||
}
|
||||
|
||||
sec->n_cipher = 1;
|
||||
} else {
|
||||
sec->n_cipher = 0;
|
||||
if (cipher == MCU_CIPHER_TKIP) {
|
||||
/* Rx/Tx MIC keys are swapped */
|
||||
memcpy(sec_key->key + 16, key->key + 24, 8);
|
||||
memcpy(sec_key->key + 24, key->key + 16, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sec_key->key_id != 6 && sec_key->key_id != 7)
|
||||
return 0;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
sec_key->bcn_mode = BP_SW_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2519,99 +2601,12 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
return PTR_ERR(skb);
|
||||
|
||||
ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
|
||||
}
|
||||
|
||||
static int mt7996_mcu_get_pn(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, u8 *pn)
|
||||
{
|
||||
#define TSC_TYPE_BIGTK_PN 2
|
||||
struct sta_rec_pn_info *pn_info;
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
int ret;
|
||||
|
||||
skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
|
||||
&msta_link->wcid);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
|
||||
pn_info = (struct sta_rec_pn_info *)tlv;
|
||||
|
||||
pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
|
||||
ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
|
||||
MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE),
|
||||
true, &rskb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
skb_pull(rskb, 4);
|
||||
|
||||
pn_info = (struct sta_rec_pn_info *)rskb->data;
|
||||
if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
|
||||
memcpy(pn, pn_info->pn, 6);
|
||||
|
||||
dev_kfree_skb(rskb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
u8 pn[6] = {};
|
||||
int len = sizeof(struct bss_req_hdr) +
|
||||
sizeof(struct mt7996_mcu_bcn_prot_tlv);
|
||||
int ret;
|
||||
|
||||
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, len);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT, sizeof(*bcn_prot));
|
||||
|
||||
bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
|
||||
|
||||
ret = mt7996_mcu_get_pn(dev, link, msta_link, pn);
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
pn[0]++;
|
||||
memcpy(bcn_prot->pn, pn, 6);
|
||||
bcn_prot->enable = BP_SW_MODE;
|
||||
memcpy(bcn_prot->key, key->key, WLAN_MAX_KEY_LEN);
|
||||
bcn_prot->key_id = key->keyidx;
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
@@ -2752,7 +2747,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev,
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
struct ieee80211_bss_conf *link_conf, bool enabled)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf);
|
||||
@@ -2763,7 +2758,6 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct tlv *tlv;
|
||||
struct bss_bcn_content_tlv *bcn;
|
||||
int len, extra_len = 0;
|
||||
bool enabled = link_conf->enable_beacon;
|
||||
|
||||
if (link_conf->nontransmitted)
|
||||
return 0;
|
||||
|
||||
@@ -351,17 +351,6 @@ enum {
|
||||
BP_HW_MODE,
|
||||
};
|
||||
|
||||
struct mt7996_mcu_bcn_prot_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 pn[6];
|
||||
u8 enable;
|
||||
u8 cipher_id;
|
||||
u8 key[WLAN_MAX_KEY_LEN];
|
||||
u8 key_id;
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct bss_ra_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -481,7 +470,8 @@ struct bss_mld_tlv {
|
||||
u8 own_mld_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 remap_idx;
|
||||
u8 __rsv[3];
|
||||
u8 link_id;
|
||||
u8 __rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_ht_uni {
|
||||
@@ -530,6 +520,9 @@ struct sec_key_uni {
|
||||
u8 key_len;
|
||||
u8 need_resp;
|
||||
u8 key[32];
|
||||
u8 pn[6];
|
||||
u8 bcn_mode;
|
||||
u8 _rsv;
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_sec_uni {
|
||||
|
||||
@@ -459,14 +459,15 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
struct pci_dev *pci_dev = pdev_ptr;
|
||||
u32 hif1_ofs = 0;
|
||||
u32 hif1_ofs;
|
||||
|
||||
if (!wed_enable)
|
||||
return 0;
|
||||
|
||||
dev->has_rro = true;
|
||||
dev->mt76.hwrro_mode = is_mt7996(&dev->mt76) ? MT76_HWRRO_V3
|
||||
: MT76_HWRRO_V3_1;
|
||||
|
||||
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
|
||||
hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;
|
||||
|
||||
if (hif2)
|
||||
wed = &dev->mt76.mmio.wed_hif2;
|
||||
@@ -490,11 +491,18 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_TXQ_RING_BASE(0) +
|
||||
MT7996_TXQ_BAND2 * MT_RING_SIZE;
|
||||
if (dev->has_rro) {
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
|
||||
} else {
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_BAND1_EXT) - 1;
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_MCU_WA_EXT * MT_RING_SIZE;
|
||||
}
|
||||
} else {
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
@@ -504,13 +512,13 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
|
||||
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
|
||||
wed->wlan.wpdma_rx[0] = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
|
||||
MT7996_RXQ_BAND0 * MT_RING_SIZE;
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_BAND2) +
|
||||
MT7996_RXQ_BAND2 * MT_RING_SIZE;
|
||||
|
||||
wed->wlan.id = MT7996_DEVICE_ID_2;
|
||||
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
|
||||
} else {
|
||||
wed->wlan.hw_rro = dev->has_rro; /* default on */
|
||||
wed->wlan.hw_rro = mt7996_has_hwrro(dev);
|
||||
wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
|
||||
wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
|
||||
wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
|
||||
@@ -525,9 +533,19 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
|
||||
MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
|
||||
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
|
||||
MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
|
||||
MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
|
||||
} else {
|
||||
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND1) +
|
||||
MT7996_RXQ_RRO_BAND1 * MT_RING_SIZE;
|
||||
wed->wlan.wpdma_rx[1] = wed->wlan.phy_base + hif1_ofs +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_BAND1) +
|
||||
MT7996_RXQ_BAND1 * MT_RING_SIZE;
|
||||
}
|
||||
|
||||
wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
|
||||
MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
|
||||
@@ -537,10 +555,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
|
||||
|
||||
wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
|
||||
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
|
||||
|
||||
wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
|
||||
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
|
||||
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
|
||||
} else {
|
||||
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND1) - 1;
|
||||
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND1) - 1;
|
||||
}
|
||||
|
||||
wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
|
||||
wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
|
||||
@@ -548,16 +570,27 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
|
||||
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
|
||||
wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
|
||||
if (dev->has_rro) {
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
if (mt7996_has_hwrro(dev)) {
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
|
||||
} else {
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base +
|
||||
MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
|
||||
}
|
||||
} else {
|
||||
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
|
||||
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
|
||||
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
|
||||
}
|
||||
dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
|
||||
|
||||
if (dev->hif2 && is_mt7992(&dev->mt76))
|
||||
wed->wlan.id = 0x7992;
|
||||
}
|
||||
|
||||
wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
|
||||
@@ -576,8 +609,10 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.reset_complete = mt76_wed_reset_complete;
|
||||
}
|
||||
|
||||
if (mtk_wed_device_attach(wed))
|
||||
if (mtk_wed_device_attach(wed)) {
|
||||
dev->mt76.hwrro_mode = MT76_HWRRO_OFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*irq = wed->irq;
|
||||
dev->mt76.dma_dev = wed->dev;
|
||||
@@ -690,12 +725,18 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
|
||||
dev->mt76.mmio.irqmask);
|
||||
if (intr1 & MT_INT_RX_TXFREE_EXT)
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
|
||||
|
||||
if (intr1 & MT_INT_RX_DONE_BAND2_EXT)
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND2]);
|
||||
|
||||
if (intr1 & MT_INT_RX_TXFREE_BAND1_EXT)
|
||||
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1_WA]);
|
||||
}
|
||||
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
mtk_wed_device_irq_set_mask(wed, 0);
|
||||
intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
|
||||
intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
|
||||
intr |= (intr1 & ~MT_INT_TX_RX_DONE_EXT);
|
||||
} else {
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
@@ -781,6 +822,8 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
.rx_skb = mt7996_queue_rx_skb,
|
||||
.rx_check = mt7996_rx_check,
|
||||
.rx_poll_complete = mt7996_rx_poll_complete,
|
||||
.rx_rro_ind_process = mt7996_rro_rx_process,
|
||||
.rx_rro_add_msdu_page = mt7996_rro_msdu_page_add,
|
||||
.update_survey = mt7996_update_channel,
|
||||
.set_channel = mt7996_set_channel,
|
||||
.vif_link_add = mt7996_vif_link_add,
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
#define MT7996_CRIT_TEMP 110
|
||||
#define MT7996_MAX_TEMP 120
|
||||
|
||||
#define MT7996_MAX_HIF_RXD_IN_PG 5
|
||||
#define MT7996_RRO_MSDU_PG_HASH_SIZE 127
|
||||
#define MT7996_RRO_MAX_SESSION 1024
|
||||
#define MT7996_RRO_WINDOW_MAX_LEN 1024
|
||||
#define MT7996_RRO_ADDR_ELEM_LEN 128
|
||||
@@ -128,6 +130,10 @@
|
||||
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||
|
||||
/* RRO 3.1 */
|
||||
#define MT7996_RRO_MSDU_PG_CR_CNT 8
|
||||
#define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
|
||||
|
||||
struct mt7996_vif;
|
||||
struct mt7996_sta;
|
||||
struct mt7996_dfs_pulse;
|
||||
@@ -178,7 +184,7 @@ enum mt7996_rxq_id {
|
||||
MT7996_RXQ_BAND1 = 5, /* for mt7992 */
|
||||
MT7996_RXQ_BAND2 = 5,
|
||||
MT7996_RXQ_RRO_BAND0 = 8,
|
||||
MT7996_RXQ_RRO_BAND1 = 8,/* unused */
|
||||
MT7996_RXQ_RRO_BAND1 = 9,
|
||||
MT7996_RXQ_RRO_BAND2 = 6,
|
||||
MT7996_RXQ_MSDU_PG_BAND0 = 10,
|
||||
MT7996_RXQ_MSDU_PG_BAND1 = 11,
|
||||
@@ -187,6 +193,7 @@ enum mt7996_rxq_id {
|
||||
MT7996_RXQ_TXFREE1 = 9,
|
||||
MT7996_RXQ_TXFREE2 = 7,
|
||||
MT7996_RXQ_RRO_IND = 0,
|
||||
MT7996_RXQ_RRO_RXDMAD_C = 0,
|
||||
MT7990_RXQ_TXFREE0 = 6,
|
||||
MT7990_RXQ_TXFREE1 = 7,
|
||||
};
|
||||
@@ -248,11 +255,16 @@ struct mt7996_vif_link {
|
||||
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
struct cfg80211_bitrate_mask bitrate_mask;
|
||||
|
||||
u8 mld_idx;
|
||||
};
|
||||
|
||||
struct mt7996_vif {
|
||||
struct mt7996_vif_link deflink; /* must be first */
|
||||
struct mt76_vif_data mt76;
|
||||
|
||||
u8 mld_group_idx;
|
||||
u8 mld_remap_idx;
|
||||
};
|
||||
|
||||
/* crash-dump */
|
||||
@@ -270,15 +282,17 @@ struct mt7996_hif {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
int irq;
|
||||
|
||||
enum pci_bus_speed speed;
|
||||
enum pcie_link_width width;
|
||||
};
|
||||
|
||||
#define WED_RRO_ADDR_SIGNATURE_MASK GENMASK(31, 24)
|
||||
#define WED_RRO_ADDR_COUNT_MASK GENMASK(14, 4)
|
||||
#define WED_RRO_ADDR_HEAD_HIGH_MASK GENMASK(3, 0)
|
||||
struct mt7996_wed_rro_addr {
|
||||
u32 head_low;
|
||||
u32 head_high : 4;
|
||||
u32 count: 11;
|
||||
u32 oor: 1;
|
||||
u32 rsv : 8;
|
||||
u32 signature : 8;
|
||||
__le32 head_low;
|
||||
__le32 data;
|
||||
};
|
||||
|
||||
struct mt7996_wed_rro_session_id {
|
||||
@@ -286,6 +300,44 @@ struct mt7996_wed_rro_session_id {
|
||||
u16 id;
|
||||
};
|
||||
|
||||
struct mt7996_msdu_page {
|
||||
struct list_head list;
|
||||
|
||||
struct mt76_queue *q;
|
||||
dma_addr_t dma_addr;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
/* data1 */
|
||||
#define RRO_HIF_DATA1_LS_MASK BIT(30)
|
||||
#define RRO_HIF_DATA1_SDL_MASK GENMASK(29, 16)
|
||||
/* data4 */
|
||||
#define RRO_HIF_DATA4_RX_TOKEN_ID_MASK GENMASK(15, 0)
|
||||
struct mt7996_rro_hif {
|
||||
__le32 data0;
|
||||
__le32 data1;
|
||||
__le32 data2;
|
||||
__le32 data3;
|
||||
__le32 data4;
|
||||
__le32 data5;
|
||||
};
|
||||
|
||||
#define MSDU_PAGE_INFO_OWNER_MASK BIT(31)
|
||||
#define MSDU_PAGE_INFO_PG_HIGH_MASK GENMASK(3, 0)
|
||||
struct mt7996_msdu_page_info {
|
||||
struct mt7996_rro_hif rxd[MT7996_MAX_HIF_RXD_IN_PG];
|
||||
__le32 pg_low;
|
||||
__le32 data;
|
||||
};
|
||||
|
||||
#define MT7996_MAX_RRO_RRS_RING 4
|
||||
struct mt7996_rro_queue_regs_emi {
|
||||
struct {
|
||||
__le16 idx;
|
||||
__le16 rsv;
|
||||
} ring[MT7996_MAX_RRO_RRS_RING];
|
||||
};
|
||||
|
||||
struct mt7996_phy {
|
||||
struct mt76_phy *mt76;
|
||||
struct mt7996_dev *dev;
|
||||
@@ -337,6 +389,9 @@ struct mt7996_dev {
|
||||
u32 q_int_mask[MT7996_MAX_QUEUE];
|
||||
u32 q_wfdma_mask;
|
||||
|
||||
u64 mld_idx_mask;
|
||||
u64 mld_remap_idx_mask;
|
||||
|
||||
const struct mt76_bus_ops *bus_ops;
|
||||
struct mt7996_phy phy;
|
||||
|
||||
@@ -377,7 +432,6 @@ struct mt7996_dev {
|
||||
|
||||
bool flash_mode:1;
|
||||
bool has_eht:1;
|
||||
bool has_rro:1;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
@@ -392,10 +446,25 @@ struct mt7996_dev {
|
||||
void *ptr;
|
||||
dma_addr_t phy_addr;
|
||||
} session;
|
||||
struct {
|
||||
void *ptr;
|
||||
dma_addr_t phy_addr;
|
||||
} msdu_pg[MT7996_RRO_MSDU_PG_CR_CNT];
|
||||
struct {
|
||||
struct mt7996_rro_queue_regs_emi *ptr;
|
||||
dma_addr_t phy_addr;
|
||||
} emi_rings_cpu;
|
||||
struct {
|
||||
struct mt7996_rro_queue_regs_emi *ptr;
|
||||
dma_addr_t phy_addr;
|
||||
} emi_rings_dma;
|
||||
|
||||
struct work_struct work;
|
||||
struct list_head poll_list;
|
||||
spinlock_t lock;
|
||||
|
||||
struct list_head page_cache;
|
||||
struct list_head page_map[MT7996_RRO_MSDU_PG_HASH_SIZE];
|
||||
} wed_rro;
|
||||
|
||||
bool ibf;
|
||||
@@ -552,6 +621,7 @@ extern struct pci_driver mt7996_hif_driver;
|
||||
|
||||
struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
void __iomem *mem_base, u32 device_id);
|
||||
void mt7996_rro_hw_init(struct mt7996_dev *dev);
|
||||
void mt7996_wfsys_reset(struct mt7996_dev *dev);
|
||||
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
|
||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
|
||||
@@ -604,16 +674,15 @@ int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, bool enable);
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
struct mt7996_vif_link *link, bool enable);
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
|
||||
struct mt76_vif_link *mlink,
|
||||
struct cfg80211_he_bss_color *he_bss_color);
|
||||
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
struct ieee80211_bss_conf *link_conf, bool enabled);
|
||||
int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt7996_vif_link *link, u32 changed);
|
||||
@@ -669,6 +738,11 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
|
||||
int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
|
||||
int mt7996_mcu_set_sniffer_mode(struct mt7996_phy *phy, bool enabled);
|
||||
|
||||
static inline bool mt7996_has_hwrro(struct mt7996_dev *dev)
|
||||
{
|
||||
return dev->mt76.hwrro_mode != MT76_HWRRO_OFF;
|
||||
}
|
||||
|
||||
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
|
||||
{
|
||||
return min(MT7996_MAX_INTERFACES * (1 + mt7996_band_valid(dev, MT_BAND1) +
|
||||
@@ -743,6 +817,8 @@ 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_add_twt_setup(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_twt_setup *twt);
|
||||
@@ -753,6 +829,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev);
|
||||
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
void mt7996_rro_msdu_page_map_free(struct mt7996_dev *dev);
|
||||
int mt7996_rro_msdu_page_add(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
dma_addr_t dma_addr, void *data);
|
||||
void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data);
|
||||
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7996_stats_work(struct work_struct *work);
|
||||
int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
|
||||
@@ -787,8 +867,6 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
|
||||
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
int mt7996_dma_rro_init(struct mt7996_dev *dev);
|
||||
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -87,6 +87,7 @@ static int mt7996_pci_hif2_probe(struct pci_dev *pdev)
|
||||
hif->dev = &pdev->dev;
|
||||
hif->regs = pcim_iomap_table(pdev)[0];
|
||||
hif->irq = pdev->irq;
|
||||
pcie_bandwidth_available(pdev, NULL, &hif->speed, &hif->width);
|
||||
spin_lock_bh(&hif_lock);
|
||||
list_add(&hif->list, &hif_list);
|
||||
spin_unlock_bh(&hif_lock);
|
||||
@@ -137,6 +138,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
|
||||
mdev = &dev->mt76;
|
||||
mt7996_wfsys_reset(dev);
|
||||
hif2 = mt7996_pci_init_hif2(pdev);
|
||||
dev->hif2 = hif2;
|
||||
|
||||
ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
|
||||
if (ret < 0)
|
||||
@@ -161,7 +163,6 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
if (hif2) {
|
||||
hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
|
||||
dev->hif2 = hif2;
|
||||
|
||||
ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -88,6 +88,8 @@ enum offs_rev {
|
||||
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
|
||||
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
|
||||
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
|
||||
|
||||
#define MT_RRO_ADDR_ARRAY_BASE0 MT_RRO_TOP(0x30)
|
||||
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
|
||||
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
|
||||
|
||||
@@ -108,6 +110,19 @@ enum offs_rev {
|
||||
|
||||
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
|
||||
|
||||
#define MT_RRO_3_0_EMU_CONF MT_RRO_TOP(0x600)
|
||||
#define MT_RRO_3_0_EMU_CONF_EN_MASK BIT(11)
|
||||
|
||||
#define MT_RRO_3_1_GLOBAL_CONFIG MT_RRO_TOP(0x604)
|
||||
#define MT_RRO_3_1_GLOBAL_CONFIG_RXDMAD_SEL BIT(6)
|
||||
#define MT_RRO_3_1_GLOBAL_CONFIG_RX_CIDX_RD_EN BIT(3)
|
||||
#define MT_RRO_3_1_GLOBAL_CONFIG_RX_DIDX_WR_EN BIT(2)
|
||||
#define MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN BIT(0)
|
||||
|
||||
#define MT_RRO_MSDU_PG_SEG_ADDR0 MT_RRO_TOP(0x620)
|
||||
#define MT_RRO_RX_RING_AP_CIDX_ADDR MT_RRO_TOP(0x6f0)
|
||||
#define MT_RRO_RX_RING_AP_DIDX_ADDR MT_RRO_TOP(0x6f4)
|
||||
|
||||
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
|
||||
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
|
||||
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
|
||||
@@ -412,7 +427,9 @@ enum offs_rev {
|
||||
|
||||
#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
|
||||
#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
|
||||
#define MT_WFDMA0_RX_INT_SEL_RING5 BIT(5)
|
||||
#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)
|
||||
#define MT_WFDMA0_RX_INT_SEL_RING9 BIT(9)
|
||||
|
||||
#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
|
||||
|
||||
@@ -430,6 +447,7 @@ enum offs_rev {
|
||||
#define MT_WFDMA0_PAUSE_RX_Q_RRO_TH MT_WFDMA0(0x27c)
|
||||
|
||||
#define WF_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
|
||||
#define WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK GENMASK(27, 24)
|
||||
#define WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD BIT(18)
|
||||
#define WF_WFDMA0_GLO_CFG_EXT0_WED_MERGE_MODE BIT(14)
|
||||
|
||||
@@ -451,6 +469,8 @@ enum offs_rev {
|
||||
|
||||
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
|
||||
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
|
||||
#define MT_WFDMA_HOST_CONFIG_BAND0_PCIE1 BIT(20)
|
||||
#define MT_WFDMA_HOST_CONFIG_BAND1_PCIE1 BIT(21)
|
||||
#define MT_WFDMA_HOST_CONFIG_BAND2_PCIE1 BIT(22)
|
||||
|
||||
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
|
||||
@@ -459,6 +479,9 @@ enum offs_rev {
|
||||
#define MT_WFDMA_AXI_R2A_CTRL MT_WFDMA_EXT_CSR(0x500)
|
||||
#define MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK GENMASK(4, 0)
|
||||
|
||||
#define MT_WFDMA_AXI_R2A_CTRL2 MT_WFDMA_EXT_CSR(0x508)
|
||||
#define MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK GENMASK(31, 28)
|
||||
|
||||
#define MT_PCIE_RECOG_ID 0xd7090
|
||||
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
|
||||
#define MT_PCIE_RECOG_ID_SEM BIT(31)
|
||||
@@ -492,6 +515,8 @@ enum offs_rev {
|
||||
#define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
|
||||
#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
|
||||
|
||||
#define MT_RXQ_RRO_AP_RING_BASE MT_RRO_TOP(0x650)
|
||||
|
||||
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
|
||||
MT_MCUQ_ID(q) * 0x4)
|
||||
#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
|
||||
@@ -514,7 +539,9 @@ enum offs_rev {
|
||||
#define MT_INT_RX_DONE_WA_EXT BIT(3) /* for mt7992 */
|
||||
#define MT_INT_RX_DONE_WA_TRI BIT(3)
|
||||
#define MT_INT_RX_TXFREE_MAIN BIT(17)
|
||||
#define MT_INT_RX_TXFREE_BAND1 BIT(15)
|
||||
#define MT_INT_RX_TXFREE_TRI BIT(15)
|
||||
#define MT_INT_RX_TXFREE_BAND1_EXT BIT(19) /* for mt7992 two PCIE*/
|
||||
#define MT_INT_RX_TXFREE_BAND0_MT7990 BIT(14)
|
||||
#define MT_INT_RX_TXFREE_BAND1_MT7990 BIT(15)
|
||||
#define MT_INT_RX_DONE_BAND2_EXT BIT(23)
|
||||
@@ -522,9 +549,10 @@ enum offs_rev {
|
||||
#define MT_INT_MCU_CMD BIT(29)
|
||||
|
||||
#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
|
||||
#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
|
||||
#define MT_INT_RX_DONE_RRO_BAND1 BIT(17)
|
||||
#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
|
||||
#define MT_INT_RX_DONE_RRO_IND BIT(11)
|
||||
#define MT_INT_RX_DONE_RRO_RXDMAD_C BIT(11)
|
||||
#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
|
||||
#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
|
||||
#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
|
||||
@@ -552,6 +580,8 @@ enum offs_rev {
|
||||
#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
|
||||
MT_INT_RX(MT_RXQ_RRO_BAND1) | \
|
||||
MT_INT_RX(MT_RXQ_RRO_BAND2) | \
|
||||
MT_INT_RX(MT_RXQ_RRO_IND) | \
|
||||
MT_INT_RX(MT_RXQ_RRO_RXDMAD_C) | \
|
||||
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
|
||||
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
|
||||
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
|
||||
|
||||
@@ -16,11 +16,13 @@ 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)
|
||||
if (dev->scan.chan && phy->main_chandef.chan &&
|
||||
!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
mt76_set_channel(phy, &phy->main_chandef, false);
|
||||
mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
|
||||
memset(&dev->scan, 0, sizeof(dev->scan));
|
||||
ieee80211_scan_completed(phy->hw, &info);
|
||||
if (!test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
ieee80211_scan_completed(phy->hw, &info);
|
||||
}
|
||||
|
||||
void mt76_abort_scan(struct mt76_dev *dev)
|
||||
@@ -28,6 +30,7 @@ void mt76_abort_scan(struct mt76_dev *dev)
|
||||
cancel_delayed_work_sync(&dev->scan_work);
|
||||
mt76_scan_complete(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_abort_scan);
|
||||
|
||||
static void
|
||||
mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
|
||||
@@ -112,9 +115,6 @@ void mt76_scan_work(struct work_struct *work)
|
||||
local_bh_enable();
|
||||
|
||||
out:
|
||||
if (!duration)
|
||||
return;
|
||||
|
||||
if (dev->scan.chan)
|
||||
duration = max_t(int, duration,
|
||||
msecs_to_jiffies(req->duration +
|
||||
@@ -139,7 +139,8 @@ int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (dev->scan.req || phy->roc_vif) {
|
||||
if (dev->scan.req || phy->roc_vif ||
|
||||
test_bit(MT76_MCU_RESET, &dev->phy.state)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -618,7 +618,8 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
(!ieee80211_is_bufferable_mmpdu(skb) ||
|
||||
ieee80211_is_deauth(hdr->frame_control)))
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
head == &wcid->tx_offchannel))
|
||||
qid = MT_TXQ_PSD;
|
||||
|
||||
q = phy->q_tx[qid];
|
||||
|
||||
@@ -118,7 +118,7 @@ int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
|
||||
case MT76_WED_Q_TXFREE:
|
||||
/* WED txfree queue needs ring to be initialized before setup */
|
||||
q->flags = 0;
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
mt76_dma_queue_reset(dev, q, true);
|
||||
mt76_dma_rx_fill(dev, q, false);
|
||||
|
||||
ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
|
||||
@@ -133,21 +133,21 @@ int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
|
||||
break;
|
||||
case MT76_WED_RRO_Q_DATA:
|
||||
q->flags &= ~MT_QFLAG_WED;
|
||||
__mt76_dma_queue_reset(dev, q, false);
|
||||
mt76_dma_queue_reset(dev, q, false);
|
||||
mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
|
||||
q->head = q->ndesc - 1;
|
||||
q->queued = q->head;
|
||||
break;
|
||||
case MT76_WED_RRO_Q_MSDU_PG:
|
||||
q->flags &= ~MT_QFLAG_WED;
|
||||
__mt76_dma_queue_reset(dev, q, false);
|
||||
mt76_dma_queue_reset(dev, q, false);
|
||||
mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
|
||||
q->head = q->ndesc - 1;
|
||||
q->queued = q->head;
|
||||
break;
|
||||
case MT76_WED_RRO_Q_IND:
|
||||
q->flags &= ~MT_QFLAG_WED;
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
mt76_dma_queue_reset(dev, q, true);
|
||||
mt76_dma_rx_fill(dev, q, false);
|
||||
mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user