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:
Johannes Berg
2025-09-19 11:23:24 +02:00
46 changed files with 2325 additions and 935 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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;

View File

@@ -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 },

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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,

View File

@@ -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 },
{ },
};

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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;