diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76')
106 files changed, 13723 insertions, 9093 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 79ab850a45a2..c78ae4b89761 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -34,4 +34,4 @@ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT7603E) += mt7603/ obj-$(CONFIG_MT7615_COMMON) += mt7615/ obj-$(CONFIG_MT7915E) += mt7915/ -obj-$(CONFIG_MT7921E) += mt7921/ +obj-$(CONFIG_MT7921_COMMON) += mt7921/ diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 72622220051b..10cbd9e560e7 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -162,15 +162,15 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) if (!sta) return; - if (!status->aggr && !(status->flag & RX_FLAG_8023)) { - mt76_rx_aggr_check_ctl(skb, frames); + if (!status->aggr) { + if (!(status->flag & RX_FLAG_8023)) + mt76_rx_aggr_check_ctl(skb, frames); return; } /* not part of a BA session */ ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK; - if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && - ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) + if (ackp == IEEE80211_QOS_CTL_ACK_POLICY_NOACK) return; tid = rcu_dereference(wcid->aggr[tidno]); diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index b8bcf22a07fd..47e9911ee9fe 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -82,7 +82,7 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data) queued = mt76_is_usb(dev) ? q->ndesc - q->queued : q->queued; seq_printf(s, " %9d | %9d | %9d | %9d |\n", - i, q->queued, q->head, q->tail); + i, queued, q->head, q->tail); } return 0; diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 5e1c1506a4c6..7378c4d1e156 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -7,6 +7,37 @@ #include "mt76.h" #include "dma.h" +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) + +#define Q_READ(_dev, _q, _field) ({ \ + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ + u32 _val; \ + if ((_q)->flags & MT_QFLAG_WED) \ + _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \ + ((_q)->wed_regs + \ + _offset)); \ + else \ + _val = readl(&(_q)->regs->_field); \ + _val; \ +}) + +#define Q_WRITE(_dev, _q, _field, _val) do { \ + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ + if ((_q)->flags & MT_QFLAG_WED) \ + mtk_wed_device_reg_write(&(_dev)->mmio.wed, \ + ((_q)->wed_regs + _offset), \ + _val); \ + else \ + writel(_val, &(_q)->regs->_field); \ +} while (0) + +#else + +#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field) +#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field) + +#endif + static struct mt76_txwi_cache * mt76_alloc_txwi(struct mt76_dev *dev) { @@ -16,11 +47,11 @@ mt76_alloc_txwi(struct mt76_dev *dev) int size; size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t)); - txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC); + txwi = kzalloc(size, GFP_ATOMIC); if (!txwi) return NULL; - addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size, + addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size, DMA_TO_DEVICE); t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size); t->dma_addr = addr; @@ -73,18 +104,20 @@ mt76_free_pending_txwi(struct mt76_dev *dev) struct mt76_txwi_cache *t; local_bh_disable(); - while ((t = __mt76_get_txwi(dev)) != NULL) - dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size, + while ((t = __mt76_get_txwi(dev)) != NULL) { + dma_unmap_single(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); + kfree(mt76_get_txwi_ptr(dev, t)); + } local_bh_enable(); } static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { - writel(q->desc_dma, &q->regs->desc_base); - writel(q->ndesc, &q->regs->ring_size); - q->head = readl(&q->regs->dma_idx); + Q_WRITE(dev, q, desc_base, q->desc_dma); + Q_WRITE(dev, q, ring_size, q->ndesc); + q->head = Q_READ(dev, q, dma_idx); q->tail = q->head; } @@ -93,49 +126,19 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) { int i; - if (!q) + if (!q || !q->ndesc) return; /* clear descriptors */ for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - writel(0, &q->regs->cpu_idx); - writel(0, &q->regs->dma_idx); + Q_WRITE(dev, q, cpu_idx, 0); + Q_WRITE(dev, q, dma_idx, 0); mt76_dma_sync_idx(dev, q); } static int -mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, - int idx, int n_desc, int bufsize, - u32 ring_base) -{ - int size; - - spin_lock_init(&q->lock); - spin_lock_init(&q->cleanup_lock); - - q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; - q->ndesc = n_desc; - q->buf_size = bufsize; - q->hw_idx = idx; - - size = q->ndesc * sizeof(struct mt76_desc); - q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL); - if (!q->desc) - return -ENOMEM; - - size = q->ndesc * sizeof(*q->entry); - q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); - if (!q->entry) - return -ENOMEM; - - mt76_dma_queue_reset(dev, q); - - return 0; -} - -static int mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, int nbufs, u32 info, struct sk_buff *skb, void *txwi) @@ -203,11 +206,11 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, struct mt76_queue_entry *e = &q->entry[idx]; if (!e->skip_buf0) - dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0], + dma_unmap_single(dev->dma_dev, e->dma_addr[0], e->dma_len[0], DMA_TO_DEVICE); if (!e->skip_buf1) - dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1], + dma_unmap_single(dev->dma_dev, e->dma_addr[1], e->dma_len[1], DMA_TO_DEVICE); if (e->txwi == DMA_DUMMY_DATA) @@ -224,7 +227,7 @@ static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) { wmb(); - writel(q->head, &q->regs->cpu_idx); + Q_WRITE(dev, q, cpu_idx, q->head); } static void @@ -233,14 +236,14 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) struct mt76_queue_entry entry; int last; - if (!q) + if (!q || !q->ndesc) return; spin_lock_bh(&q->cleanup_lock); if (flush) last = -1; else - last = readl(&q->regs->dma_idx); + last = Q_READ(dev, q, dma_idx); while (q->queued > 0 && q->tail != last) { mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry); @@ -252,8 +255,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) } if (!flush && q->tail == last) - last = readl(&q->regs->dma_idx); - + last = Q_READ(dev, q, dma_idx); } spin_unlock_bh(&q->cleanup_lock); @@ -288,7 +290,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, if (info) *info = le32_to_cpu(desc->info); - dma_unmap_single(dev->dev, buf_addr, buf_len, DMA_FROM_DEVICE); + dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE); e->buf = NULL; return buf; @@ -325,9 +327,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, if (q->queued + 1 >= q->ndesc - 1) goto error; - addr = dma_map_single(dev->dev, skb->data, skb->len, + addr = dma_map_single(dev->dma_dev, skb->data, skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto error; buf.addr = addr; @@ -347,8 +349,8 @@ error: static int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta) + enum mt76_txq_id qid, struct sk_buff *skb, + struct mt76_wcid *wcid, struct ieee80211_sta *sta) { struct ieee80211_tx_status status = { .sta = sta, @@ -374,8 +376,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, mt76_insert_hdr_pad(skb); len = skb_headlen(skb); - addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + addr = dma_map_single(dev->dma_dev, skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto free; tx_info.buf[n].addr = t->dma_addr; @@ -387,9 +389,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, if (n == ARRAY_SIZE(tx_info.buf)) goto unmap; - addr = dma_map_single(dev->dev, iter->data, iter->len, + addr = dma_map_single(dev->dma_dev, iter->data, iter->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto unmap; tx_info.buf[n].addr = addr; @@ -402,10 +404,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, goto unmap; } - dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size, + dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); - ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info); - dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size, + ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info); + dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); if (ret < 0) goto unmap; @@ -415,7 +417,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, unmap: for (n--; n > 0; n--) - dma_unmap_single(dev->dev, tx_info.buf[n].addr, + dma_unmap_single(dev->dma_dev, tx_info.buf[n].addr, tx_info.buf[n].len, DMA_TO_DEVICE); free: @@ -448,6 +450,9 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) int len = SKB_WITH_OVERHEAD(q->buf_size); int offset = q->buf_offset; + if (!q->ndesc) + return 0; + spin_lock_bh(&q->lock); while (q->queued < q->ndesc - 1) { @@ -457,14 +462,15 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) if (!buf) break; - addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) { + addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { skb_free_frag(buf); break; } qbuf.addr = addr + offset; qbuf.len = len - offset; + qbuf.skip_unmap = false; mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, NULL); frames++; } @@ -477,6 +483,85 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) return frames; } +static int +mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mmio.wed; + int ret, type, ring; + u8 flags = q->flags; + + if (!mtk_wed_device_active(wed)) + q->flags &= ~MT_QFLAG_WED; + + if (!(q->flags & MT_QFLAG_WED)) + return 0; + + type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags); + ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags); + + switch (type) { + case MT76_WED_Q_TX: + ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs); + if (!ret) + q->wed_regs = wed->tx_ring[ring].reg_base; + break; + case MT76_WED_Q_TXFREE: + /* WED txfree queue needs ring to be initialized before setup */ + q->flags = 0; + mt76_dma_queue_reset(dev, q); + mt76_dma_rx_fill(dev, q); + q->flags = flags; + + ret = mtk_wed_device_txfree_ring_setup(wed, q->regs); + if (!ret) + q->wed_regs = wed->txfree_ring.reg_base; + break; + default: + ret = -EINVAL; + } + + return ret; +#else + return 0; +#endif +} + +static int +mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, + int idx, int n_desc, int bufsize, + u32 ring_base) +{ + int ret, size; + + spin_lock_init(&q->lock); + spin_lock_init(&q->cleanup_lock); + + q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; + q->ndesc = n_desc; + q->buf_size = bufsize; + q->hw_idx = idx; + + size = q->ndesc * sizeof(struct mt76_desc); + q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL); + if (!q->desc) + return -ENOMEM; + + size = q->ndesc * sizeof(*q->entry); + q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); + if (!q->entry) + return -ENOMEM; + + ret = mt76_dma_wed_setup(dev, q); + if (ret) + return ret; + + if (q->flags != MT_WED_Q_TXFREE) + mt76_dma_queue_reset(dev, q); + + return 0; +} + static void mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) { @@ -484,6 +569,9 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) void *buf; bool more; + if (!q->ndesc) + return; + spin_lock_bh(&q->lock); do { buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more); @@ -508,6 +596,9 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) struct mt76_queue *q = &dev->q_rx[qid]; int i; + if (!q->ndesc) + return; + for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); @@ -552,14 +643,29 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, static int mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) { - int len, data_len, done = 0; + int len, data_len, done = 0, dma_idx; struct sk_buff *skb; unsigned char *data; + bool check_ddone = false; bool more; + if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) && + q->flags == MT_WED_Q_TXFREE) { + dma_idx = Q_READ(dev, q, dma_idx); + check_ddone = true; + } + while (done < budget) { u32 info; + if (check_ddone) { + if (q->tail == dma_idx) + dma_idx = Q_READ(dev, q, dma_idx); + + if (q->tail == dma_idx) + break; + } + data = mt76_dma_dequeue(dev, q, false, &len, &info, &more); if (!data) break; @@ -572,9 +678,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) if (data_len < len + q->buf_offset) { dev_kfree_skb(q->rx_head); q->rx_head = NULL; - - skb_free_frag(data); - continue; + goto free_frag; } if (q->rx_head) { @@ -582,17 +686,17 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) continue; } + if (!more && dev->drv->rx_check && + !(dev->drv->rx_check(dev, data, len))) + goto free_frag; + skb = build_skb(data, q->buf_size); - if (!skb) { - skb_free_frag(data); - continue; - } + if (!skb) + goto free_frag; + skb_reserve(skb, q->buf_offset); - if (q == &dev->q_rx[MT_RXQ_MCU]) { - u32 *rxfce = (u32 *)skb->cb; - *rxfce = info; - } + *(u32 *)skb->cb = info; __skb_put(skb, len); done++; @@ -603,6 +707,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) } dev->drv->rx_skb(dev, q - dev->q_rx, skb); + continue; + +free_frag: + skb_free_frag(data); } mt76_dma_rx_fill(dev, q); @@ -647,7 +755,7 @@ mt76_dma_init(struct mt76_dev *dev, dev->napi_dev.threaded = 1; mt76_for_each_q_rx(dev, i) { - netif_napi_add(&dev->napi_dev, &dev->napi[i], poll, 64); + netif_napi_add(&dev->napi_dev, &dev->napi[i], poll); mt76_dma_rx_fill(dev, &dev->q_rx[i]); napi_enable(&dev->napi[i]); } @@ -680,10 +788,15 @@ void mt76_dma_cleanup(struct mt76_dev *dev) mt76_worker_disable(&dev->tx_worker); netif_napi_del(&dev->tx_napi); - for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { - mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true); - if (dev->phy2) - mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true); + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { + struct mt76_phy *phy = dev->phys[i]; + int j; + + if (!phy) + continue; + + for (j = 0; j < ARRAY_SIZE(phy->q_tx); j++) + mt76_dma_tx_cleanup(dev, phy->q_tx[j], true); } for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++) @@ -695,5 +808,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev) } mt76_free_pending_txwi(dev); + + if (mtk_wed_device_active(&dev->mmio.wed)) + mtk_wed_device_detach(&dev->mmio.wed); } EXPORT_SYMBOL_GPL(mt76_dma_cleanup); diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 2d58aa31db93..9bc8758573fc 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -65,6 +65,8 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) offset = be32_to_cpup(list); ret = mtd_read(mtd, offset, len, &retlen, eep); put_mtd_device(mtd); + if (mtd_is_bitflip(ret)) + ret = 0; if (ret) { dev_err(dev->dev, "reading EEPROM from mtd %s failed: %i\n", part, ret); @@ -160,10 +162,13 @@ mt76_find_power_limits_node(struct mt76_dev *dev) } if (mt76_string_prop_find(country, dev->alpha2) || - mt76_string_prop_find(regd, region_name)) + mt76_string_prop_find(regd, region_name)) { + of_node_put(np); return cur; + } } + of_node_put(np); return fallback; } diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 62807dc311c1..6de13d641438 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -178,14 +178,19 @@ static const struct cfg80211_sar_freq_ranges mt76_sar_freq_ranges[] = { { .start_freq = 5350, .end_freq = 5470, }, { .start_freq = 5470, .end_freq = 5725, }, { .start_freq = 5725, .end_freq = 5950, }, + { .start_freq = 5945, .end_freq = 6165, }, + { .start_freq = 6165, .end_freq = 6405, }, + { .start_freq = 6405, .end_freq = 6525, }, + { .start_freq = 6525, .end_freq = 6705, }, + { .start_freq = 6705, .end_freq = 6865, }, + { .start_freq = 6865, .end_freq = 7125, }, }; -const struct cfg80211_sar_capa mt76_sar_capa = { +static const struct cfg80211_sar_capa mt76_sar_capa = { .type = NL80211_SAR_TYPE_POWER, .num_freq_ranges = ARRAY_SIZE(mt76_sar_freq_ranges), .freq_ranges = &mt76_sar_freq_ranges[0], }; -EXPORT_SYMBOL_GPL(mt76_sar_capa); static int mt76_led_init(struct mt76_dev *dev) { @@ -211,6 +216,7 @@ static int mt76_led_init(struct mt76_dev *dev) if (!of_property_read_u32(np, "led-sources", &led_pin)) dev->led_pin = led_pin; dev->led_al = of_property_read_bool(np, "led-active-low"); + of_node_put(np); } return led_classdev_register(dev->dev, &dev->led_cdev); @@ -249,6 +255,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; else vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC; + vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; for (i = 0; i < 8; i++) { if (i < nstream) @@ -259,6 +267,9 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, } vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + if (ieee80211_hw_check(phy->hw, SUPPORTS_VHT_EXT_NSS_BW)) + vht_cap->vht_mcs.tx_highest |= + cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE); } void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) @@ -324,8 +335,6 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | IEEE80211_VHT_CAP_RXSTBC_1 | IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | (3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); return 0; @@ -393,7 +402,7 @@ mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, phy->hw->wiphy->bands[band] = NULL; } -static void +static int mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) { struct mt76_dev *dev = phy->dev; @@ -411,8 +420,15 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); - wiphy->available_antennas_tx = dev->phy.antenna_mask; - wiphy->available_antennas_rx = dev->phy.antenna_mask; + wiphy->available_antennas_tx = phy->antenna_mask; + wiphy->available_antennas_rx = phy->antenna_mask; + + wiphy->sar_capa = &mt76_sar_capa; + phy->frp = devm_kcalloc(dev->dev, wiphy->sar_capa->num_freq_ranges, + sizeof(struct mt76_freq_range_power), + GFP_KERNEL); + if (!phy->frp) + return -ENOMEM; hw->txq_data_size = sizeof(struct mt76_txq); hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL; @@ -432,11 +448,13 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, AP_LINK_PS); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + + return 0; } struct mt76_phy * mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, - const struct ieee80211_ops *ops) + const struct ieee80211_ops *ops, u8 band_idx) { struct ieee80211_hw *hw; unsigned int phy_size; @@ -451,6 +469,7 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, phy->dev = dev; phy->hw = hw; phy->priv = hw->priv + phy_size; + phy->band_idx = band_idx; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->interface_modes = @@ -472,7 +491,9 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, { int ret; - mt76_phy_init(phy, phy->hw); + ret = mt76_phy_init(phy, phy->hw); + if (ret) + return ret; if (phy->cap.has_2ghz) { ret = mt76_init_sband_2g(phy, rates, n_rates); @@ -501,7 +522,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, if (ret) return ret; - phy->dev->phy2 = phy; + phy->dev->phys[phy->band_idx] = phy; return 0; } @@ -513,7 +534,7 @@ void mt76_unregister_phy(struct mt76_phy *phy) mt76_tx_status_check(dev, true); ieee80211_unregister_hw(phy->hw); - dev->phy2 = NULL; + dev->phys[phy->band_idx] = NULL; } EXPORT_SYMBOL_GPL(mt76_unregister_phy); @@ -535,10 +556,13 @@ mt76_alloc_device(struct device *pdev, unsigned int size, dev->hw = hw; dev->dev = pdev; dev->drv = drv_ops; + dev->dma_dev = pdev; phy = &dev->phy; phy->dev = dev; phy->hw = hw; + phy->band_idx = MT_BAND0; + dev->phys[phy->band_idx] = phy; spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->lock); @@ -569,6 +593,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, INIT_LIST_HEAD(&dev->wcid_list); INIT_LIST_HEAD(&dev->txwi_cache); + dev->token_size = dev->drv->token_size; for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) skb_queue_head_init(&dev->rx_skb[i]); @@ -591,7 +616,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, int ret; dev_set_drvdata(dev->dev, dev); - mt76_phy_init(phy, hw); + ret = mt76_phy_init(phy, hw); + if (ret) + return ret; if (phy->cap.has_2ghz) { ret = mt76_init_sband_2g(phy, rates, n_rates); @@ -717,7 +744,7 @@ static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q, void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); + struct mt76_phy *phy = mt76_dev_phy(dev, status->phy_idx); if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { dev_kfree_skb(skb); @@ -811,6 +838,10 @@ void mt76_set_channel(struct mt76_phy *phy) wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); mt76_update_survey(phy); + if (phy->chandef.chan->center_freq != chandef->chan->center_freq || + phy->chandef.width != chandef->width) + phy->dfs_state = MT_DFS_STATE_UNKNOWN; + phy->chandef = *chandef; phy->chan_state = mt76_channel_state(phy, chandef->chan); @@ -916,6 +947,36 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, } EXPORT_SYMBOL(mt76_wcid_key_setup); +static int +mt76_rx_signal(struct mt76_rx_status *status) +{ + s8 *chain_signal = status->chain_signal; + int signal = -128; + u8 chains; + + for (chains = status->chains; chains; chains >>= 1, chain_signal++) { + int cur, diff; + + cur = *chain_signal; + if (!(chains & BIT(0)) || + cur > 0) + continue; + + if (cur > signal) + swap(cur, signal); + + diff = signal - cur; + if (diff == 0) + signal += 3; + else if (diff <= 2) + signal += 2; + else if (diff <= 6) + signal += 1; + } + + return signal; +} + static void mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_hw **hw, @@ -944,6 +1005,9 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, status->ampdu_reference = mstat.ampdu_ref; status->device_timestamp = mstat.timestamp; status->mactime = mstat.timestamp; + status->signal = mt76_rx_signal(&mstat); + if (status->signal <= -128) + status->flag |= RX_FLAG_NO_SIGNAL_VAL; if (ieee80211_is_beacon(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control)) @@ -956,10 +1020,10 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, sizeof(mstat.chain_signal)); *sta = wcid_to_sta(mstat.wcid); - *hw = mt76_phy_hw(dev, mstat.ext_phy); + *hw = mt76_phy_hw(dev, mstat.phy_idx); } -static int +static void mt76_check_ccmp_pn(struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -969,10 +1033,13 @@ mt76_check_ccmp_pn(struct sk_buff *skb) int ret; if (!(status->flag & RX_FLAG_DECRYPTED)) - return 0; + return; + + if (status->flag & RX_FLAG_ONLY_MONITOR) + return; if (!wcid || !wcid->rx_check_pn) - return 0; + return; security_idx = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; if (status->flag & RX_FLAG_8023) @@ -986,7 +1053,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb) */ if (ieee80211_is_frag(hdr) && !ieee80211_is_first_frag(hdr->frame_control)) - return 0; + return; } /* IEEE 802.11-2020, 12.5.3.4.4 "PN and replay detection" c): @@ -1003,15 +1070,15 @@ skip_hdr_check: BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0])); ret = memcmp(status->iv, wcid->rx_key_pn[security_idx], sizeof(status->iv)); - if (ret <= 0) - return -EINVAL; /* replay */ + if (ret <= 0) { + status->flag |= RX_FLAG_ONLY_MONITOR; + return; + } memcpy(wcid->rx_key_pn[security_idx], status->iv, sizeof(status->iv)); if (status->flag & RX_FLAG_IV_STRIPPED) status->flag |= RX_FLAG_PN_VALIDATED; - - return 0; } static void @@ -1116,7 +1183,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; bool ps; - hw = mt76_phy_hw(dev, status->ext_phy); + hw = mt76_phy_hw(dev, status->phy_idx); if (ieee80211_is_pspoll(hdr->frame_control) && !wcid && !(status->flag & RX_FLAG_8023)) { sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); @@ -1163,10 +1230,12 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) if (ps) set_bit(MT_WCID_FLAG_PS, &wcid->flags); - else - clear_bit(MT_WCID_FLAG_PS, &wcid->flags); dev->drv->sta_ps(dev, sta, ps); + + if (!ps) + clear_bit(MT_WCID_FLAG_PS, &wcid->flags); + ieee80211_sta_ps_transition(sta, ps); } @@ -1182,11 +1251,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, while ((skb = __skb_dequeue(frames)) != NULL) { struct sk_buff *nskb = skb_shinfo(skb)->frag_list; - if (mt76_check_ccmp_pn(skb)) { - dev_kfree_skb(skb); - continue; - } - + mt76_check_ccmp_pn(skb); skb_shinfo(skb)->frag_list = NULL; mt76_rx_convert(dev, skb, &hw, &sta); ieee80211_rx_list(hw, sta, skb, &list); @@ -1232,10 +1297,11 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); static int -mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool ext_phy) +mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + struct mt76_dev *dev = phy->dev; int ret; int i; @@ -1252,13 +1318,13 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, continue; mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; - mtxq->wcid = wcid; + mtxq->wcid = wcid->idx; } ewma_signal_init(&wcid->rssi); - if (ext_phy) + if (phy->band_idx == MT_BAND1) mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); - wcid->ext_phy = ext_phy; + wcid->phy_idx = phy->band_idx; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); mt76_packet_id_init(wcid); @@ -1303,11 +1369,10 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return mt76_sta_add(dev, vif, sta, ext_phy); + return mt76_sta_add(phy, vif, sta); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && @@ -1330,7 +1395,9 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; mutex_lock(&dev->mutex); + spin_lock_bh(&dev->status_lock); rcu_assign_pointer(dev->wcid[wcid->idx], NULL); + spin_unlock_bh(&dev->status_lock); mutex_unlock(&dev->mutex); } EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); @@ -1348,10 +1415,63 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_get_txpower); +int mt76_init_sar_power(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt76_phy *phy = hw->priv; + const struct cfg80211_sar_capa *capa = hw->wiphy->sar_capa; + int i; + + if (sar->type != NL80211_SAR_TYPE_POWER || !sar->num_sub_specs) + return -EINVAL; + + for (i = 0; i < sar->num_sub_specs; i++) { + u32 index = sar->sub_specs[i].freq_range_index; + /* SAR specifies power limitaton in 0.25dbm */ + s32 power = sar->sub_specs[i].power >> 1; + + if (power > 127 || power < -127) + power = 127; + + phy->frp[index].range = &capa->freq_ranges[index]; + phy->frp[index].power = power; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_init_sar_power); + +int mt76_get_sar_power(struct mt76_phy *phy, + struct ieee80211_channel *chan, + int power) +{ + const struct cfg80211_sar_capa *capa = phy->hw->wiphy->sar_capa; + int freq, i; + + if (!capa || !phy->frp) + return power; + + if (power > 127 || power < -127) + power = 127; + + freq = ieee80211_channel_to_frequency(chan->hw_value, chan->band); + for (i = 0 ; i < capa->num_freq_ranges; i++) { + if (phy->frp[i].range && + freq >= phy->frp[i].range->start_freq && + freq < phy->frp[i].range->end_freq) { + power = min_t(int, phy->frp[i].power, power); + break; + } + } + + return power; +} +EXPORT_SYMBOL_GPL(mt76_get_sar_power); + static void __mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) + if (vif->bss_conf.csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) ieee80211_csa_finish(vif); } @@ -1373,7 +1493,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt76_dev *dev = priv; - if (!vif->csa_active) + if (!vif->bss_conf.csa_active) return; dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif); @@ -1474,7 +1594,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, - int ring_base) + int ring_base, u32 flags) { struct mt76_queue *hwq; int err; @@ -1483,6 +1603,8 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, if (!hwq) return ERR_PTR(-ENOMEM); + hwq->flags = flags; + err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); if (err < 0) return ERR_PTR(err); @@ -1494,7 +1616,6 @@ EXPORT_SYMBOL_GPL(mt76_init_queue); u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx) { int offset = 0; - struct ieee80211_rate *rate; if (phy->chandef.chan->band != NL80211_BAND_2GHZ) offset = 4; @@ -1503,9 +1624,11 @@ u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx) if (rateidx < 0) rateidx = 0; - rate = &mt76_rates[offset + rateidx]; + rateidx += offset; + if (rateidx >= ARRAY_SIZE(mt76_rates)) + rateidx = offset; - return rate->hw_value; + return mt76_rates[rateidx].hw_value; } EXPORT_SYMBOL_GPL(mt76_calculate_default_rate); @@ -1536,3 +1659,27 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, wi->worker_stat_count = ei - wi->initial_stat_idx; } EXPORT_SYMBOL_GPL(mt76_ethtool_worker); + +enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) +{ + struct ieee80211_hw *hw = phy->hw; + struct mt76_dev *dev = phy->dev; + + if (dev->region == NL80211_DFS_UNSET || + test_bit(MT76_SCANNING, &phy->state)) + return MT_DFS_STATE_DISABLED; + + if (!hw->conf.radar_enabled) { + if ((hw->conf.flags & IEEE80211_CONF_MONITOR) && + (phy->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return MT_DFS_STATE_ACTIVE; + + return MT_DFS_STATE_DISABLED; + } + + if (!cfg80211_reg_can_beacon(hw->wiphy, &phy->chandef, NL80211_IFTYPE_AP)) + return MT_DFS_STATE_CAC; + + return MT_DFS_STATE_ACTIVE; +} +EXPORT_SYMBOL_GPL(mt76_phy_dfs_state); diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 3f94c37251df..a8cafa39a56d 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -6,18 +6,20 @@ #include "mt76.h" struct sk_buff * -mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, - int data_len) +__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, + int len, int data_len, gfp_t gfp) { const struct mt76_mcu_ops *ops = dev->mcu_ops; - int length = ops->headroom + data_len + ops->tailroom; struct sk_buff *skb; - skb = alloc_skb(length, GFP_KERNEL); + len = max_t(int, len, data_len); + len = ops->headroom + len + ops->tailroom; + + skb = alloc_skb(len, gfp); if (!skb) return NULL; - memset(skb->head, 0, length); + memset(skb->head, 0, len); skb_reserve(skb, ops->headroom); if (data && data_len) @@ -25,7 +27,7 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, return skb; } -EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); +EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires) diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 26353b6bce97..86e3d2ac4d0d 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -73,8 +73,13 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, spin_lock_irqsave(&dev->mmio.irq_lock, flags); dev->mmio.irqmask &= ~clear; dev->mmio.irqmask |= set; - if (addr) - mt76_mmio_wr(dev, addr, dev->mmio.irqmask); + if (addr) { + if (mtk_wed_device_active(&dev->mmio.wed)) + mtk_wed_device_irq_set_mask(&dev->mmio.wed, + dev->mmio.irqmask); + else + mt76_mmio_wr(dev, addr, dev->mmio.irqmask); + } spin_unlock_irqrestore(&dev->mmio.irq_lock, flags); } EXPORT_SYMBOL_GPL(mt76_set_irq_mask); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e2da720a91b6..87db9498dea4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -13,19 +13,30 @@ #include <linux/leds.h> #include <linux/usb.h> #include <linux/average.h> +#include <linux/soc/mediatek/mtk_wed.h> #include <net/mac80211.h> #include "util.h" #include "testmode.h" #define MT_MCU_RING_SIZE 32 #define MT_RX_BUF_SIZE 2048 -#define MT_SKB_HEAD_LEN 128 +#define MT_SKB_HEAD_LEN 256 #define MT_MAX_NON_AQL_PKT 16 #define MT_TXQ_FREE_THR 32 #define MT76_TOKEN_FREE_THR 64 +#define MT_QFLAG_WED_RING GENMASK(1, 0) +#define MT_QFLAG_WED_TYPE GENMASK(3, 2) +#define MT_QFLAG_WED BIT(4) + +#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ + FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ + FIELD_PREP(MT_QFLAG_WED_RING, _n)) +#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n) +#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0) + struct mt76_dev; struct mt76_phy; struct mt76_wcid; @@ -42,6 +53,11 @@ enum mt76_bus_type { MT76_BUS_SDIO, }; +enum mt76_wed_type { + MT76_WED_Q_TX, + MT76_WED_Q_TXFREE, +}; + struct mt76_bus_ops { u32 (*rr)(struct mt76_dev *dev, u32 offset); void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); @@ -83,11 +99,21 @@ enum mt76_rxq_id { MT_RXQ_MAIN, MT_RXQ_MCU, MT_RXQ_MCU_WA, - MT_RXQ_EXT, - MT_RXQ_EXT_WA, + MT_RXQ_BAND1, + MT_RXQ_BAND1_WA, + MT_RXQ_MAIN_WA, + MT_RXQ_BAND2, + MT_RXQ_BAND2_WA, __MT_RXQ_MAX }; +enum mt76_band_id { + MT_BAND0, + MT_BAND1, + MT_BAND2, + __MT_MAX_BAND +}; + enum mt76_cipher_type { MT_CIPHER_NONE, MT_CIPHER_WEP40, @@ -104,6 +130,13 @@ enum mt76_cipher_type { MT_CIPHER_GCMP_256, }; +enum mt76_dfs_state { + MT_DFS_STATE_UNKNOWN, + MT_DFS_STATE_DISABLED, + MT_DFS_STATE_CAC, + MT_DFS_STATE_ACTIVE, +}; + struct mt76_queue_buf { dma_addr_t addr; u16 len; @@ -161,7 +194,9 @@ struct mt76_queue { u8 buf_offset; u8 hw_idx; - u8 qid; + u8 flags; + + u32 wed_regs; dma_addr_t desc_dma; struct sk_buff *rx_head; @@ -196,8 +231,8 @@ struct mt76_queue_ops { u32 ring_base); int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta); + enum mt76_txq_id qid, struct sk_buff *skb, + struct mt76_wcid *wcid, struct ieee80211_sta *sta); int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info); @@ -217,6 +252,30 @@ struct mt76_queue_ops { void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q); }; +enum mt76_phy_type { + MT_PHY_TYPE_CCK, + MT_PHY_TYPE_OFDM, + MT_PHY_TYPE_HT, + MT_PHY_TYPE_HT_GF, + MT_PHY_TYPE_VHT, + MT_PHY_TYPE_HE_SU = 8, + MT_PHY_TYPE_HE_EXT_SU, + MT_PHY_TYPE_HE_TB, + MT_PHY_TYPE_HE_MU, + __MT_PHY_TYPE_HE_MAX, +}; + +struct mt76_sta_stats { + u64 tx_mode[__MT_PHY_TYPE_HE_MAX]; + u64 tx_bw[4]; /* 20, 40, 80, 160 */ + u64 tx_nss[4]; /* 1, 2, 3, 4 */ + u64 tx_mcs[16]; /* mcs idx */ + u64 tx_bytes; + u32 tx_packets; + u32 tx_retries; + u32 tx_failed; +}; + enum mt76_wcid_flags { MT_WCID_FLAG_CHECK_PS, MT_WCID_FLAG_PS, @@ -224,10 +283,10 @@ enum mt76_wcid_flags { MT_WCID_FLAG_HDR_TRANS, }; -#define MT76_N_WCIDS 288 +#define MT76_N_WCIDS 544 /* stored in ieee80211_tx_info::hw_queue */ -#define MT_TX_HW_QUEUE_EXT_PHY BIT(3) +#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2) DECLARE_EWMA(signal, 10, 8); @@ -252,8 +311,8 @@ struct mt76_wcid { u8 hw_key_idx2; u8 sta:1; - u8 ext_phy:1; u8 amsdu:1; + u8 phy_idx:2; u8 rx_check_pn; u8 rx_key_pn[IEEE80211_NUM_TIDS + 1][6]; @@ -264,10 +323,12 @@ struct mt76_wcid { struct list_head list; struct idr pktid; + + struct mt76_sta_stats stats; }; struct mt76_txq { - struct mt76_wcid *wcid; + u16 wcid; u16 agg_ssn; bool send_bar; @@ -307,7 +368,8 @@ struct mt76_rx_tid { #define MT_PACKET_ID_MASK GENMASK(6, 0) #define MT_PACKET_ID_NO_ACK 0 #define MT_PACKET_ID_NO_SKB 1 -#define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_WED 2 +#define MT_PACKET_ID_FIRST 3 #define MT_PACKET_ID_HAS_RATE BIT(7) /* This is timer for when to give up when waiting for TXS callback, * with starting time being the time at which the DMA_DONE callback @@ -373,6 +435,8 @@ struct mt76_driver_ops { bool (*tx_status_data)(struct mt76_dev *dev, u8 *update); + bool (*rx_check)(struct mt76_dev *dev, void *data, int len); + void (*rx_skb)(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); @@ -490,11 +554,12 @@ struct mt76_usb { struct mt76_reg_pair *rp; int rp_len; u32 base; - bool burst; } mcu; }; -#define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE) +#define MT76S_XMIT_BUF_SZ 0x3fe00 +#define MT76S_NUM_TX_ENTRIES 256 +#define MT76S_NUM_RX_ENTRIES 512 struct mt76_sdio { struct mt76_worker txrx_worker; struct mt76_worker status_worker; @@ -502,7 +567,8 @@ struct mt76_sdio { struct work_struct stat_work; - u8 *xmit_buf[IEEE80211_NUM_ACS + 2]; + u8 *xmit_buf; + u32 xmit_buf_sz; struct sdio_func *func; void *intr_data; @@ -524,6 +590,8 @@ struct mt76_mmio { void __iomem *regs; spinlock_t irq_lock; u32 irqmask; + + struct mtk_wed_device wed; }; struct mt76_rx_status { @@ -539,7 +607,7 @@ struct mt76_rx_status { u8 iv[6]; - u8 ext_phy:1; + u8 phy_idx:2; u8 aggr:1; u8 qos_ctl; u16 seqno; @@ -599,6 +667,8 @@ struct mt76_testmode_data { u8 tx_power[4]; u8 tx_power_control; + u8 addr[3][ETH_ALEN]; + u32 tx_pending; u32 tx_queued; u16 tx_queued_limit; @@ -615,6 +685,7 @@ struct mt76_vif { u8 band_idx; u8 wmm_idx; u8 scan_seq_num; + u8 cipher; }; struct mt76_phy { @@ -623,6 +694,7 @@ struct mt76_phy { void *priv; unsigned long state; + u8 band_idx; struct mt76_queue *q_tx[__MT_TXQ_MAX]; @@ -630,6 +702,7 @@ struct mt76_phy { struct ieee80211_channel *main_chan; struct mt76_channel_state *chan_state; + enum mt76_dfs_state dfs_state; ktime_t survey_time; struct mt76_hw_cap cap; @@ -661,8 +734,7 @@ struct mt76_phy { struct mt76_dev { struct mt76_phy phy; /* must be first */ - - struct mt76_phy *phy2; + struct mt76_phy *phys[__MT_MAX_BAND]; struct ieee80211_hw *hw; @@ -681,6 +753,7 @@ struct mt76_dev { const struct mt76_driver_ops *drv; const struct mt76_mcu_ops *mcu_ops; struct device *dev; + struct device *dma_dev; struct mt76_mcu mcu; @@ -701,7 +774,9 @@ struct mt76_dev { spinlock_t token_lock; struct idr token; - int token_count; + u16 wed_token_count; + u16 token_count; + u16 token_size; wait_queue_head_t tx_wait; /* spinclock used to protect wcid pktid linked list */ @@ -710,7 +785,7 @@ struct mt76_dev { u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; - u32 vif_mask; + u64 vif_mask; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; @@ -766,26 +841,6 @@ struct mt76_power_limits { s8 ru[7][12]; }; -enum mt76_phy_type { - MT_PHY_TYPE_CCK, - MT_PHY_TYPE_OFDM, - MT_PHY_TYPE_HT, - MT_PHY_TYPE_HT_GF, - MT_PHY_TYPE_VHT, - MT_PHY_TYPE_HE_SU = 8, - MT_PHY_TYPE_HE_EXT_SU, - MT_PHY_TYPE_HE_TB, - MT_PHY_TYPE_HE_MU, - __MT_PHY_TYPE_HE_MAX, -}; - -struct mt76_sta_stats { - u64 tx_mode[__MT_PHY_TYPE_HE_MAX]; - u64 tx_bw[4]; /* 20, 40, 80, 160 */ - u64 tx_nss[4]; /* 1, 2, 3, 4 */ - u64 tx_mcs[16]; /* mcs idx */ -}; - struct mt76_ethtool_worker_info { u64 *data; int idx; @@ -808,7 +863,6 @@ struct mt76_ethtool_worker_info { } extern struct ieee80211_rate mt76_rates[12]; -extern const struct cfg80211_sar_capa mt76_sar_capa; #define __mt76_rr(dev, ...) (dev)->bus->rr((dev), __VA_ARGS__) #define __mt76_wr(dev, ...) (dev)->bus->wr((dev), __VA_ARGS__) @@ -845,16 +899,6 @@ extern const struct cfg80211_sar_capa mt76_sar_capa; #define mt76_hw(dev) (dev)->mphy.hw -static inline struct ieee80211_hw * -mt76_wcid_hw(struct mt76_dev *dev, u16 wcid) -{ - if (wcid <= MT76_N_WCIDS && - mt76_wcid_mask_test(dev->wcid_phy_mask, wcid)) - return dev->phy2->hw; - - return dev->phy.hw; -} - bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, int timeout); @@ -892,8 +936,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__) #define mt76_for_each_q_rx(dev, i) \ - for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \ - (dev)->q_rx[i].ndesc; i++) + for (i = 0; i < ARRAY_SIZE((dev)->q_rx); i++) \ + if ((dev)->q_rx[i].ndesc) struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, @@ -905,7 +949,8 @@ void mt76_free_device(struct mt76_dev *dev); void mt76_unregister_phy(struct mt76_phy *phy); struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, - const struct ieee80211_ops *ops); + const struct ieee80211_ops *ops, + u8 band_idx); int mt76_register_phy(struct mt76_phy *phy, bool vht, struct ieee80211_rate *rates, int n_rates); @@ -926,18 +971,17 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, - int ring_base); + int ring_base, u32 flags); u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx); static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, - int n_desc, int ring_base) + int n_desc, int ring_base, u32 flags) { struct mt76_queue *q; - q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base); + q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags); if (IS_ERR(q)) return PTR_ERR(q); - q->qid = qid; phy->q_tx[qid] = q; return 0; @@ -948,28 +992,29 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx, { struct mt76_queue *q; - q = mt76_init_queue(dev, qid, idx, n_desc, ring_base); + q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0); if (IS_ERR(q)) return PTR_ERR(q); - q->qid = __MT_TXQ_MAX + qid; dev->q_mcu[qid] = q; return 0; } static inline struct mt76_phy * -mt76_dev_phy(struct mt76_dev *dev, bool phy_ext) +mt76_dev_phy(struct mt76_dev *dev, u8 phy_idx) { - if (phy_ext && dev->phy2) - return dev->phy2; + if ((phy_idx == MT_BAND1 && dev->phys[phy_idx]) || + (phy_idx == MT_BAND2 && dev->phys[phy_idx])) + return dev->phys[phy_idx]; + return &dev->phy; } static inline struct ieee80211_hw * -mt76_phy_hw(struct mt76_dev *dev, bool phy_ext) +mt76_phy_hw(struct mt76_dev *dev, u8 phy_idx) { - return mt76_dev_phy(dev, phy_ext)->hw; + return mt76_dev_phy(dev, phy_idx)->hw; } static inline u8 * @@ -1080,13 +1125,17 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev, struct ieee80211_hw **hw) { #ifdef CONFIG_NL80211_TESTMODE - if (skb == dev->phy.test.tx_skb) - *hw = dev->phy.hw; - else if (dev->phy2 && skb == dev->phy2->test.tx_skb) - *hw = dev->phy2->hw; - else - return false; - return true; + int i; + + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { + struct mt76_phy *phy = dev->phys[i]; + + if (phy && skb == phy->test.tx_skb) { + *hw = dev->phys[i]->hw; + return true; + } + } + return false; #else return false; #endif @@ -1157,6 +1206,11 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm); +int mt76_init_sar_power(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar); +int mt76_get_sar_power(struct mt76_phy *phy, + struct ieee80211_channel *chan, + int power); void mt76_csa_check(struct mt76_dev *dev); void mt76_csa_finish(struct mt76_dev *dev); @@ -1171,6 +1225,7 @@ void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy); int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, @@ -1196,12 +1251,10 @@ static inline struct ieee80211_hw * mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = dev->phy.hw; - - if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2) - hw = dev->phy2->hw; + u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; + struct ieee80211_hw *hw = mt76_phy_hw(dev, phy_idx); - info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY; + info->hw_queue &= ~MT_TX_HW_QUEUE_PHY; return hw; } @@ -1252,13 +1305,21 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, struct mt76_sta_stats *stats); int mt76_skb_adjust_pad(struct sk_buff *skb, int pad); +int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, + u16 val, u16 offset, void *buf, size_t len); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); -int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, - bool ext); +void mt76u_read_copy(struct mt76_dev *dev, u32 offset, + void *data, int len); +u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr); +void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, + u32 addr, u32 val); +int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + struct mt76_bus_ops *ops); +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); int mt76u_alloc_mcu_queue(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_tx(struct mt76_dev *dev); @@ -1291,8 +1352,15 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *data, int len); struct sk_buff * +__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, + int len, int data_len, gfp_t gfp); +static inline struct sk_buff * mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, - int data_len); + int data_len) +{ + return __mt76_mcu_msg_alloc(dev, data, data_len, data_len, GFP_KERNEL); +} + void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); @@ -1350,8 +1418,7 @@ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) int token; spin_lock_bh(&dev->token_lock); - token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size, - GFP_ATOMIC); + token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); spin_unlock_bh(&dev->token_lock); return token; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index 5d4522f440b7..b65b0a88c1de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -20,12 +20,12 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!(mdev->beacon_mask & BIT(mvif->idx))) return; - skb = ieee80211_beacon_get(mt76_hw(dev), vif); + skb = ieee80211_beacon_get(mt76_hw(dev), vif, 0); if (!skb) return; - mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb, - &mvif->sta.wcid, NULL); + mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], + MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); spin_lock_bh(&dev->ps_lock); mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | @@ -82,12 +82,12 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) __skb_queue_head_init(&data.q); q = dev->mphy.q_tx[MT_TXQ_BEACON]; - spin_lock_bh(&q->lock); + spin_lock(&q->lock); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt7603_update_beacon_iter, dev); mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); + spin_unlock(&q->lock); /* Flush all previous CAB queue packets */ mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); @@ -117,16 +117,16 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) mt76_skb_set_moredata(data.tail[i], false); } - spin_lock_bh(&q->lock); + spin_lock(&q->lock); while ((skb = __skb_dequeue(&data.q)) != NULL) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; - mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL); + mt76_tx_queue_skb(dev, q, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL); } mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); + spin_unlock(&q->lock); for (i = 0; i < ARRAY_SIZE(data.count); i++) mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i), diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 415ea17b9be6..f9e5857850e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -76,7 +76,7 @@ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); if (q == MT_RXQ_MCU) { if (type == PKT_TYPE_RX_EVENT) @@ -173,13 +173,13 @@ int mt7603_dma_init(struct mt7603_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], - MT7603_TX_RING_SIZE, MT_TX_RING_BASE); + MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT7603_PSD_RING_SIZE, MT_TX_RING_BASE); + MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -189,12 +189,12 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN, - MT_MCU_RING_SIZE, MT_TX_RING_BASE); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC, - MT_MCU_RING_SIZE, MT_TX_RING_BASE); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -223,8 +223,8 @@ int mt7603_dma_init(struct mt7603_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7603_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7603_poll_tx); napi_enable(&dev->mt76.tx_napi); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index fe03e31989bb..49a511ae8161 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -202,10 +202,11 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); - WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, - 0, 5000)); + mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000); } + WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY); + mt76_wr(dev, MT_TX_ABORT, 0); mt7603_wtbl_set_skip_tx(dev, idx, false); @@ -325,19 +326,21 @@ void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta) addr = mt7603_wtbl1_addr(idx); - ampdu_density = sta->ht_cap.ampdu_density; + ampdu_density = sta->deflink.ht_cap.ampdu_density; if (ampdu_density < IEEE80211_HT_MPDU_DENSITY_4) ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; val = mt76_rr(dev, addr + 2 * 4); val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL; - val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) | - FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) | + val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, + sta->deflink.ht_cap.ampdu_factor) | + FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, + sta->deflink.ht_cap.ampdu_density) | MT_WTBL1_W2_TXS_BAF_REPORT; - if (sta->ht_cap.cap) + if (sta->deflink.ht_cap.cap) val |= MT_WTBL1_W2_HT; - if (sta->vht_cap.cap) + if (sta->deflink.vht_cap.cap) val |= MT_WTBL1_W2_VHT; mt76_wr(dev, addr + 2 * 4, val); @@ -346,9 +349,9 @@ void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta) val = mt76_rr(dev, addr + 9 * 4); val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | MT_WTBL2_W9_SHORT_GI_80); - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) val |= MT_WTBL2_W9_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) val |= MT_WTBL2_W9_SHORT_GI_40; mt76_wr(dev, addr + 9 * 4, val); } @@ -525,6 +528,10 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) status->flag |= RX_FLAG_MMIC_ERROR; + /* ICV error or CCMP/BIP/WPI MIC error */ + if (rxd2 & MT_RXD2_NORMAL_ICV_ERR) + status->flag |= RX_FLAG_ONLY_MONITOR; + if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { status->flag |= RX_FLAG_DECRYPTED; @@ -638,11 +645,6 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + dev->rssi_offset[1]; - status->signal = status->chain_signal[0]; - if (status->chains & BIT(1)) - status->signal = max(status->signal, - status->chain_signal[1]); - if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1) status->bw = RATE_INFO_BW_40; @@ -1130,7 +1132,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, } rate_set_tsf = READ_ONCE(sta->rate_set_tsf); - rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) - + rs_idx = !((u32)(le32_get_bits(txs_data[1], MT_TXS1_F0_TIMESTAMP) - rate_set_tsf) < 1000000); rs_idx ^= rate_set_tsf & BIT(0); rs = &sta->rateset[rs_idx]; @@ -1244,14 +1246,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) struct mt7603_sta *msta = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; - u32 txs; u8 wcidx; u8 pid; - txs = le32_to_cpu(txs_data[4]); - pid = FIELD_GET(MT_TXS4_PID, txs); - txs = le32_to_cpu(txs_data[3]); - wcidx = FIELD_GET(MT_TXS3_WCID, txs); + pid = le32_get_bits(txs_data[4], MT_TXS4_PID); + wcidx = le32_get_bits(txs_data[3], MT_TXS3_WCID); if (pid == MT_PACKET_ID_NO_ACK) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 7ac4cd247a73..ca50feb0b3a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -44,7 +44,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_lock(&dev->mt76.mutex); - mvif->idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->idx = __ffs64(~dev->mt76.vif_mask); if (mvif->idx >= MT7603_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -65,7 +65,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; - dev->mt76.vif_mask |= BIT(mvif->idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->idx); INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; @@ -75,7 +75,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); out: @@ -106,7 +106,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) spin_unlock_bh(&dev->sta_poll_lock); mutex_lock(&dev->mt76.mutex); - dev->mt76.vif_mask &= ~BIT(mvif->idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); mutex_unlock(&dev->mt76.mutex); mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); @@ -133,13 +133,15 @@ void mt7603_init_edcca(struct mt7603_dev *dev) } static int -mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) +mt7603_set_channel(struct ieee80211_hw *hw, struct cfg80211_chan_def *def) { + struct mt7603_dev *dev = hw->priv; u8 *rssi_data = (u8 *)dev->mt76.eeprom.data; int idx, ret; u8 bw = MT_BW_20; bool failed = false; + ieee80211_stop_queues(hw); cancel_delayed_work_sync(&dev->mphy.mac_work); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); @@ -205,9 +207,28 @@ out: if (failed) mt7603_mac_work(&dev->mphy.mac_work.work); + ieee80211_wake_queues(hw); + return ret; } +static int mt7603_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt7603_dev *dev = hw->priv; + struct mt76_phy *mphy = &dev->mphy; + int err; + + if (!cfg80211_chandef_valid(&mphy->chandef)) + return -EINVAL; + + err = mt76_init_sar_power(hw, sar); + if (err) + return err; + + return mt7603_set_channel(hw, &mphy->chandef); +} + static int mt7603_config(struct ieee80211_hw *hw, u32 changed) { @@ -215,11 +236,8 @@ mt7603_config(struct ieee80211_hw *hw, u32 changed) int ret = 0; if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | - IEEE80211_CONF_CHANGE_POWER)) { - ieee80211_stop_queues(hw); - ret = mt7603_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } + IEEE80211_CONF_CHANGE_POWER)) + ret = mt7603_set_channel(hw, &hw->conf.chandef); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { mutex_lock(&dev->mt76.mutex); @@ -279,7 +297,7 @@ mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, static void mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed) + struct ieee80211_bss_conf *info, u64 changed) { struct mt7603_dev *dev = hw->priv; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; @@ -287,7 +305,7 @@ mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) { - if (info->assoc || info->ibss_joined) { + if (vif->cfg.assoc || vif->cfg.ibss_joined) { mt76_wr(dev, MT_BSSID0(mvif->idx), get_unaligned_le32(info->bssid)); mt76_wr(dev, MT_BSSID1(mvif->idx), @@ -509,7 +527,8 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } static int -mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt7603_dev *dev = hw->priv; @@ -623,6 +642,9 @@ mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); int i; + if (!sta_rates) + return; + spin_lock_bh(&dev->mt76.lock); for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { msta->rates[i].idx = sta_rates->rate[i].idx; @@ -636,7 +658,7 @@ mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates); msta->rate_probe = false; mt7603_wtbl_set_smps(dev, msta, - sta->smps_mode == IEEE80211_SMPS_DYNAMIC); + sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC); spin_unlock_bh(&dev->mt76.lock); } @@ -700,6 +722,7 @@ const struct ieee80211_ops mt7603_ops = { .set_tim = mt76_set_tim, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, + .set_sar_specs = mt7603_set_sar_specs, }; MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 6abfe6b19afa..7884b952b720 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -403,7 +403,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) .tx_streams = n_chains, .rx_streams = n_chains, }; - s8 tx_power; + s8 tx_power = hw->conf.power_level * 2; int i, ret; if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_40) { @@ -414,7 +414,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) req.center_chan -= 2; } - tx_power = hw->conf.power_level * 2; + tx_power = mt76_get_sar_power(&dev->mphy, chandef->chan, tx_power); if (dev->mphy.antenna_mask == 3) tx_power -= 6; tx_power = min(tx_power, dev->tx_power_limit); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 6fd6f067da49..c26b45a09923 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -105,10 +105,10 @@ mt7615_pm_set(void *data, u64 val) if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76)) return -EOPNOTSUPP; - if (val == pm->enable) - return 0; + mutex_lock(&dev->mt76.mutex); - mt7615_mutex_acquire(dev); + if (val == pm->enable) + goto out; if (dev->phy.n_beacon_vif) { ret = -EBUSY; @@ -119,9 +119,16 @@ mt7615_pm_set(void *data, u64 val) pm->stats.last_wake_event = jiffies; pm->stats.last_doze_event = jiffies; } + /* make sure the chip is awake here and ps_work is scheduled + * just at end of the this routine. + */ + pm->enable = false; + mt76_connac_pm_wake(&dev->mphy, pm); + pm->enable = val; + mt76_connac_power_save_sched(&dev->mphy, pm); out: - mt7615_mutex_release(dev); + mutex_unlock(&dev->mt76.mutex); return ret; } @@ -359,6 +366,9 @@ mt7615_queues_acq(struct seq_file *s, void *data) int acs = i / MT7615_MAX_WMM_SETS; u32 ctrl, val, qlen = 0; + if (wmm_idx == 3 && is_mt7663(&dev->mt76)) + continue; + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx)); ctrl = BIT(31) | BIT(15) | (acs << 8); @@ -433,11 +443,16 @@ mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct mt7615_dev *dev = file->private_data; - char buf[32 * ((ETH_ALEN * 3) + 4) + 1]; + u32 len = 32 * ((ETH_ALEN * 3) + 4) + 1; u8 addr[ETH_ALEN]; + char *buf; int ofs = 0; int i; + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + for (i = 0; i < 32; i++) { if (!(dev->muar_mask & BIT(i))) continue; @@ -448,10 +463,13 @@ mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf, put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr); put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) & MT_WF_RMAC_MAR1_ADDR), addr + 4); - ofs += snprintf(buf + ofs, sizeof(buf) - ofs, "%d=%pM\n", i, addr); + ofs += snprintf(buf + ofs, len - ofs, "%d=%pM\n", i, addr); } - return simple_read_from_buffer(userbuf, count, ppos, buf, ofs); + ofs = simple_read_from_buffer(userbuf, count, ppos, buf, ofs); + + kfree(buf); + return ofs; } static ssize_t diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 00aefea1bf61..f1914431ff7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], MT7615_TX_RING_SIZE / 2, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; @@ -44,7 +44,7 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev) static int mt7615_init_tx_queues(struct mt7615_dev *dev) { - int ret, i; + int ret; ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7615_TXQ_FWDL, MT7615_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); @@ -54,14 +54,11 @@ mt7615_init_tx_queues(struct mt7615_dev *dev) if (!is_mt7615(&dev->mt76)) return mt7622_init_tx_queues_multi(dev); - ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE, - MT_TX_RING_BASE); + ret = mt76_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE, + MT_TX_RING_BASE, 0); if (ret) return ret; - for (i = 1; i <= MT_TXQ_PSD ; i++) - dev->mphy.q_tx[i] = dev->mphy.q_tx[0]; - return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7615_TXQ_MCU, MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE); } @@ -284,8 +281,8 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7615_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7615_poll_tx); napi_enable(&dev->mt76.tx_napi); mt76_poll(dev, MT_WPDMA_GLO_CFG, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 47f23ac905a3..07a1fea94f66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -194,6 +194,7 @@ mt7615_check_offload_capability(struct mt7615_dev *dev) ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + wiphy->flags &= ~WIPHY_FLAG_4ADDR_STATION; wiphy->max_remain_on_channel_duration = 5000; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | @@ -400,6 +401,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); ieee80211_hw_set(hw, WANT_MONITOR_VIF); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); if (is_mt7615(&phy->dev->mt76)) hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; @@ -457,7 +459,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) return 0; mt7615_cap_dbdc_enable(dev); - mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1); if (!mphy) return -ENOMEM; @@ -507,7 +509,7 @@ EXPORT_SYMBOL_GPL(mt7615_register_ext_phy); void mt7615_unregister_ext_phy(struct mt7615_dev *dev) { struct mt7615_phy *phy = mt7615_ext_phy(dev); - struct mt76_phy *mphy = dev->mt76.phy2; + struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1]; if (!phy) return; @@ -551,7 +553,6 @@ void mt7615_init_device(struct mt7615_dev *dev) dev->pm.stats.last_wake_event = jiffies; dev->pm.stats.last_doze_event = jiffies; mt7615_cap_dbdc_disable(dev); - dev->phy.dfs_state = -1; #ifdef CONFIG_NL80211_TESTMODE dev->mt76.test_ops = &mt7615_testmode_ops; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 423f69015e3e..2ce1705c0f43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -109,6 +109,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, void mt7615_mac_reset_counters(struct mt7615_dev *dev) { + struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; int i; for (i = 0; i < 4; i++) { @@ -118,8 +119,8 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats)); dev->mt76.phy.survey_time = ktime_get_boottime(); - if (dev->mt76.phy2) - dev->mt76.phy2->survey_time = ktime_get_boottime(); + if (mphy_ext) + mphy_ext->survey_time = ktime_get_boottime(); /* reset airtime counters */ mt76_rr(dev, MT_MIB_SDR9(0)); @@ -249,20 +250,104 @@ static void mt7615_mac_fill_tm_rx(struct mt7615_phy *phy, __le32 *rxv) #endif } +/* The HW does not translate the mac header to 802.3 for mesh point */ +static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap); + struct mt7615_sta *msta = (struct mt7615_sta *)status->wcid; + __le32 *rxd = (__le32 *)skb->data; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct ieee80211_hdr hdr; + u16 frame_control; + + if (le32_get_bits(rxd[1], MT_RXD1_NORMAL_ADDR_TYPE) != + MT_RXD1_NORMAL_U2M) + return -EINVAL; + + if (!(le32_to_cpu(rxd[0]) & MT_RXD0_NORMAL_GROUP_4)) + return -EINVAL; + + if (!msta || !msta->vif) + return -EINVAL; + + sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + + /* store the info from RXD and ethhdr to avoid being overridden */ + frame_control = le32_get_bits(rxd[4], MT_RXD4_FRAME_CONTROL); + hdr.frame_control = cpu_to_le16(frame_control); + hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_SEQ_CTRL)); + hdr.duration_id = 0; + + ether_addr_copy(hdr.addr1, vif->addr); + ether_addr_copy(hdr.addr2, sta->addr); + switch (frame_control & (IEEE80211_FCTL_TODS | + IEEE80211_FCTL_FROMDS)) { + case 0: + ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); + break; + case IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_source); + break; + case IEEE80211_FCTL_TODS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + break; + case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + ether_addr_copy(hdr.addr4, eth_hdr->h_source); + break; + default: + break; + } + + skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); + if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || + eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) + ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); + else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) + ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); + else + skb_pull(skb, 2); + + if (ieee80211_has_order(hdr.frame_control)) + memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[7], + IEEE80211_HT_CTL_LEN); + + if (ieee80211_is_data_qos(hdr.frame_control)) { + __le16 qos_ctrl; + + qos_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_QOS_CTL)); + memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, + IEEE80211_QOS_CTL_LEN); + } + + if (ieee80211_has_a4(hdr.frame_control)) + memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); + else + memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); + + status->flag &= ~(RX_FLAG_RADIOTAP_HE | RX_FLAG_RADIOTAP_HE_MU); + return 0; +} + static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_phy *mphy = &dev->mt76.phy; struct mt7615_phy *phy = &dev->phy; - struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; + struct mt7615_phy *phy2; __le32 *rxd = (__le32 *)skb->data; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; + u32 csum_status = *(u32 *)skb->cb; bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false; + u16 hdr_gap; int phy_idx; int i, idx; u8 chfreq, amsdu_info, qos_ctl = 0; @@ -272,6 +357,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) memset(status, 0, sizeof(*status)); chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); + + phy2 = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; if (!phy2) phy_idx = 0; else if (phy2->chfreq == phy->chfreq) @@ -286,9 +373,16 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) return -EINVAL; + hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; + if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_CM)) + return -EINVAL; + + /* ICV error or CCMP/BIP/WPI MIC error */ + if (rxd2 & MT_RXD2_NORMAL_ICV_ERR) + status->flag |= RX_FLAG_ONLY_MONITOR; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); - hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); if (status->wcid) { @@ -301,7 +395,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } - if ((rxd0 & csum_mask) == csum_mask) + if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) @@ -408,9 +503,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) } if (phy_idx == 1 && phy2) { - mphy = dev->mt76.phy2; + mphy = dev->mt76.phys[MT_BAND1]; phy = phy2; - status->ext_phy = true; + status->phy_idx = phy_idx; } if (!mt7615_firmware_offload(dev) && chfreq != phy->chfreq) @@ -486,15 +581,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); - status->signal = status->chain_signal[0]; - - for (i = 1; i < hweight8(mphy->antenna_mask); i++) { - if (!(status->chains & BIT(i))) - continue; - - status->signal = max(status->signal, - status->chain_signal[i]); - } mt7615_mac_fill_tm_rx(mphy->priv, rxd); @@ -503,16 +589,42 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) return -EINVAL; } - skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); - amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1); status->amsdu = !!amsdu_info; if (status->amsdu) { status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME; - if (!hdr_trans) { - memmove(skb->data + 2, skb->data, - ieee80211_get_hdrlen_from_skb(skb)); + } + + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; + if (hdr_trans && ieee80211_has_morefrags(fc)) { + if (mt7615_reverse_frag0_hdr_trans(skb, hdr_gap)) + return -EINVAL; + hdr_trans = false; + } else { + int pad_start = 0; + + skb_pull(skb, hdr_gap); + if (!hdr_trans && status->amsdu) { + pad_start = ieee80211_get_hdrlen_from_skb(skb); + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { + /* + * When header translation failure is indicated, + * the hardware will insert an extra 2-byte field + * containing the data length after the protocol + * type field. This happens either when the LLC-SNAP + * pattern did not match, or if a VLAN header was + * detected. + */ + pad_start = 12; + if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) + pad_start += 4; + else + pad_start = 0; + } + + if (pad_start) { + memmove(skb->data + 2, skb->data, pad_start); skb_pull(skb, 2); } } @@ -610,13 +722,14 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key, bool beacon) + struct ieee80211_key_conf *key, + enum mt76_txq_id qid, bool beacon) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate = &info->control.rates[0]; - bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; + u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; bool is_mmio = mt76_is_mmio(&dev->mt76); @@ -639,18 +752,18 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, tx_count = msta->rate_count; } - if (ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (phy_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; if (beacon) { p_fmt = MT_TX_TYPE_FW; - q_idx = ext_phy ? MT_LMAC_BCN1 : MT_LMAC_BCN0; - } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { + q_idx = phy_idx ? MT_LMAC_BCN1 : MT_LMAC_BCN0; + } else if (qid >= MT_TXQ_PSD) { p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; - q_idx = ext_phy ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0; + q_idx = phy_idx ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0; } else { p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; q_idx = wmm_idx * MT7615_MAX_WMM_SETS + @@ -769,60 +882,6 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, } EXPORT_SYMBOL_GPL(mt7615_mac_write_txwi); -static void -mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) -{ - int i; - - for (i = 0; i < txp->nbuf; i++) - dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), - le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); -} - -static void -mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp) -{ - u32 last_mask; - int i; - - last_mask = is_mt7663(dev) ? MT_TXD_LEN_LAST : MT_TXD_LEN_MSDU_LAST; - - for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { - struct mt7615_txp_ptr *ptr = &txp->ptr[i]; - bool last; - u16 len; - - len = le16_to_cpu(ptr->len0); - last = len & last_mask; - len &= MT_TXD_LEN_MASK; - dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, - DMA_TO_DEVICE); - if (last) - break; - - len = le16_to_cpu(ptr->len1); - last = len & last_mask; - len &= MT_TXD_LEN_MASK; - dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, - DMA_TO_DEVICE); - if (last) - break; - } -} - -void mt7615_txp_skb_unmap(struct mt76_dev *dev, - struct mt76_txwi_cache *t) -{ - struct mt7615_txp_common *txp; - - txp = mt7615_txwi_to_txp(dev, t); - if (is_mt7615(dev)) - mt7615_txp_skb_unmap_fw(dev, &txp->fw); - else - mt7615_txp_skb_unmap_hw(dev, &txp->hw); -} -EXPORT_SYMBOL_GPL(mt7615_txp_skb_unmap); - bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, @@ -1031,7 +1090,7 @@ u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid) offset %= 32; val = mt76_rr(dev, addr); - val >>= (tid % 32); + val >>= offset; if (offset > 20) { addr += 4; @@ -1320,7 +1379,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, } rate_set_tsf = READ_ONCE(sta->rate_set_tsf); - rs_idx = !((u32)(FIELD_GET(MT_TXS4_F0_TIMESTAMP, le32_to_cpu(txs_data[4])) - + rs_idx = !((u32)(le32_get_bits(txs_data[4], MT_TXS4_F0_TIMESTAMP) - rate_set_tsf) < 1000000); rs_idx ^= rate_set_tsf & BIT(0); rs = &sta->rateset[rs_idx]; @@ -1332,8 +1391,8 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, if (sta->rate_probe) { struct mt7615_phy *phy = &dev->phy; - if (sta->wcid.ext_phy && dev->mt76.phy2) - phy = dev->mt76.phy2->priv; + if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1]) + phy = dev->mt76.phys[MT_BAND1]->priv; mt7615_mac_set_rates(phy, sta, NULL, sta->rates); } @@ -1375,8 +1434,8 @@ out: fallthrough; case MT_PHY_TYPE_OFDM: mphy = &dev->mphy; - if (sta->wcid.ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; @@ -1451,14 +1510,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) struct mt76_wcid *wcid; struct mt76_phy *mphy = &dev->mt76.phy; __le32 *txs_data = data; - u32 txs; u8 wcidx; u8 pid; - txs = le32_to_cpu(txs_data[0]); - pid = FIELD_GET(MT_TXS0_PID, txs); - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); + pid = le32_get_bits(txs_data[0], MT_TXS0_PID); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); if (pid == MT_PACKET_ID_NO_ACK) return; @@ -1486,8 +1542,8 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (wcidx >= MT7615_WTBL_STA || !sta) goto out; - if (wcid->ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (wcid->phy_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; if (mt7615_fill_txs(dev, msta, &info, txs_data)) ieee80211_tx_status_noskb(mphy->hw, sta, &info); @@ -1504,7 +1560,7 @@ mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi) u32 val; u8 wcid; - mt7615_txp_skb_unmap(mdev, txwi); + mt76_connac_txp_skb_unmap(mdev, txwi); if (!txwi->skb) goto out; @@ -1532,9 +1588,11 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) mt7615_txwi_free(dev, txwi); } -static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) +static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len) { - struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; + struct mt76_connac_tx_free *free = data; + void *tx_token = data + sizeof(*free); + void *end = data + len; u8 i, count; mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); @@ -1545,21 +1603,25 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); } - count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); + count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT); if (is_mt7615(&dev->mt76)) { - __le16 *token = &free->token[0]; + __le16 *token = tx_token; + + if (WARN_ON_ONCE((void *)&token[count] > end)) + return; for (i = 0; i < count; i++) mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i])); } else { - __le32 *token = (__le32 *)&free->token[0]; + __le32 *token = tx_token; + + if (WARN_ON_ONCE((void *)&token[count] > end)) + return; for (i = 0; i < count; i++) mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i])); } - dev_kfree_skb(skb); - rcu_read_lock(); mt7615_mac_sta_poll(dev); rcu_read_unlock(); @@ -1567,6 +1629,29 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) mt76_worker_schedule(&dev->mt76.tx_worker); } +bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + __le32 *rxd = (__le32 *)data; + __le32 *end = (__le32 *)&rxd[len / 4]; + enum rx_pkt_type type; + + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + mt7615_mac_tx_free(dev, data, len); + return false; + case PKT_TYPE_TXS: + for (rxd++; rxd + 7 <= end; rxd += 7) + mt7615_mac_add_txs(dev, rxd); + return false; + default: + return true; + } +} +EXPORT_SYMBOL_GPL(mt7615_rx_check); + void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb) { @@ -1576,8 +1661,8 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, enum rx_pkt_type type; u16 flag; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); - flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG); if (type == PKT_TYPE_RX_EVENT && flag == 0x1) type = PKT_TYPE_NORMAL_MCU; @@ -1588,7 +1673,8 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, dev_kfree_skb(skb); break; case PKT_TYPE_TXRX_NOTIFY: - mt7615_mac_tx_free(dev, skb); + mt7615_mac_tx_free(dev, skb->data, skb->len); + dev_kfree_skb(skb); break; case PKT_TYPE_RX_EVENT: mt7615_mcu_rx_event(dev, skb); @@ -1725,7 +1811,7 @@ mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, struct mt7615_dev *dev = phy->dev; int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck; bool ext_phy = phy != &dev->phy; - u16 def_th = ofdm ? -98 : -110; + s16 def_th = ofdm ? -98 : -110; bool update = false; s8 *sensitivity; int signal; @@ -1874,6 +1960,7 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) static void mt7615_update_survey(struct mt7615_dev *dev) { struct mt76_dev *mdev = &dev->mt76; + struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1]; ktime_t cur_time; /* MT7615 can only update both phys simultaneously @@ -1881,14 +1968,14 @@ static void mt7615_update_survey(struct mt7615_dev *dev) */ mt7615_phy_update_channel(&mdev->phy, 0); - if (mdev->phy2) - mt7615_phy_update_channel(mdev->phy2, 1); + if (mphy_ext) + mt7615_phy_update_channel(mphy_ext, 1); cur_time = ktime_get_boottime(); mt76_update_survey_active_time(&mdev->phy, cur_time); - if (mdev->phy2) - mt76_update_survey_active_time(mdev->phy2, cur_time); + if (mphy_ext) + mt76_update_survey_active_time(mphy_ext, cur_time); /* reset obss airtime */ mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); @@ -1958,10 +2045,13 @@ void mt7615_pm_wake_work(struct work_struct *work) int i; if (mt76_is_sdio(mdev)) { + mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); mt76_worker_schedule(&mdev->sdio.txrx_worker); } else { + local_bh_disable(); mt76_for_each_q_rx(mdev, i) napi_schedule(&mdev->napi[i]); + local_bh_enable(); mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM], false); @@ -1993,6 +2083,14 @@ void mt7615_pm_power_save_work(struct work_struct *work) test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state)) goto out; + if (mutex_is_locked(&dev->mt76.mutex)) + /* if mt76 mutex is held we should not put the device + * to sleep since we are currently accessing device + * register map. We need to wait for the next power_save + * trigger. + */ + goto out; + if (time_is_after_jiffies(dev->pm.last_activity + delta)) { delta = dev->pm.last_activity + delta - jiffies; goto out; @@ -2050,21 +2148,24 @@ static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) struct mt7615_dev *dev = phy->dev; if (phy->rdd_state & BIT(0)) - mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0, + MT_RX_SEL0, 0); if (phy->rdd_state & BIT(1)) - mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1, + MT_RX_SEL0, 0); } static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) { int err; - err = mt7615_mcu_rdd_cmd(dev, RDD_START, chain, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain, + MT_RX_SEL0, 0); if (err < 0) return err; - return mt7615_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, - MT_RX_SEL0, 1); + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain, + MT_RX_SEL0, 1); } static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) @@ -2075,7 +2176,8 @@ static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) int err; /* start CAC */ - err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, ext_phy, + MT_RX_SEL0, 0); if (err < 0) return err; @@ -2139,47 +2241,58 @@ int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) struct cfg80211_chan_def *chandef = &phy->mt76->chandef; struct mt7615_dev *dev = phy->dev; bool ext_phy = phy != &dev->phy; + enum mt76_dfs_state dfs_state, prev_state; int err; if (is_mt7663(&dev->mt76)) return 0; - if (dev->mt76.region == NL80211_DFS_UNSET) { - phy->dfs_state = -1; - if (phy->rdd_state) - goto stop; + prev_state = phy->mt76->dfs_state; + dfs_state = mt76_phy_dfs_state(phy->mt76); + if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && + dfs_state < MT_DFS_STATE_CAC) + dfs_state = MT_DFS_STATE_ACTIVE; + if (prev_state == dfs_state) return 0; - } - if (test_bit(MT76_SCANNING, &phy->mt76->state)) - return 0; + if (dfs_state == MT_DFS_STATE_DISABLED) + goto stop; - if (phy->dfs_state == chandef->chan->dfs_state) - return 0; + if (prev_state <= MT_DFS_STATE_DISABLED) { + err = mt7615_dfs_init_radar_specs(phy); + if (err < 0) + return err; - err = mt7615_dfs_init_radar_specs(phy); - if (err < 0) { - phy->dfs_state = -1; - goto stop; - } + err = mt7615_dfs_start_radar_detector(phy); + if (err < 0) + return err; - phy->dfs_state = chandef->chan->dfs_state; + phy->mt76->dfs_state = MT_DFS_STATE_CAC; + } - if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { - if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) - return mt7615_dfs_start_radar_detector(phy); + if (dfs_state == MT_DFS_STATE_CAC) + return 0; - return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, - MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, + ext_phy, MT_RX_SEL0, 0); + if (err < 0) { + phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; + return err; } + phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; + return 0; + stop: - err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, ext_phy, + MT_RX_SEL0, 0); if (err < 0) return err; mt7615_dfs_stop_radar_detector(phy); + phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 46f283eb8d0f..880c9f74a7f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -86,6 +86,8 @@ enum rx_pkt_type { #define MT_RXD6_SEQ_CTRL GENMASK(15, 0) #define MT_RXD6_QOS_CTL GENMASK(31, 16) +#define MT_RXD7_HT_CONTROL GENMASK(31, 0) + #define MT_RXV1_ACID_DET_H BIT(31) #define MT_RXV1_ACID_DET_L BIT(30) #define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24) @@ -163,12 +165,6 @@ enum tx_phy_bandwidth { #define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) #define MT_CT_INFO_HSR2_TX BIT(4) -#define MT_TXD_SIZE (8 * 4) - -#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4) -#define MT_USB_HDR_SIZE 4 -#define MT_USB_TAIL_SIZE 4 - #define MT_TXD0_P_IDX BIT(31) #define MT_TXD0_Q_IDX GENMASK(30, 26) #define MT_TXD0_UDP_TCP_SUM BIT(24) @@ -248,56 +244,6 @@ enum tx_phy_bandwidth { #define MT_TX_RATE_MODE GENMASK(8, 6) #define MT_TX_RATE_IDX GENMASK(5, 0) -#define MT_TXP_MAX_BUF_NUM 6 -#define MT_HW_TXP_MAX_MSDU_NUM 4 -#define MT_HW_TXP_MAX_BUF_NUM 4 - -#define MT_MSDU_ID_VALID BIT(15) - -#define MT_TXD_LEN_MASK GENMASK(11, 0) -#define MT_TXD_LEN_MSDU_LAST BIT(14) -#define MT_TXD_LEN_AMSDU_LAST BIT(15) -/* mt7663 */ -#define MT_TXD_LEN_LAST BIT(15) - -struct mt7615_txp_ptr { - __le32 buf0; - __le16 len0; - __le16 len1; - __le32 buf1; -} __packed __aligned(4); - -struct mt7615_hw_txp { - __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; - struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; -} __packed __aligned(4); - -struct mt7615_fw_txp { - __le16 flags; - __le16 token; - u8 bss_idx; - u8 rept_wds_wcid; - u8 rsv; - u8 nbuf; - __le32 buf[MT_TXP_MAX_BUF_NUM]; - __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed __aligned(4); - -struct mt7615_txp_common { - union { - struct mt7615_fw_txp fw; - struct mt7615_hw_txp hw; - }; -}; - -struct mt7615_tx_free { - __le16 rx_byte_cnt; - __le16 ctrl; - u8 txd_cnt; - u8 rsv[3]; - __le16 token[]; -} __packed __aligned(4); - #define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0) #define MT_TXS0_PID GENMASK(31, 24) @@ -383,19 +329,6 @@ struct mt7615_dfs_radar_spec { struct mt7615_dfs_pattern radar_pattern[16]; }; -static inline struct mt7615_txp_common * -mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - u8 *txwi; - - if (!t) - return NULL; - - txwi = mt76_get_txwi_ptr(dev, t); - - return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE); -} - static inline u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid) { return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 890d9b07e156..8d4733f87cda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -73,7 +73,7 @@ static int mt7615_start(struct ieee80211_hw *hw) goto out; } - ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); if (ret) goto out; @@ -141,9 +141,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) if (i) return i - 1; - if (type != NL80211_IFTYPE_STATION) - break; - /* next, try to find a free repeater entry for the sta */ i = get_free_idx(mask >> REPEATER_BSSID_START, 0, REPEATER_BSSID_MAX - REPEATER_BSSID_START); @@ -197,7 +194,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, is_zero_ether_addr(vif->addr)) phy->monitor_vif = vif; - mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); if (mvif->mt76.idx >= MT7615_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -211,13 +208,11 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, mvif->mt76.omac_idx = idx; mvif->mt76.band_idx = ext_phy; - if (mt7615_ext_phy(dev)) - mvif->mt76.wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) + - mvif->mt76.idx % (MT7615_MAX_WMM_SETS / 2); - else - mvif->mt76.wmm_idx = mvif->mt76.idx % MT7615_MAX_WMM_SETS; + mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; + if (ext_phy) + mvif->mt76.wmm_idx += 2; - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); @@ -229,7 +224,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.ext_phy = mvif->mt76.band_idx; + mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; mt76_packet_id_init(&mvif->sta.wcid); @@ -239,7 +234,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } ret = mt7615_mcu_add_dev_info(phy, vif, true); @@ -273,7 +268,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); @@ -287,25 +282,6 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); } -static void mt7615_init_dfs_state(struct mt7615_phy *phy) -{ - struct mt76_phy *mphy = phy->mt76; - struct ieee80211_hw *hw = mphy->hw; - struct cfg80211_chan_def *chandef = &hw->conf.chandef; - - if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) - return; - - if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) - return; - - if (mphy->chandef.chan->center_freq == chandef->chan->center_freq && - mphy->chandef.width == chandef->width) - return; - - phy->dfs_state = -1; -} - int mt7615_set_channel(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; @@ -318,7 +294,6 @@ int mt7615_set_channel(struct mt7615_phy *phy) set_bit(MT76_RESET, &phy->mt76->state); - mt7615_init_dfs_state(phy); mt76_set_channel(phy->mt76); if (is_mt7615(&dev->mt76) && dev->flash_eeprom) { @@ -331,7 +306,7 @@ int mt7615_set_channel(struct mt7615_phy *phy) goto out; } - ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH)); if (ret) goto out; @@ -370,6 +345,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; @@ -408,6 +384,11 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt7615_mutex_acquire(dev); + if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) { + mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); + mt7615_mcu_add_bss_info(phy, vif, NULL, true); + } + if (cmd == SET_KEY) *wcid_keyidx = idx; else if (idx == *wcid_keyidx) @@ -429,6 +410,29 @@ out: return err; } +static int mt7615_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int err; + + if (!cfg80211_chandef_valid(&phy->mt76->chandef)) + return -EINVAL; + + err = mt76_init_sar_power(hw, sar); + if (err) + return err; + + if (mt7615_firmware_offload(phy->dev)) + return mt76_connac_mcu_set_rate_txpower(phy->mt76); + + ieee80211_stop_queues(hw); + err = mt7615_set_channel(phy); + ieee80211_wake_queues(hw); + + return err; +} + static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { struct mt7615_dev *dev = mt7615_hw_dev(hw); @@ -469,7 +473,8 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) } static int -mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; @@ -551,7 +556,7 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); @@ -591,7 +596,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ASSOC) - mt7615_mac_set_beacon_filter(phy, vif, info->assoc); + mt7615_mac_set_beacon_filter(phy, vif, vif->cfg.assoc); mt7615_mutex_release(dev); } @@ -625,7 +630,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; - msta->wcid.ext_phy = mvif->mt76.band_idx; + msta->wcid.phy_idx = mvif->mt76.band_idx; phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy; err = mt76_connac_pm_wake(phy->mt76, &dev->pm); @@ -688,6 +693,9 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); int i; + if (!sta_rates) + return; + spin_lock_bh(&dev->mt76.lock); for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { msta->rates[i].idx = sta_rates->rate[i].idx; @@ -1187,12 +1195,16 @@ static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw, struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + mt7615_mutex_acquire(dev); + if (enabled) set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); else clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); mt7615_mcu_set_sta_decap_offload(dev, vif, sta); + + mt7615_mutex_release(dev); } #ifdef CONFIG_PM @@ -1328,6 +1340,7 @@ const struct ieee80211_ops mt7615_ops = { .set_wakeup = mt7615_set_wakeup, .set_rekey_data = mt7615_set_rekey_data, #endif /* CONFIG_PM */ + .set_sar_specs = mt7615_set_sar_specs, }; EXPORT_SYMBOL_GPL(mt7615_ops); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 25f9cbe2cd61..3dac76e6df4d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -40,18 +40,6 @@ struct mt7615_fw_trailer { #define FW_START_DLYCAL BIT(1) #define FW_START_WORKING_PDA_CR4 BIT(2) -struct mt7663_fw_trailer { - u8 chip_id; - u8 eco_code; - u8 n_region; - u8 format_ver; - u8 format_flag; - u8 reserv[2]; - char fw_ver[10]; - char build_date[15]; - __le32 crc; -} __packed; - struct mt7663_fw_buf { __le32 crc; __le32 d_img_size; @@ -71,23 +59,10 @@ struct mt7663_fw_buf { #define IMG_CRC_LEN 4 -#define FW_FEATURE_SET_ENCRYPT BIT(0) -#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) - -#define DL_MODE_ENCRYPT BIT(0) -#define DL_MODE_KEY_IDX GENMASK(2, 1) -#define DL_MODE_RESET_SEC_IV BIT(3) -#define DL_MODE_WORKING_PDA_CR4 BIT(4) -#define DL_MODE_VALID_RAM_ENTRY BIT(5) -#define DL_MODE_NEED_RSP BIT(31) - -#define FW_START_OVERRIDE BIT(0) -#define FW_START_WORKING_PDA_CR4 BIT(2) - void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, int cmd, int *wait_seq) { - int txd_len, mcu_cmd = cmd & MCU_CMD_MASK; + int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); struct mt7615_uni_txd *uni_txd; struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; @@ -103,10 +78,10 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, if (wait_seq) *wait_seq = seq; - txd_len = cmd & MCU_UNI_PREFIX ? sizeof(*uni_txd) : sizeof(*mcu_txd); + txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd); txd = (__le32 *)skb_push(skb, txd_len); - if (cmd != MCU_CMD_FW_SCATTER) { + if (cmd != MCU_CMD(FW_SCATTER)) { q_idx = MT_TX_MCU_PORT_RX_Q0; pkt_fmt = MT_TX_TYPE_CMD; } else { @@ -124,7 +99,7 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt); txd[1] = cpu_to_le32(val); - if (cmd & MCU_UNI_PREFIX) { + if (cmd & __MCU_CMD_FIELD_UNI) { uni_txd = (struct mt7615_uni_txd *)txd; uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); uni_txd->option = MCU_CMD_UNI_EXT_ACK; @@ -142,28 +117,17 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, mcu_txd->s2d_index = MCU_S2D_H2N; mcu_txd->pkt_type = MCU_PKT_ID; mcu_txd->seq = seq; + mcu_txd->cid = mcu_cmd; + mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd); - switch (cmd & ~MCU_CMD_MASK) { - case MCU_FW_PREFIX: - mcu_txd->set_query = MCU_Q_NA; - mcu_txd->cid = mcu_cmd; - break; - case MCU_CE_PREFIX: - if (cmd & MCU_QUERY_MASK) - mcu_txd->set_query = MCU_Q_QUERY; - else - mcu_txd->set_query = MCU_Q_SET; - mcu_txd->cid = mcu_cmd; - break; - default: - mcu_txd->cid = MCU_CMD_EXT_CID; - if (cmd & MCU_QUERY_PREFIX) + if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) { + if (cmd & __MCU_CMD_FIELD_QUERY) mcu_txd->set_query = MCU_Q_QUERY; else mcu_txd->set_query = MCU_Q_SET; - mcu_txd->ext_cid = mcu_cmd; - mcu_txd->ext_cid_ack = 1; - break; + mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid; + } else { + mcu_txd->set_query = MCU_Q_NA; } } EXPORT_SYMBOL_GPL(mt7615_mcu_fill_msg); @@ -184,42 +148,32 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, if (seq != rxd->seq) return -EAGAIN; - switch (cmd) { - case MCU_CMD_PATCH_SEM_CONTROL: + if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) { skb_pull(skb, sizeof(*rxd) - 4); ret = *skb->data; - break; - case MCU_EXT_CMD_GET_TEMP: + } else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) { skb_pull(skb, sizeof(*rxd)); ret = le32_to_cpu(*(__le32 *)skb->data); - break; - case MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX: + } else if (cmd == MCU_EXT_QUERY(RF_REG_ACCESS)) { skb_pull(skb, sizeof(*rxd)); ret = le32_to_cpu(*(__le32 *)&skb->data[8]); - break; - case MCU_UNI_CMD_DEV_INFO_UPDATE: - case MCU_UNI_CMD_BSS_INFO_UPDATE: - case MCU_UNI_CMD_STA_REC_UPDATE: - case MCU_UNI_CMD_HIF_CTRL: - case MCU_UNI_CMD_OFFLOAD: - case MCU_UNI_CMD_SUSPEND: { + } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) || + cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) || + cmd == MCU_UNI_CMD(STA_REC_UPDATE) || + cmd == MCU_UNI_CMD(HIF_CTRL) || + cmd == MCU_UNI_CMD(OFFLOAD) || + cmd == MCU_UNI_CMD(SUSPEND)) { struct mt7615_mcu_uni_event *event; skb_pull(skb, sizeof(*rxd)); event = (struct mt7615_mcu_uni_event *)skb->data; ret = le32_to_cpu(event->status); - break; - } - case MCU_CMD_REG_READ: { + } else if (cmd == MCU_CE_QUERY(REG_READ)) { struct mt7615_mcu_reg_event *event; skb_pull(skb, sizeof(*rxd)); event = (struct mt7615_mcu_reg_event *)skb->data; ret = (int)le32_to_cpu(event->val); - break; - } - default: - break; } return ret; @@ -253,8 +207,7 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg) .address = cpu_to_le32(reg), }; - return mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS), &req, sizeof(req), true); } @@ -270,8 +223,8 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) .data = cpu_to_le32(val), }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_REG_ACCESS, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS), + &req, sizeof(req), false); } void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) @@ -385,10 +338,11 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) } mt7622_trigger_hif_int(dev, false); - - pm->stats.last_doze_event = jiffies; - pm->stats.awake_time += pm->stats.last_doze_event - - pm->stats.last_wake_event; + if (!err) { + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; + } out: mutex_unlock(&pm->mutex); @@ -398,7 +352,7 @@ out: static void mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (vif->csa_active) + if (vif->bss_conf.csa_active) ieee80211_csa_finish(vif); } @@ -415,7 +369,7 @@ mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb) return; if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx)) - mphy = dev->mt76.phy2; + mphy = dev->mt76.phys[MT_BAND1]; ieee80211_iterate_active_interfaces_atomic(mphy->hw, IEEE80211_IFACE_ITER_RESUME_ALL, @@ -434,8 +388,11 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) !r->constant_prf_detected && !r->staggered_prf_detected) return; - if (r->band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (r->band_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; + + if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC) + return; ieee80211_radar_detected(mphy->hw); dev->hw_pattern++; @@ -491,8 +448,8 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb) struct mt7615_phy *phy; struct mt76_phy *mphy; - if (*seq_num & BIT(7) && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; else mphy = &dev->mt76.phy; @@ -517,8 +474,8 @@ mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb) skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); event = (struct mt7615_roc_tlv *)skb->data; - if (event->dbdc_band && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (event->dbdc_band && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; else mphy = &dev->mt76.phy; @@ -542,8 +499,8 @@ mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb) skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); event = (struct mt76_connac_beacon_loss_event *)skb->data; - if (band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (band_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; else mphy = &dev->mt76.phy; @@ -563,8 +520,8 @@ mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb) skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); event = (struct mt76_connac_mcu_bss_event *)skb->data; - if (band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if (band_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; else mphy = &dev->mt76.phy; @@ -658,8 +615,8 @@ mt7615_mcu_muar_config(struct mt7615_dev *dev, struct ieee80211_vif *vif, if (enable) ether_addr_copy(req.addr, addr); - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE), + &req, sizeof(req), true); } static int @@ -702,7 +659,7 @@ mt7615_mcu_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif, return mt7615_mcu_muar_config(dev, vif, false, enable); memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DEV_INFO_UPDATE), &data, sizeof(data), true); } @@ -741,7 +698,7 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, if (!enable) goto out; - skb = ieee80211_beacon_get_template(hw, vif, &offs); + skb = ieee80211_beacon_get_template(hw, vif, &offs, 0); if (!skb) return -EINVAL; @@ -751,13 +708,11 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, return -EINVAL; } - if (mvif->mt76.band_idx) { - info = IEEE80211_SKB_CB(skb); - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - } + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mvif->mt76.band_idx); mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, - 0, NULL, true); + 0, NULL, 0, true); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); @@ -771,152 +726,14 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, dev_kfree_skb(skb); out: - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(BCN_OFFLOAD), &req, sizeof(req), true); } static int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) { -#define ENTER_PM_STATE 1 -#define EXIT_PM_STATE 2 - struct { - u8 pm_number; - u8 pm_state; - u8 bssid[ETH_ALEN]; - u8 dtim_period; - u8 wlan_idx; - __le16 bcn_interval; - __le32 aid; - __le32 rx_filter; - u8 band_idx; - u8 rsv[3]; - __le32 feature; - u8 omac_idx; - u8 wmm_idx; - u8 bcn_loss_cnt; - u8 bcn_sp_duration; - } __packed req = { - .pm_number = 5, - .pm_state = state ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = band, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, - sizeof(req), true); -} - -static int -mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, struct mt7615_phy *phy, - bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; - struct bss_info_basic *bss; - u8 wlan_idx = mvif->sta.wcid.idx; - struct tlv *tlv; - - tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MONITOR: - break; - case NL80211_IFTYPE_STATION: - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ - if (enable && sta) { - struct mt7615_sta *msta; - - msta = (struct mt7615_sta *)sta->drv_priv; - wlan_idx = msta->wcid.idx; - } - break; - case NL80211_IFTYPE_ADHOC: - type = NETWORK_IBSS; - break; - default: - WARN_ON(1); - break; - } - - bss = (struct bss_info_basic *)tlv; - bss->network_type = cpu_to_le32(type); - bss->bmc_tx_wlan_idx = wlan_idx; - bss->wmm_idx = mvif->mt76.wmm_idx; - bss->active = enable; - - if (vif->type != NL80211_IFTYPE_MONITOR) { - memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); - bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - bss->dtim_period = vif->bss_conf.dtim_period; - } else { - memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); - } - - return 0; -} - -static void -mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - u8 omac_idx = mvif->mt76.omac_idx; - struct bss_info_omac *omac; - struct tlv *tlv; - u32 type = 0; - - tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); - - switch (vif->type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - if (vif->p2p) - type = CONNECTION_P2P_GO; - else - type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: - if (vif->p2p) - type = CONNECTION_P2P_GC; - else - type = CONNECTION_INFRA_STA; - break; - case NL80211_IFTYPE_ADHOC: - type = CONNECTION_IBSS_ADHOC; - break; - default: - WARN_ON(1); - break; - } - - omac = (struct bss_info_omac *)tlv; - omac->conn_type = cpu_to_le32(type); - omac->omac_idx = mvif->mt76.omac_idx; - omac->band_idx = mvif->mt76.band_idx; - omac->hw_bss_idx = omac_idx > EXT_BSSID_START ? HW_BSSID_0 : omac_idx; -} - -/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ -#define BCN_TX_ESTIMATE_TIME (4096 + 20) -static void -mt7615_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7615_vif *mvif) -{ - struct bss_info_ext_bss *ext; - int ext_bss_idx, tsf_offset; - struct tlv *tlv; - - ext_bss_idx = mvif->mt76.omac_idx - EXT_BSSID_START; - if (ext_bss_idx < 0) - return; - - tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); - - ext = (struct bss_info_ext_bss *)tlv; - tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); + return mt76_connac_mcu_set_pm(&dev->mt76, band, state); } static int @@ -935,16 +752,17 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, return PTR_ERR(skb); if (enable) - mt7615_mcu_bss_omac_tlv(skb, vif); + mt76_connac_mcu_bss_omac_tlv(skb, vif); - mt7615_mcu_bss_basic_tlv(skb, vif, sta, phy, enable); + mt76_connac_mcu_bss_basic_tlv(skb, vif, sta, phy->mt76, + mvif->sta.wcid.idx, enable); if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START && mvif->mt76.omac_idx < REPEATER_BSSID_START) - mt7615_mcu_bss_ext_tlv(skb, mvif); + mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76); return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_BSS_INFO_UPDATE, true); + MCU_EXT_CMD(BSS_INFO_UPDATE), true); } static int @@ -966,8 +784,8 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, true, NULL, wtbl_hdr); - err = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, - true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(WTBL_UPDATE), true); if (err < 0) return err; @@ -979,7 +797,7 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, mt76_connac_mcu_sta_ba_tlv(skb, params, enable, true); return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + MCU_EXT_CMD(STA_REC_UPDATE), true); } static int @@ -1001,7 +819,7 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false); err = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + MCU_EXT_CMD(STA_REC_UPDATE), true); if (err < 0 || !enable) return err; @@ -1014,8 +832,8 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false, NULL, wtbl_hdr); - return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, - true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(WTBL_UPDATE), true); } static int @@ -1027,6 +845,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct mt7615_dev *dev = phy->dev; struct wtbl_req_hdr *wtbl_hdr; struct mt7615_sta *msta; + bool new_entry = true; int cmd, err; msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; @@ -1036,7 +855,13 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, if (IS_ERR(sskb)) return PTR_ERR(sskb); - mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true); + if (!sta) { + if (mvif->sta_added) + new_entry = false; + else + mvif->sta_added = true; + } + mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry); if (enable && sta) mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0, MT76_STA_INFO_STATE_ASSOC); @@ -1052,12 +877,12 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, NULL, wtbl_hdr); if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta, - NULL, wtbl_hdr); + NULL, wtbl_hdr, true, true); mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid, NULL, wtbl_hdr); } - cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; + cmd = enable ? MCU_EXT_CMD(WTBL_UPDATE) : MCU_EXT_CMD(STA_REC_UPDATE); skb = enable ? wskb : sskb; err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); @@ -1068,7 +893,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, return err; } - cmd = enable ? MCU_EXT_CMD_STA_REC_UPDATE : MCU_EXT_CMD_WTBL_UPDATE; + cmd = enable ? MCU_EXT_CMD(STA_REC_UPDATE) : MCU_EXT_CMD(WTBL_UPDATE); skb = enable ? sskb : wskb; return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); @@ -1079,19 +904,7 @@ mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sk_buff *skb = NULL; - - wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, - WTBL_SET, NULL, &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, &msta->wcid, NULL, - wtbl_hdr); - return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, - true); + return mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } static const struct mt7615_mcu_ops wtbl_update_ops = { @@ -1136,7 +949,7 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev, sta_wtbl, wtbl_hdr); return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + MCU_EXT_CMD(STA_REC_UPDATE), true); } static int @@ -1179,7 +992,7 @@ mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable) { return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable, - MCU_EXT_CMD_STA_REC_UPDATE, false); + MCU_EXT_CMD(STA_REC_UPDATE), false); } static int @@ -1191,7 +1004,7 @@ mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev, return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, - MCU_EXT_CMD_STA_REC_UPDATE); + MCU_EXT_CMD(STA_REC_UPDATE)); } static const struct mt7615_mcu_ops sta_update_ops = { @@ -1260,7 +1073,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, if (!enable) goto out; - skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0); if (!skb) return -EINVAL; @@ -1271,7 +1084,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, } mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb, - wcid, NULL, 0, NULL, true); + wcid, NULL, 0, NULL, 0, true); memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len); req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); @@ -1285,7 +1098,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, dev_kfree_skb(skb); out: - return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), &req, sizeof(req), true); } @@ -1314,7 +1127,7 @@ mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable) { return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable, - MCU_UNI_CMD_STA_REC_UPDATE, true); + MCU_UNI_CMD(STA_REC_UPDATE), true); } static int @@ -1325,7 +1138,8 @@ mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev, struct mt7615_sta *sta = (struct mt7615_sta *)params->sta->drv_priv; return mt76_connac_mcu_sta_ba(&dev->mt76, &sta->vif->mt76, params, - enable, true); + MCU_UNI_CMD(STA_REC_UPDATE), enable, + true); } static int @@ -1348,7 +1162,7 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false); err = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + MCU_UNI_CMD(STA_REC_UPDATE), true); if (err < 0 || !enable) return err; @@ -1369,7 +1183,7 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, sta_wtbl, wtbl_hdr); return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + MCU_UNI_CMD(STA_REC_UPDATE), true); } static int @@ -1381,7 +1195,7 @@ mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev, return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, - MCU_UNI_CMD_STA_REC_UPDATE); + MCU_UNI_CMD(STA_REC_UPDATE)); } static const struct mt7615_mcu_ops uni_update_ops = { @@ -1399,7 +1213,7 @@ static const struct mt7615_mcu_ops uni_update_ops = { int mt7615_mcu_restart(struct mt76_dev *dev) { - return mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, 0, true); + return mt76_mcu_send_msg(dev, MCU_CMD(RESTART_DL_REQ), NULL, 0, true); } EXPORT_SYMBOL_GPL(mt7615_mcu_restart); @@ -1445,7 +1259,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) goto out; } - ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER), fw->data + sizeof(*hdr), len); if (ret) { dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); @@ -1473,20 +1287,6 @@ release_fw: return ret; } -static u32 mt7615_mcu_gen_dl_mode(u8 feature_set, bool is_cr4) -{ - u32 ret = 0; - - ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? - (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; - ret |= FIELD_PREP(DL_MODE_KEY_IDX, - FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); - ret |= DL_MODE_NEED_RSP; - ret |= is_cr4 ? DL_MODE_WORKING_PDA_CR4 : 0; - - return ret; -} - static int mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, const struct mt7615_fw_trailer *hdr, @@ -1497,7 +1297,8 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, u32 len, addr, mode; for (i = 0; i < n_region; i++) { - mode = mt7615_mcu_gen_dl_mode(hdr[i].feature_set, is_cr4); + mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, + hdr[i].feature_set, is_cr4); len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN; addr = le32_to_cpu(hdr[i].addr); @@ -1508,7 +1309,7 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, return err; } - err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER), data + offset, len); if (err) { dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); @@ -1644,7 +1445,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) if (!mt76_poll_msec(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE, FIELD_PREP(MT_TOP_MISC2_FW_STATE, - FW_STATE_CR4_RDY), 500)) { + FW_STATE_RDY), 500)) { dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); return -EIO; } @@ -1694,8 +1495,8 @@ int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) .ctrl_val = ctrl }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, &data, - sizeof(data), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST), + &data, sizeof(data), true); } static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev) @@ -1707,14 +1508,14 @@ static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev) .cache_enable = true }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CAL_CACHE, &data, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CAL_CACHE), &data, sizeof(data), false); } static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) { u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL; - const struct mt7663_fw_trailer *hdr; + const struct mt76_connac2_fw_trailer *hdr; const struct mt7663_fw_buf *buf; const struct firmware *fw; const u8 *base_addr; @@ -1730,9 +1531,7 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) goto out; } - hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size - - FW_V3_COMMON_TAILER_SIZE); - + hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE); dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n", hdr->fw_ver, hdr->build_date); dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region); @@ -1745,7 +1544,8 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i); buf = (const struct mt7663_fw_buf *)(base_addr - shift); - mode = mt7615_mcu_gen_dl_mode(buf->feature_set, false); + mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, + buf->feature_set, false); addr = le32_to_cpu(buf->img_dest_addr); len = le32_to_cpu(buf->img_size); @@ -1756,7 +1556,7 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) goto out; } - ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER), fw->data + offset, len); if (ret) { dev_err(dev->mt76.dev, "Failed to send firmware\n"); @@ -1977,7 +1777,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) skb_put_data(skb, eep + offset, eep_len); return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); + MCU_EXT_CMD(EFUSE_BUFFER_MODE), true); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -2013,8 +1813,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, if (params->cw_max) req.cw_max = cpu_to_le16(fls(params->cw_max)); - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE), + &req, sizeof(req), true); } int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) @@ -2072,7 +1872,7 @@ int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1); out: - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, &req, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DBDC_CTRL), &req, sizeof(req), true); } @@ -2082,29 +1882,8 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) .operation = WTBL_RESET_ALL, }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, - sizeof(req), true); -} - -int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, - enum mt7615_rdd_cmd cmd, u8 index, - u8 rx_sel, u8 val) -{ - struct { - u8 ctrl; - u8 rdd_idx; - u8 rdd_rx_sel; - u8 val; - u8 rsv[4]; - } req = { - .ctrl = cmd, - .rdd_idx = index, - .rdd_rx_sel = rx_sel, - .val = val, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(WTBL_UPDATE), + &req, sizeof(req), true); } int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) @@ -2117,8 +1896,8 @@ int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) .min_lpn = cpu_to_le16(val), }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH), + &req, sizeof(req), true); } int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, @@ -2146,8 +1925,8 @@ int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, #undef __req_field }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH), + &req, sizeof(req), true); } int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, @@ -2193,8 +1972,8 @@ int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, #undef __req_field_u32 }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH), + &req, sizeof(req), true); } int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) @@ -2225,7 +2004,7 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) req.pattern[i].start_time = cpu_to_le32(ts); } - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_PATTERN), &req, sizeof(req), false); } @@ -2236,7 +2015,7 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) struct mt76_power_limits limits; s8 *limits_array = (s8 *)&limits; int n_chains = hweight8(mphy->antenna_mask); - int tx_power; + int tx_power = hw->conf.power_level * 2; int i; static const u8 sku_mapping[] = { #define SKU_FIELD(_type, _field) \ @@ -2293,9 +2072,8 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) #undef SKU_FIELD }; - tx_power = hw->conf.power_level * 2 - - mt76_tx_power_nss_delta(n_chains); - + tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power); + tx_power -= mt76_tx_power_nss_delta(n_chains); tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, &limits, tx_power); mphy->txpower_cur = tx_power; @@ -2368,10 +2146,13 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + req.switch_reason = CH_SWITCH_NORMAL; + else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; - else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, + NL80211_IFTYPE_AP)) req.switch_reason = CH_SWITCH_DFS; else req.switch_reason = CH_SWITCH_NORMAL; @@ -2394,8 +2175,8 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev) u8 rsv[3]; } req = {}; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), + &req, sizeof(req), true); } int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode, @@ -2415,8 +2196,8 @@ int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode, .value = cpu_to_le32(val), }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), + &req, sizeof(req), false); } int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) @@ -2434,8 +2215,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) }; return mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, - sizeof(req), true); + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), + &req, sizeof(req), true); } static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur) @@ -2547,7 +2328,7 @@ int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy) .bw = mt7615_mcu_chan_bw(chandef), .band = chandef->center_freq1 > 4000, - .dbdc_en = !!dev->mt76.phy2, + .dbdc_en = !!dev->mt76.phys[MT_BAND1], }; u16 center_freq = chandef->center_freq1; int freq_idx; @@ -2574,7 +2355,7 @@ again: out: req.center_freq = cpu_to_le16(center_freq); - ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RXDCOC_CAL, &req, + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RXDCOC_CAL), &req, sizeof(req), true); if ((chandef->width == NL80211_CHAN_WIDTH_80P80 || @@ -2668,7 +2449,7 @@ int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy) .bw = mt7615_mcu_chan_bw(chandef), .band = chandef->center_freq1 > 4000, - .dbdc_en = !!dev->mt76.phy2, + .dbdc_en = !!dev->mt76.phys[MT_BAND1], }; u16 center_freq = chandef->center_freq1; int freq_idx; @@ -2695,8 +2476,8 @@ again: out: req.center_freq = cpu_to_le16(center_freq); - ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXDPD_CAL, &req, - sizeof(req), true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXDPD_CAL), + &req, sizeof(req), true); if ((chandef->width == NL80211_CHAN_WIDTH_80P80 || chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) { @@ -2724,7 +2505,7 @@ int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev) .etype = cpu_to_le16(ETH_P_PAE), }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS), &req, sizeof(req), false); } @@ -2744,7 +2525,7 @@ int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, u8 pad; } req = { .bss_idx = mvif->mt76.idx, - .aid = cpu_to_le16(vif->bss_conf.aid), + .aid = cpu_to_le16(vif->cfg.aid), .dtim_period = vif->bss_conf.dtim_period, .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), }; @@ -2759,13 +2540,13 @@ int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, if (vif->type != NL80211_IFTYPE_STATION) return 0; - err = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, &req_hdr, - sizeof(req_hdr), false); + err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT), + &req_hdr, sizeof(req_hdr), false); if (err < 0 || !enable) return err; - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED), + &req, sizeof(req), false); } int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, @@ -2784,6 +2565,6 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, phy->roc_grant = false; - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC), + &req, sizeof(req), false); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 98c383e400a1..615956acc6b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -76,35 +76,6 @@ struct mt7615_uni_txd { u8 reserved2[4]; } __packed __aligned(4); -/* event table */ -enum { - MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, - MCU_EVENT_FW_START = 0x01, - MCU_EVENT_GENERIC = 0x01, - MCU_EVENT_ACCESS_REG = 0x02, - MCU_EVENT_MT_PATCH_SEM = 0x04, - MCU_EVENT_REG_ACCESS = 0x05, - MCU_EVENT_SCAN_DONE = 0x0d, - MCU_EVENT_ROC = 0x10, - MCU_EVENT_BSS_ABSENCE = 0x11, - MCU_EVENT_BSS_BEACON_LOSS = 0x13, - MCU_EVENT_CH_PRIVILEGE = 0x18, - MCU_EVENT_SCHED_SCAN_DONE = 0x23, - MCU_EVENT_EXT = 0xed, - MCU_EVENT_RESTART_DL = 0xef, - MCU_EVENT_COREDUMP = 0xf0, -}; - -/* ext event table */ -enum { - MCU_EXT_EVENT_PS_SYNC = 0x5, - MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, - MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, - MCU_EXT_EVENT_ASSERT_DUMP = 0x23, - MCU_EXT_EVENT_RDD_REPORT = 0x3a, - MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, -}; - enum { MT_SKU_CCK_1_2 = 0, MT_SKU_CCK_55_11, @@ -230,23 +201,6 @@ struct mt7615_mcu_rdd_report { } hw_pulse[32]; }; -#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) -#define MCU_PKT_ID 0xa0 - -enum { - MCU_Q_QUERY, - MCU_Q_SET, - MCU_Q_RESERVED, - MCU_Q_NA -}; - -enum { - MCU_S2D_H2N, - MCU_S2D_C2N, - MCU_S2D_H2C, - MCU_S2D_H2CN -}; - enum { MCU_ATE_SET_FREQ_OFFSET = 0xa, MCU_ATE_SET_TX_POWER_CONTROL = 0x15, @@ -281,21 +235,6 @@ struct mt7615_roc_tlv { } __packed; enum { - PATCH_NOT_DL_SEM_FAIL = 0x0, - PATCH_IS_DL = 0x1, - PATCH_NOT_DL_SEM_SUCCESS = 0x2, - PATCH_REL_SEM_SUCCESS = 0x3 -}; - -enum { - FW_STATE_INITIAL = 0, - FW_STATE_FW_DOWNLOAD = 1, - FW_STATE_NORMAL_OPERATION = 2, - FW_STATE_NORMAL_TRX = 3, - FW_STATE_CR4_RDY = 7 -}; - -enum { FW_STATE_PWR_ON = 1, FW_STATE_N9_RDY = 2, }; @@ -312,73 +251,4 @@ enum { __DBDC_TYPE_MAX, }; -struct bss_info_omac { - __le16 tag; - __le16 len; - u8 hw_bss_idx; - u8 omac_idx; - u8 band_idx; - u8 rsv0; - __le32 conn_type; - u32 rsv1; -} __packed; - -struct bss_info_basic { - __le16 tag; - __le16 len; - __le32 network_type; - u8 active; - u8 rsv0; - __le16 bcn_interval; - u8 bssid[ETH_ALEN]; - u8 wmm_idx; - u8 dtim_period; - u8 bmc_tx_wlan_idx; - u8 cipher; /* not used */ - u8 phymode; /* not used */ - u8 rsv1[5]; -} __packed; - -struct bss_info_rf_ch { - __le16 tag; - __le16 len; - u8 pri_ch; - u8 central_ch0; - u8 central_ch1; - u8 bw; -} __packed; - -struct bss_info_ext_bss { - __le16 tag; - __le16 len; - __le32 mbss_tsf_offset; /* in unit of us */ - u8 rsv[8]; -} __packed; - -enum { - BSS_INFO_OMAC, - BSS_INFO_BASIC, - BSS_INFO_RF_CH, /* optional, for BT/LTE coex */ - BSS_INFO_PM, /* sta only */ - BSS_INFO_UAPSD, /* sta only */ - BSS_INFO_ROAM_DETECTION, /* obsoleted */ - BSS_INFO_LQ_RM, /* obsoleted */ - BSS_INFO_EXT_BSS, - BSS_INFO_BMC_INFO, /* for bmc rate control in CR4 */ - BSS_INFO_SYNC_MODE, /* obsoleted */ - BSS_INFO_RA, - BSS_INFO_MAX_NUM -}; - -enum { - CH_SWITCH_NORMAL = 0, - CH_SWITCH_SCAN = 3, - CH_SWITCH_MCC = 4, - CH_SWITCH_DFS = 5, - CH_SWITCH_BACKGROUND_SCAN_START = 6, - CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, - CH_SWITCH_BACKGROUND_SCAN_STOP = 8, - CH_SWITCH_SCAN_BYPASS_DPD = 9 -}; - #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 71719c787511..a784f9d9e935 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -135,6 +135,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t) if (is_mt7663(&dev->mt76)) { mcu_int = mt76_rr(dev, MT_MCU2HOST_INT_STATUS); mcu_int &= MT7663_MCU_CMD_ERROR_MASK; + mt76_wr(dev, MT_MCU2HOST_INT_STATUS, mcu_int); } else { mcu_int = mt76_rr(dev, MT_MCU_CMD); mcu_int &= MT_MCU_CMD_ERROR_MASK; @@ -144,7 +145,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t) return; dev->reset_state = mcu_int; - ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + queue_work(dev->mt76.wq, &dev->reset_work); wake_up(&dev->reset_wait); } @@ -185,14 +186,15 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, { static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), + .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_txp_common), .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, .token_size = MT7615_TOKEN_SIZE, .tx_prepare_skb = mt7615_tx_prepare_skb, - .tx_complete_skb = mt7615_tx_complete_skb, + .tx_complete_skb = mt76_connac_tx_complete_skb, + .rx_check = mt7615_rx_check, .rx_skb = mt7615_queue_rx_skb, .rx_poll_complete = mt7615_rx_poll_complete, .sta_ps = mt7615_sta_ps, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 6ff6d5800918..060d52c81d9e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -141,6 +141,7 @@ struct mt7615_sta { struct mt7615_vif { struct mt76_vif mt76; /* must be first */ struct mt7615_sta sta; + bool sta_added; }; struct mib_stats { @@ -177,7 +178,6 @@ struct mt7615_phy { u8 chfreq; u8 rdd_state; - int dfs_state; u32 rx_ampdu_ts; u32 ampdu_ref; @@ -345,7 +345,7 @@ mt7615_hw_dev(struct ieee80211_hw *hw) static inline struct mt7615_phy * mt7615_ext_phy(struct mt7615_dev *dev) { - struct mt76_phy *phy = dev->mt76.phy2; + struct mt76_phy *phy = dev->mt76.phys[MT_BAND1]; if (!phy) return NULL; @@ -403,30 +403,9 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); -int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, - enum mt7615_rdd_cmd cmd, u8 index, - u8 rx_sel, u8 val); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl); -static inline bool is_mt7622(struct mt76_dev *dev) -{ - if (!IS_ENABLED(CONFIG_MT7622_WMAC)) - return false; - - return mt76_chip(dev) == 0x7622; -} - -static inline bool is_mt7615(struct mt76_dev *dev) -{ - return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; -} - -static inline bool is_mt7611(struct mt76_dev *dev) -{ - return mt76_chip(dev) == 0x7611; -} - static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, 0, 0, mask); @@ -498,7 +477,8 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key, bool beacon); + struct ieee80211_key_conf *key, + enum mt76_txq_id qid, bool beacon); void mt7615_mac_set_timing(struct mt7615_phy *phy); int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, @@ -528,8 +508,8 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info); void mt7615_tx_worker(struct mt76_worker *w); -void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); void mt7615_tx_token_put(struct mt7615_dev *dev); +bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); @@ -538,8 +518,6 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7615_mac_work(struct work_struct *work); -void mt7615_txp_skb_unmap(struct mt76_dev *dev, - struct mt76_txwi_cache *txwi); int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev); int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val); int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, @@ -579,6 +557,7 @@ void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); int mt7663_usb_sdio_register_device(struct mt7615_dev *dev); int mt7663u_mcu_init(struct mt7615_dev *dev); +int mt7663u_mcu_power_on(struct mt7615_dev *dev); /* sdio */ int mt7663s_mcu_init(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index a2465b49ecd0..87b4aa52ee0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -28,8 +28,6 @@ static void mt7615_pci_init_work(struct work_struct *work) return; mt7615_init_work(dev); - if (dev->dbdc_support) - mt7615_register_ext_phy(dev); } static int mt7615_init_hardware(struct mt7615_dev *dev) @@ -160,6 +158,12 @@ int mt7615_register_device(struct mt7615_dev *dev) mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); + if (dev->dbdc_support) { + ret = mt7615_register_ext_phy(dev); + if (ret) + return ret; + } + return mt7615_init_debugfs(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index d1806f198aed..0019890fdb78 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -14,75 +14,6 @@ #include "../dma.h" #include "mac.h" -void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - if (!e->txwi) { - dev_kfree_skb_any(e->skb); - return; - } - - /* error path */ - if (e->skb == DMA_DUMMY_DATA) { - struct mt76_txwi_cache *t; - struct mt7615_dev *dev; - struct mt7615_txp_common *txp; - u16 token; - - dev = container_of(mdev, struct mt7615_dev, mt76); - txp = mt7615_txwi_to_txp(mdev, e->txwi); - - if (is_mt7615(&dev->mt76)) - token = le16_to_cpu(txp->fw.token); - else - token = le16_to_cpu(txp->hw.msdu_id[0]) & - ~MT_MSDU_ID_VALID; - - t = mt76_token_put(mdev, token); - e->skb = t ? t->skb : NULL; - } - - if (e->skb) - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - -static void -mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, - void *txp_ptr, u32 id) -{ - struct mt7615_hw_txp *txp = txp_ptr; - struct mt7615_txp_ptr *ptr = &txp->ptr[0]; - int i, nbuf = tx_info->nbuf - 1; - u32 last_mask; - - tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); - tx_info->nbuf = 1; - - txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); - - if (is_mt7663(&dev->mt76)) - last_mask = MT_TXD_LEN_LAST; - else - last_mask = MT_TXD_LEN_AMSDU_LAST | - MT_TXD_LEN_MSDU_LAST; - - for (i = 0; i < nbuf; i++) { - u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK; - u32 addr = tx_info->buf[i + 1].addr; - - if (i == nbuf - 1) - len |= last_mask; - - if (i & 1) { - ptr->buf1 = cpu_to_le32(addr); - ptr->len1 = cpu_to_le16(len); - ptr++; - } else { - ptr->buf0 = cpu_to_le32(addr); - ptr->len0 = cpu_to_le16(len); - } - } -} - static void mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, void *txp_ptr, u32 id) @@ -91,7 +22,8 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct ieee80211_vif *vif = info->control.vif; - struct mt7615_fw_txp *txp = txp_ptr; + struct mt76_connac_fw_txp *txp = txp_ptr; + u8 *rept_wds_wcid = (u8 *)&txp->rept_wds_wcid; int nbuf = tx_info->nbuf - 1; int i; @@ -122,7 +54,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, } txp->token = cpu_to_le16(id); - txp->rept_wds_wcid = 0xff; + *rept_wds_wcid = 0xff; } int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -145,9 +77,10 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) { struct mt7615_phy *phy = &dev->phy; + u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; - if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2) - phy = mdev->phy2->priv; + if (phy_idx && mdev->phys[MT_BAND1]) + phy = mdev->phys[MT_BAND1]->priv; spin_lock_bh(&dev->mt76.lock); mt7615_mac_set_rates(phy, msta, &info->control.rates[0], @@ -164,14 +97,14 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, - pid, key, false); + pid, key, qid, false); txp = txwi + MT_TXD_SIZE; - memset(txp, 0, sizeof(struct mt7615_txp_common)); + memset(txp, 0, sizeof(struct mt76_connac_txp_common)); if (is_mt7615(&dev->mt76)) mt7615_write_fw_txp(dev, tx_info, txp, id); else - mt7615_write_hw_txp(dev, tx_info, txp, id); + mt76_connac_write_hw_txp(mdev, tx_info, txp, id); tx_info->skb = DMA_DUMMY_DATA; @@ -250,16 +183,18 @@ mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) static void mt7615_update_beacons(struct mt7615_dev *dev) { + struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; + ieee80211_iterate_active_interfaces(dev->mt76.hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7615_update_vif_beacon, dev->mt76.hw); - if (!dev->mt76.phy2) + if (!mphy_ext) return; - ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + ieee80211_iterate_active_interfaces(mphy_ext->hw, IEEE80211_IFACE_ITER_RESUME_ALL, - mt7615_update_vif_beacon, dev->mt76.phy2->hw); + mt7615_update_vif_beacon, mphy_ext->hw); } void mt7615_mac_reset_work(struct work_struct *work) @@ -268,9 +203,10 @@ void mt7615_mac_reset_work(struct work_struct *work) struct mt76_phy *ext_phy; struct mt7615_dev *dev; unsigned long timeout; + int i; dev = container_of(work, struct mt7615_dev, reset_work); - ext_phy = dev->mt76.phy2; + ext_phy = dev->mt76.phys[MT_BAND1]; phy2 = ext_phy ? ext_phy->priv : NULL; if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) @@ -299,8 +235,8 @@ void mt7615_mac_reset_work(struct work_struct *work) mt76_txq_schedule_all(ext_phy); mt76_worker_disable(&dev->mt76.tx_worker); - napi_disable(&dev->mt76.napi[0]); - napi_disable(&dev->mt76.napi[1]); + mt76_for_each_q_rx(&dev->mt76, i) + napi_disable(&dev->mt76.napi[i]); napi_disable(&dev->mt76.tx_napi); mt7615_mutex_acquire(dev); @@ -330,11 +266,10 @@ void mt7615_mac_reset_work(struct work_struct *work) napi_enable(&dev->mt76.tx_napi); napi_schedule(&dev->mt76.tx_napi); - napi_enable(&dev->mt76.napi[0]); - napi_schedule(&dev->mt76.napi[0]); - - napi_enable(&dev->mt76.napi[1]); - napi_schedule(&dev->mt76.napi[1]); + mt76_for_each_q_rx(&dev->mt76, i) { + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); + } local_bh_enable(); ieee80211_wake_queues(mt76_hw(dev)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 31c4a76b7f91..304212f5f8da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -56,7 +56,10 @@ static int mt7663s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr) struct mt7663s_intr *irq_data = sdio->intr_data; int i, err; + sdio_claim_host(sdio->func); err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data)); + sdio_release_host(sdio->func); + if (err) return err; @@ -80,6 +83,7 @@ static int mt7663s_probe(struct sdio_func *func, .tx_complete_skb = mt7663_usb_sdio_tx_complete_skb, .tx_status_data = mt7663_usb_sdio_tx_status_data, .rx_skb = mt7615_queue_rx_skb, + .rx_check = mt7615_rx_check, .sta_ps = mt7615_sta_ps, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, @@ -98,7 +102,7 @@ static int mt7663s_probe(struct sdio_func *func, struct ieee80211_ops *ops; struct mt7615_dev *dev; struct mt76_dev *mdev; - int i, ret; + int ret; ops = devm_kmemdup(&func->dev, &mt7615_ops, sizeof(mt7615_ops), GFP_KERNEL); @@ -137,16 +141,6 @@ static int mt7663s_probe(struct sdio_func *func, goto error; } - for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) { - mdev->sdio.xmit_buf[i] = devm_kmalloc(mdev->dev, - MT76S_XMIT_BUF_SZ, - GFP_KERNEL); - if (!mdev->sdio.xmit_buf[i]) { - ret = -ENOMEM; - goto error; - } - } - ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MAIN); if (ret) goto error; @@ -187,7 +181,6 @@ static void mt7663s_remove(struct sdio_func *func) mt76_free_device(&dev->mt76); } -#ifdef CONFIG_PM static int mt7663s_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); @@ -242,28 +235,20 @@ static int mt7663s_resume(struct device *dev) return err; } -static const struct dev_pm_ops mt7663s_pm_ops = { - .suspend = mt7663s_suspend, - .resume = mt7663s_resume, -}; -#endif - MODULE_DEVICE_TABLE(sdio, mt7663s_table); MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9); MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH); MODULE_FIRMWARE(MT7663_FIRMWARE_N9); MODULE_FIRMWARE(MT7663_ROM_PATCH); +static DEFINE_SIMPLE_DEV_PM_OPS(mt7663s_pm_ops, mt7663s_suspend, mt7663s_resume); + static struct sdio_driver mt7663s_driver = { .name = KBUILD_MODNAME, .probe = mt7663s_probe, .remove = mt7663s_remove, .id_table = mt7663s_table, -#ifdef CONFIG_PM - .drv = { - .pm = &mt7663s_pm_ops, - } -#endif + .drv.pm = pm_sleep_ptr(&mt7663s_pm_ops), }; module_sdio_driver(mt7663s_driver); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c index 59d99264f5e5..a3d1cfa729ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c @@ -91,7 +91,7 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy) } return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_SET_TX_POWER_CTRL, false); + MCU_EXT_CMD(SET_TX_POWER_CTRL), false); } static void @@ -185,36 +185,35 @@ mt7615_tm_set_tx_antenna(struct mt7615_phy *phy, bool en) for (i = 0; i < 4; i++) { mt76_rmw_field(dev, MT_WF_PHY_RFINTF3_0(i), MT_WF_PHY_RFINTF3_0_ANT, - (td->tx_antenna_mask & BIT(i)) ? 0 : 0xa); - + (mask & BIT(i)) ? 0 : 0xa); } /* 2.4 GHz band */ mt76_rmw_field(dev, MT_ANT_SWITCH_CON(3), MT_ANT_SWITCH_CON_MODE(0), - (td->tx_antenna_mask & BIT(0)) ? 0x8 : 0x1b); + (mask & BIT(0)) ? 0x8 : 0x1b); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(4), MT_ANT_SWITCH_CON_MODE(2), - (td->tx_antenna_mask & BIT(1)) ? 0xe : 0x1b); + (mask & BIT(1)) ? 0xe : 0x1b); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(6), MT_ANT_SWITCH_CON_MODE1(0), - (td->tx_antenna_mask & BIT(2)) ? 0x0 : 0xf); + (mask & BIT(2)) ? 0x0 : 0xf); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(7), MT_ANT_SWITCH_CON_MODE1(2), - (td->tx_antenna_mask & BIT(3)) ? 0x6 : 0xf); + (mask & BIT(3)) ? 0x6 : 0xf); /* 5 GHz band */ mt76_rmw_field(dev, MT_ANT_SWITCH_CON(4), MT_ANT_SWITCH_CON_MODE(1), - (td->tx_antenna_mask & BIT(0)) ? 0xd : 0x1b); + (mask & BIT(0)) ? 0xd : 0x1b); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(2), MT_ANT_SWITCH_CON_MODE(3), - (td->tx_antenna_mask & BIT(1)) ? 0x13 : 0x1b); + (mask & BIT(1)) ? 0x13 : 0x1b); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(7), MT_ANT_SWITCH_CON_MODE1(1), - (td->tx_antenna_mask & BIT(2)) ? 0x5 : 0xf); + (mask & BIT(2)) ? 0x5 : 0xf); mt76_rmw_field(dev, MT_ANT_SWITCH_CON(8), MT_ANT_SWITCH_CON_MODE1(3), - (td->tx_antenna_mask & BIT(3)) ? 0xb : 0xf); + (mask & BIT(3)) ? 0xb : 0xf); for (i = 0; i < 4; i++) { u32 val; val = mt7615_rf_rr(dev, i, 0x48); val &= ~(0x3ff << 20); - if (td->tx_antenna_mask & BIT(i)) + if (mask & BIT(i)) val |= 3 << 20; else val |= (2 << 28) | (2 << 26) | (8 << 20); @@ -229,7 +228,7 @@ mt7615_tm_set_tx_frames(struct mt7615_phy *phy, bool en) struct ieee80211_tx_info *info; struct sk_buff *skb = phy->mt76->test.tx_skb; - mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); mt7615_tm_set_tx_antenna(phy, en); mt7615_tm_set_rx_enable(dev, !en); if (!en || !skb) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index 0396ad532ba6..f2d651d7adff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -17,9 +17,68 @@ static const struct usb_device_id mt7615_device_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7663, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x043e, 0x310c, 0xff, 0xff, 0xff) }, { }, }; +static u32 mt7663u_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7663u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static u32 mt7663u_rmw(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + +static void mt7663u_copy(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + static void mt7663u_stop(struct ieee80211_hw *hw) { struct mt7615_phy *phy = mt7615_hw_phy(hw); @@ -60,11 +119,20 @@ static int mt7663u_probe(struct usb_interface *usb_intf, .tx_complete_skb = mt7663_usb_sdio_tx_complete_skb, .tx_status_data = mt7663_usb_sdio_tx_status_data, .rx_skb = mt7615_queue_rx_skb, + .rx_check = mt7615_rx_check, .sta_ps = mt7615_sta_ps, .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, }; + static struct mt76_bus_ops bus_ops = { + .rr = mt7663u_rr, + .wr = mt7663u_wr, + .rmw = mt7663u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt7663u_copy, + .type = MT76_BUS_USB, + }; struct usb_device *udev = interface_to_usbdev(usb_intf); struct ieee80211_ops *ops; struct mt7615_dev *dev; @@ -91,7 +159,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf, INIT_WORK(&dev->mcu_work, mt7663u_init_work); dev->reg_map = mt7663_usb_sdio_reg_map; dev->ops = ops; - ret = mt76u_init(mdev, usb_intf, true); + ret = __mt76u_init(mdev, usb_intf, &bus_ops); if (ret < 0) goto error; @@ -99,27 +167,15 @@ static int mt7663u_probe(struct usb_interface *usb_intf, (mt76_rr(dev, MT_HW_REV) & 0xff); dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - if (mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, - FW_STATE_PWR_ON << 1, 500)) { - dev_dbg(dev->mt76.dev, "Usb device already powered on\n"); - set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state); - goto alloc_queues; - } - - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); - if (ret) - goto error; - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, FW_STATE_PWR_ON << 1, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - ret = -EIO; - goto error; + ret = mt7663u_mcu_power_on(dev); + if (ret) + goto error; + } else { + set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state); } -alloc_queues: ret = mt76u_alloc_mcu_queue(&dev->mt76); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index 028ff432d811..98bf2f6ae936 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -21,7 +21,7 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int ret, ep, len, pad; mt7615_mcu_fill_msg(dev, skb, cmd, seq); - if (cmd != MCU_CMD_FW_SCATTER) + if (cmd != MCU_CMD(FW_SCATTER)) ep = MT_EP_OUT_INBAND_CMD; else ep = MT_EP_OUT_AC_BE; @@ -42,6 +42,26 @@ out: return ret; } +int mt7663u_mcu_power_on(struct mt7615_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, + MT_TOP_MISC2_FW_PWR_ON, + FW_STATE_PWR_ON << 1, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return 0; +} + int mt7663u_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7663u_mcu_ops = { @@ -57,23 +77,17 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) { - mt7615_mcu_restart(&dev->mt76); + ret = mt7615_mcu_restart(&dev->mt76); + if (ret) + return ret; + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, 0, 500)) return -EIO; - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); + ret = mt7663u_mcu_power_on(dev); if (ret) return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, - MT_TOP_MISC2_FW_PWR_ON, - FW_STATE_PWR_ON << 1, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - return -EIO; - } } ret = __mt7663_load_firmware(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 5a6d7829c6e0..0052d103e276 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -49,7 +49,7 @@ mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid, __le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE); memset(txwi, 0, MT_USB_TXD_SIZE); - mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false); + mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, qid, false); skb_push(skb, MT_USB_TXD_SIZE); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index e7f01c2978a2..635192c878cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -12,9 +12,28 @@ #define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10 #define MT76_CONNAC_MAX_SCAN_MATCH 16 +#define MT76_CONNAC_MAX_WMM_SETS 4 + #define MT76_CONNAC_COREDUMP_TIMEOUT (HZ / 20) #define MT76_CONNAC_COREDUMP_SZ (1300 * 1024) +#define MT_TXD_SIZE (8 * 4) + +#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4) +#define MT_USB_HDR_SIZE 4 +#define MT_USB_TAIL_SIZE 4 + +#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4) +#define MT_SDIO_TAIL_SIZE 8 +#define MT_SDIO_HDR_SIZE 4 + +#define MT_MSDU_ID_VALID BIT(15) + +#define MT_TXD_LEN_LAST BIT(15) +#define MT_TXD_LEN_MASK GENMASK(11, 0) +#define MT_TXD_LEN_MSDU_LAST BIT(14) +#define MT_TXD_LEN_AMSDU_LAST BIT(15) + enum { CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20, CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40, @@ -44,10 +63,18 @@ enum { REPEATER_BSSID_MAX = 0x3f, }; +struct mt76_connac_reg_map { + u32 phys; + u32 maps; + u32 size; +}; + struct mt76_connac_pm { - bool enable; - bool ds_enable; - bool suspended; + bool enable:1; + bool enable_user:1; + bool ds_enable:1; + bool ds_enable_user:1; + bool suspended:1; spinlock_t txq_lock; struct { @@ -83,6 +110,51 @@ struct mt76_connac_coredump { unsigned long last_activity; }; +struct mt76_connac_sta_key_conf { + s8 keyidx; + u8 key[16]; +}; + +#define MT_TXP_MAX_BUF_NUM 6 + +struct mt76_connac_fw_txp { + __le16 flags; + __le16 token; + u8 bss_idx; + __le16 rept_wds_wcid; + u8 nbuf; + __le32 buf[MT_TXP_MAX_BUF_NUM]; + __le16 len[MT_TXP_MAX_BUF_NUM]; +} __packed __aligned(4); + +#define MT_HW_TXP_MAX_MSDU_NUM 4 +#define MT_HW_TXP_MAX_BUF_NUM 4 + +struct mt76_connac_txp_ptr { + __le32 buf0; + __le16 len0; + __le16 len1; + __le32 buf1; +} __packed __aligned(4); + +struct mt76_connac_hw_txp { + __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; + struct mt76_connac_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; +} __packed __aligned(4); + +struct mt76_connac_txp_common { + union { + struct mt76_connac_fw_txp fw; + struct mt76_connac_hw_txp hw; + }; +}; + +struct mt76_connac_tx_free { + __le16 rx_byte_cnt; + __le16 ctrl; + __le32 txd; +} __packed __aligned(4); + extern const struct wiphy_wowlan_support mt76_connac_wowlan_support; static inline bool is_mt7922(struct mt76_dev *dev) @@ -100,12 +172,107 @@ static inline bool is_mt7663(struct mt76_dev *dev) return mt76_chip(dev) == 0x7663; } +static inline bool is_mt7915(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7915; +} + +static inline bool is_mt7916(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7906; +} + +static inline bool is_mt7986(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7986; +} + +static inline bool is_mt7622(struct mt76_dev *dev) +{ + if (!IS_ENABLED(CONFIG_MT7622_WMAC)) + return false; + + return mt76_chip(dev) == 0x7622; +} + +static inline bool is_mt7615(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; +} + +static inline bool is_mt7611(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7611; +} + +static inline bool is_connac_v1(struct mt76_dev *dev) +{ + return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev); +} + +static inline bool is_mt76_fw_txp(struct mt76_dev *dev) +{ + switch (mt76_chip(dev)) { + case 0x7961: + case 0x7922: + case 0x7663: + case 0x7622: + return false; + default: + return true; + } +} + +static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef) +{ + static const u8 width_to_bw[] = { + [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ, + [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ, + [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ, + [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ, + [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ, + [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, + [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, + [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, + }; + + if (chandef->width >= ARRAY_SIZE(width_to_bw)) + return 0; + + return width_to_bw[chandef->width]; +} + +static inline u8 mt76_connac_lmac_mapping(u8 ac) +{ + /* LMAC uses the reverse order of mac80211 AC indexes */ + return 3 - ac; +} + +static inline void * +mt76_connac_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) +{ + u8 *txwi; + + if (!t) + return NULL; + + txwi = mt76_get_txwi_ptr(dev, t); + + return (void *)(txwi + MT_TXD_SIZE); +} + int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm); void mt76_connac_power_save_sched(struct mt76_phy *phy, struct mt76_connac_pm *pm); void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm, struct mt76_wcid *wcid); +static inline void mt76_connac_tx_cleanup(struct mt76_dev *dev) +{ + dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WM], false); + dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WA], false); +} + static inline bool mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm) { @@ -168,11 +335,37 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm) mutex_unlock(&dev->mutex); } +int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, + int ring_base, u32 flags); +void mt76_connac_write_hw_txp(struct mt76_dev *dev, + struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id); +void mt76_connac_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *txwi); +void mt76_connac_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e); void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw, struct mt76_connac_pm *pm, struct mt76_wcid *wcid, struct sk_buff *skb); void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy, struct mt76_connac_pm *pm); +void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed); +bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, + __le32 *txs_data); +bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data); +void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev, + struct sk_buff *skb, + __le32 *rxv, u32 mode); +int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif, + struct sk_buff *skb, u16 hdr_offset); +int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, + struct mt76_rx_status *status, + struct ieee80211_supported_band *sband, + __le32 *rxv, u8 *mode); #endif /* __MT76_CONNAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h new file mode 100644 index 000000000000..f33171bcd343 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2022 MediaTek Inc. */ + +#ifndef __MT76_CONNAC2_MAC_H +#define __MT76_CONNAC2_MAC_H + +enum tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +enum tx_pkt_type { + MT_TX_TYPE_CT, + MT_TX_TYPE_SF, + MT_TX_TYPE_CMD, + MT_TX_TYPE_FW, +}; + +enum { + MT_CTX0, + MT_HIF0 = 0x0, + + MT_LMAC_AC00 = 0x0, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0, + MT_LMAC_BCN0, + MT_LMAC_PSMP0, +}; + +#define MT_TXD0_Q_IDX GENMASK(31, 25) +#define MT_TXD0_PKT_FMT GENMASK(24, 23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_LONG_FORMAT BIT(31) +#define MT_TXD1_TGID BIT(30) +#define MT_TXD1_OWN_MAC GENMASK(29, 24) +#define MT_TXD1_AMSDU BIT(23) +#define MT_TXD1_TID GENMASK(22, 20) +#define MT_TXD1_HDR_PAD GENMASK(19, 18) +#define MT_TXD1_HDR_FORMAT GENMASK(17, 16) +#define MT_TXD1_HDR_INFO GENMASK(15, 11) +#define MT_TXD1_ETH_802_3 BIT(15) +#define MT_TXD1_VTA BIT(10) +#define MT_TXD1_WLAN_IDX GENMASK(9, 0) + +#define MT_TXD2_FIX_RATE BIT(31) +#define MT_TXD2_FIXED_RATE BIT(30) +#define MT_TXD2_POWER_OFFSET GENMASK(29, 24) +#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_BIP BIT(11) +#define MT_TXD2_MULTICAST BIT(10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_SOUNDING BIT(8) +#define MT_TXD2_NDPA BIT(7) +#define MT_TXD2_NDP BIT(6) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SW_POWER_MGMT BIT(29) +#define MT_TXD3_BA_DISABLE BIT(28) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) +#define MT_TXD3_TIMING_MEASURE BIT(5) +#define MT_TXD3_DAS BIT(4) +#define MT_TXD3_EEOSP BIT(3) +#define MT_TXD3_EMRD BIT(2) +#define MT_TXD3_PROTECT_FRAME BIT(1) +#define MT_TXD3_NO_ACK BIT(0) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_MD BIT(15) +#define MT_TXD5_ADD_BA BIT(14) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_TX_IBF BIT(31) +#define MT_TXD6_TX_EBF BIT(30) +#define MT_TXD6_TX_RATE GENMASK(29, 16) +#define MT_TXD6_SGI GENMASK(15, 14) +#define MT_TXD6_HELTF GENMASK(13, 12) +#define MT_TXD6_LDPC BIT(11) +#define MT_TXD6_SPE_ID_IDX BIT(10) +#define MT_TXD6_ANT_ID GENMASK(7, 4) +#define MT_TXD6_DYN_BW BIT(3) +#define MT_TXD6_FIXED_BW BIT(2) +#define MT_TXD6_BW GENMASK(1, 0) + +#define MT_TXD7_TXD_LEN GENMASK(31, 30) +#define MT_TXD7_UDP_TCP_SUM BIT(29) +#define MT_TXD7_IP_SUM BIT(28) +#define MT_TXD7_TYPE GENMASK(21, 20) +#define MT_TXD7_SUB_TYPE GENMASK(19, 16) + +#define MT_TXD7_PSE_FID GENMASK(27, 16) +#define MT_TXD7_SPE_IDX GENMASK(15, 11) +#define MT_TXD7_HW_AMSDU BIT(10) +#define MT_TXD7_TX_TIME GENMASK(9, 0) + +#define MT_TXD8_L_TYPE GENMASK(5, 4) +#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0) + +#define MT_TX_RATE_STBC BIT(13) +#define MT_TX_RATE_NSS GENMASK(12, 10) +#define MT_TX_RATE_MODE GENMASK(9, 6) +#define MT_TX_RATE_SU_EXT_TONE BIT(5) +#define MT_TX_RATE_DCM BIT(4) +/* VHT/HE only use bits 0-3 */ +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXS0_FIXED_RATE BIT(31) +#define MT_TXS0_BW GENMASK(30, 29) +#define MT_TXS0_TID GENMASK(28, 26) +#define MT_TXS0_AMPDU BIT(25) +#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) +#define MT_TXS0_BA_ERROR BIT(22) +#define MT_TXS0_PS_FLAG BIT(21) +#define MT_TXS0_TXOP_TIMEOUT BIT(20) +#define MT_TXS0_BIP_ERROR BIT(19) + +#define MT_TXS0_QUEUE_TIMEOUT BIT(18) +#define MT_TXS0_RTS_TIMEOUT BIT(17) +#define MT_TXS0_ACK_TIMEOUT BIT(16) +#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) + +#define MT_TXS0_TX_STATUS_HOST BIT(15) +#define MT_TXS0_TX_STATUS_MCU BIT(14) +#define MT_TXS0_TX_RATE GENMASK(13, 0) + +#define MT_TXS1_SEQNO GENMASK(31, 20) +#define MT_TXS1_RESP_RATE GENMASK(19, 16) +#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) +#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) + +#define MT_TXS2_BF_STATUS GENMASK(31, 30) +#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27) +#define MT_TXS2_SHARED_ANTENNA BIT(26) +#define MT_TXS2_WCID GENMASK(25, 16) +#define MT_TXS2_TX_DELAY GENMASK(15, 0) + +#define MT_TXS3_PID GENMASK(31, 24) +#define MT_TXS3_ANT_ID GENMASK(23, 0) + +#define MT_TXS4_TIMESTAMP GENMASK(31, 0) + +/* PPDU based TXS */ +#define MT_TXS5_MPDU_TX_BYTE GENMASK(22, 0) +#define MT_TXS5_MPDU_TX_CNT GENMASK(31, 23) + +#define MT_TXS6_MPDU_FAIL_CNT GENMASK(31, 23) + +#define MT_TXS7_MPDU_RETRY_CNT GENMASK(31, 23) + +/* RXD DW1 */ +#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0) +#define MT_RXD1_NORMAL_GROUP_1 BIT(11) +#define MT_RXD1_NORMAL_GROUP_2 BIT(12) +#define MT_RXD1_NORMAL_GROUP_3 BIT(13) +#define MT_RXD1_NORMAL_GROUP_4 BIT(14) +#define MT_RXD1_NORMAL_GROUP_5 BIT(15) +#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) +#define MT_RXD1_NORMAL_CM BIT(23) +#define MT_RXD1_NORMAL_CLM BIT(24) +#define MT_RXD1_NORMAL_ICV_ERR BIT(25) +#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) +#define MT_RXD1_NORMAL_FCS_ERR BIT(27) +#define MT_RXD1_NORMAL_BAND_IDX BIT(28) +#define MT_RXD1_NORMAL_SPP_EN BIT(29) +#define MT_RXD1_NORMAL_ADD_OM BIT(30) +#define MT_RXD1_NORMAL_SEC_DONE BIT(31) + +/* RXD DW2 */ +#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) +#define MT_RXD2_NORMAL_CO_ANT BIT(6) +#define MT_RXD2_NORMAL_BF_CQI BIT(7) +#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) +#define MT_RXD2_NORMAL_HDR_TRANS BIT(13) +#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14) +#define MT_RXD2_NORMAL_TID GENMASK(19, 16) +#define MT_RXD2_NORMAL_MU_BAR BIT(21) +#define MT_RXD2_NORMAL_SW_BIT BIT(22) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) +#define MT_RXD2_NORMAL_INT_FRAME BIT(26) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) +#define MT_RXD2_NORMAL_BF_REPORT BIT(31) + +/* RXD DW4 */ +#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) +#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) +#define MT_RXD4_MID_AMSDU_FRAME BIT(1) +#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) +#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9) +#define MT_RXD4_NORMAL_CLS BIT(10) +#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11) +#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13) +#define MT_RXD4_NORMAL_WOL GENMASK(18, 14) +#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19) +#define MT_RXD3_NORMAL_PF_MODE BIT(29) +#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) + +#define MT_RXV_HDR_BAND_IDX BIT(24) + +/* RXD DW3 */ +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) +#define MT_RXD3_NORMAL_U2M BIT(0) +#define MT_RXD3_NORMAL_HTC_VLD BIT(0) +#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19) +#define MT_RXD3_NORMAL_BEACON_MC BIT(20) +#define MT_RXD3_NORMAL_BEACON_UC BIT(21) +#define MT_RXD3_NORMAL_AMSDU BIT(22) +#define MT_RXD3_NORMAL_MESH BIT(23) +#define MT_RXD3_NORMAL_MHCP BIT(24) +#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25) +#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26) +#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27) +#define MT_RXD3_NORMAL_MORE BIT(28) +#define MT_RXD3_NORMAL_UNWANT BIT(29) +#define MT_RXD3_NORMAL_RX_DROP BIT(30) +#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) + +/* RXD GROUP4 */ +#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0) +#define MT_RXD6_TA_LO GENMASK(31, 16) + +#define MT_RXD7_TA_HI GENMASK(31, 0) + +#define MT_RXD8_SEQ_CTRL GENMASK(15, 0) +#define MT_RXD8_QOS_CTL GENMASK(31, 16) + +#define MT_RXD9_HT_CONTROL GENMASK(31, 0) + +/* P-RXV DW0 */ +#define MT_PRXV_TX_RATE GENMASK(6, 0) +#define MT_PRXV_TX_DCM BIT(4) +#define MT_PRXV_TX_ER_SU_106T BIT(5) +#define MT_PRXV_NSTS GENMASK(9, 7) +#define MT_PRXV_TXBF BIT(10) +#define MT_PRXV_HT_AD_CODE BIT(11) +#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28) + +#define MT_PRXV_FRAME_MODE GENMASK(14, 12) +#define MT_PRXV_HT_SGI GENMASK(16, 15) +#define MT_PRXV_HT_STBC GENMASK(23, 22) +#define MT_PRXV_TX_MODE GENMASK(27, 24) +#define MT_PRXV_DCM BIT(17) +#define MT_PRXV_NUM_RX BIT(20, 18) + +/* P-RXV DW1 */ +#define MT_PRXV_RCPI3 GENMASK(31, 24) +#define MT_PRXV_RCPI2 GENMASK(23, 16) +#define MT_PRXV_RCPI1 GENMASK(15, 8) +#define MT_PRXV_RCPI0 GENMASK(7, 0) +#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) + +/* C-RXV */ +#define MT_CRXV_HT_STBC GENMASK(1, 0) +#define MT_CRXV_TX_MODE GENMASK(7, 4) +#define MT_CRXV_FRAME_MODE GENMASK(10, 8) +#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) +#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) +#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) +#define MT_CRXV_HE_PE_DISAMBIG BIT(23) +#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) +#define MT_CRXV_HE_UPLINK BIT(31) + +#define MT_CRXV_HE_RU0 GENMASK(7, 0) +#define MT_CRXV_HE_RU1 GENMASK(15, 8) +#define MT_CRXV_HE_RU2 GENMASK(23, 16) +#define MT_CRXV_HE_RU3 GENMASK(31, 24) + +#define MT_CRXV_HE_MU_AID GENMASK(30, 20) + +#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) +#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) +#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) +#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) + +#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0) +#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6) +#define MT_CRXV_HE_BEAM_CHNG BIT(13) +#define MT_CRXV_HE_DOPPLER BIT(16) + +#define MT_CRXV_SNR GENMASK(18, 13) +#define MT_CRXV_FOE_LO GENMASK(31, 19) +#define MT_CRXV_FOE_HI GENMASK(6, 0) +#define MT_CRXV_FOE_SHIFT 13 + +#define MT_CT_INFO_APPLY_TXD BIT(0) +#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) +#define MT_CT_INFO_MGMT_FRAME BIT(2) +#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define MT_CT_INFO_HSR2_TX BIT(4) +#define MT_CT_INFO_FROM_HOST BIT(7) + +enum tx_mcu_port_q_idx { + MT_TX_MCU_PORT_RX_Q0 = 0x20, + MT_TX_MCU_PORT_RX_Q1, + MT_TX_MCU_PORT_RX_Q2, + MT_TX_MCU_PORT_RX_Q3, + MT_TX_MCU_PORT_RX_FWDL = 0x3e +}; + +enum tx_port_idx { + MT_TX_PORT_IDX_LMAC, + MT_TX_PORT_IDX_MCU +}; + +#endif /* __MT76_CONNAC2_MAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index af43bcb54578..34ac3d81a510 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -2,14 +2,17 @@ /* Copyright (C) 2020 MediaTek Inc. */ #include "mt76_connac.h" +#include "mt76_connac2_mac.h" +#include "dma.h" + +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ + IEEE80211_RADIOTAP_HE_##f) int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm) { struct mt76_dev *dev = phy->dev; - if (!pm->enable) - return 0; - if (mt76_is_usb(dev)) return 0; @@ -118,3 +121,939 @@ void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy, mt76_worker_schedule(&phy->dev->tx_worker); } EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs); + +void mt76_connac_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e) +{ + if (!e->txwi) { + dev_kfree_skb_any(e->skb); + return; + } + + /* error path */ + if (e->skb == DMA_DUMMY_DATA) { + struct mt76_connac_txp_common *txp; + struct mt76_txwi_cache *t; + u16 token; + + txp = mt76_connac_txwi_to_txp(mdev, e->txwi); + if (is_mt76_fw_txp(mdev)) + token = le16_to_cpu(txp->fw.token); + else + token = le16_to_cpu(txp->hw.msdu_id[0]) & + ~MT_MSDU_ID_VALID; + + t = mt76_token_put(mdev, token); + e->skb = t ? t->skb : NULL; + } + + if (e->skb) + mt76_tx_complete_skb(mdev, e->wcid, e->skb); +} +EXPORT_SYMBOL_GPL(mt76_connac_tx_complete_skb); + +void mt76_connac_write_hw_txp(struct mt76_dev *dev, + struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id) +{ + struct mt76_connac_hw_txp *txp = txp_ptr; + struct mt76_connac_txp_ptr *ptr = &txp->ptr[0]; + int i, nbuf = tx_info->nbuf - 1; + u32 last_mask; + + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); + tx_info->nbuf = 1; + + txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); + + if (is_mt7663(dev) || is_mt7921(dev)) + last_mask = MT_TXD_LEN_LAST; + else + last_mask = MT_TXD_LEN_AMSDU_LAST | + MT_TXD_LEN_MSDU_LAST; + + for (i = 0; i < nbuf; i++) { + u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK; + u32 addr = tx_info->buf[i + 1].addr; + + if (i == nbuf - 1) + len |= last_mask; + + if (i & 1) { + ptr->buf1 = cpu_to_le32(addr); + ptr->len1 = cpu_to_le16(len); + ptr++; + } else { + ptr->buf0 = cpu_to_le32(addr); + ptr->len0 = cpu_to_le16(len); + } + } +} +EXPORT_SYMBOL_GPL(mt76_connac_write_hw_txp); + +static void +mt76_connac_txp_skb_unmap_fw(struct mt76_dev *mdev, + struct mt76_connac_fw_txp *txp) +{ + struct device *dev = is_connac_v1(mdev) ? mdev->dev : mdev->dma_dev; + int i; + + for (i = 0; i < txp->nbuf; i++) + dma_unmap_single(dev, le32_to_cpu(txp->buf[i]), + le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); +} + +static void +mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev, + struct mt76_connac_hw_txp *txp) +{ + u32 last_mask; + int i; + + if (is_mt7663(dev) || is_mt7921(dev)) + last_mask = MT_TXD_LEN_LAST; + else + last_mask = MT_TXD_LEN_MSDU_LAST; + + for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { + struct mt76_connac_txp_ptr *ptr = &txp->ptr[i]; + bool last; + u16 len; + + len = le16_to_cpu(ptr->len0); + last = len & last_mask; + len &= MT_TXD_LEN_MASK; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, + DMA_TO_DEVICE); + if (last) + break; + + len = le16_to_cpu(ptr->len1); + last = len & last_mask; + len &= MT_TXD_LEN_MASK; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, + DMA_TO_DEVICE); + if (last) + break; + } +} + +void mt76_connac_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt76_connac_txp_common *txp; + + txp = mt76_connac_txwi_to_txp(dev, t); + if (is_mt76_fw_txp(dev)) + mt76_connac_txp_skb_unmap_fw(dev, &txp->fw); + else + mt76_connac_txp_skb_unmap_hw(dev, &txp->hw); +} +EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap); + +int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc, + int ring_base, u32 flags) +{ + int i, err; + + err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags); + if (err < 0) + return err; + + for (i = 1; i <= MT_TXQ_PSD; i++) + phy->q_tx[i] = phy->q_tx[0]; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues); + +static u16 +mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, + bool beacon, bool mcast) +{ + u8 mode = 0, band = mphy->chandef.chan->band; + int rateidx = 0, mcast_rate; + + if (!vif) + goto legacy; + + if (is_mt7921(mphy->dev)) { + rateidx = ffs(vif->bss_conf.basic_rates) - 1; + goto legacy; + } + + if (beacon) { + struct cfg80211_bitrate_mask *mask; + + mask = &vif->bss_conf.beacon_tx_rate; + if (hweight16(mask->control[band].he_mcs[0]) == 1) { + rateidx = ffs(mask->control[band].he_mcs[0]) - 1; + mode = MT_PHY_TYPE_HE_SU; + goto out; + } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) { + rateidx = ffs(mask->control[band].vht_mcs[0]) - 1; + mode = MT_PHY_TYPE_VHT; + goto out; + } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) { + rateidx = ffs(mask->control[band].ht_mcs[0]) - 1; + mode = MT_PHY_TYPE_HT; + goto out; + } else if (hweight32(mask->control[band].legacy) == 1) { + rateidx = ffs(mask->control[band].legacy) - 1; + goto legacy; + } + } + + mcast_rate = vif->bss_conf.mcast_rate[band]; + if (mcast && mcast_rate > 0) + rateidx = mcast_rate - 1; + else + rateidx = ffs(vif->bss_conf.basic_rates) - 1; + +legacy: + rateidx = mt76_calculate_default_rate(mphy, rateidx); + mode = rateidx >> 8; + rateidx &= GENMASK(7, 0); + +out: + return FIELD_PREP(MT_TX_RATE_IDX, rateidx) | + FIELD_PREP(MT_TX_RATE_MODE, mode); +} + +static void +mt76_connac2_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb, + struct mt76_wcid *wcid) +{ + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + u8 fc_type, fc_stype; + u16 ethertype; + bool wmm = false; + u32 val; + + if (wcid->sta) { + struct ieee80211_sta *sta; + + sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); + wmm = sta->wme; + } + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | + FIELD_PREP(MT_TXD1_TID, tid); + + ethertype = get_unaligned_be16(&skb->data[12]); + if (ethertype >= ETH_P_802_3_MIN) + val |= MT_TXD1_ETH_802_3; + + txwi[1] |= cpu_to_le32(val); + + fc_type = IEEE80211_FTYPE_DATA >> 2; + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + + txwi[2] |= cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + + txwi[7] |= cpu_to_le32(val); +} + +static void +mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, + struct ieee80211_key_conf *key) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool multicast = is_multicast_ether_addr(hdr->addr1); + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + __le16 fc = hdr->frame_control; + u8 fc_type, fc_stype; + u32 val; + + if (ieee80211_is_action(fc) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { + u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + + txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); + tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; + } else if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; + u16 control = le16_to_cpu(bar->control); + + tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); + } + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, + ieee80211_get_hdrlen_from_skb(skb) / 2) | + FIELD_PREP(MT_TXD1_TID, tid); + + txwi[1] |= cpu_to_le32(val); + + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | + FIELD_PREP(MT_TXD2_MULTICAST, multicast); + + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + val |= MT_TXD2_BIP; + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); + } + + if (!ieee80211_is_data(fc) || multicast || + info->flags & IEEE80211_TX_CTL_USE_MINRATE) + val |= MT_TXD2_FIX_RATE; + + txwi[2] |= cpu_to_le32(val); + + if (ieee80211_is_beacon(fc)) { + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); + if (!is_mt7921(dev)) + txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, + 0x18)); + } + + if (info->flags & IEEE80211_TX_CTL_INJECTED) { + u16 seqno = le16_to_cpu(hdr->seq_ctrl); + + if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar; + + bar = (struct ieee80211_bar *)skb->data; + seqno = le16_to_cpu(bar->start_seq_num); + } + + val = MT_TXD3_SN_VALID | + FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); + txwi[3] |= cpu_to_le32(val); + txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU); + } + + if (mt76_is_mmio(dev)) { + val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + txwi[7] |= cpu_to_le32(val); + } else { + val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | + FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); + txwi[8] |= cpu_to_le32(val); + } +} + +void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; + struct ieee80211_vif *vif = info->control.vif; + struct mt76_phy *mphy = &dev->phy; + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0; + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE; + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; + bool beacon = !!(changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)); + bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)); + + if (vif) { + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + band_idx = mvif->band_idx; + } + + if (phy_idx && dev->phys[MT_BAND1]) + mphy = dev->phys[MT_BAND1]; + + if (inband_disc) { + p_fmt = MT_TX_TYPE_FW; + q_idx = MT_LMAC_ALTX0; + } else if (beacon) { + p_fmt = MT_TX_TYPE_FW; + q_idx = MT_LMAC_BCN0; + } else if (qid >= MT_TXQ_PSD) { + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; + q_idx = MT_LMAC_ALTX0; + } else { + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + + mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); + + /* counting non-offloading skbs */ + wcid->stats.tx_bytes += skb->len; + wcid->stats.tx_packets++; + } + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); + if (!is_mt7921(dev)) + val |= MT_TXD1_VTA; + if (phy_idx || band_idx) + val |= MT_TXD1_TGID; + + txwi[1] = cpu_to_le32(val); + txwi[2] = 0; + + val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15); + if (!is_mt7921(dev)) + val |= MT_TXD3_SW_POWER_MGMT; + if (key) + val |= MT_TXD3_PROTECT_FRAME; + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + val |= MT_TXD3_NO_ACK; + + txwi[3] = cpu_to_le32(val); + txwi[4] = 0; + + val = FIELD_PREP(MT_TXD5_PID, pid); + if (pid >= MT_PACKET_ID_FIRST) + val |= MT_TXD5_TX_STATUS_HOST; + + txwi[5] = cpu_to_le32(val); + txwi[6] = 0; + txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; + + if (is_8023) + mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid); + else + mt76_connac2_mac_write_txwi_80211(dev, txwi, skb, key); + + if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { + /* Fixed rata is available just for 802.11 txd */ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool multicast = is_multicast_ether_addr(hdr->addr1); + u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, + multicast); + u32 val = MT_TXD6_FIXED_BW; + + /* hardware won't add HTC for mgmt/ctrl frame */ + txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); + + val |= FIELD_PREP(MT_TXD6_TX_RATE, rate); + txwi[6] |= cpu_to_le32(val); + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + } +} +EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi); + +bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, + __le32 *txs_data) +{ + struct mt76_sta_stats *stats = &wcid->stats; + struct ieee80211_supported_band *sband; + struct mt76_phy *mphy; + struct rate_info rate = {}; + bool cck = false; + u32 txrate, txs, mode; + + txs = le32_to_cpu(txs_data[0]); + + /* PPDU based reporting */ + if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { + stats->tx_bytes += + le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE); + stats->tx_packets += + le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT); + stats->tx_failed += + le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); + stats->tx_retries += + le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT); + } + + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); + + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; + + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) + stats->tx_nss[rate.nss - 1]++; + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) + stats->tx_mcs[rate.mcs]++; + + mode = FIELD_GET(MT_TX_RATE_MODE, txrate); + switch (mode) { + case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; + case MT_PHY_TYPE_OFDM: + mphy = &dev->phy; + if (wcid->phy_idx == MT_BAND1 && dev->phys[MT_BAND1]) + mphy = dev->phys[MT_BAND1]; + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; + else + sband = &mphy->sband_2g.sband; + + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); + rate.legacy = sband->bitrates[rate.mcs].bitrate; + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: + if (rate.mcs > 31) + return false; + + rate.flags = RATE_INFO_FLAGS_MCS; + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) + rate.flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_VHT: + if (rate.mcs > 9) + return false; + + rate.flags = RATE_INFO_FLAGS_VHT_MCS; + break; + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + case MT_PHY_TYPE_HE_MU: + if (rate.mcs > 11) + return false; + + rate.he_gi = wcid->rate.he_gi; + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); + rate.flags = RATE_INFO_FLAGS_HE_MCS; + break; + default: + return false; + } + + stats->tx_mode[mode]++; + + switch (FIELD_GET(MT_TXS0_BW, txs)) { + case IEEE80211_STA_RX_BW_160: + rate.bw = RATE_INFO_BW_160; + stats->tx_bw[3]++; + break; + case IEEE80211_STA_RX_BW_80: + rate.bw = RATE_INFO_BW_80; + stats->tx_bw[2]++; + break; + case IEEE80211_STA_RX_BW_40: + rate.bw = RATE_INFO_BW_40; + stats->tx_bw[1]++; + break; + default: + rate.bw = RATE_INFO_BW_20; + stats->tx_bw[0]++; + break; + } + wcid->rate = rate; + + return true; +} +EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_txs); + +bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data) +{ + struct sk_buff_head list; + struct sk_buff *skb; + + mt76_tx_status_lock(dev, &list); + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool noacked = !(info->flags & IEEE80211_TX_STAT_ACK); + + if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.ampdu_len = 1; + info->status.ampdu_ack_len = !noacked; + info->status.rates[0].idx = -1; + + wcid->stats.tx_failed += noacked; + + mt76_connac2_mac_fill_txs(dev, wcid, txs_data); + mt76_tx_status_skb_done(dev, skb, &list); + } + mt76_tx_status_unlock(dev, &list); + + return !!skb; +} +EXPORT_SYMBOL_GPL(mt76_connac2_mac_add_txs_skb); + +static void +mt76_connac2_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, + struct ieee80211_radiotap_he *he, + __le32 *rxv) +{ + u32 ru_h, ru_l; + u8 ru, offs = 0; + + ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L); + ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H); + ru = (u8)(ru_l | ru_h << 4); + + status->bw = RATE_INFO_BW_HE_RU; + + switch (ru) { + case 0 ... 36: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; + offs = ru; + break; + case 37 ... 52: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; + offs = ru - 37; + break; + case 53 ... 60: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; + offs = ru - 53; + break; + case 61 ... 64: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; + offs = ru - 61; + break; + case 65 ... 66: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; + offs = ru - 65; + break; + case 67: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 68: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; + break; + } + + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | + le16_encode_bits(offs, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); +} + +static void +mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb, + __le32 *rxv) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static struct ieee80211_radiotap_he_mu mu_known = { + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), + }; + struct ieee80211_radiotap_he_mu *he_mu; + + if (is_mt7921(dev)) { + mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN); + mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN); + } + + status->flag |= RX_FLAG_RADIOTAP_HE_MU; + + he_mu = skb_push(skb, sizeof(mu_known)); + memcpy(he_mu, &mu_known, sizeof(mu_known)); + +#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) + + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); + if (status->he_dcm) + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); + + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | + MU_PREP(FLAGS2_SIG_B_SYMS_USERS, + le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); + + he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0); + + if (status->bw >= RATE_INFO_BW_40) { + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); + he_mu->ru_ch2[0] = + le32_get_bits(rxv[3], MT_CRXV_HE_RU1); + } + + if (status->bw >= RATE_INFO_BW_80) { + he_mu->ru_ch1[1] = + le32_get_bits(rxv[3], MT_CRXV_HE_RU2); + he_mu->ru_ch2[1] = + le32_get_bits(rxv[3], MT_CRXV_HE_RU3); + } +} + +void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev, + struct sk_buff *skb, + __le32 *rxv, u32 mode) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static const struct ieee80211_radiotap_he known = { + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | + HE_BITS(DATA1_DATA_DCM_KNOWN) | + HE_BITS(DATA1_STBC_KNOWN) | + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), + .data2 = HE_BITS(DATA2_GI_KNOWN) | + HE_BITS(DATA2_TXBF_KNOWN) | + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN), + }; + u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1; + struct ieee80211_radiotap_he *he; + + status->flag |= RX_FLAG_RADIOTAP_HE; + + he = skb_push(skb, sizeof(known)); + memcpy(he, &known, sizeof(known)); + + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | + le16_encode_bits(ltf_size, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) + he->data5 |= HE_BITS(DATA5_TXBF); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); + + switch (mode) { + case MT_PHY_TYPE_HE_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | + HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); + break; + case MT_PHY_TYPE_HE_EXT_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); + break; + case MT_PHY_TYPE_HE_MU: + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | + HE_BITS(DATA1_UL_DL_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); + + mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv); + mt76_connac2_mac_decode_he_mu_radiotap(dev, skb, rxv); + break; + case MT_PHY_TYPE_HE_TB: + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); + + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]); + + mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(mt76_connac2_mac_decode_he_radiotap); + +/* The HW does not translate the mac header to 802.3 for mesh point */ +int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif, + struct sk_buff *skb, u16 hdr_offset) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_offset); + __le32 *rxd = (__le32 *)skb->data; + struct ieee80211_sta *sta; + struct ieee80211_hdr hdr; + u16 frame_control; + + if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != + MT_RXD3_NORMAL_U2M) + return -EINVAL; + + if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) + return -EINVAL; + + sta = container_of((void *)status->wcid, struct ieee80211_sta, drv_priv); + + /* store the info from RXD and ethhdr to avoid being overridden */ + frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL); + hdr.frame_control = cpu_to_le16(frame_control); + hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL)); + hdr.duration_id = 0; + + ether_addr_copy(hdr.addr1, vif->addr); + ether_addr_copy(hdr.addr2, sta->addr); + switch (frame_control & (IEEE80211_FCTL_TODS | + IEEE80211_FCTL_FROMDS)) { + case 0: + ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); + break; + case IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_source); + break; + case IEEE80211_FCTL_TODS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + break; + case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + ether_addr_copy(hdr.addr4, eth_hdr->h_source); + break; + default: + break; + } + + skb_pull(skb, hdr_offset + sizeof(struct ethhdr) - 2); + if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || + eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) + ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); + else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) + ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); + else + skb_pull(skb, 2); + + if (ieee80211_has_order(hdr.frame_control)) + memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9], + IEEE80211_HT_CTL_LEN); + if (ieee80211_is_data_qos(hdr.frame_control)) { + __le16 qos_ctrl; + + qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL)); + memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, + IEEE80211_QOS_CTL_LEN); + } + + if (ieee80211_has_a4(hdr.frame_control)) + memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); + else + memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans); + +int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, + struct mt76_rx_status *status, + struct ieee80211_supported_band *sband, + __le32 *rxv, u8 *mode) +{ + u32 v0, v2; + u8 stbc, gi, bw, dcm, nss; + int i, idx; + bool cck = false; + + v0 = le32_to_cpu(rxv[0]); + v2 = le32_to_cpu(rxv[2]); + + idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; + + if (!is_mt7915(dev)) { + stbc = FIELD_GET(MT_PRXV_HT_STBC, v0); + gi = FIELD_GET(MT_PRXV_HT_SGI, v0); + *mode = FIELD_GET(MT_PRXV_TX_MODE, v0); + if (is_mt7921(dev)) + dcm = !!(idx & MT_PRXV_TX_DCM); + else + dcm = FIELD_GET(MT_PRXV_DCM, v0); + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0); + } else { + stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); + gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); + *mode = FIELD_GET(MT_CRXV_TX_MODE, v2); + dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM); + bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2); + } + + switch (*mode) { + case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; + case MT_PHY_TYPE_OFDM: + i = mt76_get_rate(dev, sband, i, cck); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + status->encoding = RX_ENC_HT; + if (gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (i > 31) + return -EINVAL; + break; + case MT_PHY_TYPE_VHT: + status->nss = nss; + status->encoding = RX_ENC_VHT; + if (gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (i > 11) + return -EINVAL; + break; + case MT_PHY_TYPE_HE_MU: + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + status->nss = nss; + status->encoding = RX_ENC_HE; + i &= GENMASK(3, 0); + + if (gi <= NL80211_RATE_INFO_HE_GI_3_2) + status->he_gi = gi; + + status->he_dcm = dcm; + break; + default: + return -EINVAL; + } + status->rate_idx = i; + + switch (bw) { + case IEEE80211_STA_RX_BW_20: + break; + case IEEE80211_STA_RX_BW_40: + if (*mode & MT_PHY_TYPE_HE_EXT_SU && + (idx & MT_PRXV_TX_ER_SU_106T)) { + status->bw = RATE_INFO_BW_HE_RU; + status->he_ru = + NL80211_RATE_INFO_HE_RU_ALLOC_106; + } else { + status->bw = RATE_INFO_BW_40; + } + break; + case IEEE80211_STA_RX_BW_80: + status->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_160: + status->bw = RATE_INFO_BW_160; + break; + default: + return -EINVAL; + } + + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; + if (*mode < MT_PHY_TYPE_HE_SU && gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 26b4b875dcc0..011fc9729b38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ +#include <linux/firmware.h> +#include "mt76_connac2_mac.h" #include "mt76_connac_mcu.h" int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option) @@ -13,8 +15,8 @@ int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option) .addr = cpu_to_le32(addr), }; - return mt76_mcu_send_msg(dev, MCU_CMD_FW_START_REQ, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_CMD(FW_START_REQ), &req, + sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_start_firmware); @@ -27,8 +29,8 @@ int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get) .op = cpu_to_le32(op), }; - return mt76_mcu_send_msg(dev, MCU_CMD_PATCH_SEM_CONTROL, &req, - sizeof(req), true); + return mt76_mcu_send_msg(dev, MCU_CMD(PATCH_SEM_CONTROL), + &req, sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_patch_sem_ctrl); @@ -41,8 +43,8 @@ int mt76_connac_mcu_start_patch(struct mt76_dev *dev) .check_crc = 0, }; - return mt76_mcu_send_msg(dev, MCU_CMD_PATCH_FINISH_REQ, &req, - sizeof(req), true); + return mt76_mcu_send_msg(dev, MCU_CMD(PATCH_FINISH_REQ), + &req, sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_start_patch); @@ -62,11 +64,11 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len, }; int cmd; - if (is_mt7921(dev) && - (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS) || addr == 0x900000)) - cmd = MCU_CMD_PATCH_START_REQ; + if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) || + (is_mt7921(dev) && addr == 0x900000)) + cmd = MCU_CMD(PATCH_START_REQ); else - cmd = MCU_CMD_TARGET_ADDRESS_LEN_REQ; + cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ); return mt76_mcu_send_msg(dev, cmd, &req, sizeof(req), true); } @@ -160,7 +162,8 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy) memcpy(__skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); - return mt76_mcu_skb_send_msg(dev, skb, MCU_CMD_SET_CHAN_DOMAIN, false); + return mt76_mcu_skb_send_msg(dev, skb, MCU_CE_CMD(SET_CHAN_DOMAIN), + false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_channel_domain); @@ -176,7 +179,7 @@ int mt76_connac_mcu_set_mac_enable(struct mt76_dev *dev, int band, bool enable, .band = band, }; - return mt76_mcu_send_msg(dev, MCU_EXT_CMD_MAC_INIT_CTRL, &req_mac, + return mt76_mcu_send_msg(dev, MCU_EXT_CMD(MAC_INIT_CTRL), &req_mac, sizeof(req_mac), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_mac_enable); @@ -192,14 +195,14 @@ int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif) */ } req = { .bss_idx = mvif->idx, - .ps_state = vif->bss_conf.ps ? 2 : 0, + .ps_state = vif->cfg.ps ? 2 : 0, }; if (vif->type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; - return mt76_mcu_send_msg(dev, MCU_CMD_SET_PS_PROFILE, &req, - sizeof(req), false); + return mt76_mcu_send_msg(dev, MCU_CE_CMD(SET_PS_PROFILE), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_vif_ps); @@ -218,7 +221,7 @@ int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band) .pkt_thresh = cpu_to_le32(0x2), }; - return mt76_mcu_send_msg(dev, MCU_EXT_CMD_PROTECT_CTRL, &req, + return mt76_mcu_send_msg(dev, MCU_EXT_CMD(PROTECT_CTRL), &req, sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rts_thresh); @@ -258,9 +261,8 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); if (sta_hdr) { - u16 size = le16_to_cpu(sta_hdr->len); - - sta_hdr->len = cpu_to_le16(size + len); + len += le16_to_cpu(sta_hdr->len); + sta_hdr->len = cpu_to_le16(len); } return ptlv; @@ -268,8 +270,8 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_nested_tlv); struct sk_buff * -mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, - struct mt76_wcid *wcid) +__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, + struct mt76_wcid *wcid, int len) { struct sta_req_hdr hdr = { .bss_idx = mvif->idx, @@ -280,7 +282,7 @@ mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo, &hdr.wlan_idx_hi); - skb = mt76_mcu_msg_alloc(dev, NULL, MT76_CONNAC_STA_UPDATE_MAX_SIZE); + skb = mt76_mcu_msg_alloc(dev, NULL, len); if (!skb) return ERR_PTR(-ENOMEM); @@ -288,7 +290,7 @@ mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, return skb; } -EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_sta_req); +EXPORT_SYMBOL_GPL(__mt76_connac_mcu_alloc_sta_req); struct wtbl_req_hdr * mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid, @@ -312,12 +314,54 @@ mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid, } if (sta_hdr) - sta_hdr->len = cpu_to_le16(sizeof(hdr)); + le16_add_cpu(&sta_hdr->len, sizeof(hdr)); return skb_put_data(nskb, &hdr, sizeof(hdr)); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req); +void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + u8 omac_idx = mvif->omac_idx; + struct bss_info_omac *omac; + struct tlv *tlv; + u32 type = 0; + + switch (vif->type) { + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + if (vif->p2p) + type = CONNECTION_P2P_GO; + else + type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: + if (vif->p2p) + type = CONNECTION_P2P_GC; + else + type = CONNECTION_INFRA_STA; + break; + case NL80211_IFTYPE_ADHOC: + type = CONNECTION_IBSS_ADHOC; + break; + default: + WARN_ON(1); + break; + } + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); + + omac = (struct bss_info_omac *)tlv; + omac->conn_type = cpu_to_le32(type); + omac->omac_idx = mvif->omac_idx; + omac->band_idx = mvif->band_idx; + omac->hw_bss_idx = omac_idx > EXT_BSSID_START ? HW_BSSID_0 : omac_idx; +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv); + void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -362,7 +406,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, else conn_type = CONNECTION_INFRA_AP; basic->conn_type = cpu_to_le32(conn_type); - basic->aid = cpu_to_le16(vif->bss_conf.aid); + basic->aid = cpu_to_le16(vif->cfg.aid); break; case NL80211_IFTYPE_ADHOC: basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); @@ -378,9 +422,8 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_basic_tlv); -static void -mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct sta_rec_uapsd *uapsd; struct tlv *tlv; @@ -409,6 +452,7 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, } uapsd->max_sp = sta->max_sp; } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_uapsd); void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, @@ -422,13 +466,17 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, sizeof(*htr), wtbl_tlv, sta_wtbl); htr = (struct wtbl_hdr_trans *)tlv; - htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags); + htr->no_rx_trans = true; if (vif->type == NL80211_IFTYPE_STATION) htr->to_ds = true; else htr->from_ds = true; + if (!wcid) + return; + + htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags); if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) { htr->to_ds = true; htr->from_ds = true; @@ -463,6 +511,25 @@ int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_update_hdr_trans); +int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb = NULL; + + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET, NULL, + &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, NULL, wtbl_hdr); + + return mt76_mcu_skb_send_msg(dev, skb, MCU_EXT_CMD(WTBL_UPDATE), true); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_update_hdr_trans); + void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, @@ -483,15 +550,14 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, if (sta) { if (vif->type == NL80211_IFTYPE_STATION) - generic->partial_aid = cpu_to_le16(vif->bss_conf.aid); + generic->partial_aid = cpu_to_le16(vif->cfg.aid); else generic->partial_aid = cpu_to_le16(sta->aid); memcpy(generic->peer_addr, sta->addr, ETH_ALEN); generic->muar_idx = mvif->omac_idx; generic->qos = sta->wme; } else { - if (is_mt7921(dev) && - vif->type == NL80211_IFTYPE_STATION) + if (!is_connac_v1(dev) && vif->type == NL80211_IFTYPE_STATION) memcpy(generic->peer_addr, vif->bss_conf.bssid, ETH_ALEN); else @@ -508,7 +574,7 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, rx->rca2 = 1; rx->rv = 1; - if (is_mt7921(dev)) + if (!is_connac_v1(dev)) return; tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_SPE, sizeof(*spe), @@ -530,14 +596,14 @@ mt76_connac_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, vif->type != NL80211_IFTYPE_STATION) return; - if (!sta->max_amsdu_len) + if (!sta->deflink.agg.max_amsdu_len) return; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct sta_rec_amsdu *)tlv; amsdu->max_amsdu_num = 8; amsdu->amsdu_en = true; - amsdu->max_mpdu_size = sta->max_amsdu_len >= + amsdu->max_mpdu_size = sta->deflink.agg.max_amsdu_len >= IEEE80211_MAX_MPDU_LEN_VHT_7991; wcid->amsdu = true; @@ -548,7 +614,7 @@ mt76_connac_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, static void mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) { - struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; + struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem; struct sta_rec_he *he; struct tlv *tlv; @@ -636,7 +702,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) he->he_cap = cpu_to_le32(cap); - switch (sta->bandwidth) { + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_160: if (elem->phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) @@ -688,9 +754,9 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, u8 mode = 0; if (sta) { - ht_cap = &sta->ht_cap; - vht_cap = &sta->vht_cap; - he_cap = &sta->he_cap; + ht_cap = &sta->deflink.ht_cap; + vht_cap = &sta->deflink.vht_cap; + he_cap = &sta->deflink.he_cap; } else { struct ieee80211_supported_band *sband; @@ -739,25 +805,25 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, u16 supp_rates; /* starec ht */ - if (sta->ht_cap.ht_supported) { + if (sta->deflink.ht_cap.ht_supported) { struct sta_rec_ht *ht; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; - ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap); } /* starec vht */ - if (sta->vht_cap.vht_supported) { + if (sta->deflink.vht_cap.vht_supported) { struct sta_rec_vht *vht; int len; len = is_mt7921(dev) ? sizeof(*vht) : sizeof(*vht) - 4; tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len); vht = (struct sta_rec_vht *)tlv; - vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; - vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap); + vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map; } /* starec uapsd */ @@ -766,11 +832,11 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, if (!is_mt7921(dev)) return; - if (sta->ht_cap.ht_supported || sta->he_cap.has_he) + if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he) mt76_connac_mcu_sta_amsdu_tlv(skb, sta, vif); /* starec he */ - if (sta->he_cap.has_he) { + if (sta->deflink.he_cap.has_he) { mt76_connac_mcu_sta_he_tlv(skb, sta); if (band == NL80211_BAND_6GHZ && sta_state == MT76_STA_INFO_STATE_ASSOC) { @@ -779,7 +845,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G, sizeof(*he_6g_capa)); he_6g_capa = (struct sta_rec_he_6g_capa *)tlv; - he_6g_capa->capa = sta->he_6ghz_capa.capa; + he_6g_capa->capa = sta->deflink.he_6ghz_capa.capa; } } @@ -789,14 +855,14 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates); phy->rcpi = rcpi; phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR, - sta->ht_cap.ampdu_factor) | + sta->deflink.ht_cap.ampdu_factor) | FIELD_PREP(IEEE80211_HT_AMPDU_PARM_DENSITY, - sta->ht_cap.ampdu_density); + sta->deflink.ht_cap.ampdu_density); tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); ra_info = (struct sta_rec_ra_info *)tlv; - supp_rates = sta->supp_rates[band]; + supp_rates = sta->deflink.supp_rates[band]; if (band == NL80211_BAND_2GHZ) supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) | FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf); @@ -805,25 +871,26 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, ra_info->legacy = cpu_to_le16(supp_rates); - if (sta->ht_cap.ht_supported) - memcpy(ra_info->rx_mcs_bitmask, sta->ht_cap.mcs.rx_mask, + if (sta->deflink.ht_cap.ht_supported) + memcpy(ra_info->rx_mcs_bitmask, + sta->deflink.ht_cap.mcs.rx_mask, HT_MCS_MASK_NUM); tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state)); state = (struct sta_rec_state *)tlv; state->state = sta_state; - if (sta->vht_cap.vht_supported) { - state->vht_opmode = sta->bandwidth; - state->vht_opmode |= (sta->rx_nss - 1) << + if (sta->deflink.vht_cap.vht_supported) { + state->vht_opmode = sta->deflink.bandwidth; + state->vht_opmode |= (sta->deflink.rx_nss - 1) << IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; } } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_tlv); -static void -mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - void *sta_wtbl, void *wtbl_tlv) +void mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb, + struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) { struct wtbl_smps *smps; struct tlv *tlv; @@ -831,30 +898,39 @@ mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), wtbl_tlv, sta_wtbl); smps = (struct wtbl_smps *)tlv; - - if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) - smps->smps = true; + smps->smps = (sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC); } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_smps_tlv); void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv) + void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc) { struct wtbl_ht *ht = NULL; struct tlv *tlv; u32 flags = 0; - if (sta->ht_cap.ht_supported) { + if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_6ghz_capa.capa) { tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), wtbl_tlv, sta_wtbl); ht = (struct wtbl_ht *)tlv; - ht->ldpc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); - ht->af = sta->ht_cap.ampdu_factor; - ht->mm = sta->ht_cap.ampdu_density; + ht->ldpc = ht_ldpc && + !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); + + if (sta->deflink.ht_cap.ht_supported) { + ht->af = sta->deflink.ht_cap.ampdu_factor; + ht->mm = sta->deflink.ht_cap.ampdu_density; + } else { + ht->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); + ht->mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); + } + ht->ht = true; } - if (sta->vht_cap.vht_supported) { + if (sta->deflink.vht_cap.vht_supported || sta->deflink.he_6ghz_capa.capa) { struct wtbl_vht *vht; u8 af; @@ -862,18 +938,19 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, sizeof(*vht), wtbl_tlv, sta_wtbl); vht = (struct wtbl_vht *)tlv; - vht->ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + vht->ldpc = vht_ldpc && + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); vht->vht = true; af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->vht_cap.cap); + sta->deflink.vht_cap.cap); if (ht) ht->af = max(ht->af, af); } mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv); - if (!is_mt7921(dev) && sta->ht_cap.ht_supported) { + if (is_connac_v1(dev) && sta->deflink.ht_cap.ht_supported) { /* sgi */ u32 msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; @@ -883,15 +960,15 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, sizeof(*raw), wtbl_tlv, sta_wtbl); - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) flags |= MT_WTBL_W5_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) flags |= MT_WTBL_W5_SHORT_GI_40; - if (sta->vht_cap.vht_supported) { - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + if (sta->deflink.vht_cap.vht_supported) { + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) flags |= MT_WTBL_W5_SHORT_GI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) flags |= MT_WTBL_W5_SHORT_GI_160; } raw = (struct wtbl_raw *)tlv; @@ -941,7 +1018,8 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy, sta_wtbl, wtbl_hdr); if (info->sta) mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, - sta_wtbl, wtbl_hdr); + sta_wtbl, wtbl_hdr, + true, true); } return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); @@ -975,13 +1053,13 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb, ba->rst_ba_sb = 1; } - if (is_mt7921(dev)) { + if (!is_connac_v1(dev)) { ba->ba_winsize = enable ? cpu_to_le16(params->buf_size) : 0; return; } if (enable && tx) { - u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; + static const u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; int i; for (i = 7; i > 0; i--) { @@ -1071,7 +1149,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN); - cmd = enable ? MCU_UNI_CMD_DEV_INFO_UPDATE : MCU_UNI_CMD_BSS_INFO_UPDATE; + cmd = enable ? MCU_UNI_CMD(DEV_INFO_UPDATE) : MCU_UNI_CMD(BSS_INFO_UPDATE); data = enable ? (void *)&dev_req : (void *)&basic_req; len = enable ? sizeof(dev_req) : sizeof(basic_req); @@ -1079,7 +1157,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, if (err < 0) return err; - cmd = enable ? MCU_UNI_CMD_BSS_INFO_UPDATE : MCU_UNI_CMD_DEV_INFO_UPDATE; + cmd = enable ? MCU_UNI_CMD(BSS_INFO_UPDATE) : MCU_UNI_CMD(DEV_INFO_UPDATE); data = enable ? (void *)&basic_req : (void *)&dev_req; len = enable ? sizeof(basic_req) : sizeof(dev_req); @@ -1108,7 +1186,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv); int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, - bool enable, bool tx) + int cmd, bool enable, bool tx) { struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv; struct wtbl_req_hdr *wtbl_hdr; @@ -1131,7 +1209,7 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, mt76_connac_mcu_wtbl_ba_tlv(dev, skb, params, enable, tx, sta_wtbl, wtbl_hdr); - ret = mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD_STA_REC_UPDATE, true); + ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true); if (ret) return ret; @@ -1141,15 +1219,12 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx); - return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD_STA_REC_UPDATE, - true); + return mt76_mcu_skb_send_msg(dev, skb, cmd, true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba); -static u8 -mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, - enum nl80211_band band, - struct ieee80211_sta *sta) +u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta) { struct mt76_dev *dev = phy->dev; const struct ieee80211_sta_he_cap *he_cap; @@ -1157,13 +1232,13 @@ mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta_ht_cap *ht_cap; u8 mode = 0; - if (!is_mt7921(dev)) + if (is_connac_v1(dev)) return 0x38; if (sta) { - ht_cap = &sta->ht_cap; - vht_cap = &sta->vht_cap; - he_cap = &sta->he_cap; + ht_cap = &sta->deflink.ht_cap; + vht_cap = &sta->deflink.vht_cap; + he_cap = &sta->deflink.he_cap; } else { struct ieee80211_supported_band *sband; @@ -1179,9 +1254,9 @@ mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, if (ht_cap->ht_supported) mode |= PHY_MODE_GN; - if (he_cap->has_he) + if (he_cap && he_cap->has_he) mode |= PHY_MODE_AX_24G; - } else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) { + } else if (band == NL80211_BAND_5GHZ) { mode |= PHY_MODE_A; if (ht_cap->ht_supported) @@ -1190,18 +1265,18 @@ mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, if (vht_cap->vht_supported) mode |= PHY_MODE_AC; - if (he_cap->has_he) { - if (band == NL80211_BAND_6GHZ) - mode |= PHY_MODE_AX_6G; - else - mode |= PHY_MODE_AX_5G; - } + if (he_cap && he_cap->has_he) + mode |= PHY_MODE_AX_5G; + } else if (band == NL80211_BAND_6GHZ) { + mode |= PHY_MODE_A | PHY_MODE_AN | + PHY_MODE_AC | PHY_MODE_AX_5G; } return mode; } +EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode); -static const struct ieee80211_sta_he_cap * +const struct ieee80211_sta_he_cap * mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) { enum nl80211_band band = phy->chandef.chan->band; @@ -1211,6 +1286,7 @@ mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) return ieee80211_get_he_iftype_cap(sband, vif->type); } +EXPORT_SYMBOL_GPL(mt76_connac_get_he_phy_cap); #define DEFAULT_HE_PE_DURATION 4 #define DEFAULT_HE_DURATION_RTS_THRES 1023 @@ -1318,7 +1394,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; basic_req.basic.hw_bss_idx = idx; if (band == NL80211_BAND_6GHZ) - basic_req.basic.phymode_ext = BIT(0); + basic_req.basic.phymode_ext = PHY_MODE_AX_6G; basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, NULL); basic_req.basic.nonht_basic_phy = cpu_to_le16(basic_phy); @@ -1331,6 +1407,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, else conn_type = CONNECTION_INFRA_AP; basic_req.basic.conn_type = cpu_to_le32(conn_type); + /* Fully active/deactivate BSS network in AP mode only */ + basic_req.basic.active = enable; break; case NL80211_IFTYPE_STATION: if (vif->p2p) @@ -1352,7 +1430,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, basic_req.basic.sta_idx = cpu_to_le16(wcid->idx); basic_req.basic.conn_state = !enable; - err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD_BSS_INFO_UPDATE, &basic_req, + err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &basic_req, sizeof(basic_req), true); if (err < 0) return err; @@ -1390,7 +1468,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, mt76_connac_mcu_uni_bss_he_tlv(phy, vif, (struct tlv *)&he_req.he); - err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD_BSS_INFO_UPDATE, + err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &he_req, sizeof(he_req), true); if (err < 0) return err; @@ -1428,7 +1506,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan) rlm_req.rlm.sco = 3; /* SCB */ - return mt76_mcu_send_msg(mdev, MCU_UNI_CMD_BSS_INFO_UPDATE, &rlm_req, + return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req, sizeof(rlm_req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss); @@ -1443,7 +1521,6 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, int ext_channels_num = max_t(int, sreq->n_channels - 32, 0); struct ieee80211_channel **scan_list = sreq->channels; struct mt76_dev *mdev = phy->dev; - bool ext_phy = phy == mdev->phy2; struct mt76_connac_mcu_scan_channel *chan; struct mt76_connac_hw_scan_req *req; struct sk_buff *skb; @@ -1457,7 +1534,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req = (struct mt76_connac_hw_scan_req *)skb_put(skb, sizeof(*req)); - req->seq_num = mvif->scan_seq_num | ext_phy << 7; + req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; req->bss_idx = mvif->idx; req->scan_type = sreq->n_ssids ? 1 : 0; req->probe_req_num = sreq->n_ssids ? 2 : 0; @@ -1522,7 +1599,8 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, req->scan_func |= SCAN_FUNC_RANDOM_MAC; } - err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_START_HW_SCAN, false); + err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CE_CMD(START_HW_SCAN), + false); if (err < 0) clear_bit(MT76_HW_SCANNING, &phy->state); @@ -1550,8 +1628,8 @@ int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy, ieee80211_scan_completed(phy->hw, &info); } - return mt76_mcu_send_msg(phy->dev, MCU_CMD_CANCEL_HW_SCAN, &req, - sizeof(req), false); + return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(CANCEL_HW_SCAN), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_cancel_hw_scan); @@ -1564,7 +1642,6 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, struct mt76_connac_mcu_scan_channel *chan; struct mt76_connac_sched_scan_req *req; struct mt76_dev *mdev = phy->dev; - bool ext_phy = phy == mdev->phy2; struct cfg80211_match_set *match; struct cfg80211_ssid *ssid; struct sk_buff *skb; @@ -1578,7 +1655,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, req = (struct mt76_connac_sched_scan_req *)skb_put(skb, sizeof(*req)); req->version = 1; - req->seq_num = mvif->scan_seq_num | ext_phy << 7; + req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { u8 *addr = is_mt7663(phy->dev) ? req->mt7663.random_mac @@ -1637,7 +1714,8 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy, memcpy(skb_put(skb, sreq->ie_len), sreq->ie, sreq->ie_len); } - return mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_SCHED_SCAN_REQ, false); + return mt76_mcu_skb_send_msg(mdev, skb, MCU_CE_CMD(SCHED_SCAN_REQ), + false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_req); @@ -1657,8 +1735,8 @@ int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy, else clear_bit(MT76_HW_SCHED_SCANNING, &phy->state); - return mt76_mcu_send_msg(phy->dev, MCU_CMD_SCHED_SCAN_ENABLE, &req, - sizeof(req), false); + return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(SCHED_SCAN_ENABLE), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_enable); @@ -1670,8 +1748,8 @@ int mt76_connac_mcu_chip_config(struct mt76_dev *dev) memcpy(req.data, "assert", 7); - return mt76_mcu_send_msg(dev, MCU_CMD_CHIP_CONFIG, &req, sizeof(req), - false); + return mt76_mcu_send_msg(dev, MCU_CE_CMD(CHIP_CONFIG), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_chip_config); @@ -1683,8 +1761,8 @@ int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable) snprintf(req.data, sizeof(req.data), "KeepFullPwr %d", !enable); - return mt76_mcu_send_msg(dev, MCU_CMD_CHIP_CONFIG, &req, sizeof(req), - false); + return mt76_mcu_send_msg(dev, MCU_CE_CMD(CHIP_CONFIG), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_deep_sleep); @@ -1786,8 +1864,8 @@ int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy) struct sk_buff *skb; int ret, i; - ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CMD_GET_NIC_CAPAB, NULL, - 0, true, &skb); + ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB), + NULL, 0, true, &skb); if (ret) return ret; @@ -1885,30 +1963,6 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, } } -static s8 mt76_connac_get_sar_power(struct mt76_phy *phy, - struct ieee80211_channel *chan, - s8 target_power) -{ - const struct cfg80211_sar_capa *capa = phy->hw->wiphy->sar_capa; - struct mt76_freq_range_power *frp = phy->frp; - int freq, i; - - if (!capa || !frp) - return target_power; - - freq = ieee80211_channel_to_frequency(chan->hw_value, chan->band); - for (i = 0 ; i < capa->num_freq_ranges; i++) { - if (frp[i].range && - freq >= frp[i].range->start_freq && - freq < frp[i].range->end_freq) { - target_power = min_t(s8, frp[i].power, target_power); - break; - } - } - - return target_power; -} - static s8 mt76_connac_get_ch_power(struct mt76_phy *phy, struct ieee80211_channel *chan, s8 target_power) @@ -2008,12 +2062,12 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, } batch_size = DIV_ROUND_UP(n_chan, batch_len); - if (!phy->cap.has_5ghz) - last_ch = chan_list_2ghz[n_chan - 1]; - else if (phy->cap.has_6ghz) - last_ch = chan_list_6ghz[n_chan - 1]; + if (phy->cap.has_6ghz) + last_ch = chan_list_6ghz[ARRAY_SIZE(chan_list_6ghz) - 1]; + else if (phy->cap.has_5ghz) + last_ch = chan_list_5ghz[ARRAY_SIZE(chan_list_5ghz) - 1]; else - last_ch = chan_list_5ghz[n_chan - 1]; + last_ch = chan_list_2ghz[ARRAY_SIZE(chan_list_2ghz) - 1]; for (i = 0; i < batch_size; i++) { struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {}; @@ -2053,8 +2107,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, reg_power = mt76_connac_get_ch_power(phy, &chan, tx_power); - sar_power = mt76_connac_get_sar_power(phy, &chan, - reg_power); + sar_power = mt76_get_sar_power(phy, &chan, reg_power); mt76_get_rate_power_limits(phy, &chan, &limits, sar_power); @@ -2070,7 +2123,8 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, memcpy(skb->data, &tx_power_tlv, sizeof(tx_power_tlv)); err = mt76_mcu_skb_send_msg(dev, skb, - MCU_CMD_SET_RATE_TX_POWER, false); + MCU_CE_CMD(SET_RATE_TX_POWER), + false); if (err < 0) return err; } @@ -2109,8 +2163,10 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, struct mt76_vif *vif, struct ieee80211_bss_conf *info) { + struct ieee80211_vif *mvif = container_of(info, struct ieee80211_vif, + bss_conf); struct sk_buff *skb; - int i, len = min_t(int, info->arp_addr_cnt, + int i, len = min_t(int, mvif->cfg.arp_addr_cnt, IEEE80211_BSS_ARP_ADDR_LIST_LEN); struct { struct { @@ -2137,13 +2193,10 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, return -ENOMEM; skb_put_data(skb, &req_hdr, sizeof(req_hdr)); - for (i = 0; i < len; i++) { - u8 *addr = (u8 *)skb_put(skb, sizeof(__be32)); + for (i = 0; i < len; i++) + skb_put_data(skb, &mvif->cfg.arp_addr_list[i], sizeof(__be32)); - memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); - } - - return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD_OFFLOAD, true); + return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_arp_filter); @@ -2162,8 +2215,8 @@ int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw, .bss_idx = mvif->idx, }; - return mt76_mcu_send_msg(phy->dev, MCU_CMD_SET_P2P_OPPPS, &req, - sizeof(req), false); + return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(SET_P2P_OPPPS), + &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_p2p_oppps); @@ -2249,7 +2302,8 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw, memcpy(gtk_tlv->kck, key->kck, NL80211_KCK_LEN); memcpy(gtk_tlv->replay_ctr, key->replay_ctr, NL80211_REPLAY_CTR_LEN); - return mt76_mcu_skb_send_msg(phy->dev, skb, MCU_UNI_CMD_OFFLOAD, true); + return mt76_mcu_skb_send_msg(phy->dev, skb, + MCU_UNI_CMD(OFFLOAD), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_gtk_rekey); @@ -2275,8 +2329,8 @@ mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif, }, }; - return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req, + sizeof(req), true); } static int @@ -2301,8 +2355,8 @@ mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, }, }; - return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req, + sizeof(req), true); } static int @@ -2331,8 +2385,8 @@ mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev, }, }; - return mt76_mcu_send_msg(dev, MCU_UNI_CMD_SUSPEND, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req, + sizeof(req), true); } static int @@ -2366,7 +2420,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev, memcpy(ptlv->pattern, pattern->pattern, pattern->pattern_len); memcpy(ptlv->mask, pattern->mask, DIV_ROUND_UP(pattern->pattern_len, 8)); - return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD_SUSPEND, true); + return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true); } static int @@ -2418,8 +2472,8 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, else if (mt76_is_sdio(dev)) req.wow_ctrl_tlv.wakeup_hif = WOW_GPIO; - return mt76_mcu_send_msg(dev, MCU_UNI_CMD_SUSPEND, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req, + sizeof(req), true); } int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) @@ -2452,8 +2506,8 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) else if (mt76_is_sdio(dev)) req.hdr.hif_type = 0; - return mt76_mcu_send_msg(dev, MCU_UNI_CMD_HIF_CTRL, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(HIF_CTRL), &req, + sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_hif_suspend); @@ -2461,7 +2515,7 @@ void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt76_phy *phy = priv; - bool suspend = test_bit(MT76_STATE_SUSPEND, &phy->state); + bool suspend = !test_bit(MT76_STATE_RUNNING, &phy->state); struct ieee80211_hw *hw = phy->hw; struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; int i; @@ -2488,8 +2542,8 @@ u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset) .addr = cpu_to_le32(offset), }; - return mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, &req, sizeof(req), - true); + return mt76_mcu_send_msg(dev, MCU_CE_QUERY(REG_READ), &req, + sizeof(req), true); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_rr); @@ -2503,9 +2557,565 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val) .val = cpu_to_le32(val), }; - mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false); + mt76_mcu_send_msg(dev, MCU_CE_CMD(REG_WRITE), &req, + sizeof(req), false); } EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_wr); +static int +mt76_connac_mcu_sta_key_tlv(struct mt76_connac_sta_key_conf *sta_key_conf, + struct sk_buff *skb, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + struct sta_rec_sec *sec; + u32 len = sizeof(*sec); + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); + sec = (struct sta_rec_sec *)tlv; + sec->add = cmd; + + if (cmd == SET_KEY) { + struct sec_key *sec_key; + u8 cipher; + + cipher = mt76_connac_mcu_get_cipher(key->cipher); + if (cipher == MCU_CIPHER_NONE) + return -EOPNOTSUPP; + + sec_key = &sec->key[0]; + sec_key->cipher_len = sizeof(*sec_key); + + if (cipher == MCU_CIPHER_BIP_CMAC_128) { + sec_key->cipher_id = MCU_CIPHER_AES_CCMP; + sec_key->key_id = sta_key_conf->keyidx; + sec_key->key_len = 16; + memcpy(sec_key->key, sta_key_conf->key, 16); + + sec_key = &sec->key[1]; + sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; + sec_key->cipher_len = sizeof(*sec_key); + sec_key->key_len = 16; + memcpy(sec_key->key, key->key, 16); + sec->n_cipher = 2; + } else { + sec_key->cipher_id = cipher; + sec_key->key_id = key->keyidx; + sec_key->key_len = key->keylen; + memcpy(sec_key->key, key->key, key->keylen); + + 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); + } + + /* store key_conf for BIP batch update */ + if (cipher == MCU_CIPHER_AES_CCMP) { + memcpy(sta_key_conf->key, key->key, key->keylen); + sta_key_conf->keyidx = key->keyidx; + } + + len -= sizeof(*sec_key); + sec->n_cipher = 1; + } + } else { + len -= sizeof(sec->key); + sec->n_cipher = 0; + } + sec->len = cpu_to_le16(len); + + return 0; +} + +int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct mt76_connac_sta_key_conf *sta_key_conf, + struct ieee80211_key_conf *key, int mcu_cmd, + struct mt76_wcid *wcid, enum set_key_cmd cmd) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct sk_buff *skb; + int ret; + + skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd); + if (ret) + return ret; + + return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_key); + +/* SIFS 20us + 512 byte beacon transmitted by 1Mbps (3906us) */ +#define BCN_TX_ESTIMATE_TIME (4096 + 20) +void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif *mvif) +{ + struct bss_info_ext_bss *ext; + int ext_bss_idx, tsf_offset; + struct tlv *tlv; + + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; + if (ext_bss_idx < 0) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); + + ext = (struct bss_info_ext_bss *)tlv; + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_ext_tlv); + +int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct mt76_phy *phy, u16 wlan_idx, + bool enable) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; + struct bss_info_basic *bss; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); + bss = (struct bss_info_basic *)tlv; + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_MONITOR: + break; + case NL80211_IFTYPE_AP: + if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) { + u8 bssid_id = vif->bss_conf.bssid_indicator; + struct wiphy *wiphy = phy->hw->wiphy; + + if (bssid_id > ilog2(wiphy->mbssid_max_interfaces)) + return -EINVAL; + + bss->non_tx_bssid = vif->bss_conf.bssid_index; + bss->max_bssid = bssid_id; + } + break; + case NL80211_IFTYPE_STATION: + if (enable) { + rcu_read_lock(); + if (!sta) + sta = ieee80211_find_sta(vif, + vif->bss_conf.bssid); + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (sta) { + struct mt76_wcid *wcid; + + wcid = (struct mt76_wcid *)sta->drv_priv; + wlan_idx = wcid->idx; + } + rcu_read_unlock(); + } + break; + case NL80211_IFTYPE_ADHOC: + type = NETWORK_IBSS; + break; + default: + WARN_ON(1); + break; + } + + bss->network_type = cpu_to_le32(type); + bss->bmc_wcid_lo = to_wcid_lo(wlan_idx); + bss->bmc_wcid_hi = to_wcid_hi(wlan_idx); + bss->wmm_idx = mvif->wmm_idx; + bss->active = enable; + bss->cipher = mvif->cipher; + + if (vif->type != NL80211_IFTYPE_MONITOR) { + struct cfg80211_chan_def *chandef = &phy->chandef; + + memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); + bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + bss->dtim_period = vif->bss_conf.dtim_period; + bss->phy_mode = mt76_connac_get_phy_mode(phy, vif, + chandef->chan->band, NULL); + } else { + memcpy(bss->bssid, phy->macaddr, ETH_ALEN); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_basic_tlv); + +#define ENTER_PM_STATE 1 +#define EXIT_PM_STATE 2 +int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter) +{ + struct { + u8 pm_number; + u8 pm_state; + u8 bssid[ETH_ALEN]; + u8 dtim_period; + u8 wlan_idx_lo; + __le16 bcn_interval; + __le32 aid; + __le32 rx_filter; + u8 band_idx; + u8 wlan_idx_hi; + u8 rsv[2]; + __le32 feature; + u8 omac_idx; + u8 wmm_idx; + u8 bcn_loss_cnt; + u8 bcn_sp_duration; + } __packed req = { + .pm_number = 5, + .pm_state = enter ? ENTER_PM_STATE : EXIT_PM_STATE, + .band_idx = band, + }; + + return mt76_mcu_send_msg(dev, MCU_EXT_CMD(PM_STATE_CTRL), &req, + sizeof(req), true); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_pm); + +int mt76_connac_mcu_restart(struct mt76_dev *dev) +{ + struct { + u8 power_mode; + u8 rsv[3]; + } req = { + .power_mode = 1, + }; + + return mt76_mcu_send_msg(dev, MCU_CMD(NIC_POWER_CTRL), &req, + sizeof(req), false); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_restart); + +int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index, + u8 rx_sel, u8 val) +{ + struct { + u8 ctrl; + u8 rdd_idx; + u8 rdd_rx_sel; + u8 val; + u8 rsv[4]; + } __packed req = { + .ctrl = cmd, + .rdd_idx = index, + .rdd_rx_sel = rx_sel, + .val = val, + }; + + return mt76_mcu_send_msg(dev, MCU_EXT_CMD(SET_RDD_CTRL), &req, + sizeof(req), true); +} +EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd); + +static int +mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev, + const struct mt76_connac2_fw_trailer *hdr, + const u8 *data, bool is_wa) +{ + int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096; + u32 override = 0, option = 0; + + for (i = 0; i < hdr->n_region; i++) { + const struct mt76_connac2_fw_region *region; + u32 len, addr, mode; + int err; + + region = (const void *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); + mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set, + is_wa); + len = le32_to_cpu(region->len); + addr = le32_to_cpu(region->addr); + + if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) + override = addr; + + err = mt76_connac_mcu_init_download(dev, addr, len, mode); + if (err) { + dev_err(dev->dev, "Download request failed\n"); + return err; + } + + err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER), + data + offset, len, max_len); + if (err) { + dev_err(dev->dev, "Failed to send firmware.\n"); + return err; + } + + offset += len; + } + + if (override) + option |= FW_START_OVERRIDE; + if (is_wa) + option |= FW_START_WORKING_PDA_CR4; + + return mt76_connac_mcu_start_firmware(dev, override, option); +} + +int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm, + const char *fw_wa) +{ + const struct mt76_connac2_fw_trailer *hdr; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, fw_wm, dev->dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false); + if (ret) { + dev_err(dev->dev, "Failed to start WM firmware\n"); + goto out; + } + + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + + release_firmware(fw); + + if (!fw_wa) + return 0; + + ret = request_firmware(&fw, fw_wa, dev->dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true); + if (ret) { + dev_err(dev->dev, "Failed to start WA firmware\n"); + goto out; + } + + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + +out: + release_firmware(fw); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_connac2_load_ram); + +static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info) +{ + u32 mode = DL_MODE_NEED_RSP; + + if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT) + return mode; + + switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) { + case PATCH_SEC_ENC_TYPE_PLAIN: + break; + case PATCH_SEC_ENC_TYPE_AES: + mode |= DL_MODE_ENCRYPT; + mode |= FIELD_PREP(DL_MODE_KEY_IDX, + (info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX; + mode |= DL_MODE_RESET_SEC_IV; + break; + case PATCH_SEC_ENC_TYPE_SCRAMBLE: + mode |= DL_MODE_ENCRYPT; + mode |= DL_CONFIG_ENCRY_MODE_SEL; + mode |= DL_MODE_RESET_SEC_IV; + break; + default: + dev_err(dev->dev, "Encryption type not support!\n"); + } + + return mode; +} + +int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name) +{ + int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096; + const struct mt76_connac2_patch_hdr *hdr; + const struct firmware *fw = NULL; + + sem = mt76_connac_mcu_patch_sem_ctrl(dev, true); + switch (sem) { + case PATCH_IS_DL: + return 0; + case PATCH_NOT_DL_SEM_SUCCESS: + break; + default: + dev_err(dev->dev, "Failed to get patch semaphore\n"); + return -EAGAIN; + } + + ret = request_firmware(&fw, fw_name, dev->dev); + if (ret) + goto out; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const void *)fw->data; + dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", + be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); + + for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { + struct mt76_connac2_patch_sec *sec; + u32 len, addr, mode; + const u8 *dl; + u32 sec_info; + + sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec)); + if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) != + PATCH_SEC_TYPE_INFO) { + ret = -EINVAL; + goto out; + } + + addr = be32_to_cpu(sec->info.addr); + len = be32_to_cpu(sec->info.len); + dl = fw->data + be32_to_cpu(sec->offs); + sec_info = be32_to_cpu(sec->info.sec_key_idx); + mode = mt76_connac2_get_data_mode(dev, sec_info); + + ret = mt76_connac_mcu_init_download(dev, addr, len, mode); + if (ret) { + dev_err(dev->dev, "Download request failed\n"); + goto out; + } + + ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER), + dl, len, max_len); + if (ret) { + dev_err(dev->dev, "Failed to send patch\n"); + goto out; + } + } + + ret = mt76_connac_mcu_start_patch(dev); + if (ret) + dev_err(dev->dev, "Failed to start patch\n"); + +out: + sem = mt76_connac_mcu_patch_sem_ctrl(dev, false); + switch (sem) { + case PATCH_REL_SEM_SUCCESS: + break; + default: + ret = -EAGAIN; + dev_err(dev->dev, "Failed to release patch semaphore\n"); + break; + } + + release_firmware(fw); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_connac2_load_patch); + +int mt76_connac2_mcu_fill_message(struct mt76_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); + struct mt76_connac2_mcu_uni_txd *uni_txd; + struct mt76_connac2_mcu_txd *mcu_txd; + __le32 *txd; + u32 val; + u8 seq; + + /* TODO: make dynamic based on msg type */ + dev->mcu.timeout = 20 * HZ; + + seq = ++dev->mcu.msg_seq & 0xf; + if (!seq) + seq = ++dev->mcu.msg_seq & 0xf; + + if (cmd == MCU_CMD(FW_SCATTER)) + goto exit; + + txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd); + txd = (__le32 *)skb_push(skb, txd_len); + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | + FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) | + FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0); + txd[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD); + txd[1] = cpu_to_le32(val); + + if (cmd & __MCU_CMD_FIELD_UNI) { + uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd; + uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + uni_txd->cid = cpu_to_le16(mcu_cmd); + uni_txd->s2d_index = MCU_S2D_H2N; + uni_txd->pkt_type = MCU_PKT_ID; + uni_txd->seq = seq; + + goto exit; + } + + mcu_txd = (struct mt76_connac2_mcu_txd *)txd; + mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); + mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, + MT_TX_MCU_PORT_RX_Q0)); + mcu_txd->pkt_type = MCU_PKT_ID; + mcu_txd->seq = seq; + mcu_txd->cid = mcu_cmd; + mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd); + + if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) { + if (cmd & __MCU_CMD_FIELD_QUERY) + mcu_txd->set_query = MCU_Q_QUERY; + else + mcu_txd->set_query = MCU_Q_SET; + mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid; + } else { + mcu_txd->set_query = MCU_Q_NA; + } + + if (cmd & __MCU_CMD_FIELD_WA) + mcu_txd->s2d_index = MCU_S2D_H2C; + else + mcu_txd->s2d_index = MCU_S2D_H2N; + +exit: + if (wait_seq) + *wait_seq = seq; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message); + MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 4e2c9dafd776..718f427d8f6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -6,11 +6,260 @@ #include "mt76_connac.h" +#define FW_FEATURE_SET_ENCRYPT BIT(0) +#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) +#define FW_FEATURE_ENCRY_MODE BIT(4) +#define FW_FEATURE_OVERRIDE_ADDR BIT(5) +#define FW_FEATURE_NON_DL BIT(6) + +#define DL_MODE_ENCRYPT BIT(0) +#define DL_MODE_KEY_IDX GENMASK(2, 1) +#define DL_MODE_RESET_SEC_IV BIT(3) +#define DL_MODE_WORKING_PDA_CR4 BIT(4) +#define DL_MODE_VALID_RAM_ENTRY BIT(5) +#define DL_CONFIG_ENCRY_MODE_SEL BIT(6) +#define DL_MODE_NEED_RSP BIT(31) + +#define FW_START_OVERRIDE BIT(0) +#define FW_START_WORKING_PDA_CR4 BIT(2) + +#define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0) +#define PATCH_SEC_TYPE_MASK GENMASK(15, 0) +#define PATCH_SEC_TYPE_INFO 0x2 + +#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24) +#define PATCH_SEC_ENC_TYPE_PLAIN 0x00 +#define PATCH_SEC_ENC_TYPE_AES 0x01 +#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02 +#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0) +#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0) + +enum { + FW_TYPE_DEFAULT = 0, + FW_TYPE_CLC = 2, + FW_TYPE_MAX_NUM = 255 +}; + +#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) +#define MCU_PKT_ID 0xa0 + +struct mt76_connac2_mcu_txd { + __le32 txd[8]; + + __le16 len; + __le16 pq_id; + + u8 cid; + u8 pkt_type; + u8 set_query; /* FW don't care */ + u8 seq; + + u8 uc_d2b0_rev; + u8 ext_cid; + u8 s2d_index; + u8 ext_cid_ack; + + u32 rsv[5]; +} __packed __aligned(4); + +/** + * struct mt76_connac2_mcu_uni_txd - mcu command descriptor for firmware v3 + * @txd: hardware descriptor + * @len: total length not including txd + * @cid: command identifier + * @pkt_type: must be 0xa0 (cmd packet by long format) + * @frag_n: fragment number + * @seq: sequence number + * @checksum: 0 mean there is no checksum + * @s2d_index: index for command source and destination + * Definition | value | note + * CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM + * CMD_S2D_IDX_C2N | 0x01 | command from WA to WM + * CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA + * CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM + * + * @option: command option + * BIT[0]: UNI_CMD_OPT_BIT_ACK + * set to 1 to request a fw reply + * if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY + * is set, mcu firmware will send response event EID = 0x01 + * (UNI_EVENT_ID_CMD_RESULT) to the host. + * BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD + * 0: original command + * 1: unified command + * BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY + * 0: QUERY command + * 1: SET command + */ +struct mt76_connac2_mcu_uni_txd { + __le32 txd[8]; + + /* DW1 */ + __le16 len; + __le16 cid; + + /* DW2 */ + u8 rsv; + u8 pkt_type; + u8 frag_n; + u8 seq; + + /* DW3 */ + __le16 checksum; + u8 s2d_index; + u8 option; + + /* DW4 */ + u8 rsv1[4]; +} __packed __aligned(4); + +struct mt76_connac2_mcu_rxd { + __le32 rxd[6]; + + __le16 len; + __le16 pkt_type_id; + + u8 eid; + u8 seq; + u8 rsv[2]; + + u8 ext_eid; + u8 rsv1[2]; + u8 s2d_index; +}; + +struct mt76_connac2_patch_hdr { + char build_date[16]; + char platform[4]; + __be32 hw_sw_ver; + __be32 patch_ver; + __be16 checksum; + u16 rsv; + struct { + __be32 patch_ver; + __be32 subsys; + __be32 feature; + __be32 n_region; + __be32 crc; + u32 rsv[11]; + } desc; +} __packed; + +struct mt76_connac2_patch_sec { + __be32 type; + __be32 offs; + __be32 size; + union { + __be32 spec[13]; + struct { + __be32 addr; + __be32 len; + __be32 sec_key_idx; + __be32 align_len; + u32 rsv[9]; + } info; + }; +} __packed; + +struct mt76_connac2_fw_trailer { + u8 chip_id; + u8 eco_code; + u8 n_region; + u8 format_ver; + u8 format_flag; + u8 rsv[2]; + char fw_ver[10]; + char build_date[15]; + __le32 crc; +} __packed; + +struct mt76_connac2_fw_region { + __le32 decomp_crc; + __le32 decomp_len; + __le32 decomp_blk_sz; + u8 rsv[4]; + __le32 addr; + __le32 len; + u8 feature_set; + u8 type; + u8 rsv1[14]; +} __packed; + struct tlv { __le16 tag; __le16 len; } __packed; +struct bss_info_omac { + __le16 tag; + __le16 len; + u8 hw_bss_idx; + u8 omac_idx; + u8 band_idx; + u8 rsv0; + __le32 conn_type; + u32 rsv1; +} __packed; + +struct bss_info_basic { + __le16 tag; + __le16 len; + __le32 network_type; + u8 active; + u8 rsv0; + __le16 bcn_interval; + u8 bssid[ETH_ALEN]; + u8 wmm_idx; + u8 dtim_period; + u8 bmc_wcid_lo; + u8 cipher; + u8 phy_mode; + u8 max_bssid; /* max BSSID. range: 1 ~ 8, 0: MBSSID disabled */ + u8 non_tx_bssid;/* non-transmitted BSSID, 0: transmitted BSSID */ + u8 bmc_wcid_hi; /* high Byte and version */ + u8 rsv[2]; +} __packed; + +struct bss_info_rf_ch { + __le16 tag; + __le16 len; + u8 pri_ch; + u8 center_ch0; + u8 center_ch1; + u8 bw; + u8 he_ru26_block; /* 1: don't send HETB in RU26, 0: allow */ + u8 he_all_disable; /* 1: disallow all HETB, 0: allow */ + u8 rsv[2]; +} __packed; + +struct bss_info_ext_bss { + __le16 tag; + __le16 len; + __le32 mbss_tsf_offset; /* in unit of us */ + u8 rsv[8]; +} __packed; + +enum { + BSS_INFO_OMAC, + BSS_INFO_BASIC, + BSS_INFO_RF_CH, /* optional, for BT/LTE coex */ + BSS_INFO_PM, /* sta only */ + BSS_INFO_UAPSD, /* sta only */ + BSS_INFO_ROAM_DETECT, /* obsoleted */ + BSS_INFO_LQ_RM, /* obsoleted */ + BSS_INFO_EXT_BSS, + BSS_INFO_BMC_RATE, /* for bmc rate control in CR4 */ + BSS_INFO_SYNC_MODE, /* obsoleted */ + BSS_INFO_RA, + BSS_INFO_HW_AMSDU, + BSS_INFO_BSS_COLOR, + BSS_INFO_HE_BASIC, + BSS_INFO_PROTECT_INFO, + BSS_INFO_OFFLOAD, + BSS_INFO_11V_MBSSID, + BSS_INFO_MAX_NUM +}; + /* sta_rec */ struct sta_ntlv_hdr { @@ -54,7 +303,7 @@ struct sta_rec_vht { __le32 vht_cap; __le16 vht_rx_mcs_map; __le16 vht_tx_mcs_map; - /* mt7921 */ + /* mt7915 - mt7921 */ u8 rts_bw_sig; u8 rsv[3]; } __packed; @@ -152,6 +401,191 @@ struct sta_rec_he_6g_capa { u8 rsv[2]; } __packed; +struct sec_key { + u8 cipher_id; + u8 cipher_len; + u8 key_id; + u8 key_len; + u8 key[32]; +} __packed; + +struct sta_rec_sec { + __le16 tag; + __le16 len; + u8 add; + u8 n_cipher; + u8 rsv[2]; + + struct sec_key key[2]; +} __packed; + +struct sta_rec_bf { + __le16 tag; + __le16 len; + + __le16 pfmu; /* 0xffff: no access right for PFMU */ + bool su_mu; /* 0: SU, 1: MU */ + u8 bf_cap; /* 0: iBF, 1: eBF */ + u8 sounding_phy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + u8 ndpa_rate; + u8 ndp_rate; + u8 rept_poll_rate; + u8 tx_mode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT ... */ + u8 ncol; + u8 nrow; + u8 bw; /* 0: 20M, 1: 40M, 2: 80M, 3: 160M */ + + u8 mem_total; + u8 mem_20m; + struct { + u8 row; + u8 col: 6, row_msb: 2; + } mem[4]; + + __le16 smart_ant; + u8 se_idx; + u8 auto_sounding; /* b7: low traffic indicator + * b6: Stop sounding for this entry + * b5 ~ b0: postpone sounding + */ + u8 ibf_timeout; + u8 ibf_dbw; + u8 ibf_ncol; + u8 ibf_nrow; + u8 nrow_bw160; + u8 ncol_bw160; + u8 ru_start_idx; + u8 ru_end_idx; + + bool trigger_su; + bool trigger_mu; + bool ng16_su; + bool ng16_mu; + bool codebook42_su; + bool codebook75_mu; + + u8 he_ltf; + u8 rsv[3]; +} __packed; + +struct sta_rec_bfee { + __le16 tag; + __le16 len; + bool fb_identity_matrix; /* 1: feedback identity matrix */ + bool ignore_feedback; /* 1: ignore */ + u8 rsv[2]; +} __packed; + +struct sta_rec_muru { + __le16 tag; + __le16 len; + + struct { + bool ofdma_dl_en; + bool ofdma_ul_en; + bool mimo_dl_en; + bool mimo_ul_en; + u8 rsv[4]; + } cfg; + + struct { + u8 punc_pream_rx; + bool he_20m_in_40m_2g; + bool he_20m_in_160m; + bool he_80m_in_160m; + bool lt16_sigb; + bool rx_su_comp_sigb; + bool rx_su_non_comp_sigb; + u8 rsv; + } ofdma_dl; + + struct { + u8 t_frame_dur; + u8 mu_cascading; + u8 uo_ra; + u8 he_2x996_tone; + u8 rx_t_frame_11ac; + u8 rsv[3]; + } ofdma_ul; + + struct { + bool vht_mu_bfee; + bool partial_bw_dl_mimo; + u8 rsv[2]; + } mimo_dl; + + struct { + bool full_ul_mimo; + bool partial_ul_mimo; + u8 rsv[2]; + } mimo_ul; +} __packed; + +struct sta_phy { + u8 type; + u8 flag; + u8 stbc; + u8 sgi; + u8 bw; + u8 ldpc; + u8 mcs; + u8 nss; + u8 he_ltf; +}; + +struct sta_rec_ra { + __le16 tag; + __le16 len; + + u8 valid; + u8 auto_rate; + u8 phy_mode; + u8 channel; + u8 bw; + u8 disable_cck; + u8 ht_mcs32; + u8 ht_gf; + u8 ht_mcs[4]; + u8 mmps_mode; + u8 gband_256; + u8 af; + u8 auth_wapi_mode; + u8 rate_len; + + u8 supp_mode; + u8 supp_cck_rate; + u8 supp_ofdm_rate; + __le32 supp_ht_mcs; + __le16 supp_vht_mcs[4]; + + u8 op_mode; + u8 op_vht_chan_width; + u8 op_vht_rx_nss; + u8 op_vht_rx_nss_type; + + __le32 sta_cap; + + struct sta_phy phy; +} __packed; + +struct sta_rec_ra_fixed { + __le16 tag; + __le16 len; + + __le32 field; + u8 op_mode; + u8 op_vht_chan_width; + u8 op_vht_rx_nss; + u8 op_vht_rx_nss_type; + + struct sta_phy phy; + + u8 spe_en; + u8 short_preamble; + u8 is_5g; + u8 mmps_mode; +} __packed; + /* wtbl_rec */ struct wtbl_req_hdr { @@ -234,6 +668,7 @@ struct wtbl_ba { __le16 sn; u8 ba_en; u8 ba_winsize_idx; + /* originator & recipient */ __le16 ba_winsize; /* recipient only */ u8 peer_addr[ETH_ALEN]; @@ -304,12 +739,18 @@ struct wtbl_raw { #define MT76_CONNAC_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_bf) + \ sizeof(struct sta_rec_ht) + \ sizeof(struct sta_rec_he) + \ sizeof(struct sta_rec_ba) + \ sizeof(struct sta_rec_vht) + \ sizeof(struct sta_rec_uapsd) + \ sizeof(struct sta_rec_amsdu) + \ + sizeof(struct sta_rec_muru) + \ + sizeof(struct sta_rec_bfee) + \ + sizeof(struct sta_rec_ra) + \ + sizeof(struct sta_rec_sec) + \ + sizeof(struct sta_rec_ra_fixed) + \ sizeof(struct sta_rec_he_6g_capa) + \ sizeof(struct tlv) + \ MT76_CONNAC_WTBL_UPDATE_MAX_SIZE) @@ -423,7 +864,8 @@ enum { #define PHY_MODE_AC BIT(5) #define PHY_MODE_AX_24G BIT(6) #define PHY_MODE_AX_5G BIT(7) -#define PHY_MODE_AX_6G BIT(8) + +#define PHY_MODE_AX_6G BIT(0) /* phymode_ext */ #define MODE_CCK BIT(0) #define MODE_OFDM BIT(1) @@ -431,6 +873,21 @@ enum { #define MODE_VHT BIT(3) #define MODE_HE BIT(4) +#define STA_CAP_WMM BIT(0) +#define STA_CAP_SGI_20 BIT(4) +#define STA_CAP_SGI_40 BIT(5) +#define STA_CAP_TX_STBC BIT(6) +#define STA_CAP_RX_STBC BIT(7) +#define STA_CAP_VHT_SGI_80 BIT(16) +#define STA_CAP_VHT_SGI_160 BIT(17) +#define STA_CAP_VHT_TX_STBC BIT(18) +#define STA_CAP_VHT_RX_STBC BIT(19) +#define STA_CAP_VHT_LDPC BIT(23) +#define STA_CAP_LDPC BIT(24) +#define STA_CAP_HT BIT(26) +#define STA_CAP_VHT BIT(27) +#define STA_CAP_HE BIT(28) + enum { PHY_TYPE_HR_DSSS_INDEX = 0, PHY_TYPE_ERP_INDEX, @@ -489,6 +946,121 @@ enum { DEV_INFO_MAX_NUM }; +/* event table */ +enum { + MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, + MCU_EVENT_FW_START = 0x01, + MCU_EVENT_GENERIC = 0x01, + MCU_EVENT_ACCESS_REG = 0x02, + MCU_EVENT_MT_PATCH_SEM = 0x04, + MCU_EVENT_REG_ACCESS = 0x05, + MCU_EVENT_LP_INFO = 0x07, + MCU_EVENT_SCAN_DONE = 0x0d, + MCU_EVENT_TX_DONE = 0x0f, + MCU_EVENT_ROC = 0x10, + MCU_EVENT_BSS_ABSENCE = 0x11, + MCU_EVENT_BSS_BEACON_LOSS = 0x13, + MCU_EVENT_CH_PRIVILEGE = 0x18, + MCU_EVENT_SCHED_SCAN_DONE = 0x23, + MCU_EVENT_DBG_MSG = 0x27, + MCU_EVENT_TXPWR = 0xd0, + MCU_EVENT_EXT = 0xed, + MCU_EVENT_RESTART_DL = 0xef, + MCU_EVENT_COREDUMP = 0xf0, +}; + +/* ext event table */ +enum { + MCU_EXT_EVENT_PS_SYNC = 0x5, + MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, + MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, + MCU_EXT_EVENT_ASSERT_DUMP = 0x23, + MCU_EXT_EVENT_RDD_REPORT = 0x3a, + MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, + MCU_EXT_EVENT_BCC_NOTIFY = 0x75, + MCU_EXT_EVENT_MURU_CTRL = 0x9f, +}; + +enum { + MCU_Q_QUERY, + MCU_Q_SET, + MCU_Q_RESERVED, + MCU_Q_NA +}; + +enum { + MCU_S2D_H2N, + MCU_S2D_C2N, + MCU_S2D_H2C, + MCU_S2D_H2CN +}; + +enum { + PATCH_NOT_DL_SEM_FAIL, + PATCH_IS_DL, + PATCH_NOT_DL_SEM_SUCCESS, + PATCH_REL_SEM_SUCCESS +}; + +enum { + FW_STATE_INITIAL, + FW_STATE_FW_DOWNLOAD, + FW_STATE_NORMAL_OPERATION, + FW_STATE_NORMAL_TRX, + FW_STATE_RDY = 7 +}; + +enum { + CH_SWITCH_NORMAL = 0, + CH_SWITCH_SCAN = 3, + CH_SWITCH_MCC = 4, + CH_SWITCH_DFS = 5, + CH_SWITCH_BACKGROUND_SCAN_START = 6, + CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, + CH_SWITCH_BACKGROUND_SCAN_STOP = 8, + CH_SWITCH_SCAN_BYPASS_DPD = 9 +}; + +enum { + THERMAL_SENSOR_TEMP_QUERY, + THERMAL_SENSOR_MANUAL_CTRL, + THERMAL_SENSOR_INFO_QUERY, + THERMAL_SENSOR_TASK_CTRL, +}; + +enum mcu_cipher_type { + MCU_CIPHER_NONE = 0, + MCU_CIPHER_WEP40, + MCU_CIPHER_WEP104, + MCU_CIPHER_WEP128, + MCU_CIPHER_TKIP, + MCU_CIPHER_AES_CCMP, + MCU_CIPHER_CCMP_256, + MCU_CIPHER_GCMP, + MCU_CIPHER_GCMP_256, + MCU_CIPHER_WAPI, + MCU_CIPHER_BIP_CMAC_128, +}; + +enum { + EE_MODE_EFUSE, + EE_MODE_BUFFER, +}; + +enum { + EE_FORMAT_BIN, + EE_FORMAT_WHOLE, + EE_FORMAT_MULTIPLE, +}; + +enum { + MCU_PHY_STATE_TX_RATE, + MCU_PHY_STATE_RX_RATE, + MCU_PHY_STATE_RSSI, + MCU_PHY_STATE_CONTENTION_RX_RATE, + MCU_PHY_STATE_OFDMLQ_CNINFO, +}; + #define MCU_CMD_ACK BIT(0) #define MCU_CMD_UNI BIT(1) #define MCU_CMD_QUERY BIT(2) @@ -496,29 +1068,51 @@ enum { #define MCU_CMD_UNI_EXT_ACK (MCU_CMD_ACK | MCU_CMD_UNI | \ MCU_CMD_QUERY) -#define MCU_FW_PREFIX BIT(31) -#define MCU_UNI_PREFIX BIT(30) -#define MCU_CE_PREFIX BIT(29) -#define MCU_QUERY_PREFIX BIT(28) -#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX | \ - MCU_CE_PREFIX | MCU_QUERY_PREFIX) - -#define MCU_QUERY_MASK BIT(16) +#define __MCU_CMD_FIELD_ID GENMASK(7, 0) +#define __MCU_CMD_FIELD_EXT_ID GENMASK(15, 8) +#define __MCU_CMD_FIELD_QUERY BIT(16) +#define __MCU_CMD_FIELD_UNI BIT(17) +#define __MCU_CMD_FIELD_CE BIT(18) +#define __MCU_CMD_FIELD_WA BIT(19) + +#define MCU_CMD(_t) FIELD_PREP(__MCU_CMD_FIELD_ID, \ + MCU_CMD_##_t) +#define MCU_EXT_CMD(_t) (MCU_CMD(EXT_CID) | \ + FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \ + MCU_EXT_CMD_##_t)) +#define MCU_EXT_QUERY(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_QUERY) +#define MCU_UNI_CMD(_t) (__MCU_CMD_FIELD_UNI | \ + FIELD_PREP(__MCU_CMD_FIELD_ID, \ + MCU_UNI_CMD_##_t)) +#define MCU_CE_CMD(_t) (__MCU_CMD_FIELD_CE | \ + FIELD_PREP(__MCU_CMD_FIELD_ID, \ + MCU_CE_CMD_##_t)) +#define MCU_CE_QUERY(_t) (MCU_CE_CMD(_t) | __MCU_CMD_FIELD_QUERY) + +#define MCU_WA_CMD(_t) (MCU_CMD(_t) | __MCU_CMD_FIELD_WA) +#define MCU_WA_EXT_CMD(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_WA) +#define MCU_WA_PARAM_CMD(_t) (MCU_WA_CMD(WA_PARAM) | \ + FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \ + MCU_WA_PARAM_CMD_##_t)) enum { MCU_EXT_CMD_EFUSE_ACCESS = 0x01, MCU_EXT_CMD_RF_REG_ACCESS = 0x02, + MCU_EXT_CMD_RF_TEST = 0x04, MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, + MCU_EXT_CMD_TXBF_ACTION = 0x1e, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + MCU_EXT_CMD_THERMAL_PROT = 0x23, MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, MCU_EXT_CMD_EDCA_UPDATE = 0x27, MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, - MCU_EXT_CMD_GET_TEMP = 0x2c, + MCU_EXT_CMD_THERMAL_CTRL = 0x2c, MCU_EXT_CMD_WTBL_UPDATE = 0x32, + MCU_EXT_CMD_SET_DRR_CTRL = 0x36, MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, MCU_EXT_CMD_ATE_CTRL = 0x3d, MCU_EXT_CMD_PROTECT_CTRL = 0x3e, @@ -527,59 +1121,77 @@ enum { MCU_EXT_CMD_RX_HDR_TRANS = 0x47, MCU_EXT_CMD_MUAR_UPDATE = 0x48, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, + MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a, MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_EFUSE_FREE_BLOCK = 0x4f, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, MCU_EXT_CMD_RXDCOC_CAL = 0x59, + MCU_EXT_CMD_GET_MIB_INFO = 0x5a, MCU_EXT_CMD_TXDPD_CAL = 0x60, MCU_EXT_CMD_CAL_CACHE = 0x67, - MCU_EXT_CMD_SET_RDD_TH = 0x7c, + MCU_EXT_CMD_SET_RADAR_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, + MCU_EXT_CMD_MWDS_SUPPORT = 0x80, + MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, + MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94, + MCU_EXT_CMD_FW_DBG_CTRL = 0x95, + MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, + MCU_EXT_CMD_SET_RDD_TH = 0x9d, + MCU_EXT_CMD_MURU_CTRL = 0x9f, + MCU_EXT_CMD_SET_SPR = 0xa8, + MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, + MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, + MCU_EXT_CMD_PHY_STAT_INFO = 0xad, }; enum { - MCU_UNI_CMD_DEV_INFO_UPDATE = MCU_UNI_PREFIX | 0x01, - MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02, - MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03, - MCU_UNI_CMD_SUSPEND = MCU_UNI_PREFIX | 0x05, - MCU_UNI_CMD_OFFLOAD = MCU_UNI_PREFIX | 0x06, - MCU_UNI_CMD_HIF_CTRL = MCU_UNI_PREFIX | 0x07, + MCU_UNI_CMD_DEV_INFO_UPDATE = 0x01, + MCU_UNI_CMD_BSS_INFO_UPDATE = 0x02, + MCU_UNI_CMD_STA_REC_UPDATE = 0x03, + MCU_UNI_CMD_SUSPEND = 0x05, + MCU_UNI_CMD_OFFLOAD = 0x06, + MCU_UNI_CMD_HIF_CTRL = 0x07, + MCU_UNI_CMD_SNIFFER = 0x24, }; enum { - MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01, - MCU_CMD_FW_START_REQ = MCU_FW_PREFIX | 0x02, + MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, + MCU_CMD_FW_START_REQ = 0x02, MCU_CMD_INIT_ACCESS_REG = 0x3, - MCU_CMD_NIC_POWER_CTRL = MCU_FW_PREFIX | 0x4, - MCU_CMD_PATCH_START_REQ = MCU_FW_PREFIX | 0x05, - MCU_CMD_PATCH_FINISH_REQ = MCU_FW_PREFIX | 0x07, - MCU_CMD_PATCH_SEM_CONTROL = MCU_FW_PREFIX | 0x10, + MCU_CMD_NIC_POWER_CTRL = 0x4, + MCU_CMD_PATCH_START_REQ = 0x05, + MCU_CMD_PATCH_FINISH_REQ = 0x07, + MCU_CMD_PATCH_SEM_CONTROL = 0x10, + MCU_CMD_WA_PARAM = 0xc4, MCU_CMD_EXT_CID = 0xed, - MCU_CMD_FW_SCATTER = MCU_FW_PREFIX | 0xee, - MCU_CMD_RESTART_DL_REQ = MCU_FW_PREFIX | 0xef, + MCU_CMD_FW_SCATTER = 0xee, + MCU_CMD_RESTART_DL_REQ = 0xef, }; /* offload mcu commands */ enum { - MCU_CMD_TEST_CTRL = MCU_CE_PREFIX | 0x01, - MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03, - MCU_CMD_SET_PS_PROFILE = MCU_CE_PREFIX | 0x05, - MCU_CMD_SET_CHAN_DOMAIN = MCU_CE_PREFIX | 0x0f, - MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16, - MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17, - MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b, - MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1d, - MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33, - MCU_CMD_SET_RATE_TX_POWER = MCU_CE_PREFIX | 0x5d, - MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61, - MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62, - MCU_CMD_GET_NIC_CAPAB = MCU_CE_PREFIX | 0x8a, - MCU_CMD_SET_MU_EDCA_PARMS = MCU_CE_PREFIX | 0xb0, - MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0, - MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0, - MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca, - MCU_CMD_FWLOG_2_HOST = MCU_CE_PREFIX | 0xc5, - MCU_CMD_GET_WTBL = MCU_CE_PREFIX | 0xcd, - MCU_CMD_GET_TXPWR = MCU_CE_PREFIX | 0xd0, + MCU_CE_CMD_TEST_CTRL = 0x01, + MCU_CE_CMD_START_HW_SCAN = 0x03, + MCU_CE_CMD_SET_PS_PROFILE = 0x05, + MCU_CE_CMD_SET_CHAN_DOMAIN = 0x0f, + MCU_CE_CMD_SET_BSS_CONNECTED = 0x16, + MCU_CE_CMD_SET_BSS_ABORT = 0x17, + MCU_CE_CMD_CANCEL_HW_SCAN = 0x1b, + MCU_CE_CMD_SET_ROC = 0x1c, + MCU_CE_CMD_SET_EDCA_PARMS = 0x1d, + MCU_CE_CMD_SET_P2P_OPPPS = 0x33, + MCU_CE_CMD_SET_CLC = 0x5c, + MCU_CE_CMD_SET_RATE_TX_POWER = 0x5d, + MCU_CE_CMD_SCHED_SCAN_ENABLE = 0x61, + MCU_CE_CMD_SCHED_SCAN_REQ = 0x62, + MCU_CE_CMD_GET_NIC_CAPAB = 0x8a, + MCU_CE_CMD_SET_MU_EDCA_PARMS = 0xb0, + MCU_CE_CMD_REG_WRITE = 0xc0, + MCU_CE_CMD_REG_READ = 0xc0, + MCU_CE_CMD_CHIP_CONFIG = 0xca, + MCU_CE_CMD_FWLOG_2_HOST = 0xc5, + MCU_CE_CMD_GET_WTBL = 0xcd, + MCU_CE_CMD_GET_TXPWR = 0xd0, }; enum { @@ -998,6 +1610,51 @@ struct mt76_connac_config { u8 data[320]; } __packed; +static inline enum mcu_cipher_type +mt76_connac_mcu_get_cipher(int cipher) +{ + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return MCU_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return MCU_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + return MCU_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_AES_CMAC: + return MCU_CIPHER_BIP_CMAC_128; + case WLAN_CIPHER_SUITE_CCMP: + return MCU_CIPHER_AES_CCMP; + case WLAN_CIPHER_SUITE_CCMP_256: + return MCU_CIPHER_CCMP_256; + case WLAN_CIPHER_SUITE_GCMP: + return MCU_CIPHER_GCMP; + case WLAN_CIPHER_SUITE_GCMP_256: + return MCU_CIPHER_GCMP_256; + case WLAN_CIPHER_SUITE_SMS4: + return MCU_CIPHER_WAPI; + default: + return MCU_CIPHER_NONE; + } +} + +static inline u32 +mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa) +{ + u32 ret = 0; + + ret |= feature_set & FW_FEATURE_SET_ENCRYPT ? + DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0; + if (is_mt7921(dev)) + ret |= feature_set & FW_FEATURE_ENCRY_MODE ? + DL_CONFIG_ENCRY_MODE_SEL : 0; + ret |= FIELD_PREP(DL_MODE_KEY_IDX, + FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); + ret |= DL_MODE_NEED_RSP; + ret |= is_wa ? DL_MODE_WORKING_PDA_CR4 : 0; + + return ret; +} + #define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) #define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) @@ -1007,7 +1664,7 @@ mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid, { *wlan_idx_hi = 0; - if (is_mt7921(dev)) { + if (!is_connac_v1(dev)) { *wlan_idx_lo = wcid ? to_wcid_lo(wcid->idx) : 0; *wlan_idx_hi = wcid ? to_wcid_hi(wcid->idx) : 0; } else { @@ -1016,8 +1673,16 @@ mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid, } struct sk_buff * +__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, + struct mt76_wcid *wcid, int len); +static inline struct sk_buff * mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, - struct mt76_wcid *wcid); + struct mt76_wcid *wcid) +{ + return __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, + MT76_CONNAC_STA_UPDATE_MAX_SIZE); +} + struct wtbl_req_hdr * mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid, int cmd, void *sta_wtbl, struct sk_buff **skb); @@ -1047,13 +1712,16 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid, int cmd); +int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 rcpi, u8 state); void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv); + void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc); void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_ampdu_params *params, bool enable, bool tx, void *sta_wtbl, @@ -1067,7 +1735,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, bool enable); int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, - bool enable, bool tx); + int cmd, bool enable, bool tx); int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy, struct ieee80211_vif *vif, struct mt76_wcid *wcid, @@ -1117,4 +1785,37 @@ int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif); u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset); void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val); + +const struct ieee80211_sta_he_cap * +mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif); +u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta); + +int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct mt76_connac_sta_key_conf *sta_key_conf, + struct ieee80211_key_conf *key, int mcu_cmd, + struct mt76_wcid *wcid, enum set_key_cmd cmd); + +void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif *mvif); +void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif); +int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct mt76_phy *phy, u16 wlan_idx, + bool enable); +void mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb, + struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv); +int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter); +int mt76_connac_mcu_restart(struct mt76_dev *dev); +int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index, + u8 rx_sel, u8 val); +int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm, + const char *fw_wa); +int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name); +int mt76_connac2_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *wait_seq); #endif /* __MT76_CONNAC_MCU_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 0bac39bf3b66..66d47c70111a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -237,7 +237,10 @@ int mt76x0_register_device(struct mt76x02_dev *dev) { int ret; - mt76x02_init_device(dev); + ret = mt76x02_init_device(dev); + if (ret) + return ret; + mt76x02_config_mac_addr_list(dev); ret = mt76_register_device(&dev->mt76, true, mt76x02_rates, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index 700ae9c12f1d..07380cce8755 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -31,6 +31,32 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_txq_schedule_all(&dev->mphy); } +int mt76x0_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + int err = -EINVAL, power = hw->conf.power_level * 2; + struct mt76x02_dev *dev = hw->priv; + struct mt76_phy *mphy = &dev->mphy; + + mutex_lock(&dev->mt76.mutex); + if (!cfg80211_chandef_valid(&mphy->chandef)) + goto out; + + err = mt76_init_sar_power(hw, sar); + if (err) + goto out; + + dev->txpower_conf = mt76_get_sar_power(mphy, mphy->chandef.chan, + power); + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) + mt76x0_phy_set_txpower(dev); +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} +EXPORT_SYMBOL_GPL(mt76x0_set_sar_specs); + int mt76x0_config(struct ieee80211_hw *hw, u32 changed) { struct mt76x02_dev *dev = hw->priv; @@ -44,9 +70,13 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->txpower_conf = hw->conf.power_level * 2; + struct mt76_phy *mphy = &dev->mphy; - if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + dev->txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = mt76_get_sar_power(mphy, + mphy->chandef.chan, + dev->txpower_conf); + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) mt76x0_phy_set_txpower(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h index 6953f253a28a..99dcb8feb9f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h @@ -49,6 +49,8 @@ void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); void mt76x0_mac_stop(struct mt76x02_dev *dev); int mt76x0_config(struct ieee80211_hw *hw, u32 changed); +int mt76x0_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar); /* PHY */ void mt76x0_phy_init(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index f19228fc5a70..9277ff38b7a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -85,6 +85,7 @@ static const struct ieee80211_ops mt76x0e_ops = { .set_rts_threshold = mt76x02_set_rts_threshold, .get_antenna = mt76_get_antenna, .reconfig_complete = mt76x02_reconfig_complete, + .set_sar_specs = mt76x0_set_sar_specs, }; static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index f2b2fa733845..0422c332354a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -141,6 +141,7 @@ static const struct ieee80211_ops mt76x0u_ops = { .set_tim = mt76_set_tim, .release_buffered_frames = mt76_release_buffered_frames, .get_antenna = mt76_get_antenna, + .set_sar_specs = mt76x0_set_sar_specs, }; static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset) @@ -244,7 +245,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); mt76x02u_init_mcu(mdev); - ret = mt76u_init(mdev, usb_intf, false); + ret = mt76u_init(mdev, usb_intf); if (ret) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 4d58c2c1c0ac..50eaeff11af3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -103,7 +103,8 @@ struct mt76x02_dev { u8 tbtt_count; u32 tx_hang_reset; - u8 tx_hang_check; + u8 tx_hang_check[4]; + u8 beacon_hang_check; u8 mcu_timeout; struct mt76x02_calibration cal; @@ -133,7 +134,7 @@ struct mt76x02_dev { extern struct ieee80211_rate mt76x02_rates[12]; -void mt76x02_init_device(struct mt76x02_dev *dev); +int mt76x02_init_device(struct mt76x02_dev *dev); void mt76x02_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast); @@ -155,7 +156,8 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params); + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params); void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -186,7 +188,7 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); void mt76x02_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed); + struct ieee80211_bss_conf *info, u64 changed); void mt76x02_reconfig_complete(struct ieee80211_hw *hw, enum ieee80211_reconfig_type reconfig_type); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index 5d034cec191b..ad4dc8e17b58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -57,8 +57,11 @@ void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, int bcn_len = dev->beacon_ops->slot_size; int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count); - if (!mt76x02_write_beacon(dev, bcn_addr, skb)) + if (!mt76x02_write_beacon(dev, bcn_addr, skb)) { + if (!dev->beacon_data_count) + dev->beacon_hang_check++; dev->beacon_data_count++; + } dev_kfree_skb(skb); } EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); @@ -74,6 +77,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, if (!dev->mt76.beacon_mask) dev->tbtt_count = 0; + dev->beacon_hang_check = 0; if (enable) { dev->mt76.beacon_mask |= BIT(mvif->idx); } else { @@ -139,7 +143,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) return; - skb = ieee80211_beacon_get(mt76_hw(dev), vif); + skb = ieee80211_beacon_get(mt76_hw(dev), vif, 0); if (!skb) return; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index a601350531cd..024a5c0a5a57 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -823,10 +823,7 @@ EXPORT_SYMBOL_GPL(mt76x02_phy_dfs_adjust_agc); void mt76x02_dfs_init_params(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; - - if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - dev->mt76.region != NL80211_DFS_UNSET) { + if (mt76_phy_dfs_state(&dev->mphy) > MT_DFS_STATE_DISABLED) { mt76x02_dfs_init_sw_detector(dev); mt76x02_dfs_set_bbp_params(dev); /* enable debug mode */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index a404fd7ea968..93d96739f802 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -404,7 +404,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, txwi->rate |= cpu_to_le16(MT_RXWI_RATE_LDPC); if ((info->flags & IEEE80211_TX_CTL_STBC) && nss == 1) txwi->rate |= cpu_to_le16(MT_RXWI_RATE_STBC); - if (nss > 1 && sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC) + if (nss > 1 && sta && sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC) txwi_flags |= MT_TXWI_FLAGS_MMPS; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ; @@ -412,9 +412,9 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ; if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) { u8 ba_size = IEEE80211_MIN_AMPDU_BUF; - u8 ampdu_density = sta->ht_cap.ampdu_density; + u8 ampdu_density = sta->deflink.ht_cap.ampdu_density; - ba_size <<= sta->ht_cap.ampdu_factor; + ba_size <<= sta->deflink.ht_cap.ampdu_factor; ba_size = min_t(int, 63, ba_size - 1); if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ba_size = 0; @@ -860,9 +860,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->chain_signal[1] = mt76x02_mac_get_rssi(dev, rxwi->rssi[1], 1); - signal = max_t(s8, signal, status->chain_signal[1]); } - status->signal = signal; status->freq = dev->mphy.chandef.chan->center_freq; status->band = dev->mphy.chandef.chan->band; @@ -1040,15 +1038,34 @@ EXPORT_SYMBOL_GPL(mt76x02_update_channel); static void mt76x02_check_mac_err(struct mt76x02_dev *dev) { - u32 val = mt76_rr(dev, 0x10f4); + if (dev->mt76.beacon_mask) { + if (mt76_rr(dev, MT_TX_STA_0) & MT_TX_STA_0_BEACONS) { + dev->beacon_hang_check = 0; + return; + } - if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5)))) - return; + if (dev->beacon_hang_check < 10) + return; - dev_err(dev->mt76.dev, "mac specific condition occurred\n"); + } else { + u32 val = mt76_rr(dev, 0x10f4); + if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5)))) + return; + } + dev_err(dev->mt76.dev, "MAC error detected\n"); + + mt76_wr(dev, MT_MAC_SYS_CTRL, 0); + if (!mt76x02_wait_for_txrx_idle(&dev->mt76)) { + dev_err(dev->mt76.dev, "MAC stop failed\n"); + goto out; + } + + dev->beacon_hang_check = 0; mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR); udelay(10); + +out: mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); } @@ -1178,8 +1195,7 @@ void mt76x02_mac_work(struct work_struct *work) dev->mt76.aggr_stats[idx++] += val >> 16; } - if (!dev->mt76.beacon_mask) - mt76x02_check_mac_err(dev); + mt76x02_check_mac_err(dev); if (dev->ed_monitor) mt76x02_edcca_check(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index ec0de691129a..e9c5e85ec07c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -59,7 +59,8 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t) struct ieee80211_vif *vif = info->control.vif; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL); + mt76_tx_queue_skb(dev, q, MT_TXQ_PSD, skb, &mvif->group_wcid, + NULL); } spin_unlock(&q->lock); } @@ -191,13 +192,13 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) for (i = 0; i < IEEE80211_NUM_ACS; i++) { ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i), MT76x02_TX_RING_SIZE, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE); + MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -230,8 +231,8 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt76x02_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt76x02_poll_tx); napi_enable(&dev->mt76.tx_napi); return 0; @@ -348,18 +349,20 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev) for (i = 0; i < 4; i++) { q = dev->mphy.q_tx[i]; - if (!q->queued) - continue; - prev_dma_idx = dev->mt76.tx_dma_idx[i]; dma_idx = readl(&q->regs->dma_idx); dev->mt76.tx_dma_idx[i] = dma_idx; - if (prev_dma_idx == dma_idx) - break; + if (!q->queued || prev_dma_idx != dma_idx) { + dev->tx_hang_check[i] = 0; + continue; + } + + if (++dev->tx_hang_check[i] >= MT_TX_HANG_TH) + return true; } - return i < 4; + return false; } static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -530,23 +533,13 @@ static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) if (test_bit(MT76_RESTART, &dev->mphy.state)) return; - if (mt76x02_tx_hang(dev)) { - if (++dev->tx_hang_check >= MT_TX_HANG_TH) - goto restart; - } else { - dev->tx_hang_check = 0; - } - - if (dev->mcu_timeout) - goto restart; - - return; + if (!mt76x02_tx_hang(dev) && !dev->mcu_timeout) + return; -restart: mt76x02_watchdog_reset(dev); dev->tx_hang_reset++; - dev->tx_hang_check = 0; + memset(dev->tx_hang_check, 0, sizeof(dev->tx_hang_check)); memset(dev->mt76.tx_dma_idx, 0xff, sizeof(dev->mt76.tx_dma_idx)); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index fa7872ac22bf..fe0c5e3298bc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -571,6 +571,8 @@ #define MT_RX_STAT_2_OVERFLOW_ERRORS GENMASK(31, 16) #define MT_TX_STA_0 0x170c +#define MT_TX_STA_0_BEACONS GENMASK(31, 16) + #define MT_TX_STA_1 0x1710 #define MT_TX_STA_2 0x1714 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index 2953df7d8388..02da543dfc5c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -21,29 +21,16 @@ static void mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) { struct mt76_usb *usb = &dev->usb; - u32 reg, val; int i; - if (usb->mcu.burst) { - WARN_ON_ONCE(len / 4 != usb->mcu.rp_len); - - reg = usb->mcu.rp[0].reg - usb->mcu.base; - for (i = 0; i < usb->mcu.rp_len; i++) { - val = get_unaligned_le32(data + 4 * i); - usb->mcu.rp[i].reg = reg++; - usb->mcu.rp[i].value = val; - } - } else { - WARN_ON_ONCE(len / 8 != usb->mcu.rp_len); - - for (i = 0; i < usb->mcu.rp_len; i++) { - reg = get_unaligned_le32(data + 8 * i) - - usb->mcu.base; - val = get_unaligned_le32(data + 8 * i + 4); - - WARN_ON_ONCE(usb->mcu.rp[i].reg != reg); - usb->mcu.rp[i].value = val; - } + WARN_ON_ONCE(len / 8 != usb->mcu.rp_len); + + for (i = 0; i < usb->mcu.rp_len; i++) { + u32 reg = get_unaligned_le32(data + 8 * i) - usb->mcu.base; + u32 val = get_unaligned_le32(data + 8 * i + 4); + + WARN_ON_ONCE(usb->mcu.rp[i].reg != reg); + usb->mcu.rp[i].value = val; } } @@ -108,7 +95,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500, MT_EP_OUT_INBAND_CMD); if (ret) - return ret; + goto out; if (wait_resp) ret = mt76x02u_mcu_wait_resp(dev, seq); @@ -207,7 +194,6 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, usb->mcu.rp = data; usb->mcu.rp_len = n; usb->mcu.base = base; - usb->mcu.burst = false; ret = __mt76x02u_mcu_send_msg(dev, skb, CMD_RANDOM_READ, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 1f17d86ff755..604ddcc21123 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -138,7 +138,7 @@ mt76x02_led_set_brightness(struct led_classdev *led_cdev, mt76x02_led_set_config(mdev, 0xff, 0); } -void mt76x02_init_device(struct mt76x02_dev *dev) +int mt76x02_init_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; @@ -197,6 +197,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) dev->mphy.chainmask = 0x101; dev->mphy.antenna_mask = 1; } + + return 0; } EXPORT_SYMBOL_GPL(mt76x02_init_device); @@ -290,7 +292,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, mt76_packet_id_init(&mvif->group_wcid); mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->group_wcid; + rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid); + mtxq->wcid = MT_VIF_WCID(idx); } int @@ -325,11 +328,11 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) idx += 8; /* vif is already set or idx is 8 for AP/Mesh/... */ - if (dev->mt76.vif_mask & BIT(idx) || + if (dev->mt76.vif_mask & BIT_ULL(idx) || (vif->type != NL80211_IFTYPE_STATION && idx > 7)) return -EBUSY; - dev->mt76.vif_mask |= BIT(idx); + dev->mt76.vif_mask |= BIT_ULL(idx); mt76x02_vif_init(dev, vif, idx); return 0; @@ -342,7 +345,8 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, struct mt76x02_dev *dev = hw->priv; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - dev->mt76.vif_mask &= ~BIT(mvif->idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); + rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL); mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); @@ -483,7 +487,8 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, EXPORT_SYMBOL_GPL(mt76x02_set_key); int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params) + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params) { struct mt76x02_dev *dev = hw->priv; u8 cw_min = 5, cw_max = 10, qid; @@ -632,7 +637,7 @@ EXPORT_SYMBOL_GPL(mt76x02_sta_ps); void mt76x02_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76x02_dev *dev = hw->priv; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index a92a479aebaa..7b01a06d7f8d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -8,6 +8,35 @@ #include "eeprom.h" #include "../mt76x02_phy.h" +int mt76x2_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + int err = -EINVAL, power = hw->conf.power_level * 2; + struct mt76x02_dev *dev = hw->priv; + struct mt76_phy *mphy = &dev->mphy; + + mutex_lock(&dev->mt76.mutex); + if (!cfg80211_chandef_valid(&mphy->chandef)) + goto out; + + err = mt76_init_sar_power(hw, sar); + if (err) + goto out; + + dev->txpower_conf = mt76_get_sar_power(mphy, mphy->chandef.chan, + power); + /* convert to per-chain power for 2x2 devices */ + dev->txpower_conf -= 6; + + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) + mt76x2_phy_set_txpower(dev); +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} +EXPORT_SYMBOL_GPL(mt76x2_set_sar_specs); + static void mt76x2_set_wlan_state(struct mt76x02_dev *dev, bool enable) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index d01f47c83eb1..be1217329a77 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -41,6 +41,8 @@ extern const struct ieee80211_ops mt76x2_ops; int mt76x2_register_device(struct mt76x02_dev *dev); int mt76x2_resume_device(struct mt76x02_dev *dev); +int mt76x2_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar); void mt76x2_phy_power_on(struct mt76x02_dev *dev); void mt76x2_stop_hardware(struct mt76x02_dev *dev); int mt76x2_eeprom_init(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 8a22ee581674..df85ebc6e1df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -80,7 +80,7 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id) mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9); /* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */ - mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf); + mt76_rmw_field(dev, 0x15a0c, 0xfU << 28, 0xf); /* RG_SSUSB_CDR_BR_PE1D = 0x3 */ mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index c6fa8cf92529..e38e8e5685c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -292,8 +292,9 @@ int mt76x2_register_device(struct mt76x02_dev *dev) int ret; INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate); - - mt76x02_init_device(dev); + ret = mt76x02_init_device(dev); + if (ret) + return ret; ret = mt76x2_init_hardware(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 933125b07ea3..b38bb7a2362b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -78,8 +78,12 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->txpower_conf = hw->conf.power_level * 2; + struct mt76_phy *mphy = &dev->mphy; + dev->txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = mt76_get_sar_power(mphy, + mphy->chandef.chan, + dev->txpower_conf); /* convert to per-chain power for 2x2 devices */ dev->txpower_conf -= 6; @@ -155,5 +159,6 @@ const struct ieee80211_ops mt76x2_ops = { .get_antenna = mt76_get_antenna, .set_rts_threshold = mt76x02_set_rts_threshold, .reconfig_complete = mt76x02_reconfig_complete, + .set_sar_specs = mt76x2_set_sar_specs, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 2575369e44e2..55068f3252ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -57,7 +57,7 @@ static int mt76x2u_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); mt76x02u_init_mcu(mdev); - err = mt76u_init(mdev, intf, false); + err = mt76u_init(mdev, intf); if (err < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 85dcdc22fbeb..33a14365ec9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -194,7 +194,9 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) int err; INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate); - mt76x02_init_device(dev); + err = mt76x02_init_device(dev); + if (err) + return err; err = mt76x2u_init_eeprom(dev); if (err < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index b66836928d9d..ac07ed1f63a3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -78,12 +78,16 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->txpower_conf = hw->conf.power_level * 2; + struct mt76_phy *mphy = &dev->mphy; + dev->txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = mt76_get_sar_power(mphy, + mphy->chandef.chan, + dev->txpower_conf); /* convert to per-chain power for 2x2 devices */ dev->txpower_conf -= 6; - if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) mt76x2_phy_set_txpower(dev); } @@ -121,4 +125,5 @@ const struct ieee80211_ops mt76x2u_ops = { .set_tim = mt76_set_tim, .release_buffered_frames = mt76_release_buffered_frames, .get_antenna = mt76_get_antenna, + .set_sar_specs = mt76x2_set_sar_specs, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig index d98225da694c..f21282cea845 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig @@ -1,9 +1,10 @@ # SPDX-License-Identifier: ISC config MT7915E tristate "MediaTek MT7915E (PCIe) support" - select MT76_CORE + select MT76_CONNAC_LIB depends on MAC80211 depends on PCI + select RELAY help This adds support for MT7915-based wireless PCIe devices, which support concurrent dual-band operation at both 5GHz @@ -11,3 +12,13 @@ config MT7915E OFDMA, spatial reuse and dual carrier modulation. To compile this driver as a module, choose M here. + +config MT7986_WMAC + bool "MT7986 (SoC) WMAC support" + depends on MT7915E + depends on ARCH_MEDIATEK || COMPILE_TEST + select REGMAP + help + This adds support for the built-in WMAC on MT7986 SoC device + which has the same feature set as a MT7915, but enables 6E + support. diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index 80e49244348e..b794ceb79c37 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -6,3 +6,4 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ debugfs.o mmio.o mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o +mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
\ No newline at end of file diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index a15aa256d0cf..6ef3431cad64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -1,9 +1,13 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ +#include <linux/relay.h> #include "mt7915.h" #include "eeprom.h" #include "mcu.h" +#include "mac.h" + +#define FW_BIN_LOG_MAGIC 0x44e98caf /** global debugfs **/ @@ -19,9 +23,9 @@ mt7915_implicit_txbf_set(void *data, u64 val) { struct mt7915_dev *dev = data; - if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) - return -EBUSY; - + /* The existing connected stations shall reconnect to apply + * new implicit txbf configuration. + */ dev->ibf = !!val; return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE); @@ -40,48 +44,396 @@ mt7915_implicit_txbf_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get, mt7915_implicit_txbf_set, "%lld\n"); -/* test knob of system layer 1/2 error recovery */ -static int mt7915_ser_trigger_set(void *data, u64 val) +/* test knob of system error recovery */ +static ssize_t +mt7915_fw_ser_set(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) { - enum { - SER_SET_RECOVER_L1 = 1, - SER_SET_RECOVER_L2, - SER_ENABLE = 2, - SER_RECOVER - }; - struct mt7915_dev *dev = data; + struct mt7915_phy *phy = file->private_data; + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + char buf[16]; int ret = 0; + u16 val; + + if (count >= sizeof(buf)) + return -EINVAL; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + if (count && buf[count - 1] == '\n') + buf[count - 1] = '\0'; + else + buf[count] = '\0'; + + if (kstrtou16(buf, 0, &val)) + return -EINVAL; switch (val) { + case SER_QUERY: + /* grab firmware SER stats */ + ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy); + break; case SER_SET_RECOVER_L1: case SER_SET_RECOVER_L2: - ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0); + case SER_SET_RECOVER_L3_RX_ABORT: + case SER_SET_RECOVER_L3_TX_ABORT: + case SER_SET_RECOVER_L3_TX_DISABLE: + case SER_SET_RECOVER_L3_BF: + ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy); if (ret) return ret; - return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0); + ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy); + break; default: break; } + return ret ? ret : count; +} + +static ssize_t +mt7915_fw_ser_get(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct mt7915_phy *phy = file->private_data; + struct mt7915_dev *dev = phy->dev; + char *buff; + int desc = 0; + ssize_t ret; + static const size_t bufsz = 400; + + buff = kmalloc(bufsz, GFP_KERNEL); + if (!buff) + return -ENOMEM; + + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_STATUS = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_SER_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS)); + + ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); + kfree(buff); return ret; } -DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL, - mt7915_ser_trigger_set, "%lld\n"); +static const struct file_operations mt7915_fw_ser_ops = { + .write = mt7915_fw_ser_set, + .read = mt7915_fw_ser_get, + .open = simple_open, + .llseek = default_llseek, +}; static int mt7915_radar_trigger(void *data, u64 val) { struct mt7915_dev *dev = data; - return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0); + if (val > MT_RX_SEL2) + return -EINVAL; + + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE, + val, 0, 0); } DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, mt7915_radar_trigger, "%lld\n"); static int +mt7915_muru_debug_set(void *data, u64 val) +{ + struct mt7915_dev *dev = data; + + dev->muru_debug = val; + mt7915_mcu_muru_debug_set(dev, dev->muru_debug); + + return 0; +} + +static int +mt7915_muru_debug_get(void *data, u64 *val) +{ + struct mt7915_dev *dev = data; + + *val = dev->muru_debug; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_debug, mt7915_muru_debug_get, + mt7915_muru_debug_set, "%lld\n"); + +static int mt7915_muru_stats_show(struct seq_file *file, void *data) +{ + struct mt7915_phy *phy = file->private; + struct mt7915_dev *dev = phy->dev; + struct mt7915_mcu_muru_stats mu_stats = {}; + static const char * const dl_non_he_type[] = { + "CCK", "OFDM", "HT MIX", "HT GF", + "VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU" + }; + static const char * const dl_he_type[] = { + "HE SU", "HE EXT", "HE 2MU", "HE 3MU", "HE 4MU", + "HE 2RU", "HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU", + "HE >16RU" + }; + static const char * const ul_he_type[] = { + "HE 2MU", "HE 3MU", "HE 4MU", "HE SU", "HE 2RU", + "HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU", "HE >16RU" + }; + int ret, i; + u64 total_ppdu_cnt, sub_total_cnt; + + if (!dev->muru_debug) { + seq_puts(file, "Please enable muru_debug first.\n"); + return 0; + } + + mutex_lock(&dev->mt76.mutex); + + ret = mt7915_mcu_muru_debug_get(phy, &mu_stats); + if (ret) + goto exit; + + /* Non-HE Downlink*/ + seq_puts(file, "[Non-HE]\nDownlink\nData Type: "); + + for (i = 0; i < 5; i++) + seq_printf(file, "%8s | ", dl_non_he_type[i]); + +#define __dl_u32(s) le32_to_cpu(mu_stats.dl.s) + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ", + __dl_u32(cck_cnt), + __dl_u32(ofdm_cnt), + __dl_u32(htmix_cnt), + __dl_u32(htgf_cnt), + __dl_u32(vht_su_cnt)); + + seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); + + for (i = 5; i < 8; i++) + seq_printf(file, "%8s | ", dl_non_he_type[i]); + + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | ", + __dl_u32(vht_2mu_cnt), + __dl_u32(vht_3mu_cnt), + __dl_u32(vht_4mu_cnt)); + + sub_total_cnt = __dl_u32(vht_2mu_cnt) + + __dl_u32(vht_3mu_cnt) + + __dl_u32(vht_4mu_cnt); + + seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", + sub_total_cnt); + + total_ppdu_cnt = sub_total_cnt + + __dl_u32(cck_cnt) + + __dl_u32(ofdm_cnt) + + __dl_u32(htmix_cnt) + + __dl_u32(htgf_cnt) + + __dl_u32(vht_su_cnt); + + seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt); + + /* HE Downlink */ + seq_puts(file, "\n\n[HE]\nDownlink\nData Type: "); + + for (i = 0; i < 2; i++) + seq_printf(file, "%8s | ", dl_he_type[i]); + + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | ", + __dl_u32(he_su_cnt), + __dl_u32(he_ext_su_cnt)); + + seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); + + for (i = 2; i < 5; i++) + seq_printf(file, "%8s | ", dl_he_type[i]); + + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | ", + __dl_u32(he_2mu_cnt), + __dl_u32(he_3mu_cnt), + __dl_u32(he_4mu_cnt)); + + seq_puts(file, "\nDownlink OFDMA\nData Type: "); + + for (i = 5; i < 11; i++) + seq_printf(file, "%8s | ", dl_he_type[i]); + + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ", + __dl_u32(he_2ru_cnt), + __dl_u32(he_3ru_cnt), + __dl_u32(he_4ru_cnt), + __dl_u32(he_5to8ru_cnt), + __dl_u32(he_9to16ru_cnt), + __dl_u32(he_gtr16ru_cnt)); + + sub_total_cnt = __dl_u32(he_2mu_cnt) + + __dl_u32(he_3mu_cnt) + + __dl_u32(he_4mu_cnt); + total_ppdu_cnt = sub_total_cnt; + + seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", + sub_total_cnt); + + sub_total_cnt = __dl_u32(he_2ru_cnt) + + __dl_u32(he_3ru_cnt) + + __dl_u32(he_4ru_cnt) + + __dl_u32(he_5to8ru_cnt) + + __dl_u32(he_9to16ru_cnt) + + __dl_u32(he_gtr16ru_cnt); + total_ppdu_cnt += sub_total_cnt; + + seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", + sub_total_cnt); + + total_ppdu_cnt += __dl_u32(he_su_cnt) + + __dl_u32(he_ext_su_cnt); + + seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); +#undef __dl_u32 + + /* HE Uplink */ + seq_puts(file, "\n\nUplink"); + seq_puts(file, "\nTrigger-based Uplink MU-MIMO\nData Type: "); + + for (i = 0; i < 3; i++) + seq_printf(file, "%8s | ", ul_he_type[i]); + +#define __ul_u32(s) le32_to_cpu(mu_stats.ul.s) + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | ", + __ul_u32(hetrig_2mu_cnt), + __ul_u32(hetrig_3mu_cnt), + __ul_u32(hetrig_4mu_cnt)); + + seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type: "); + + for (i = 3; i < 10; i++) + seq_printf(file, "%8s | ", ul_he_type[i]); + + seq_puts(file, "\nTotal Count:"); + seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u | %7u | ", + __ul_u32(hetrig_su_cnt), + __ul_u32(hetrig_2ru_cnt), + __ul_u32(hetrig_3ru_cnt), + __ul_u32(hetrig_4ru_cnt), + __ul_u32(hetrig_5to8ru_cnt), + __ul_u32(hetrig_9to16ru_cnt), + __ul_u32(hetrig_gtr16ru_cnt)); + + sub_total_cnt = __ul_u32(hetrig_2mu_cnt) + + __ul_u32(hetrig_3mu_cnt) + + __ul_u32(hetrig_4mu_cnt); + total_ppdu_cnt = sub_total_cnt; + + seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", + sub_total_cnt); + + sub_total_cnt = __ul_u32(hetrig_2ru_cnt) + + __ul_u32(hetrig_3ru_cnt) + + __ul_u32(hetrig_4ru_cnt) + + __ul_u32(hetrig_5to8ru_cnt) + + __ul_u32(hetrig_9to16ru_cnt) + + __ul_u32(hetrig_gtr16ru_cnt); + total_ppdu_cnt += sub_total_cnt; + + seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", + sub_total_cnt); + + total_ppdu_cnt += __ul_u32(hetrig_su_cnt); + + seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt); +#undef __ul_u32 + +exit: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} +DEFINE_SHOW_ATTRIBUTE(mt7915_muru_stats); + +static int +mt7915_rdd_monitor(struct seq_file *s, void *data) +{ + struct mt7915_dev *dev = dev_get_drvdata(s->private); + struct cfg80211_chan_def *chandef = &dev->rdd2_chandef; + const char *bw; + int ret = 0; + + mutex_lock(&dev->mt76.mutex); + + if (!cfg80211_chandef_valid(chandef)) { + ret = -EINVAL; + goto out; + } + + if (!dev->rdd2_phy) { + seq_puts(s, "not running\n"); + goto out; + } + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_40: + bw = "40"; + break; + case NL80211_CHAN_WIDTH_80: + bw = "80"; + break; + case NL80211_CHAN_WIDTH_160: + bw = "160"; + break; + case NL80211_CHAN_WIDTH_80P80: + bw = "80P80"; + break; + default: + bw = "20"; + break; + } + + seq_printf(s, "channel %d (%d MHz) width %s MHz center1: %d MHz\n", + chandef->chan->hw_value, chandef->chan->center_freq, + bw, chandef->center_freq1); +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static int mt7915_fw_debug_wm_set(void *data, u64 val) { struct mt7915_dev *dev = data; @@ -92,27 +444,46 @@ mt7915_fw_debug_wm_set(void *data, u64 val) DEBUG_SPL, DEBUG_RPT_RX, } debug; + bool tx, rx, en; int ret; - dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; + dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; + + if (dev->fw.debug_bin) + val = 16; + else + val = dev->fw.debug_wm; + + tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1)); + rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2)); + en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0)); - ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, dev->fw_debug_wm); + ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val); if (ret) - return ret; + goto out; for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) { - ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, !!dev->fw_debug_wm); + if (debug == DEBUG_RPT_RX) + val = en && rx; + else + val = en && tx; + + ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val); if (ret) - return ret; + goto out; } /* WM CPU info record control */ mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0)); - mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw_debug_wm); + mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5)); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5)); - return 0; +out: + if (ret) + dev->fw.debug_wm = 0; + + return ret; } static int @@ -120,7 +491,7 @@ mt7915_fw_debug_wm_get(void *data, u64 *val) { struct mt7915_dev *dev = data; - *val = dev->fw_debug_wm; + *val = dev->fw.debug_wm; return 0; } @@ -134,14 +505,19 @@ mt7915_fw_debug_wa_set(void *data, u64 val) struct mt7915_dev *dev = data; int ret; - dev->fw_debug_wa = val ? MCU_FW_LOG_TO_HOST : 0; + dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0; - ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw_debug_wa); + ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa); if (ret) - return ret; + goto out; + + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), + MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0); +out: + if (ret) + dev->fw.debug_wa = 0; - return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_PDMA_RX, - !!dev->fw_debug_wa, 0); + return ret; } static int @@ -149,7 +525,7 @@ mt7915_fw_debug_wa_get(void *data, u64 *val) { struct mt7915_dev *dev = data; - *val = dev->fw_debug_wa; + *val = dev->fw.debug_wa; return 0; } @@ -157,12 +533,77 @@ mt7915_fw_debug_wa_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wa, mt7915_fw_debug_wa_get, mt7915_fw_debug_wa_set, "%lld\n"); +static struct dentry * +create_buf_file_cb(const char *filename, struct dentry *parent, umode_t mode, + struct rchan_buf *buf, int *is_global) +{ + struct dentry *f; + + f = debugfs_create_file("fwlog_data", mode, parent, buf, + &relay_file_operations); + if (IS_ERR(f)) + return NULL; + + *is_global = 1; + + return f; +} + +static int +remove_buf_file_cb(struct dentry *f) +{ + debugfs_remove(f); + + return 0; +} + +static int +mt7915_fw_debug_bin_set(void *data, u64 val) +{ + static struct rchan_callbacks relay_cb = { + .create_buf_file = create_buf_file_cb, + .remove_buf_file = remove_buf_file_cb, + }; + struct mt7915_dev *dev = data; + + if (!dev->relay_fwlog) + dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir, + 1500, 512, &relay_cb, NULL); + if (!dev->relay_fwlog) + return -ENOMEM; + + dev->fw.debug_bin = val; + + relay_reset(dev->relay_fwlog); + + return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm); +} + +static int +mt7915_fw_debug_bin_get(void *data, u64 *val) +{ + struct mt7915_dev *dev = data; + + *val = dev->fw.debug_bin; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_bin, mt7915_fw_debug_bin_get, + mt7915_fw_debug_bin_set, "%lld\n"); + static int mt7915_fw_util_wm_show(struct seq_file *file, void *data) { struct mt7915_dev *dev = file->private; - if (dev->fw_debug_wm) { + seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC)); + seq_printf(file, "Exception state: 0x%x\n", + is_mt7915(&dev->mt76) ? + (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(15, 8)) : + (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(7, 0))); + + if (dev->fw.debug_wm) { seq_printf(file, "Busy: %u%% Peak busy: %u%%\n", mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT), mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT)); @@ -181,7 +622,9 @@ mt7915_fw_util_wa_show(struct seq_file *file, void *data) { struct mt7915_dev *dev = file->private; - if (dev->fw_debug_wa) + seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC)); + + if (dev->fw.debug_wa) return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY), MCU_WA_PARAM_CPU_UTIL, 0, 0); @@ -200,12 +643,12 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, /* Tx ampdu stat */ for (i = 0; i < ARRAY_SIZE(range); i++) - range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i)); + range[i] = mt76_rr(dev, MT_MIB_ARNG(phy->band_idx, i)); for (i = 0; i < ARRAY_SIZE(bound); i++) bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; - seq_printf(file, "\nPhy %d\n", ext_phy); + seq_printf(file, "\nPhy %d, Phy band %d\n", ext_phy, phy->band_idx); seq_printf(file, "Length: %8d | ", bound[0]); for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) @@ -213,7 +656,7 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, bound[i] + 1, bound[i + 1]); seq_puts(file, "\nCount: "); - n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + n = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0; i < ARRAY_SIZE(bound); i++) seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + n]); seq_puts(file, "\n"); @@ -302,14 +745,14 @@ mt7915_tx_stats_show(struct seq_file *file, void *data) DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats); static void -mt7915_hw_queue_read(struct seq_file *s, u32 base, u32 size, +mt7915_hw_queue_read(struct seq_file *s, u32 size, const struct hw_queue_map *map) { struct mt7915_phy *phy = s->private; struct mt7915_dev *dev = phy->dev; u32 i, val; - val = mt76_rr(dev, base + MT_FL_Q_EMPTY); + val = mt76_rr(dev, MT_FL_Q_EMPTY); for (i = 0; i < size; i++) { u32 ctrl, head, tail, queued; @@ -317,13 +760,13 @@ mt7915_hw_queue_read(struct seq_file *s, u32 base, u32 size, continue; ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24); - mt76_wr(dev, base + MT_FL_Q0_CTRL, ctrl); + mt76_wr(dev, MT_FL_Q0_CTRL, ctrl); - head = mt76_get_field(dev, base + MT_FL_Q2_CTRL, + head = mt76_get_field(dev, MT_FL_Q2_CTRL, GENMASK(11, 0)); - tail = mt76_get_field(dev, base + MT_FL_Q2_CTRL, + tail = mt76_get_field(dev, MT_FL_Q2_CTRL, GENMASK(27, 16)); - queued = mt76_get_field(dev, base + MT_FL_Q3_CTRL, + queued = mt76_get_field(dev, MT_FL_Q3_CTRL, GENMASK(11, 0)); seq_printf(s, "\t%s: ", map[i].name); @@ -351,12 +794,12 @@ mt7915_sta_hw_queue_read(void *data, struct ieee80211_sta *sta) if (val & BIT(offs)) continue; - mt76_wr(dev, MT_PLE_BASE + MT_FL_Q0_CTRL, ctrl | msta->wcid.idx); - qlen = mt76_get_field(dev, MT_PLE_BASE + MT_FL_Q3_CTRL, + mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx); + qlen = mt76_get_field(dev, MT_FL_Q3_CTRL, GENMASK(11, 0)); seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n", - sta->addr, msta->wcid.idx, msta->vif->wmm_idx, - ac, qlen); + sta->addr, msta->wcid.idx, + msta->vif->mt76.wmm_idx, ac, qlen); } } @@ -414,7 +857,7 @@ mt7915_hw_queues_show(struct seq_file *file, void *data) val, head, tail); seq_puts(file, "PLE non-empty queue info:\n"); - mt7915_hw_queue_read(file, MT_PLE_BASE, ARRAY_SIZE(ple_queue_map), + mt7915_hw_queue_read(file, ARRAY_SIZE(ple_queue_map), &ple_queue_map[0]); /* iterate per-sta ple queue */ @@ -422,7 +865,7 @@ mt7915_hw_queues_show(struct seq_file *file, void *data) mt7915_sta_hw_queue_read, file); /* pse queue */ seq_puts(file, "PSE non-empty queue info:\n"); - mt7915_hw_queue_read(file, MT_PSE_BASE, ARRAY_SIZE(pse_queue_map), + mt7915_hw_queue_read(file, ARRAY_SIZE(pse_queue_map), &pse_queue_map[0]); return 0; @@ -519,6 +962,37 @@ mt7915_twt_stats(struct seq_file *s, void *data) return 0; } +/* The index of RF registers use the generic regidx, combined with two parts: + * WF selection [31:28] and offset [27:0]. + */ +static int +mt7915_rf_regval_get(void *data, u64 *val) +{ + struct mt7915_dev *dev = data; + u32 regval; + int ret; + + ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, ®val, false); + if (ret) + return ret; + + *val = regval; + + return 0; +} + +static int +mt7915_rf_regval_set(void *data, u64 val) +{ + struct mt7915_dev *dev = data; + u32 val32 = val; + + return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true); +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get, + mt7915_rf_regval_set, "0x%08llx\n"); + int mt7915_init_debugfs(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; @@ -528,14 +1002,18 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) dir = mt76_register_debugfs_fops(phy->mt76, NULL); if (!dir) return -ENOMEM; - + debugfs_create_file("muru_debug", 0600, dir, dev, &fops_muru_debug); + debugfs_create_file("muru_stats", 0400, dir, phy, + &mt7915_muru_stats_fops); debugfs_create_file("hw-queues", 0400, dir, phy, &mt7915_hw_queues_fops); debugfs_create_file("xmit-queues", 0400, dir, phy, &mt7915_xmit_queues_fops); debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops); + debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_ops); debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm); debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa); + debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin); debugfs_create_file("fw_util_wm", 0400, dir, dev, &mt7915_fw_util_wm_fops); debugfs_create_file("fw_util_wa", 0400, dir, dev, @@ -546,17 +1024,79 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) &mt7915_rate_txpower_fops); debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, mt7915_twt_stats); - debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger); - if (!dev->dbdc_support || ext_phy) { + debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); + + if (!dev->dbdc_support || phy->band_idx) { debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); debugfs_create_file("radar_trigger", 0200, dir, dev, &fops_radar_trigger); + debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, + mt7915_rdd_monitor); } + if (!ext_phy) + dev->debugfs_dir = dir; + return 0; } +static void +mt7915_debugfs_write_fwlog(struct mt7915_dev *dev, const void *hdr, int hdrlen, + const void *data, int len) +{ + static DEFINE_SPINLOCK(lock); + unsigned long flags; + void *dest; + + spin_lock_irqsave(&lock, flags); + dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4); + if (dest) { + *(u32 *)dest = hdrlen + len; + dest += 4; + + if (hdrlen) { + memcpy(dest, hdr, hdrlen); + dest += hdrlen; + } + + memcpy(dest, data, len); + relay_flush(dev->relay_fwlog); + } + spin_unlock_irqrestore(&lock, flags); +} + +void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len) +{ + struct { + __le32 magic; + __le32 timestamp; + __le16 msg_type; + __le16 len; + } hdr = { + .magic = cpu_to_le32(FW_BIN_LOG_MAGIC), + .msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR), + }; + + if (!dev->relay_fwlog) + return; + + hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0))); + hdr.len = *(__le16 *)data; + mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len); +} + +bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len) +{ + if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC) + return false; + + if (dev->relay_fwlog) + mt7915_debugfs_write_fwlog(dev, NULL, 0, data, len); + + return true; +} + #ifdef CONFIG_MAC80211_DEBUGFS /** per-station debugfs **/ @@ -605,8 +1145,8 @@ static ssize_t mt7915_sta_fixed_rate_set(struct file *file, phy.ldpc = (phy.bw || phy.ldpc) * GENMASK(2, 0); for (i = 0; i <= phy.bw; i++) { - phy.sgi |= gi << (i << sta->he_cap.has_he); - phy.he_ltf |= he_ltf << (i << sta->he_cap.has_he); + phy.sgi |= gi << (i << sta->deflink.he_cap.has_he); + phy.he_ltf |= he_ltf << (i << sta->deflink.he_cap.has_he); } field = RATE_PARAM_FIXED; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 9182568f95c7..00aafc2422f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -5,25 +5,18 @@ #include "../dma.h" #include "mac.h" -int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc) +static int +mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base) { - int i, err; + struct mt7915_dev *dev = phy->dev; - err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE); - if (err < 0) - return err; - - for (i = 0; i <= MT_TXQ_PSD; i++) - phy->mt76->q_tx[i] = phy->mt76->q_tx[0]; + if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + ring_base = MT_WED_TX_RING_BASE; + idx -= MT_TXQ_ID(0); + } - return 0; -} - -static void -mt7915_tx_cleanup(struct mt7915_dev *dev) -{ - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false); + return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base, + MT_WED_Q_TX(idx)); } static int mt7915_poll_tx(struct napi_struct *napi, int budget) @@ -32,148 +25,443 @@ static int mt7915_poll_tx(struct napi_struct *napi, int budget) dev = container_of(napi, struct mt7915_dev, mt76.tx_napi); - mt7915_tx_cleanup(dev); - + mt76_connac_tx_cleanup(&dev->mt76); if (napi_complete_done(napi, 0)) mt7915_irq_enable(dev, MT_INT_TX_DONE_MCU); return 0; } +static void mt7915_dma_config(struct mt7915_dev *dev) +{ +#define Q_CONFIG(q, wfdma, int, id) do { \ + if (wfdma) \ + dev->wfdma_mask |= (1 << (q)); \ + dev->q_int_mask[(q)] = int; \ + dev->q_id[(q)] = id; \ + } while (0) + +#define MCUQ_CONFIG(q, wfdma, int, id) Q_CONFIG(q, (wfdma), (int), (id)) +#define RXQ_CONFIG(q, wfdma, int, id) Q_CONFIG(__RXQ(q), (wfdma), (int), (id)) +#define TXQ_CONFIG(q, wfdma, int, id) Q_CONFIG(__TXQ(q), (wfdma), (int), (id)) + + if (is_mt7915(&dev->mt76)) { + RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7915_RXQ_BAND0); + RXQ_CONFIG(MT_RXQ_MCU, WFDMA1, MT_INT_RX_DONE_WM, MT7915_RXQ_MCU_WM); + RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA1, MT_INT_RX_DONE_WA, MT7915_RXQ_MCU_WA); + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7915_RXQ_BAND1); + RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA1, MT_INT_RX_DONE_WA_EXT, MT7915_RXQ_MCU_WA_EXT); + RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA1, MT_INT_RX_DONE_WA_MAIN, MT7915_RXQ_MCU_WA); + TXQ_CONFIG(0, WFDMA1, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0); + TXQ_CONFIG(1, WFDMA1, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1); + MCUQ_CONFIG(MT_MCUQ_WM, WFDMA1, MT_INT_TX_DONE_MCU_WM, MT7915_TXQ_MCU_WM); + MCUQ_CONFIG(MT_MCUQ_WA, WFDMA1, MT_INT_TX_DONE_MCU_WA, MT7915_TXQ_MCU_WA); + MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA1, MT_INT_TX_DONE_FWDL, MT7915_TXQ_FWDL); + } else { + RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0); + RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7916_RXQ_MCU_WM); + RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7916_RXQ_MCU_WA); + RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1); + RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT); + RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN); + TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0); + TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1); + MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7915_TXQ_MCU_WM); + MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA_MT7916, MT7915_TXQ_MCU_WA); + MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7915_TXQ_FWDL); + } +} + static void __mt7915_dma_prefetch(struct mt7915_dev *dev, u32 ofs) { -#define PREFETCH(base, depth) ((base) << 16 | (depth)) - - mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL + ofs, PREFETCH(0x0, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL + ofs, PREFETCH(0x40, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL + ofs, PREFETCH(0x80, 0x0)); - - mt76_wr(dev, MT_WFDMA1_TX_RING0_EXT_CTRL + ofs, PREFETCH(0x80, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING1_EXT_CTRL + ofs, PREFETCH(0xc0, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING2_EXT_CTRL + ofs, PREFETCH(0x100, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING3_EXT_CTRL + ofs, PREFETCH(0x140, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING4_EXT_CTRL + ofs, PREFETCH(0x180, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING5_EXT_CTRL + ofs, PREFETCH(0x1c0, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING6_EXT_CTRL + ofs, PREFETCH(0x200, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING7_EXT_CTRL + ofs, PREFETCH(0x240, 0x4)); - - mt76_wr(dev, MT_WFDMA1_TX_RING16_EXT_CTRL + ofs, PREFETCH(0x280, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING17_EXT_CTRL + ofs, PREFETCH(0x2c0, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING18_EXT_CTRL + ofs, PREFETCH(0x300, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING19_EXT_CTRL + ofs, PREFETCH(0x340, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING20_EXT_CTRL + ofs, PREFETCH(0x380, 0x4)); - mt76_wr(dev, MT_WFDMA1_TX_RING21_EXT_CTRL + ofs, PREFETCH(0x3c0, 0x0)); - - mt76_wr(dev, MT_WFDMA1_RX_RING0_EXT_CTRL + ofs, PREFETCH(0x3c0, 0x4)); - mt76_wr(dev, MT_WFDMA1_RX_RING1_EXT_CTRL + ofs, PREFETCH(0x400, 0x4)); - mt76_wr(dev, MT_WFDMA1_RX_RING2_EXT_CTRL + ofs, PREFETCH(0x440, 0x4)); - mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL + ofs, PREFETCH(0x480, 0x0)); +#define PREFETCH(_base, _depth) ((_base) << 16 | (_depth)) + u32 base = 0; + + /* prefetch SRAM wrapping boundary for tx/rx ring. */ + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x0, 0x4)); + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x40, 0x4)); + mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x80, 0x4)); + mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0xc0, 0x4)); + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x100, 0x4)); + + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, + PREFETCH(0x140, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, + PREFETCH(0x180, 0x4)); + if (!is_mt7915(&dev->mt76)) { + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, + PREFETCH(0x1c0, 0x4)); + base = 0x40; + } + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs, + PREFETCH(0x1c0 + base, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, + PREFETCH(0x200 + base, 0x4)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs, + PREFETCH(0x240 + base, 0x4)); + + /* for mt7915, the ring which is next the last + * used ring must be initialized. + */ + if (is_mt7915(&dev->mt76)) { + ofs += 0x4; + mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, + PREFETCH(0x140, 0x0)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs, + PREFETCH(0x200 + base, 0x0)); + mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs, + PREFETCH(0x280 + base, 0x0)); + } } void mt7915_dma_prefetch(struct mt7915_dev *dev) { __mt7915_dma_prefetch(dev, 0); if (dev->hif2) - __mt7915_dma_prefetch(dev, MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE); + __mt7915_dma_prefetch(dev, MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0)); } -int mt7915_dma_init(struct mt7915_dev *dev) +static void mt7915_dma_disable(struct mt7915_dev *dev, bool rst) { + struct mt76_dev *mdev = &dev->mt76; u32 hif1_ofs = 0; - int ret; - - mt76_dma_attach(&dev->mt76); if (dev->hif2) - hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE; + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + + /* reset */ + if (rst) { + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + if (is_mt7915(mdev)) { + mt76_clear(dev, MT_WFDMA1_RST, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA1_RST, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + } + + if (dev->hif2) { + mt76_clear(dev, MT_WFDMA0_RST + hif1_ofs, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST + hif1_ofs, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + if (is_mt7915(mdev)) { + mt76_clear(dev, MT_WFDMA1_RST + hif1_ofs, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA1_RST + hif1_ofs, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + } + } + } - /* configure global setting */ - mt76_set(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + /* disable */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_clear(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (dev->hif2) { + mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO_PFET2); + } +} + +static int mt7915_dma_enable(struct mt7915_dev *dev) +{ + struct mt76_dev *mdev = &dev->mt76; + u32 hif1_ofs = 0; + u32 irq_mask; + + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); /* reset dma idx */ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); - mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR, ~0); + if (is_mt7915(mdev)) + mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR, ~0); + if (dev->hif2) { + mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR + hif1_ofs, ~0); + if (is_mt7915(mdev)) + mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR + hif1_ofs, ~0); + } - /* configure delay interrupt */ + /* configure delay interrupt off */ mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); - mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0); + if (is_mt7915(mdev)) { + mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0); + } else { + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG1, 0); + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG2, 0); + } if (dev->hif2) { - mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0 + hif1_ofs, 0); + if (is_mt7915(mdev)) { + mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0 + + hif1_ofs, 0); + } else { + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG1 + + hif1_ofs, 0); + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG2 + + hif1_ofs, 0); + } + } + + /* configure perfetch settings */ + mt7915_dma_prefetch(dev); + + /* hif wait WFDMA idle */ + mt76_set(dev, MT_WFDMA0_BUSY_ENA, + MT_WFDMA0_BUSY_ENA_TX_FIFO0 | + MT_WFDMA0_BUSY_ENA_TX_FIFO1 | + MT_WFDMA0_BUSY_ENA_RX_FIFO); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_BUSY_ENA, + MT_WFDMA1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA1_BUSY_ENA_RX_FIFO); + + if (dev->hif2) { + mt76_set(dev, MT_WFDMA0_BUSY_ENA + hif1_ofs, + MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_BUSY_ENA + hif1_ofs, + MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO); + } + + mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, + MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); + + /* set WFDMA Tx/Rx */ + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR + hif1_ofs, ~0); - mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR + hif1_ofs, ~0); + if (dev->hif2) { + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0 + hif1_ofs, 0); - mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0 + hif1_ofs, 0); + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_PDMA_BAND); } - /* configure perfetch settings */ - mt7915_dma_prefetch(dev); + /* enable interrupts for TX/RX rings */ + irq_mask = MT_INT_RX_DONE_MCU | + MT_INT_TX_DONE_MCU | + MT_INT_MCU_CMD; + + if (!dev->phy.band_idx) + irq_mask |= MT_INT_BAND0_RX_DONE; + + if (dev->dbdc_support || dev->phy.band_idx) + irq_mask |= MT_INT_BAND1_RX_DONE; + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + u32 wed_irq_mask = irq_mask; + + wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; + mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); + mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + } + + mt7915_irq_enable(dev, irq_mask); + + return 0; +} + +int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) +{ + struct mt76_dev *mdev = &dev->mt76; + u32 wa_rx_base, wa_rx_idx; + u32 hif1_ofs = 0; + int ret; + + mt7915_dma_config(dev); + + mt76_dma_attach(&dev->mt76); + + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + + mt7915_dma_disable(dev, true); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED); + + mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL, + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) | + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) | + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1)); + } else { + mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED); + } /* init tx queue */ - ret = mt7915_init_tx_queues(&dev->phy, MT7915_TXQ_BAND0, - MT7915_TX_RING_SIZE); + ret = mt7915_init_tx_queues(&dev->phy, + MT_TXQ_ID(dev->phy.band_idx), + MT7915_TX_RING_SIZE, + MT_TXQ_RING_BASE(0)); if (ret) return ret; + if (phy2) { + ret = mt7915_init_tx_queues(phy2, + MT_TXQ_ID(phy2->band_idx), + MT7915_TX_RING_SIZE, + MT_TXQ_RING_BASE(1)); + if (ret) + return ret; + } + /* command to WM */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7915_TXQ_MCU_WM, - MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, + MT_MCUQ_ID(MT_MCUQ_WM), + MT7915_TX_MCU_RING_SIZE, + MT_MCUQ_RING_BASE(MT_MCUQ_WM)); if (ret) return ret; /* command to WA */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, MT7915_TXQ_MCU_WA, - MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, + MT_MCUQ_ID(MT_MCUQ_WA), + MT7915_TX_MCU_RING_SIZE, + MT_MCUQ_RING_BASE(MT_MCUQ_WA)); if (ret) return ret; /* firmware download */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7915_TXQ_FWDL, - MT7915_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, + MT_MCUQ_ID(MT_MCUQ_FWDL), + MT7915_TX_FWDL_RING_SIZE, + MT_MCUQ_RING_BASE(MT_MCUQ_FWDL)); if (ret) return ret; /* event from WM */ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], - MT7915_RXQ_MCU_WM, MT7915_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + MT_RXQ_ID(MT_RXQ_MCU), + MT7915_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MCU)); if (ret) return ret; /* event from WA */ + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + wa_rx_base = MT_WED_RX_RING_BASE; + wa_rx_idx = MT7915_RXQ_MCU_WA; + dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE; + } else { + wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA); + wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA); + } ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], - MT7915_RXQ_MCU_WA, MT7915_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + wa_rx_idx, MT7915_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, wa_rx_base); if (ret) return ret; - /* rx data queue */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], - MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); - if (ret) - return ret; + /* rx data queue for band0 */ + if (!dev->phy.band_idx) { + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], + MT_RXQ_ID(MT_RXQ_MAIN), + MT7915_RX_RING_SIZE, + MT_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_MAIN)); + if (ret) + return ret; + } - if (dev->dbdc_support) { - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT], - MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE, + /* tx free notify event from WA for band0 */ + if (!is_mt7915(mdev)) { + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA], + MT_RXQ_ID(MT_RXQ_MAIN_WA), + MT7915_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE, - MT_RX_DATA_RING_BASE + hif1_ofs); + MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA)); if (ret) return ret; + } - /* event from WA */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA], - MT7915_RXQ_MCU_WA_EXT, + if (dev->dbdc_support || dev->phy.band_idx) { + /* rx data queue for band1 */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1], + MT_RXQ_ID(MT_RXQ_BAND1), + MT7915_RX_RING_SIZE, + MT_RX_BUF_SIZE, + MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs); + if (ret) + return ret; + + /* tx free notify event from WA for band1 */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA], + MT_RXQ_ID(MT_RXQ_BAND1_WA), MT7915_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE, - MT_RX_EVENT_RING_BASE + hif1_ofs); + MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs); if (ret) return ret; } @@ -182,84 +470,18 @@ int mt7915_dma_init(struct mt7915_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7915_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7915_poll_tx); napi_enable(&dev->mt76.tx_napi); - /* hif wait WFDMA idle */ - mt76_set(dev, MT_WFDMA0_BUSY_ENA, - MT_WFDMA0_BUSY_ENA_TX_FIFO0 | - MT_WFDMA0_BUSY_ENA_TX_FIFO1 | - MT_WFDMA0_BUSY_ENA_RX_FIFO); - - mt76_set(dev, MT_WFDMA1_BUSY_ENA, - MT_WFDMA1_BUSY_ENA_TX_FIFO0 | - MT_WFDMA1_BUSY_ENA_TX_FIFO1 | - MT_WFDMA1_BUSY_ENA_RX_FIFO); - - mt76_set(dev, MT_WFDMA0_PCIE1_BUSY_ENA, - MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 | - MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 | - MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO); - - mt76_set(dev, MT_WFDMA1_PCIE1_BUSY_ENA, - MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 | - MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 | - MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO); - - mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, - MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); - - /* set WFDMA Tx/Rx */ - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); - - if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - (MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN)); - mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, - (MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN)); - mt76_set(dev, MT_WFDMA_HOST_CONFIG, - MT_WFDMA_HOST_CONFIG_PDMA_BAND); - } - - /* enable interrupts for TX/RX rings */ - mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_MCU | - MT_INT_MCU_CMD); + mt7915_dma_enable(dev); return 0; } void mt7915_dma_cleanup(struct mt7915_dev *dev) { - /* disable */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_clear(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN); - - /* reset */ - mt76_clear(dev, MT_WFDMA1_RST, - MT_WFDMA1_RST_DMASHDL_ALL_RST | - MT_WFDMA1_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA1_RST, - MT_WFDMA1_RST_DMASHDL_ALL_RST | - MT_WFDMA1_RST_LOGIC_RST); - - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); + mt7915_dma_disable(dev, true); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index ee3d64434821..4b1a9811646f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ +#include <linux/firmware.h> #include "mt7915.h" #include "eeprom.h" @@ -9,6 +10,10 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) struct mt76_dev *mdev = &dev->mt76; u8 *eeprom = mdev->eeprom.data; u32 val = eeprom[MT_EE_DO_PRE_CAL]; + u32 offs; + + if (!dev->flash_mode) + return 0; if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP)) return 0; @@ -18,57 +23,138 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) if (!dev->cal) return -ENOMEM; - return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val); + offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2; + + return mt76_get_of_eeprom(mdev, dev->cal, offs, val); +} + +static int mt7915_check_eeprom(struct mt7915_dev *dev) +{ + u8 *eeprom = dev->mt76.eeprom.data; + u16 val = get_unaligned_le16(eeprom); + + switch (val) { + case 0x7915: + case 0x7916: + case 0x7986: + return 0; + default: + return -EINVAL; + } +} + +static char *mt7915_eeprom_name(struct mt7915_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + return dev->dbdc_support ? + MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT; + case 0x7986: + switch (mt7915_check_adie(dev, true)) { + case MT7976_ONE_ADIE_DBDC: + return MT7986_EEPROM_MT7976_DEFAULT_DBDC; + case MT7975_ONE_ADIE: + return MT7986_EEPROM_MT7975_DEFAULT; + case MT7976_ONE_ADIE: + return MT7986_EEPROM_MT7976_DEFAULT; + case MT7975_DUAL_ADIE: + return MT7986_EEPROM_MT7975_DUAL_DEFAULT; + case MT7976_DUAL_ADIE: + return MT7986_EEPROM_MT7976_DUAL_DEFAULT; + default: + break; + } + return NULL; + default: + return MT7916_EEPROM_DEFAULT; + } +} + +static int +mt7915_eeprom_load_default(struct mt7915_dev *dev) +{ + u8 *eeprom = dev->mt76.eeprom.data; + const struct firmware *fw = NULL; + int ret; + + ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data) { + dev_err(dev->mt76.dev, "Invalid default bin\n"); + ret = -EINVAL; + goto out; + } + + memcpy(eeprom, fw->data, mt7915_eeprom_size(dev)); + dev->flash_mode = true; + +out: + release_firmware(fw); + + return ret; } static int mt7915_eeprom_load(struct mt7915_dev *dev) { int ret; + u16 eeprom_size = mt7915_eeprom_size(dev); - ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE); + ret = mt76_eeprom_init(&dev->mt76, eeprom_size); if (ret < 0) return ret; if (ret) { dev->flash_mode = true; - ret = mt7915_eeprom_load_precal(dev); } else { + u8 free_block_num; u32 block_num, i; - block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE, + mt7915_mcu_get_eeprom_free_block(dev, &free_block_num); + /* efuse info not enough */ + if (free_block_num >= 29) + return -EINVAL; + + /* read eeprom data from efuse */ + block_num = DIV_ROUND_UP(eeprom_size, MT7915_EEPROM_BLOCK_SIZE); for (i = 0; i < block_num; i++) mt7915_mcu_get_eeprom(dev, i * MT7915_EEPROM_BLOCK_SIZE); } - return ret; -} - -static int mt7915_check_eeprom(struct mt7915_dev *dev) -{ - u8 *eeprom = dev->mt76.eeprom.data; - u16 val = get_unaligned_le16(eeprom); - - switch (val) { - case 0x7915: - return 0; - default: - return -EINVAL; - } + return mt7915_check_eeprom(dev); } -void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) +static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; u8 *eeprom = dev->mt76.eeprom.data; u32 val; - val = eeprom[MT_EE_WIFI_CONF + ext_phy]; + val = eeprom[MT_EE_WIFI_CONF + phy->band_idx]; val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); - if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) - val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; + + if (!is_mt7915(&dev->mt76)) { + switch (val) { + case MT_EE_V2_BAND_SEL_5GHZ: + phy->mt76->cap.has_5ghz = true; + return; + case MT_EE_V2_BAND_SEL_6GHZ: + phy->mt76->cap.has_6ghz = true; + return; + case MT_EE_V2_BAND_SEL_5GHZ_6GHZ: + phy->mt76->cap.has_5ghz = true; + phy->mt76->cap.has_6ghz = true; + return; + default: + phy->mt76->cap.has_2ghz = true; + return; + } + } else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) { + val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; + } switch (val) { case MT_EE_BAND_SEL_5GHZ: @@ -84,32 +170,65 @@ void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) } } -static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, + struct mt7915_phy *phy) { - u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data; + u8 nss, nss_band, nss_band_max, *eeprom = dev->mt76.eeprom.data; + struct mt76_phy *mphy = phy->mt76; + bool ext_phy = phy != &dev->phy; - mt7915_eeprom_parse_band_config(&dev->phy); + mt7915_eeprom_parse_band_config(phy); + + /* read tx/rx mask from eeprom */ + if (is_mt7915(&dev->mt76)) { + nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, + eeprom[MT_EE_WIFI_CONF]); + } else { + nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, + eeprom[MT_EE_WIFI_CONF + phy->band_idx]); + } - /* read tx mask from eeprom */ - nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]); if (!nss || nss > 4) nss = 4; + /* read tx/rx stream */ nss_band = nss; if (dev->dbdc_support) { - nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, - eeprom[MT_EE_WIFI_CONF + 3]); - if (!nss_band || nss_band > 2) - nss_band = 2; + if (is_mt7915(&dev->mt76)) { + nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, + eeprom[MT_EE_WIFI_CONF + 3]); + if (phy->band_idx) + nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1, + eeprom[MT_EE_WIFI_CONF + 3]); + } else { + nss_band = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM, + eeprom[MT_EE_WIFI_CONF + 2 + phy->band_idx]); + } + + nss_band_max = is_mt7986(&dev->mt76) ? + MT_EE_NSS_MAX_DBDC_MA7986 : MT_EE_NSS_MAX_DBDC_MA7915; + } else { + nss_band_max = is_mt7986(&dev->mt76) ? + MT_EE_NSS_MAX_MA7986 : MT_EE_NSS_MAX_MA7915; + } - if (nss_band >= nss) - nss = 4; + if (!nss_band || nss_band > nss_band_max) + nss_band = nss_band_max; + + if (nss_band > nss) { + dev_warn(dev->mt76.dev, + "nss mismatch, nss(%d) nss_band(%d) band(%d) ext_phy(%d)\n", + nss, nss_band, phy->band_idx, ext_phy); + nss = nss_band; } - dev->chainmask = BIT(nss) - 1; - dev->mphy.antenna_mask = BIT(nss_band) - 1; - dev->mphy.chainmask = dev->mphy.antenna_mask; + mphy->chainmask = BIT(nss) - 1; + if (ext_phy) + mphy->chainmask <<= dev->chainshift; + mphy->antenna_mask = BIT(nss_band) - 1; + dev->chainmask |= mphy->chainmask; + dev->chainshift = hweight8(dev->mphy.chainmask); } int mt7915_eeprom_init(struct mt7915_dev *dev) @@ -117,14 +236,21 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) int ret; ret = mt7915_eeprom_load(dev); - if (ret < 0) - return ret; + if (ret < 0) { + if (ret != -EINVAL) + return ret; + + dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n"); + ret = mt7915_eeprom_load_default(dev); + if (ret) + return ret; + } - ret = mt7915_check_eeprom(dev); + ret = mt7915_eeprom_load_precal(dev); if (ret) return ret; - mt7915_eeprom_parse_hw_cap(dev); + mt7915_eeprom_parse_hw_cap(dev, &dev->phy); memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); @@ -139,27 +265,43 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, { u8 *eeprom = dev->mt76.eeprom.data; int index, target_power; - bool tssi_on; + bool tssi_on, is_7976; if (chain_idx > 3) return -EINVAL; tssi_on = mt7915_tssi_enabled(dev, chan->band); + is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76); if (chan->band == NL80211_BAND_2GHZ) { - index = MT_EE_TX0_POWER_2G + chain_idx * 3; - target_power = eeprom[index]; - - if (!tssi_on) - target_power += eeprom[index + 1]; + if (is_7976) { + index = MT_EE_TX0_POWER_2G_V2 + chain_idx; + target_power = eeprom[index]; + } else { + index = MT_EE_TX0_POWER_2G + chain_idx * 3; + target_power = eeprom[index]; + + if (!tssi_on) + target_power += eeprom[index + 1]; + } + } else if (chan->band == NL80211_BAND_5GHZ) { + int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976); + + if (is_7976) { + index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5; + target_power = eeprom[index + group]; + } else { + index = MT_EE_TX0_POWER_5G + chain_idx * 12; + target_power = eeprom[index + group]; + + if (!tssi_on) + target_power += eeprom[index + 8]; + } } else { - int group = mt7915_get_channel_group(chan->hw_value); - - index = MT_EE_TX0_POWER_5G + chain_idx * 12; - target_power = eeprom[index + group]; + int group = mt7915_get_channel_group_6g(chan->hw_value); - if (!tssi_on) - target_power += eeprom[index + 8]; + index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8; + target_power = is_7976 ? eeprom[index + group] : 0; } return target_power; @@ -168,15 +310,20 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band) { u8 *eeprom = dev->mt76.eeprom.data; - u32 val; + u32 val, offs; s8 delta; + bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76); if (band == NL80211_BAND_2GHZ) - val = eeprom[MT_EE_RATE_DELTA_2G]; + offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G; + else if (band == NL80211_BAND_5GHZ) + offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G; else - val = eeprom[MT_EE_RATE_DELTA_5G]; + offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0; + + val = eeprom[offs]; - if (!(val & MT_EE_RATE_DELTA_EN)) + if (!offs || !(val & MT_EE_RATE_DELTA_EN)) return 0; delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index a43389a41800..7578ac6d0be6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -23,11 +23,19 @@ enum mt7915_eeprom_field { MT_EE_RATE_DELTA_5G = 0x29d, MT_EE_TX0_POWER_2G = 0x2fc, MT_EE_TX0_POWER_5G = 0x34b, + MT_EE_RATE_DELTA_2G_V2 = 0x7d3, + MT_EE_RATE_DELTA_5G_V2 = 0x81e, + MT_EE_RATE_DELTA_6G_V2 = 0x884, /* 6g fields only appear in eeprom v2 */ + MT_EE_TX0_POWER_2G_V2 = 0x441, + MT_EE_TX0_POWER_5G_V2 = 0x445, + MT_EE_TX0_POWER_6G_V2 = 0x465, MT_EE_ADIE_FT_VERSION = 0x9a0, __MT_EE_MAX = 0xe00, + __MT_EE_MAX_V2 = 0x1000, /* 0xe10 ~ 0x5780 used to save group cal data */ - MT_EE_PRECAL = 0xe10 + MT_EE_PRECAL = 0xe10, + MT_EE_PRECAL_V2 = 0x1010 }; #define MT_EE_WIFI_CAL_GROUP BIT(0) @@ -39,6 +47,7 @@ enum mt7915_eeprom_field { #define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0) #define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6) #define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(7, 6) +#define MT_EE_WIFI_CONF_STREAM_NUM GENMASK(7, 5) #define MT_EE_WIFI_CONF3_TX_PATH_B0 GENMASK(1, 0) #define MT_EE_WIFI_CONF3_TX_PATH_B1 GENMASK(5, 4) #define MT_EE_WIFI_CONF7_TSSI0_2G BIT(0) @@ -49,6 +58,19 @@ enum mt7915_eeprom_field { #define MT_EE_RATE_DELTA_SIGN BIT(6) #define MT_EE_RATE_DELTA_EN BIT(7) +#define MT_EE_NSS_MAX_MA7915 4 +#define MT_EE_NSS_MAX_DBDC_MA7915 2 +#define MT_EE_NSS_MAX_MA7986 4 +#define MT_EE_NSS_MAX_DBDC_MA7986 4 + +enum mt7915_adie_sku { + MT7976_ONE_ADIE_DBDC = 0x7, + MT7975_ONE_ADIE = 0x8, + MT7976_ONE_ADIE = 0xa, + MT7975_DUAL_ADIE = 0xd, + MT7976_DUAL_ADIE = 0xf, +}; + enum mt7915_eeprom_band { MT_EE_BAND_SEL_DEFAULT, MT_EE_BAND_SEL_5GHZ, @@ -56,6 +78,13 @@ enum mt7915_eeprom_band { MT_EE_BAND_SEL_DUAL, }; +enum { + MT_EE_V2_BAND_SEL_2GHZ, + MT_EE_V2_BAND_SEL_5GHZ, + MT_EE_V2_BAND_SEL_6GHZ, + MT_EE_V2_BAND_SEL_5GHZ_6GHZ, +}; + enum mt7915_sku_rate_group { SKU_CCK, SKU_OFDM, @@ -76,8 +105,20 @@ enum mt7915_sku_rate_group { }; static inline int -mt7915_get_channel_group(int channel) +mt7915_get_channel_group_5g(int channel, bool is_7976) { + if (is_7976) { + if (channel <= 64) + return 0; + if (channel <= 96) + return 1; + if (channel <= 128) + return 2; + if (channel <= 144) + return 3; + return 4; + } + if (channel >= 184 && channel <= 196) return 0; if (channel <= 48) @@ -95,6 +136,15 @@ mt7915_get_channel_group(int channel) return 7; } +static inline int +mt7915_get_channel_group_6g(int channel) +{ + if (channel <= 29) + return 0; + + return DIV_ROUND_UP(channel - 29, 32); +} + static inline bool mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 4fa8e7ba93e6..cc2aac86bcfb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -50,15 +50,22 @@ static ssize_t mt7915_thermal_temp_show(struct device *dev, int i = to_sensor_dev_attr(attr)->index; int temperature; - if (i) - return sprintf(buf, "%u\n", phy->throttle_temp[i - 1] * 1000); - - temperature = mt7915_mcu_get_temperature(phy); - if (temperature < 0) - return temperature; - - /* display in millidegree celcius */ - return sprintf(buf, "%u\n", temperature * 1000); + switch (i) { + case 0: + temperature = mt7915_mcu_get_temperature(phy); + if (temperature < 0) + return temperature; + /* display in millidegree celcius */ + return sprintf(buf, "%u\n", temperature * 1000); + case 1: + case 2: + return sprintf(buf, "%u\n", + phy->throttle_temp[i - 1] * 1000); + case 3: + return sprintf(buf, "%hhu\n", phy->throttle_state); + default: + return -EINVAL; + } } static ssize_t mt7915_thermal_temp_store(struct device *dev, @@ -84,11 +91,13 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev, static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7915_thermal_temp, 0); static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7915_thermal_temp, 1); static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7915_thermal_temp, 2); +static SENSOR_DEVICE_ATTR_RO(throttle1, mt7915_thermal_temp, 3); static struct attribute *mt7915_hwmon_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_throttle1.dev_attr.attr, NULL, }; ATTRIBUTE_GROUPS(mt7915_hwmon); @@ -97,7 +106,7 @@ static int mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev, unsigned long *state) { - *state = MT7915_THERMAL_THROTTLE_MAX; + *state = MT7915_CDEV_THROTTLE_MAX; return 0; } @@ -108,7 +117,7 @@ mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev, { struct mt7915_phy *phy = cdev->devdata; - *state = phy->throttle_state; + *state = phy->cdev_state; return 0; } @@ -118,22 +127,27 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev, unsigned long state) { struct mt7915_phy *phy = cdev->devdata; + u8 throttling = MT7915_THERMAL_THROTTLE_MAX - state; int ret; - if (state > MT7915_THERMAL_THROTTLE_MAX) + if (state > MT7915_CDEV_THROTTLE_MAX) return -EINVAL; if (phy->throttle_temp[0] > phy->throttle_temp[1]) return 0; - if (state == phy->throttle_state) + if (state == phy->cdev_state) return 0; - ret = mt7915_mcu_set_thermal_throttling(phy, state); + /* + * cooling_device convention: 0 = no cooling, more = more cooling + * mcu convention: 1 = max cooling, more = less cooling + */ + ret = mt7915_mcu_set_thermal_throttling(phy, throttling); if (ret) return ret; - phy->throttle_state = state; + phy->cdev_state = state; return 0; } @@ -186,7 +200,8 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) phy->throttle_temp[0] = 110; phy->throttle_temp[1] = 120; - return 0; + return mt7915_mcu_set_thermal_throttling(phy, + MT7915_THERMAL_THROTTLE_MAX); } static void mt7915_led_set_config(struct led_classdev *led_cdev, @@ -288,17 +303,18 @@ mt7915_regd_notifier(struct wiphy *wiphy, struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt76_phy *mphy = hw->priv; struct mt7915_phy *phy = mphy->priv; - struct cfg80211_chan_def *chandef = &mphy->chandef; memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; + if (dev->mt76.region == NL80211_DFS_UNSET) + mt7915_mcu_rdd_background_enable(phy, NULL); + mt7915_init_txpower(dev, &mphy->sband_2g.sband); mt7915_init_txpower(dev, &mphy->sband_5g.sband); + mt7915_init_txpower(dev, &mphy->sband_6g.sband); - if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) - return; - + mphy->dfs_state = MT_DFS_STATE_UNKNOWN; mt7915_dfs_init_radar_detector(phy); } @@ -306,11 +322,13 @@ static void mt7915_init_wiphy(struct ieee80211_hw *hw) { struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt76_dev *mdev = &phy->dev->mt76; struct wiphy *wiphy = hw->wiphy; + struct mt7915_dev *dev = phy->dev; hw->queues = 4; - hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; - hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; hw->netdev_features = NETIF_F_RXCSUM; hw->radiotap_timestamp.units_pos = @@ -325,6 +343,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7915_regd_notifier; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy->mbssid_max_interfaces = 16; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); @@ -332,31 +351,66 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); + + if (!mdev->dev->of_node || + !of_property_read_bool(mdev->dev->of_node, + "mediatek,disable-radar-background")) + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_RADAR_BACKGROUND); ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); hw->max_tx_fragments = 4; - if (phy->mt76->cap.has_2ghz) + if (phy->mt76->cap.has_2ghz) { phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; + phy->mt76->sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_4; + } if (phy->mt76->cap.has_5ghz) { phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; - phy->mt76->sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + phy->mt76->sband_5g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_4; + + if (is_mt7915(&dev->mt76)) { + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + + if (!dev->dbdc_support) + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + } else { + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + + /* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */ + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + } } mt76_set_stream_caps(phy->mt76, true); mt7915_set_stream_vht_txbf_caps(phy); mt7915_set_stream_he_caps(phy); + + wiphy->available_antennas_rx = phy->mt76->antenna_mask; + wiphy->available_antennas_tx = phy->mt76->antenna_mask; } static void @@ -387,19 +441,30 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set); mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680); - /* disable rx rate report by default due to hw issues */ + + /* mt7915: disable rx rate report by default due to hw issues */ mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); } static void mt7915_mac_init(struct mt7915_dev *dev) { int i; + u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680; + + /* config pse qid6 wfdma port selection */ + if (!is_mt7915(&dev->mt76) && dev->hif2) + mt76_rmw(dev, MT_WF_PP_TOP_RXQ_WFDMA_CF_5, 0, + MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK); + + mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len); + + if (!is_mt7915(&dev->mt76)) + mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); - mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 0x400); /* enable hardware de-agg */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); - for (i = 0; i < MT7915_WTBL_SIZE; i++) + for (i = 0; i < mt7915_wtbl_size(dev); i++) mt7915_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); for (i = 0; i < 2; i++) @@ -430,59 +495,70 @@ static int mt7915_txbf_init(struct mt7915_dev *dev) return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE); } -static int mt7915_register_ext_phy(struct mt7915_dev *dev) +static struct mt7915_phy * +mt7915_alloc_ext_phy(struct mt7915_dev *dev) { - struct mt7915_phy *phy = mt7915_ext_phy(dev); + struct mt7915_phy *phy; struct mt76_phy *mphy; - int ret; if (!dev->dbdc_support) - return 0; + return NULL; - if (phy) - return 0; - - mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1); if (!mphy) - return -ENOMEM; + return ERR_PTR(-ENOMEM); phy = mphy->priv; phy->dev = dev; phy->mt76 = mphy; - mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; - mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1; + + /* Bind main phy to band0 and ext_phy to band1 for dbdc case */ + phy->band_idx = 1; + + return phy; +} + +static int +mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy) +{ + struct mt76_phy *mphy = phy->mt76; + int ret; INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); - mt7915_eeprom_parse_band_config(phy); - mt7915_init_wiphy(mphy->hw); + mt7915_eeprom_parse_hw_cap(dev, phy); memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2, ETH_ALEN); + /* Make the secondary PHY MAC address local without overlapping with + * the usual MAC address allocation scheme on multiple virtual interfaces + */ + if (!is_valid_ether_addr(mphy->macaddr)) { + memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); + mphy->macaddr[0] |= 2; + mphy->macaddr[0] ^= BIT(7); + } mt76_eeprom_override(mphy); - ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1, - MT7915_TX_RING_SIZE); - if (ret) - goto error; + /* init wiphy according to mphy and phy */ + mt7915_init_wiphy(mphy->hw); ret = mt76_register_phy(mphy, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) - goto error; + return ret; ret = mt7915_thermal_init(phy); if (ret) - goto error; + goto unreg; - ret = mt7915_init_debugfs(phy); - if (ret) - goto error; + mt7915_init_debugfs(phy); return 0; -error: - ieee80211_free_hw(mphy->hw); +unreg: + mt76_unregister_phy(mphy); return ret; } @@ -495,89 +571,114 @@ static void mt7915_init_work(struct work_struct *work) mt7915_mac_init(dev); mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband); + mt7915_init_txpower(dev, &dev->mphy.sband_6g.sband); mt7915_txbf_init(dev); } -static void mt7915_wfsys_reset(struct mt7915_dev *dev) +void mt7915_wfsys_reset(struct mt7915_dev *dev) { - u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; - #define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) #define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) - mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); + if (is_mt7915(&dev->mt76)) { + u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; - /* change to software control */ - val |= MT_TOP_PWR_SW_RST; - mt76_wr(dev, MT_TOP_PWR_CTRL, val); + mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); - /* reset wfsys */ - val &= ~MT_TOP_PWR_SW_RST; - mt76_wr(dev, MT_TOP_PWR_CTRL, val); + /* change to software control */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); - /* release wfsys then mcu re-excutes romcode */ - val |= MT_TOP_PWR_SW_RST; - mt76_wr(dev, MT_TOP_PWR_CTRL, val); + /* reset wfsys */ + val &= ~MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); - /* switch to hw control */ - val &= ~MT_TOP_PWR_SW_RST; - val |= MT_TOP_PWR_HW_CTRL; - mt76_wr(dev, MT_TOP_PWR_CTRL, val); + /* release wfsys then mcu re-executes romcode */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); - /* check whether mcu resets to default */ - if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT, - MT_MCU_DUMMY_DEFAULT, 1000)) { - dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); - return; + /* switch to hw control */ + val &= ~MT_TOP_PWR_SW_RST; + val |= MT_TOP_PWR_HW_CTRL; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* check whether mcu resets to default */ + if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, + MT_MCU_DUMMY_DEFAULT, MT_MCU_DUMMY_DEFAULT, + 1000)) { + dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); + return; + } + + /* wfsys reset won't clear host registers */ + mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); + + msleep(100); + } else if (is_mt7986(&dev->mt76)) { + mt7986_wmac_disable(dev); + msleep(20); + + mt7986_wmac_enable(dev); + msleep(20); + } else { + mt76_set(dev, MT_WF_SUBSYS_RST, 0x1); + msleep(20); + + mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1); + msleep(20); } +} + +static bool mt7915_band_config(struct mt7915_dev *dev) +{ + bool ret = true; - /* wfsys reset won't clear host registers */ - mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); + dev->phy.band_idx = 0; - msleep(100); + if (is_mt7986(&dev->mt76)) { + u32 sku = mt7915_check_adie(dev, true); + + /* + * for mt7986, dbdc support is determined by the number + * of adie chips and the main phy is bound to band1 when + * dbdc is disabled. + */ + if (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE) { + dev->phy.band_idx = 1; + ret = false; + } + } else { + ret = is_mt7915(&dev->mt76) ? + !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true; + } + + return ret; } -static int mt7915_init_hardware(struct mt7915_dev *dev) +static int +mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2) { int ret, idx; + mt76_wr(dev, MT_INT_MASK_CSR, 0); mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); INIT_WORK(&dev->init_work, mt7915_init_work); - dev->dbdc_support = !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)); - - /* If MCU was already running, it is likely in a bad state */ - if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) > - FW_STATE_FW_DOWNLOAD) - mt7915_wfsys_reset(dev); - ret = mt7915_dma_init(dev); + ret = mt7915_dma_init(dev, phy2); if (ret) return ret; set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - /* - * force firmware operation mode into normal state, - * which should be set before firmware download stage. - */ - mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - ret = mt7915_mcu_init(dev); - if (ret) { - /* Reset and try again */ - mt7915_wfsys_reset(dev); - - ret = mt7915_mcu_init(dev); - if (ret) - return ret; - } + if (ret) + return ret; ret = mt7915_eeprom_init(dev); if (ret < 0) return ret; - if (dev->flash_mode) { ret = mt7915_mcu_apply_group_cal(dev); if (ret) @@ -626,11 +727,18 @@ void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy) } static void -mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, +mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev, + struct ieee80211_sta_he_cap *he_cap, int vif, int nss) { struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem; - u8 c; + u8 c, nss_160; + + /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */ + if (is_mt7915(&dev->mt76) && !dev->dbdc_support) + nss_160 = nss / 2; + else + nss_160 = nss; #ifdef CONFIG_MAC80211_MESH if (vif == NL80211_IFTYPE_MESH_POINT) @@ -650,9 +758,10 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK; - c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | - IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; + c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US; + if (!is_mt7915(&dev->mt76)) + c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | + IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; elem->phy_cap_info[2] |= c; c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | @@ -684,20 +793,28 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, /* num_snd_dim * for mt7915, max supported nss is 2 for bw > 80MHz */ - c = (nss - 1) | - IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2; + c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, + nss - 1) | + FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK, + nss_160 - 1); elem->phy_cap_info[5] |= c; c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; + + if (!is_mt7915(&dev->mt76)) { + c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ | + IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; + elem->phy_cap_info[7] |= c; + } } static void mt7915_gen_ppe_thresh(u8 *he_ppet, int nss) { u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; + static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, @@ -718,9 +835,17 @@ static int mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) { + struct mt7915_dev *dev = phy->dev; int i, idx = 0, nss = hweight8(phy->mt76->chainmask); u16 mcs_map = 0; u16 mcs_map_160 = 0; + u8 nss_160; + + /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */ + if (is_mt7915(&dev->mt76) && !dev->dbdc_support) + nss_160 = nss / 2; + else + nss_160 = nss; for (i = 0; i < 8; i++) { if (i < nss) @@ -728,8 +853,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, else mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2)); - /* Can do 1/2 of NSS streams in 160Mhz mode. */ - if (i < nss / 2) + if (i < nss_160) mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2)); else mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2)); @@ -767,7 +891,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, if (band == NL80211_BAND_2GHZ) he_cap_elem->phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; - else if (band == NL80211_BAND_5GHZ) + else he_cap_elem->phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | @@ -806,7 +930,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, if (band == NL80211_BAND_2GHZ) he_cap_elem->phy_cap_info[0] |= IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; - else if (band == NL80211_BAND_5GHZ) + else he_cap_elem->phy_cap_info[0] |= IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; @@ -845,7 +969,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160); he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160); - mt7915_set_stream_he_txbf_caps(he_cap, i, nss); + mt7915_set_stream_he_txbf_caps(dev, he_cap, i, nss); memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & @@ -853,8 +977,24 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US; + u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, + IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); } + + if (band == NL80211_BAND_6GHZ) { + u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | + IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; + + cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | + u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | + u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); + + data[idx].he_6ghz_capa.capa = cpu_to_le16(cap); + } + idx++; } @@ -884,12 +1024,21 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) band->iftype_data = data; band->n_iftype_data = n; } + + if (phy->mt76->cap.has_6ghz) { + data = phy->iftype[NL80211_BAND_6GHZ]; + n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data); + + band = &phy->mt76->sband_6g.sband; + band->iftype_data = data; + band->n_iftype_data = n; + } } static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) { struct mt7915_phy *phy = mt7915_ext_phy(dev); - struct mt76_phy *mphy = dev->mt76.phy2; + struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1]; if (!phy) return; @@ -899,9 +1048,22 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) ieee80211_free_hw(mphy->hw); } +static void mt7915_stop_hardware(struct mt7915_dev *dev) +{ + mt7915_mcu_exit(dev); + mt7915_tx_token_put(dev); + mt7915_dma_cleanup(dev); + tasklet_disable(&dev->irq_tasklet); + + if (is_mt7986(&dev->mt76)) + mt7986_wmac_disable(dev); +} + + int mt7915_register_device(struct mt7915_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7915_phy *phy2; int ret; dev->phy.dev = dev; @@ -917,20 +1079,17 @@ int mt7915_register_device(struct mt7915_dev *dev) init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); - ret = mt7915_init_hardware(dev); - if (ret) - return ret; + dev->dbdc_support = mt7915_band_config(dev); - mt7915_init_wiphy(hw); + phy2 = mt7915_alloc_ext_phy(dev); + if (IS_ERR(phy2)) + return PTR_ERR(phy2); - if (!dev->dbdc_support) - dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + ret = mt7915_init_hardware(dev, phy2); + if (ret) + goto free_phy2; - dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; - dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; - dev->phy.dfs_state = -1; + mt7915_init_wiphy(hw); #ifdef CONFIG_NL80211_TESTMODE dev->mt76.test_ops = &mt7915_testmode_ops; @@ -945,19 +1104,34 @@ int mt7915_register_device(struct mt7915_dev *dev) ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) - return ret; + goto stop_hw; ret = mt7915_thermal_init(&dev->phy); if (ret) - return ret; + goto unreg_dev; ieee80211_queue_work(mt76_hw(dev), &dev->init_work); - ret = mt7915_register_ext_phy(dev); - if (ret) - return ret; + if (phy2) { + ret = mt7915_register_ext_phy(dev, phy2); + if (ret) + goto unreg_thermal; + } + + mt7915_init_debugfs(&dev->phy); + + return 0; - return mt7915_init_debugfs(&dev->phy); +unreg_thermal: + mt7915_unregister_thermal(&dev->phy); +unreg_dev: + mt76_unregister_device(&dev->mt76); +stop_hw: + mt7915_stop_hardware(dev); +free_phy2: + if (phy2) + ieee80211_free_hw(phy2->mt76->hw); + return ret; } void mt7915_unregister_device(struct mt7915_dev *dev) @@ -965,10 +1139,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev) mt7915_unregister_ext_phy(dev); mt7915_unregister_thermal(&dev->phy); mt76_unregister_device(&dev->mt76); - mt7915_mcu_exit(dev); - mt7915_tx_token_put(dev); - mt7915_dma_cleanup(dev); - tasklet_disable(&dev->irq_tasklet); + mt7915_stop_hardware(dev); mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 809dc18e5083..a4bcc617c1a3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -10,10 +10,6 @@ #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) -#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) -#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ - IEEE80211_RADIOTAP_HE_##f) - static const struct mt7915_dfs_radar_spec etsi_radar_specs = { .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, .radar_pattern = { @@ -165,7 +161,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - u8 q = mt7915_lmac_mapping(dev, i); + u8 q = mt76_connac_lmac_mapping(i); u32 tx_cur = tx_time[q]; u32 rx_cur = rx_time[q]; u8 tid = ac_to_tid[i]; @@ -218,172 +214,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) rcu_read_unlock(); } -static void -mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, - struct ieee80211_radiotap_he *he, - __le32 *rxv) -{ - u32 ru_h, ru_l; - u8 ru, offs = 0; - - ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0])); - ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1])); - ru = (u8)(ru_l | ru_h << 4); - - status->bw = RATE_INFO_BW_HE_RU; - - switch (ru) { - case 0 ... 36: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; - offs = ru; - break; - case 37 ... 52: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; - offs = ru - 37; - break; - case 53 ... 60: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; - offs = ru - 53; - break; - case 61 ... 64: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; - offs = ru - 61; - break; - case 65 ... 66: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; - offs = ru - 65; - break; - case 67: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; - break; - case 68: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; - break; - } - - he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | - le16_encode_bits(offs, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); -} - -static void -mt7915_mac_decode_he_mu_radiotap(struct sk_buff *skb, - struct mt76_rx_status *status, - __le32 *rxv) -{ - static const struct ieee80211_radiotap_he_mu mu_known = { - .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | - HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), - .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), - }; - struct ieee80211_radiotap_he_mu *he_mu = NULL; - - he_mu = skb_push(skb, sizeof(mu_known)); - memcpy(he_mu, &mu_known, sizeof(mu_known)); - -#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) - - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); - if (status->he_dcm) - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); - - he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | - MU_PREP(FLAGS2_SIG_B_SYMS_USERS, - le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); - - he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0); - - if (status->bw >= RATE_INFO_BW_40) { - he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); - he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1); - } - - if (status->bw >= RATE_INFO_BW_80) { - he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2); - he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3); - } -} - -static void -mt7915_mac_decode_he_radiotap(struct sk_buff *skb, - struct mt76_rx_status *status, - __le32 *rxv, u32 phy) -{ - static const struct ieee80211_radiotap_he known = { - .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | - HE_BITS(DATA1_DATA_DCM_KNOWN) | - HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN) | - HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN), - .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN) | - HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN), - }; - struct ieee80211_radiotap_he *he = NULL; - u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1; - - he = skb_push(skb, sizeof(known)); - memcpy(he, &known, sizeof(known)); - - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); - he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | - le16_encode_bits(ltf_size, - IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); - if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) - he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); - - switch (phy) { - case MT_PHY_TYPE_HE_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BEAM_CHANGE_KNOWN); - - he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | - HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - break; - case MT_PHY_TYPE_HE_EXT_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - break; - case MT_PHY_TYPE_HE_MU: - he->data1 |= HE_BITS(DATA1_FORMAT_MU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); - - mt7915_mac_decode_he_radiotap_ru(status, he, rxv); - break; - case MT_PHY_TYPE_HE_TB: - he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | - HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - - he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]); - - mt7915_mac_decode_he_radiotap_ru(status, he, rxv); - break; - default: - break; - } -} - static int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) { @@ -391,10 +221,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) struct mt76_phy *mphy = &dev->mt76.phy; struct mt7915_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; - struct ieee80211_hdr *hdr; __le32 *rxd = (__le32 *)skb->data; __le32 *rxv = NULL; - u32 mode = 0; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); @@ -403,21 +231,24 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; bool unicast, insert_ccmp_hdr = false; u8 remove_pad, amsdu_info; + u8 mode = 0, qos_ctl = 0; + struct mt7915_sta *msta = NULL; + u32 csum_status = *(u32 *)skb->cb; bool hdr_trans; + u16 hdr_gap; u16 seq_ctrl = 0; - u8 qos_ctl = 0; __le16 fc = 0; - int i, idx; + int idx; memset(status, 0, sizeof(*status)); - if (rxd1 & MT_RXD1_NORMAL_BAND_IDX) { - mphy = dev->mt76.phy2; + if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->band_idx) { + mphy = dev->mt76.phys[MT_BAND1]; if (!mphy) return -EINVAL; phy = mphy->priv; - status->ext_phy = true; + status->phy_idx = 1; } if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) @@ -426,14 +257,19 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) return -EINVAL; + hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; + if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) + return -EINVAL; + + /* ICV error or CCMP/BIP/WPI MIC error */ + if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) + status->flag |= RX_FLAG_ONLY_MONITOR; + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); - hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - struct mt7915_sta *msta; - msta = container_of(status->wcid, struct mt7915_sta, wcid); spin_lock_bh(&dev->sta_poll_lock); if (list_empty(&msta->poll_list)) @@ -445,13 +281,16 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->band = mphy->chandef.chan->band; if (status->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (status->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; if (!sband->channels) return -EINVAL; - if ((rxd0 & csum_mask) == csum_mask) + if ((rxd0 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) @@ -541,7 +380,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) /* RXD Group 3 - P-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { - u32 v0, v1, v2; + u32 v0, v1; + int ret; rxv = rxd; rxd += 2; @@ -550,7 +390,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) v0 = le32_to_cpu(rxv[0]); v1 = le32_to_cpu(rxv[1]); - v2 = le32_to_cpu(rxv[2]); if (v0 & MT_PRXV_HT_AD_CODE) status->enc_flags |= RX_ENC_FLAG_LDPC; @@ -560,121 +399,81 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1); status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1); - status->signal = status->chain_signal[0]; - - for (i = 1; i < hweight8(mphy->antenna_mask); i++) { - if (!(status->chains & BIT(i))) - continue; - - status->signal = max(status->signal, - status->chain_signal[i]); - } /* RXD Group 5 - C-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { - u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); - u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); - bool cck = false; - rxd += 18; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; + } - idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); - mode = FIELD_GET(MT_CRXV_TX_MODE, v2); - - switch (mode) { - case MT_PHY_TYPE_CCK: - cck = true; - fallthrough; - case MT_PHY_TYPE_OFDM: - i = mt76_get_rate(&dev->mt76, sband, i, cck); - break; - case MT_PHY_TYPE_HT_GF: - case MT_PHY_TYPE_HT: - status->encoding = RX_ENC_HT; - if (i > 31) - return -EINVAL; - break; - case MT_PHY_TYPE_VHT: - status->nss = - FIELD_GET(MT_PRXV_NSTS, v0) + 1; - status->encoding = RX_ENC_VHT; - if (i > 9) - return -EINVAL; - break; - case MT_PHY_TYPE_HE_MU: - status->flag |= RX_FLAG_RADIOTAP_HE_MU; - fallthrough; - case MT_PHY_TYPE_HE_SU: - case MT_PHY_TYPE_HE_EXT_SU: - case MT_PHY_TYPE_HE_TB: - status->nss = - FIELD_GET(MT_PRXV_NSTS, v0) + 1; - status->encoding = RX_ENC_HE; - status->flag |= RX_FLAG_RADIOTAP_HE; - i &= GENMASK(3, 0); - - if (gi <= NL80211_RATE_INFO_HE_GI_3_2) - status->he_gi = gi; - - status->he_dcm = !!(idx & MT_PRXV_TX_DCM); - break; - default: - return -EINVAL; - } - status->rate_idx = i; - - switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) { - case IEEE80211_STA_RX_BW_20: - break; - case IEEE80211_STA_RX_BW_40: - if (mode & MT_PHY_TYPE_HE_EXT_SU && - (idx & MT_PRXV_TX_ER_SU_106T)) { - status->bw = RATE_INFO_BW_HE_RU; - status->he_ru = - NL80211_RATE_INFO_HE_RU_ALLOC_106; - } else { - status->bw = RATE_INFO_BW_40; - } - break; - case IEEE80211_STA_RX_BW_80: - status->bw = RATE_INFO_BW_80; - break; - case IEEE80211_STA_RX_BW_160: - status->bw = RATE_INFO_BW_160; - break; - default: - return -EINVAL; - } - - status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - if (mode < MT_PHY_TYPE_HE_SU && gi) - status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) { + ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, + sband, rxv, &mode); + if (ret < 0) + return ret; } } - skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); - amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); status->amsdu = !!amsdu_info; if (status->amsdu) { status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; - if (!hdr_trans) { - memmove(skb->data + 2, skb->data, - ieee80211_get_hdrlen_from_skb(skb)); - skb_pull(skb, 2); - } } - if (insert_ccmp_hdr && !hdr_trans) { - u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; + if (hdr_trans && ieee80211_has_morefrags(fc)) { + struct ieee80211_vif *vif; + int err; + + if (!msta || !msta->vif) + return -EINVAL; - mt76_insert_ccmp_hdr(skb, key_id); + vif = container_of((void *)msta->vif, struct ieee80211_vif, + drv_priv); + err = mt76_connac2_reverse_frag0_hdr_trans(vif, skb, hdr_gap); + if (err) + return err; + + hdr_trans = false; + } else { + int pad_start = 0; + + skb_pull(skb, hdr_gap); + if (!hdr_trans && status->amsdu) { + pad_start = ieee80211_get_hdrlen_from_skb(skb); + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { + /* + * When header translation failure is indicated, + * the hardware will insert an extra 2-byte field + * containing the data length after the protocol + * type field. This happens either when the LLC-SNAP + * pattern did not match, or if a VLAN header was + * detected. + */ + pad_start = 12; + if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) + pad_start += 4; + else + pad_start = 0; + } + + if (pad_start) { + memmove(skb->data + 2, skb->data, pad_start); + skb_pull(skb, 2); + } } if (!hdr_trans) { + struct ieee80211_hdr *hdr; + + if (insert_ccmp_hdr) { + u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + + mt76_insert_ccmp_hdr(skb, key_id); + } + hdr = mt76_skb_get_hdr(skb); fc = hdr->frame_control; if (ieee80211_is_data_qos(fc)) { @@ -682,16 +481,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) qos_ctl = *ieee80211_get_qos_ctl(hdr); } } else { - status->flag &= ~(RX_FLAG_RADIOTAP_HE | - RX_FLAG_RADIOTAP_HE_MU); status->flag |= RX_FLAG_8023; } - if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) { - mt7915_mac_decode_he_radiotap(skb, status, rxv, mode); - if (status->flag & RX_FLAG_RADIOTAP_HE_MU) - mt7915_mac_decode_he_mu_radiotap(skb, status, rxv); - } + if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) + mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode); if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; @@ -713,14 +507,17 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) __le32 *rxv_hdr = rxd + 2; __le32 *rxv = rxd + 4; u32 rcpi, ib_rssi, wb_rssi, v20, v21; - bool ext_phy; + u8 band_idx; s32 foe; u8 snr; int i; - ext_phy = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1])); - if (ext_phy) + band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX); + if (band_idx && !phy->band_idx) { phy = mt7915_ext_phy(dev); + if (!phy) + goto out; + } rcpi = le32_to_cpu(rxv[6]); ib_rssi = le32_to_cpu(rxv[7]); @@ -745,8 +542,8 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) phy->test.last_freq_offset = foe; phy->test.last_snr = snr; +out: #endif - dev_kfree_skb(skb); } @@ -865,254 +662,19 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, #endif } -static void -mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid) -{ - - u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - u8 fc_type, fc_stype; - bool wmm = false; - u32 val; - - if (wcid->sta) { - struct ieee80211_sta *sta; - - sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); - wmm = sta->wme; - } - - val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | - FIELD_PREP(MT_TXD1_TID, tid); - - if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) - val |= MT_TXD1_ETH_802_3; - - txwi[1] |= cpu_to_le32(val); - - fc_type = IEEE80211_FTYPE_DATA >> 2; - fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; - - val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | - FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); - - txwi[2] |= cpu_to_le32(val); - - val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | - FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); - txwi[7] |= cpu_to_le32(val); -} - -static void -mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct ieee80211_key_conf *key, - bool *mcast) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - __le16 fc = hdr->frame_control; - u8 fc_type, fc_stype; - u32 val; - - *mcast = is_multicast_ether_addr(hdr->addr1); - - if (ieee80211_is_action(fc) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { - u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - - txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); - tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; - } else if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; - u16 control = le16_to_cpu(bar->control); - - tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); - } - - val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | - FIELD_PREP(MT_TXD1_HDR_INFO, - ieee80211_get_hdrlen_from_skb(skb) / 2) | - FIELD_PREP(MT_TXD1_TID, tid); - txwi[1] |= cpu_to_le32(val); - - fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; - fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; - - val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | - FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | - FIELD_PREP(MT_TXD2_MULTICAST, *mcast); - - if (key && *mcast && ieee80211_is_robust_mgmt_frame(skb) && - key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { - val |= MT_TXD2_BIP; - txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); - } - - if (!ieee80211_is_data(fc) || *mcast || - info->flags & IEEE80211_TX_CTL_USE_MINRATE) - val |= MT_TXD2_FIX_RATE; - - txwi[2] |= cpu_to_le32(val); - - if (ieee80211_is_beacon(fc)) { - txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); - txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); - } - - if (info->flags & IEEE80211_TX_CTL_INJECTED) { - u16 seqno = le16_to_cpu(hdr->seq_ctrl); - - if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar; - - bar = (struct ieee80211_bar *)skb->data; - seqno = le16_to_cpu(bar->start_seq_num); - } - - val = MT_TXD3_SN_VALID | - FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); - txwi[3] |= cpu_to_le32(val); - } - - val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | - FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); - txwi[7] |= cpu_to_le32(val); -} - -static u16 -mt7915_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, - bool beacon, bool mcast) -{ - u8 mode = 0, band = mphy->chandef.chan->band; - int rateidx = 0, mcast_rate; - - if (beacon) { - struct cfg80211_bitrate_mask *mask; - - mask = &vif->bss_conf.beacon_tx_rate; - if (hweight16(mask->control[band].he_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].he_mcs[0]) - 1; - mode = MT_PHY_TYPE_HE_SU; - goto out; - } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].vht_mcs[0]) - 1; - mode = MT_PHY_TYPE_VHT; - goto out; - } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].ht_mcs[0]) - 1; - mode = MT_PHY_TYPE_HT; - goto out; - } else if (hweight32(mask->control[band].legacy) == 1) { - rateidx = ffs(mask->control[band].legacy) - 1; - goto legacy; - } - } - - mcast_rate = vif->bss_conf.mcast_rate[band]; - if (mcast && mcast_rate > 0) - rateidx = mcast_rate - 1; - else - rateidx = ffs(vif->bss_conf.basic_rates) - 1; - -legacy: - rateidx = mt76_calculate_default_rate(mphy, rateidx); - mode = rateidx >> 8; - rateidx &= GENMASK(7, 0); - -out: - return FIELD_PREP(MT_TX_RATE_IDX, rateidx) | - FIELD_PREP(MT_TX_RATE_MODE, mode); -} - -void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, +void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, bool beacon) + struct ieee80211_key_conf *key, + enum mt76_txq_id qid, u32 changed) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; - struct mt76_phy *mphy = &dev->mphy; - bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; - u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; - bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - bool mcast = false; - u16 tx_count = 15; - u32 val; - - if (vif) { - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - - omac_idx = mvif->omac_idx; - wmm_idx = mvif->wmm_idx; - } - - if (ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; + struct mt76_phy *mphy = &dev->phy; - if (beacon) { - p_fmt = MT_TX_TYPE_FW; - q_idx = MT_LMAC_BCN0; - } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { - p_fmt = MT_TX_TYPE_CT; - q_idx = MT_LMAC_ALTX0; - } else { - p_fmt = MT_TX_TYPE_CT; - q_idx = wmm_idx * MT7915_MAX_WMM_SETS + - mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb)); - } - - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | - FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | - FIELD_PREP(MT_TXD0_Q_IDX, q_idx); - txwi[0] = cpu_to_le32(val); - - val = MT_TXD1_LONG_FORMAT | MT_TXD1_VTA | - FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | - FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); - - if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) - val |= MT_TXD1_TGID; - - txwi[1] = cpu_to_le32(val); - - txwi[2] = 0; - - val = MT_TXD3_SW_POWER_MGMT | - FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); - if (key) - val |= MT_TXD3_PROTECT_FRAME; - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - val |= MT_TXD3_NO_ACK; - - txwi[3] = cpu_to_le32(val); - txwi[4] = 0; - - val = FIELD_PREP(MT_TXD5_PID, pid); - if (pid >= MT_PACKET_ID_FIRST) - val |= MT_TXD5_TX_STATUS_HOST; - txwi[5] = cpu_to_le32(val); - - txwi[6] = 0; - txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; - - if (is_8023) - mt7915_mac_write_txwi_8023(dev, txwi, skb, wcid); - else - mt7915_mac_write_txwi_80211(dev, txwi, skb, key, &mcast); + if (phy_idx && dev->phys[MT_BAND1]) + mphy = dev->phys[MT_BAND1]; - if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { - u16 rate = mt7915_mac_tx_rate_val(mphy, vif, beacon, mcast); - - /* hardware won't add HTC for mgmt/ctrl frame */ - txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); - - val = MT_TXD6_FIXED_BW | - FIELD_PREP(MT_TXD6_TX_RATE, rate); - txwi[6] |= cpu_to_le32(val); - txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); - } + mt76_connac2_mac_write_txwi(dev, txwi, skb, wcid, key, pid, qid, changed); if (mt76_testmode_enabled(mphy)) mt7915_mac_write_txwi_tm(mphy->priv, txwi, skb); @@ -1128,8 +690,8 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct ieee80211_vif *vif = info->control.vif; + struct mt76_connac_fw_txp *txp; struct mt76_txwi_cache *t; - struct mt7915_txp *txp; int id, i, nbuf = tx_info->nbuf - 1; u8 *txwi = (u8 *)txwi_ptr; int pid; @@ -1159,10 +721,10 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, - false); + mt7915_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, pid, key, + qid, 0); - txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE); + txp = (struct mt76_connac_fw_txp *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); @@ -1181,7 +743,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (vif) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - txp->bss_idx = mvif->idx; + txp->bss_idx = mvif->mt76.idx; } txp->token = cpu_to_le16(id); @@ -1199,6 +761,29 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } +u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) +{ + struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE; + __le32 *txwi = ptr; + u32 val; + + memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp)); + + val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3); + txwi[1] = cpu_to_le32(val); + + txp->token = cpu_to_le16(token_id); + txp->nbuf = 1; + txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp)); + + return MT_TXD_SIZE + sizeof(*txp); +} + static void mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) { @@ -1206,10 +791,10 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) u16 fc, tid; u32 val; - if (!sta || !sta->ht_cap.ht_supported) + if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) return; - tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1])); + tid = le32_get_bits(txwi[1], MT_TXD1_TID); if (tid >= 6) /* skip VO queue */ return; @@ -1225,27 +810,16 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) } static void -mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - struct mt7915_txp *txp; - int i; - - txp = mt7915_txwi_to_txp(dev, t); - for (i = 0; i < txp->nbuf; i++) - dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), - le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); -} - -static void mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, struct ieee80211_sta *sta, struct list_head *free_list) { struct mt76_dev *mdev = &dev->mt76; + struct mt7915_sta *msta; struct mt76_wcid *wcid; __le32 *txwi; u16 wcid_idx; - mt7915_txp_skb_unmap(mdev, t); + mt76_connac_txp_skb_unmap(mdev, t); if (!t->skb) goto out; @@ -1253,13 +827,24 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, if (sta) { wcid = (struct mt76_wcid *)sta->drv_priv; wcid_idx = wcid->idx; - - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7915_tx_check_aggr(sta, txwi); } else { - wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]); + + if (wcid && wcid->sta) { + msta = container_of(wcid, struct mt7915_sta, wcid); + sta = container_of((void *)msta, struct ieee80211_sta, + drv_priv); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->poll_list)) + list_add_tail(&msta->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + } } + if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7915_tx_check_aggr(sta, txwi); + __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); out: @@ -1268,17 +853,10 @@ out: } static void -mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) +mt7915_mac_tx_free_prepare(struct mt7915_dev *dev) { - struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data; struct mt76_dev *mdev = &dev->mt76; - struct mt76_phy *mphy_ext = mdev->phy2; - struct mt76_txwi_cache *txwi; - struct ieee80211_sta *sta = NULL; - LIST_HEAD(free_list); - struct sk_buff *tmp; - u8 i, count; - bool wake = false; + struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1]; /* clean DMA queues and unmap buffers first */ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); @@ -1287,15 +865,52 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); } +} - /* - * TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, - * to the time ack is received or dropped by hw (air + hw queue time). - * Should avoid accessing WTBL to get Tx airtime, and use it instead. - */ - count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl)); - for (i = 0; i < count; i++) { - u32 msdu, info = le32_to_cpu(free->info[i]); +static void +mt7915_mac_tx_free_done(struct mt7915_dev *dev, + struct list_head *free_list, bool wake) +{ + struct sk_buff *skb, *tmp; + + mt7915_mac_sta_poll(dev); + + if (wake) + mt76_set_tx_blocked(&dev->mt76, false); + + mt76_worker_schedule(&dev->mt76.tx_worker); + + list_for_each_entry_safe(skb, tmp, free_list, list) { + skb_list_del_init(skb); + napi_consume_skb(skb, 1); + } +} + +static void +mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) +{ + struct mt76_connac_tx_free *free = data; + __le32 *tx_info = (__le32 *)(data + sizeof(*free)); + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + struct ieee80211_sta *sta = NULL; + LIST_HEAD(free_list); + void *end = data + len; + bool v3, wake = false; + u16 total, count = 0; + u32 txd = le32_to_cpu(free->txd); + __le32 *cur_info; + + mt7915_mac_tx_free_prepare(dev); + + total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); + v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4); + if (WARN_ON_ONCE((void *)&tx_info[total >> v3] > end)) + return; + + for (cur_info = tx_info; count < total; cur_info++) { + u32 msdu, info = le32_to_cpu(*cur_info); + u8 i; /* * 1'b1: new wcid pair. @@ -1306,7 +921,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) struct mt76_wcid *wcid; u16 idx; - count++; idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); wcid = rcu_dereference(dev->mt76.wcid[idx]); sta = wcid_to_sta(wcid); @@ -1321,148 +935,58 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) continue; } - msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); - txwi = mt76_token_release(mdev, msdu, &wake); - if (!txwi) + if (v3 && (info & MT_TX_FREE_MPDU_HEADER)) continue; - mt7915_txwi_free(dev, txwi, sta, &free_list); - } - - mt7915_mac_sta_poll(dev); - - if (wake) - mt76_set_tx_blocked(&dev->mt76, false); - - mt76_worker_schedule(&dev->mt76.tx_worker); - - napi_consume_skb(skb, 1); + for (i = 0; i < 1 + v3; i++) { + if (v3) { + msdu = (info >> (15 * i)) & MT_TX_FREE_MSDU_ID_V3; + if (msdu == MT_TX_FREE_MSDU_ID_V3) + continue; + } else { + msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); + } + count++; + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; - list_for_each_entry_safe(skb, tmp, &free_list, list) { - skb_list_del_init(skb); - napi_consume_skb(skb, 1); + mt7915_txwi_free(dev, txwi, sta, &free_list); + } } + + mt7915_mac_tx_free_done(dev, &free_list, wake); } -static bool -mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, - __le32 *txs_data, struct mt76_sta_stats *stats) +static void +mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) { - struct ieee80211_supported_band *sband; + struct mt76_connac_tx_free *free = data; + __le16 *info = (__le16 *)(data + sizeof(*free)); struct mt76_dev *mdev = &dev->mt76; - struct mt76_phy *mphy; - struct ieee80211_tx_info *info; - struct sk_buff_head list; - struct rate_info rate = {}; - struct sk_buff *skb; - bool cck = false; - u32 txrate, txs, mode; - - mt76_tx_status_lock(mdev, &list); - skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); - if (!skb) - goto out_no_skb; - - txs = le32_to_cpu(txs_data[0]); - - info = IEEE80211_SKB_CB(skb); - if (!(txs & MT_TXS0_ACK_ERROR_MASK)) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.ampdu_len = 1; - info->status.ampdu_ack_len = !!(info->flags & - IEEE80211_TX_STAT_ACK); - - info->status.rates[0].idx = -1; - - txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); - - rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); - rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; - - if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) - stats->tx_nss[rate.nss - 1]++; - if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) - stats->tx_mcs[rate.mcs]++; - - mode = FIELD_GET(MT_TX_RATE_MODE, txrate); - switch (mode) { - case MT_PHY_TYPE_CCK: - cck = true; - fallthrough; - case MT_PHY_TYPE_OFDM: - mphy = &dev->mphy; - if (wcid->ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; - - if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) - sband = &mphy->sband_5g.sband; - else - sband = &mphy->sband_2g.sband; - - rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); - rate.legacy = sband->bitrates[rate.mcs].bitrate; - break; - case MT_PHY_TYPE_HT: - case MT_PHY_TYPE_HT_GF: - rate.mcs += (rate.nss - 1) * 8; - if (rate.mcs > 31) - goto out; + void *end = data + len; + LIST_HEAD(free_list); + bool wake = false; + u8 i, count; - rate.flags = RATE_INFO_FLAGS_MCS; - if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) - rate.flags |= RATE_INFO_FLAGS_SHORT_GI; - break; - case MT_PHY_TYPE_VHT: - if (rate.mcs > 9) - goto out; + mt7915_mac_tx_free_prepare(dev); - rate.flags = RATE_INFO_FLAGS_VHT_MCS; - break; - case MT_PHY_TYPE_HE_SU: - case MT_PHY_TYPE_HE_EXT_SU: - case MT_PHY_TYPE_HE_TB: - case MT_PHY_TYPE_HE_MU: - if (rate.mcs > 11) - goto out; + count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl)); + if (WARN_ON_ONCE((void *)&info[count] > end)) + return; - rate.he_gi = wcid->rate.he_gi; - rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); - rate.flags = RATE_INFO_FLAGS_HE_MCS; - break; - default: - goto out; - } + for (i = 0; i < count; i++) { + struct mt76_txwi_cache *txwi; + u16 msdu = le16_to_cpu(info[i]); - stats->tx_mode[mode]++; + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; - switch (FIELD_GET(MT_TXS0_BW, txs)) { - case IEEE80211_STA_RX_BW_160: - rate.bw = RATE_INFO_BW_160; - stats->tx_bw[3]++; - break; - case IEEE80211_STA_RX_BW_80: - rate.bw = RATE_INFO_BW_80; - stats->tx_bw[2]++; - break; - case IEEE80211_STA_RX_BW_40: - rate.bw = RATE_INFO_BW_40; - stats->tx_bw[1]++; - break; - default: - rate.bw = RATE_INFO_BW_20; - stats->tx_bw[0]++; - break; + mt7915_txwi_free(dev, txwi, NULL, &free_list); } - wcid->rate = rate; - -out: - mt76_tx_status_skb_done(mdev, skb, &list); - -out_no_skb: - mt76_tx_status_unlock(mdev, &list); - return !!skb; + mt7915_mac_tx_free_done(dev, &free_list, wake); } static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) @@ -1471,23 +995,18 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; - u32 txs; u8 pid; - txs = le32_to_cpu(txs_data[0]); - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) return; - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); + pid = le32_get_bits(txs_data[3], MT_TXS3_PID); - txs = le32_to_cpu(txs_data[3]); - pid = FIELD_GET(MT_TXS3_PID, txs); - - if (pid < MT_PACKET_ID_FIRST) + if (pid < MT_PACKET_ID_WED) return; - if (wcidx >= MT7915_WTBL_SIZE) + if (wcidx >= mt7915_wtbl_size(dev)) return; rcu_read_lock(); @@ -1498,7 +1017,10 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) msta = container_of(wcid, struct mt7915_sta, wcid); - mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats); + if (pid == MT_PACKET_ID_WED) + mt76_connac2_mac_fill_txs(&dev->mt76, wcid, txs_data); + else + mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); if (!wcid->sta) goto out; @@ -1512,6 +1034,34 @@ out: rcu_read_unlock(); } +bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + __le32 *rxd = (__le32 *)data; + __le32 *end = (__le32 *)&rxd[len / 4]; + enum rx_pkt_type type; + + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + mt7915_mac_tx_free(dev, data, len); + return false; + case PKT_TYPE_TXRX_NOTIFY_V0: + mt7915_mac_tx_free_v0(dev, data, len); + return false; + case PKT_TYPE_TXS: + for (rxd += 2; rxd + 8 <= end; rxd += 8) + mt7915_mac_add_txs(dev, rxd); + return false; + case PKT_TYPE_RX_FW_MONITOR: + mt7915_debugfs_rx_fw_monitor(dev, data, len); + return false; + default: + return true; + } +} + void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb) { @@ -1520,11 +1070,16 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); switch (type) { case PKT_TYPE_TXRX_NOTIFY: - mt7915_mac_tx_free(dev, skb); + mt7915_mac_tx_free(dev, skb->data, skb->len); + napi_consume_skb(skb, 1); + break; + case PKT_TYPE_TXRX_NOTIFY_V0: + mt7915_mac_tx_free_v0(dev, skb->data, skb->len); + napi_consume_skb(skb, 1); break; case PKT_TYPE_RX_EVENT: mt7915_mcu_rx_event(dev, skb); @@ -1534,7 +1089,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, break; case PKT_TYPE_TXS: for (rxd += 2; rxd + 8 <= end; rxd += 8) - mt7915_mac_add_txs(dev, rxd); + mt7915_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; + case PKT_TYPE_RX_FW_MONITOR: + mt7915_debugfs_rx_fw_monitor(dev, skb->data, skb->len); dev_kfree_skb(skb); break; case PKT_TYPE_NORMAL: @@ -1549,32 +1108,10 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } -void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - if (!e->txwi) { - dev_kfree_skb_any(e->skb); - return; - } - - /* error path */ - if (e->skb == DMA_DUMMY_DATA) { - struct mt76_txwi_cache *t; - struct mt7915_txp *txp; - - txp = mt7915_txwi_to_txp(mdev, e->txwi); - t = mt76_token_put(mdev, le16_to_cpu(txp->token)); - e->skb = t ? t->skb : NULL; - } - - if (e->skb) - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; - u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy); + u32 reg = MT_WF_PHY_RX_CTRL1(phy->band_idx); mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); mt76_set(dev, reg, BIT(11) | BIT(9)); @@ -1583,25 +1120,22 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) void mt7915_mac_reset_counters(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; int i; for (i = 0; i < 4; i++) { - mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); + mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i)); + mt76_rr(dev, MT_TX_AGG_CNT2(phy->band_idx, i)); } - if (ext_phy) { - dev->mt76.phy2->survey_time = ktime_get_boottime(); + i = 0; + phy->mt76->survey_time = ktime_get_boottime(); + if (phy->band_idx) i = ARRAY_SIZE(dev->mt76.aggr_stats) / 2; - } else { - dev->mt76.phy.survey_time = ktime_get_boottime(); - i = 0; - } + memset(&dev->mt76.aggr_stats[i], 0, sizeof(dev->mt76.aggr_stats) / 2); /* reset airtime counters */ - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(ext_phy), + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(phy->band_idx), MT_WF_RMAC_MIB_RXTIME_CLR); mt7915_mcu_get_chan_mib_info(phy, true); @@ -1611,29 +1145,23 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) { s16 coverage_class = phy->coverage_class; struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; + struct mt7915_phy *ext_phy = mt7915_ext_phy(dev); u32 val, reg_offset; u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); int offset; - bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ; + bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; - if (ext_phy) { + if (ext_phy) coverage_class = max_t(s16, dev->phy.coverage_class, - coverage_class); - } else { - struct mt7915_phy *phy_ext = mt7915_ext_phy(dev); + ext_phy->coverage_class); - if (phy_ext) - coverage_class = max_t(s16, phy_ext->coverage_class, - coverage_class); - } - mt76_set(dev, MT_ARB_SCR(ext_phy), + mt76_set(dev, MT_ARB_SCR(phy->band_idx), MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); udelay(1); @@ -1641,35 +1169,40 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); - mt76_wr(dev, MT_TMAC_CDTR(ext_phy), cck + reg_offset); - mt76_wr(dev, MT_TMAC_ODTR(ext_phy), ofdm + reg_offset); - mt76_wr(dev, MT_TMAC_ICR0(ext_phy), - FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) | + mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset); + mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx), + FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | FIELD_PREP(MT_IFS_RIFS, 2) | FIELD_PREP(MT_IFS_SIFS, 10) | FIELD_PREP(MT_IFS_SLOT, phy->slottime)); - mt76_wr(dev, MT_TMAC_ICR1(ext_phy), + mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx), FIELD_PREP(MT_IFS_EIFS_CCK, 314)); - if (phy->slottime < 20 || is_5ghz) + if (phy->slottime < 20 || a_band) val = MT7915_CFEND_RATE_DEFAULT; else val = MT7915_CFEND_RATE_11B; - mt76_rmw_field(dev, MT_AGG_ACR0(ext_phy), MT_AGG_ACR_CFEND_RATE, val); - mt76_clear(dev, MT_ARB_SCR(ext_phy), + mt76_rmw_field(dev, MT_AGG_ACR0(phy->band_idx), MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR(phy->band_idx), MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); } void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy) { - mt76_set(dev, MT_WF_PHY_RXTD12(ext_phy), + u32 reg; + + reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RXTD12(ext_phy) : + MT_WF_PHY_RXTD12_MT7916(ext_phy); + mt76_set(dev, reg, MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | MT_WF_PHY_RXTD12_IRPI_SW_CLR); - mt76_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), - FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); + reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RX_CTRL1(ext_phy) : + MT_WF_PHY_RX_CTRL1_MT7916(ext_phy); + mt76_set(dev, reg, FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); } static u8 @@ -1681,7 +1214,9 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) int nss, i; for (nss = 0; nss < hweight8(phy->mt76->chainmask); nss++) { - u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support)); + u32 reg = is_mt7915(&dev->mt76) ? + MT_WF_IRPI_NSS(0, nss + (idx << dev->dbdc_support)) : + MT_WF_IRPI_NSS_MT7916(idx, nss); for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { val = mt76_rr(dev, reg); @@ -1700,12 +1235,11 @@ void mt7915_update_channel(struct mt76_phy *mphy) { struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv; struct mt76_channel_state *state = mphy->chan_state; - bool ext_phy = phy != &phy->dev->phy; int nf; mt7915_mcu_get_chan_mib_info(phy, false); - nf = mt7915_phy_get_nf(phy, ext_phy); + nf = mt7915_phy_get_nf(phy, phy->band_idx); if (!phy->noise) phy->noise = nf << 4; else if (nf) @@ -1736,7 +1270,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: - mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); + mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, + BSS_CHANGED_BEACON_ENABLED); break; default: break; @@ -1746,36 +1281,44 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) static void mt7915_update_beacons(struct mt7915_dev *dev) { + struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; + ieee80211_iterate_active_interfaces(dev->mt76.hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7915_update_vif_beacon, dev->mt76.hw); - if (!dev->mt76.phy2) + if (!mphy_ext) return; - ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + ieee80211_iterate_active_interfaces(mphy_ext->hw, IEEE80211_IFACE_ITER_RESUME_ALL, - mt7915_update_vif_beacon, dev->mt76.phy2->hw); + mt7915_update_vif_beacon, mphy_ext->hw); } static void mt7915_dma_reset(struct mt7915_dev *dev) { - struct mt76_phy *mphy_ext = dev->mt76.phy2; - u32 hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE; + struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; + u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); int i; mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_clear(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + if (is_mt7915(&dev->mt76)) + mt76_clear(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN); if (dev->hif2) { mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - (MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN)); - mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, - (MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN)); + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + if (is_mt7915(&dev->mt76)) + mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN); } usleep_range(1000, 2000); @@ -1799,19 +1342,23 @@ mt7915_dma_reset(struct mt7915_dev *dev) mt76_set(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN | - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - (MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN)); - mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, - (MT_WFDMA1_GLO_CFG_TX_DMA_EN | + if (is_mt7915(&dev->mt76)) + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN | MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO)); + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + if (dev->hif2) { + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + if (is_mt7915(&dev->mt76)) + mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); } } @@ -1835,9 +1382,10 @@ void mt7915_mac_reset_work(struct work_struct *work) struct mt7915_phy *phy2; struct mt76_phy *ext_phy; struct mt7915_dev *dev; + int i; dev = container_of(work, struct mt7915_dev, reset_work); - ext_phy = dev->mt76.phy2; + ext_phy = dev->mt76.phys[MT_BAND1]; phy2 = ext_phy ? ext_phy->priv : NULL; if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) @@ -1856,9 +1404,8 @@ void mt7915_mac_reset_work(struct work_struct *work) cancel_delayed_work_sync(&phy2->mt76->mac_work); } mt76_worker_disable(&dev->mt76.tx_worker); - napi_disable(&dev->mt76.napi[0]); - napi_disable(&dev->mt76.napi[1]); - napi_disable(&dev->mt76.napi[2]); + mt76_for_each_q_rx(&dev->mt76, i) + napi_disable(&dev->mt76.napi[i]); napi_disable(&dev->mt76.tx_napi); mutex_lock(&dev->mt76.mutex); @@ -1881,14 +1428,10 @@ void mt7915_mac_reset_work(struct work_struct *work) clear_bit(MT76_RESET, &phy2->mt76->state); local_bh_disable(); - napi_enable(&dev->mt76.napi[0]); - napi_schedule(&dev->mt76.napi[0]); - - napi_enable(&dev->mt76.napi[1]); - napi_schedule(&dev->mt76.napi[1]); - - napi_enable(&dev->mt76.napi[2]); - napi_schedule(&dev->mt76.napi[2]); + mt76_for_each_q_rx(&dev->mt76, i) { + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); + } local_bh_enable(); tasklet_schedule(&dev->irq_tasklet); @@ -1898,8 +1441,10 @@ void mt7915_mac_reset_work(struct work_struct *work) mt76_worker_enable(&dev->mt76.tx_worker); + local_bh_disable(); napi_enable(&dev->mt76.tx_napi); napi_schedule(&dev->mt76.tx_napi); + local_bh_enable(); ieee80211_wake_queues(mt76_hw(dev)); if (ext_phy) @@ -1921,106 +1466,131 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; struct mib_stats *mib = &phy->mib; - bool ext_phy = phy != &dev->phy; int i, aggr0, aggr1, cnt; + u32 val; - mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); + cnt = mt76_rr(dev, MT_MIB_SDR3(phy->band_idx)); + mib->fcs_err_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) : + FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR4(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR4(phy->band_idx)); mib->rx_fifo_full_cnt += FIELD_GET(MT_MIB_SDR4_RX_FIFO_FULL_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR5(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR5(phy->band_idx)); mib->rx_mpdu_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR6(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR6(phy->band_idx)); mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR7(ext_phy)); - mib->rx_vector_mismatch_cnt += FIELD_GET(MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR7(phy->band_idx)); + mib->rx_vector_mismatch_cnt += + FIELD_GET(MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR8(phy->band_idx)); + mib->rx_delimiter_fail_cnt += + FIELD_GET(MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR8(ext_phy)); - mib->rx_delimiter_fail_cnt += FIELD_GET(MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR10(phy->band_idx)); + mib->rx_mrdy_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR10_MRDY_COUNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR10_MRDY_COUNT_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR11(ext_phy)); - mib->rx_len_mismatch_cnt += FIELD_GET(MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR11(phy->band_idx)); + mib->rx_len_mismatch_cnt += + FIELD_GET(MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR12(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR12(phy->band_idx)); mib->tx_ampdu_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR13(ext_phy)); - mib->tx_stop_q_empty_cnt += FIELD_GET(MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR13(phy->band_idx)); + mib->tx_stop_q_empty_cnt += + FIELD_GET(MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR14(phy->band_idx)); + mib->tx_mpdu_attempts_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK_MT7916, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR15(phy->band_idx)); + mib->tx_mpdu_success_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR16(phy->band_idx)); + mib->primary_cca_busy_time += + FIELD_GET(MT_MIB_SDR16_PRIMARY_CCA_BUSY_TIME_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR14(ext_phy)); - mib->tx_mpdu_attempts_cnt += FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR17(phy->band_idx)); + mib->secondary_cca_busy_time += + FIELD_GET(MT_MIB_SDR17_SECONDARY_CCA_BUSY_TIME_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR15(ext_phy)); - mib->tx_mpdu_success_cnt += FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR18(phy->band_idx)); + mib->primary_energy_detect_time += + FIELD_GET(MT_MIB_SDR18_PRIMARY_ENERGY_DETECT_TIME_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR22(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR19(phy->band_idx)); + mib->cck_mdrdy_time += FIELD_GET(MT_MIB_SDR19_CCK_MDRDY_TIME_MASK, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR20(phy->band_idx)); + mib->ofdm_mdrdy_time += + FIELD_GET(MT_MIB_SDR20_OFDM_VHT_MDRDY_TIME_MASK, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR21(phy->band_idx)); + mib->green_mdrdy_time += + FIELD_GET(MT_MIB_SDR21_GREEN_MDRDY_TIME_MASK, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR22(phy->band_idx)); mib->rx_ampdu_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR23(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR23(phy->band_idx)); mib->rx_ampdu_bytes_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR24(ext_phy)); - mib->rx_ampdu_valid_subframe_cnt += FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR24(phy->band_idx)); + mib->rx_ampdu_valid_subframe_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR25(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR25(phy->band_idx)); mib->rx_ampdu_valid_subframe_bytes_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR27(ext_phy)); - mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR27(phy->band_idx)); + mib->tx_rwp_fail_cnt += + FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR28(ext_phy)); - mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR28(phy->band_idx)); + mib->tx_rwp_need_cnt += + FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR29(ext_phy)); - mib->rx_pfdrop_cnt += FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDR29(phy->band_idx)); + mib->rx_pfdrop_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR30(ext_phy)); - mib->rx_vec_queue_overflow_drop_cnt += - FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK, cnt); + cnt = mt76_rr(dev, MT_MIB_SDRVEC(phy->band_idx)); + mib->rx_vec_queue_overflow_drop_cnt += is_mt7915(&dev->mt76) ? + FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK, cnt) : + FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK_MT7916, cnt); - cnt = mt76_rr(dev, MT_MIB_SDR31(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDR31(phy->band_idx)); mib->rx_ba_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_SDR32(ext_phy)); - mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt); - - cnt = mt76_rr(dev, MT_MIB_SDR33(ext_phy)); - mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT_MASK, cnt); - - cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_SDRMUBF(phy->band_idx)); mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt); - cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_DR8(phy->band_idx)); mib->tx_mu_mpdu_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_DR9(phy->band_idx)); mib->tx_mu_acked_mpdu_cnt += cnt; - cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy)); + cnt = mt76_rr(dev, MT_MIB_DR11(phy->band_idx)); mib->tx_su_acked_mpdu_cnt += cnt; - cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy)); - mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt); - mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt); - - cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy)); - mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt); - mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt); - mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt); - mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt); - - cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy)); - mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt); - mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt); - mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt); - - cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy)); - mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt); - mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt); + cnt = mt76_rr(dev, MT_ETBF_PAR_RPT0(phy->band_idx)); + mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_PAR_RPT0_FB_BW, cnt); + mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NC, cnt); + mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NR, cnt); for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); @@ -2028,30 +1598,127 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) mib->tx_amsdu_cnt += cnt; } - aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; - for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { - u32 val; + aggr0 = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + if (is_mt7915(&dev->mt76)) { + for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { + val = mt76_rr(dev, MT_MIB_MB_SDR1(phy->band_idx, (i << 4))); + mib->ba_miss_cnt += + FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + mib->ack_fail_cnt += + FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); + + val = mt76_rr(dev, MT_MIB_MB_SDR0(phy->band_idx, (i << 4))); + mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt += + FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); + + val = mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i)); + dev->mt76.aggr_stats[aggr0++] += val & 0xffff; + dev->mt76.aggr_stats[aggr0++] += val >> 16; + + val = mt76_rr(dev, MT_TX_AGG_CNT2(phy->band_idx, i)); + dev->mt76.aggr_stats[aggr1++] += val & 0xffff; + dev->mt76.aggr_stats[aggr1++] += val >> 16; + } + + cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx)); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx)); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT, cnt); - val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); - mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - mib->ack_fail_cnt += - FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); + cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx)); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt); - val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); - mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt += - FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); + cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx)); + mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt); + mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt); - val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - dev->mt76.aggr_stats[aggr0++] += val & 0xffff; - dev->mt76.aggr_stats[aggr0++] += val >> 16; + cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx)); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt); + } else { + for (i = 0; i < 2; i++) { + /* rts count */ + val = mt76_rr(dev, MT_MIB_MB_SDR0(phy->band_idx, (i << 2))); + mib->rts_cnt += FIELD_GET(GENMASK(15, 0), val); + mib->rts_cnt += FIELD_GET(GENMASK(31, 16), val); + + /* rts retry count */ + val = mt76_rr(dev, MT_MIB_MB_SDR1(phy->band_idx, (i << 2))); + mib->rts_retries_cnt += FIELD_GET(GENMASK(15, 0), val); + mib->rts_retries_cnt += FIELD_GET(GENMASK(31, 16), val); + + /* ba miss count */ + val = mt76_rr(dev, MT_MIB_MB_SDR2(phy->band_idx, (i << 2))); + mib->ba_miss_cnt += FIELD_GET(GENMASK(15, 0), val); + mib->ba_miss_cnt += FIELD_GET(GENMASK(31, 16), val); + + /* ack fail count */ + val = mt76_rr(dev, MT_MIB_MB_BFTF(phy->band_idx, (i << 2))); + mib->ack_fail_cnt += FIELD_GET(GENMASK(15, 0), val); + mib->ack_fail_cnt += FIELD_GET(GENMASK(31, 16), val); + } + + for (i = 0; i < 8; i++) { + val = mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i)); + dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val); + dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val); + } + + cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx)); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR7(phy->band_idx)); + mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_MIB_BFCR7_BFEE_TX_FB_CPL, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR2(phy->band_idx)); + mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_MIB_BFCR2_BFEE_TX_FB_TRIG, cnt); - val = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); - dev->mt76.aggr_stats[aggr1++] += val & 0xffff; - dev->mt76.aggr_stats[aggr1++] += val >> 16; + cnt = mt76_rr(dev, MT_MIB_BFCR0(phy->band_idx)); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); + + cnt = mt76_rr(dev, MT_MIB_BFCR1(phy->band_idx)); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); } } +static void mt7915_mac_severe_check(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 trb; + + if (!phy->omac_mask) + return; + + /* In rare cases, TRB pointers might be out of sync leads to RMAC + * stopping Rx, so check status periodically to see if TRB hardware + * requires minimal recovery. + */ + trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->band_idx)); + + if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) != + FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) && + (FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) != + FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) && + trb == phy->trb_ts) + mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT, + ext_phy); + + phy->trb_ts = trb; +} + void mt7915_mac_sta_rc_work(struct work_struct *work) { struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); @@ -2104,6 +1771,7 @@ void mt7915_mac_work(struct work_struct *work) mphy->mac_work_count = 0; mt7915_mac_update_stats(phy); + mt7915_mac_severe_check(phy); } mutex_unlock(&mphy->dev->mutex); @@ -2119,39 +1787,59 @@ static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy) struct mt7915_dev *dev = phy->dev; if (phy->rdd_state & BIT(0)) - mt7915_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0, + MT_RX_SEL0, 0); if (phy->rdd_state & BIT(1)) - mt7915_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1, + MT_RX_SEL0, 0); } static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) { - int err; + int err, region; - err = mt7915_mcu_rdd_cmd(dev, RDD_START, chain, MT_RX_SEL0, 0); + switch (dev->mt76.region) { + case NL80211_DFS_ETSI: + region = 0; + break; + case NL80211_DFS_JP: + region = 2; + break; + case NL80211_DFS_FCC: + default: + region = 1; + break; + } + + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain, + MT_RX_SEL0, region); if (err < 0) return err; - return mt7915_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, MT_RX_SEL0, 1); + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain, + MT_RX_SEL0, 1); } static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy) { struct cfg80211_chan_def *chandef = &phy->mt76->chandef; struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; int err; /* start CAC */ - err = mt7915_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, phy->band_idx, + MT_RX_SEL0, 0); if (err < 0) return err; - err = mt7915_dfs_start_rdd(dev, ext_phy); + err = mt7915_dfs_start_rdd(dev, phy->band_idx); if (err < 0) return err; - phy->rdd_state |= BIT(ext_phy); + phy->rdd_state |= BIT(phy->band_idx); + + if (!is_mt7915(&dev->mt76)) + return 0; if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) { @@ -2201,48 +1889,56 @@ mt7915_dfs_init_radar_specs(struct mt7915_phy *phy) int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) { - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; + enum mt76_dfs_state dfs_state, prev_state; int err; - if (dev->mt76.region == NL80211_DFS_UNSET) { - phy->dfs_state = -1; - if (phy->rdd_state) - goto stop; - - return 0; - } + prev_state = phy->mt76->dfs_state; + dfs_state = mt76_phy_dfs_state(phy->mt76); - if (test_bit(MT76_SCANNING, &phy->mt76->state)) + if (prev_state == dfs_state) return 0; - if (phy->dfs_state == chandef->chan->dfs_state) - return 0; + if (prev_state == MT_DFS_STATE_UNKNOWN) + mt7915_dfs_stop_radar_detector(phy); - err = mt7915_dfs_init_radar_specs(phy); - if (err < 0) { - phy->dfs_state = -1; + if (dfs_state == MT_DFS_STATE_DISABLED) goto stop; - } - phy->dfs_state = chandef->chan->dfs_state; + if (prev_state <= MT_DFS_STATE_DISABLED) { + err = mt7915_dfs_init_radar_specs(phy); + if (err < 0) + return err; - if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { - if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) - return mt7915_dfs_start_radar_detector(phy); + err = mt7915_dfs_start_radar_detector(phy); + if (err < 0) + return err; + + phy->mt76->dfs_state = MT_DFS_STATE_CAC; + } - return mt7915_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, - MT_RX_SEL0, 0); + if (dfs_state == MT_DFS_STATE_CAC) + return 0; + + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, + phy->band_idx, MT_RX_SEL0, 0); + if (err < 0) { + phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; + return err; } + phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; + return 0; + stop: - err = mt7915_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, - MT_RX_SEL0, 0); + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, + phy->band_idx, MT_RX_SEL0, 0); if (err < 0) return err; mt7915_dfs_stop_radar_detector(phy); + phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; + return 0; } @@ -2320,6 +2016,34 @@ static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt) return 0; } +static bool +mt7915_mac_twt_param_equal(struct mt7915_sta *msta, + struct ieee80211_twt_params *twt_agrt) +{ + u16 type = le16_to_cpu(twt_agrt->req_type); + u8 exp; + int i; + + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); + for (i = 0; i < MT7915_MAX_STA_TWT_AGRT; i++) { + struct mt7915_twt_flow *f; + + if (!(msta->twt.flowid_mask & BIT(i))) + continue; + + f = &msta->twt.flow[i]; + if (f->duration == twt_agrt->min_twt_dur && + f->mantissa == twt_agrt->mantissa && + f->exp == exp && + f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && + f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && + f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) + return true; + } + + return false; +} + void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt) @@ -2345,14 +2069,24 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) goto unlock; + if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) { + setup_cmd = TWT_SETUP_CMD_DICTATE; + twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR; + goto unlock; + } + flowid = ffs(~msta->twt.flowid_mask) - 1; - le16p_replace_bits(&twt_agrt->req_type, flowid, - IEEE80211_TWT_REQTYPE_FLOWID); + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); + twt_agrt->req_type |= le16_encode_bits(flowid, + IEEE80211_TWT_REQTYPE_FLOWID); table_id = ffs(~dev->twt.table_mask) - 1; exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); + if (mt7915_mac_twt_param_equal(msta, twt_agrt)) + goto unlock; + flow = &msta->twt.flow[flowid]; memset(flow, 0, sizeof(*flow)); INIT_LIST_HEAD(&flow->list); @@ -2394,8 +2128,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, unlock: mutex_unlock(&dev->mt76.mutex); out: - le16p_replace_bits(&twt_agrt->req_type, setup_cmd, - IEEE80211_TWT_REQTYPE_SETUP_CMD); + twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); + twt_agrt->req_type |= + le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 7a2c740d1464..6fa9c79f3e5f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -4,6 +4,8 @@ #ifndef __MT7915_MAC_H #define __MT7915_MAC_H +#include "../mt76_connac2_mac.h" + #define MT_CT_PARSE_LEN 72 #define MT_CT_DMA_BUF_NUM 2 @@ -23,331 +25,24 @@ enum rx_pkt_type { PKT_TYPE_RETRIEVE, PKT_TYPE_TXRX_NOTIFY, PKT_TYPE_RX_EVENT, + PKT_TYPE_RX_FW_MONITOR = 0x0c, + PKT_TYPE_TXRX_NOTIFY_V0 = 0x18, }; -/* RXD DW1 */ -#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0) -#define MT_RXD1_NORMAL_GROUP_1 BIT(11) -#define MT_RXD1_NORMAL_GROUP_2 BIT(12) -#define MT_RXD1_NORMAL_GROUP_3 BIT(13) -#define MT_RXD1_NORMAL_GROUP_4 BIT(14) -#define MT_RXD1_NORMAL_GROUP_5 BIT(15) -#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16) -#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) -#define MT_RXD1_NORMAL_CM BIT(23) -#define MT_RXD1_NORMAL_CLM BIT(24) -#define MT_RXD1_NORMAL_ICV_ERR BIT(25) -#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) -#define MT_RXD1_NORMAL_FCS_ERR BIT(27) -#define MT_RXD1_NORMAL_BAND_IDX BIT(28) -#define MT_RXD1_NORMAL_SPP_EN BIT(29) -#define MT_RXD1_NORMAL_ADD_OM BIT(30) -#define MT_RXD1_NORMAL_SEC_DONE BIT(31) - -/* RXD DW2 */ -#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) -#define MT_RXD2_NORMAL_CO_ANT BIT(6) -#define MT_RXD2_NORMAL_BF_CQI BIT(7) -#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) -#define MT_RXD2_NORMAL_HDR_TRANS BIT(13) -#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14) -#define MT_RXD2_NORMAL_TID GENMASK(19, 16) -#define MT_RXD2_NORMAL_MU_BAR BIT(21) -#define MT_RXD2_NORMAL_SW_BIT BIT(22) -#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) -#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) -#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) -#define MT_RXD2_NORMAL_INT_FRAME BIT(26) -#define MT_RXD2_NORMAL_FRAG BIT(27) -#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) -#define MT_RXD2_NORMAL_NDATA BIT(29) -#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) -#define MT_RXD2_NORMAL_BF_REPORT BIT(31) - -/* RXD DW3 */ -#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) -#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) -#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) -#define MT_RXD3_NORMAL_U2M BIT(0) -#define MT_RXD3_NORMAL_HTC_VLD BIT(0) -#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19) -#define MT_RXD3_NORMAL_BEACON_MC BIT(20) -#define MT_RXD3_NORMAL_BEACON_UC BIT(21) -#define MT_RXD3_NORMAL_AMSDU BIT(22) -#define MT_RXD3_NORMAL_MESH BIT(23) -#define MT_RXD3_NORMAL_MHCP BIT(24) -#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25) -#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26) -#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27) -#define MT_RXD3_NORMAL_MORE BIT(28) -#define MT_RXD3_NORMAL_UNWANT BIT(29) -#define MT_RXD3_NORMAL_RX_DROP BIT(30) -#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) - -/* RXD DW4 */ -#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) -#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) -#define MT_RXD4_MID_AMSDU_FRAME BIT(1) -#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) - -#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9) -#define MT_RXD4_NORMAL_CLS BIT(10) -#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11) -#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13) -#define MT_RXD4_NORMAL_WOL GENMASK(18, 14) -#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19) -#define MT_RXD3_NORMAL_PF_MODE BIT(29) -#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) - -#define MT_RXV_HDR_BAND_IDX BIT(24) - -/* RXD GROUP4 */ -#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0) -#define MT_RXD6_TA_LO GENMASK(31, 16) - -#define MT_RXD7_TA_HI GENMASK(31, 0) - -#define MT_RXD8_SEQ_CTRL GENMASK(15, 0) -#define MT_RXD8_QOS_CTL GENMASK(31, 16) - -#define MT_RXD9_HT_CONTROL GENMASK(31, 0) - -/* P-RXV */ -#define MT_PRXV_TX_RATE GENMASK(6, 0) -#define MT_PRXV_TX_DCM BIT(4) -#define MT_PRXV_TX_ER_SU_106T BIT(5) -#define MT_PRXV_NSTS GENMASK(9, 7) -#define MT_PRXV_TXBF BIT(10) -#define MT_PRXV_HT_AD_CODE BIT(11) -#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28) -#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) -#define MT_PRXV_RCPI3 GENMASK(31, 24) -#define MT_PRXV_RCPI2 GENMASK(23, 16) -#define MT_PRXV_RCPI1 GENMASK(15, 8) -#define MT_PRXV_RCPI0 GENMASK(7, 0) - -/* C-RXV */ -#define MT_CRXV_HT_STBC GENMASK(1, 0) -#define MT_CRXV_TX_MODE GENMASK(7, 4) -#define MT_CRXV_FRAME_MODE GENMASK(10, 8) -#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) -#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) -#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) -#define MT_CRXV_HE_PE_DISAMBIG BIT(23) -#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) -#define MT_CRXV_HE_UPLINK BIT(31) -#define MT_CRXV_HE_RU0 GENMASK(7, 0) -#define MT_CRXV_HE_RU1 GENMASK(15, 8) -#define MT_CRXV_HE_RU2 GENMASK(23, 16) -#define MT_CRXV_HE_RU3 GENMASK(31, 24) - -#define MT_CRXV_HE_MU_AID GENMASK(30, 20) - -#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) -#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) -#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) -#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) - -#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0) -#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6) -#define MT_CRXV_HE_BEAM_CHNG BIT(13) -#define MT_CRXV_HE_DOPPLER BIT(16) - -#define MT_CRXV_SNR GENMASK(18, 13) -#define MT_CRXV_FOE_LO GENMASK(31, 19) -#define MT_CRXV_FOE_HI GENMASK(6, 0) -#define MT_CRXV_FOE_SHIFT 13 - -enum tx_header_format { - MT_HDR_FORMAT_802_3, - MT_HDR_FORMAT_CMD, - MT_HDR_FORMAT_802_11, - MT_HDR_FORMAT_802_11_EXT, -}; - -enum tx_pkt_type { - MT_TX_TYPE_CT, - MT_TX_TYPE_SF, - MT_TX_TYPE_CMD, - MT_TX_TYPE_FW, -}; - -enum tx_port_idx { - MT_TX_PORT_IDX_LMAC, - MT_TX_PORT_IDX_MCU -}; - -enum tx_mcu_port_q_idx { - MT_TX_MCU_PORT_RX_Q0 = 0x20, - MT_TX_MCU_PORT_RX_Q1, - MT_TX_MCU_PORT_RX_Q2, - MT_TX_MCU_PORT_RX_Q3, - MT_TX_MCU_PORT_RX_FWDL = 0x3e -}; - -#define MT_CT_INFO_APPLY_TXD BIT(0) -#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) -#define MT_CT_INFO_MGMT_FRAME BIT(2) -#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) -#define MT_CT_INFO_HSR2_TX BIT(4) -#define MT_CT_INFO_FROM_HOST BIT(7) - -#define MT_TXD_SIZE (8 * 4) - -#define MT_TXD0_Q_IDX GENMASK(31, 25) -#define MT_TXD0_PKT_FMT GENMASK(24, 23) -#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) -#define MT_TXD0_TX_BYTES GENMASK(15, 0) - -#define MT_TXD1_LONG_FORMAT BIT(31) -#define MT_TXD1_TGID BIT(30) -#define MT_TXD1_OWN_MAC GENMASK(29, 24) -#define MT_TXD1_AMSDU BIT(23) -#define MT_TXD1_TID GENMASK(22, 20) -#define MT_TXD1_HDR_PAD GENMASK(19, 18) -#define MT_TXD1_HDR_FORMAT GENMASK(17, 16) -#define MT_TXD1_HDR_INFO GENMASK(15, 11) -#define MT_TXD1_ETH_802_3 BIT(15) -#define MT_TXD1_VTA BIT(10) -#define MT_TXD1_WLAN_IDX GENMASK(9, 0) - -#define MT_TXD2_FIX_RATE BIT(31) -#define MT_TXD2_FIXED_RATE BIT(30) -#define MT_TXD2_POWER_OFFSET GENMASK(29, 24) -#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) -#define MT_TXD2_FRAG GENMASK(15, 14) -#define MT_TXD2_HTC_VLD BIT(13) -#define MT_TXD2_DURATION BIT(12) -#define MT_TXD2_BIP BIT(11) -#define MT_TXD2_MULTICAST BIT(10) -#define MT_TXD2_RTS BIT(9) -#define MT_TXD2_SOUNDING BIT(8) -#define MT_TXD2_NDPA BIT(7) -#define MT_TXD2_NDP BIT(6) -#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) -#define MT_TXD2_SUB_TYPE GENMASK(3, 0) - -#define MT_TXD3_SN_VALID BIT(31) -#define MT_TXD3_PN_VALID BIT(30) -#define MT_TXD3_SW_POWER_MGMT BIT(29) -#define MT_TXD3_BA_DISABLE BIT(28) -#define MT_TXD3_SEQ GENMASK(27, 16) -#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) -#define MT_TXD3_TX_COUNT GENMASK(10, 6) -#define MT_TXD3_TIMING_MEASURE BIT(5) -#define MT_TXD3_DAS BIT(4) -#define MT_TXD3_EEOSP BIT(3) -#define MT_TXD3_EMRD BIT(2) -#define MT_TXD3_PROTECT_FRAME BIT(1) -#define MT_TXD3_NO_ACK BIT(0) - -#define MT_TXD4_PN_LOW GENMASK(31, 0) - -#define MT_TXD5_PN_HIGH GENMASK(31, 16) -#define MT_TXD5_MD BIT(15) -#define MT_TXD5_ADD_BA BIT(14) -#define MT_TXD5_TX_STATUS_HOST BIT(10) -#define MT_TXD5_TX_STATUS_MCU BIT(9) -#define MT_TXD5_TX_STATUS_FMT BIT(8) -#define MT_TXD5_PID GENMASK(7, 0) - -#define MT_TXD6_TX_IBF BIT(31) -#define MT_TXD6_TX_EBF BIT(30) -#define MT_TXD6_TX_RATE GENMASK(29, 16) -#define MT_TXD6_SGI GENMASK(15, 14) -#define MT_TXD6_HELTF GENMASK(13, 12) -#define MT_TXD6_LDPC BIT(11) -#define MT_TXD6_SPE_ID_IDX BIT(10) -#define MT_TXD6_ANT_ID GENMASK(7, 4) -#define MT_TXD6_DYN_BW BIT(3) -#define MT_TXD6_FIXED_BW BIT(2) -#define MT_TXD6_BW GENMASK(1, 0) - -#define MT_TXD7_TXD_LEN GENMASK(31, 30) -#define MT_TXD7_UDP_TCP_SUM BIT(29) -#define MT_TXD7_IP_SUM BIT(28) - -#define MT_TXD7_TYPE GENMASK(21, 20) -#define MT_TXD7_SUB_TYPE GENMASK(19, 16) - -#define MT_TXD7_PSE_FID GENMASK(27, 16) -#define MT_TXD7_SPE_IDX GENMASK(15, 11) -#define MT_TXD7_HW_AMSDU BIT(10) -#define MT_TXD7_TX_TIME GENMASK(9, 0) - -#define MT_TX_RATE_STBC BIT(13) -#define MT_TX_RATE_NSS GENMASK(12, 10) -#define MT_TX_RATE_MODE GENMASK(9, 6) -#define MT_TX_RATE_SU_EXT_TONE BIT(5) -#define MT_TX_RATE_DCM BIT(4) -/* VHT/HE only use bits 0-3 */ -#define MT_TX_RATE_IDX GENMASK(5, 0) - -#define MT_TXP_MAX_BUF_NUM 6 - -struct mt7915_txp { - __le16 flags; - __le16 token; - u8 bss_idx; - __le16 rept_wds_wcid; - u8 nbuf; - __le32 buf[MT_TXP_MAX_BUF_NUM]; - __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed __aligned(4); - -struct mt7915_tx_free { - __le16 rx_byte_cnt; - __le16 ctrl; - u8 txd_cnt; - u8 rsv[3]; - __le32 info[]; -} __packed __aligned(4); - +#define MT_TX_FREE_VER GENMASK(18, 16) #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) +#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) #define MT_TX_FREE_LATENCY GENMASK(12, 0) /* 0: success, others: dropped */ -#define MT_TX_FREE_STATUS GENMASK(14, 13) #define MT_TX_FREE_MSDU_ID GENMASK(30, 16) #define MT_TX_FREE_PAIR BIT(31) +#define MT_TX_FREE_MPDU_HEADER BIT(30) +#define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0) + /* will support this field in further revision */ #define MT_TX_FREE_RATE GENMASK(13, 0) -#define MT_TXS0_FIXED_RATE BIT(31) -#define MT_TXS0_BW GENMASK(30, 29) -#define MT_TXS0_TID GENMASK(28, 26) -#define MT_TXS0_AMPDU BIT(25) -#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) -#define MT_TXS0_BA_ERROR BIT(22) -#define MT_TXS0_PS_FLAG BIT(21) -#define MT_TXS0_TXOP_TIMEOUT BIT(20) -#define MT_TXS0_BIP_ERROR BIT(19) - -#define MT_TXS0_QUEUE_TIMEOUT BIT(18) -#define MT_TXS0_RTS_TIMEOUT BIT(17) -#define MT_TXS0_ACK_TIMEOUT BIT(16) -#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) - -#define MT_TXS0_TX_STATUS_HOST BIT(15) -#define MT_TXS0_TX_STATUS_MCU BIT(14) -#define MT_TXS0_TX_RATE GENMASK(13, 0) - -#define MT_TXS1_SEQNO GENMASK(31, 20) -#define MT_TXS1_RESP_RATE GENMASK(19, 16) -#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) -#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) - -#define MT_TXS2_BF_STATUS GENMASK(31, 30) -#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27) -#define MT_TXS2_SHARED_ANTENNA BIT(26) -#define MT_TXS2_WCID GENMASK(25, 16) -#define MT_TXS2_TX_DELAY GENMASK(15, 0) - -#define MT_TXS3_PID GENMASK(31, 24) -#define MT_TXS3_ANT_ID GENMASK(23, 0) - -#define MT_TXS4_TIMESTAMP GENMASK(31, 0) - #define MT_TXS5_F0_FINAL_MPDU BIT(31) #define MT_TXS5_F0_QOS BIT(30) #define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) @@ -403,17 +98,4 @@ struct mt7915_dfs_radar_spec { struct mt7915_dfs_pattern radar_pattern[16]; }; -static inline struct mt7915_txp * -mt7915_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - u8 *txwi; - - if (!t) - return NULL; - - txwi = mt76_get_txwi_ptr(dev, t); - - return (struct mt7915_txp *)(txwi + MT_TXD_SIZE); -} - #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 057ab27b7083..89b519cfd14c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -34,7 +34,7 @@ static int mt7915_start(struct ieee80211_hw *hw) running = mt7915_dev_running(dev); if (!running) { - ret = mt7915_mcu_set_pm(dev, 0, 0); + ret = mt76_connac_mcu_set_pm(&dev->mt76, 0, 0); if (ret) goto out; @@ -42,15 +42,11 @@ static int mt7915_start(struct ieee80211_hw *hw) if (ret) goto out; - ret = mt7915_mcu_set_scs(dev, 0, true); - if (ret) - goto out; - mt7915_mac_enable_nf(dev, 0); } - if (phy != &dev->phy) { - ret = mt7915_mcu_set_pm(dev, 1, 0); + if (phy != &dev->phy || phy->band_idx) { + ret = mt76_connac_mcu_set_pm(&dev->mt76, 1, 0); if (ret) goto out; @@ -58,14 +54,11 @@ static int mt7915_start(struct ieee80211_hw *hw) if (ret) goto out; - ret = mt7915_mcu_set_scs(dev, 1, true); - if (ret) - goto out; - mt7915_mac_enable_nf(dev, 1); } - ret = mt7915_mcu_set_rts_thresh(phy, 0x92b); + ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, + phy != &dev->phy); if (ret) goto out; @@ -106,12 +99,12 @@ static void mt7915_stop(struct ieee80211_hw *hw) clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); if (phy != &dev->phy) { - mt7915_mcu_set_pm(dev, 1, 1); + mt76_connac_mcu_set_pm(&dev->mt76, 1, 1); mt7915_mcu_set_mac(dev, 1, false, false); } if (!mt7915_dev_running(dev)) { - mt7915_mcu_set_pm(dev, 0, 1); + mt76_connac_mcu_set_pm(&dev->mt76, 0, 1); mt7915_mcu_set_mac(dev, 0, false, false); } @@ -173,14 +166,14 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; - mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0); - mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0); + mvif->bitrate_mask.control[i].he_gi = 0xff; + mvif->bitrate_mask.control[i].he_ltf = 0xff; mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); - memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0), + memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].ht_mcs)); - memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0), + memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].vht_mcs)); - memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0), + memset(mvif->bitrate_mask.control[i].he_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].he_mcs)); } } @@ -203,8 +196,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, is_zero_ether_addr(vif->addr)) phy->monitor_vif = vif; - mvif->idx = ffs(~dev->mt76.vif_mask) - 1; - if (mvif->idx >= MT7915_MAX_INTERFACES) { + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); + if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) { ret = -ENOSPC; goto out; } @@ -214,29 +207,27 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, ret = -ENOSPC; goto out; } - mvif->omac_idx = idx; + mvif->mt76.omac_idx = idx; mvif->phy = phy; - mvif->band_idx = ext_phy; + mvif->mt76.band_idx = phy->band_idx; - if (dev->mt76.phy2) - mvif->wmm_idx = ext_phy * (MT7915_MAX_WMM_SETS / 2) + - mvif->idx % (MT7915_MAX_WMM_SETS / 2); - else - mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS; + mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; + if (ext_phy) + mvif->mt76.wmm_idx += 2; ret = mt7915_mcu_add_dev_info(phy, vif, true); if (ret) goto out; - dev->mt76.vif_mask |= BIT(mvif->idx); - phy->omac_mask |= BIT_ULL(mvif->omac_idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); + phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - idx = MT7915_WTBL_RESERVED - mvif->idx; + idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.rc_list); INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.ext_phy = mvif->band_idx; + mvif->sta.wcid.phy_idx = ext_phy; mvif->sta.wcid.hw_key_idx = -1; mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; mt76_packet_id_init(&mvif->sta.wcid); @@ -244,20 +235,23 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, mt7915_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } if (vif->type != NL80211_IFTYPE_AP && - (!mvif->omac_idx || mvif->omac_idx > 3)) + (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) vif->offload_flags = 0; vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; mt7915_init_bitrate_mask(vif); memset(&mvif->cap, -1, sizeof(mvif->cap)); + mt7915_mcu_add_bss_info(phy, vif, true); + mt7915_mcu_add_sta(dev, vif, NULL, true); + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + out: mutex_unlock(&dev->mt76.mutex); @@ -288,8 +282,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); mutex_lock(&dev->mt76.mutex); - dev->mt76.vif_mask &= ~BIT(mvif->idx); - phy->omac_mask &= ~BIT_ULL(mvif->omac_idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); + phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->sta_poll_lock); @@ -300,25 +294,6 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, mt76_packet_id_flush(&dev->mt76, &msta->wcid); } -static void mt7915_init_dfs_state(struct mt7915_phy *phy) -{ - struct mt76_phy *mphy = phy->mt76; - struct ieee80211_hw *hw = mphy->hw; - struct cfg80211_chan_def *chandef = &hw->conf.chandef; - - if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) - return; - - if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) - return; - - if (mphy->chandef.chan->center_freq == chandef->chan->center_freq && - mphy->chandef.width == chandef->width) - return; - - phy->dfs_state = -1; -} - int mt7915_set_channel(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; @@ -329,7 +304,6 @@ int mt7915_set_channel(struct mt7915_phy *phy) mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &phy->mt76->state); - mt7915_init_dfs_state(phy); mt76_set_channel(phy->mt76); if (dev->flash_mode) { @@ -368,6 +342,7 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; @@ -407,6 +382,11 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&dev->mt76.mutex); + if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) { + mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); + mt7915_mcu_add_bss_info(phy, vif, true); + } + if (cmd == SET_KEY) *wcid_keyidx = idx; else if (idx == *wcid_keyidx) @@ -417,8 +397,31 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); - err = mt7915_mcu_add_key(dev, vif, msta, key, cmd); + err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, + key, MCU_EXT_CMD(STA_REC_UPDATE), + &msta->wcid, cmd); +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} + +static int mt7915_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + int err = -EINVAL; + + mutex_lock(&dev->mt76.mutex); + if (!cfg80211_chandef_valid(&phy->mt76->chandef)) + goto out; + err = mt76_init_sar_power(hw, sar); + if (err) + goto out; + + err = mt7915_mcu_set_txpower_sku(phy); out: mutex_unlock(&dev->mt76.mutex); @@ -475,14 +478,14 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) } static int -mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; /* no need to update right away, we'll get BSS_CHANGED_QOS */ - queue = mt7915_lmac_mapping(dev, queue); + queue = mt76_connac_lmac_mapping(queue); mvif->queue_params[queue] = *params; return 0; @@ -556,7 +559,7 @@ mt7915_update_bss_color(struct ieee80211_hw *hw, case NL80211_IFTYPE_AP: { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - if (mvif->omac_idx > HW_BSSID_MAX) + if (mvif->mt76.omac_idx > HW_BSSID_MAX) return; fallthrough; } @@ -571,7 +574,7 @@ mt7915_update_bss_color(struct ieee80211_hw *hw, static void mt7915_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = mt7915_hw_dev(hw); @@ -591,7 +594,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ASSOC) { - mt7915_mcu_add_bss_info(phy, vif, info->assoc); + mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc); mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable); } @@ -620,8 +623,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, mt7915_update_bss_color(hw, vif, &info->he_bss_color); if (changed & (BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_ENABLED)) - mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); + BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) + mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); mutex_unlock(&dev->mt76.mutex); } @@ -634,7 +639,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw, struct mt7915_dev *dev = mt7915_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7915_mcu_add_beacon(hw, vif, true); + mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); mutex_unlock(&dev->mt76.mutex); } @@ -644,6 +649,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + bool ext_phy = mvif->phy != &dev->phy; int ret, idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); @@ -655,7 +661,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; - msta->wcid.ext_phy = mvif->band_idx; + msta->wcid.phy_idx = ext_phy; msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; msta->jiffies = jiffies; @@ -726,7 +732,7 @@ static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val) int ret; mutex_lock(&dev->mt76.mutex); - ret = mt7915_mcu_set_rts_thresh(phy, val); + ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, phy != &dev->phy); mutex_unlock(&dev->mt76.mutex); return ret; @@ -838,10 +844,15 @@ u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif) lockdep_assert_held(&dev->mt76.mutex); - n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx; + n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : mvif->mt76.omac_idx; /* TSF software read */ - mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, - MT_LPON_TCR_SW_READ); + if (is_mt7915(&dev->mt76)) + mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_READ); + else + mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_READ); tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band)); tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band)); @@ -878,12 +889,17 @@ mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); - n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx; + n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : mvif->mt76.omac_idx; mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]); /* TSF software overwrite */ - mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, - MT_LPON_TCR_SW_WRITE); + if (is_mt7915(&dev->mt76)) + mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_WRITE); + else + mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_WRITE); mutex_unlock(&dev->mt76.mutex); } @@ -904,12 +920,17 @@ mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&dev->mt76.mutex); - n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx; + n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 + : mvif->mt76.omac_idx; mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]); /* TSF software adjust*/ - mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, - MT_LPON_TCR_SW_ADJUST); + if (is_mt7915(&dev->mt76)) + mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_ADJUST); + else + mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, + MT_LPON_TCR_SW_ADJUST); mutex_unlock(&dev->mt76.mutex); } @@ -944,12 +965,9 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) phy->mt76->antenna_mask = tx_ant; - if (ext_phy) { - if (dev->chainmask == 0xf) - tx_ant <<= 2; - else - tx_ant <<= 1; - } + if (ext_phy) + tx_ant <<= dev->chainshift; + phy->mt76->chainmask = tx_ant; mt76_set_stream_caps(phy->mt76, true); @@ -971,7 +989,8 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, struct rate_info *txrate = &msta->wcid.rate; struct rate_info rxrate = {}; - if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { + if (is_mt7915(&phy->dev->mt76) && + !mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { sinfo->rxrate = rxrate; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); } @@ -991,6 +1010,23 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, } sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + + /* offloading flows bypass networking stack, so driver counts and + * reports sta statistics via NL80211_STA_INFO when WED is active. + */ + if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + sinfo->tx_bytes = msta->wcid.stats.tx_bytes; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); + + sinfo->tx_packets = msta->wcid.stats.tx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + } } static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) @@ -1056,7 +1092,7 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, else clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); - mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); + mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw, @@ -1072,7 +1108,7 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw, else clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); - mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); + mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); } static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { @@ -1128,8 +1164,15 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_fifo_full_cnt", "rx_mpdu_cnt", "channel_idle_cnt", + "primary_cca_busy_time", + "secondary_cca_busy_time", + "primary_energy_detect_time", + "cck_mdrdy_time", + "ofdm_mdrdy_time", + "green_mdrdy_time", "rx_vector_mismatch_cnt", "rx_delimiter_fail_cnt", + "rx_mrdy_cnt", "rx_len_mismatch_cnt", "rx_ampdu_cnt", "rx_ampdu_bytes_cnt", @@ -1195,10 +1238,10 @@ static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) struct mt76_ethtool_worker_info *wi = wi_data; struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - if (msta->vif->idx != wi->idx) + if (msta->vif->mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->stats); + mt76_ethtool_worker(wi, &msta->wcid.stats); } static @@ -1211,11 +1254,10 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt76_ethtool_worker_info wi = { .data = data, - .idx = mvif->idx, + .idx = mvif->mt76.idx, }; struct mib_stats *mib = &phy->mib; /* See mt7915_ampdu_stat_read_phy, etc */ - bool ext_phy = phy != &dev->phy; int i, n, ei = 0; mutex_lock(&dev->mt76.mutex); @@ -1232,7 +1274,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, data[ei++] = mib->tx_pkt_ibf_cnt; /* Tx ampdu stat */ - n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + n = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++) data[ei++] = dev->mt76.aggr_stats[i + n]; @@ -1270,8 +1312,15 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, data[ei++] = mib->rx_fifo_full_cnt; data[ei++] = mib->rx_mpdu_cnt; data[ei++] = mib->channel_idle_cnt; + data[ei++] = mib->primary_cca_busy_time; + data[ei++] = mib->secondary_cca_busy_time; + data[ei++] = mib->primary_energy_detect_time; + data[ei++] = mib->cck_mdrdy_time; + data[ei++] = mib->ofdm_mdrdy_time; + data[ei++] = mib->green_mdrdy_time; data[ei++] = mib->rx_vector_mismatch_cnt; data[ei++] = mib->rx_delimiter_fail_cnt; + data[ei++] = mib->rx_mrdy_cnt; data[ei++] = mib->rx_len_mismatch_cnt; data[ei++] = mib->rx_ampdu_cnt; data[ei++] = mib->rx_ampdu_bytes_cnt; @@ -1309,6 +1358,88 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } +static int +mt7915_set_radar_background(struct ieee80211_hw *hw, + struct cfg80211_chan_def *chandef) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = phy->dev; + int ret = -EINVAL; + bool running; + + mutex_lock(&dev->mt76.mutex); + + if (dev->mt76.region == NL80211_DFS_UNSET) + goto out; + + if (dev->rdd2_phy && dev->rdd2_phy != phy) { + /* rdd2 is already locked */ + ret = -EBUSY; + goto out; + } + + /* rdd2 already configured on a radar channel */ + running = dev->rdd2_phy && + cfg80211_chandef_valid(&dev->rdd2_chandef) && + !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR); + + if (!chandef || running || + !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) { + ret = mt7915_mcu_rdd_background_enable(phy, NULL); + if (ret) + goto out; + + if (!running) + goto update_phy; + } + + ret = mt7915_mcu_rdd_background_enable(phy, chandef); + if (ret) + goto out; + +update_phy: + dev->rdd2_phy = chandef ? phy : NULL; + if (chandef) + dev->rdd2_chandef = *chandef; +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int +mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct net_device_path_ctx *ctx, + struct net_device_path *path) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + + if (!mtk_wed_device_active(wed)) + return -ENODEV; + + if (msta->wcid.idx > 0xff) + return -EIO; + + path->type = DEV_PATH_MTK_WDMA; + path->dev = ctx->dev; + path->mtk_wdma.wdma_idx = wed->wdma_idx; + path->mtk_wdma.bss = mvif->mt76.idx; + path->mtk_wdma.wcid = msta->wcid.idx; + path->mtk_wdma.queue = phy != &dev->phy; + + ctx->dev = NULL; + + return 0; +} +#endif + const struct ieee80211_ops mt7915_ops = { .tx = mt7915_tx, .start = mt7915_start, @@ -1331,6 +1462,7 @@ const struct ieee80211_ops mt7915_ops = { .sw_scan_complete = mt76_sw_scan_complete, .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, + .set_sar_specs = mt7915_set_sar_specs, .channel_switch_beacon = mt7915_channel_switch_beacon, .get_stats = mt7915_get_stats, .get_et_sset_count = mt7915_get_et_sset_count, @@ -1354,4 +1486,8 @@ const struct ieee80211_ops mt7915_ops = { #ifdef CONFIG_MAC80211_DEBUGFS .sta_add_debugfs = mt7915_sta_add_debugfs, #endif + .set_radar_background = mt7915_set_radar_background, +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + .net_fill_forward_path = mt7915_net_fill_forward_path, +#endif }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 852d5d97c70b..8d297e4aa7d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1,199 +1,37 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ -#include <linux/firmware.h> #include <linux/fs.h> #include "mt7915.h" #include "mcu.h" #include "mac.h" #include "eeprom.h" -struct mt7915_patch_hdr { - char build_date[16]; - char platform[4]; - __be32 hw_sw_ver; - __be32 patch_ver; - __be16 checksum; - u16 reserved; - struct { - __be32 patch_ver; - __be32 subsys; - __be32 feature; - __be32 n_region; - __be32 crc; - u32 reserved[11]; - } desc; -} __packed; - -struct mt7915_patch_sec { - __be32 type; - __be32 offs; - __be32 size; - union { - __be32 spec[13]; - struct { - __be32 addr; - __be32 len; - __be32 sec_key_idx; - __be32 align_len; - u32 reserved[9]; - } info; - }; -} __packed; - -struct mt7915_fw_trailer { - u8 chip_id; - u8 eco_code; - u8 n_region; - u8 format_ver; - u8 format_flag; - u8 reserved[2]; - char fw_ver[10]; - char build_date[15]; - u32 crc; -} __packed; - -struct mt7915_fw_region { - __le32 decomp_crc; - __le32 decomp_len; - __le32 decomp_blk_sz; - u8 reserved[4]; - __le32 addr; - __le32 len; - u8 feature_set; - u8 reserved1[15]; -} __packed; +#define fw_name(_dev, name, ...) ({ \ + char *_fw; \ + switch (mt76_chip(&(_dev)->mt76)) { \ + case 0x7915: \ + _fw = MT7915_##name; \ + break; \ + case 0x7986: \ + _fw = MT7986_##name##__VA_ARGS__; \ + break; \ + default: \ + _fw = MT7916_##name; \ + break; \ + } \ + _fw; \ +}) + +#define fw_name_var(_dev, name) (mt7915_check_adie(dev, false) ? \ + fw_name(_dev, name) : \ + fw_name(_dev, name, _MT7975)) #define MCU_PATCH_ADDRESS 0x200000 -#define FW_FEATURE_SET_ENCRYPT BIT(0) -#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) -#define FW_FEATURE_OVERRIDE_ADDR BIT(5) - -#define DL_MODE_ENCRYPT BIT(0) -#define DL_MODE_KEY_IDX GENMASK(2, 1) -#define DL_MODE_RESET_SEC_IV BIT(3) -#define DL_MODE_WORKING_PDA_CR4 BIT(4) -#define DL_MODE_NEED_RSP BIT(31) - -#define FW_START_OVERRIDE BIT(0) -#define FW_START_WORKING_PDA_CR4 BIT(2) - -#define PATCH_SEC_TYPE_MASK GENMASK(15, 0) -#define PATCH_SEC_TYPE_INFO 0x2 - -#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) -#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) - #define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p) #define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m) -static enum mcu_cipher_type -mt7915_mcu_get_cipher(int cipher) -{ - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - return MCU_CIPHER_WEP40; - case WLAN_CIPHER_SUITE_WEP104: - return MCU_CIPHER_WEP104; - case WLAN_CIPHER_SUITE_TKIP: - return MCU_CIPHER_TKIP; - case WLAN_CIPHER_SUITE_AES_CMAC: - return MCU_CIPHER_BIP_CMAC_128; - case WLAN_CIPHER_SUITE_CCMP: - return MCU_CIPHER_AES_CCMP; - case WLAN_CIPHER_SUITE_CCMP_256: - return MCU_CIPHER_CCMP_256; - case WLAN_CIPHER_SUITE_GCMP: - return MCU_CIPHER_GCMP; - case WLAN_CIPHER_SUITE_GCMP_256: - return MCU_CIPHER_GCMP_256; - case WLAN_CIPHER_SUITE_SMS4: - return MCU_CIPHER_WAPI; - default: - return MCU_CIPHER_NONE; - } -} - -static u8 mt7915_mcu_chan_bw(struct cfg80211_chan_def *chandef) -{ - static const u8 width_to_bw[] = { - [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ, - [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ, - [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ, - [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ, - [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ, - [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, - [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, - [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, - }; - - if (chandef->width >= ARRAY_SIZE(width_to_bw)) - return 0; - - return width_to_bw[chandef->width]; -} - -static const struct ieee80211_sta_he_cap * -mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif) -{ - struct ieee80211_supported_band *sband; - enum nl80211_band band; - - band = phy->mt76->chandef.chan->band; - sband = phy->mt76->hw->wiphy->bands[band]; - - return ieee80211_get_he_iftype_cap(sband, vif->type); -} - -static u8 -mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - enum nl80211_band band = mvif->phy->mt76->chandef.chan->band; - struct ieee80211_sta_ht_cap *ht_cap; - struct ieee80211_sta_vht_cap *vht_cap; - const struct ieee80211_sta_he_cap *he_cap; - u8 mode = 0; - - if (sta) { - ht_cap = &sta->ht_cap; - vht_cap = &sta->vht_cap; - he_cap = &sta->he_cap; - } else { - struct ieee80211_supported_band *sband; - - sband = mvif->phy->mt76->hw->wiphy->bands[band]; - - ht_cap = &sband->ht_cap; - vht_cap = &sband->vht_cap; - he_cap = ieee80211_get_he_iftype_cap(sband, vif->type); - } - - if (band == NL80211_BAND_2GHZ) { - mode |= PHY_MODE_B | PHY_MODE_G; - - if (ht_cap->ht_supported) - mode |= PHY_MODE_GN; - - if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_24G; - } else if (band == NL80211_BAND_5GHZ) { - mode |= PHY_MODE_A; - - if (ht_cap->ht_supported) - mode |= PHY_MODE_AN; - - if (vht_cap->vht_supported) - mode |= PHY_MODE_AC; - - if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_5G; - } - - return mode; -} - static u8 mt7915_mcu_get_sta_nss(u16 mcs_map) { @@ -211,24 +49,13 @@ mt7915_mcu_get_sta_nss(u16 mcs_map) static void mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, - const u16 *mask) + u16 mcs_map) { struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct cfg80211_chan_def *chandef = &msta->vif->phy->mt76->chandef; - int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss; - u16 mcs_map; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_80P80: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80p80); - break; - case NL80211_CHAN_WIDTH_160: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160); - break; - default: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80); - break; - } + struct mt7915_dev *dev = msta->vif->phy->dev; + enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band; + const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs; + int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; for (nss = 0; nss < max_nss; nss++) { int mcs; @@ -266,8 +93,9 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, mcs_map &= ~(0x3 << (nss * 2)); mcs_map |= mcs << (nss * 2); - /* only support 2ss on 160MHz */ - if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160)) + /* only support 2ss on 160MHz for mt7915 */ + if (is_mt7915(&dev->mt76) && nss > 1 && + sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) break; } @@ -278,8 +106,10 @@ static void mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, const u16 *mask) { - u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); - int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = msta->vif->phy->dev; + u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); + int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; u16 mcs; for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) { @@ -299,8 +129,9 @@ mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]); - /* only support 2ss on 160MHz */ - if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160)) + /* only support 2ss on 160MHz for mt7915 */ + if (is_mt7915(&dev->mt76) && nss > 1 && + sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) break; } } @@ -309,17 +140,17 @@ static void mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs, const u8 *mask) { - int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss; + int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss; for (nss = 0; nss < max_nss; nss++) - ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss]; + ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss]; } static int mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq) { - struct mt7915_mcu_rxd *rxd; + struct mt76_connac2_mcu_rxd *rxd; int ret = 0; if (!skb) { @@ -328,7 +159,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, return -ETIMEDOUT; } - rxd = (struct mt7915_mcu_rxd *)skb->data; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; if (seq != rxd->seq) return -EAGAIN; @@ -339,7 +170,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, skb_pull(skb, sizeof(*rxd) + 4); ret = le32_to_cpu(*(__le32 *)skb->data); } else { - skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); } return ret; @@ -350,69 +181,20 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *wait_seq) { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - struct mt7915_mcu_txd *mcu_txd; enum mt76_mcuq_id qid; - __le32 *txd; - u32 val; - u8 seq; - - /* TODO: make dynamic based on msg type */ - mdev->mcu.timeout = 20 * HZ; + int ret; - seq = ++dev->mt76.mcu.msg_seq & 0xf; - if (!seq) - seq = ++dev->mt76.mcu.msg_seq & 0xf; + ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq); + if (ret) + return ret; - if (cmd == MCU_CMD(FW_SCATTER)) { + if (cmd == MCU_CMD(FW_SCATTER)) qid = MT_MCUQ_FWDL; - goto exit; - } - - mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd)); - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) + else if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) qid = MT_MCUQ_WA; else qid = MT_MCUQ_WM; - txd = mcu_txd->txd; - - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | - FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) | - FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0); - txd[0] = cpu_to_le32(val); - - val = MT_TXD1_LONG_FORMAT | - FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD); - txd[1] = cpu_to_le32(val); - - mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); - mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, - MT_TX_MCU_PORT_RX_Q0)); - mcu_txd->pkt_type = MCU_PKT_ID; - mcu_txd->seq = seq; - - mcu_txd->cid = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); - mcu_txd->set_query = MCU_Q_NA; - mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd); - if (mcu_txd->ext_cid) { - mcu_txd->ext_cid_ack = 1; - - /* do not use Q_SET for efuse */ - if (cmd & __MCU_CMD_FIELD_QUERY) - mcu_txd->set_query = MCU_Q_QUERY; - else - mcu_txd->set_query = MCU_Q_SET; - } - - if (cmd & __MCU_CMD_FIELD_WA) - mcu_txd->s2d_index = MCU_S2D_H2C; - else - mcu_txd->s2d_index = MCU_S2D_H2N; - -exit: - if (wait_seq) - *wait_seq = seq; - return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0); } @@ -434,7 +216,7 @@ int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) static void mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (vif->csa_active) + if (vif->bss_conf.csa_active) ieee80211_csa_finish(vif); } @@ -446,8 +228,8 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb) c = (struct mt7915_mcu_csa_notify *)skb->data; - if (c->band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; ieee80211_iterate_active_interfaces_atomic(mphy->hw, IEEE80211_IFACE_ITER_RESUME_ALL, @@ -465,8 +247,8 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb) if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE) return; - if (t->ctrl.band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; phy = (struct mt7915_phy *)mphy->priv; phy->throttle_state = t->ctrl.duty.duty_cycle; @@ -480,22 +262,33 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) r = (struct mt7915_mcu_rdd_report *)skb->data; - if (r->band_idx && dev->mt76.phy2) - mphy = dev->mt76.phy2; + if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; - ieee80211_radar_detected(mphy->hw); + if (r->band_idx == MT_RX_SEL2) + cfg80211_background_radar_event(mphy->hw->wiphy, + &dev->rdd2_chandef, + GFP_ATOMIC); + else + ieee80211_radar_detected(mphy->hw); dev->hw_pattern++; } static void mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) { - struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; - const char *data = (char *)&rxd[1]; - const char *type; + struct mt76_connac2_mcu_rxd *rxd; + int len = skb->len - sizeof(*rxd); + const char *data, *type; + + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; + data = (char *)&rxd[1]; switch (rxd->s2d_index) { case 0: + if (mt7915_debugfs_rx_log(dev, data, len)) + return; + type = "WM"; break; case 2: @@ -506,24 +299,40 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) break; } - wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, - (int)(skb->len - sizeof(*rxd)), data); + wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data); } static void mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (!vif->color_change_active) + if (!vif->bss_conf.color_change_active) return; ieee80211_color_change_finish(vif); } static void +mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7915_mcu_bcc_notify *b; + + b = (struct mt7915_mcu_bcc_notify *)skb->data; + + if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_mcu_cca_finish, mphy->hw); +} + +static void mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) { - struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + struct mt76_connac2_mcu_rxd *rxd; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; switch (rxd->ext_eid) { case MCU_EXT_EVENT_THERMAL_PROTECT: mt7915_mcu_rx_thermal_notify(dev, skb); @@ -538,9 +347,7 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) mt7915_mcu_rx_log_message(dev, skb); break; case MCU_EXT_EVENT_BCC_NOTIFY: - ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7915_mcu_cca_finish, dev); + mt7915_mcu_rx_bcc_notify(dev, skb); break; default: break; @@ -550,8 +357,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) static void mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb) { - struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + struct mt76_connac2_mcu_rxd *rxd; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; switch (rxd->eid) { case MCU_EVENT_EXT: mt7915_mcu_rx_ext_event(dev, skb); @@ -564,8 +372,9 @@ mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb) void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) { - struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + struct mt76_connac2_mcu_rxd *rxd; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST || rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || @@ -577,88 +386,6 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) mt76_mcu_rx_event(&dev->mt76, skb); } -static struct sk_buff * -mt7915_mcu_alloc_sta_req(struct mt7915_dev *dev, struct mt7915_vif *mvif, - struct mt7915_sta *msta, int len) -{ - struct sta_req_hdr hdr = { - .bss_idx = mvif->idx, - .wlan_idx_lo = msta ? to_wcid_lo(msta->wcid.idx) : 0, - .wlan_idx_hi = msta ? to_wcid_hi(msta->wcid.idx) : 0, - .muar_idx = msta && msta->wcid.sta ? mvif->omac_idx : 0xe, - .is_tlv_append = 1, - }; - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len); - if (!skb) - return ERR_PTR(-ENOMEM); - - skb_put_data(skb, &hdr, sizeof(hdr)); - - return skb; -} - -static struct wtbl_req_hdr * -mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, - int cmd, void *sta_wtbl, struct sk_buff **skb) -{ - struct tlv *sta_hdr = sta_wtbl; - struct wtbl_req_hdr hdr = { - .wlan_idx_lo = to_wcid_lo(msta->wcid.idx), - .wlan_idx_hi = to_wcid_hi(msta->wcid.idx), - .operation = cmd, - }; - struct sk_buff *nskb = *skb; - - if (!nskb) { - nskb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - MT7915_WTBL_UPDATE_MAX_SIZE); - if (!nskb) - return ERR_PTR(-ENOMEM); - - *skb = nskb; - } - - if (sta_hdr) - le16_add_cpu(&sta_hdr->len, sizeof(hdr)); - - return skb_put_data(nskb, &hdr, sizeof(hdr)); -} - -static struct tlv * -mt7915_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, - void *sta_ntlv, void *sta_wtbl) -{ - struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv; - struct tlv *sta_hdr = sta_wtbl; - struct tlv *ptlv, tlv = { - .tag = cpu_to_le16(tag), - .len = cpu_to_le16(len), - }; - u16 ntlv; - - ptlv = skb_put(skb, len); - memcpy(ptlv, &tlv, sizeof(tlv)); - - ntlv = le16_to_cpu(ntlv_hdr->tlv_num); - ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); - - if (sta_hdr) { - u16 size = le16_to_cpu(sta_hdr->len); - - sta_hdr->len = cpu_to_le16(size + len); - } - - return ptlv; -} - -static struct tlv * -mt7915_mcu_add_tlv(struct sk_buff *skb, int tag, int len) -{ - return mt7915_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL); -} - static struct tlv * mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, __le16 *sub_ntlv, __le16 *len) @@ -678,104 +405,6 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, } /** bss info **/ -static int -mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct mt7915_phy *phy, bool enable) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct bss_info_basic *bss; - u16 wlan_idx = mvif->sta.wcid.idx; - u32 type = NETWORK_INFRA; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MONITOR: - break; - case NL80211_IFTYPE_STATION: - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ - if (enable) { - struct ieee80211_sta *sta; - struct mt7915_sta *msta; - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!sta) { - rcu_read_unlock(); - return -EINVAL; - } - - msta = (struct mt7915_sta *)sta->drv_priv; - wlan_idx = msta->wcid.idx; - rcu_read_unlock(); - } - break; - case NL80211_IFTYPE_ADHOC: - type = NETWORK_IBSS; - break; - default: - WARN_ON(1); - break; - } - - bss = (struct bss_info_basic *)tlv; - bss->network_type = cpu_to_le32(type); - bss->bmc_wcid_lo = to_wcid_lo(wlan_idx); - bss->bmc_wcid_hi = to_wcid_hi(wlan_idx); - bss->wmm_idx = mvif->wmm_idx; - bss->active = enable; - - if (vif->type != NL80211_IFTYPE_MONITOR) { - memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); - bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - bss->dtim_period = vif->bss_conf.dtim_period; - bss->phy_mode = mt7915_get_phy_mode(vif, NULL); - } else { - memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); - } - - return 0; -} - -static void -mt7915_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct bss_info_omac *omac; - struct tlv *tlv; - u32 type = 0; - u8 idx; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); - - switch (vif->type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: - type = CONNECTION_INFRA_STA; - break; - case NL80211_IFTYPE_ADHOC: - type = CONNECTION_IBSS_ADHOC; - break; - default: - WARN_ON(1); - break; - } - - omac = (struct bss_info_omac *)tlv; - idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; - omac->conn_type = cpu_to_le32(type); - omac->omac_idx = mvif->omac_idx; - omac->band_idx = mvif->band_idx; - omac->hw_bss_idx = idx; -} - struct mt7915_he_obss_narrow_bw_ru_data { bool tolerated; }; @@ -828,12 +457,12 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct tlv *tlv; int freq1 = chandef->center_freq1; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch)); ch = (struct bss_info_rf_ch *)tlv; ch->pri_ch = chandef->chan->hw_value; ch->center_ch0 = ieee80211_frequency_to_channel(freq1); - ch->bw = mt7915_mcu_chan_bw(chandef); + ch->bw = mt76_connac_chan_bw(chandef); if (chandef->width == NL80211_CHAN_WIDTH_80P80) { int freq2 = chandef->center_freq2; @@ -842,12 +471,7 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) { - struct mt7915_dev *dev = phy->dev; - struct mt76_phy *mphy = &dev->mt76.phy; - bool ext_phy = phy != &dev->phy; - - if (ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + struct mt76_phy *mphy = phy->mt76; ch->he_ru26_block = mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif); @@ -865,7 +489,7 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct bss_info_ra *ra; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra)); ra = (struct bss_info_ra *)tlv; ra->op_mode = vif->type == NL80211_IFTYPE_AP; @@ -893,9 +517,9 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct bss_info_he *he; struct tlv *tlv; - cap = mt7915_get_he_phy_cap(phy, vif); + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); he = (struct bss_info_he *)tlv; he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; @@ -919,7 +543,7 @@ mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb) struct bss_info_hw_amsdu *amsdu; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct bss_info_hw_amsdu *)tlv; amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1); @@ -929,26 +553,6 @@ mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb) } static void -mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif) -{ -/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ -#define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss *ext; - int ext_bss_idx, tsf_offset; - struct tlv *tlv; - - ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; - if (ext_bss_idx < 0) - return; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); - - ext = (struct bss_info_ext_bss *)tlv; - tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); -} - -static void mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) { struct bss_info_bmc_rate *bmc; @@ -956,7 +560,7 @@ mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) enum nl80211_band band = chandef->chan->band; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc)); bmc = (struct bss_info_bmc_rate *)tlv; if (band == NL80211_BAND_2GHZ) { @@ -973,7 +577,7 @@ mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif, { struct mt7915_dev *dev = phy->dev; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - u32 idx = mvif->omac_idx - REPEATER_BSSID_START; + u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START; u32 mask = phy->omac_mask >> 32 & ~BIT(idx); const u8 *addr = vif->addr; struct { @@ -1009,23 +613,25 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_dev *dev = phy->dev; struct sk_buff *skb; - if (mvif->omac_idx >= REPEATER_BSSID_START) { + if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) { mt7915_mcu_muar_config(phy, vif, false, enable); mt7915_mcu_muar_config(phy, vif, true, enable); } - skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL, - MT7915_BSS_UPDATE_MAX_SIZE); + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL, + MT7915_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* bss_omac must be first */ if (enable) - mt7915_mcu_bss_omac_tlv(skb, vif); + mt76_connac_mcu_bss_omac_tlv(skb, vif); - mt7915_mcu_bss_basic_tlv(skb, vif, phy, enable); + mt76_connac_mcu_bss_basic_tlv(skb, vif, NULL, phy->mt76, + mvif->sta.wcid.idx, enable); if (vif->type == NL80211_IFTYPE_MONITOR) goto out; @@ -1039,319 +645,58 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, if (vif->bss_conf.he_support) mt7915_mcu_bss_he_tlv(skb, vif, phy); - if (mvif->omac_idx >= EXT_BSSID_START && - mvif->omac_idx < REPEATER_BSSID_START) - mt7915_mcu_bss_ext_tlv(skb, mvif); + if (mvif->mt76.omac_idx >= EXT_BSSID_START && + mvif->mt76.omac_idx < REPEATER_BSSID_START) + mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76); } out: - return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(BSS_INFO_UPDATE), true); } /** starec & wtbl **/ -static int -mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, - struct ieee80211_key_conf *key, enum set_key_cmd cmd) -{ - struct mt7915_sta_key_conf *bip = &msta->bip; - struct sta_rec_sec *sec; - struct tlv *tlv; - u32 len = sizeof(*sec); - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); - - sec = (struct sta_rec_sec *)tlv; - sec->add = cmd; - - if (cmd == SET_KEY) { - struct sec_key *sec_key; - u8 cipher; - - cipher = mt7915_mcu_get_cipher(key->cipher); - if (cipher == MCU_CIPHER_NONE) - return -EOPNOTSUPP; - - sec_key = &sec->key[0]; - sec_key->cipher_len = sizeof(*sec_key); - - if (cipher == MCU_CIPHER_BIP_CMAC_128) { - sec_key->cipher_id = MCU_CIPHER_AES_CCMP; - sec_key->key_id = bip->keyidx; - sec_key->key_len = 16; - memcpy(sec_key->key, bip->key, 16); - - sec_key = &sec->key[1]; - sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; - sec_key->cipher_len = sizeof(*sec_key); - sec_key->key_len = 16; - memcpy(sec_key->key, key->key, 16); - - sec->n_cipher = 2; - } else { - sec_key->cipher_id = cipher; - sec_key->key_id = key->keyidx; - sec_key->key_len = key->keylen; - memcpy(sec_key->key, key->key, key->keylen); - - 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); - } - - /* store key_conf for BIP batch update */ - if (cipher == MCU_CIPHER_AES_CCMP) { - memcpy(bip->key, key->key, key->keylen); - bip->keyidx = key->keyidx; - } - - len -= sizeof(*sec_key); - sec->n_cipher = 1; - } - } else { - len -= sizeof(sec->key); - sec->n_cipher = 0; - } - sec->len = cpu_to_le16(len); - - return 0; -} - -int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct mt7915_sta *msta, struct ieee80211_key_conf *key, - enum set_key_cmd cmd) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct sk_buff *skb; - int len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_sec); - int ret; - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - ret = mt7915_mcu_sta_key_tlv(msta, skb, key, cmd); - if (ret) - return ret; - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - -static void -mt7915_mcu_sta_ba_tlv(struct sk_buff *skb, - struct ieee80211_ampdu_params *params, - bool enable, bool tx) -{ - struct sta_rec_ba *ba; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); - - ba = (struct sta_rec_ba *)tlv; - ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT; - ba->winsize = cpu_to_le16(params->buf_size); - ba->ssn = cpu_to_le16(params->ssn); - ba->ba_en = enable << params->tid; - ba->amsdu = params->amsdu; - ba->tid = params->tid; -} - -static void -mt7915_mcu_wtbl_ba_tlv(struct sk_buff *skb, - struct ieee80211_ampdu_params *params, - bool enable, bool tx, void *sta_wtbl, - void *wtbl_tlv) -{ - struct wtbl_ba *ba; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba), - wtbl_tlv, sta_wtbl); - - ba = (struct wtbl_ba *)tlv; - ba->tid = params->tid; - - if (tx) { - ba->ba_type = MT_BA_TYPE_ORIGINATOR; - ba->sn = enable ? cpu_to_le16(params->ssn) : 0; - ba->ba_en = enable; - } else { - memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN); - ba->ba_type = MT_BA_TYPE_RECIPIENT; - ba->rst_ba_tid = params->tid; - ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; - ba->rst_ba_sb = 1; - } - - if (enable) - ba->ba_winsize = cpu_to_le16(params->buf_size); -} - -static int -mt7915_mcu_sta_ba(struct mt7915_dev *dev, - struct ieee80211_ampdu_params *params, - bool enable, bool tx) +int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) { struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; struct mt7915_vif *mvif = msta->vif; - struct wtbl_req_hdr *wtbl_hdr; - struct tlv *sta_wtbl; - struct sk_buff *skb; - int ret; - if (enable && tx && !params->amsdu) + if (enable && !params->amsdu) msta->wcid.amsdu = false; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT7915_STA_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, - &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); - - ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); - if (ret) - return ret; - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT7915_STA_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - mt7915_mcu_sta_ba_tlv(skb, params, enable, tx); - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - -int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, - struct ieee80211_ampdu_params *params, - bool enable) -{ - return mt7915_mcu_sta_ba(dev, params, enable, true); + return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, true); } int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - return mt7915_mcu_sta_ba(dev, params, enable, false); -} - -static void -mt7915_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct wtbl_generic *generic; - struct wtbl_rx *rx; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_GENERIC, sizeof(*generic), - wtbl_tlv, sta_wtbl); - - generic = (struct wtbl_generic *)tlv; - - if (sta) { - memcpy(generic->peer_addr, sta->addr, ETH_ALEN); - generic->partial_aid = cpu_to_le16(sta->aid); - generic->muar_idx = mvif->omac_idx; - generic->qos = sta->wme; - } else { - /* use BSSID in station mode */ - if (vif->type == NL80211_IFTYPE_STATION) - memcpy(generic->peer_addr, vif->bss_conf.bssid, - ETH_ALEN); - else - eth_broadcast_addr(generic->peer_addr); - - generic->muar_idx = 0xe; - } - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx), - wtbl_tlv, sta_wtbl); - - rx = (struct wtbl_rx *)tlv; - rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1; - rx->rca2 = 1; - rx->rv = 1; -} - -static void -mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable) -{ -#define EXTRA_INFO_VER BIT(0) -#define EXTRA_INFO_NEW BIT(1) - struct sta_rec_basic *basic; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic)); - - basic = (struct sta_rec_basic *)tlv; - basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); - - if (enable) { - basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); - basic->conn_state = CONN_STATE_PORT_SECURE; - } else { - basic->conn_state = CONN_STATE_DISCONNECT; - } - - if (!sta) { - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); - eth_broadcast_addr(basic->peer_addr); - return; - } - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA); - break; - case NL80211_IFTYPE_STATION: - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP); - break; - case NL80211_IFTYPE_ADHOC: - basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); - break; - default: - WARN_ON(1); - break; - } + struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; + struct mt7915_vif *mvif = msta->vif; - memcpy(basic->peer_addr, sta->addr, ETH_ALEN); - basic->aid = cpu_to_le16(sta->aid); - basic->qos = sta->wme; + return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, false); } static void mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct ieee80211_he_cap_elem *elem = &sta->he_cap.he_cap_elem; - enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band; - const u16 *mcs_mask = msta->vif->bitrate_mask.control[band].he_mcs; + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he *he; struct tlv *tlv; u32 cap = 0; - if (!sta->he_cap.has_he) + if (!sta->deflink.he_cap.has_he) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he)); he = (struct sta_rec_he *)tlv; @@ -1375,8 +720,9 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G)) cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT; - if (mvif->cap.ldpc && (elem->phy_cap_info[1] & - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) + if (mvif->cap.he_ldpc && + (elem->phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) cap |= STA_REC_HE_CAP_LDPC; if (elem->phy_cap_info[1] & @@ -1433,22 +779,23 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, he->he_cap = cpu_to_le32(cap); - switch (sta->bandwidth) { + mcs_map = sta->deflink.he_cap.he_mcs_nss_supp; + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_160: if (elem->phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW8080], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_80p80)); mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW160], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_160)); fallthrough; default: mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW80], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_80)); break; } @@ -1479,43 +826,11 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, } static void -mt7915_mcu_sta_uapsd_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - struct ieee80211_vif *vif) -{ - struct sta_rec_uapsd *uapsd; - struct tlv *tlv; - - if (vif->type != NL80211_IFTYPE_AP || !sta->wme) - return; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_APPS, sizeof(*uapsd)); - uapsd = (struct sta_rec_uapsd *)tlv; - - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) { - uapsd->dac_map |= BIT(3); - uapsd->tac_map |= BIT(3); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) { - uapsd->dac_map |= BIT(2); - uapsd->tac_map |= BIT(2); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) { - uapsd->dac_map |= BIT(1); - uapsd->tac_map |= BIT(1); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) { - uapsd->dac_map |= BIT(0); - uapsd->tac_map |= BIT(0); - } - uapsd->max_sp = sta->max_sp; -} - -static void -mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - struct ieee80211_vif *vif) +mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + struct ieee80211_sta *sta, struct ieee80211_vif *vif) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct ieee80211_he_cap_elem *elem = &sta->he_cap.he_cap_elem; + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct sta_rec_muru *muru; struct tlv *tlv; @@ -1523,33 +838,32 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, vif->type != NL80211_IFTYPE_AP) return; - if (!sta->vht_cap.vht_supported) - return; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); muru = (struct sta_rec_muru *)tlv; muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || mvif->cap.vht_mu_ebfer || mvif->cap.vht_mu_ebfee; + if (!is_mt7915(&dev->mt76)) + muru->cfg.mimo_ul_en = true; + muru->cfg.ofdma_dl_en = true; - muru->mimo_dl.vht_mu_bfee = - !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + if (sta->deflink.vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); - if (!sta->he_cap.has_he) + if (!sta->deflink.he_cap.has_he) return; muru->mimo_dl.partial_bw_dl_mimo = HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]); - muru->cfg.mimo_ul_en = true; muru->mimo_ul.full_ul_mimo = HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]); muru->mimo_ul.partial_ul_mimo = HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]); - muru->cfg.ofdma_dl_en = true; muru->ofdma_dl.punc_pream_rx = HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); muru->ofdma_dl.he_20m_in_40m_2g = @@ -1573,10 +887,13 @@ mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) struct sta_rec_ht *ht; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); + if (!sta->deflink.ht_cap.ht_supported) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; - ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap); } static void @@ -1585,20 +902,20 @@ mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) struct sta_rec_vht *vht; struct tlv *tlv; - if (!sta->vht_cap.vht_supported) + if (!sta->deflink.vht_cap.vht_supported) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); vht = (struct sta_rec_vht *)tlv; - vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; - vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap); + vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map; } static void -mt7915_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct sta_rec_amsdu *amsdu; @@ -1608,99 +925,30 @@ mt7915_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, vif->type != NL80211_IFTYPE_AP) return; - if (!sta->max_amsdu_len) + if (!sta->deflink.agg.max_amsdu_len) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct sta_rec_amsdu *)tlv; amsdu->max_amsdu_num = 8; amsdu->amsdu_en = true; - amsdu->max_mpdu_size = sta->max_amsdu_len >= - IEEE80211_MAX_MPDU_LEN_VHT_7991; msta->wcid.amsdu = true; -} - -static void -mt7915_mcu_wtbl_smps_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - void *sta_wtbl, void *wtbl_tlv) -{ - struct wtbl_smps *smps; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), - wtbl_tlv, sta_wtbl); - smps = (struct wtbl_smps *)tlv; - smps->smps = (sta->smps_mode == IEEE80211_SMPS_DYNAMIC); -} - -static void -mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct wtbl_ht *ht = NULL; - struct tlv *tlv; - /* wtbl ht */ - if (sta->ht_cap.ht_supported) { - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), - wtbl_tlv, sta_wtbl); - ht = (struct wtbl_ht *)tlv; - ht->ldpc = mvif->cap.ldpc && - (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); - ht->af = sta->ht_cap.ampdu_factor; - ht->mm = sta->ht_cap.ampdu_density; - ht->ht = true; - } - - /* wtbl vht */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *vht; - u8 af; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), - wtbl_tlv, sta_wtbl); - vht = (struct wtbl_vht *)tlv; - vht->ldpc = mvif->cap.ldpc && - (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - vht->vht = true; - - af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->vht_cap.cap); - if (ht) - ht->af = max_t(u8, ht->af, af); - } - - mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv); -} - -static void -mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - void *sta_wtbl, void *wtbl_tlv) -{ - struct mt7915_sta *msta; - struct wtbl_hdr_trans *htr = NULL; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS, sizeof(*htr), - wtbl_tlv, sta_wtbl); - htr = (struct wtbl_hdr_trans *)tlv; - htr->no_rx_trans = true; - if (vif->type == NL80211_IFTYPE_STATION) - htr->to_ds = true; - else - htr->from_ds = true; - - if (!sta) + switch (sta->deflink.agg.max_amsdu_len) { + case IEEE80211_MAX_MPDU_LEN_VHT_11454: + if (!is_mt7915(&dev->mt76)) { + amsdu->max_mpdu_size = + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; + return; + } + fallthrough; + case IEEE80211_MAX_MPDU_LEN_HT_7935: + case IEEE80211_MAX_MPDU_LEN_VHT_7991: + amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; + return; + default: + amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; return; - - msta = (struct mt7915_sta *)sta->drv_priv; - htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); - if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) { - htr->to_ds = true; - htr->from_ds = true; } } @@ -1711,74 +959,30 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_sta *msta; struct wtbl_req_hdr *wtbl_hdr; + struct mt76_wcid *wcid; struct tlv *tlv; msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; + wcid = sta ? &msta->wcid : NULL; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, - tlv, &skb); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_RESET_AND_SET, tlv, + &skb); if (IS_ERR(wtbl_hdr)) return PTR_ERR(wtbl_hdr); - mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, tlv, wtbl_hdr); - mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, tlv, wtbl_hdr); - + mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, skb, vif, sta, tlv, + wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr); if (sta) - mt7915_mcu_wtbl_ht_tlv(skb, vif, sta, tlv, wtbl_hdr); + mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv, + wtbl_hdr, mvif->cap.ht_ldpc, + mvif->cap.vht_ldpc); return 0; } -int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, MT7915_WTBL_UPDATE_MAX_SIZE); - if (!skb) - return -ENOMEM; - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE), - true); -} - -int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct tlv *sta_wtbl; - struct sk_buff *skb; - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT7915_STA_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, - &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - static inline bool mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) @@ -1793,8 +997,8 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, if (!bfee && tx_ant < 2) return false; - if (sta->he_cap.has_he) { - struct ieee80211_he_cap_elem *pe = &sta->he_cap.he_cap_elem; + if (sta->deflink.he_cap.has_he) { + struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; if (bfee) return mvif->cap.he_su_ebfee && @@ -1804,8 +1008,8 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } - if (sta->vht_cap.vht_supported) { - u32 cap = sta->vht_cap.cap; + if (sta->deflink.vht_cap.vht_supported) { + u32 cap = sta->deflink.vht_cap.cap; if (bfee) return mvif->cap.vht_su_ebfee && @@ -1831,7 +1035,7 @@ static void mt7915_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7915_phy *phy, struct sta_rec_bf *bf) { - struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; + struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs; u8 n = 0; bf->tx_mode = MT_PHY_TYPE_HT; @@ -1856,7 +1060,7 @@ static void mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, struct sta_rec_bf *bf, bool explicit) { - struct ieee80211_sta_vht_cap *pc = &sta->vht_cap; + struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap; struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap; u16 mcs_map = le16_to_cpu(pc->vht_mcs.rx_mcs_map); u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); @@ -1877,14 +1081,14 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, bf->ncol = min_t(u8, nss_mcs, bf->nrow); bf->ibf_ncol = bf->ncol; - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) bf->nrow = 1; } else { bf->nrow = tx_ant; bf->ncol = min_t(u8, nss_mcs, bf->nrow); bf->ibf_ncol = nss_mcs; - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) bf->ibf_nrow = 1; } } @@ -1893,9 +1097,10 @@ static void mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct mt7915_phy *phy, struct sta_rec_bf *bf) { - struct ieee80211_sta_he_cap *pc = &sta->he_cap; + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; - const struct ieee80211_sta_he_cap *vc = mt7915_get_he_phy_cap(phy, vif); + const struct ieee80211_sta_he_cap *vc = + mt76_connac_get_he_phy_cap(phy->mt76, vif); const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); @@ -1917,7 +1122,7 @@ mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, bf->ncol = min_t(u8, nss_mcs, bf->nrow); bf->ibf_ncol = bf->ncol; - if (sta->bandwidth != IEEE80211_STA_RX_BW_160) + if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160) return; /* go over for 160MHz and 80p80 */ @@ -1953,8 +1158,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_phy *phy = - mvif->band_idx ? mt7915_ext_phy(dev) : &dev->phy; + struct mt7915_phy *phy = mvif->phy; int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; @@ -1966,32 +1170,35 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, }; bool ebf; + if (!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) + return; + ebf = mt7915_is_ebf_supported(phy, vif, sta, false); if (!ebf && !dev->ibf) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); bf = (struct sta_rec_bf *)tlv; /* he: eBF only, in accordance with spec * vht: support eBF and iBF * ht: iBF only, since mac80211 lacks of eBF support */ - if (sta->he_cap.has_he && ebf) + if (sta->deflink.he_cap.has_he && ebf) mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); - else if (sta->vht_cap.vht_supported) + else if (sta->deflink.vht_cap.vht_supported) mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); - else if (sta->ht_cap.ht_supported) + else if (sta->deflink.ht_cap.ht_supported) mt7915_mcu_sta_bfer_ht(sta, phy, bf); else return; bf->bf_cap = ebf ? ebf : dev->ibf << 1; - bf->bw = sta->bandwidth; - bf->ibf_dbw = sta->bandwidth; + bf->bw = sta->deflink.bandwidth; + bf->ibf_dbw = sta->deflink.bandwidth; bf->ibf_nrow = tx_ant; - if (!ebf && sta->bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) + if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) bf->ibf_timeout = 0x48; else bf->ibf_timeout = 0x18; @@ -2001,7 +1208,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, else bf->mem_20m = matrix[bf->nrow][bf->ncol]; - switch (sta->bandwidth) { + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_160: case IEEE80211_STA_RX_BW_80: bf->mem_total = bf->mem_20m * 2; @@ -2020,26 +1227,28 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_phy *phy = - mvif->band_idx ? mt7915_ext_phy(dev) : &dev->phy; + struct mt7915_phy *phy = mvif->phy; int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bfee *bfee; struct tlv *tlv; u8 nrow = 0; + if (!(sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he)) + return; + if (!mt7915_is_ebf_supported(phy, vif, sta, true)) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee)); bfee = (struct sta_rec_bfee *)tlv; - if (sta->he_cap.has_he) { - struct ieee80211_he_cap_elem *pe = &sta->he_cap.he_cap_elem; + if (sta->deflink.he_cap.has_he) { + struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; nrow = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, pe->phy_cap_info[5]); - } else if (sta->vht_cap.vht_supported) { - struct ieee80211_sta_vht_cap *pc = &sta->vht_cap; + } else if (sta->deflink.vht_cap.vht_supported) { + struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap; nrow = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK, pc->cap); @@ -2049,6 +1258,21 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2); } +static enum mcu_mmps_mode +mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode smps) +{ + switch (smps) { + case IEEE80211_SMPS_OFF: + return MCU_MMPS_DISABLE; + case IEEE80211_SMPS_STATIC: + return MCU_MMPS_STATIC; + case IEEE80211_SMPS_DYNAMIC: + return MCU_MMPS_DYNAMIC; + default: + return MCU_MMPS_DISABLE; + } +} + int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2060,13 +1284,13 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct sta_rec_ra_fixed *ra; struct sk_buff *skb; struct tlv *tlv; - int len = sizeof(struct sta_req_hdr) + sizeof(*ra); - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); - tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); ra = (struct sta_rec_ra_fixed *)tlv; switch (field) { @@ -2076,7 +1300,11 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, case RATE_PARAM_FIXED_MCS: case RATE_PARAM_FIXED_GI: case RATE_PARAM_FIXED_HE_LTF: - ra->phy = *phy; + if (phy) + ra->phy = *phy; + break; + case RATE_PARAM_MMPS_UPDATE: + ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode); break; default: break; @@ -2087,6 +1315,39 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, MCU_EXT_CMD(STA_REC_UPDATE), true); } +int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int ret; + + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, + sizeof(struct tlv)); + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); + + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(STA_REC_UPDATE), true); + if (ret) + return ret; + + return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, NULL, + RATE_PARAM_MMPS_UPDATE); +} + static int mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -2099,25 +1360,30 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, struct sta_phy phy = {}; int ret, nrates = 0; -#define __sta_phy_bitrate_mask_check(_mcs, _gi, _he) \ +#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \ do { \ u8 i, gi = mask->control[band]._gi; \ gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \ - for (i = 0; i <= sta->bandwidth; i++) { \ + for (i = 0; i <= sta->deflink.bandwidth; i++) { \ phy.sgi |= gi << (i << (_he)); \ phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\ } \ - for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) \ - nrates += hweight16(mask->control[band]._mcs[i]); \ - phy.mcs = ffs(mask->control[band]._mcs[0]) - 1; \ + for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \ + if (!mask->control[band]._mcs[i]) \ + continue; \ + nrates += hweight16(mask->control[band]._mcs[i]); \ + phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \ + if (_ht) \ + phy.mcs += 8 * i; \ + } \ } while (0) - if (sta->he_cap.has_he) { - __sta_phy_bitrate_mask_check(he_mcs, he_gi, 1); - } else if (sta->vht_cap.vht_supported) { - __sta_phy_bitrate_mask_check(vht_mcs, gi, 0); - } else if (sta->ht_cap.ht_supported) { - __sta_phy_bitrate_mask_check(ht_mcs, gi, 0); + if (sta->deflink.he_cap.has_he) { + __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1); + } else if (sta->deflink.vht_cap.vht_supported) { + __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0); + } else if (sta->deflink.ht_cap.ht_supported) { + __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0); } else { nrates = hweight32(mask->control[band].legacy); phy.mcs = ffs(mask->control[band].legacy) - 1; @@ -2150,7 +1416,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, * actual txrate hardware sends out. */ addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7); - if (sta->he_cap.has_he) + if (sta->deflink.he_cap.has_he) mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi); else mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); @@ -2177,23 +1443,25 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; + struct mt76_phy *mphy = mvif->phy->mt76; + struct cfg80211_chan_def *chandef = &mphy->chandef; struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask; enum nl80211_band band = chandef->chan->band; struct sta_rec_ra *ra; struct tlv *tlv; - u32 supp_rate = sta->supp_rates[band]; + u32 supp_rate = sta->deflink.supp_rates[band]; u32 cap = sta->wme ? STA_CAP_WMM : 0; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); ra = (struct sta_rec_ra *)tlv; ra->valid = true; ra->auto_rate = true; - ra->phy_mode = mt7915_get_phy_mode(vif, sta); + ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta); ra->channel = chandef->chan->hw_value; - ra->bw = sta->bandwidth; - ra->phy.bw = sta->bandwidth; + ra->bw = sta->deflink.bandwidth; + ra->phy.bw = sta->deflink.bandwidth; + ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode); if (supp_rate) { supp_rate &= mask->control[band].legacy; @@ -2213,22 +1481,22 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, } } - if (sta->ht_cap.ht_supported) { + if (sta->deflink.ht_cap.ht_supported) { ra->supp_mode |= MODE_HT; - ra->af = sta->ht_cap.ampdu_factor; - ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); + ra->af = sta->deflink.ht_cap.ampdu_factor; + ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); cap |= STA_CAP_HT; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) cap |= STA_CAP_SGI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) cap |= STA_CAP_SGI_40; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC) cap |= STA_CAP_TX_STBC; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (mvif->cap.ldpc && - (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) + if (mvif->cap.ht_ldpc && + (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, @@ -2236,34 +1504,38 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; } - if (sta->vht_cap.vht_supported) { + if (sta->deflink.vht_cap.vht_supported) { u8 af; ra->supp_mode |= MODE_VHT; af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->vht_cap.cap); + sta->deflink.vht_cap.cap); ra->af = max_t(u8, ra->af, af); cap |= STA_CAP_VHT; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) cap |= STA_CAP_VHT_SGI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) cap |= STA_CAP_VHT_SGI_160; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC) cap |= STA_CAP_VHT_TX_STBC; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (mvif->cap.ldpc && - (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) + if (mvif->cap.vht_ldpc && + (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mask->control[band].vht_mcs); } - if (sta->he_cap.has_he) { + if (sta->deflink.he_cap.has_he) { ra->supp_mode |= MODE_HE; cap |= STA_CAP_HE; + + if (sta->deflink.he_6ghz_capa.capa) + ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); } ra->sta_cap = cpu_to_le32(cap); @@ -2277,8 +1549,8 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *skb; int ret; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT7915_STA_UPDATE_MAX_SIZE); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2286,7 +1558,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, * once dev->rc_work changes the settings driver should also * update sta_rec_he here. */ - if (sta->he_cap.has_he && changed) + if (changed) mt7915_mcu_sta_he_tlv(skb, sta, vif); /* sta_rec_ra accommodates BW, NSS and only MCS range format @@ -2323,7 +1595,7 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif, u8 rsv1[8]; } __packed req = { .action = cpu_to_le32(MT_STA_BSS_GROUP), - .val = cpu_to_le32(mvif->idx % 16), + .val = cpu_to_le32(mvif->mt76.idx % 16), }; msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; @@ -2344,18 +1616,19 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT7915_STA_UPDATE_MAX_SIZE); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); /* starec basic */ - mt7915_mcu_sta_basic_tlv(skb, vif, sta, enable); + mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, + !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx])); if (!enable) goto out; /* tag order is in accordance with firmware dependency. */ - if (sta && sta->ht_cap.ht_supported) { + if (sta) { /* starec bfer */ mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta); /* starec ht */ @@ -2363,74 +1636,31 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, /* starec vht */ mt7915_mcu_sta_vht_tlv(skb, sta); /* starec uapsd */ - mt7915_mcu_sta_uapsd_tlv(skb, sta, vif); + mt76_connac_mcu_sta_uapsd(skb, vif, sta); } ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta); - if (ret) + if (ret) { + dev_kfree_skb(skb); return ret; + } - if (sta && sta->ht_cap.ht_supported) { + if (sta) { /* starec amsdu */ - mt7915_mcu_sta_amsdu_tlv(skb, vif, sta); + mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta); /* starec he */ mt7915_mcu_sta_he_tlv(skb, sta, vif); /* starec muru */ - mt7915_mcu_sta_muru_tlv(skb, sta, vif); + mt7915_mcu_sta_muru_tlv(dev, skb, sta, vif); /* starec bfee */ mt7915_mcu_sta_bfee_tlv(dev, skb, vif, sta); } ret = mt7915_mcu_add_group(dev, vif, sta); - if (ret) + if (ret) { + dev_kfree_skb(skb); return ret; -out: - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - -int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, - struct ieee80211_sta *sta, u32 rate) -{ - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct mt7915_vif *mvif = msta->vif; - struct sta_rec_ra_fixed *ra; - struct sk_buff *skb; - struct tlv *tlv; - int len = sizeof(struct sta_req_hdr) + sizeof(*ra); - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); - ra = (struct sta_rec_ra_fixed *)tlv; - - if (!rate) { - ra->field = cpu_to_le32(RATE_PARAM_AUTO); - goto out; } - - ra->field = cpu_to_le32(RATE_PARAM_FIXED); - ra->phy.type = FIELD_GET(RATE_CFG_PHY_TYPE, rate); - ra->phy.bw = FIELD_GET(RATE_CFG_BW, rate); - ra->phy.nss = FIELD_GET(RATE_CFG_NSS, rate); - ra->phy.mcs = FIELD_GET(RATE_CFG_MCS, rate); - ra->phy.stbc = FIELD_GET(RATE_CFG_STBC, rate); - - if (ra->phy.bw) - ra->phy.ldpc = 7; - else - ra->phy.ldpc = FIELD_GET(RATE_CFG_LDPC, rate) * 7; - - /* HT/VHT - SGI: 1, LGI: 0; HE - SGI: 0, MGI: 1, LGI: 2 */ - if (ra->phy.type > MT_PHY_TYPE_VHT) { - ra->phy.he_ltf = FIELD_GET(RATE_CFG_HE_LTF, rate) * 85; - ra->phy.sgi = FIELD_GET(RATE_CFG_GI, rate) * 85; - } else { - ra->phy.sgi = FIELD_GET(RATE_CFG_GI, rate) * 15; - } - out: return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(STA_REC_UPDATE), true); @@ -2458,8 +1688,8 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, } __packed tlv; } data = { .hdr = { - .omac_idx = mvif->omac_idx, - .dbdc_idx = mvif->band_idx, + .omac_idx = mvif->mt76.omac_idx, + .dbdc_idx = mvif->mt76.band_idx, .tlv_num = cpu_to_le16(1), .is_tlv_append = 1, }, @@ -2467,11 +1697,11 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, .tag = cpu_to_le16(DEV_INFO_ACTIVE), .len = cpu_to_le16(sizeof(struct req_tlv)), .active = enable, - .dbdc_idx = mvif->band_idx, + .dbdc_idx = mvif->mt76.band_idx, }, }; - if (mvif->omac_idx >= REPEATER_BSSID_START) + if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) return mt7915_mcu_muar_config(phy, vif, false, enable); memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); @@ -2491,7 +1721,7 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, if (!offs->cntdwn_counter_offs[0]) return; - sub_tag = vif->csa_active ? BSS_INFO_BCN_CSA : BSS_INFO_BCN_BCC; + sub_tag = vif->bss_conf.csa_active ? BSS_INFO_BCN_CSA : BSS_INFO_BCN_BCC; tlv = mt7915_mcu_add_nested_subtlv(rskb, sub_tag, sizeof(*info), &bcn->sub_ntlv, &bcn->len); info = (struct bss_info_bcn_cntdwn *)tlv; @@ -2499,6 +1729,61 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, } static void +mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, + struct ieee80211_vif *vif, struct bss_info_bcn *bcn, + struct ieee80211_mutable_offsets *offs) +{ + struct bss_info_bcn_mbss *mbss; + const struct element *elem; + struct tlv *tlv; + + if (!vif->bss_conf.bssid_indicator) + return; + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID, + sizeof(*mbss), &bcn->sub_ntlv, + &bcn->len); + + mbss = (struct bss_info_bcn_mbss *)tlv; + mbss->offset[0] = cpu_to_le16(offs->tim_offset); + mbss->bitmap = cpu_to_le32(1); + + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, + &skb->data[offs->mbssid_off], + skb->len - offs->mbssid_off) { + const struct element *sub_elem; + + if (elem->datalen < 2) + continue; + + for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) { + const struct ieee80211_bssid_index *idx; + const u8 *idx_ie; + + if (sub_elem->id || sub_elem->datalen < 4) + continue; /* not a valid BSS profile */ + + /* Find WLAN_EID_MULTI_BSSID_IDX + * in the merged nontransmitted profile + */ + idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, + sub_elem->data, + sub_elem->datalen); + if (!idx_ie || idx_ie[1] < sizeof(*idx)) + continue; + + idx = (void *)(idx_ie + 2); + if (!idx->bssid_index || idx->bssid_index > 31) + continue; + + mbss->offset[idx->bssid_index] = + cpu_to_le16(idx_ie - skb->data); + mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index)); + } + } +} + +static void mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *rskb, struct sk_buff *skb, struct bss_info_bcn *bcn, @@ -2510,6 +1795,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, u8 *buf; int len = sizeof(*cont) + MT_TXD_SIZE + skb->len; + len = (len & 0x3) ? ((len | 0x3) + 1) : len; tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT, len, &bcn->sub_ntlv, &bcn->len); @@ -2520,15 +1806,15 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, if (offs->cntdwn_counter_offs[0]) { u16 offset = offs->cntdwn_counter_offs[0]; - if (vif->csa_active) + if (vif->bss_conf.csa_active) cont->csa_ofs = cpu_to_le16(offset - 4); - if (vif->color_change_active) + if (vif->bss_conf.color_change_active) cont->bcc_ofs = cpu_to_le16(offset - 3); } buf = (u8 *)tlv + sizeof(*cont); - mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, - true); + mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL, + 0, BSS_CHANGED_BEACON); memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } @@ -2560,8 +1846,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, len); if (ie && ie[1] >= sizeof(*ht)) { ht = (void *)(ie + 2); - vc->ldpc |= !!(le16_to_cpu(ht->cap_info) & - IEEE80211_HT_CAP_LDPC_CODING); + vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) & + IEEE80211_HT_CAP_LDPC_CODING); } ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable, @@ -2572,7 +1858,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, vht = (void *)(ie + 2); bc = le32_to_cpu(vht->vht_cap_info); - vc->ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC); + vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC); vc->vht_su_ebfer = (bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) && (pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); @@ -2591,11 +1877,13 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, mgmt->u.beacon.variable, len); if (ie && ie[1] >= sizeof(*he) + 1) { const struct ieee80211_sta_he_cap *pc = - mt7915_get_he_phy_cap(phy, vif); + mt76_connac_get_he_phy_cap(phy->mt76, vif); const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; he = (void *)(ie + 3); + vc->he_ldpc = + HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]); vc->he_su_ebfer = HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); @@ -2608,10 +1896,77 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, } } -int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int en) +static void +mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct sk_buff *rskb, struct bss_info_bcn *bcn, + u32 changed) +{ +#define OFFLOAD_TX_MODE_SU BIT(0) +#define OFFLOAD_TX_MODE_MU BIT(1) + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; + enum nl80211_band band = chandef->chan->band; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct bss_info_inband_discovery *discov; + struct ieee80211_tx_info *info; + struct sk_buff *skb = NULL; + struct tlv *tlv; + bool ext_phy = phy != &dev->phy; + u8 *buf, interval; + int len; + + if (changed & BSS_CHANGED_FILS_DISCOVERY && + vif->bss_conf.fils_discovery.max_interval) { + interval = vif->bss_conf.fils_discovery.max_interval; + skb = ieee80211_get_fils_discovery_tmpl(hw, vif); + } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && + vif->bss_conf.unsol_bcast_probe_resp_interval) { + interval = vif->bss_conf.unsol_bcast_probe_resp_interval; + skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); + } + + if (!skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->control.vif = vif; + info->band = band; + + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy); + + len = sizeof(*discov) + MT_TXD_SIZE + skb->len; + len = (len & 0x3) ? ((len | 0x3) + 1) : len; + + if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) { + dev_err(dev->mt76.dev, "inband discovery size limit exceed\n"); + dev_kfree_skb(skb); + return; + } + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV, + len, &bcn->sub_ntlv, &bcn->len); + discov = (struct bss_info_inband_discovery *)tlv; + discov->tx_mode = OFFLOAD_TX_MODE_SU; + /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */ + discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); + discov->tx_interval = interval; + discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + discov->enable = true; + + buf = (u8 *)tlv + sizeof(*discov); + + mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL, + 0, changed); + memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); + + dev_kfree_skb(skb); +} + +int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int en, u32 changed) { -#define MAX_BEACON_SIZE 512 struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; @@ -2620,358 +1975,113 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct sk_buff *skb, *rskb; struct tlv *tlv; struct bss_info_bcn *bcn; - int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE; + int len = MT7915_MAX_BSS_OFFLOAD_SIZE; + bool ext_phy = phy != &dev->phy; + + if (vif->bss_conf.nontransmitted) + return 0; - rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + NULL, len); if (IS_ERR(rskb)) return PTR_ERR(rskb); - tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); + tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); bcn = (struct bss_info_bcn *)tlv; bcn->enable = en; if (!en) goto out; - skb = ieee80211_beacon_get_template(hw, vif, &offs); + skb = ieee80211_beacon_get_template(hw, vif, &offs, 0); if (!skb) return -EINVAL; - if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) { + if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) { dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); dev_kfree_skb(skb); return -EINVAL; } - if (mvif->band_idx) { - info = IEEE80211_SKB_CB(skb); - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - } + info = IEEE80211_SKB_CB(skb); + info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy); mt7915_mcu_beacon_check_caps(phy, vif, skb); - /* TODO: subtag - 11v MBSSID */ mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs); + mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs); mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); dev_kfree_skb(skb); + if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || + changed & BSS_CHANGED_FILS_DISCOVERY) + mt7915_mcu_beacon_inband_discov(dev, vif, rskb, + bcn, changed); + out: return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, MCU_EXT_CMD(BSS_INFO_UPDATE), true); } -static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, - u32 option) -{ - struct { - __le32 option; - __le32 addr; - } req = { - .option = cpu_to_le32(option), - .addr = cpu_to_le32(addr), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(FW_START_REQ), &req, - sizeof(req), true); -} - -static int mt7915_mcu_restart(struct mt76_dev *dev) -{ - struct { - u8 power_mode; - u8 rsv[3]; - } req = { - .power_mode = 1, - }; - - return mt76_mcu_send_msg(dev, MCU_CMD(NIC_POWER_CTRL), &req, - sizeof(req), false); -} - -static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) +static int mt7915_driver_own(struct mt7915_dev *dev, u8 band) { - struct { - __le32 op; - } req = { - .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(PATCH_SEM_CONTROL), &req, - sizeof(req), true); -} - -static int mt7915_mcu_start_patch(struct mt7915_dev *dev) -{ - struct { - u8 check_crc; - u8 reserved[3]; - } req = { - .check_crc = 0, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(PATCH_FINISH_REQ), &req, - sizeof(req), true); -} - -static int mt7915_driver_own(struct mt7915_dev *dev) -{ - mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_DRV_OWN); - if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND0, - MT_TOP_LPCR_HOST_FW_OWN, 0, 500)) { + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(band), MT_TOP_LPCR_HOST_DRV_OWN); + if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND(band), + MT_TOP_LPCR_HOST_FW_OWN_STAT, 0, 500)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } - return 0; -} + /* clear irq when the driver own success */ + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND_IRQ_STAT(band), + MT_TOP_LPCR_HOST_BAND_STAT); -static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, - u32 len, u32 mode) -{ - struct { - __le32 addr; - __le32 len; - __le32 mode; - } req = { - .addr = cpu_to_le32(addr), - .len = cpu_to_le32(len), - .mode = cpu_to_le32(mode), - }; - int attr; - - if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS)) - attr = MCU_CMD(PATCH_START_REQ); - else - attr = MCU_CMD(TARGET_ADDRESS_LEN_REQ); - - return mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); -} - -static int mt7915_load_patch(struct mt7915_dev *dev) -{ - const struct mt7915_patch_hdr *hdr; - const struct firmware *fw = NULL; - int i, ret, sem; - - sem = mt7915_mcu_patch_sem_ctrl(dev, 1); - switch (sem) { - case PATCH_IS_DL: - return 0; - case PATCH_NOT_DL_SEM_SUCCESS: - break; - default: - dev_err(dev->mt76.dev, "Failed to get patch semaphore\n"); - return -EAGAIN; - } - - ret = request_firmware(&fw, MT7915_ROM_PATCH, dev->mt76.dev); - if (ret) - goto out; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7915_patch_hdr *)(fw->data); - - dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", - be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); - - for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { - struct mt7915_patch_sec *sec; - const u8 *dl; - u32 len, addr; - - sec = (struct mt7915_patch_sec *)(fw->data + sizeof(*hdr) + - i * sizeof(*sec)); - if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) != - PATCH_SEC_TYPE_INFO) { - ret = -EINVAL; - goto out; - } - - addr = be32_to_cpu(sec->info.addr); - len = be32_to_cpu(sec->info.len); - dl = fw->data + be32_to_cpu(sec->offs); - - ret = mt7915_mcu_init_download(dev, addr, len, - DL_MODE_NEED_RSP); - if (ret) { - dev_err(dev->mt76.dev, "Download request failed\n"); - goto out; - } - - ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER), - dl, len, 4096); - if (ret) { - dev_err(dev->mt76.dev, "Failed to send patch\n"); - goto out; - } - } - - ret = mt7915_mcu_start_patch(dev); - if (ret) - dev_err(dev->mt76.dev, "Failed to start patch\n"); - -out: - sem = mt7915_mcu_patch_sem_ctrl(dev, 0); - switch (sem) { - case PATCH_REL_SEM_SUCCESS: - break; - default: - ret = -EAGAIN; - dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); - break; - } - release_firmware(fw); - - return ret; -} - -static u32 mt7915_mcu_gen_dl_mode(u8 feature_set, bool is_wa) -{ - u32 ret = 0; - - ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? - (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; - ret |= FIELD_PREP(DL_MODE_KEY_IDX, - FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); - ret |= DL_MODE_NEED_RSP; - ret |= is_wa ? DL_MODE_WORKING_PDA_CR4 : 0; - - return ret; + return 0; } static int -mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, - const struct mt7915_fw_trailer *hdr, - const u8 *data, bool is_wa) +mt7915_firmware_state(struct mt7915_dev *dev, bool wa) { - int i, offset = 0; - u32 override = 0, option = 0; - - for (i = 0; i < hdr->n_region; i++) { - const struct mt7915_fw_region *region; - int err; - u32 len, addr, mode; - - region = (const struct mt7915_fw_region *)((const u8 *)hdr - - (hdr->n_region - i) * sizeof(*region)); - mode = mt7915_mcu_gen_dl_mode(region->feature_set, is_wa); - len = le32_to_cpu(region->len); - addr = le32_to_cpu(region->addr); - - if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) - override = addr; - - err = mt7915_mcu_init_download(dev, addr, len, mode); - if (err) { - dev_err(dev->mt76.dev, "Download request failed\n"); - return err; - } - - err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER), - data + offset, len, 4096); - if (err) { - dev_err(dev->mt76.dev, "Failed to send firmware.\n"); - return err; - } + u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, + wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD); - offset += len; + if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, + state, 1000)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; } - - if (override) - option |= FW_START_OVERRIDE; - - if (is_wa) - option |= FW_START_WORKING_PDA_CR4; - - return mt7915_mcu_start_firmware(dev, override, option); + return 0; } -static int mt7915_load_ram(struct mt7915_dev *dev) +static int mt7915_load_firmware(struct mt7915_dev *dev) { - const struct mt7915_fw_trailer *hdr; - const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7915_FIRMWARE_WM, dev->mt76.dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size - - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, false); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); - goto out; + /* make sure fw is download state */ + if (mt7915_firmware_state(dev, false)) { + /* restart firmware once */ + __mt76_mcu_restart(&dev->mt76); + ret = mt7915_firmware_state(dev, false); + if (ret) { + dev_err(dev->mt76.dev, + "Firmware is not ready for download\n"); + return ret; + } } - release_firmware(fw); - - ret = request_firmware(&fw, MT7915_FIRMWARE_WA, dev->mt76.dev); + ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH)); if (ret) return ret; - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size - - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, true); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WA firmware\n"); - goto out; - } - - snprintf(dev->mt76.hw->wiphy->fw_version, - sizeof(dev->mt76.hw->wiphy->fw_version), - "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - -out: - release_firmware(fw); - - return ret; -} - -static int mt7915_load_firmware(struct mt7915_dev *dev) -{ - int ret; - - ret = mt7915_load_patch(dev); + ret = mt76_connac2_load_ram(&dev->mt76, fw_name_var(dev, FIRMWARE_WM), + fw_name(dev, FIRMWARE_WA)); if (ret) return ret; - ret = mt7915_load_ram(dev); + ret = mt7915_firmware_state(dev, true); if (ret) return ret; - if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, - FIELD_PREP(MT_TOP_MISC_FW_STATE, - FW_STATE_WACPU_RDY), 1000)) { - dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); - return -EIO; - } - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); dev_dbg(dev->mt76.dev, "Firmware init done\n"); @@ -3014,6 +2124,47 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) sizeof(data), false); } +int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled) +{ + struct { + __le32 cmd; + u8 enable; + } data = { + .cmd = cpu_to_le32(MURU_SET_TXC_TX_STATS_EN), + .enable = enabled, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &data, + sizeof(data), false); +} + +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) +{ + struct mt7915_dev *dev = phy->dev; + struct sk_buff *skb; + struct mt7915_mcu_muru_stats *mu_stats = + (struct mt7915_mcu_muru_stats *)ms; + int ret; + + struct { + __le32 cmd; + u8 band_idx; + } req = { + .cmd = cpu_to_le32(MURU_GET_TXC_TX_STATS), + .band_idx = phy->band_idx, + }; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + memcpy(mu_stats, skb->data, sizeof(struct mt7915_mcu_muru_stats)); + dev_kfree_skb(skb); + + return 0; +} + static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled) { struct { @@ -3086,18 +2237,29 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev) int mt7915_mcu_init(struct mt7915_dev *dev) { static const struct mt76_mcu_ops mt7915_mcu_ops = { - .headroom = sizeof(struct mt7915_mcu_txd), + .headroom = sizeof(struct mt76_connac2_mcu_txd), .mcu_skb_send_msg = mt7915_mcu_send_message, .mcu_parse_response = mt7915_mcu_parse_response, - .mcu_restart = mt7915_mcu_restart, + .mcu_restart = mt76_connac_mcu_restart, }; int ret; dev->mt76.mcu_ops = &mt7915_mcu_ops; - ret = mt7915_driver_own(dev); + /* force firmware operation mode into normal state, + * which should be set before firmware download stage. + */ + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + + ret = mt7915_driver_own(dev, 0); if (ret) return ret; + /* set driver own for band1 when two hif exist */ + if (dev->hif2) { + ret = mt7915_driver_own(dev, 1); + if (ret) + return ret; + } ret = mt7915_load_firmware(dev); if (ret) @@ -3112,6 +2274,9 @@ int mt7915_mcu_init(struct mt7915_dev *dev) if (ret) return ret; + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); + ret = mt7915_mcu_set_mwds(dev, 1); if (ret) return ret; @@ -3132,14 +2297,15 @@ int mt7915_mcu_init(struct mt7915_dev *dev) void mt7915_mcu_exit(struct mt7915_dev *dev) { __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, - FIELD_PREP(MT_TOP_MISC_FW_STATE, - FW_STATE_FW_DOWNLOAD), 1000)) { + if (mt7915_firmware_state(dev, false)) { dev_err(dev->mt76.dev, "Failed to exit mcu\n"); return; } - mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_FW_OWN); + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN); + if (dev->hif2) + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1), + MT_TOP_LPCR_HOST_FW_OWN); skb_queue_purge(&dev->mt76.mcu.res_q); } @@ -3201,42 +2367,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, &req_mac, sizeof(req_mac), true); } -int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) -{ - struct { - __le32 cmd; - u8 band; - u8 enable; - } __packed req = { - .cmd = cpu_to_le32(SCS_ENABLE), - .band = band, - .enable = enable + 1, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SCS_CTRL), &req, - sizeof(req), false); -} - -int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) -{ - struct mt7915_dev *dev = phy->dev; - struct { - u8 prot_idx; - u8 band; - u8 rsv[2]; - __le32 len_thresh; - __le32 pkt_thresh; - } __packed req = { - .prot_idx = 1, - .band = phy != &dev->phy, - .len_thresh = cpu_to_le32(val), - .pkt_thresh = cpu_to_le32(0x2), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PROTECT_CTRL), &req, - sizeof(req), true); -} - int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param) { struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param; @@ -3264,7 +2394,7 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) struct edca *e = &req.edca[ac]; e->set = WMM_PARAM_SET; - e->queue = ac + mvif->wmm_idx * MT7915_MAX_WMM_SETS; + e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS; e->aifs = q->aifs; e->txop = cpu_to_le16(q->txop); @@ -3282,58 +2412,6 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) return mt7915_mcu_update_edca(dev, &req); } -int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) -{ -#define ENTER_PM_STATE 1 -#define EXIT_PM_STATE 2 - struct { - u8 pm_number; - u8 pm_state; - u8 bssid[ETH_ALEN]; - u8 dtim_period; - u8 wlan_idx_lo; - __le16 bcn_interval; - __le32 aid; - __le32 rx_filter; - u8 band_idx; - u8 wlan_idx_hi; - u8 rsv[2]; - __le32 feature; - u8 omac_idx; - u8 wmm_idx; - u8 bcn_loss_cnt; - u8 bcn_sp_duration; - } __packed req = { - .pm_number = 5, - .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = band, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PM_STATE_CTRL), &req, - sizeof(req), true); -} - -int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, - enum mt7915_rdd_cmd cmd, u8 index, - u8 rx_sel, u8 val) -{ - struct { - u8 ctrl; - u8 rdd_idx; - u8 rdd_rx_sel; - u8 val; - u8 rsv[4]; - } __packed req = { - .ctrl = cmd, - .rdd_idx = index, - .rdd_rx_sel = rx_sel, - .val = val, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_CTRL), &req, - sizeof(req), true); -} - int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val) { struct { @@ -3432,12 +2510,109 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, sizeof(req), true); } +static int +mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy, + struct cfg80211_chan_def *chandef, + int cmd) +{ + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_channel *chan = mphy->chandef.chan; + int freq = mphy->chandef.center_freq1; + struct mt7915_mcu_background_chain_ctrl req = { + .monitor_scan_type = 2, /* simple rx */ + }; + + if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP) + return -EINVAL; + + if (!cfg80211_chandef_valid(&mphy->chandef)) + return -EINVAL; + + switch (cmd) { + case CH_SWITCH_BACKGROUND_SCAN_START: { + req.chan = chan->hw_value; + req.central_chan = ieee80211_frequency_to_channel(freq); + req.bw = mt76_connac_chan_bw(&mphy->chandef); + req.monitor_chan = chandef->chan->hw_value; + req.monitor_central_chan = + ieee80211_frequency_to_channel(chandef->center_freq1); + req.monitor_bw = mt76_connac_chan_bw(chandef); + req.band_idx = phy != &dev->phy; + req.scan_mode = 1; + break; + } + case CH_SWITCH_BACKGROUND_SCAN_RUNNING: + req.monitor_chan = chandef->chan->hw_value; + req.monitor_central_chan = + ieee80211_frequency_to_channel(chandef->center_freq1); + req.band_idx = phy != &dev->phy; + req.scan_mode = 2; + break; + case CH_SWITCH_BACKGROUND_SCAN_STOP: + req.chan = chan->hw_value; + req.central_chan = ieee80211_frequency_to_channel(freq); + req.bw = mt76_connac_chan_bw(&mphy->chandef); + req.tx_stream = hweight8(mphy->antenna_mask); + req.rx_stream = mphy->antenna_mask; + break; + default: + return -EINVAL; + } + req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL), + &req, sizeof(req), false); +} + +int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, + struct cfg80211_chan_def *chandef) +{ + struct mt7915_dev *dev = phy->dev; + int err, region; + + if (!chandef) { /* disable offchain */ + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2, + 0, 0); + if (err) + return err; + + return mt7915_mcu_background_chain_ctrl(phy, NULL, + CH_SWITCH_BACKGROUND_SCAN_STOP); + } + + err = mt7915_mcu_background_chain_ctrl(phy, chandef, + CH_SWITCH_BACKGROUND_SCAN_START); + if (err) + return err; + + switch (dev->mt76.region) { + case NL80211_DFS_ETSI: + region = 0; + break; + case NL80211_DFS_JP: + region = 2; + break; + case NL80211_DFS_FCC: + default: + region = 1; + break; + } + + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2, + 0, region); +} + int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) { + static const u8 ch_band[] = { + [NL80211_BAND_2GHZ] = 0, + [NL80211_BAND_5GHZ] = 1, + [NL80211_BAND_6GHZ] = 2, + }; struct mt7915_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1; - bool ext_phy = phy != &dev->phy; struct { u8 control_ch; u8 center_ch; @@ -3458,11 +2633,11 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) } __packed req = { .control_ch = chandef->chan->hw_value, .center_ch = ieee80211_frequency_to_channel(freq1), - .bw = mt7915_mcu_chan_bw(chandef), + .bw = mt76_connac_chan_bw(chandef), .tx_streams_num = hweight8(phy->mt76->antenna_mask), .rx_streams = phy->mt76->antenna_mask, - .band_idx = ext_phy, - .channel_band = chandef->chan->band, + .band_idx = phy->band_idx, + .channel_band = ch_band[chandef->chan->band], }; #ifdef CONFIG_NL80211_TESTMODE @@ -3473,17 +2648,18 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) req.tx_streams_num = fls(phy->mt76->test.tx_antenna_mask); req.rx_streams = phy->mt76->test.tx_antenna_mask; - if (ext_phy) { - req.tx_streams_num = 2; - req.rx_streams >>= 2; - } + if (phy != &dev->phy) + req.rx_streams >>= dev->chainshift; } #endif - if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + req.switch_reason = CH_SWITCH_NORMAL; + else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; - else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, + NL80211_IFTYPE_AP)) req.switch_reason = CH_SWITCH_DFS; else req.switch_reason = CH_SWITCH_NORMAL; @@ -3506,7 +2682,8 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) #define PAGE_IDX_MASK GENMASK(4, 2) #define PER_PAGE_SIZE 0x400 struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER }; - u8 total = DIV_ROUND_UP(MT7915_EEPROM_SIZE, PER_PAGE_SIZE); + u16 eeprom_size = mt7915_eeprom_size(dev); + u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE); u8 *eep = (u8 *)dev->mt76.eeprom.data; int eep_len; int i; @@ -3515,8 +2692,8 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) struct sk_buff *skb; int ret; - if (i == total - 1 && !!(MT7915_EEPROM_SIZE % PER_PAGE_SIZE)) - eep_len = MT7915_EEPROM_SIZE % PER_PAGE_SIZE; + if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE)) + eep_len = eeprom_size % PER_PAGE_SIZE; else eep_len = PER_PAGE_SIZE; @@ -3579,6 +2756,30 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) return 0; } +int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num) +{ + struct { + u8 _rsv; + u8 version; + u8 die_idx; + u8 _rsv2; + } __packed req = { + .version = 1, + }; + struct sk_buff *skb; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_FREE_BLOCK), &req, + sizeof(req), true, &skb); + if (ret) + return ret; + + *block_num = *(u8 *)skb->data; + dev_kfree_skb(skb); + + return 0; +} + static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx, u8 *data, u32 len, int cmd) { @@ -3725,19 +2926,26 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy) int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) { /* strict order */ - static const enum mt7915_chan_mib_offs offs[] = { - MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME + static const u32 offs[] = { + MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME, + MIB_BUSY_TIME_V2, MIB_TX_TIME_V2, MIB_RX_TIME_V2, + MIB_OBSS_AIRTIME_V2 }; struct mt76_channel_state *state = phy->mt76->chan_state; struct mt76_channel_state *state_ts = &phy->state_ts; struct mt7915_dev *dev = phy->dev; struct mt7915_mcu_mib *res, req[4]; struct sk_buff *skb; - int i, ret; + int i, ret, start = 0, ofs = 20; + + if (!is_mt7915(&dev->mt76)) { + start = 4; + ofs = 0; + } for (i = 0; i < 4; i++) { req[i].band = cpu_to_le32(phy != &dev->phy); - req[i].offs = cpu_to_le32(offs[i]); + req[i].offs = cpu_to_le32(offs[i + start]); } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO), @@ -3745,7 +2953,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) if (ret) return ret; - res = (struct mt7915_mcu_mib *)(skb->data + 20); + res = (struct mt7915_mcu_mib *)(skb->data + ofs); if (chan_switch) goto out; @@ -3797,7 +3005,7 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state) u8 rsv[2]; } __packed req = { .ctrl = { - .band_idx = phy != &dev->phy, + .band_idx = phy->band_idx, }, }; int level; @@ -3854,11 +3062,11 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy) struct mt76_power_limits limits_array; s8 *la = (s8 *)&limits_array; int i, idx, n_chains = hweight8(mphy->antenna_mask); - int tx_power; - - tx_power = hw->conf.power_level * 2 - - mt76_tx_power_nss_delta(n_chains); + int tx_power = hw->conf.power_level * 2; + tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, + tx_power); + tx_power -= mt76_tx_power_nss_delta(n_chains); tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, &limits_array, tx_power); mphy->txpower_cur = tx_power; @@ -4045,7 +3253,7 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, } __packed req = { .action = MT_SPR_ENABLE, .arg_num = 1, - .band_idx = mvif->band_idx, + .band_idx = mvif->mt76.band_idx, .val = cpu_to_le32(enable), }; @@ -4066,7 +3274,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, __le16 wcid; } __packed req = { .category = MCU_PHY_STATE_CONTENTION_RX_RATE, - .band = mvif->band_idx, + .band = mvif->mt76.band_idx, .wcid = cpu_to_le16(msta->wcid.idx), }; struct ieee80211_supported_band *sband; @@ -4092,6 +3300,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, case MT_PHY_TYPE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; @@ -4165,11 +3375,13 @@ int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vi struct sk_buff *skb; struct tlv *tlv; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + NULL, len); if (IS_ERR(skb)) return PTR_ERR(skb); - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR, sizeof(*bss_color)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR, + sizeof(*bss_color)); bss_color = (struct bss_info_color *)tlv; bss_color->disable = !he_bss_color->enabled; bss_color->color = he_bss_color->color; @@ -4206,11 +3418,11 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev, } __packed req = { .tbl_idx = flow->table_id, .cmd = cmd, - .own_mac_idx = mvif->omac_idx, + .own_mac_idx = mvif->mt76.omac_idx, .flowid = flow->id, .peer_id = cpu_to_le16(flow->wcid), .duration = flow->duration, - .bss_idx = mvif->idx, + .bss_idx = mvif->mt76.idx, .start_tsf = cpu_to_le64(flow->tsf), .mantissa = flow->mantissa, .exponent = flow->exp, @@ -4227,3 +3439,32 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev, return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE), &req, sizeof(req), true); } + +int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) +{ + struct { + __le32 idx; + __le32 ofs; + __le32 data; + } __packed req = { + .idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 28))), + .ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(27, 0))), + .data = set ? cpu_to_le32(*val) : 0, + }; + struct sk_buff *skb; + int ret; + + if (set) + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS), + &req, sizeof(req), false); + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + *val = le32_to_cpu(*(__le32 *)(skb->data + 8)); + dev_kfree_skb(skb); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 1f5a64ba9b59..cd1edf553fc1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -4,47 +4,7 @@ #ifndef __MT7915_MCU_H #define __MT7915_MCU_H -struct mt7915_mcu_txd { - __le32 txd[8]; - - __le16 len; - __le16 pq_id; - - u8 cid; - u8 pkt_type; - u8 set_query; /* FW don't care */ - u8 seq; - - u8 uc_d2b0_rev; - u8 ext_cid; - u8 s2d_index; - u8 ext_cid_ack; - - u32 reserved[5]; -} __packed __aligned(4); - -/* event table */ -enum { - MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, - MCU_EVENT_FW_START = 0x01, - MCU_EVENT_GENERIC = 0x01, - MCU_EVENT_ACCESS_REG = 0x02, - MCU_EVENT_MT_PATCH_SEM = 0x04, - MCU_EVENT_CH_PRIVILEGE = 0x18, - MCU_EVENT_EXT = 0xed, - MCU_EVENT_RESTART_DL = 0xef, -}; - -/* ext event table */ -enum { - MCU_EXT_EVENT_PS_SYNC = 0x5, - MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, - MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, - MCU_EXT_EVENT_ASSERT_DUMP = 0x23, - MCU_EXT_EVENT_RDD_REPORT = 0x3a, - MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, - MCU_EXT_EVENT_BCC_NOTIFY = 0x75, -}; +#include "../mt76_connac_mcu.h" enum { MCU_ATE_SET_TRX = 0x1, @@ -53,21 +13,6 @@ enum { MCU_ATE_CLEAN_TXQUEUE = 0x1c, }; -struct mt7915_mcu_rxd { - __le32 rxd[6]; - - __le16 len; - __le16 pkt_type_id; - - u8 eid; - u8 seq; - __le16 __rsv; - - u8 ext_eid; - u8 __rsv1[2]; - u8 s2d_index; -}; - struct mt7915_mcu_thermal_ctrl { u8 ctrl_id; u8 band_idx; @@ -84,7 +29,7 @@ struct mt7915_mcu_thermal_ctrl { } __packed; struct mt7915_mcu_thermal_notify { - struct mt7915_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd rxd; struct mt7915_mcu_thermal_ctrl ctrl; __le32 temperature; @@ -92,7 +37,7 @@ struct mt7915_mcu_thermal_notify { } __packed; struct mt7915_mcu_csa_notify { - struct mt7915_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd rxd; u8 omac_idx; u8 csa_count; @@ -100,8 +45,17 @@ struct mt7915_mcu_csa_notify { u8 rsv; } __packed; +struct mt7915_mcu_bcc_notify { + struct mt76_connac2_mcu_rxd rxd; + + u8 band_idx; + u8 omac_idx; + u8 cca_count; + u8 rsv; +} __packed; + struct mt7915_mcu_rdd_report { - struct mt7915_mcu_rxd rxd; + struct mt76_connac2_mcu_rxd rxd; u8 band_idx; u8 long_detected; @@ -152,6 +106,29 @@ struct mt7915_mcu_rdd_report { } hw_pulse[32]; } __packed; +struct mt7915_mcu_background_chain_ctrl { + u8 chan; /* primary channel */ + u8 central_chan; /* central channel */ + u8 bw; + u8 tx_stream; + u8 rx_stream; + + u8 monitor_chan; /* monitor channel */ + u8 monitor_central_chan;/* monitor central channel */ + u8 monitor_bw; + u8 monitor_tx_stream; + u8 monitor_rx_stream; + + u8 scan_mode; /* 0: ScanStop + * 1: ScanStart + * 2: ScanRunning + */ + u8 band_idx; /* DBDC */ + u8 monitor_scan_type; + u8 band; /* 0: 2.4GHz, 1: 5GHz */ + u8 rsv[2]; +} __packed; + struct mt7915_mcu_eeprom { u8 buffer_mode; u8 format; @@ -182,10 +159,16 @@ struct mt7915_mcu_mib { } __packed; enum mt7915_chan_mib_offs { + /* mt7915 */ MIB_BUSY_TIME = 14, MIB_TX_TIME = 81, MIB_RX_TIME, - MIB_OBSS_AIRTIME = 86 + MIB_OBSS_AIRTIME = 86, + /* mt7916 */ + MIB_BUSY_TIME_V2 = 0, + MIB_TX_TIME_V2 = 6, + MIB_RX_TIME_V2 = 8, + MIB_OBSS_AIRTIME_V2 = 490 }; struct edca { @@ -206,93 +189,56 @@ struct mt7915_mcu_tx { struct edca edca[IEEE80211_NUM_ACS]; } __packed; +struct mt7915_mcu_muru_stats { + __le32 event_id; + struct { + __le32 cck_cnt; + __le32 ofdm_cnt; + __le32 htmix_cnt; + __le32 htgf_cnt; + __le32 vht_su_cnt; + __le32 vht_2mu_cnt; + __le32 vht_3mu_cnt; + __le32 vht_4mu_cnt; + __le32 he_su_cnt; + __le32 he_ext_su_cnt; + __le32 he_2ru_cnt; + __le32 he_2mu_cnt; + __le32 he_3ru_cnt; + __le32 he_3mu_cnt; + __le32 he_4ru_cnt; + __le32 he_4mu_cnt; + __le32 he_5to8ru_cnt; + __le32 he_9to16ru_cnt; + __le32 he_gtr16ru_cnt; + } dl; + + struct { + __le32 hetrig_su_cnt; + __le32 hetrig_2ru_cnt; + __le32 hetrig_3ru_cnt; + __le32 hetrig_4ru_cnt; + __le32 hetrig_5to8ru_cnt; + __le32 hetrig_9to16ru_cnt; + __le32 hetrig_gtr16ru_cnt; + __le32 hetrig_2mu_cnt; + __le32 hetrig_3mu_cnt; + __le32 hetrig_4mu_cnt; + } ul; +}; + #define WMM_AIFS_SET BIT(0) #define WMM_CW_MIN_SET BIT(1) #define WMM_CW_MAX_SET BIT(2) #define WMM_TXOP_SET BIT(3) #define WMM_PARAM_SET GENMASK(3, 0) -#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) -#define MCU_PKT_ID 0xa0 - -enum { - MCU_Q_QUERY, - MCU_Q_SET, - MCU_Q_RESERVED, - MCU_Q_NA -}; - -enum { - MCU_S2D_H2N, - MCU_S2D_C2N, - MCU_S2D_H2C, - MCU_S2D_H2CN -}; - enum { MCU_FW_LOG_WM, MCU_FW_LOG_WA, MCU_FW_LOG_TO_HOST, }; -#define __MCU_CMD_FIELD_ID GENMASK(7, 0) -#define __MCU_CMD_FIELD_EXT_ID GENMASK(15, 8) -#define __MCU_CMD_FIELD_QUERY BIT(16) -#define __MCU_CMD_FIELD_WA BIT(17) - -enum { - MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, - MCU_CMD_FW_START_REQ = 0x02, - MCU_CMD_INIT_ACCESS_REG = 0x3, - MCU_CMD_NIC_POWER_CTRL = 0x4, - MCU_CMD_PATCH_START_REQ = 0x05, - MCU_CMD_PATCH_FINISH_REQ = 0x07, - MCU_CMD_PATCH_SEM_CONTROL = 0x10, - MCU_CMD_WA_PARAM = 0xC4, - MCU_CMD_EXT_CID = 0xED, - MCU_CMD_FW_SCATTER = 0xEE, - MCU_CMD_RESTART_DL_REQ = 0xEF, -}; - -enum { - MCU_EXT_CMD_EFUSE_ACCESS = 0x01, - MCU_EXT_CMD_RF_TEST = 0x04, - MCU_EXT_CMD_PM_STATE_CTRL = 0x07, - MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, - MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, - MCU_EXT_CMD_TXBF_ACTION = 0x1e, - MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, - MCU_EXT_CMD_THERMAL_PROT = 0x23, - MCU_EXT_CMD_STA_REC_UPDATE = 0x25, - MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, - MCU_EXT_CMD_EDCA_UPDATE = 0x27, - MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, - MCU_EXT_CMD_THERMAL_CTRL = 0x2c, - MCU_EXT_CMD_WTBL_UPDATE = 0x32, - MCU_EXT_CMD_SET_DRR_CTRL = 0x36, - MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, - MCU_EXT_CMD_ATE_CTRL = 0x3d, - MCU_EXT_CMD_PROTECT_CTRL = 0x3e, - MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, - MCU_EXT_CMD_RX_HDR_TRANS = 0x47, - MCU_EXT_CMD_MUAR_UPDATE = 0x48, - MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a, - MCU_EXT_CMD_SET_RX_PATH = 0x4e, - MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, - MCU_EXT_CMD_GET_MIB_INFO = 0x5a, - MCU_EXT_CMD_MWDS_SUPPORT = 0x80, - MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, - MCU_EXT_CMD_SCS_CTRL = 0x82, - MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94, - MCU_EXT_CMD_FW_DBG_CTRL = 0x95, - MCU_EXT_CMD_SET_RDD_TH = 0x9d, - MCU_EXT_CMD_MURU_CTRL = 0x9f, - MCU_EXT_CMD_SET_SPR = 0xa8, - MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, - MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, - MCU_EXT_CMD_PHY_STAT_INFO = 0xad, -}; - enum { MCU_TWT_AGRT_ADD, MCU_TWT_AGRT_MODIFY, @@ -314,164 +260,13 @@ enum { MCU_WA_PARAM_RED = 0x0e, }; -#define MCU_CMD(_t) FIELD_PREP(__MCU_CMD_FIELD_ID, MCU_CMD_##_t) -#define MCU_EXT_CMD(_t) (MCU_CMD(EXT_CID) | \ - FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \ - MCU_EXT_CMD_##_t)) -#define MCU_EXT_QUERY(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_QUERY) - -#define MCU_WA_CMD(_t) (MCU_CMD(_t) | __MCU_CMD_FIELD_WA) -#define MCU_WA_EXT_CMD(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_WA) -#define MCU_WA_PARAM_CMD(_t) (MCU_WA_CMD(WA_PARAM) | \ - FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \ - MCU_WA_PARAM_CMD_##_t)) - -enum { - PATCH_SEM_RELEASE, - PATCH_SEM_GET -}; - -enum { - PATCH_NOT_DL_SEM_FAIL, - PATCH_IS_DL, - PATCH_NOT_DL_SEM_SUCCESS, - PATCH_REL_SEM_SUCCESS -}; - -enum { - FW_STATE_INITIAL, - FW_STATE_FW_DOWNLOAD, - FW_STATE_NORMAL_OPERATION, - FW_STATE_NORMAL_TRX, - FW_STATE_WACPU_RDY = 7 -}; - -enum { - EE_MODE_EFUSE, - EE_MODE_BUFFER, -}; - -enum { - EE_FORMAT_BIN, - EE_FORMAT_WHOLE, - EE_FORMAT_MULTIPLE, -}; - -enum { - MCU_PHY_STATE_TX_RATE, - MCU_PHY_STATE_RX_RATE, - MCU_PHY_STATE_RSSI, - MCU_PHY_STATE_CONTENTION_RX_RATE, - MCU_PHY_STATE_OFDMLQ_CNINFO, +enum mcu_mmps_mode { + MCU_MMPS_STATIC, + MCU_MMPS_DYNAMIC, + MCU_MMPS_RSV, + MCU_MMPS_DISABLE, }; -#define STA_TYPE_STA BIT(0) -#define STA_TYPE_AP BIT(1) -#define STA_TYPE_ADHOC BIT(2) -#define STA_TYPE_WDS BIT(4) -#define STA_TYPE_BC BIT(5) - -#define NETWORK_INFRA BIT(16) -#define NETWORK_P2P BIT(17) -#define NETWORK_IBSS BIT(18) -#define NETWORK_WDS BIT(21) - -#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) -#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) -#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) -#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P) -#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) -#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) -#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) - -#define CONN_STATE_DISCONNECT 0 -#define CONN_STATE_CONNECT 1 -#define CONN_STATE_PORT_SECURE 2 - -enum { - DEV_INFO_ACTIVE, - DEV_INFO_MAX_NUM -}; - -enum { - SCS_SEND_DATA, - SCS_SET_MANUAL_PD_TH, - SCS_CONFIG, - SCS_ENABLE, - SCS_SHOW_INFO, - SCS_GET_GLO_ADDR, - SCS_GET_GLO_ADDR_EVENT, -}; - -enum { - CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20, - CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40, - CMD_CBW_80MHZ = IEEE80211_STA_RX_BW_80, - CMD_CBW_160MHZ = IEEE80211_STA_RX_BW_160, - CMD_CBW_10MHZ, - CMD_CBW_5MHZ, - CMD_CBW_8080MHZ, - - CMD_HE_MCS_BW80 = 0, - CMD_HE_MCS_BW160, - CMD_HE_MCS_BW8080, - CMD_HE_MCS_BW_NUM -}; - -struct tlv { - __le16 tag; - __le16 len; -} __packed; - -struct bss_info_omac { - __le16 tag; - __le16 len; - u8 hw_bss_idx; - u8 omac_idx; - u8 band_idx; - u8 rsv0; - __le32 conn_type; - u32 rsv1; -} __packed; - -struct bss_info_basic { - __le16 tag; - __le16 len; - __le32 network_type; - u8 active; - u8 rsv0; - __le16 bcn_interval; - u8 bssid[ETH_ALEN]; - u8 wmm_idx; - u8 dtim_period; - u8 bmc_wcid_lo; - u8 cipher; - u8 phy_mode; - u8 max_bssid; /* max BSSID. range: 1 ~ 8, 0: MBSSID disabled */ - u8 non_tx_bssid;/* non-transmitted BSSID, 0: transmitted BSSID */ - u8 bmc_wcid_hi; /* high Byte and version */ - u8 rsv[2]; -} __packed; - -struct bss_info_rf_ch { - __le16 tag; - __le16 len; - u8 pri_ch; - u8 center_ch0; - u8 center_ch1; - u8 bw; - u8 he_ru26_block; /* 1: don't send HETB in RU26, 0: allow */ - u8 he_all_disable; /* 1: disallow all HETB, 0: allow */ - u8 rsv[2]; -} __packed; - -struct bss_info_ext_bss { - __le16 tag; - __le16 len; - __le32 mbss_tsf_offset; /* in unit of us */ - u8 rsv[8]; -} __packed; - struct bss_info_bmc_rate { __le16 tag; __le16 len; @@ -572,394 +367,29 @@ struct bss_info_bcn_cont { __le16 pkt_len; } __packed __aligned(4); +struct bss_info_inband_discovery { + __le16 tag; + __le16 len; + u8 tx_type; + u8 tx_mode; + u8 tx_interval; + u8 enable; + __le16 rsv; + __le16 prob_rsp_len; +} __packed __aligned(4); + enum { BSS_INFO_BCN_CSA, BSS_INFO_BCN_BCC, BSS_INFO_BCN_MBSSID, BSS_INFO_BCN_CONTENT, + BSS_INFO_BCN_DISCOV, BSS_INFO_BCN_MAX }; enum { - BSS_INFO_OMAC, - BSS_INFO_BASIC, - BSS_INFO_RF_CH, /* optional, for BT/LTE coex */ - BSS_INFO_PM, /* sta only */ - BSS_INFO_UAPSD, /* sta only */ - BSS_INFO_ROAM_DETECT, /* obsoleted */ - BSS_INFO_LQ_RM, /* obsoleted */ - BSS_INFO_EXT_BSS, - BSS_INFO_BMC_RATE, /* for bmc rate control in CR4 */ - BSS_INFO_SYNC_MODE, /* obsoleted */ - BSS_INFO_RA, - BSS_INFO_HW_AMSDU, - BSS_INFO_BSS_COLOR, - BSS_INFO_HE_BASIC, - BSS_INFO_PROTECT_INFO, - BSS_INFO_OFFLOAD, - BSS_INFO_11V_MBSSID, - BSS_INFO_MAX_NUM -}; - -enum { - WTBL_RESET_AND_SET = 1, - WTBL_SET, - WTBL_QUERY, - WTBL_RESET_ALL -}; - -struct wtbl_req_hdr { - u8 wlan_idx_lo; - u8 operation; - __le16 tlv_num; - u8 wlan_idx_hi; - u8 rsv[3]; -} __packed; - -struct wtbl_generic { - __le16 tag; - __le16 len; - u8 peer_addr[ETH_ALEN]; - u8 muar_idx; - u8 skip_tx; - u8 cf_ack; - u8 qos; - u8 mesh; - u8 adm; - __le16 partial_aid; - u8 baf_en; - u8 aad_om; -} __packed; - -struct wtbl_rx { - __le16 tag; - __le16 len; - u8 rcid; - u8 rca1; - u8 rca2; - u8 rv; - u8 rsv[4]; -} __packed; - -struct wtbl_ht { - __le16 tag; - __le16 len; - u8 ht; - u8 ldpc; - u8 af; - u8 mm; - u8 rsv[4]; -} __packed; - -struct wtbl_vht { - __le16 tag; - __le16 len; - u8 ldpc; - u8 dyn_bw; - u8 vht; - u8 txop_ps; - u8 rsv[4]; -} __packed; - -struct wtbl_hdr_trans { - __le16 tag; - __le16 len; - u8 to_ds; - u8 from_ds; - u8 no_rx_trans; - u8 _rsv; -}; - -enum { - MT_BA_TYPE_INVALID, - MT_BA_TYPE_ORIGINATOR, - MT_BA_TYPE_RECIPIENT -}; - -enum { - RST_BA_MAC_TID_MATCH, - RST_BA_MAC_MATCH, - RST_BA_NO_MATCH -}; - -struct wtbl_ba { - __le16 tag; - __le16 len; - /* common */ - u8 tid; - u8 ba_type; - u8 rsv0[2]; - /* originator only */ - __le16 sn; - u8 ba_en; - u8 ba_winsize_idx; - /* originator & recipient */ - __le16 ba_winsize; - /* recipient only */ - u8 peer_addr[ETH_ALEN]; - u8 rst_ba_tid; - u8 rst_ba_sel; - u8 rst_ba_sb; - u8 band_idx; - u8 rsv1[4]; -} __packed; - -struct wtbl_smps { - __le16 tag; - __le16 len; - u8 smps; - u8 rsv[3]; -} __packed; - -enum { - WTBL_GENERIC, - WTBL_RX, - WTBL_HT, - WTBL_VHT, - WTBL_PEER_PS, /* not used */ - WTBL_TX_PS, - WTBL_HDR_TRANS, - WTBL_SEC_KEY, - WTBL_BA, - WTBL_RDG, /* obsoleted */ - WTBL_PROTECT, /* not used */ - WTBL_CLEAR, /* not used */ - WTBL_BF, - WTBL_SMPS, - WTBL_RAW_DATA, /* debug only */ - WTBL_PN, - WTBL_SPE, - WTBL_MAX_NUM -}; - -struct sta_ntlv_hdr { - u8 rsv[2]; - __le16 tlv_num; -} __packed; - -struct sta_req_hdr { - u8 bss_idx; - u8 wlan_idx_lo; - __le16 tlv_num; - u8 is_tlv_append; - u8 muar_idx; - u8 wlan_idx_hi; - u8 rsv; -} __packed; - -struct sta_rec_basic { - __le16 tag; - __le16 len; - __le32 conn_type; - u8 conn_state; - u8 qos; - __le16 aid; - u8 peer_addr[ETH_ALEN]; - __le16 extra_info; -} __packed; - -struct sta_rec_ht { - __le16 tag; - __le16 len; - __le16 ht_cap; - u16 rsv; -} __packed; - -struct sta_rec_vht { - __le16 tag; - __le16 len; - __le32 vht_cap; - __le16 vht_rx_mcs_map; - __le16 vht_tx_mcs_map; - u8 rts_bw_sig; - u8 rsv[3]; -} __packed; - -struct sta_rec_uapsd { - __le16 tag; - __le16 len; - u8 dac_map; - u8 tac_map; - u8 max_sp; - u8 rsv0; - __le16 listen_interval; - u8 rsv1[2]; -} __packed; - -struct sta_rec_muru { - __le16 tag; - __le16 len; - - struct { - bool ofdma_dl_en; - bool ofdma_ul_en; - bool mimo_dl_en; - bool mimo_ul_en; - u8 rsv[4]; - } cfg; - - struct { - u8 punc_pream_rx; - bool he_20m_in_40m_2g; - bool he_20m_in_160m; - bool he_80m_in_160m; - bool lt16_sigb; - bool rx_su_comp_sigb; - bool rx_su_non_comp_sigb; - u8 rsv; - } ofdma_dl; - - struct { - u8 t_frame_dur; - u8 mu_cascading; - u8 uo_ra; - u8 he_2x996_tone; - u8 rx_t_frame_11ac; - u8 rsv[3]; - } ofdma_ul; - - struct { - bool vht_mu_bfee; - bool partial_bw_dl_mimo; - u8 rsv[2]; - } mimo_dl; - - struct { - bool full_ul_mimo; - bool partial_ul_mimo; - u8 rsv[2]; - } mimo_ul; -} __packed; - -struct sta_rec_he { - __le16 tag; - __le16 len; - - __le32 he_cap; - - u8 t_frame_dur; - u8 max_ampdu_exp; - u8 bw_set; - u8 device_class; - u8 dcm_tx_mode; - u8 dcm_tx_max_nss; - u8 dcm_rx_mode; - u8 dcm_rx_max_nss; - u8 dcm_max_ru; - u8 punc_pream_rx; - u8 pkt_ext; - u8 rsv1; - - __le16 max_nss_mcs[CMD_HE_MCS_BW_NUM]; - - u8 rsv2[2]; -} __packed; - -struct sta_rec_ba { - __le16 tag; - __le16 len; - u8 tid; - u8 ba_type; - u8 amsdu; - u8 ba_en; - __le16 ssn; - __le16 winsize; -} __packed; - -struct sta_rec_amsdu { - __le16 tag; - __le16 len; - u8 max_amsdu_num; - u8 max_mpdu_size; - u8 amsdu_en; - u8 rsv; -} __packed; - -struct sec_key { - u8 cipher_id; - u8 cipher_len; - u8 key_id; - u8 key_len; - u8 key[32]; -} __packed; - -struct sta_rec_sec { - __le16 tag; - __le16 len; - u8 add; - u8 n_cipher; - u8 rsv[2]; - - struct sec_key key[2]; -} __packed; - -struct sta_phy { - u8 type; - u8 flag; - u8 stbc; - u8 sgi; - u8 bw; - u8 ldpc; - u8 mcs; - u8 nss; - u8 he_ltf; -}; - -struct sta_rec_ra { - __le16 tag; - __le16 len; - - u8 valid; - u8 auto_rate; - u8 phy_mode; - u8 channel; - u8 bw; - u8 disable_cck; - u8 ht_mcs32; - u8 ht_gf; - u8 ht_mcs[4]; - u8 mmps_mode; - u8 gband_256; - u8 af; - u8 auth_wapi_mode; - u8 rate_len; - - u8 supp_mode; - u8 supp_cck_rate; - u8 supp_ofdm_rate; - __le32 supp_ht_mcs; - __le16 supp_vht_mcs[4]; - - u8 op_mode; - u8 op_vht_chan_width; - u8 op_vht_rx_nss; - u8 op_vht_rx_nss_type; - - __le32 sta_cap; - - struct sta_phy phy; -} __packed; - -struct sta_rec_ra_fixed { - __le16 tag; - __le16 len; - - __le32 field; - u8 op_mode; - u8 op_vht_chan_width; - u8 op_vht_rx_nss; - u8 op_vht_rx_nss_type; - - struct sta_phy phy; - - u8 spe_en; - u8 short_preamble; - u8 is_5g; - u8 mmps_mode; -} __packed; - -enum { RATE_PARAM_FIXED = 3, + RATE_PARAM_MMPS_UPDATE = 5, RATE_PARAM_FIXED_HE_LTF = 7, RATE_PARAM_FIXED_MCS, RATE_PARAM_FIXED_GI = 11, @@ -975,120 +405,6 @@ enum { #define RATE_CFG_PHY_TYPE GENMASK(27, 24) #define RATE_CFG_HE_LTF GENMASK(31, 28) -struct sta_rec_bf { - __le16 tag; - __le16 len; - - __le16 pfmu; /* 0xffff: no access right for PFMU */ - bool su_mu; /* 0: SU, 1: MU */ - u8 bf_cap; /* 0: iBF, 1: eBF */ - u8 sounding_phy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ - u8 ndpa_rate; - u8 ndp_rate; - u8 rept_poll_rate; - u8 tx_mode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT ... */ - u8 ncol; - u8 nrow; - u8 bw; /* 0: 20M, 1: 40M, 2: 80M, 3: 160M */ - - u8 mem_total; - u8 mem_20m; - struct { - u8 row; - u8 col: 6, row_msb: 2; - } mem[4]; - - __le16 smart_ant; - u8 se_idx; - u8 auto_sounding; /* b7: low traffic indicator - * b6: Stop sounding for this entry - * b5 ~ b0: postpone sounding - */ - u8 ibf_timeout; - u8 ibf_dbw; - u8 ibf_ncol; - u8 ibf_nrow; - u8 nrow_bw160; - u8 ncol_bw160; - u8 ru_start_idx; - u8 ru_end_idx; - - bool trigger_su; - bool trigger_mu; - bool ng16_su; - bool ng16_mu; - bool codebook42_su; - bool codebook75_mu; - - u8 he_ltf; - u8 rsv[3]; -} __packed; - -struct sta_rec_bfee { - __le16 tag; - __le16 len; - bool fb_identity_matrix; /* 1: feedback identity matrix */ - bool ignore_feedback; /* 1: ignore */ - u8 rsv[2]; -} __packed; - -enum { - STA_REC_BASIC, - STA_REC_RA, - STA_REC_RA_CMM_INFO, - STA_REC_RA_UPDATE, - STA_REC_BF, - STA_REC_AMSDU, - STA_REC_BA, - STA_REC_RED, /* not used */ - STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */ - STA_REC_HT, - STA_REC_VHT, - STA_REC_APPS, - STA_REC_KEY, - STA_REC_WTBL, - STA_REC_HE, - STA_REC_HW_AMSDU, - STA_REC_WTBL_AADOM, - STA_REC_KEY_V2, - STA_REC_MURU, - STA_REC_MUEDCA, - STA_REC_BFEE, - STA_REC_MAX_NUM -}; - -enum mcu_cipher_type { - MCU_CIPHER_NONE = 0, - MCU_CIPHER_WEP40, - MCU_CIPHER_WEP104, - MCU_CIPHER_WEP128, - MCU_CIPHER_TKIP, - MCU_CIPHER_AES_CCMP, - MCU_CIPHER_CCMP_256, - MCU_CIPHER_GCMP, - MCU_CIPHER_GCMP_256, - MCU_CIPHER_WAPI, - MCU_CIPHER_BIP_CMAC_128, -}; - -enum { - CH_SWITCH_NORMAL = 0, - CH_SWITCH_SCAN = 3, - CH_SWITCH_MCC = 4, - CH_SWITCH_DFS = 5, - CH_SWITCH_BACKGROUND_SCAN_START = 6, - CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, - CH_SWITCH_BACKGROUND_SCAN_STOP = 8, - CH_SWITCH_SCAN_BYPASS_DPD = 9 -}; - -enum { - THERMAL_SENSOR_TEMP_QUERY, - THERMAL_SENSOR_MANUAL_CTRL, - THERMAL_SENSOR_INFO_QUERY, - THERMAL_SENSOR_TASK_CTRL, -}; - enum { THERMAL_PROTECT_PARAMETER_CTRL, THERMAL_PROTECT_BASIC_INFO, @@ -1116,28 +432,31 @@ enum { MURU_PLATFORM_TYPE_PERF_LEVEL_2, }; -#define MT7915_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_generic) + \ - sizeof(struct wtbl_rx) + \ - sizeof(struct wtbl_ht) + \ - sizeof(struct wtbl_vht) + \ - sizeof(struct wtbl_hdr_trans) +\ - sizeof(struct wtbl_ba) + \ - sizeof(struct wtbl_smps)) +/* tx cmd tx statistics */ +enum { + MURU_SET_TXC_TX_STATS_EN = 150, + MURU_GET_TXC_TX_STATS = 151, +}; + +enum { + SER_QUERY, + /* recovery */ + SER_SET_RECOVER_L1, + SER_SET_RECOVER_L2, + SER_SET_RECOVER_L3_RX_ABORT, + SER_SET_RECOVER_L3_TX_ABORT, + SER_SET_RECOVER_L3_TX_DISABLE, + SER_SET_RECOVER_L3_BF, + /* action */ + SER_ENABLE = 2, + SER_RECOVER +}; -#define MT7915_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ - sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_bf) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_he) + \ - sizeof(struct sta_rec_ba) + \ - sizeof(struct sta_rec_vht) + \ - sizeof(struct sta_rec_uapsd) + \ - sizeof(struct sta_rec_amsdu) + \ - sizeof(struct sta_rec_muru) + \ - sizeof(struct sta_rec_bfee) + \ - sizeof(struct tlv) + \ - MT7915_WTBL_UPDATE_MAX_SIZE) +#define MT7915_MAX_BEACON_SIZE 512 +#define MT7915_MAX_INBAND_FRAME_SIZE 256 +#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \ + MT7915_MAX_INBAND_FRAME_SIZE + \ + MT7915_BEACON_UPDATE_SIZE) #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct bss_info_omac) + \ @@ -1152,64 +471,7 @@ enum { #define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct bss_info_bcn_cntdwn) + \ sizeof(struct bss_info_bcn_mbss) + \ - sizeof(struct bss_info_bcn_cont)) - -#define PHY_MODE_A BIT(0) -#define PHY_MODE_B BIT(1) -#define PHY_MODE_G BIT(2) -#define PHY_MODE_GN BIT(3) -#define PHY_MODE_AN BIT(4) -#define PHY_MODE_AC BIT(5) -#define PHY_MODE_AX_24G BIT(6) -#define PHY_MODE_AX_5G BIT(7) -#define PHY_MODE_AX_6G BIT(8) - -#define MODE_CCK BIT(0) -#define MODE_OFDM BIT(1) -#define MODE_HT BIT(2) -#define MODE_VHT BIT(3) -#define MODE_HE BIT(4) - -#define STA_CAP_WMM BIT(0) -#define STA_CAP_SGI_20 BIT(4) -#define STA_CAP_SGI_40 BIT(5) -#define STA_CAP_TX_STBC BIT(6) -#define STA_CAP_RX_STBC BIT(7) -#define STA_CAP_VHT_SGI_80 BIT(16) -#define STA_CAP_VHT_SGI_160 BIT(17) -#define STA_CAP_VHT_TX_STBC BIT(18) -#define STA_CAP_VHT_RX_STBC BIT(19) -#define STA_CAP_VHT_LDPC BIT(23) -#define STA_CAP_LDPC BIT(24) -#define STA_CAP_HT BIT(26) -#define STA_CAP_VHT BIT(27) -#define STA_CAP_HE BIT(28) - -/* HE MAC */ -#define STA_REC_HE_CAP_HTC BIT(0) -#define STA_REC_HE_CAP_BQR BIT(1) -#define STA_REC_HE_CAP_BSR BIT(2) -#define STA_REC_HE_CAP_OM BIT(3) -#define STA_REC_HE_CAP_AMSDU_IN_AMPDU BIT(4) -/* HE PHY */ -#define STA_REC_HE_CAP_DUAL_BAND BIT(5) -#define STA_REC_HE_CAP_LDPC BIT(6) -#define STA_REC_HE_CAP_TRIG_CQI_FK BIT(7) -#define STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE BIT(8) -/* STBC */ -#define STA_REC_HE_CAP_LE_EQ_80M_TX_STBC BIT(9) -#define STA_REC_HE_CAP_LE_EQ_80M_RX_STBC BIT(10) -#define STA_REC_HE_CAP_GT_80M_TX_STBC BIT(11) -#define STA_REC_HE_CAP_GT_80M_RX_STBC BIT(12) -/* GI */ -#define STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI BIT(13) -#define STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI BIT(14) -#define STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI BIT(15) -#define STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI BIT(16) -#define STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI BIT(17) -/* 242 TONE */ -#define STA_REC_HE_CAP_BW20_RU242_SUPPORT BIT(18) -#define STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242 BIT(19) -#define STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242 BIT(20) + sizeof(struct bss_info_bcn_cont) + \ + sizeof(struct bss_info_inband_discovery)) #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 1f6ba306c850..7bd5f6725d7b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -1,103 +1,450 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pci.h> + #include "mt7915.h" +#include "mac.h" +#include "../trace.h" + +static const u32 mt7915_reg[] = { + [INT_SOURCE_CSR] = 0xd7010, + [INT_MASK_CSR] = 0xd7014, + [INT1_SOURCE_CSR] = 0xd7088, + [INT1_MASK_CSR] = 0xd708c, + [INT_MCU_CMD_SOURCE] = 0xd51f0, + [INT_MCU_CMD_EVENT] = 0x3108, + [WFDMA0_ADDR] = 0xd4000, + [WFDMA0_PCIE1_ADDR] = 0xd8000, + [WFDMA_EXT_CSR_ADDR] = 0xd7000, + [CBTOP1_PHY_END] = 0x77ffffff, + [INFRA_MCU_ADDR_END] = 0x7c3fffff, + [FW_EXCEPTION_ADDR] = 0x219848, + [SWDEF_BASE_ADDR] = 0x41f200, +}; + +static const u32 mt7916_reg[] = { + [INT_SOURCE_CSR] = 0xd4200, + [INT_MASK_CSR] = 0xd4204, + [INT1_SOURCE_CSR] = 0xd8200, + [INT1_MASK_CSR] = 0xd8204, + [INT_MCU_CMD_SOURCE] = 0xd41f0, + [INT_MCU_CMD_EVENT] = 0x2108, + [WFDMA0_ADDR] = 0xd4000, + [WFDMA0_PCIE1_ADDR] = 0xd8000, + [WFDMA_EXT_CSR_ADDR] = 0xd7000, + [CBTOP1_PHY_END] = 0x7fffffff, + [INFRA_MCU_ADDR_END] = 0x7c085fff, + [FW_EXCEPTION_ADDR] = 0x022050bc, + [SWDEF_BASE_ADDR] = 0x411400, +}; + +static const u32 mt7986_reg[] = { + [INT_SOURCE_CSR] = 0x24200, + [INT_MASK_CSR] = 0x24204, + [INT1_SOURCE_CSR] = 0x28200, + [INT1_MASK_CSR] = 0x28204, + [INT_MCU_CMD_SOURCE] = 0x241f0, + [INT_MCU_CMD_EVENT] = 0x54000108, + [WFDMA0_ADDR] = 0x24000, + [WFDMA0_PCIE1_ADDR] = 0x28000, + [WFDMA_EXT_CSR_ADDR] = 0x27000, + [CBTOP1_PHY_END] = 0x7fffffff, + [INFRA_MCU_ADDR_END] = 0x7c085fff, + [FW_EXCEPTION_ADDR] = 0x02204ffc, + [SWDEF_BASE_ADDR] = 0x411400, +}; + +static const u32 mt7915_offs[] = { + [TMAC_CDTR] = 0x090, + [TMAC_ODTR] = 0x094, + [TMAC_ATCR] = 0x098, + [TMAC_TRCR0] = 0x09c, + [TMAC_ICR0] = 0x0a4, + [TMAC_ICR1] = 0x0b4, + [TMAC_CTCR0] = 0x0f4, + [TMAC_TFCR0] = 0x1e0, + [MDP_BNRCFR0] = 0x070, + [MDP_BNRCFR1] = 0x074, + [ARB_DRNGR0] = 0x194, + [ARB_SCR] = 0x080, + [RMAC_MIB_AIRTIME14] = 0x3b8, + [AGG_AWSCR0] = 0x05c, + [AGG_PCR0] = 0x06c, + [AGG_ACR0] = 0x084, + [AGG_ACR4] = 0x08c, + [AGG_MRCR] = 0x098, + [AGG_ATCR1] = 0x0f0, + [AGG_ATCR3] = 0x0f4, + [LPON_UTTR0] = 0x080, + [LPON_UTTR1] = 0x084, + [LPON_FRCR] = 0x314, + [MIB_SDR3] = 0x014, + [MIB_SDR4] = 0x018, + [MIB_SDR5] = 0x01c, + [MIB_SDR7] = 0x024, + [MIB_SDR8] = 0x028, + [MIB_SDR9] = 0x02c, + [MIB_SDR10] = 0x030, + [MIB_SDR11] = 0x034, + [MIB_SDR12] = 0x038, + [MIB_SDR13] = 0x03c, + [MIB_SDR14] = 0x040, + [MIB_SDR15] = 0x044, + [MIB_SDR16] = 0x048, + [MIB_SDR17] = 0x04c, + [MIB_SDR18] = 0x050, + [MIB_SDR19] = 0x054, + [MIB_SDR20] = 0x058, + [MIB_SDR21] = 0x05c, + [MIB_SDR22] = 0x060, + [MIB_SDR23] = 0x064, + [MIB_SDR24] = 0x068, + [MIB_SDR25] = 0x06c, + [MIB_SDR27] = 0x074, + [MIB_SDR28] = 0x078, + [MIB_SDR29] = 0x07c, + [MIB_SDRVEC] = 0x080, + [MIB_SDR31] = 0x084, + [MIB_SDR32] = 0x088, + [MIB_SDRMUBF] = 0x090, + [MIB_DR8] = 0x0c0, + [MIB_DR9] = 0x0c4, + [MIB_DR11] = 0x0cc, + [MIB_MB_SDR0] = 0x100, + [MIB_MB_SDR1] = 0x104, + [TX_AGG_CNT] = 0x0a8, + [TX_AGG_CNT2] = 0x164, + [MIB_ARNG] = 0x4b8, + [WTBLON_TOP_WDUCR] = 0x0, + [WTBL_UPDATE] = 0x030, + [PLE_FL_Q_EMPTY] = 0x0b0, + [PLE_FL_Q_CTRL] = 0x1b0, + [PLE_AC_QEMPTY] = 0x500, + [PLE_FREEPG_CNT] = 0x100, + [PLE_FREEPG_HEAD_TAIL] = 0x104, + [PLE_PG_HIF_GROUP] = 0x110, + [PLE_HIF_PG_INFO] = 0x114, + [AC_OFFSET] = 0x040, + [ETBF_PAR_RPT0] = 0x068, +}; + +static const u32 mt7916_offs[] = { + [TMAC_CDTR] = 0x0c8, + [TMAC_ODTR] = 0x0cc, + [TMAC_ATCR] = 0x00c, + [TMAC_TRCR0] = 0x010, + [TMAC_ICR0] = 0x014, + [TMAC_ICR1] = 0x018, + [TMAC_CTCR0] = 0x114, + [TMAC_TFCR0] = 0x0e4, + [MDP_BNRCFR0] = 0x090, + [MDP_BNRCFR1] = 0x094, + [ARB_DRNGR0] = 0x1e0, + [ARB_SCR] = 0x000, + [RMAC_MIB_AIRTIME14] = 0x0398, + [AGG_AWSCR0] = 0x030, + [AGG_PCR0] = 0x040, + [AGG_ACR0] = 0x054, + [AGG_ACR4] = 0x05c, + [AGG_MRCR] = 0x068, + [AGG_ATCR1] = 0x1a8, + [AGG_ATCR3] = 0x080, + [LPON_UTTR0] = 0x360, + [LPON_UTTR1] = 0x364, + [LPON_FRCR] = 0x37c, + [MIB_SDR3] = 0x698, + [MIB_SDR4] = 0x788, + [MIB_SDR5] = 0x780, + [MIB_SDR7] = 0x5a8, + [MIB_SDR8] = 0x78c, + [MIB_SDR9] = 0x024, + [MIB_SDR10] = 0x76c, + [MIB_SDR11] = 0x790, + [MIB_SDR12] = 0x558, + [MIB_SDR13] = 0x560, + [MIB_SDR14] = 0x564, + [MIB_SDR15] = 0x568, + [MIB_SDR16] = 0x7fc, + [MIB_SDR17] = 0x800, + [MIB_SDR18] = 0x030, + [MIB_SDR19] = 0x5ac, + [MIB_SDR20] = 0x5b0, + [MIB_SDR21] = 0x5b4, + [MIB_SDR22] = 0x770, + [MIB_SDR23] = 0x774, + [MIB_SDR24] = 0x778, + [MIB_SDR25] = 0x77c, + [MIB_SDR27] = 0x080, + [MIB_SDR28] = 0x084, + [MIB_SDR29] = 0x650, + [MIB_SDRVEC] = 0x5a8, + [MIB_SDR31] = 0x55c, + [MIB_SDR32] = 0x7a8, + [MIB_SDRMUBF] = 0x7ac, + [MIB_DR8] = 0x56c, + [MIB_DR9] = 0x570, + [MIB_DR11] = 0x574, + [MIB_MB_SDR0] = 0x688, + [MIB_MB_SDR1] = 0x690, + [TX_AGG_CNT] = 0x7dc, + [TX_AGG_CNT2] = 0x7ec, + [MIB_ARNG] = 0x0b0, + [WTBLON_TOP_WDUCR] = 0x200, + [WTBL_UPDATE] = 0x230, + [PLE_FL_Q_EMPTY] = 0x360, + [PLE_FL_Q_CTRL] = 0x3e0, + [PLE_AC_QEMPTY] = 0x600, + [PLE_FREEPG_CNT] = 0x380, + [PLE_FREEPG_HEAD_TAIL] = 0x384, + [PLE_PG_HIF_GROUP] = 0x00c, + [PLE_HIF_PG_INFO] = 0x388, + [AC_OFFSET] = 0x080, + [ETBF_PAR_RPT0] = 0x100, +}; + +static const struct mt76_connac_reg_map mt7915_reg_map[] = { + { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */ + { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure regs) */ + { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */ + { 0x54000000, 0x02000, 0x01000 }, /* WFDMA PCIE0 MCU DMA0 */ + { 0x55000000, 0x03000, 0x01000 }, /* WFDMA PCIE0 MCU DMA1 */ + { 0x58000000, 0x06000, 0x01000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + { 0x59000000, 0x07000, 0x01000 }, /* WFDMA PCIE1 MCU DMA1 */ + { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ + { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ + { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ + { 0x820c0000, 0x08000, 0x04000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x0c000, 0x02000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x0e000, 0x02000 }, /* WF_UMAC_TOP (PP) */ + { 0x820ce000, 0x21c00, 0x00200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820cf000, 0x22000, 0x01000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x820e0000, 0x20000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x20400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e2000, 0x20800, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x20c00, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e4000, 0x21000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e5000, 0x21400, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x820e7000, 0x21e00, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820e9000, 0x23400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x24000, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820eb000, 0x24200, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820ec000, 0x24600, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820ed000, 0x24800, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820f0000, 0xa0000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0xa0600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0xa0800, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0xa0c00, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0xa1000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0xa1400, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0xa1e00, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0xa3400, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0xa4000, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0xa4200, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0xa4600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0xa4800, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + { 0x0, 0x0, 0x0 }, /* imply end of search */ +}; + +static const struct mt76_connac_reg_map mt7916_reg_map[] = { + { 0x54000000, 0x02000, 0x01000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */ + { 0x55000000, 0x03000, 0x01000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */ + { 0x56000000, 0x04000, 0x01000 }, /* WFDMA_2 (Reserved) */ + { 0x57000000, 0x05000, 0x01000 }, /* WFDMA_3 (MCU wrap CR) */ + { 0x58000000, 0x06000, 0x01000 }, /* WFDMA_4 (PCIE1 MCU DMA0) */ + { 0x59000000, 0x07000, 0x01000 }, /* WFDMA_5 (PCIE1 MCU DMA1) */ + { 0x820c0000, 0x08000, 0x04000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x0c000, 0x02000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x0e000, 0x02000 }, /* WF_UMAC_TOP (PP) */ + { 0x820e0000, 0x20000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x20400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e2000, 0x20800, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x20c00, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e4000, 0x21000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e5000, 0x21400, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x820ce000, 0x21c00, 0x00200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820e7000, 0x21e00, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820cf000, 0x22000, 0x01000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820e9000, 0x23400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x24000, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820eb000, 0x24200, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820ec000, 0x24600, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820ed000, 0x24800, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820ca000, 0x26000, 0x02000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */ + { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure cr) */ + { 0x820f0000, 0xa0000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0xa0600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0xa0800, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0xa0c00, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0xa1000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0xa1400, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0xa1e00, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0xa3400, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0xa4000, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0xa4200, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0xa4600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0xa4800, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + { 0x820c4000, 0xa8000, 0x01000 }, /* WF_LMAC_TOP (WF_UWTBL ) */ + { 0x820b0000, 0xae000, 0x01000 }, /* [APB2] WFSYS_ON */ + { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ + { 0x0, 0x0, 0x0 }, /* imply end of search */ +}; + +static const struct mt76_connac_reg_map mt7986_reg_map[] = { + { 0x54000000, 0x402000, 0x01000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */ + { 0x55000000, 0x403000, 0x01000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */ + { 0x56000000, 0x404000, 0x01000 }, /* WFDMA_2 (Reserved) */ + { 0x57000000, 0x405000, 0x01000 }, /* WFDMA_3 (MCU wrap CR) */ + { 0x58000000, 0x406000, 0x01000 }, /* WFDMA_4 (PCIE1 MCU DMA0) */ + { 0x59000000, 0x407000, 0x01000 }, /* WFDMA_5 (PCIE1 MCU DMA1) */ + { 0x820c0000, 0x408000, 0x04000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x40c000, 0x02000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x40e000, 0x02000 }, /* WF_UMAC_TOP (PP) */ + { 0x820e0000, 0x420000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x420400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e2000, 0x420800, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x420c00, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e4000, 0x421000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e5000, 0x421400, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x820ce000, 0x421c00, 0x00200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820e7000, 0x421e00, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820cf000, 0x422000, 0x01000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820e9000, 0x423400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x424000, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820eb000, 0x424200, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820ec000, 0x424600, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820ed000, 0x424800, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820ca000, 0x426000, 0x02000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + { 0x820d0000, 0x430000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x00400000, 0x480000, 0x10000 }, /* WF_MCU_SYSRAM */ + { 0x00410000, 0x490000, 0x10000 }, /* WF_MCU_SYSRAM */ + { 0x820f0000, 0x4a0000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0x4a0600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0x4a0800, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0x4a0c00, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0x4a1000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0x4a1400, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0x4a1e00, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0x4a3400, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0x4a4000, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0x4a4200, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0x4a4600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0x4a4800, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + { 0x820c4000, 0x4a8000, 0x01000 }, /* WF_LMAC_TOP (WF_UWTBL ) */ + { 0x820b0000, 0x4ae000, 0x01000 }, /* [APB2] WFSYS_ON */ + { 0x80020000, 0x4b0000, 0x10000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0x4c0000, 0x10000 }, /* WF_TOP_MISC_ON */ + { 0x89000000, 0x4d0000, 0x01000 }, /* WF_MCU_CFG_ON */ + { 0x89010000, 0x4d1000, 0x01000 }, /* WF_MCU_CIRQ */ + { 0x89020000, 0x4d2000, 0x01000 }, /* WF_MCU_GPT */ + { 0x89030000, 0x4d3000, 0x01000 }, /* WF_MCU_WDT */ + { 0x80010000, 0x4d4000, 0x01000 }, /* WF_AXIDMA */ + { 0x0, 0x0, 0x0 }, /* imply end of search */ +}; static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) { u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); + u32 l1_remap; + + if (is_mt7986(&dev->mt76)) + return MT_CONN_INFRA_OFFSET(addr); - mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base); + l1_remap = is_mt7915(&dev->mt76) ? + MT_HIF_REMAP_L1 : MT_HIF_REMAP_L1_MT7916; + + dev->bus_ops->rmw(&dev->mt76, l1_remap, + MT_HIF_REMAP_L1_MASK, + FIELD_PREP(MT_HIF_REMAP_L1_MASK, base)); /* use read to push write */ - mt76_rr(dev, MT_HIF_REMAP_L1); + dev->bus_ops->rr(&dev->mt76, l1_remap); return MT_HIF_REMAP_BASE_L1 + offset; } static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) { - u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); - u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + u32 offset, base; - mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base); - /* use read to push write */ - mt76_rr(dev, MT_HIF_REMAP_L2); + if (is_mt7915(&dev->mt76)) { + offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); + base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2, + MT_HIF_REMAP_L2_MASK, + FIELD_PREP(MT_HIF_REMAP_L2_MASK, base)); - return MT_HIF_REMAP_BASE_L2 + offset; + /* use read to push write */ + dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2); + } else { + u32 ofs = is_mt7986(&dev->mt76) ? 0x400000 : 0; + + offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_MT7916, addr); + base = FIELD_GET(MT_HIF_REMAP_L2_BASE_MT7916, addr); + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2_MT7916 + ofs, + MT_HIF_REMAP_L2_MASK_MT7916, + FIELD_PREP(MT_HIF_REMAP_L2_MASK_MT7916, base)); + + /* use read to push write */ + dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2_MT7916 + ofs); + + offset += (MT_HIF_REMAP_BASE_L2_MT7916 + ofs); + } + + return offset; } static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr) { - static const struct { - u32 phys; - u32 mapped; - u32 size; - } fixed_map[] = { - { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */ - { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure regs) */ - { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */ - { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */ - { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */ - { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ - { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */ - { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ - { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ - { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ - { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ - { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */ - { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */ - { 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */ - { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */ - { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */ - { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ - { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ - { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ - { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ - { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ - { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ - { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ - { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ - { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ - { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ - { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ - { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ - { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ - { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ - { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ - { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ - { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ - { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ - { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ - { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ - { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ - { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ - { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ - { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ - { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ - }; int i; if (addr < 0x100000) return addr; - for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { + if (!dev->reg.map) { + dev_err(dev->mt76.dev, "err: reg_map is null\n"); + return addr; + } + + for (i = 0; i < dev->reg.map_size; i++) { u32 ofs; - if (addr < fixed_map[i].phys) + if (addr < dev->reg.map[i].phys) continue; - ofs = addr - fixed_map[i].phys; - if (ofs > fixed_map[i].size) + ofs = addr - dev->reg.map[i].phys; + if (ofs > dev->reg.map[i].size) continue; - return fixed_map[i].mapped + ofs; + return dev->reg.map[i].maps + ofs; } - if ((addr >= 0x18000000 && addr < 0x18c00000) || - (addr >= 0x70000000 && addr < 0x78000000)) + if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) || + (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) || + (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END)) return mt7915_reg_map_l1(dev, addr); + if (dev_is_pci(dev->mt76.dev) && + ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || + (addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END))) + return mt7915_reg_map_l1(dev, addr); + + /* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */ + if (addr >= MT_INFRA_MCU_START && addr <= MT_INFRA_MCU_END) { + addr = addr - MT_INFRA_MCU_START + MT_INFRA_BASE; + return mt7915_reg_map_l1(dev, addr); + } + return mt7915_reg_map_l2(dev, addr); } @@ -125,7 +472,9 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) return dev->bus_ops->rmw(mdev, addr, mask, val); } -int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq) +static int mt7915_mmio_init(struct mt76_dev *mdev, + void __iomem *mem_base, + u32 device_id) { struct mt76_bus_ops *bus_ops; struct mt7915_dev *dev; @@ -133,6 +482,29 @@ int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq) dev = container_of(mdev, struct mt7915_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); + switch (device_id) { + case 0x7915: + dev->reg.reg_rev = mt7915_reg; + dev->reg.offs_rev = mt7915_offs; + dev->reg.map = mt7915_reg_map; + dev->reg.map_size = ARRAY_SIZE(mt7915_reg_map); + break; + case 0x7906: + dev->reg.reg_rev = mt7916_reg; + dev->reg.offs_rev = mt7916_offs; + dev->reg.map = mt7916_reg_map; + dev->reg.map_size = ARRAY_SIZE(mt7916_reg_map); + break; + case 0x7986: + dev->reg.reg_rev = mt7986_reg; + dev->reg.offs_rev = mt7916_offs; + dev->reg.map = mt7986_reg_map; + dev->reg.map_size = ARRAY_SIZE(mt7986_reg_map); + break; + default: + return -EINVAL; + } + dev->bus_ops = dev->mt76.bus; bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), GFP_KERNEL); @@ -144,11 +516,214 @@ int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq) bus_ops->rmw = mt7915_rmw; dev->mt76.bus = bus_ops; - mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + mdev->rev = (device_id << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - mt76_wr(dev, MT_INT_MASK_CSR, 0); + return 0; +} + +void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, + bool write_reg, + u32 clear, u32 set) +{ + struct mt76_dev *mdev = &dev->mt76; + unsigned long flags; + + spin_lock_irqsave(&mdev->mmio.irq_lock, flags); + + mdev->mmio.irqmask &= ~clear; + mdev->mmio.irqmask |= set; + + if (write_reg) { + mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask); + mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask); + } + + spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags); +} + +static void mt7915_rx_poll_complete(struct mt76_dev *mdev, + enum mt76_rxq_id q) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + + mt7915_irq_enable(dev, MT_INT_RX(q)); +} + +/* TODO: support 2/4/6/8 MSI-X vectors */ +static void mt7915_irq_tasklet(struct tasklet_struct *t) +{ + struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + u32 intr, intr1, mask; + + 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); + } else { + mt76_wr(dev, MT_INT_MASK_CSR, 0); + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + intr &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + } + + if (dev->hif2) { + intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); + intr1 &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1); + + intr |= intr1; + } + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + mask = intr & MT_INT_RX_DONE_ALL; + if (intr & MT_INT_TX_DONE_MCU) + mask |= MT_INT_TX_DONE_MCU; + + mt7915_irq_disable(dev, mask); + + if (intr & MT_INT_TX_DONE_MCU) + napi_schedule(&dev->mt76.tx_napi); + + if (intr & MT_INT_RX(MT_RXQ_MAIN)) + napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); + + if (intr & MT_INT_RX(MT_RXQ_BAND1)) + napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1]); + + if (intr & MT_INT_RX(MT_RXQ_MCU)) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); + + if (intr & MT_INT_RX(MT_RXQ_MCU_WA)) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); + + if (!is_mt7915(&dev->mt76) && + (intr & MT_INT_RX(MT_RXQ_MAIN_WA))) + napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN_WA]); + + if (intr & MT_INT_RX(MT_RXQ_BAND1_WA)) + napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1_WA]); + + if (intr & MT_INT_MCU_CMD) { + u32 val = mt76_rr(dev, MT_MCU_CMD); + + mt76_wr(dev, MT_MCU_CMD, val); + if (val & MT_MCU_CMD_ERROR_MASK) { + dev->reset_state = val; + queue_work(dev->mt76.wq, &dev->reset_work); + wake_up(&dev->reset_wait); + } + } +} + +irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) +{ + struct mt7915_dev *dev = dev_instance; + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + + if (mtk_wed_device_active(wed)) { + mtk_wed_device_irq_set_mask(wed, 0); + } else { + mt76_wr(dev, MT_INT_MASK_CSR, 0); + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + } + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + tasklet_schedule(&dev->irq_tasklet); + + return IRQ_HANDLED; +} + +struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, + void __iomem *mem_base, u32 device_id) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp), + .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .token_size = MT7915_TOKEN_SIZE, + .tx_prepare_skb = mt7915_tx_prepare_skb, + .tx_complete_skb = mt76_connac_tx_complete_skb, + .rx_skb = mt7915_queue_rx_skb, + .rx_check = mt7915_rx_check, + .rx_poll_complete = mt7915_rx_poll_complete, + .sta_ps = mt7915_sta_ps, + .sta_add = mt7915_mac_sta_add, + .sta_remove = mt7915_mac_sta_remove, + .update_survey = mt7915_update_channel, + }; + struct mt7915_dev *dev; + struct mt76_dev *mdev; + int ret; + + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7915_ops, &drv_ops); + if (!mdev) + return ERR_PTR(-ENOMEM); + + dev = container_of(mdev, struct mt7915_dev, mt76); + + ret = mt7915_mmio_init(mdev, mem_base, device_id); + if (ret) + goto error; + + tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet); + + return dev; + +error: + mt76_free_device(&dev->mt76); + + return ERR_PTR(ret); +} + +static int __init mt7915_init(void) +{ + int ret; + + ret = pci_register_driver(&mt7915_hif_driver); + if (ret) + return ret; + + ret = pci_register_driver(&mt7915_pci_driver); + if (ret) + goto error_pci; + + if (IS_ENABLED(CONFIG_MT7986_WMAC)) { + ret = platform_driver_register(&mt7986_wmac_driver); + if (ret) + goto error_wmac; + } return 0; + +error_wmac: + pci_unregister_driver(&mt7915_pci_driver); +error_pci: + pci_unregister_driver(&mt7915_hif_driver); + + return ret; +} + +static void __exit mt7915_exit(void) +{ + if (IS_ENABLED(CONFIG_MT7986_WMAC)) + platform_driver_unregister(&mt7986_wmac_driver); + + pci_unregister_driver(&mt7915_pci_driver); + pci_unregister_driver(&mt7915_hif_driver); } + +module_init(mt7915_init); +module_exit(mt7915_exit); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index e69b4c8974ee..1eb11617a625 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -6,13 +6,13 @@ #include <linux/interrupt.h> #include <linux/ktime.h> -#include "../mt76.h" +#include "../mt76_connac.h" #include "regs.h" #define MT7915_MAX_INTERFACES 19 -#define MT7915_MAX_WMM_SETS 4 #define MT7915_WTBL_SIZE 288 -#define MT7915_WTBL_RESERVED (MT7915_WTBL_SIZE - 1) +#define MT7916_WTBL_SIZE 544 +#define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1) #define MT7915_WTBL_STA (MT7915_WTBL_RESERVED - \ MT7915_MAX_INTERFACES) @@ -30,7 +30,28 @@ #define MT7915_FIRMWARE_WM "mediatek/mt7915_wm.bin" #define MT7915_ROM_PATCH "mediatek/mt7915_rom_patch.bin" +#define MT7916_FIRMWARE_WA "mediatek/mt7916_wa.bin" +#define MT7916_FIRMWARE_WM "mediatek/mt7916_wm.bin" +#define MT7916_ROM_PATCH "mediatek/mt7916_rom_patch.bin" + +#define MT7986_FIRMWARE_WA "mediatek/mt7986_wa.bin" +#define MT7986_FIRMWARE_WM "mediatek/mt7986_wm.bin" +#define MT7986_FIRMWARE_WM_MT7975 "mediatek/mt7986_wm_mt7975.bin" +#define MT7986_ROM_PATCH "mediatek/mt7986_rom_patch.bin" +#define MT7986_ROM_PATCH_MT7975 "mediatek/mt7986_rom_patch_mt7975.bin" + +#define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin" +#define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin" +#define MT7916_EEPROM_DEFAULT "mediatek/mt7916_eeprom.bin" +#define MT7986_EEPROM_MT7975_DEFAULT "mediatek/mt7986_eeprom_mt7975.bin" +#define MT7986_EEPROM_MT7975_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7975_dual.bin" +#define MT7986_EEPROM_MT7976_DEFAULT "mediatek/mt7986_eeprom_mt7976.bin" +#define MT7986_EEPROM_MT7976_DEFAULT_DBDC "mediatek/mt7986_eeprom_mt7976_dbdc.bin" +#define MT7986_EEPROM_MT7976_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7976_dual.bin" + #define MT7915_EEPROM_SIZE 3584 +#define MT7916_EEPROM_SIZE 4096 + #define MT7915_EEPROM_BLOCK_SIZE 16 #define MT7915_TOKEN_SIZE 8192 @@ -38,11 +59,14 @@ #define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ #define MT7915_THERMAL_THROTTLE_MAX 100 +#define MT7915_CDEV_THROTTLE_MAX 99 #define MT7915_SKU_RATE_NUM 161 #define MT7915_MAX_TWT_AGRT 16 #define MT7915_MAX_STA_TWT_AGRT 8 +#define MT7915_MIN_TWT_DUR 64 +#define MT7915_MAX_QUEUE (MT_RXQ_BAND2 + __MT_MCUQ_MAX + 2) struct mt7915_vif; struct mt7915_sta; @@ -65,9 +89,13 @@ enum mt7915_rxq_id { MT7915_RXQ_MCU_WA_EXT, }; -struct mt7915_sta_key_conf { - s8 keyidx; - u8 key[16]; +enum mt7916_rxq_id { + MT7916_RXQ_MCU_WM = 0, + MT7916_RXQ_MCU_WA, + MT7916_RXQ_MCU_WA_MAIN, + MT7916_RXQ_MCU_WA_EXT, + MT7916_RXQ_BAND0, + MT7916_RXQ_BAND1, }; struct mt7915_twt_flow { @@ -99,9 +127,7 @@ struct mt7915_sta { unsigned long jiffies; unsigned long ampdu_state; - struct mt76_sta_stats stats; - - struct mt7915_sta_key_conf bip; + struct mt76_connac_sta_key_conf bip; struct { u8 flowid_mask; @@ -110,7 +136,9 @@ struct mt7915_sta { }; struct mt7915_vif_cap { - bool ldpc:1; + bool ht_ldpc:1; + bool vht_ldpc:1; + bool he_ldpc:1; bool vht_su_ebfer:1; bool vht_su_ebfee:1; bool vht_mu_ebfer:1; @@ -121,10 +149,7 @@ struct mt7915_vif_cap { }; struct mt7915_vif { - u16 idx; - u8 omac_idx; - u8 band_idx; - u8 wmm_idx; + struct mt76_vif mt76; /* must be first */ struct mt7915_vif_cap cap; struct mt7915_sta sta; @@ -172,8 +197,15 @@ struct mib_stats { /* rx stats */ u32 rx_fifo_full_cnt; u32 channel_idle_cnt; + u32 primary_cca_busy_time; + u32 secondary_cca_busy_time; + u32 primary_energy_detect_time; + u32 cck_mdrdy_time; + u32 ofdm_mdrdy_time; + u32 green_mdrdy_time; u32 rx_vector_mismatch_cnt; u32 rx_delimiter_fail_cnt; + u32 rx_mrdy_cnt; u32 rx_len_mismatch_cnt; u32 rx_mpdu_cnt; u32 rx_ampdu_cnt; @@ -200,16 +232,18 @@ struct mt7915_phy { struct mt76_phy *mt76; struct mt7915_dev *dev; - struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES]; + struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; struct ieee80211_vif *monitor_vif; struct thermal_cooling_device *cdev; + u8 cdev_state; u8 throttle_state; u32 throttle_temp[2]; /* 0: critical high, 1: maximum */ u32 rxfilter; u64 omac_mask; + u8 band_idx; u16 noise; @@ -217,7 +251,8 @@ struct mt7915_phy { u8 slottime; u8 rdd_state; - int dfs_state; + + u32 trb_ts; u32 rx_ampdu_ts; u32 ampdu_ref; @@ -247,12 +282,21 @@ struct mt7915_dev { }; struct mt7915_hif *hif2; + struct mt7915_reg_desc reg; + u8 q_id[MT7915_MAX_QUEUE]; + u32 q_int_mask[MT7915_MAX_QUEUE]; + u32 wfdma_mask; const struct mt76_bus_ops *bus_ops; struct tasklet_struct irq_tasklet; struct mt7915_phy phy; + /* monitor rx chain configured channel */ + struct cfg80211_chan_def rdd2_chandef; + struct mt7915_phy *rdd2_phy; + u16 chainmask; + u16 chainshift; u32 hif_idx; struct work_struct init_work; @@ -270,49 +314,41 @@ struct mt7915_dev { bool dbdc_support; bool flash_mode; + bool muru_debug; bool ibf; - u8 fw_debug_wm; - u8 fw_debug_wa; + + struct dentry *debugfs_dir; + struct rchan *relay_fwlog; void *cal; struct { - u8 table_mask; + u8 debug_wm; + u8 debug_wa; + u8 debug_bin; + } fw; + + struct { + u16 table_mask; u8 n_agrt; } twt; -}; -enum { - HW_BSSID_0 = 0x0, - HW_BSSID_1, - HW_BSSID_2, - HW_BSSID_3, - HW_BSSID_MAX = HW_BSSID_3, - EXT_BSSID_START = 0x10, - EXT_BSSID_1, - EXT_BSSID_15 = 0x1f, - EXT_BSSID_MAX = EXT_BSSID_15, - REPEATER_BSSID_START = 0x20, - REPEATER_BSSID_MAX = 0x3f, + struct reset_control *rstc; + void __iomem *dcm; + void __iomem *sku; }; enum { - MT_CTX0, - MT_HIF0 = 0x0, - - MT_LMAC_AC00 = 0x0, - MT_LMAC_AC01, - MT_LMAC_AC02, - MT_LMAC_AC03, - MT_LMAC_ALTX0 = 0x10, - MT_LMAC_BMC0, - MT_LMAC_BCN0, - MT_LMAC_PSMP0, + WFDMA0 = 0x0, + WFDMA1, + WFDMA_EXT, + __MT_WFDMA_MAX, }; enum { MT_RX_SEL0, MT_RX_SEL1, + MT_RX_SEL2, /* monitor chain */ }; enum mt7915_rdd_cmd { @@ -350,7 +386,7 @@ mt7915_hw_dev(struct ieee80211_hw *hw) static inline struct mt7915_phy * mt7915_ext_phy(struct mt7915_dev *dev) { - struct mt76_phy *phy = dev->mt76.phy2; + struct mt76_phy *phy = dev->mt76.phys[MT_BAND1]; if (!phy) return NULL; @@ -358,26 +394,52 @@ mt7915_ext_phy(struct mt7915_dev *dev) return phy->priv; } -static inline u8 mt7915_lmac_mapping(struct mt7915_dev *dev, u8 ac) +static inline u32 mt7915_check_adie(struct mt7915_dev *dev, bool sku) { - /* LMAC uses the reverse order of mac80211 AC indexes */ - return 3 - ac; + u32 mask = sku ? MT_CONNINFRA_SKU_MASK : MT_ADIE_TYPE_MASK; + + if (!is_mt7986(&dev->mt76)) + return 0; + + return mt76_rr(dev, MT_CONNINFRA_SKU_DEC_ADDR) & mask; } extern const struct ieee80211_ops mt7915_ops; extern const struct mt76_testmode_ops mt7915_testmode_ops; +extern struct pci_driver mt7915_pci_driver; +extern struct pci_driver mt7915_hif_driver; +extern struct platform_driver mt7986_wmac_driver; + +#ifdef CONFIG_MT7986_WMAC +int mt7986_wmac_enable(struct mt7915_dev *dev); +void mt7986_wmac_disable(struct mt7915_dev *dev); +#else +static inline int mt7986_wmac_enable(struct mt7915_dev *dev) +{ + return 0; +} -u32 mt7915_reg_map(struct mt7915_dev *dev, u32 addr); +static inline void mt7986_wmac_disable(struct mt7915_dev *dev) +{ +} +#endif +struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, + void __iomem *mem_base, u32 device_id); +void mt7915_wfsys_reset(struct mt7915_dev *dev); +irqreturn_t mt7915_irq_handler(int irq, void *dev_instance); u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif); +u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); + int mt7915_register_device(struct mt7915_dev *dev); void mt7915_unregister_device(struct mt7915_dev *dev); int mt7915_eeprom_init(struct mt7915_dev *dev); -void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy); +void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, + struct mt7915_phy *phy); int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx); s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band); -int mt7915_dma_init(struct mt7915_dev *dev); +int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); int mt7915_mcu_init(struct mt7915_dev *dev); @@ -391,22 +453,16 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable); int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable); -int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool add); int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool add); -int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct mt7915_sta *msta, struct ieee80211_key_conf *key, - enum set_key_cmd cmd); int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct cfg80211_he_bss_color *he_bss_color); int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int enable); + int enable, u32 changed); int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -423,14 +479,12 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, void *data, u32 field); int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); +int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num); int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans); int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, u8 en); -int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable); int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); -int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val); -int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter); int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable); int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy); int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len); @@ -448,17 +502,23 @@ int mt7915_mcu_get_temperature(struct mt7915_phy *phy); int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state); int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); -int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd, - u8 index, u8 rx_sel, u8 val); +int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, + struct cfg80211_chan_def *chandef); +int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set); int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_exit(struct mt7915_dev *dev); -static inline bool is_mt7915(struct mt76_dev *dev) +static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) +{ + return is_mt7915(&dev->mt76) ? MT7915_WTBL_SIZE : MT7916_WTBL_SIZE; +} + +static inline u16 mt7915_eeprom_size(struct mt7915_dev *dev) { - return mt76_chip(dev) == 0x7915; + return is_mt7915(&dev->mt76) ? MT7915_EEPROM_SIZE : MT7916_EEPROM_SIZE; } void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg, @@ -487,9 +547,10 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask); void mt7915_mac_reset_counters(struct mt7915_phy *phy); void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy); -void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, +void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, bool beacon); + struct ieee80211_key_conf *key, + enum mt76_txq_id qid, u32 changed); void mt7915_mac_set_timing(struct mt7915_phy *phy); int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -499,7 +560,6 @@ void mt7915_mac_work(struct work_struct *work); void mt7915_mac_reset_work(struct work_struct *work); void mt7915_mac_sta_rc_work(struct work_struct *work); void mt7915_mac_update_stats(struct mt7915_phy *phy); -int mt7915_mmio_init(struct mt76_dev *mdev, void __iomem *mem_base, int irq); void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev, struct mt7915_sta *msta, u8 flowid); @@ -510,11 +570,10 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); void mt7915_tx_token_put(struct mt7915_dev *dev); -int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); +bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); void mt7915_stats_work(struct work_struct *work); int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force); @@ -522,7 +581,11 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy); void mt7915_set_stream_he_caps(struct mt7915_phy *phy); void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy); void mt7915_update_channel(struct mt76_phy *mphy); +int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enable); +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms); int mt7915_init_debugfs(struct mt7915_phy *phy); +void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len); +bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len); #ifdef CONFIG_MAC80211_DEBUGFS void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index 0af4cdb897b7..728a879c3b00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -12,41 +12,26 @@ #include "mac.h" #include "../trace.h" +static bool wed_enable = false; +module_param(wed_enable, bool, 0644); + static LIST_HEAD(hif_list); static DEFINE_SPINLOCK(hif_lock); static u32 hif_idx; static const struct pci_device_id mt7915_pci_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) }, { }, }; static const struct pci_device_id mt7915_hif_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) }, { }, }; -void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg, - u32 clear, u32 set) -{ - struct mt76_dev *mdev = &dev->mt76; - unsigned long flags; - - spin_lock_irqsave(&mdev->mmio.irq_lock, flags); - - mdev->mmio.irqmask &= ~clear; - mdev->mmio.irqmask |= set; - - if (write_reg) { - mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask); - mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask); - } - - spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags); -} - -static struct mt7915_hif * -mt7915_pci_get_hif2(struct mt7915_dev *dev) +static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx) { struct mt7915_hif *hif; u32 val; @@ -56,7 +41,7 @@ mt7915_pci_get_hif2(struct mt7915_dev *dev) list_for_each_entry(hif, &hif_list, list) { val = readl(hif->regs + MT_PCIE_RECOG_ID); val &= MT_PCIE_RECOG_ID_MASK; - if (val != dev->hif_idx) + if (val != idx) continue; get_device(hif->dev); @@ -78,166 +63,133 @@ static void mt7915_put_hif2(struct mt7915_hif *hif) put_device(hif->dev); } -static void -mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) { - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - static const u32 rx_irq_mask[] = { - [MT_RXQ_MAIN] = MT_INT_RX_DONE_DATA0, - [MT_RXQ_EXT] = MT_INT_RX_DONE_DATA1, - [MT_RXQ_MCU] = MT_INT_RX_DONE_WM, - [MT_RXQ_MCU_WA] = MT_INT_RX_DONE_WA, - [MT_RXQ_EXT_WA] = MT_INT_RX_DONE_WA_EXT, - }; - - mt7915_irq_enable(dev, rx_irq_mask[q]); -} + hif_idx++; + if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) && + !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL)) + return NULL; -/* TODO: support 2/4/6/8 MSI-X vectors */ -static void mt7915_irq_tasklet(struct tasklet_struct *t) -{ - struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet); - u32 intr, intr1, mask; + writel(hif_idx | MT_PCIE_RECOG_ID_SEM, + pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); - - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - intr &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - - if (dev->hif2) { - intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); - intr1 &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1); - - intr |= intr1; - } + return mt7915_pci_get_hif2(hif_idx); +} - trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); +static int mt7915_pci_hif2_probe(struct pci_dev *pdev) +{ + struct mt7915_hif *hif; - mask = intr & MT_INT_RX_DONE_ALL; - if (intr & MT_INT_TX_DONE_MCU) - mask |= MT_INT_TX_DONE_MCU; + hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); + if (!hif) + return -ENOMEM; - mt7915_irq_disable(dev, mask); + hif->dev = &pdev->dev; + hif->regs = pcim_iomap_table(pdev)[0]; + hif->irq = pdev->irq; + spin_lock_bh(&hif_lock); + list_add(&hif->list, &hif_list); + spin_unlock_bh(&hif_lock); + pci_set_drvdata(pdev, hif); - if (intr & MT_INT_TX_DONE_MCU) - napi_schedule(&dev->mt76.tx_napi); + return 0; +} - if (intr & MT_INT_RX_DONE_DATA0) - napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int mt7915_wed_offload_enable(struct mtk_wed_device *wed) +{ + struct mt7915_dev *dev; + struct mt7915_phy *phy; + int ret; - if (intr & MT_INT_RX_DONE_DATA1) - napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]); + dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - if (intr & MT_INT_RX_DONE_WM) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); + spin_lock_bh(&dev->mt76.token_lock); + dev->mt76.token_size = wed->wlan.token_start; + spin_unlock_bh(&dev->mt76.token_lock); - if (intr & MT_INT_RX_DONE_WA) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); + ret = wait_event_timeout(dev->mt76.tx_wait, + !dev->mt76.wed_token_count, HZ); + if (!ret) + return -EAGAIN; - if (intr & MT_INT_RX_DONE_WA_EXT) - napi_schedule(&dev->mt76.napi[MT_RXQ_EXT_WA]); + phy = &dev->phy; + mt76_set(dev, MT_AGG_ACR4(phy->band_idx), MT_AGG_ACR_PPDU_TXS2H); - if (intr & MT_INT_MCU_CMD) { - u32 val = mt76_rr(dev, MT_MCU_CMD); + phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; + if (phy) + mt76_set(dev, MT_AGG_ACR4(phy->band_idx), + MT_AGG_ACR_PPDU_TXS2H); - mt76_wr(dev, MT_MCU_CMD, val); - if (val & MT_MCU_CMD_ERROR_MASK) { - dev->reset_state = val; - ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); - wake_up(&dev->reset_wait); - } - } + return 0; } -static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) +static void mt7915_wed_offload_disable(struct mtk_wed_device *wed) { - struct mt7915_dev *dev = dev_instance; + struct mt7915_dev *dev; + struct mt7915_phy *phy; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); + dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return IRQ_NONE; + spin_lock_bh(&dev->mt76.token_lock); + dev->mt76.token_size = MT7915_TOKEN_SIZE; + spin_unlock_bh(&dev->mt76.token_lock); - tasklet_schedule(&dev->irq_tasklet); + /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than + * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. + */ + phy = &dev->phy; + mt76_clear(dev, MT_AGG_ACR4(phy->band_idx), MT_AGG_ACR_PPDU_TXS2H); - return IRQ_HANDLED; + phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; + if (phy) + mt76_clear(dev, MT_AGG_ACR4(phy->band_idx), + MT_AGG_ACR_PPDU_TXS2H); } +#endif -static void mt7915_pci_init_hif2(struct mt7915_dev *dev) +static int +mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq) { - struct mt7915_hif *hif; - - dev->hif_idx = ++hif_idx; - if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL)) - return; - - mt76_wr(dev, MT_PCIE_RECOG_ID, dev->hif_idx | MT_PCIE_RECOG_ID_SEM); - - hif = mt7915_pci_get_hif2(dev); - if (!hif) - return; - - dev->hif2 = hif; +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + int ret; - mt76_wr(dev, MT_INT1_MASK_CSR, 0); + if (!wed_enable) + return 0; - if (devm_request_irq(dev->mt76.dev, hif->irq, mt7915_irq_handler, - IRQF_SHARED, KBUILD_MODNAME "-hif", dev)) { - mt7915_put_hif2(hif); - hif = NULL; - } + wed->wlan.pci_dev = pdev; + wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) + + MT_WFDMA_EXT_CSR_BASE; + wed->wlan.nbuf = 4096; + wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; + wed->wlan.init_buf = mt7915_wed_init_buf; + wed->wlan.offload_enable = mt7915_wed_offload_enable; + wed->wlan.offload_disable = mt7915_wed_offload_disable; - /* master switch of PCIe tnterrupt enable */ - mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); -} + if (mtk_wed_device_attach(wed) != 0) + return 0; -static int mt7915_pci_hif2_probe(struct pci_dev *pdev) -{ - struct mt7915_hif *hif; + *irq = wed->irq; + dev->mt76.dma_dev = wed->dev; - hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); - if (!hif) - return -ENOMEM; - - hif->dev = &pdev->dev; - hif->regs = pcim_iomap_table(pdev)[0]; - hif->irq = pdev->irq; - spin_lock_bh(&hif_lock); - list_add(&hif->list, &hif_list); - spin_unlock_bh(&hif_lock); - pci_set_drvdata(pdev, hif); + ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + return 1; +#else return 0; +#endif } static int mt7915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - static const struct mt76_driver_ops drv_ops = { - /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp), - .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, - .survey_flags = SURVEY_INFO_TIME_TX | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_BSS_RX, - .token_size = MT7915_TOKEN_SIZE, - .tx_prepare_skb = mt7915_tx_prepare_skb, - .tx_complete_skb = mt7915_tx_complete_skb, - .rx_skb = mt7915_queue_rx_skb, - .rx_poll_complete = mt7915_rx_poll_complete, - .sta_ps = mt7915_sta_ps, - .sta_add = mt7915_mac_sta_add, - .sta_remove = mt7915_mac_sta_remove, - .update_survey = mt7915_update_channel, - }; + struct mt7915_hif *hif2 = NULL; struct mt7915_dev *dev; struct mt76_dev *mdev; + int irq; int ret; ret = pcim_enable_device(pdev); @@ -256,48 +208,76 @@ static int mt7915_pci_probe(struct pci_dev *pdev, mt76_pci_disable_aspm(pdev); - if (id->device == 0x7916) + if (id->device == 0x7916 || id->device == 0x790a) return mt7915_pci_hif2_probe(pdev); - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops, - &drv_ops); - if (!mdev) - return -ENOMEM; + dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], + id->device); + if (IS_ERR(dev)) + return PTR_ERR(dev); - dev = container_of(mdev, struct mt7915_dev, mt76); + mdev = &dev->mt76; + mt7915_wfsys_reset(dev); + hif2 = mt7915_pci_init_hif2(pdev); - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + ret = mt7915_pci_wed_init(dev, pdev, &irq); if (ret < 0) - goto free; + goto free_wed_or_irq_vector; - ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq); - if (ret) - goto error; + if (!ret) { + hif2 = mt7915_pci_init_hif2(pdev); - tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet); + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto free_device; - mt76_wr(dev, MT_INT_MASK_CSR, 0); + irq = pdev->irq; + } + + ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto free_wed_or_irq_vector; /* master switch of PCIe tnterrupt enable */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (ret) - goto error; + if (hif2) { + dev->hif2 = hif2; - mt7915_pci_init_hif2(dev); + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + /* master switch of PCIe tnterrupt enable */ + if (is_mt7915(mdev)) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + else + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); + + ret = devm_request_irq(mdev->dev, dev->hif2->irq, + mt7915_irq_handler, IRQF_SHARED, + KBUILD_MODNAME "-hif", dev); + if (ret) + goto free_hif2; + } ret = mt7915_register_device(dev); if (ret) - goto free_irq; + goto free_hif2_irq; return 0; -free_irq: - devm_free_irq(mdev->dev, pdev->irq, dev); -error: - pci_free_irq_vectors(pdev); -free: + +free_hif2_irq: + if (dev->hif2) + devm_free_irq(mdev->dev, dev->hif2->irq, dev); +free_hif2: + if (dev->hif2) + put_device(dev->hif2->dev); + devm_free_irq(mdev->dev, irq, dev); +free_wed_or_irq_vector: + if (mtk_wed_device_active(&mdev->mmio.wed)) + mtk_wed_device_detach(&mdev->mmio.wed); + else + pci_free_irq_vectors(pdev); +free_device: mt76_free_device(&dev->mt76); return ret; @@ -321,47 +301,25 @@ static void mt7915_pci_remove(struct pci_dev *pdev) mt7915_unregister_device(dev); } -static struct pci_driver mt7915_hif_driver = { +struct pci_driver mt7915_hif_driver = { .name = KBUILD_MODNAME "_hif", .id_table = mt7915_hif_device_table, .probe = mt7915_pci_probe, .remove = mt7915_hif_remove, }; -static struct pci_driver mt7915_pci_driver = { +struct pci_driver mt7915_pci_driver = { .name = KBUILD_MODNAME, .id_table = mt7915_pci_device_table, .probe = mt7915_pci_probe, .remove = mt7915_pci_remove, }; -static int __init mt7915_init(void) -{ - int ret; - - ret = pci_register_driver(&mt7915_hif_driver); - if (ret) - return ret; - - ret = pci_register_driver(&mt7915_pci_driver); - if (ret) - pci_unregister_driver(&mt7915_hif_driver); - - return ret; -} - -static void __exit mt7915_exit(void) -{ - pci_unregister_driver(&mt7915_pci_driver); - pci_unregister_driver(&mt7915_hif_driver); -} - -module_init(mt7915_init); -module_exit(mt7915_exit); - MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); MODULE_FIRMWARE(MT7915_FIRMWARE_WA); MODULE_FIRMWARE(MT7915_FIRMWARE_WM); MODULE_FIRMWARE(MT7915_ROM_PATCH); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(MT7916_FIRMWARE_WA); +MODULE_FIRMWARE(MT7916_FIRMWARE_WM); +MODULE_FIRMWARE(MT7916_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 59693535b098..5920e705835a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -4,41 +4,149 @@ #ifndef __MT7915_REGS_H #define __MT7915_REGS_H +/* used to differentiate between generations */ +struct mt7915_reg_desc { + const u32 *reg_rev; + const u32 *offs_rev; + const struct mt76_connac_reg_map *map; + u32 map_size; +}; + +enum reg_rev { + INT_SOURCE_CSR, + INT_MASK_CSR, + INT1_SOURCE_CSR, + INT1_MASK_CSR, + INT_MCU_CMD_SOURCE, + INT_MCU_CMD_EVENT, + WFDMA0_ADDR, + WFDMA0_PCIE1_ADDR, + WFDMA_EXT_CSR_ADDR, + CBTOP1_PHY_END, + INFRA_MCU_ADDR_END, + FW_EXCEPTION_ADDR, + SWDEF_BASE_ADDR, + __MT_REG_MAX, +}; + +enum offs_rev { + TMAC_CDTR, + TMAC_ODTR, + TMAC_ATCR, + TMAC_TRCR0, + TMAC_ICR0, + TMAC_ICR1, + TMAC_CTCR0, + TMAC_TFCR0, + MDP_BNRCFR0, + MDP_BNRCFR1, + ARB_DRNGR0, + ARB_SCR, + RMAC_MIB_AIRTIME14, + AGG_AWSCR0, + AGG_PCR0, + AGG_ACR0, + AGG_ACR4, + AGG_MRCR, + AGG_ATCR1, + AGG_ATCR3, + LPON_UTTR0, + LPON_UTTR1, + LPON_FRCR, + MIB_SDR3, + MIB_SDR4, + MIB_SDR5, + MIB_SDR7, + MIB_SDR8, + MIB_SDR9, + MIB_SDR10, + MIB_SDR11, + MIB_SDR12, + MIB_SDR13, + MIB_SDR14, + MIB_SDR15, + MIB_SDR16, + MIB_SDR17, + MIB_SDR18, + MIB_SDR19, + MIB_SDR20, + MIB_SDR21, + MIB_SDR22, + MIB_SDR23, + MIB_SDR24, + MIB_SDR25, + MIB_SDR27, + MIB_SDR28, + MIB_SDR29, + MIB_SDRVEC, + MIB_SDR31, + MIB_SDR32, + MIB_SDRMUBF, + MIB_DR8, + MIB_DR9, + MIB_DR11, + MIB_MB_SDR0, + MIB_MB_SDR1, + TX_AGG_CNT, + TX_AGG_CNT2, + MIB_ARNG, + WTBLON_TOP_WDUCR, + WTBL_UPDATE, + PLE_FL_Q_EMPTY, + PLE_FL_Q_CTRL, + PLE_AC_QEMPTY, + PLE_FREEPG_CNT, + PLE_FREEPG_HEAD_TAIL, + PLE_PG_HIF_GROUP, + PLE_HIF_PG_INFO, + AC_OFFSET, + ETBF_PAR_RPT0, + __MT_OFFS_MAX, +}; + +#define __REG(id) (dev->reg.reg_rev[(id)]) +#define __OFFS(id) (dev->reg.offs_rev[(id)]) + /* MCU WFDMA0 */ #define MT_MCU_WFDMA0_BASE 0x2000 #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs)) + #define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120) /* MCU WFDMA1 */ #define MT_MCU_WFDMA1_BASE 0x3000 #define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) -#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) +#define MT_MCU_INT_EVENT __REG(INT_MCU_CMD_EVENT) #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) #define MT_MCU_INT_EVENT_DMA_INIT BIT(1) #define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) #define MT_MCU_INT_EVENT_RESET_DONE BIT(3) -#define MT_PLE_BASE 0x8000 +/* PLE */ +#define MT_PLE_BASE 0x820c0000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) -#define MT_FL_Q_EMPTY 0x0b0 -#define MT_FL_Q0_CTRL 0x1b0 -#define MT_FL_Q2_CTRL 0x1b8 -#define MT_FL_Q3_CTRL 0x1bc - -#define MT_PLE_FREEPG_CNT MT_PLE(0x100) -#define MT_PLE_FREEPG_HEAD_TAIL MT_PLE(0x104) -#define MT_PLE_PG_HIF_GROUP MT_PLE(0x110) -#define MT_PLE_HIF_PG_INFO MT_PLE(0x114) -#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x500 + 0x40 * (ac) + \ - ((n) << 2)) +#define MT_FL_Q_EMPTY MT_PLE(__OFFS(PLE_FL_Q_EMPTY)) +#define MT_FL_Q0_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL)) +#define MT_FL_Q2_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0x8) +#define MT_FL_Q3_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0xc) + +#define MT_PLE_FREEPG_CNT MT_PLE(__OFFS(PLE_FREEPG_CNT)) +#define MT_PLE_FREEPG_HEAD_TAIL MT_PLE(__OFFS(PLE_FREEPG_HEAD_TAIL)) +#define MT_PLE_PG_HIF_GROUP MT_PLE(__OFFS(PLE_PG_HIF_GROUP)) +#define MT_PLE_HIF_PG_INFO MT_PLE(__OFFS(PLE_HIF_PG_INFO)) + +#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(__OFFS(PLE_AC_QEMPTY) + \ + __OFFS(AC_OFFSET) * \ + (ac) + ((n) << 2)) #define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) -#define MT_PSE_BASE 0xc000 +#define MT_PSE_BASE 0x820c8000 #define MT_PSE(ofs) (MT_PSE_BASE + (ofs)) -#define MT_MDP_BASE 0xf000 +/* WF MDP TOP */ +#define MT_MDP_BASE 0x820cd000 #define MT_MDP(ofs) (MT_MDP_BASE + (ofs)) #define MT_MDP_DCR0 MT_MDP(0x000) @@ -47,73 +155,87 @@ #define MT_MDP_DCR1 MT_MDP(0x004) #define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3) -#define MT_MDP_BNRCFR0(_band) MT_MDP(0x070 + ((_band) << 8)) +#define MT_MDP_DCR2 MT_MDP(0x0e8) +#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2) + +#define MT_MDP_BNRCFR0(_band) MT_MDP(__OFFS(MDP_BNRCFR0) + \ + ((_band) << 8)) #define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4) #define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6) #define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8) -#define MT_MDP_BNRCFR1(_band) MT_MDP(0x074 + ((_band) << 8)) +#define MT_MDP_BNRCFR1(_band) MT_MDP(__OFFS(MDP_BNRCFR1) + \ + ((_band) << 8)) #define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22) #define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27) #define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29) #define MT_MDP_TO_HIF 0 #define MT_MDP_TO_WM 1 -/* TMAC: band 0(0x21000), band 1(0xa1000) */ -#define MT_WF_TMAC_BASE(_band) ((_band) ? 0xa1000 : 0x21000) +/* TRB: band 0(0x820e1000), band 1(0x820f1000) */ +#define MT_WF_TRB_BASE(_band) ((_band) ? 0x820f1000 : 0x820e1000) +#define MT_WF_TRB(_band, ofs) (MT_WF_TRB_BASE(_band) + (ofs)) + +#define MT_TRB_RXPSR0(_band) MT_WF_TRB(_band, 0x03c) +#define MT_TRB_RXPSR0_RX_WTBL_PTR GENMASK(25, 16) +#define MT_TRB_RXPSR0_RX_RMAC_PTR GENMASK(9, 0) + +/* TMAC: band 0(0x820e4000), band 1(0x820f4000) */ +#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) #define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) #define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) #define MT_TMAC_TCR0_TX_BLINK GENMASK(7, 6) #define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) -#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) -#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) +#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, __OFFS(TMAC_CDTR)) + #define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, __OFFS(TMAC_ODTR)) #define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) #define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) -#define MT_TMAC_ATCR(_band) MT_WF_TMAC(_band, 0x098) +#define MT_TMAC_ATCR(_band) MT_WF_TMAC(_band, __OFFS(TMAC_ATCR)) #define MT_TMAC_ATCR_TXV_TOUT GENMASK(7, 0) -#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) +#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, __OFFS(TMAC_TRCR0)) #define MT_TMAC_TRCR0_TR2T_CHK GENMASK(8, 0) #define MT_TMAC_TRCR0_I2T_CHK GENMASK(24, 16) -#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) -#define MT_IFS_EIFS_OFDM GENMASK(8, 0) +#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, __OFFS(TMAC_ICR0)) +#define MT_IFS_EIFS_OFDM GENMASK(8, 0) #define MT_IFS_RIFS GENMASK(14, 10) #define MT_IFS_SIFS GENMASK(22, 16) #define MT_IFS_SLOT GENMASK(30, 24) -#define MT_TMAC_ICR1(_band) MT_WF_TMAC(_band, 0x0b4) +#define MT_TMAC_ICR1(_band) MT_WF_TMAC(_band, __OFFS(TMAC_ICR1)) #define MT_IFS_EIFS_CCK GENMASK(8, 0) -#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) +#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, __OFFS(TMAC_CTCR0)) #define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) #define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) -#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) +#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, __OFFS(TMAC_TFCR0)) -#define MT_WF_DMA_BASE(_band) ((_band) ? 0xa1e00 : 0x21e00) +/* WF DMA TOP: band 0(0x820e7000),band 1(0x820f7000) */ +#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000) #define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) #define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) #define MT_DMA_DCR0_RXD_G5_EN BIT(23) -/* ETBF: band 0(0x24000), band 1(0xa4000) */ -#define MT_WF_ETBF_BASE(_band) ((_band) ? 0xa4000 : 0x24000) +/* ETBF: band 0(0x820ea000), band 1(0x820fa000) */ +#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) #define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) #define MT_ETBF_TX_NDP_BFRP(_band) MT_WF_ETBF(_band, 0x040) #define MT_ETBF_TX_FB_CPL GENMASK(31, 16) #define MT_ETBF_TX_FB_TRI GENMASK(15, 0) -#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x068) -#define MT_ETBF_RX_FB_BW GENMASK(7, 6) -#define MT_ETBF_RX_FB_NC GENMASK(5, 3) -#define MT_ETBF_RX_FB_NR GENMASK(2, 0) +#define MT_ETBF_PAR_RPT0(_band) MT_WF_ETBF(_band, __OFFS(ETBF_PAR_RPT0)) +#define MT_ETBF_PAR_RPT0_FB_BW GENMASK(7, 6) +#define MT_ETBF_PAR_RPT0_FB_NC GENMASK(5, 3) +#define MT_ETBF_PAR_RPT0_FB_NR GENMASK(2, 0) #define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x0f0) #define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) @@ -125,174 +247,209 @@ #define MT_ETBF_RX_FB_VHT GENMASK(15, 8) #define MT_ETBF_RX_FB_HT GENMASK(7, 0) -/* LPON: band 0(0x24200), band 1(0xa4200) */ -#define MT_WF_LPON_BASE(_band) ((_band) ? 0xa4200 : 0x24200) +/* LPON: band 0(0x820eb000), band 1(0x820fb000) */ +#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000) #define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs)) -#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080) -#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084) +#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, __OFFS(LPON_UTTR0)) +#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, __OFFS(LPON_UTTR1)) +#define MT_LPON_FRCR(_band) MT_WF_LPON(_band, __OFFS(LPON_FRCR)) -#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4) +#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + \ + (((n) * 4) << 1)) +#define MT_LPON_TCR_MT7916(_band, n) MT_WF_LPON(_band, 0x0a8 + \ + (((n) * 4) << 4)) #define MT_LPON_TCR_SW_MODE GENMASK(1, 0) #define MT_LPON_TCR_SW_WRITE BIT(0) #define MT_LPON_TCR_SW_ADJUST BIT(1) #define MT_LPON_TCR_SW_READ GENMASK(1, 0) -/* MIB: band 0(0x24800), band 1(0xa4800) */ +/* MIB: band 0(0x820ed000), band 1(0x820fd000) */ /* These counters are (mostly?) clear-on-read. So, some should not * be read at all in case firmware is already reading them. These * are commented with 'DNR' below. The DNR stats will be read by querying * the firmware API for the appropriate message. For counters the driver * does read, the driver should accumulate the counters. */ -#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800) +#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) #define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) #define MT_MIB_SDR0(_band) MT_WF_MIB(_band, 0x010) #define MT_MIB_SDR0_BERACON_TX_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014) +#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR3)) #define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0) +#define MT_MIB_SDR3_FCS_ERR_MASK_MT7916 GENMASK(31, 16) -#define MT_MIB_SDR4(_band) MT_WF_MIB(_band, 0x018) +#define MT_MIB_SDR4(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR4)) #define MT_MIB_SDR4_RX_FIFO_FULL_MASK GENMASK(15, 0) /* rx mpdu counter, full 32 bits */ -#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x01c) +#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR5)) #define MT_MIB_SDR6(_band) MT_WF_MIB(_band, 0x020) #define MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR7(_band) MT_WF_MIB(_band, 0x024) +#define MT_MIB_SDR7(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR7)) #define MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR8(_band) MT_WF_MIB(_band, 0x028) +#define MT_MIB_SDR8(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR8)) #define MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK GENMASK(15, 0) /* aka CCA_NAV_TX_TIME */ -#define MT_MIB_SDR9_DNR(_band) MT_WF_MIB(_band, 0x02c) -#define MT_MIB_SDR9_CCA_BUSY_TIME_MASK GENMASK(23, 0) +#define MT_MIB_SDR9_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR9)) +#define MT_MIB_SDR9_CCA_BUSY_TIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR10_DNR(_band) MT_WF_MIB(_band, 0x030) -#define MT_MIB_SDR10_MRDY_COUNT_MASK GENMASK(25, 0) +#define MT_MIB_SDR10(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR10)) +#define MT_MIB_SDR10_MRDY_COUNT_MASK GENMASK(25, 0) +#define MT_MIB_SDR10_MRDY_COUNT_MASK_MT7916 GENMASK(31, 0) -#define MT_MIB_SDR11(_band) MT_WF_MIB(_band, 0x034) +#define MT_MIB_SDR11(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR11)) #define MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK GENMASK(15, 0) /* tx ampdu cnt, full 32 bits */ -#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x038) +#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR12)) -#define MT_MIB_SDR13(_band) MT_WF_MIB(_band, 0x03c) +#define MT_MIB_SDR13(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR13)) #define MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK GENMASK(15, 0) /* counts all mpdus in ampdu, regardless of success */ -#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x040) +#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR14)) #define MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK GENMASK(23, 0) +#define MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK_MT7916 GENMASK(31, 0) /* counts all successfully tx'd mpdus in ampdu */ -#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x044) +#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR15)) #define MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK GENMASK(23, 0) +#define MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916 GENMASK(31, 0) /* in units of 'us' */ -#define MT_MIB_SDR16_DNR(_band) MT_WF_MIB(_band, 0x048) +#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR16)) #define MT_MIB_SDR16_PRIMARY_CCA_BUSY_TIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR17_DNR(_band) MT_WF_MIB(_band, 0x04c) +#define MT_MIB_SDR17(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR17)) #define MT_MIB_SDR17_SECONDARY_CCA_BUSY_TIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR18(_band) MT_WF_MIB(_band, 0x050) +#define MT_MIB_SDR18(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR18)) #define MT_MIB_SDR18_PRIMARY_ENERGY_DETECT_TIME_MASK GENMASK(23, 0) /* units are us */ -#define MT_MIB_SDR19_DNR(_band) MT_WF_MIB(_band, 0x054) +#define MT_MIB_SDR19(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR19)) #define MT_MIB_SDR19_CCK_MDRDY_TIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR20_DNR(_band) MT_WF_MIB(_band, 0x058) +#define MT_MIB_SDR20(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR20)) #define MT_MIB_SDR20_OFDM_VHT_MDRDY_TIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR21_DNR(_band) MT_WF_MIB(_band, 0x05c) -#define MT_MIB_SDR20_GREEN_MDRDY_TIME_MASK GENMASK(23, 0) +#define MT_MIB_SDR21(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR21)) +#define MT_MIB_SDR21_GREEN_MDRDY_TIME_MASK GENMASK(23, 0) /* rx ampdu count, 32-bit */ -#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x060) +#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR22)) /* rx ampdu bytes count, 32-bit */ -#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x064) +#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR23)) /* rx ampdu valid subframe count */ -#define MT_MIB_SDR24(_band) MT_WF_MIB(_band, 0x068) +#define MT_MIB_SDR24(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR24)) #define MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK GENMASK(23, 0) +#define MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK_MT7916 GENMASK(31, 0) /* rx ampdu valid subframe bytes count, 32bits */ -#define MT_MIB_SDR25(_band) MT_WF_MIB(_band, 0x06c) +#define MT_MIB_SDR25(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR25)) /* remaining windows protected stats */ -#define MT_MIB_SDR27(_band) MT_WF_MIB(_band, 0x074) +#define MT_MIB_SDR27(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR27)) #define MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR28(_band) MT_WF_MIB(_band, 0x078) +#define MT_MIB_SDR28(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR28)) #define MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK GENMASK(15, 0) -#define MT_MIB_SDR29(_band) MT_WF_MIB(_band, 0x07c) -#define MT_MIB_SDR29_RX_PFDROP_CNT_MASK GENMASK(7, 0) +#define MT_MIB_SDR29(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR29)) +#define MT_MIB_SDR29_RX_PFDROP_CNT_MASK GENMASK(7, 0) +#define MT_MIB_SDR29_RX_PFDROP_CNT_MASK_MT7916 GENMASK(15, 0) -#define MT_MIB_SDR30(_band) MT_WF_MIB(_band, 0x080) +#define MT_MIB_SDRVEC(_band) MT_WF_MIB(_band, __OFFS(MIB_SDRVEC)) #define MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK GENMASK(15, 0) +#define MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK_MT7916 GENMASK(31, 16) /* rx blockack count, 32 bits */ -#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x084) +#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR31)) -#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x088) -#define MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK GENMASK(15, 0) +#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR32)) +#define MT_MIB_SDR32_TX_PKT_EBF_CNT GENMASK(15, 0) +#define MT_MIB_SDR32_TX_PKT_IBF_CNT GENMASK(31, 16) -#define MT_MIB_SDR33(_band) MT_WF_MIB(_band, 0x08c) -#define MT_MIB_SDR33_TX_PKT_IBF_CNT_MASK GENMASK(15, 0) +#define MT_MIB_SDR33(_band) MT_WF_MIB(_band, 0x088) +#define MT_MIB_SDR33_TX_PKT_IBF_CNT GENMASK(15, 0) -#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) +#define MT_MIB_SDRMUBF(_band) MT_WF_MIB(_band, __OFFS(MIB_SDRMUBF)) #define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) /* 36, 37 both DNR */ -#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) -#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4) -#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc) +#define MT_MIB_DR8(_band) MT_WF_MIB(_band, __OFFS(MIB_DR8)) +#define MT_MIB_DR9(_band) MT_WF_MIB(_band, __OFFS(MIB_DR9)) +#define MT_MIB_DR11(_band) MT_WF_MIB(_band, __OFFS(MIB_DR11)) -#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, __OFFS(MIB_MB_SDR0) + (n)) #define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) #define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4)) +#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, __OFFS(MIB_MB_SDR1) + (n)) #define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0) #define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16) -#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2)) -#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2)) -#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2)) +#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x518 + (n)) +#define MT_MIB_MB_BFTF(_band, n) MT_WF_MIB(_band, 0x510 + (n)) + +#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, __OFFS(TX_AGG_CNT) + \ + ((n) << 2)) +#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, __OFFS(TX_AGG_CNT2) + \ + ((n) << 2)) +#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, __OFFS(MIB_ARNG) + \ + ((n) << 2)) #define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) -#define MT_WTBLON_TOP_BASE 0x34000 +#define MT_MIB_BFCR0(_band) MT_WF_MIB(_band, 0x7b0) +#define MT_MIB_BFCR0_RX_FB_HT GENMASK(15, 0) +#define MT_MIB_BFCR0_RX_FB_VHT GENMASK(31, 16) + +#define MT_MIB_BFCR1(_band) MT_WF_MIB(_band, 0x7b4) +#define MT_MIB_BFCR1_RX_FB_HE GENMASK(15, 0) + +#define MT_MIB_BFCR2(_band) MT_WF_MIB(_band, 0x7b8) +#define MT_MIB_BFCR2_BFEE_TX_FB_TRIG GENMASK(15, 0) + +#define MT_MIB_BFCR7(_band) MT_WF_MIB(_band, 0x7cc) +#define MT_MIB_BFCR7_BFEE_TX_FB_CPL GENMASK(15, 0) + +/* WTBLON TOP */ +#define MT_WTBLON_TOP_BASE 0x820d4000 #define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x0) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(__OFFS(WTBLON_TOP_WDUCR)) #define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x030) +#define MT_WTBL_UPDATE MT_WTBLON_TOP(__OFFS(WTBL_UPDATE)) #define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) #define MT_WTBL_UPDATE_BUSY BIT(31) -#define MT_WTBL_BASE 0x38000 +/* WTBL */ +#define MT_WTBL_BASE 0x820d8000 #define MT_WTBL_LMAC_ID GENMASK(14, 8) #define MT_WTBL_LMAC_DW GENMASK(7, 2) #define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ - FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ - FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) + FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ + FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) -/* AGG: band 0(0x20800), band 1(0xa0800) */ -#define MT_WF_AGG_BASE(_band) ((_band) ? 0xa0800 : 0x20800) +/* AGG: band 0(0x820e2000), band 1(0x820f2000) */ +#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) #define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) -#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) -#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) +#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_AWSCR0) + \ + (_n) * 4)) +#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \ + (_n) * 4)) #define MT_AGG_PCR0_MM_PROT BIT(0) #define MT_AGG_PCR0_GF_PROT BIT(1) #define MT_AGG_PCR0_BW20_PROT BIT(2) @@ -305,31 +462,35 @@ #define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) #define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) -#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) +#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, __OFFS(AGG_ACR0)) #define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) #define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) -#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) -#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) -#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) -#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) +#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, __OFFS(AGG_ACR4)) +#define MT_AGG_ACR_PPDU_TXS2H BIT(1) + +#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, __OFFS(AGG_MRCR)) +#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) +#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) +#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) #define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) -#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) -#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) +#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR1)) +#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, __OFFS(AGG_ATCR3)) -/* ARB: band 0(0x20c00), band 1(0xa0c00) */ -#define MT_WF_ARB_BASE(_band) ((_band) ? 0xa0c00 : 0x20c00) +/* ARB: band 0(0x820e3000), band 1(0x820f3000) */ +#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000) #define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) -#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) +#define MT_ARB_SCR(_band) MT_WF_ARB(_band, __OFFS(ARB_SCR)) #define MT_ARB_SCR_TX_DISABLE BIT(8) #define MT_ARB_SCR_RX_DISABLE BIT(9) -#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) +#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, (__OFFS(ARB_DRNGR0) + \ + (_n) * 4)) -/* RMAC: band 0(0x21400), band 1(0xa1400) */ -#define MT_WF_RMAC_BASE(_band) ((_band) ? 0xa1400 : 0x21400) +/* RMAC: band 0(0x820e5000), band 1(0x820f5000) */ +#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) #define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) #define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) @@ -366,7 +527,7 @@ #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) /* WFDMA0 */ -#define MT_WFDMA0_BASE 0xd4000 +#define MT_WFDMA0_BASE __REG(WFDMA0_ADDR) #define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) #define MT_WFDMA0_RST MT_WFDMA0(0x100) @@ -381,15 +542,14 @@ #define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) #define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) #define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) #define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) - -#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x500) - -#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) -#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) -#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) +#define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4) +#define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8) /* WFDMA1 */ #define MT_WFDMA1_BASE 0xd5000 @@ -404,129 +564,400 @@ #define MT_WFDMA1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA1_BUSY_ENA_RX_FIFO BIT(2) -#define MT_MCU_CMD MT_WFDMA1(0x1f0) -#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) -#define MT_MCU_CMD_STOP_DMA BIT(2) -#define MT_MCU_CMD_RESET_DONE BIT(3) -#define MT_MCU_CMD_RECOVERY_DONE BIT(4) -#define MT_MCU_CMD_NORMAL_STATE BIT(5) -#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) - #define MT_WFDMA1_GLO_CFG MT_WFDMA1(0x208) #define MT_WFDMA1_GLO_CFG_TX_DMA_EN BIT(0) #define MT_WFDMA1_GLO_CFG_RX_DMA_EN BIT(2) #define MT_WFDMA1_GLO_CFG_OMIT_TX_INFO BIT(28) #define MT_WFDMA1_GLO_CFG_OMIT_RX_INFO BIT(27) +#define MT_WFDMA1_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) #define MT_WFDMA1_RST_DTX_PTR MT_WFDMA1(0x20c) #define MT_WFDMA1_PRI_DLY_INT_CFG0 MT_WFDMA1(0x2f0) -#define MT_TX_RING_BASE MT_WFDMA1(0x300) -#define MT_RX_EVENT_RING_BASE MT_WFDMA1(0x500) - -#define MT_WFDMA1_TX_RING0_EXT_CTRL MT_WFDMA1(0x600) -#define MT_WFDMA1_TX_RING1_EXT_CTRL MT_WFDMA1(0x604) -#define MT_WFDMA1_TX_RING2_EXT_CTRL MT_WFDMA1(0x608) -#define MT_WFDMA1_TX_RING3_EXT_CTRL MT_WFDMA1(0x60c) -#define MT_WFDMA1_TX_RING4_EXT_CTRL MT_WFDMA1(0x610) -#define MT_WFDMA1_TX_RING5_EXT_CTRL MT_WFDMA1(0x614) -#define MT_WFDMA1_TX_RING6_EXT_CTRL MT_WFDMA1(0x618) -#define MT_WFDMA1_TX_RING7_EXT_CTRL MT_WFDMA1(0x61c) - -#define MT_WFDMA1_TX_RING16_EXT_CTRL MT_WFDMA1(0x640) -#define MT_WFDMA1_TX_RING17_EXT_CTRL MT_WFDMA1(0x644) -#define MT_WFDMA1_TX_RING18_EXT_CTRL MT_WFDMA1(0x648) -#define MT_WFDMA1_TX_RING19_EXT_CTRL MT_WFDMA1(0x64c) -#define MT_WFDMA1_TX_RING20_EXT_CTRL MT_WFDMA1(0x650) -#define MT_WFDMA1_TX_RING21_EXT_CTRL MT_WFDMA1(0x654) -#define MT_WFDMA1_TX_RING22_EXT_CTRL MT_WFDMA1(0x658) -#define MT_WFDMA1_TX_RING23_EXT_CTRL MT_WFDMA1(0x65c) - -#define MT_WFDMA1_RX_RING0_EXT_CTRL MT_WFDMA1(0x680) -#define MT_WFDMA1_RX_RING1_EXT_CTRL MT_WFDMA1(0x684) -#define MT_WFDMA1_RX_RING2_EXT_CTRL MT_WFDMA1(0x688) -#define MT_WFDMA1_RX_RING3_EXT_CTRL MT_WFDMA1(0x68c) - /* WFDMA CSR */ -#define MT_WFDMA_EXT_CSR_BASE 0xd7000 +#define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR) +#define MT_WFDMA_EXT_CSR_PHYS_BASE 0x18027000 #define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) +#define MT_WFDMA_EXT_CSR_PHYS(ofs) (MT_WFDMA_EXT_CSR_PHYS_BASE + (ofs)) -#define MT_INT_SOURCE_CSR MT_WFDMA_EXT_CSR(0x10) -#define MT_INT_MASK_CSR MT_WFDMA_EXT_CSR(0x14) -#define MT_INT_RX_DONE_DATA0 BIT(16) -#define MT_INT_RX_DONE_DATA1 BIT(17) -#define MT_INT_RX_DONE_WM BIT(0) -#define MT_INT_RX_DONE_WA BIT(1) -#define MT_INT_RX_DONE_WA_EXT BIT(2) -#define MT_INT_RX_DONE_ALL (GENMASK(2, 0) | GENMASK(17, 16)) -#define MT_INT_TX_DONE_MCU_WA BIT(15) -#define MT_INT_TX_DONE_FWDL BIT(26) -#define MT_INT_TX_DONE_MCU_WM BIT(27) -#define MT_INT_TX_DONE_BAND0 BIT(30) -#define MT_INT_TX_DONE_BAND1 BIT(31) - -#define MT_INT_BAND1_MASK (MT_INT_RX_DONE_WA_EXT | \ - MT_INT_TX_DONE_BAND1) - -#define MT_INT_MCU_CMD BIT(29) - -#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WA | \ - MT_INT_TX_DONE_MCU_WM | \ - MT_INT_TX_DONE_FWDL) - -#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30) +#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR_PHYS(0x30) #define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0) +#define MT_WFDMA_HOST_CONFIG_WED BIT(1) -#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) -#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) +#define MT_WFDMA_WED_RING_CONTROL MT_WFDMA_EXT_CSR_PHYS(0x34) +#define MT_WFDMA_WED_RING_CONTROL_TX0 GENMASK(4, 0) +#define MT_WFDMA_WED_RING_CONTROL_TX1 GENMASK(12, 8) +#define MT_WFDMA_WED_RING_CONTROL_RX1 GENMASK(20, 16) -#define MT_INT1_SOURCE_CSR MT_WFDMA_EXT_CSR(0x88) -#define MT_INT1_MASK_CSR MT_WFDMA_EXT_CSR(0x8c) +#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR_PHYS(0x44) +#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) -#define MT_PCIE_RECOG_ID MT_WFDMA_EXT_CSR(0x90) +#define MT_PCIE_RECOG_ID 0xd7090 #define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0) #define MT_PCIE_RECOG_ID_SEM BIT(31) +#define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204) + +#define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300) +#define MT_WED_RX_RING_BASE MT_WFDMA_EXT_CSR(0x400) + /* WFDMA0 PCIE1 */ -#define MT_WFDMA0_PCIE1_BASE 0xd8000 -#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) +#define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR) +#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) -#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c) +#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c) #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0) #define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO BIT(2) /* WFDMA1 PCIE1 */ -#define MT_WFDMA1_PCIE1_BASE 0xd9000 -#define MT_WFDMA1_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) +#define MT_WFDMA1_PCIE1_BASE 0xd9000 +#define MT_WFDMA1_PCIE1(ofs) (MT_WFDMA1_PCIE1_BASE + (ofs)) -#define MT_WFDMA1_PCIE1_BUSY_ENA MT_WFDMA1_PCIE1(0x13c) +#define MT_WFDMA1_PCIE1_BUSY_ENA MT_WFDMA1_PCIE1(0x13c) #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0) #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2) -#define MT_TOP_RGU_BASE 0xf0000 -#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0)) -#define MT_TOP_PWR_KEY (0x5746 << 16) -#define MT_TOP_PWR_SW_RST BIT(0) -#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2) -#define MT_TOP_PWR_HW_CTRL BIT(4) -#define MT_TOP_PWR_PWR_ON BIT(7) +/* WFDMA COMMON */ +#define __RXQ(q) ((q) + __MT_MCUQ_MAX) +#define __TXQ(q) (__RXQ(q) + MT_RXQ_BAND2) + +#define MT_Q_ID(q) (dev->q_id[(q)]) +#define MT_Q_BASE(q) ((dev->wfdma_mask >> (q)) & 0x1 ? \ + MT_WFDMA1_BASE : MT_WFDMA0_BASE) + +#define MT_MCUQ_ID(q) MT_Q_ID(q) +#define MT_TXQ_ID(q) MT_Q_ID(__TXQ(q)) +#define MT_RXQ_ID(q) MT_Q_ID(__RXQ(q)) + +#define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300) +#define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300) +#define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500) + +#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \ + MT_MCUQ_ID(q)* 0x4) +#define MT_RXQ_BAND1_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \ + MT_RXQ_ID(q)* 0x4) +#define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \ + MT_TXQ_ID(q)* 0x4) + +#define MT_INT_SOURCE_CSR __REG(INT_SOURCE_CSR) +#define MT_INT_MASK_CSR __REG(INT_MASK_CSR) + +#define MT_INT1_SOURCE_CSR __REG(INT1_SOURCE_CSR) +#define MT_INT1_MASK_CSR __REG(INT1_MASK_CSR) -#define MT_INFRA_CFG_BASE 0xf1000 -#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) +#define MT_INT_RX_DONE_BAND0 BIT(16) +#define MT_INT_RX_DONE_BAND1 BIT(17) +#define MT_INT_RX_DONE_WM BIT(0) +#define MT_INT_RX_DONE_WA BIT(1) +#define MT_INT_RX_DONE_WA_MAIN BIT(1) +#define MT_INT_RX_DONE_WA_EXT BIT(2) +#define MT_INT_MCU_CMD BIT(29) +#define MT_INT_RX_DONE_BAND0_MT7916 BIT(22) +#define MT_INT_RX_DONE_BAND1_MT7916 BIT(23) +#define MT_INT_RX_DONE_WA_MAIN_MT7916 BIT(2) +#define MT_INT_RX_DONE_WA_EXT_MT7916 BIT(3) + +#define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)]) +#define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)]) + +#define MT_INT_RX_DONE_MCU (MT_INT_RX(MT_RXQ_MCU) | \ + MT_INT_RX(MT_RXQ_MCU_WA)) + +#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \ + MT_INT_RX(MT_RXQ_MAIN_WA)) + +#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \ + MT_INT_RX(MT_RXQ_BAND1_WA) | \ + MT_INT_RX(MT_RXQ_MAIN_WA)) + +#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \ + MT_INT_BAND0_RX_DONE | \ + MT_INT_BAND1_RX_DONE) + +#define MT_INT_TX_DONE_FWDL BIT(26) +#define MT_INT_TX_DONE_MCU_WM BIT(27) +#define MT_INT_TX_DONE_MCU_WA BIT(15) +#define MT_INT_TX_DONE_BAND0 BIT(30) +#define MT_INT_TX_DONE_BAND1 BIT(31) +#define MT_INT_TX_DONE_MCU_WA_MT7916 BIT(25) -#define MT_HIF_REMAP_L1 MT_INFRA(0x1ac) +#define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \ + MT_INT_TX_MCU(MT_MCUQ_WM) | \ + MT_INT_TX_MCU(MT_MCUQ_FWDL)) + +#define MT_MCU_CMD __REG(INT_MCU_CMD_SOURCE) +#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_DMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) + +/* TOP RGU */ +#define MT_TOP_RGU_BASE 0x18000000 +#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0)) +#define MT_TOP_PWR_KEY (0x5746 << 16) +#define MT_TOP_PWR_SW_RST BIT(0) +#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2) +#define MT_TOP_PWR_HW_CTRL BIT(4) +#define MT_TOP_PWR_PWR_ON BIT(7) + +#define MT_TOP_RGU_SYSRAM_PDN (MT_TOP_RGU_BASE + 0x050) +#define MT_TOP_RGU_SYSRAM_SLP (MT_TOP_RGU_BASE + 0x054) +#define MT_TOP_WFSYS_PWR (MT_TOP_RGU_BASE + 0x010) +#define MT_TOP_PWR_EN_MASK BIT(7) +#define MT_TOP_PWR_ACK_MASK BIT(6) +#define MT_TOP_PWR_KEY_MASK GENMASK(31, 16) + +#define MT7986_TOP_WM_RESET (MT_TOP_RGU_BASE + 0x120) +#define MT7986_TOP_WM_RESET_MASK BIT(0) + +/* l1/l2 remap */ +#define MT_HIF_REMAP_L1 0xf11ac +#define MT_HIF_REMAP_L1_MT7916 0xfe260 #define MT_HIF_REMAP_L1_MASK GENMASK(15, 0) #define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0) #define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) #define MT_HIF_REMAP_BASE_L1 0xe0000 -#define MT_HIF_REMAP_L2 MT_INFRA(0x1b0) +#define MT_HIF_REMAP_L2 0xf11b0 #define MT_HIF_REMAP_L2_MASK GENMASK(19, 0) #define MT_HIF_REMAP_L2_OFFSET GENMASK(11, 0) #define MT_HIF_REMAP_L2_BASE GENMASK(31, 12) -#define MT_HIF_REMAP_BASE_L2 0x00000 +#define MT_HIF_REMAP_L2_MT7916 0x1b8 +#define MT_HIF_REMAP_L2_MASK_MT7916 GENMASK(31, 16) +#define MT_HIF_REMAP_L2_OFFSET_MT7916 GENMASK(15, 0) +#define MT_HIF_REMAP_L2_BASE_MT7916 GENMASK(31, 16) +#define MT_HIF_REMAP_BASE_L2_MT7916 0x40000 + +#define MT_INFRA_BASE 0x18000000 +#define MT_WFSYS0_PHY_START 0x18400000 +#define MT_WFSYS1_PHY_START 0x18800000 +#define MT_WFSYS1_PHY_END 0x18bfffff +#define MT_CBTOP1_PHY_START 0x70000000 +#define MT_CBTOP1_PHY_END __REG(CBTOP1_PHY_END) +#define MT_CBTOP2_PHY_START 0xf0000000 +#define MT_CBTOP2_PHY_END 0xffffffff +#define MT_INFRA_MCU_START 0x7c000000 +#define MT_INFRA_MCU_END __REG(INFRA_MCU_ADDR_END) +#define MT_CONN_INFRA_OFFSET(p) ((p) - MT_INFRA_BASE) + +/* CONN INFRA CFG */ +#define MT_CONN_INFRA_BASE 0x18001000 +#define MT_CONN_INFRA(ofs) (MT_CONN_INFRA_BASE + (ofs)) + +#define MT_CONN_INFRA_EFUSE MT_CONN_INFRA(0x020) + +#define MT_CONN_INFRA_ADIE_RESET MT_CONN_INFRA(0x030) +#define MT_CONN_INFRA_ADIE1_RESET_MASK BIT(0) +#define MT_CONN_INFRA_ADIE2_RESET_MASK BIT(2) + +#define MT_CONN_INFRA_OSC_RC_EN MT_CONN_INFRA(0x380) + +#define MT_CONN_INFRA_OSC_CTRL MT_CONN_INFRA(0x300) +#define MT_CONN_INFRA_OSC_RC_EN_MASK BIT(7) +#define MT_CONN_INFRA_OSC_STB_TIME_MASK GENMASK(23, 0) + +#define MT_CONN_INFRA_HW_CTRL MT_CONN_INFRA(0x200) +#define MT_CONN_INFRA_HW_CTRL_MASK BIT(0) + +#define MT_CONN_INFRA_WF_SLP_PROT MT_CONN_INFRA(0x540) +#define MT_CONN_INFRA_WF_SLP_PROT_MASK BIT(0) + +#define MT_CONN_INFRA_WF_SLP_PROT_RDY MT_CONN_INFRA(0x544) +#define MT_CONN_INFRA_CONN_WF_MASK (BIT(29) | BIT(31)) +#define MT_CONN_INFRA_CONN (BIT(25) | BIT(29) | BIT(31)) + +#define MT_CONN_INFRA_EMI_REQ MT_CONN_INFRA(0x414) +#define MT_CONN_INFRA_EMI_REQ_MASK BIT(0) +#define MT_CONN_INFRA_INFRA_REQ_MASK BIT(5) + +/* AFE */ +#define MT_AFE_CTRL_BASE(_band) (0x18003000 + ((_band) << 19)) +#define MT_AFE_CTRL(_band, ofs) (MT_AFE_CTRL_BASE(_band) + (ofs)) + +#define MT_AFE_DIG_EN_01(_band) MT_AFE_CTRL(_band, 0x00) +#define MT_AFE_DIG_EN_02(_band) MT_AFE_CTRL(_band, 0x04) +#define MT_AFE_DIG_EN_03(_band) MT_AFE_CTRL(_band, 0x08) +#define MT_AFE_DIG_TOP_01(_band) MT_AFE_CTRL(_band, 0x0c) + +#define MT_AFE_PLL_STB_TIME(_band) MT_AFE_CTRL(_band, 0xf4) +#define MT_AFE_PLL_STB_TIME_MASK (GENMASK(30, 16) | GENMASK(14, 0)) +#define MT_AFE_PLL_STB_TIME_VAL (FIELD_PREP(GENMASK(30, 16), 0x4bc) | \ + FIELD_PREP(GENMASK(14, 0), 0x7e4)) +#define MT_AFE_BPLL_CFG_MASK GENMASK(7, 6) +#define MT_AFE_WPLL_CFG_MASK GENMASK(1, 0) +#define MT_AFE_MCU_WPLL_CFG_MASK GENMASK(3, 2) +#define MT_AFE_MCU_BPLL_CFG_MASK GENMASK(17, 16) +#define MT_AFE_PLL_CFG_MASK (MT_AFE_BPLL_CFG_MASK | \ + MT_AFE_WPLL_CFG_MASK | \ + MT_AFE_MCU_WPLL_CFG_MASK | \ + MT_AFE_MCU_BPLL_CFG_MASK) +#define MT_AFE_PLL_CFG_VAL (FIELD_PREP(MT_AFE_BPLL_CFG_MASK, 0x1) | \ + FIELD_PREP(MT_AFE_WPLL_CFG_MASK, 0x2) | \ + FIELD_PREP(MT_AFE_MCU_WPLL_CFG_MASK, 0x1) | \ + FIELD_PREP(MT_AFE_MCU_BPLL_CFG_MASK, 0x2)) + +#define MT_AFE_DIG_TOP_01_MASK GENMASK(18, 15) +#define MT_AFE_DIG_TOP_01_VAL FIELD_PREP(MT_AFE_DIG_TOP_01_MASK, 0x9) + +#define MT_AFE_RG_WBG_EN_RCK_MASK BIT(0) +#define MT_AFE_RG_WBG_EN_BPLL_UP_MASK BIT(21) +#define MT_AFE_RG_WBG_EN_WPLL_UP_MASK BIT(20) +#define MT_AFE_RG_WBG_EN_PLL_UP_MASK (MT_AFE_RG_WBG_EN_BPLL_UP_MASK | \ + MT_AFE_RG_WBG_EN_WPLL_UP_MASK) +#define MT_AFE_RG_WBG_EN_TXCAL_MASK GENMASK(21, 17) + +#define MT_ADIE_SLP_CTRL_BASE(_band) (0x18005000 + ((_band) << 19)) +#define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs)) + +#define MT_ADIE_SLP_CTRL_CK0(_band) MT_ADIE_SLP_CTRL(_band, 0x120) + +/* ADIE */ +#define MT_ADIE_CHIP_ID 0x02c +#define MT_ADIE_VERSION_MASK GENMASK(15, 0) +#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16) +#define MT_ADIE_IDX0 GENMASK(15, 0) +#define MT_ADIE_IDX1 GENMASK(31, 16) + +#define MT_ADIE_RG_TOP_THADC_BG 0x034 +#define MT_ADIE_VRPI_SEL_CR_MASK GENMASK(15, 12) +#define MT_ADIE_VRPI_SEL_EFUSE_MASK GENMASK(6, 3) + +#define MT_ADIE_RG_TOP_THADC 0x038 +#define MT_ADIE_PGA_GAIN_MASK GENMASK(25, 23) +#define MT_ADIE_PGA_GAIN_EFUSE_MASK GENMASK(2, 0) +#define MT_ADIE_LDO_CTRL_MASK GENMASK(27, 26) +#define MT_ADIE_LDO_CTRL_EFUSE_MASK GENMASK(6, 5) + +#define MT_AFE_RG_ENCAL_WBTAC_IF_SW 0x070 +#define MT_ADIE_EFUSE_RDATA0 0x130 + +#define MT_ADIE_EFUSE2_CTRL 0x148 +#define MT_ADIE_EFUSE_CTRL_MASK BIT(1) + +#define MT_ADIE_EFUSE_CFG 0x144 +#define MT_ADIE_EFUSE_MODE_MASK GENMASK(7, 6) +#define MT_ADIE_EFUSE_ADDR_MASK GENMASK(25, 16) +#define MT_ADIE_EFUSE_VALID_MASK BIT(29) +#define MT_ADIE_EFUSE_KICK_MASK BIT(30) + +#define MT_ADIE_THADC_ANALOG 0x3a6 + +#define MT_ADIE_THADC_SLOP 0x3a7 +#define MT_ADIE_ANA_EN_MASK BIT(7) + +#define MT_ADIE_7975_XTAL_CAL 0x3a1 +#define MT_ADIE_TRIM_MASK GENMASK(6, 0) +#define MT_ADIE_EFUSE_TRIM_MASK GENMASK(5, 0) +#define MT_ADIE_XO_TRIM_EN_MASK BIT(7) +#define MT_ADIE_XTAL_DECREASE_MASK BIT(6) + +#define MT_ADIE_7975_XO_TRIM2 0x3a2 +#define MT_ADIE_7975_XO_TRIM3 0x3a3 +#define MT_ADIE_7975_XO_TRIM4 0x3a4 +#define MT_ADIE_7975_XTAL_EN 0x3a5 + +#define MT_ADIE_XO_TRIM_FLOW 0x3ac +#define MT_ADIE_XTAL_AXM_80M_OSC 0x390 +#define MT_ADIE_XTAL_AXM_40M_OSC 0x391 +#define MT_ADIE_XTAL_TRIM1_80M_OSC 0x398 +#define MT_ADIE_XTAL_TRIM1_40M_OSC 0x399 +#define MT_ADIE_WRI_CK_SEL 0x4ac +#define MT_ADIE_RG_STRAP_PIN_IN 0x4fc +#define MT_ADIE_XTAL_C1 0x654 +#define MT_ADIE_XTAL_C2 0x658 +#define MT_ADIE_RG_XO_01 0x65c +#define MT_ADIE_RG_XO_03 0x664 + +#define MT_ADIE_CLK_EN 0xa00 + +#define MT_ADIE_7975_XTAL 0xa18 +#define MT_ADIE_7975_XTAL_EN_MASK BIT(29) + +#define MT_ADIE_7975_COCLK 0xa1c +#define MT_ADIE_7975_XO_2 0xa84 +#define MT_ADIE_7975_XO_2_FIX_EN BIT(31) + +#define MT_ADIE_7975_XO_CTRL2 0xa94 +#define MT_ADIE_7975_XO_CTRL2_C1_MASK GENMASK(26, 20) +#define MT_ADIE_7975_XO_CTRL2_C2_MASK GENMASK(18, 12) +#define MT_ADIE_7975_XO_CTRL2_MASK (MT_ADIE_7975_XO_CTRL2_C1_MASK | \ + MT_ADIE_7975_XO_CTRL2_C2_MASK) + +#define MT_ADIE_7975_XO_CTRL6 0xaa4 +#define MT_ADIE_7975_XO_CTRL6_MASK BIT(16) + +/* TOP SPI */ +#define MT_TOP_SPI_ADIE_BASE(_band) (0x18004000 + ((_band) << 19)) +#define MT_TOP_SPI_ADIE(_band, ofs) (MT_TOP_SPI_ADIE_BASE(_band) + (ofs)) + +#define MT_TOP_SPI_BUSY_CR(_band) MT_TOP_SPI_ADIE(_band, 0) +#define MT_TOP_SPI_POLLING_BIT BIT(5) + +#define MT_TOP_SPI_ADDR_CR(_band) MT_TOP_SPI_ADIE(_band, 0x50) +#define MT_TOP_SPI_READ_ADDR_FORMAT (BIT(12) | BIT(13) | BIT(15)) +#define MT_TOP_SPI_WRITE_ADDR_FORMAT (BIT(13) | BIT(15)) + +#define MT_TOP_SPI_WRITE_DATA_CR(_band) MT_TOP_SPI_ADIE(_band, 0x54) +#define MT_TOP_SPI_READ_DATA_CR(_band) MT_TOP_SPI_ADIE(_band, 0x58) + +/* CONN INFRA CKGEN */ +#define MT_INFRA_CKGEN_BASE 0x18009000 +#define MT_INFRA_CKGEN(ofs) (MT_INFRA_CKGEN_BASE + (ofs)) + +#define MT_INFRA_CKGEN_BUS MT_INFRA_CKGEN(0xa00) +#define MT_INFRA_CKGEN_BUS_CLK_SEL_MASK BIT(23) +#define MT_INFRA_CKGEN_BUS_RDY_SEL_MASK BIT(29) + +#define MT_INFRA_CKGEN_BUS_WPLL_DIV_1 MT_INFRA_CKGEN(0x008) +#define MT_INFRA_CKGEN_BUS_WPLL_DIV_2 MT_INFRA_CKGEN(0x00c) + +#define MT_INFRA_CKGEN_RFSPI_WPLL_DIV MT_INFRA_CKGEN(0x040) +#define MT_INFRA_CKGEN_DIV_SEL_MASK GENMASK(7, 2) +#define MT_INFRA_CKGEN_DIV_EN_MASK BIT(0) + +/* CONN INFRA BUS */ +#define MT_INFRA_BUS_BASE 0x1800e000 +#define MT_INFRA_BUS(ofs) (MT_INFRA_BUS_BASE + (ofs)) + +#define MT_INFRA_BUS_OFF_TIMEOUT MT_INFRA_BUS(0x300) +#define MT_INFRA_BUS_TIMEOUT_LIMIT_MASK GENMASK(14, 7) +#define MT_INFRA_BUS_TIMEOUT_EN_MASK GENMASK(3, 0) + +#define MT_INFRA_BUS_ON_TIMEOUT MT_INFRA_BUS(0x31c) +#define MT_INFRA_BUS_EMI_START MT_INFRA_BUS(0x360) +#define MT_INFRA_BUS_EMI_END MT_INFRA_BUS(0x364) + +/* CONN_INFRA_SKU */ +#define MT_CONNINFRA_SKU_DEC_ADDR 0x18050000 +#define MT_CONNINFRA_SKU_MASK GENMASK(15, 0) +#define MT_ADIE_TYPE_MASK BIT(1) + +/* FW MODE SYNC */ +#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR) + +#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR) + +#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) +#define MT_SWDEF_MODE MT_SWDEF(0x3c) +#define MT_SWDEF_NORMAL_MODE 0 +#define MT_SWDEF_ICAP_MODE 1 +#define MT_SWDEF_SPECTRUM_MODE 2 + +#define MT_SWDEF_SER_STATS MT_SWDEF(0x040) +#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044) +#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048) +#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C) +#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050) +#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054) +#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058) +#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C) +#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x060) +#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x064) #define MT_DIC_CMD_REG_BASE 0x41f000 #define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs)) @@ -540,13 +971,7 @@ #define MT_CPU_UTIL_PEAK_IDLE_CNT MT_CPU_UTIL(0x0c) #define MT_CPU_UTIL_CTRL MT_CPU_UTIL(0x1c) -#define MT_SWDEF_BASE 0x41f200 -#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) -#define MT_SWDEF_MODE MT_SWDEF(0x3c) -#define MT_SWDEF_NORMAL_MODE 0 -#define MT_SWDEF_ICAP_MODE 1 -#define MT_SWDEF_SPECTRUM_MODE 2 - +/* LED */ #define MT_LED_TOP_BASE 0x18013000 #define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n)) @@ -561,46 +986,127 @@ #define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4)) +#define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */ +#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */ +#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8) + +/* MT TOP */ #define MT_TOP_BASE 0x18060000 #define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) -#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) +#define MT_TOP_LPCR_HOST_BAND(_band) MT_TOP(0x10 + ((_band) * 0x10)) #define MT_TOP_LPCR_HOST_FW_OWN BIT(0) #define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) +#define MT_TOP_LPCR_HOST_FW_OWN_STAT BIT(2) + +#define MT_TOP_LPCR_HOST_BAND_IRQ_STAT(_band) MT_TOP(0x14 + ((_band) * 0x10)) +#define MT_TOP_LPCR_HOST_BAND_STAT BIT(0) #define MT_TOP_MISC MT_TOP(0xf0) #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) -#define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */ -#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */ -#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8) +#define MT_TOP_WFSYS_WAKEUP MT_TOP(0x1a4) +#define MT_TOP_WFSYS_WAKEUP_MASK BIT(0) + +#define MT_TOP_MCU_EMI_BASE MT_TOP(0x1c4) +#define MT_TOP_MCU_EMI_BASE_MASK GENMASK(19, 0) + +#define MT_TOP_CONN_INFRA_WAKEUP MT_TOP(0x1a0) +#define MT_TOP_CONN_INFRA_WAKEUP_MASK BIT(0) + +#define MT_TOP_WFSYS_RESET_STATUS MT_TOP(0x2cc) +#define MT_TOP_WFSYS_RESET_STATUS_MASK BIT(30) + +/* SEMA */ +#define MT_SEMA_BASE 0x18070000 +#define MT_SEMA(ofs) (MT_SEMA_BASE + (ofs)) + +#define MT_SEMA_RFSPI_STATUS (MT_SEMA(0x2000) + (11 * 4)) +#define MT_SEMA_RFSPI_RELEASE (MT_SEMA(0x2200) + (11 * 4)) +#define MT_SEMA_RFSPI_STATUS_MASK BIT(1) + +/* MCU BUS */ +#define MT_MCU_BUS_BASE 0x18400000 +#define MT_MCU_BUS(ofs) (MT_MCU_BUS_BASE + (ofs)) + +#define MT_MCU_BUS_TIMEOUT MT_MCU_BUS(0xf0440) +#define MT_MCU_BUS_TIMEOUT_SET_MASK GENMASK(7, 0) +#define MT_MCU_BUS_TIMEOUT_CG_EN_MASK BIT(28) +#define MT_MCU_BUS_TIMEOUT_EN_MASK BIT(31) + +#define MT_MCU_BUS_REMAP MT_MCU_BUS(0x120) + +/* TOP CFG */ +#define MT_TOP_CFG_BASE 0x184b0000 +#define MT_TOP_CFG(ofs) (MT_TOP_CFG_BASE + (ofs)) + +#define MT_TOP_CFG_IP_VERSION_ADDR MT_TOP_CFG(0x010) + +/* TOP CFG ON */ +#define MT_TOP_CFG_ON_BASE 0x184c1000 +#define MT_TOP_CFG_ON(ofs) (MT_TOP_CFG_ON_BASE + (ofs)) + +#define MT_TOP_CFG_ON_ROM_IDX MT_TOP_CFG_ON(0x604) + +/* SLP CTRL */ +#define MT_SLP_BASE 0x184c3000 +#define MT_SLP(ofs) (MT_SLP_BASE + (ofs)) + +#define MT_SLP_STATUS MT_SLP(0x00c) +#define MT_SLP_WFDMA2CONN_MASK (BIT(21) | BIT(23)) +#define MT_SLP_CTRL_EN_MASK BIT(0) +#define MT_SLP_CTRL_BSY_MASK BIT(1) + +/* MCU BUS DBG */ +#define MT_MCU_BUS_DBG_BASE 0x18500000 +#define MT_MCU_BUS_DBG(ofs) (MT_MCU_BUS_DBG_BASE + (ofs)) + +#define MT_MCU_BUS_DBG_TIMEOUT MT_MCU_BUS_DBG(0x0) +#define MT_MCU_BUS_DBG_TIMEOUT_SET_MASK GENMASK(31, 16) +#define MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK BIT(3) +#define MT_MCU_BUS_DBG_TIMEOUT_EN_MASK BIT(2) #define MT_HW_BOUND 0x70010020 -#define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 +#define MT_WF_SUBSYS_RST 0x70002600 -#define MT_PCIE1_MAC_BASE 0x74020000 -#define MT_PCIE1_MAC(ofs) (MT_PCIE1_MAC_BASE + (ofs)) -#define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188) - +/* PCIE MAC */ #define MT_PCIE_MAC_BASE 0x74030000 #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) -#define MT_WF_IRPI_BASE 0x83006000 -#define MT_WF_IRPI(ofs) (MT_WF_IRPI_BASE + ((ofs) << 16)) +#define MT_PCIE1_MAC_INT_ENABLE 0x74020188 +#define MT_PCIE1_MAC_INT_ENABLE_MT7916 0x74090188 + +#define MT_WM_MCU_PC 0x7c060204 +#define MT_WA_MCU_PC 0x7c06020c + +/* PP TOP */ +#define MT_WF_PP_TOP_BASE 0x820cc000 +#define MT_WF_PP_TOP(ofs) (MT_WF_PP_TOP_BASE + (ofs)) + +#define MT_WF_PP_TOP_RXQ_WFDMA_CF_5 MT_WF_PP_TOP(0x0e8) +#define MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK BIT(6) + +#define MT_WF_IRPI_BASE 0x83000000 +#define MT_WF_IRPI(ofs) (MT_WF_IRPI_BASE + (ofs)) + +#define MT_WF_IRPI_NSS(phy, nss) MT_WF_IRPI(0x6000 + ((phy) << 20) + ((nss) << 16)) +#define MT_WF_IRPI_NSS_MT7916(phy, nss) MT_WF_IRPI(0x1000 + ((phy) << 20) + ((nss) << 16)) -/* PHY: band 0(0x83080000), band 1(0x83090000) */ +/* PHY */ #define MT_WF_PHY_BASE 0x83080000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) #define MT_WF_PHY_RX_CTRL1(_phy) MT_WF_PHY(0x2004 + ((_phy) << 16)) +#define MT_WF_PHY_RX_CTRL1_MT7916(_phy) MT_WF_PHY(0x2004 + ((_phy) << 20)) #define MT_WF_PHY_RX_CTRL1_IPI_EN GENMASK(2, 0) #define MT_WF_PHY_RX_CTRL1_STSCNT_EN GENMASK(11, 9) #define MT_WF_PHY_RXTD12(_phy) MT_WF_PHY(0x8230 + ((_phy) << 16)) +#define MT_WF_PHY_RXTD12_MT7916(_phy) MT_WF_PHY(0x8230 + ((_phy) << 20)) #define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY BIT(18) -#define MT_WF_PHY_RXTD12_IRPI_SW_CLR BIT(29) +#define MT_WF_PHY_RXTD12_IRPI_SW_CLR BIT(29) #define MT_MCU_WM_CIRQ_BASE 0x89010000 #define MT_MCU_WM_CIRQ(ofs) (MT_MCU_WM_CIRQ_BASE + (ofs)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c new file mode 100644 index 000000000000..c74afa746251 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -0,0 +1,1243 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/consumer.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_reserved_mem.h> +#include <linux/of_gpio.h> +#include <linux/iopoll.h> +#include <linux/reset.h> +#include <linux/of_net.h> +#include <linux/clk.h> + +#include "mt7915.h" + +/* INFRACFG */ +#define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0 +#define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4 + +#define MT_INFRACFG_RX_EN_MASK BIT(16) +#define MT_INFRACFG_TX_RDY_MASK BIT(4) +#define MT_INFRACFG_TX_EN_MASK BIT(0) + +/* TOP POS */ +#define MT_TOP_POS_FAST_CTRL 0x114 +#define MT_TOP_POS_FAST_EN_MASK BIT(3) + +#define MT_TOP_POS_SKU 0x21c +#define MT_TOP_POS_SKU_MASK GENMASK(31, 28) +#define MT_TOP_POS_SKU_ADIE_DBDC_MASK BIT(2) + +enum { + ADIE_SB, + ADIE_DBDC +}; + +static int +mt76_wmac_spi_read(struct mt7915_dev *dev, u8 adie, u32 addr, u32 *val) +{ + int ret; + u32 cur; + + ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_SPI_BUSY_CR(adie)); + if (ret) + return ret; + + mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie), + MT_TOP_SPI_READ_ADDR_FORMAT | addr); + mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), 0); + + ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_SPI_BUSY_CR(adie)); + if (ret) + return ret; + + *val = mt76_rr(dev, MT_TOP_SPI_READ_DATA_CR(adie)); + + return 0; +} + +static int +mt76_wmac_spi_write(struct mt7915_dev *dev, u8 adie, u32 addr, u32 val) +{ + int ret; + u32 cur; + + ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_SPI_BUSY_CR(adie)); + if (ret) + return ret; + + mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie), + MT_TOP_SPI_WRITE_ADDR_FORMAT | addr); + mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), val); + + return read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_SPI_BUSY_CR(adie)); +} + +static int +mt76_wmac_spi_rmw(struct mt7915_dev *dev, u8 adie, + u32 addr, u32 mask, u32 val) +{ + u32 cur, ret; + + ret = mt76_wmac_spi_read(dev, adie, addr, &cur); + if (ret) + return ret; + + cur &= ~mask; + cur |= val; + + return mt76_wmac_spi_write(dev, adie, addr, cur); +} + +static int +mt7986_wmac_adie_efuse_read(struct mt7915_dev *dev, u8 adie, + u32 addr, u32 *data) +{ + int ret, temp; + u32 val, mask; + + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_EFUSE_CFG, + MT_ADIE_EFUSE_CTRL_MASK); + if (ret) + return ret; + + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, BIT(30), 0x0); + if (ret) + return ret; + + mask = (MT_ADIE_EFUSE_MODE_MASK | MT_ADIE_EFUSE_ADDR_MASK | + MT_ADIE_EFUSE_KICK_MASK); + val = FIELD_PREP(MT_ADIE_EFUSE_MODE_MASK, 0) | + FIELD_PREP(MT_ADIE_EFUSE_ADDR_MASK, addr) | + FIELD_PREP(MT_ADIE_EFUSE_KICK_MASK, 1); + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, mask, val); + if (ret) + return ret; + + ret = read_poll_timeout(mt76_wmac_spi_read, temp, + !temp && !FIELD_GET(MT_ADIE_EFUSE_KICK_MASK, val), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, adie, MT_ADIE_EFUSE2_CTRL, &val); + if (ret) + return ret; + + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE2_CTRL, &val); + if (ret) + return ret; + + if (FIELD_GET(MT_ADIE_EFUSE_VALID_MASK, val) == 1) + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE_RDATA0, + data); + + return ret; +} + +static inline void mt76_wmac_spi_lock(struct mt7915_dev *dev) +{ + u32 cur; + + read_poll_timeout(mt76_rr, cur, + FIELD_GET(MT_SEMA_RFSPI_STATUS_MASK, cur), + 1000, 1000 * MSEC_PER_SEC, false, dev, + MT_SEMA_RFSPI_STATUS); +} + +static inline void mt76_wmac_spi_unlock(struct mt7915_dev *dev) +{ + mt76_wr(dev, MT_SEMA_RFSPI_RELEASE, 1); +} + +static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) +{ + val |= readl(base + offset) & ~mask; + writel(val, base + offset); + + return val; +} + +static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev) +{ + u32 val; + + val = readl(dev->sku + MT_TOP_POS_SKU); + + return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val); +} + +static int mt7986_wmac_consys_reset(struct mt7915_dev *dev, bool enable) +{ + if (!enable) + return reset_control_assert(dev->rstc); + + mt76_wmac_rmw(dev->sku, MT_TOP_POS_FAST_CTRL, + MT_TOP_POS_FAST_EN_MASK, + FIELD_PREP(MT_TOP_POS_FAST_EN_MASK, 0x1)); + + return reset_control_deassert(dev->rstc); +} + +static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev) +{ + struct pinctrl_state *state; + struct pinctrl *pinctrl; + int ret; + u8 type; + + type = mt7986_wmac_check_adie_type(dev); + pinctrl = devm_pinctrl_get(dev->mt76.dev); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); + + switch (type) { + case ADIE_SB: + state = pinctrl_lookup_state(pinctrl, "default"); + if (IS_ERR_OR_NULL(state)) + return -EINVAL; + break; + case ADIE_DBDC: + state = pinctrl_lookup_state(pinctrl, "dbdc"); + if (IS_ERR_OR_NULL(state)) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = pinctrl_select_state(pinctrl, state); + if (ret) + return ret; + + usleep_range(500, 1000); + + return 0; +} + +static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable) +{ + int ret; + u32 cur; + + mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT, + MT_INFRACFG_RX_EN_MASK, + FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable)); + ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_RX_EN_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT); + if (ret) + return ret; + + mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT, + MT_INFRACFG_TX_EN_MASK, + FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable)); + ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_TX_RDY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT); + if (ret) + return ret; + + mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT, + MT_INFRACFG_RX_EN_MASK, + FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable)); + mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT, + MT_INFRACFG_TX_EN_MASK, + FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable)); + + return 0; +} + +static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev) +{ + u32 cur; + + return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, + false, dev, MT_CONN_INFRA_BASE); +} + +static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) +{ + struct device *pdev = dev->mt76.dev; + struct reserved_mem *rmem; + struct device_node *np; + u32 val; + + np = of_parse_phandle(pdev->of_node, "memory-region", 0); + if (!np) + return -EINVAL; + + rmem = of_reserved_mem_lookup(np); + if (!rmem) + return -EINVAL; + + val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK; + + /* Set conninfra subsys PLL check */ + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + + mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE, + MT_TOP_MCU_EMI_BASE_MASK, val); + + mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base); + mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size); + + mt76_rr(dev, MT_CONN_INFRA_EFUSE); + + /* Set conninfra sysram */ + mt76_wr(dev, MT_TOP_RGU_SYSRAM_PDN, 0); + mt76_wr(dev, MT_TOP_RGU_SYSRAM_SLP, 1); + + return 0; +} + +static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) +{ + int ret; + u32 adie_main, adie_ext; + + mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, + MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1); + mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, + MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); + + mt76_wmac_spi_lock(dev); + + ret = mt76_wmac_spi_read(dev, 0, MT_ADIE_CHIP_ID, &adie_main); + if (ret) + goto out; + + ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); + if (ret) + goto out; + + *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) | + (MT_ADIE_CHIP_ID_MASK & adie_ext); + +out: + mt76_wmac_spi_unlock(dev); + + return 0; +} + +static inline u16 mt7986_adie_idx(u8 adie, u32 adie_type) +{ + if (adie == 0) + return u32_get_bits(adie_type, MT_ADIE_IDX0); + else + return u32_get_bits(adie_type, MT_ADIE_IDX1); +} + +static inline bool is_7975(struct mt7915_dev *dev, u8 adie, u32 adie_type) +{ + return mt7986_adie_idx(adie, adie_type) == 0x7975; +} + +static inline bool is_7976(struct mt7915_dev *dev, u8 adie, u32 adie_type) +{ + return mt7986_adie_idx(adie, adie_type) == 0x7976; +} + +static int mt7986_wmac_adie_thermal_cal(struct mt7915_dev *dev, u8 adie) +{ + int ret; + u32 data, val; + + ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_ANALOG, + &data); + if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) { + val = FIELD_GET(MT_ADIE_VRPI_SEL_EFUSE_MASK, data); + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC_BG, + MT_ADIE_VRPI_SEL_CR_MASK, + FIELD_PREP(MT_ADIE_VRPI_SEL_CR_MASK, val)); + if (ret) + return ret; + + val = FIELD_GET(MT_ADIE_PGA_GAIN_EFUSE_MASK, data); + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC, + MT_ADIE_PGA_GAIN_MASK, + FIELD_PREP(MT_ADIE_PGA_GAIN_MASK, val)); + if (ret) + return ret; + } + + ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_SLOP, + &data); + if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) { + val = FIELD_GET(MT_ADIE_LDO_CTRL_EFUSE_MASK, data); + + return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC, + MT_ADIE_LDO_CTRL_MASK, + FIELD_PREP(MT_ADIE_LDO_CTRL_MASK, val)); + } + + return 0; +} + +static int +mt7986_read_efuse_xo_trim_7976(struct mt7915_dev *dev, u8 adie, + bool is_40m, int *result) +{ + int ret; + u32 data, addr; + + addr = is_40m ? MT_ADIE_XTAL_AXM_40M_OSC : MT_ADIE_XTAL_AXM_80M_OSC; + ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); + if (ret) + return ret; + + if (!FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) { + *result = 64; + } else { + *result = FIELD_GET(MT_ADIE_TRIM_MASK, data); + addr = is_40m ? MT_ADIE_XTAL_TRIM1_40M_OSC : + MT_ADIE_XTAL_TRIM1_80M_OSC; + ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); + if (ret) + return ret; + + if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data) && + FIELD_GET(MT_ADIE_XTAL_DECREASE_MASK, data)) + *result -= FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data); + else if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) + *result += FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data); + + *result = max(0, min(127, *result)); + } + + return 0; +} + +static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie) +{ + int ret, trim_80m, trim_40m; + u32 data, val, mode; + + ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_XO_TRIM_FLOW, + &data); + if (ret || !FIELD_GET(BIT(1), data)) + return 0; + + ret = mt7986_read_efuse_xo_trim_7976(dev, adie, false, &trim_80m); + if (ret) + return ret; + + ret = mt7986_read_efuse_xo_trim_7976(dev, adie, true, &trim_40m); + if (ret) + return ret; + + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_RG_STRAP_PIN_IN, &val); + if (ret) + return ret; + + mode = FIELD_PREP(GENMASK(6, 4), val); + if (!mode || mode == 0x2) { + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1, + GENMASK(31, 24), + FIELD_PREP(GENMASK(31, 24), trim_80m)); + if (ret) + return ret; + + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2, + GENMASK(31, 24), + FIELD_PREP(GENMASK(31, 24), trim_80m)); + } else if (mode == 0x3 || mode == 0x4 || mode == 0x6) { + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1, + GENMASK(23, 16), + FIELD_PREP(GENMASK(23, 16), trim_40m)); + if (ret) + return ret; + + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2, + GENMASK(23, 16), + FIELD_PREP(GENMASK(23, 16), trim_40m)); + } + + return ret; +} + +static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) +{ + u32 id, version, rg_xo_01, rg_xo_03; + int ret; + + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id); + if (ret) + return ret; + + version = FIELD_GET(MT_ADIE_VERSION_MASK, id); + + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00); + if (ret) + return ret; + + if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) { + rg_xo_01 = 0x1d59080f; + rg_xo_03 = 0x34c00fe0; + } else { + rg_xo_01 = 0x1959f80f; + rg_xo_03 = 0x34d00fe0; + } + + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01); + if (ret) + return ret; + + return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03); +} + +static int +mt7986_read_efuse_xo_trim_7975(struct mt7915_dev *dev, u8 adie, + u32 addr, u32 *result) +{ + int ret; + u32 data; + + ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); + if (ret) + return ret; + + if ((data & MT_ADIE_XO_TRIM_EN_MASK)) { + if ((data & MT_ADIE_XTAL_DECREASE_MASK)) + *result -= (data & MT_ADIE_EFUSE_TRIM_MASK); + else + *result += (data & MT_ADIE_EFUSE_TRIM_MASK); + + *result = (*result & MT_ADIE_TRIM_MASK); + } + + return 0; +} + +static int mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev *dev, u8 adie) +{ + int ret; + u32 data, result = 0, value; + + ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_EN, + &data); + if (ret || !(data & BIT(1))) + return 0; + + ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_CAL, + &data); + if (ret) + return ret; + + if (data & MT_ADIE_XO_TRIM_EN_MASK) + result = (data & MT_ADIE_TRIM_MASK); + + ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM2, + &result); + if (ret) + return ret; + + ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM3, + &result); + if (ret) + return ret; + + ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM4, + &result); + if (ret) + return ret; + + /* Update trim value to C1 and C2*/ + value = FIELD_GET(MT_ADIE_7975_XO_CTRL2_C1_MASK, result) | + FIELD_GET(MT_ADIE_7975_XO_CTRL2_C2_MASK, result); + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL2, + MT_ADIE_7975_XO_CTRL2_MASK, value); + if (ret) + return ret; + + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_7975_XTAL, &value); + if (ret) + return ret; + + if (value & MT_ADIE_7975_XTAL_EN_MASK) { + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_2, + MT_ADIE_7975_XO_2_FIX_EN, 0x0); + if (ret) + return ret; + } + + return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL6, + MT_ADIE_7975_XO_CTRL6_MASK, 0x1); +} + +static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) +{ + int ret; + + /* disable CAL LDO and fine tune RFDIG LDO */ + ret = mt76_wmac_spi_write(dev, adie, 0x348, 0x00000002); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x378, 0x00000002); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x3a8, 0x00000002); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x3d8, 0x00000002); + if (ret) + return ret; + + /* set CKA driving and filter */ + ret = mt76_wmac_spi_write(dev, adie, 0xa1c, 0x30000aaa); + if (ret) + return ret; + + /* set CKB LDO to 1.4V */ + ret = mt76_wmac_spi_write(dev, adie, 0xa84, 0x8470008a); + if (ret) + return ret; + + /* turn on SX0 LTBUF */ + ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); + if (ret) + return ret; + + /* CK_BUF_SW_EN = 1 (all buf in manual mode.) */ + ret = mt76_wmac_spi_write(dev, adie, 0xaa4, 0x01001fc0); + if (ret) + return ret; + + /* BT mode/WF normal mode 00000005 */ + ret = mt76_wmac_spi_write(dev, adie, 0x070, 0x00000005); + if (ret) + return ret; + + /* BG thermal sensor offset update */ + ret = mt76_wmac_spi_write(dev, adie, 0x344, 0x00000088); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x374, 0x00000088); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x3a4, 0x00000088); + if (ret) + return ret; + + ret = mt76_wmac_spi_write(dev, adie, 0x3d4, 0x00000088); + if (ret) + return ret; + + /* set WCON VDD IPTAT to "0000" */ + ret = mt76_wmac_spi_write(dev, adie, 0xa80, 0x44d07000); + if (ret) + return ret; + + /* change back LTBUF SX3 drving to default value */ + ret = mt76_wmac_spi_write(dev, adie, 0xa88, 0x3900aaaa); + if (ret) + return ret; + + /* SM input cap off */ + ret = mt76_wmac_spi_write(dev, adie, 0x2c4, 0x00000000); + if (ret) + return ret; + + /* set CKB driving and filter */ + return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); +} + +static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) +{ + int ret; + + mt76_wmac_spi_lock(dev); + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_CLK_EN, ~0); + if (ret) + goto out; + + if (is_7975(dev, adie, adie_type)) { + ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_COCLK, + BIT(1), 0x1); + if (ret) + goto out; + + ret = mt7986_wmac_adie_thermal_cal(dev, adie); + if (ret) + goto out; + + ret = mt7986_wmac_adie_xtal_trim_7975(dev, adie); + if (ret) + goto out; + + ret = mt7986_wmac_adie_patch_7975(dev, adie); + } else if (is_7976(dev, adie, adie_type)) { + if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) { + ret = mt76_wmac_spi_write(dev, adie, + MT_ADIE_WRI_CK_SEL, 0x1c); + if (ret) + goto out; + } + + ret = mt7986_wmac_adie_thermal_cal(dev, adie); + if (ret) + goto out; + + ret = mt7986_wmac_adie_xtal_trim_7976(dev, adie); + if (ret) + goto out; + + ret = mt7986_wmac_adie_patch_7976(dev, adie); + } +out: + mt76_wmac_spi_unlock(dev); + + return ret; +} + +static int +mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) +{ + int ret; + u8 idx; + + mt76_wmac_spi_lock(dev); + if (is_7975(dev, adie, adie_type)) + ret = mt76_wmac_spi_write(dev, adie, + MT_AFE_RG_ENCAL_WBTAC_IF_SW, + 0x80000000); + else + ret = mt76_wmac_spi_write(dev, adie, + MT_AFE_RG_ENCAL_WBTAC_IF_SW, + 0x88888005); + if (ret) + goto out; + + idx = dbdc ? ADIE_DBDC : adie; + + mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), + MT_AFE_RG_WBG_EN_RCK_MASK, 0x1); + usleep_range(60, 100); + + mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), + MT_AFE_RG_WBG_EN_RCK_MASK, 0x0); + + mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx), + MT_AFE_RG_WBG_EN_BPLL_UP_MASK, 0x1); + usleep_range(30, 100); + + mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx), + MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1); + usleep_range(60, 100); + + mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), + MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f); + usleep_range(800, 1000); + + mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), + MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0); + mt76_rmw(dev, MT_AFE_DIG_EN_03(idx), + MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0); + + ret = mt76_wmac_spi_write(dev, adie, MT_AFE_RG_ENCAL_WBTAC_IF_SW, + 0x5); + +out: + mt76_wmac_spi_unlock(dev); + + return ret; +} + +static void mt7986_wmac_subsys_pll_initial(struct mt7915_dev *dev, u8 band) +{ + mt76_rmw(dev, MT_AFE_PLL_STB_TIME(band), + MT_AFE_PLL_STB_TIME_MASK, MT_AFE_PLL_STB_TIME_VAL); + + mt76_rmw(dev, MT_AFE_DIG_EN_02(band), + MT_AFE_PLL_CFG_MASK, MT_AFE_PLL_CFG_VAL); + + mt76_rmw(dev, MT_AFE_DIG_TOP_01(band), + MT_AFE_DIG_TOP_01_MASK, MT_AFE_DIG_TOP_01_VAL); +} + +static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev) +{ + /* Subsys pll init */ + mt7986_wmac_subsys_pll_initial(dev, 0); + mt7986_wmac_subsys_pll_initial(dev, 1); + + /* Set legacy OSC control stable time*/ + mt76_rmw(dev, MT_CONN_INFRA_OSC_RC_EN, + MT_CONN_INFRA_OSC_RC_EN_MASK, 0x0); + mt76_rmw(dev, MT_CONN_INFRA_OSC_CTRL, + MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706); + + /* prevent subsys from power on/of in a short time interval */ + mt76_rmw(dev, MT_TOP_WFSYS_PWR, + MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, + MT_TOP_PWR_KEY); +} + +static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev) +{ + mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT, + MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0x2); + + mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT, + MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); + + mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, + MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0xc); + + mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, + MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); + + return mt7986_wmac_coninfra_check(dev); +} + +static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type) +{ + u32 cur; + + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1, + MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2, + MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1, + MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2, + MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV, + MT_INFRA_CKGEN_DIV_SEL_MASK, 0x8); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV, + MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); + + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_CLK_SEL_MASK, 0x0); + + mt76_rmw_field(dev, MT_CONN_INFRA_HW_CTRL, + MT_CONN_INFRA_HW_CTRL_MASK, 0x1); + + mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, + MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1); + + usleep_range(900, 1000); + + mt76_wmac_spi_lock(dev); + if (is_7975(dev, 0, adie_type) || is_7976(dev, 0, adie_type)) { + mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(0), + MT_SLP_CTRL_EN_MASK, 0x1); + + read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_ADIE_SLP_CTRL_CK0(0)); + } + if (is_7975(dev, 1, adie_type) || is_7976(dev, 1, adie_type)) { + mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(1), + MT_SLP_CTRL_EN_MASK, 0x1); + + read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_ADIE_SLP_CTRL_CK0(0)); + } + mt76_wmac_spi_unlock(dev); + + mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, + MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0); + usleep_range(900, 1000); +} + +static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable) +{ + mt76_rmw_field(dev, MT_TOP_WFSYS_WAKEUP, + MT_TOP_WFSYS_WAKEUP_MASK, enable); + + usleep_range(900, 1000); + + if (!enable) + return 0; + + return mt7986_wmac_coninfra_check(dev); +} + +static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable) +{ + u32 cur; + + mt76_rmw_field(dev, MT7986_TOP_WM_RESET, + MT7986_TOP_WM_RESET_MASK, enable); + if (!enable) + return 0; + + return read_poll_timeout(mt76_rr, cur, (cur == 0x1d1e), + USEC_PER_MSEC, 5000 * USEC_PER_MSEC, false, + dev, MT_TOP_CFG_ON_ROM_IDX); +} + +static int mt7986_wmac_wfsys_poweron(struct mt7915_dev *dev, bool enable) +{ + u32 mask = MT_TOP_PWR_EN_MASK | MT_TOP_PWR_KEY_MASK; + u32 cur; + + mt76_rmw(dev, MT_TOP_WFSYS_PWR, mask, + MT_TOP_PWR_KEY | FIELD_PREP(MT_TOP_PWR_EN_MASK, enable)); + + return read_poll_timeout(mt76_rr, cur, + (FIELD_GET(MT_TOP_WFSYS_RESET_STATUS_MASK, cur) == enable), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_WFSYS_RESET_STATUS); +} + +static int mt7986_wmac_wfsys_setting(struct mt7915_dev *dev) +{ + int ret; + u32 cur; + + /* Turn off wfsys2conn bus sleep protect */ + mt76_rmw(dev, MT_CONN_INFRA_WF_SLP_PROT, + MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x0); + + ret = mt7986_wmac_wfsys_poweron(dev, true); + if (ret) + return ret; + + /* Check bus sleep protect */ + + ret = read_poll_timeout(mt76_rr, cur, + !(cur & MT_CONN_INFRA_CONN_WF_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_CONN_INFRA_WF_SLP_PROT_RDY); + if (ret) + return ret; + + ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_WFDMA2CONN_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_SLP_STATUS); + if (ret) + return ret; + + return read_poll_timeout(mt76_rr, cur, (cur == 0x02060000), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_TOP_CFG_IP_VERSION_ADDR); +} + +static void mt7986_wmac_wfsys_set_timeout(struct mt7915_dev *dev) +{ + u32 mask = MT_MCU_BUS_TIMEOUT_SET_MASK | + MT_MCU_BUS_TIMEOUT_CG_EN_MASK | + MT_MCU_BUS_TIMEOUT_EN_MASK; + u32 val = FIELD_PREP(MT_MCU_BUS_TIMEOUT_SET_MASK, 1) | + FIELD_PREP(MT_MCU_BUS_TIMEOUT_CG_EN_MASK, 1) | + FIELD_PREP(MT_MCU_BUS_TIMEOUT_EN_MASK, 1); + + mt76_rmw(dev, MT_MCU_BUS_TIMEOUT, mask, val); + + mt76_wr(dev, MT_MCU_BUS_REMAP, 0x810f0000); + + mask = MT_MCU_BUS_DBG_TIMEOUT_SET_MASK | + MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK | + MT_MCU_BUS_DBG_TIMEOUT_EN_MASK; + val = FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_SET_MASK, 0x3aa) | + FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK, 1) | + FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_EN_MASK, 1); + + mt76_rmw(dev, MT_MCU_BUS_DBG_TIMEOUT, mask, val); +} + +static int mt7986_wmac_sku_update(struct mt7915_dev *dev, u32 adie_type) +{ + u32 val; + + if (is_7976(dev, 0, adie_type) && is_7976(dev, 1, adie_type)) + val = 0xf; + else if (is_7975(dev, 0, adie_type) && is_7975(dev, 1, adie_type)) + val = 0xd; + else if (is_7976(dev, 0, adie_type)) + val = 0x7; + else if (is_7975(dev, 1, adie_type)) + val = 0x8; + else if (is_7976(dev, 1, adie_type)) + val = 0xa; + else + return -EINVAL; + + mt76_wmac_rmw(dev->sku, MT_TOP_POS_SKU, MT_TOP_POS_SKU_MASK, + FIELD_PREP(MT_TOP_POS_SKU_MASK, val)); + + mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, val); + + return 0; +} + +static int +mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type) +{ + int ret; + + if (!(is_7975(dev, adie, adie_type) || is_7976(dev, adie, adie_type))) + return 0; + + ret = mt7986_wmac_adie_cfg(dev, adie, adie_type); + if (ret) + return ret; + + ret = mt7986_wmac_afe_cal(dev, adie, false, adie_type); + if (ret) + return ret; + + if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC)) + ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type); + + return ret; +} + +static int mt7986_wmac_subsys_powerup(struct mt7915_dev *dev, u32 adie_type) +{ + int ret; + + mt7986_wmac_subsys_setting(dev); + + ret = mt7986_wmac_bus_timeout(dev); + if (ret) + return ret; + + mt7986_wmac_clock_enable(dev, adie_type); + + return 0; +} + +static int mt7986_wmac_wfsys_powerup(struct mt7915_dev *dev) +{ + int ret; + + ret = mt7986_wmac_wm_enable(dev, false); + if (ret) + return ret; + + ret = mt7986_wmac_wfsys_setting(dev); + if (ret) + return ret; + + mt7986_wmac_wfsys_set_timeout(dev); + + return mt7986_wmac_wm_enable(dev, true); +} + +int mt7986_wmac_enable(struct mt7915_dev *dev) +{ + int ret; + u32 adie_type; + + ret = mt7986_wmac_consys_reset(dev, true); + if (ret) + return ret; + + ret = mt7986_wmac_gpio_setup(dev); + if (ret) + return ret; + + ret = mt7986_wmac_consys_lockup(dev, false); + if (ret) + return ret; + + ret = mt7986_wmac_coninfra_check(dev); + if (ret) + return ret; + + ret = mt7986_wmac_coninfra_setup(dev); + if (ret) + return ret; + + ret = mt7986_wmac_sku_setup(dev, &adie_type); + if (ret) + return ret; + + ret = mt7986_wmac_adie_setup(dev, 0, adie_type); + if (ret) + return ret; + + ret = mt7986_wmac_adie_setup(dev, 1, adie_type); + if (ret) + return ret; + + ret = mt7986_wmac_subsys_powerup(dev, adie_type); + if (ret) + return ret; + + ret = mt7986_wmac_top_wfsys_wakeup(dev, true); + if (ret) + return ret; + + ret = mt7986_wmac_wfsys_powerup(dev); + if (ret) + return ret; + + return mt7986_wmac_sku_update(dev, adie_type); +} + +void mt7986_wmac_disable(struct mt7915_dev *dev) +{ + u32 cur; + + mt7986_wmac_top_wfsys_wakeup(dev, true); + + /* Turn on wfsys2conn bus sleep protect */ + mt76_rmw_field(dev, MT_CONN_INFRA_WF_SLP_PROT, + MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x1); + + /* Check wfsys2conn bus sleep protect */ + read_poll_timeout(mt76_rr, cur, !(cur ^ MT_CONN_INFRA_CONN), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, + dev, MT_CONN_INFRA_WF_SLP_PROT_RDY); + + mt7986_wmac_wfsys_poweron(dev, false); + + /* Turn back wpll setting */ + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2); + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2); + + /* Reset EMI */ + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_EMI_REQ_MASK, 0x1); + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_EMI_REQ_MASK, 0x0); + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_INFRA_REQ_MASK, 0x1); + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_INFRA_REQ_MASK, 0x0); + + mt7986_wmac_top_wfsys_wakeup(dev, false); + mt7986_wmac_consys_lockup(dev, true); + mt7986_wmac_consys_reset(dev, false); +} + +static int mt7986_wmac_init(struct mt7915_dev *dev) +{ + struct device *pdev = dev->mt76.dev; + struct platform_device *pfdev = to_platform_device(pdev); + struct clk *mcu_clk, *ap_conn_clk; + + mcu_clk = devm_clk_get(pdev, "mcu"); + if (IS_ERR(mcu_clk)) + dev_err(pdev, "mcu clock not found\n"); + else if (clk_prepare_enable(mcu_clk)) + dev_err(pdev, "mcu clock configuration failed\n"); + + ap_conn_clk = devm_clk_get(pdev, "ap2conn"); + if (IS_ERR(ap_conn_clk)) + dev_err(pdev, "ap2conn clock not found\n"); + else if (clk_prepare_enable(ap_conn_clk)) + dev_err(pdev, "ap2conn clock configuration failed\n"); + + dev->dcm = devm_platform_ioremap_resource(pfdev, 1); + if (IS_ERR(dev->dcm)) + return PTR_ERR(dev->dcm); + + dev->sku = devm_platform_ioremap_resource(pfdev, 2); + if (IS_ERR(dev->sku)) + return PTR_ERR(dev->sku); + + dev->rstc = devm_reset_control_get(pdev, "consys"); + if (IS_ERR(dev->rstc)) + return PTR_ERR(dev->rstc); + + return 0; +} + +static int mt7986_wmac_probe(struct platform_device *pdev) +{ + void __iomem *mem_base; + struct mt7915_dev *dev; + struct mt76_dev *mdev; + int irq, ret; + u32 chip_id; + + chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + mem_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mem_base)) { + dev_err(&pdev->dev, "Failed to get memory resource\n"); + return PTR_ERR(mem_base); + } + + dev = mt7915_mmio_probe(&pdev->dev, mem_base, chip_id); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + mdev = &dev->mt76; + ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto free_device; + + ret = mt7986_wmac_init(dev); + if (ret) + goto free_irq; + + mt7915_wfsys_reset(dev); + + ret = mt7915_register_device(dev); + if (ret) + goto free_irq; + + return 0; + +free_irq: + devm_free_irq(mdev->dev, irq, dev); + +free_device: + mt76_free_device(&dev->mt76); + + return ret; +} + +static int mt7986_wmac_remove(struct platform_device *pdev) +{ + struct mt7915_dev *dev = platform_get_drvdata(pdev); + + mt7915_unregister_device(dev); + + return 0; +} + +static const struct of_device_id mt7986_wmac_of_match[] = { + { .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 }, + {}, +}; + +struct platform_driver mt7986_wmac_driver = { + .driver = { + .name = "mt7986-wmac", + .of_match_table = mt7986_wmac_of_match, + }, + .probe = mt7986_wmac_probe, + .remove = mt7986_wmac_remove, +}; + +MODULE_FIRMWARE(MT7986_FIRMWARE_WA); +MODULE_FIRMWARE(MT7986_FIRMWARE_WM); +MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975); +MODULE_FIRMWARE(MT7986_ROM_PATCH); +MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c index 89aae323d29e..efb9bb8231e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -23,30 +23,16 @@ struct reg_band { u32 band[2]; }; -#define REG_BAND(_reg) \ - { .band[0] = MT_##_reg(0), .band[1] = MT_##_reg(1) } -#define REG_BAND_IDX(_reg, _idx) \ - { .band[0] = MT_##_reg(0, _idx), .band[1] = MT_##_reg(1, _idx) } - -static const struct reg_band reg_backup_list[] = { - REG_BAND_IDX(AGG_PCR0, 0), - REG_BAND_IDX(AGG_PCR0, 1), - REG_BAND_IDX(AGG_AWSCR0, 0), - REG_BAND_IDX(AGG_AWSCR0, 1), - REG_BAND_IDX(AGG_AWSCR0, 2), - REG_BAND_IDX(AGG_AWSCR0, 3), - REG_BAND(AGG_MRCR), - REG_BAND(TMAC_TFCR0), - REG_BAND(TMAC_TCR0), - REG_BAND(AGG_ATCR1), - REG_BAND(AGG_ATCR3), - REG_BAND(TMAC_TRCR0), - REG_BAND(TMAC_ICR0), - REG_BAND_IDX(ARB_DRNGR0, 0), - REG_BAND_IDX(ARB_DRNGR0, 1), - REG_BAND(WF_RFCR), - REG_BAND(WF_RFCR1), -}; +#define REG_BAND(_list, _reg) \ + { _list.band[0] = MT_##_reg(0); \ + _list.band[1] = MT_##_reg(1); } +#define REG_BAND_IDX(_list, _reg, _idx) \ + { _list.band[0] = MT_##_reg(0, _idx); \ + _list.band[1] = MT_##_reg(1, _idx); } + +#define TM_REG_MAX_ID 17 +static struct reg_band reg_backup_list[TM_REG_MAX_ID]; + static int mt7915_tm_set_tx_power(struct mt7915_phy *phy) @@ -182,13 +168,14 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu) } static int -mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min, +mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min, u16 cw_max, u16 txop) { + struct mt7915_vif *mvif = (struct mt7915_vif *)phy->monitor_vif->drv_priv; struct mt7915_mcu_tx req = { .total = 1 }; struct edca *e = &req.edca[0]; - e->queue = qid; + e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS; e->set = WMM_PARAM_SET; e->aifs = aifs; @@ -196,7 +183,7 @@ mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min, e->cw_max = cpu_to_le16(cw_max); e->txop = cpu_to_le16(txop); - return mt7915_mcu_update_edca(dev, &req); + return mt7915_mcu_update_edca(phy->dev, &req); } static int @@ -212,7 +199,6 @@ mt7915_tm_set_ipg_params(struct mt7915_phy *phy, u32 ipg, u8 mode) u8 slot_time = 9, sifs = TM_DEFAULT_SIFS; u8 aifsn = TM_MIN_AIFSN; u32 i2t_time, tr2t_time, txv_time; - bool ext_phy = phy != &dev->phy; u16 cw = 0; if (ipg < sig_ext + slot_time + sifs) @@ -242,29 +228,25 @@ mt7915_tm_set_ipg_params(struct mt7915_phy *phy, u32 ipg, u8 mode) ipg -= aifsn * slot_time; - if (ipg > TM_DEFAULT_SIFS) { - if (ipg < TM_MAX_SIFS) - sifs = ipg; - else - sifs = TM_MAX_SIFS; - } + if (ipg > TM_DEFAULT_SIFS) + sifs = min_t(u32, ipg, TM_MAX_SIFS); } done: - txv_time = mt76_get_field(dev, MT_TMAC_ATCR(ext_phy), + txv_time = mt76_get_field(dev, MT_TMAC_ATCR(phy->band_idx), MT_TMAC_ATCR_TXV_TOUT); txv_time *= 50; /* normal clock time */ i2t_time = (slot_time * 1000 - txv_time - BBP_PROC_TIME) / 50; tr2t_time = (sifs * 1000 - txv_time - BBP_PROC_TIME) / 50; - mt76_set(dev, MT_TMAC_TRCR0(ext_phy), + mt76_set(dev, MT_TMAC_TRCR0(phy->band_idx), FIELD_PREP(MT_TMAC_TRCR0_TR2T_CHK, tr2t_time) | FIELD_PREP(MT_TMAC_TRCR0_I2T_CHK, i2t_time)); mt7915_tm_set_slot_time(phy, slot_time, sifs); - return mt7915_tm_set_wmm_qid(dev, - mt7915_lmac_mapping(dev, IEEE80211_AC_BE), + return mt7915_tm_set_wmm_qid(phy, + mt76_connac_lmac_mapping(IEEE80211_AC_BE), aifsn, cw, cw, 0); } @@ -290,6 +272,8 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time) case MT76_TM_TX_MODE_OFDM: if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; else sband = &mphy->sband_2g.sband; @@ -351,51 +335,67 @@ mt7915_tm_reg_backup_restore(struct mt7915_phy *phy) { int n_regs = ARRAY_SIZE(reg_backup_list); struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; u32 *b = phy->test.reg_backup; int i; + REG_BAND_IDX(reg_backup_list[0], AGG_PCR0, 0); + REG_BAND_IDX(reg_backup_list[1], AGG_PCR0, 1); + REG_BAND_IDX(reg_backup_list[2], AGG_AWSCR0, 0); + REG_BAND_IDX(reg_backup_list[3], AGG_AWSCR0, 1); + REG_BAND_IDX(reg_backup_list[4], AGG_AWSCR0, 2); + REG_BAND_IDX(reg_backup_list[5], AGG_AWSCR0, 3); + REG_BAND(reg_backup_list[6], AGG_MRCR); + REG_BAND(reg_backup_list[7], TMAC_TFCR0); + REG_BAND(reg_backup_list[8], TMAC_TCR0); + REG_BAND(reg_backup_list[9], AGG_ATCR1); + REG_BAND(reg_backup_list[10], AGG_ATCR3); + REG_BAND(reg_backup_list[11], TMAC_TRCR0); + REG_BAND(reg_backup_list[12], TMAC_ICR0); + REG_BAND_IDX(reg_backup_list[13], ARB_DRNGR0, 0); + REG_BAND_IDX(reg_backup_list[14], ARB_DRNGR0, 1); + REG_BAND(reg_backup_list[15], WF_RFCR); + REG_BAND(reg_backup_list[16], WF_RFCR1); + if (phy->mt76->test.state == MT76_TM_STATE_OFF) { for (i = 0; i < n_regs; i++) - mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]); + mt76_wr(dev, reg_backup_list[i].band[phy->band_idx], b[i]); return; } - if (b) - return; + if (!b) { + b = devm_kzalloc(dev->mt76.dev, 4 * n_regs, GFP_KERNEL); + if (!b) + return; - b = devm_kzalloc(dev->mt76.dev, 4 * n_regs, GFP_KERNEL); - if (!b) - return; - - phy->test.reg_backup = b; - for (i = 0; i < n_regs; i++) - b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]); + phy->test.reg_backup = b; + for (i = 0; i < n_regs; i++) + b[i] = mt76_rr(dev, reg_backup_list[i].band[phy->band_idx]); + } - mt76_clear(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_MM_PROT | + mt76_clear(dev, MT_AGG_PCR0(phy->band_idx, 0), MT_AGG_PCR0_MM_PROT | MT_AGG_PCR0_GF_PROT | MT_AGG_PCR0_ERP_PROT | MT_AGG_PCR0_VHT_PROT | MT_AGG_PCR0_BW20_PROT | MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT); - mt76_set(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_PTA_WIN_DIS); + mt76_set(dev, MT_AGG_PCR0(phy->band_idx, 0), MT_AGG_PCR0_PTA_WIN_DIS); - mt76_wr(dev, MT_AGG_PCR0(ext_phy, 1), MT_AGG_PCR1_RTS0_NUM_THRES | + mt76_wr(dev, MT_AGG_PCR0(phy->band_idx, 1), MT_AGG_PCR1_RTS0_NUM_THRES | MT_AGG_PCR1_RTS0_LEN_THRES); - mt76_clear(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_BAR_CNT_LIMIT | + mt76_clear(dev, MT_AGG_MRCR(phy->band_idx), MT_AGG_MRCR_BAR_CNT_LIMIT | MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT | MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT); - mt76_rmw(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_RTS_FAIL_LIMIT | + mt76_rmw(dev, MT_AGG_MRCR(phy->band_idx), MT_AGG_MRCR_RTS_FAIL_LIMIT | MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, FIELD_PREP(MT_AGG_MRCR_RTS_FAIL_LIMIT, 1) | FIELD_PREP(MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, 1)); - mt76_wr(dev, MT_TMAC_TFCR0(ext_phy), 0); - mt76_clear(dev, MT_TMAC_TCR0(ext_phy), MT_TMAC_TCR0_TBTT_STOP_CTRL); + mt76_wr(dev, MT_TMAC_TFCR0(phy->band_idx), 0); + mt76_clear(dev, MT_TMAC_TCR0(phy->band_idx), MT_TMAC_TCR0_TBTT_STOP_CTRL); /* config rx filter for testmode rx */ - mt76_wr(dev, MT_WF_RFCR(ext_phy), 0xcf70a); - mt76_wr(dev, MT_WF_RFCR1(ext_phy), 0); + mt76_wr(dev, MT_WF_RFCR(phy->band_idx), 0xcf70a); + mt76_wr(dev, MT_WF_RFCR1(phy->band_idx), 0); } static void @@ -453,7 +453,7 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en) u8 tx_ant = td->tx_antenna_mask; if (phy != &dev->phy) - tx_ant >>= 2; + tx_ant >>= dev->chainshift; phy->test.spe_idx = spe_idx_map[tx_ant]; } } @@ -575,6 +575,8 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en) if (chandef->chan->band == NL80211_BAND_5GHZ) sband = &phy->mt76->sband_5g.sband; + else if (chandef->chan->band == NL80211_BAND_6GHZ) + sband = &phy->mt76->sband_6g.sband; else sband = &phy->mt76->sband_2g.sband; @@ -721,11 +723,11 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg) { struct mt7915_phy *phy = mphy->priv; struct mt7915_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; enum mt76_rxq_id q; void *rx, *rssi; u16 fcs_err; int i; + u32 cnt; rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX); if (!rx) @@ -769,9 +771,11 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg) nla_nest_end(msg, rx); - fcs_err = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); - q = ext_phy ? MT_RXQ_EXT : MT_RXQ_MAIN; + cnt = mt76_rr(dev, MT_MIB_SDR3(phy->band_idx)); + fcs_err = is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) : + FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt); + + q = phy->band_idx ? MT_RXQ_BAND1 : MT_RXQ_MAIN; mphy->test.rx_stats.packets[q] += fcs_err; mphy->test.rx_stats.fcs_error[q] += fcs_err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig index 71154fc2a87c..adff2d7350b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig @@ -24,3 +24,14 @@ config MT7921S This adds support for MT7921S 802.11ax 2x2:2SS wireless devices. To compile this driver as a module, choose M here. + +config MT7921U + tristate "MediaTek MT7921U (USB) support" + select MT76_USB + select MT7921_COMMON + depends on MAC80211 + depends on USB + help + This adds support for MT7921U 802.11ax 2x2:2SS wireless devices. + + To compile this driver as a module, choose M here. diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index 1187acedfeda..e5d2d2e131a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -3,10 +3,13 @@ obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o obj-$(CONFIG_MT7921E) += mt7921e.o obj-$(CONFIG_MT7921S) += mt7921s.o +obj-$(CONFIG_MT7921U) += mt7921u.o CFLAGS_trace.o := -I$(src) mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o +mt7921-common-$(CONFIG_ACPI) += acpi_sar.o mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o +mt7921u-y := usb.o usb_mac.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c new file mode 100644 index 000000000000..47e034a9b003 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. */ + +#include <linux/acpi.h> +#include "mt7921.h" + +static int +mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *sar_root, *sar_unit; + struct mt76_dev *mdev = &dev->mt76; + acpi_handle root, handle; + acpi_status status; + u32 i = 0; + int ret; + + root = ACPI_HANDLE(mdev->dev); + if (!root) + return -EOPNOTSUPP; + + status = acpi_get_handle(root, method, &handle); + if (ACPI_FAILURE(status)) + return -EIO; + + status = acpi_evaluate_object(handle, NULL, NULL, &buf); + if (ACPI_FAILURE(status)) + return -EIO; + + sar_root = buf.pointer; + if (sar_root->type != ACPI_TYPE_PACKAGE || + sar_root->package.count < 4 || + sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) { + dev_err(mdev->dev, "sar cnt = %d\n", + sar_root->package.count); + goto free; + } + + if (!*tbl) { + *tbl = devm_kzalloc(mdev->dev, sar_root->package.count, + GFP_KERNEL); + if (!*tbl) + goto free; + } + if (len) + *len = sar_root->package.count; + + for (i = 0; i < sar_root->package.count; i++) { + sar_unit = &sar_root->package.elements[i]; + + if (sar_unit->type != ACPI_TYPE_INTEGER) + break; + *(*tbl + i) = (u8)sar_unit->integer.value; + } +free: + ret = (i == sar_root->package.count) ? 0 : -EINVAL; + + kfree(sar_root); + + return ret; +} + +/* MTCL : Country List Table for 6G band */ +static int +mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version) +{ + *version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0) + ? 1 : 2; + return 0; +} + +/* MTDS : Dynamic SAR Power Table */ +static int +mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version) +{ + int len, ret, sarlen, prelen, tblcnt; + bool enable; + + ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len); + if (ret) + return ret; + + /* Table content validation */ + switch (version) { + case 1: + enable = ((struct mt7921_asar_dyn *)*table)->enable; + sarlen = sizeof(struct mt7921_asar_dyn_limit); + prelen = sizeof(struct mt7921_asar_dyn); + break; + case 2: + enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable; + sarlen = sizeof(struct mt7921_asar_dyn_limit_v2); + prelen = sizeof(struct mt7921_asar_dyn_v2); + break; + default: + return -EINVAL; + } + + tblcnt = (len - prelen) / sarlen; + if (!enable || + tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN) + ret = -EINVAL; + + return ret; +} + +/* MTGS : Geo SAR Power Table */ +static int +mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version) +{ + int len, ret = 0, sarlen, prelen, tblcnt; + + ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len); + if (ret) + return ret; + + /* Table content validation */ + switch (version) { + case 1: + sarlen = sizeof(struct mt7921_asar_geo_limit); + prelen = sizeof(struct mt7921_asar_geo); + break; + case 2: + sarlen = sizeof(struct mt7921_asar_geo_limit_v2); + prelen = sizeof(struct mt7921_asar_geo_v2); + break; + default: + return -EINVAL; + } + + tblcnt = (len - prelen) / sarlen; + if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO) + ret = -EINVAL; + + return ret; +} + +int mt7921_init_acpi_sar(struct mt7921_dev *dev) +{ + struct mt7921_acpi_sar *asar; + int ret; + + asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL); + if (!asar) + return -ENOMEM; + + mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + + /* MTDS is mandatory. Return error if table is invalid */ + ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->dyn); + devm_kfree(dev->mt76.dev, asar->countrylist); + devm_kfree(dev->mt76.dev, asar); + return ret; + } + + /* MTGS is optional */ + ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver); + if (ret) { + devm_kfree(dev->mt76.dev, asar->geo); + asar->geo = NULL; + } + + dev->phy.acpisar = asar; + + return 0; +} + +static s8 +mt7921_asar_get_geo_pwr(struct mt7921_phy *phy, + enum nl80211_band band, s8 dyn_power) +{ + struct mt7921_acpi_sar *asar = phy->acpisar; + struct mt7921_asar_geo_band *band_pwr; + s8 geo_power; + u8 idx, max; + + if (!asar->geo) + return dyn_power; + + switch (phy->mt76->dev->region) { + case NL80211_DFS_FCC: + idx = 0; + break; + case NL80211_DFS_ETSI: + idx = 1; + break; + default: /* WW */ + idx = 2; + break; + } + + if (asar->ver == 1) { + band_pwr = &asar->geo->tbl[idx].band[0]; + max = ARRAY_SIZE(asar->geo->tbl[idx].band); + } else { + band_pwr = &asar->geo_v2->tbl[idx].band[0]; + max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band); + } + + switch (band) { + case NL80211_BAND_2GHZ: + idx = 0; + break; + case NL80211_BAND_5GHZ: + idx = 1; + break; + case NL80211_BAND_6GHZ: + idx = 2; + break; + default: + return dyn_power; + } + + if (idx >= max) + return dyn_power; + + geo_power = (band_pwr + idx)->pwr; + dyn_power += (band_pwr + idx)->offset; + + return min(geo_power, dyn_power); +} + +static s8 +mt7921_asar_range_pwr(struct mt7921_phy *phy, + const struct cfg80211_sar_freq_ranges *range, + u8 idx) +{ + const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; + struct mt7921_acpi_sar *asar = phy->acpisar; + u8 *limit, band, max; + + if (!capa) + return 127; + + if (asar->ver == 1) { + limit = &asar->dyn->tbl[0].frp[0]; + max = ARRAY_SIZE(asar->dyn->tbl[0].frp); + } else { + limit = &asar->dyn_v2->tbl[0].frp[0]; + max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp); + } + + if (idx >= max) + return 127; + + if (range->start_freq >= 5945) + band = NL80211_BAND_6GHZ; + else if (range->start_freq >= 5150) + band = NL80211_BAND_5GHZ; + else + band = NL80211_BAND_2GHZ; + + return mt7921_asar_get_geo_pwr(phy, band, limit[idx]); +} + +int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) +{ + const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; + int i; + + if (!phy->acpisar) + return 0; + + /* When ACPI SAR enabled in HW, we should apply rules for .frp + * 1. w/o .sar_specs : set ACPI SAR power as the defatul value + * 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR) + */ + for (i = 0; i < capa->num_freq_ranges; i++) { + struct mt76_freq_range_power *frp = &phy->mt76->frp[i]; + + frp->range = set_default ? &capa->freq_ranges[i] : frp->range; + if (!frp->range) + continue; + + frp->power = min_t(s8, set_default ? 127 : frp->power, + mt7921_asar_range_pwr(phy, frp->range, i)); + } + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h new file mode 100644 index 000000000000..23f86bfae0c0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2022 MediaTek Inc. */ + +#ifndef __MT7921_ACPI_SAR_H +#define __MT7921_ACPI_SAR_H + +#define MT7921_ASAR_MIN_DYN 1 +#define MT7921_ASAR_MAX_DYN 8 +#define MT7921_ASAR_MIN_GEO 3 +#define MT7921_ASAR_MAX_GEO 8 + +#define MT7921_ACPI_MTCL "MTCL" +#define MT7921_ACPI_MTDS "MTDS" +#define MT7921_ACPI_MTGS "MTGS" + +struct mt7921_asar_dyn_limit { + u8 idx; + u8 frp[5]; +} __packed; + +struct mt7921_asar_dyn { + u8 names[4]; + u8 enable; + u8 nr_tbl; + struct mt7921_asar_dyn_limit tbl[0]; +} __packed; + +struct mt7921_asar_dyn_limit_v2 { + u8 idx; + u8 frp[11]; +} __packed; + +struct mt7921_asar_dyn_v2 { + u8 names[4]; + u8 enable; + u8 rsvd; + u8 nr_tbl; + struct mt7921_asar_dyn_limit_v2 tbl[0]; +} __packed; + +struct mt7921_asar_geo_band { + u8 pwr; + u8 offset; +} __packed; + +struct mt7921_asar_geo_limit { + u8 idx; + /* 0:2G, 1:5G */ + struct mt7921_asar_geo_band band[2]; +} __packed; + +struct mt7921_asar_geo { + u8 names[4]; + u8 version; + u8 nr_tbl; + struct mt7921_asar_geo_limit tbl[0]; +} __packed; + +struct mt7921_asar_geo_limit_v2 { + u8 idx; + /* 0:2G, 1:5G, 2:6G */ + struct mt7921_asar_geo_band band[3]; +} __packed; + +struct mt7921_asar_geo_v2 { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_tbl; + struct mt7921_asar_geo_limit_v2 tbl[0]; +} __packed; + +struct mt7921_asar_cl { + u8 names[4]; + u8 version; + u8 mode_6g; + u8 cl6g[6]; +} __packed; + +struct mt7921_acpi_sar { + u8 ver; + union { + struct mt7921_asar_dyn *dyn; + struct mt7921_asar_dyn_v2 *dyn_v2; + }; + union { + struct mt7921_asar_geo *geo; + struct mt7921_asar_geo_v2 *geo_v2; + }; + struct mt7921_asar_cl *countrylist; +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index 7cdfdf83529f..bce76417f95d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -129,23 +129,22 @@ mt7921_queues_acq(struct seq_file *s, void *data) mt7921_mutex_acquire(dev); - for (i = 0; i < 16; i++) { - int j, acs = i / 4, index = i % 4; + for (i = 0; i < 4; i++) { u32 ctrl, val, qlen = 0; + int j; - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); - ctrl = BIT(31) | BIT(15) | (acs << 8); + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); + ctrl = BIT(31) | BIT(11) | (i << 24); for (j = 0; j < 32; j++) { if (val & BIT(j)) continue; - mt76_wr(dev, MT_PLE_FL_Q0_CTRL, - ctrl | (j + (index << 5))); + mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, GENMASK(11, 0)); } - seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); + seq_printf(s, "AC%d: queued=%d\n", i, qlen); } mt7921_mutex_release(dev); @@ -262,39 +261,35 @@ mt7921_txpwr(struct seq_file *s, void *data) return 0; } -static void -mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct mt7921_dev *dev = priv; - - mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable); -} - static int mt7921_pm_set(void *data, u64 val) { struct mt7921_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; - mt7921_mutex_acquire(dev); + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + + mutex_lock(&dev->mt76.mutex); - if (val == pm->enable) + if (val == pm->enable_user) goto out; - if (!pm->enable) { + if (!pm->enable_user) { pm->stats.last_wake_event = jiffies; pm->stats.last_doze_event = jiffies; } - pm->enable = val; - - ieee80211_iterate_active_interfaces(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7921_pm_interface_iter, dev); - - mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); - + /* make sure the chip is awake here and ps_work is scheduled + * just at end of the this routine. + */ + pm->enable = false; + mt76_connac_pm_wake(&dev->mphy, pm); + + pm->enable_user = val; + mt7921_set_runtime_pm(dev); + mt76_connac_power_save_sched(&dev->mphy, pm); out: - mt7921_mutex_release(dev); + mutex_unlock(&dev->mt76.mutex); return 0; } @@ -304,7 +299,7 @@ mt7921_pm_get(void *data, u64 *val) { struct mt7921_dev *dev = data; - *val = dev->pm.enable; + *val = dev->pm.enable_user; return 0; } @@ -316,13 +311,20 @@ mt7921_deep_sleep_set(void *data, u64 val) { struct mt7921_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); bool enable = !!val; + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + mt7921_mutex_acquire(dev); - if (pm->ds_enable != enable) { - mt76_connac_mcu_set_deep_sleep(&dev->mt76, enable); - pm->ds_enable = enable; - } + if (pm->ds_enable_user == enable) + goto out; + + pm->ds_enable_user = enable; + pm->ds_enable = enable && !monitor; + mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); +out: mt7921_mutex_release(dev); return 0; @@ -333,7 +335,7 @@ mt7921_deep_sleep_get(void *data, u64 *val) { struct mt7921_dev *dev = data; - *val = dev->pm.ds_enable; + *val = dev->pm.ds_enable_user; return 0; } @@ -432,8 +434,13 @@ int mt7921_init_debugfs(struct mt7921_dev *dev) if (!dir) return -ENOMEM; - debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, - mt7921_queues_read); + if (mt76_is_mmio(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt7921_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt76_queues_read); + debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7921_queues_acq); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index cdff1fd52d93..d1f10f6d9adc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -5,20 +5,6 @@ #include "../dma.h" #include "mac.h" -int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc) -{ - int i, err; - - err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE); - if (err < 0) - return err; - - for (i = 0; i <= MT_TXQ_PSD; i++) - phy->mt76->q_tx[i] = phy->mt76->q_tx[0]; - - return 0; -} - static int mt7921_poll_tx(struct napi_struct *napi, int budget) { struct mt7921_dev *dev; @@ -31,7 +17,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) return 0; } - mt7921_mcu_tx_cleanup(dev); + mt76_connac_tx_cleanup(&dev->mt76); if (napi_complete(napi)) mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL); mt76_connac_pm_unref(&dev->mphy, &dev->pm); @@ -78,110 +64,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev) mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); } -static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) -{ - static const struct { - u32 phys; - u32 mapped; - u32 size; - } fixed_map[] = { - { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ - { 0x820ed000, 0x24800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ - { 0x820e4000, 0x21000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ - { 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ - { 0x820eb000, 0x24200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ - { 0x820e2000, 0x20800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ - { 0x820e3000, 0x20c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ - { 0x820e5000, 0x21400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ - { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */ - { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */ - { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */ - { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */ - { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */ - { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ - { 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */ - { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ - { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ - { 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */ - { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ - { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ - { 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */ - { 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */ - { 0x820cc000, 0x0e000, 0x1000 }, /* WF_UMAC_TOP (PP) */ - { 0x820cd000, 0x0f000, 0x1000 }, /* WF_MDP_TOP */ - { 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */ - { 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */ - { 0x820e0000, 0x20000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ - { 0x820e1000, 0x20400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ - { 0x820e9000, 0x23400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ - { 0x820ea000, 0x24000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ - { 0x820ec000, 0x24600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ - { 0x820f0000, 0xa0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ - { 0x820f1000, 0xa0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ - { 0x820f2000, 0xa0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ - { 0x820f3000, 0xa0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ - { 0x820f4000, 0xa1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ - { 0x820f5000, 0xa1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ - { 0x820f7000, 0xa1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ - { 0x820f9000, 0xa3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ - { 0x820fa000, 0xa4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ - { 0x820fb000, 0xa4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ - { 0x820fc000, 0xa4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ - { 0x820fd000, 0xa4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ - }; - int i; - - if (addr < 0x100000) - return addr; - - for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { - u32 ofs; - - if (addr < fixed_map[i].phys) - continue; - - ofs = addr - fixed_map[i].phys; - if (ofs > fixed_map[i].size) - continue; - - return fixed_map[i].mapped + ofs; - } - - if ((addr >= 0x18000000 && addr < 0x18c00000) || - (addr >= 0x70000000 && addr < 0x78000000) || - (addr >= 0x7c000000 && addr < 0x7c400000)) - return mt7921_reg_map_l1(dev, addr); - - dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n", - addr); - - return 0; -} - -static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - u32 addr = __mt7921_reg_addr(dev, offset); - - return dev->bus_ops->rr(mdev, addr); -} - -static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - u32 addr = __mt7921_reg_addr(dev, offset); - - dev->bus_ops->wr(mdev, addr, val); -} - -static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - u32 addr = __mt7921_reg_addr(dev, offset); - - return dev->bus_ops->rmw(mdev, addr, mask, val); -} - static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) { if (force) { @@ -341,23 +223,8 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev) int mt7921_dma_init(struct mt7921_dev *dev) { - struct mt76_bus_ops *bus_ops; int ret; - dev->phy.dev = dev; - dev->phy.mt76 = &dev->mt76.phy; - dev->mt76.phy.priv = &dev->phy; - dev->bus_ops = dev->mt76.bus; - bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), - GFP_KERNEL); - if (!bus_ops) - return -ENOMEM; - - bus_ops->rr = mt7921_rr; - bus_ops->wr = mt7921_wr; - bus_ops->rmw = mt7921_rmw; - dev->mt76.bus = bus_ops; - mt76_dma_attach(&dev->mt76); ret = mt7921_dma_disable(dev, true); @@ -369,8 +236,9 @@ int mt7921_dma_init(struct mt7921_dev *dev) return ret; /* init tx queue */ - ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0, - MT7921_TX_RING_SIZE); + ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, + MT7921_TX_RING_SIZE, + MT_TX_RING_BASE, 0); if (ret) return ret; @@ -415,8 +283,8 @@ int mt7921_dma_init(struct mt7921_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7921_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7921_poll_tx); napi_enable(&dev->mt76.tx_napi); return mt7921_dma_enable(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h index 54f30401343c..4b647278eb30 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h @@ -11,12 +11,15 @@ enum mt7921_eeprom_field { MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, MT_EE_WIFI_CONF = 0x07c, - __MT_EE_MAX = 0x3bf + MT_EE_HW_TYPE = 0x55b, + __MT_EE_MAX = 0x9ff }; #define MT_EE_WIFI_CONF_TX_MASK BIT(0) #define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2) +#define MT_EE_HW_TYPE_ENCAP BIT(0) + enum mt7921_eeprom_band { MT_EE_NA, MT_EE_5GHZ, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 210998f086ab..dcdb3cf04ac1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -11,6 +11,10 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = MT7921_MAX_INTERFACES, .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) } }; @@ -30,14 +34,14 @@ mt7921_regd_notifier(struct wiphy *wiphy, { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; mt7921_mutex_acquire(dev); + mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env); mt76_connac_mcu_set_channel_domain(hw->priv); - mt76_connac_mcu_set_rate_txpower(phy->mt76); + mt7921_set_tx_sar_pwr(hw, NULL); mt7921_mutex_release(dev); } @@ -49,8 +53,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) struct wiphy *wiphy = hw->wiphy; hw->queues = 4; - hw->max_rx_aggregation_subframes = 64; - hw->max_tx_aggregation_subframes = 128; + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; hw->netdev_features = NETIF_F_RXCSUM; hw->radiotap_timestamp.units_pos = @@ -64,7 +68,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->iface_combinations = if_comb; wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | WIPHY_FLAG_4ADDR_STATION); - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_scan_ssids = 4; @@ -76,18 +81,14 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->max_sched_scan_reqs = 1; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->reg_notifier = mt7921_regd_notifier; - wiphy->sar_capa = &mt76_sar_capa; - - phy->mt76->frp = devm_kcalloc(dev->mt76.dev, - wiphy->sar_capa->num_freq_ranges, - sizeof(struct mt76_freq_range_power), - GFP_KERNEL); - if (!phy->mt76->frp) - return -ENOMEM; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, HAS_RATE_CONTROL); @@ -96,6 +97,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, WANT_MONITOR_VIF); ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + ieee80211_hw_set(hw, CONNECTION_MONITOR); if (dev->pm.enable) ieee80211_hw_set(hw, CONNECTION_MONITOR); @@ -173,7 +176,7 @@ out: static int mt7921_init_hardware(struct mt7921_dev *dev) { - int ret, idx, i; + int ret, i; set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); @@ -190,6 +193,13 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return ret; } + return 0; +} + +static int mt7921_init_wcid(struct mt7921_dev *dev) +{ + int idx; + /* Beacon and mgmt frames should occupy wcid 0 */ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); if (idx) @@ -203,6 +213,38 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return 0; } +static void mt7921_init_work(struct work_struct *work) +{ + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + init_work); + int ret; + + ret = mt7921_init_hardware(dev); + if (ret) + return; + + mt76_set_stream_caps(&dev->mphy, true); + mt7921_set_stream_he_caps(&dev->phy); + + ret = mt76_register_device(&dev->mt76, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); + if (ret) { + dev_err(dev->mt76.dev, "register device failed\n"); + return; + } + + ret = mt7921_init_debugfs(dev); + if (ret) { + dev_err(dev->mt76.dev, "register debugfs failed\n"); + return; + } + + /* we support chip reset now */ + dev->hw_init_done = true; + + mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); +} + int mt7921_register_device(struct mt7921_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -224,27 +266,34 @@ int mt7921_register_device(struct mt7921_dev *dev) INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work); INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work); INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work); +#if IS_ENABLED(CONFIG_IPV6) + INIT_WORK(&dev->ipv6_ns_work, mt7921_set_ipv6_ns_work); + skb_queue_head_init(&dev->ipv6_ns_list); +#endif skb_queue_head_init(&dev->phy.scan_event_list); skb_queue_head_init(&dev->coredump.msg_list); INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); + INIT_WORK(&dev->init_work, mt7921_init_work); dev->pm.idle_timeout = MT7921_PM_TIMEOUT; dev->pm.stats.last_wake_event = jiffies; dev->pm.stats.last_doze_event = jiffies; - - /* TODO: mt7921s run sleep mode on default */ - if (mt76_is_mmio(&dev->mt76)) { + if (!mt76_is_usb(&dev->mt76)) { + dev->pm.enable_user = true; dev->pm.enable = true; + dev->pm.ds_enable_user = true; dev->pm.ds_enable = true; } - if (mt76_is_sdio(&dev->mt76)) + if (!mt76_is_mmio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - ret = mt7921_init_hardware(dev); + mt7921_init_acpi_sar(dev); + + ret = mt7921_init_wcid(dev); if (ret) return ret; @@ -259,32 +308,20 @@ int mt7921_register_device(struct mt7921_dev *dev) IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); + if (is_mt7922(&dev->mt76)) + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + IEEE80211_VHT_CAP_SHORT_GI_160; dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; - mt76_set_stream_caps(&dev->mphy, true); - mt7921_set_stream_he_caps(&dev->phy); - - ret = mt76_register_device(&dev->mt76, true, mt76_rates, - ARRAY_SIZE(mt76_rates)); - if (ret) - return ret; - - ret = mt7921_init_debugfs(dev); - if (ret) - return ret; - - ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); - if (ret) - return ret; - - dev->hw_init_done = true; + queue_work(system_wq, &dev->init_work); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index db3302b1576a..650ab97ae052 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -9,10 +9,6 @@ #include "mac.h" #include "mcu.h" -#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) -#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ - IEEE80211_RADIOTAP_HE_##f) - static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, u16 idx, bool unicast) { @@ -116,7 +112,7 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - u8 q = mt7921_lmac_mapping(dev, i); + u8 q = mt76_connac_lmac_mapping(i); u32 tx_cur = tx_time[q]; u32 rx_cur = rx_time[q]; u8 tid = ac_to_tid[i]; @@ -169,179 +165,6 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll); static void -mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, - struct ieee80211_radiotap_he *he, - __le32 *rxv) -{ - u32 ru_h, ru_l; - u8 ru, offs = 0; - - ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0])); - ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1])); - ru = (u8)(ru_l | ru_h << 4); - - status->bw = RATE_INFO_BW_HE_RU; - - switch (ru) { - case 0 ... 36: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; - offs = ru; - break; - case 37 ... 52: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; - offs = ru - 37; - break; - case 53 ... 60: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; - offs = ru - 53; - break; - case 61 ... 64: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; - offs = ru - 61; - break; - case 65 ... 66: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; - offs = ru - 65; - break; - case 67: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; - break; - case 68: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; - break; - } - - he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | - le16_encode_bits(offs, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); -} - -static void -mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, - struct mt76_rx_status *status, - __le32 *rxv) -{ - static const struct ieee80211_radiotap_he_mu mu_known = { - .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | - HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN), - .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) | - HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN), - }; - struct ieee80211_radiotap_he_mu *he_mu; - - he_mu = skb_push(skb, sizeof(mu_known)); - memcpy(he_mu, &mu_known, sizeof(mu_known)); - -#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) - - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); - if (status->he_dcm) - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); - - he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | - MU_PREP(FLAGS2_SIG_B_SYMS_USERS, - le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); - - he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, le32_to_cpu(rxv[3])); - - if (status->bw >= RATE_INFO_BW_40) { - he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); - he_mu->ru_ch2[0] = - FIELD_GET(MT_CRXV_HE_RU1, le32_to_cpu(rxv[3])); - } - - if (status->bw >= RATE_INFO_BW_80) { - he_mu->ru_ch1[1] = - FIELD_GET(MT_CRXV_HE_RU2, le32_to_cpu(rxv[3])); - he_mu->ru_ch2[1] = - FIELD_GET(MT_CRXV_HE_RU3, le32_to_cpu(rxv[3])); - } -} - -static void -mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - struct mt76_rx_status *status, - __le32 *rxv, u32 phy) -{ - static const struct ieee80211_radiotap_he known = { - .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | - HE_BITS(DATA1_DATA_DCM_KNOWN) | - HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN) | - HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN), - .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN) | - HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN), - }; - struct ieee80211_radiotap_he *he = NULL; - u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1; - - he = skb_push(skb, sizeof(known)); - memcpy(he, &known, sizeof(known)); - - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); - he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | - le16_encode_bits(ltf_size, - IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); - if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) - he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); - - switch (phy) { - case MT_PHY_TYPE_HE_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BEAM_CHANGE_KNOWN); - - he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | - HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); - break; - case MT_PHY_TYPE_HE_EXT_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - break; - case MT_PHY_TYPE_HE_MU: - he->data1 |= HE_BITS(DATA1_FORMAT_MU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); - he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); - - mt7921_mac_decode_he_radiotap_ru(status, he, rxv); - break; - case MT_PHY_TYPE_HE_TB: - he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | - HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - - he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]); - - mt7921_mac_decode_he_radiotap_ru(status, he, rxv); - break; - default: - break; - } -} - -static void mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy, struct mt76_rx_status *status, u8 chfreq) { @@ -402,19 +225,21 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; bool hdr_trans, unicast, insert_ccmp_hdr = false; u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info; + u16 hdr_gap; __le32 *rxv = NULL, *rxd = (__le32 *)skb->data; struct mt76_phy *mphy = &dev->mt76.phy; struct mt7921_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; - struct ieee80211_hdr *hdr; + u32 csum_status = *(u32 *)skb->cb; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); + struct mt7921_sta *msta = NULL; u16 seq_ctrl = 0; __le16 fc = 0; - u32 mode = 0; + u8 mode = 0; int i, idx; memset(status, 0, sizeof(*status)); @@ -428,15 +253,20 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) return -EINVAL; + hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; + if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) + return -EINVAL; + + /* ICV error or CCMP/BIP/WPI MIC error */ + if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) + status->flag |= RX_FLAG_ONLY_MONITOR; + chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); - hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - struct mt7921_sta *msta; - msta = container_of(status->wcid, struct mt7921_sta, wcid); spin_lock_bh(&dev->sta_poll_lock); if (list_empty(&msta->poll_list)) @@ -461,7 +291,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) if (!sband->channels) return -EINVAL; - if ((rxd0 & csum_mask) == csum_mask) + if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) @@ -551,9 +382,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) /* RXD Group 3 - P-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { - u8 stbc, gi; u32 v0, v1; - bool cck; + int ret; rxv = rxd; rxd += 2; @@ -581,85 +411,10 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->chain_signal[i]); } - if (status->signal == -128) - status->flag |= RX_FLAG_NO_SIGNAL_VAL; - - stbc = FIELD_GET(MT_PRXV_STBC, v0); - gi = FIELD_GET(MT_PRXV_SGI, v0); - cck = false; - - idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); - mode = FIELD_GET(MT_PRXV_TX_MODE, v0); - - switch (mode) { - case MT_PHY_TYPE_CCK: - cck = true; - fallthrough; - case MT_PHY_TYPE_OFDM: - i = mt76_get_rate(&dev->mt76, sband, i, cck); - break; - case MT_PHY_TYPE_HT_GF: - case MT_PHY_TYPE_HT: - status->encoding = RX_ENC_HT; - if (i > 31) - return -EINVAL; - break; - case MT_PHY_TYPE_VHT: - status->nss = - FIELD_GET(MT_PRXV_NSTS, v0) + 1; - status->encoding = RX_ENC_VHT; - if (i > 9) - return -EINVAL; - break; - case MT_PHY_TYPE_HE_MU: - status->flag |= RX_FLAG_RADIOTAP_HE_MU; - fallthrough; - case MT_PHY_TYPE_HE_SU: - case MT_PHY_TYPE_HE_EXT_SU: - case MT_PHY_TYPE_HE_TB: - status->nss = - FIELD_GET(MT_PRXV_NSTS, v0) + 1; - status->encoding = RX_ENC_HE; - status->flag |= RX_FLAG_RADIOTAP_HE; - i &= GENMASK(3, 0); - - if (gi <= NL80211_RATE_INFO_HE_GI_3_2) - status->he_gi = gi; - - status->he_dcm = !!(idx & MT_PRXV_TX_DCM); - break; - default: - return -EINVAL; - } - - status->rate_idx = i; - - switch (FIELD_GET(MT_PRXV_FRAME_MODE, v0)) { - case IEEE80211_STA_RX_BW_20: - break; - case IEEE80211_STA_RX_BW_40: - if (mode & MT_PHY_TYPE_HE_EXT_SU && - (idx & MT_PRXV_TX_ER_SU_106T)) { - status->bw = RATE_INFO_BW_HE_RU; - status->he_ru = - NL80211_RATE_INFO_HE_RU_ALLOC_106; - } else { - status->bw = RATE_INFO_BW_40; - } - break; - case IEEE80211_STA_RX_BW_80: - status->bw = RATE_INFO_BW_80; - break; - case IEEE80211_STA_RX_BW_160: - status->bw = RATE_INFO_BW_160; - break; - default: - return -EINVAL; - } - - status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - if (mode < MT_PHY_TYPE_HE_SU && gi) - status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband, + rxv, &mode); + if (ret < 0) + return ret; if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { rxd += 18; @@ -668,14 +423,31 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) } } - skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); - amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); status->amsdu = !!amsdu_info; if (status->amsdu) { status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; - if (!hdr_trans) { + } + + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; + if (hdr_trans && ieee80211_has_morefrags(fc)) { + struct ieee80211_vif *vif; + int err; + + if (!msta || !msta->vif) + return -EINVAL; + + vif = container_of((void *)msta->vif, struct ieee80211_vif, + drv_priv); + err = mt76_connac2_reverse_frag0_hdr_trans(vif, skb, hdr_gap); + if (err) + return err; + + hdr_trans = false; + } else { + skb_pull(skb, hdr_gap); + if (!hdr_trans && status->amsdu) { memmove(skb->data + 2, skb->data, ieee80211_get_hdrlen_from_skb(skb)); skb_pull(skb, 2); @@ -683,6 +455,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) } if (!hdr_trans) { + struct ieee80211_hdr *hdr; + if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); @@ -696,19 +470,13 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) qos_ctl = *ieee80211_get_qos_ctl(hdr); } } else { - status->flag &= ~(RX_FLAG_RADIOTAP_HE | - RX_FLAG_RADIOTAP_HE_MU); status->flag |= RX_FLAG_8023; } mt7921_mac_assoc_rssi(dev, skb); - if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) { - mt7921_mac_decode_he_radiotap(skb, status, rxv, mode); - - if (status->flag & RX_FLAG_RADIOTAP_HE_MU) - mt7921_mac_decode_he_mu_radiotap(skb, status, rxv); - } + if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) + mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode); if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; @@ -720,218 +488,16 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) return 0; } -static void -mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid) -{ - u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - u8 fc_type, fc_stype; - bool wmm = false; - u32 val; - - if (wcid->sta) { - struct ieee80211_sta *sta; - - sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); - wmm = sta->wme; - } - - val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | - FIELD_PREP(MT_TXD1_TID, tid); - - if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) - val |= MT_TXD1_ETH_802_3; - - txwi[1] |= cpu_to_le32(val); - - fc_type = IEEE80211_FTYPE_DATA >> 2; - fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; - - val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | - FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); - - txwi[2] |= cpu_to_le32(val); - - val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | - FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); - txwi[7] |= cpu_to_le32(val); -} - -static void -mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct ieee80211_key_conf *key) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - bool multicast = is_multicast_ether_addr(hdr->addr1); - u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - __le16 fc = hdr->frame_control; - u8 fc_type, fc_stype; - u32 val; - - if (ieee80211_is_action(fc) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { - u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - - txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); - tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; - } else if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; - u16 control = le16_to_cpu(bar->control); - - tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); - } - - val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | - FIELD_PREP(MT_TXD1_HDR_INFO, - ieee80211_get_hdrlen_from_skb(skb) / 2) | - FIELD_PREP(MT_TXD1_TID, tid); - txwi[1] |= cpu_to_le32(val); - - fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; - fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; - - val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | - FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | - FIELD_PREP(MT_TXD2_MULTICAST, multicast); - - if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && - key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { - val |= MT_TXD2_BIP; - txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); - } - - if (!ieee80211_is_data(fc) || multicast || - info->flags & IEEE80211_TX_CTL_USE_MINRATE) - val |= MT_TXD2_FIX_RATE; - - txwi[2] |= cpu_to_le32(val); - - if (ieee80211_is_beacon(fc)) { - txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); - txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); - } - - if (info->flags & IEEE80211_TX_CTL_INJECTED) { - u16 seqno = le16_to_cpu(hdr->seq_ctrl); - - if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar; - - bar = (struct ieee80211_bar *)skb->data; - seqno = le16_to_cpu(bar->start_seq_num); - } - - val = MT_TXD3_SN_VALID | - FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); - txwi[3] |= cpu_to_le32(val); - } - - val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | - FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); - txwi[7] |= cpu_to_le32(val); -} - -void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_key_conf *key, int pid, - bool beacon) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; - struct mt76_phy *mphy = &dev->mphy; - u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; - bool is_mmio = mt76_is_mmio(&dev->mt76); - u32 sz_txd = is_mmio ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE; - bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - u16 tx_count = 15; - u32 val; - - if (vif) { - struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; - - omac_idx = mvif->omac_idx; - wmm_idx = mvif->wmm_idx; - } - - if (beacon) { - p_fmt = MT_TX_TYPE_FW; - q_idx = MT_LMAC_BCN0; - } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { - p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; - q_idx = MT_LMAC_ALTX0; - } else { - p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; - q_idx = wmm_idx * MT7921_MAX_WMM_SETS + - mt7921_lmac_mapping(dev, skb_get_queue_mapping(skb)); - } - - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | - FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | - FIELD_PREP(MT_TXD0_Q_IDX, q_idx); - txwi[0] = cpu_to_le32(val); - - val = MT_TXD1_LONG_FORMAT | - FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | - FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); - - txwi[1] = cpu_to_le32(val); - txwi[2] = 0; - - val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); - if (key) - val |= MT_TXD3_PROTECT_FRAME; - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - val |= MT_TXD3_NO_ACK; - - txwi[3] = cpu_to_le32(val); - txwi[4] = 0; - - val = FIELD_PREP(MT_TXD5_PID, pid); - if (pid >= MT_PACKET_ID_FIRST) - val |= MT_TXD5_TX_STATUS_HOST; - txwi[5] = cpu_to_le32(val); - - txwi[6] = 0; - txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; - - if (is_8023) - mt7921_mac_write_txwi_8023(dev, txwi, skb, wcid); - else - mt7921_mac_write_txwi_80211(dev, txwi, skb, key); - - if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { - int rateidx = ffs(vif->bss_conf.basic_rates) - 1; - u16 rate, mode; - - /* hardware won't add HTC for mgmt/ctrl frame */ - txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); - - rate = mt76_calculate_default_rate(mphy, rateidx); - mode = rate >> 8; - rate &= GENMASK(7, 0); - rate |= FIELD_PREP(MT_TX_RATE_MODE, mode); - - val = MT_TXD6_FIXED_BW | - FIELD_PREP(MT_TXD6_TX_RATE, rate); - txwi[6] |= cpu_to_le32(val); - txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); - } -} -EXPORT_SYMBOL_GPL(mt7921_mac_write_txwi); - -void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) { struct mt7921_sta *msta; u16 fc, tid; u32 val; - if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he)) + if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) return; - tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1])); + tid = le32_get_bits(txwi[1], MT_TXD1_TID); if (tid >= 6) /* skip VO queue */ return; @@ -945,144 +511,20 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) if (!test_and_set_bit(tid, &msta->ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } -EXPORT_SYMBOL_GPL(mt7921_tx_check_aggr); -static bool -mt7921_mac_add_txs_skb(struct mt7921_dev *dev, struct mt76_wcid *wcid, int pid, - __le32 *txs_data) -{ - struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid); - struct mt76_sta_stats *stats = &msta->stats; - struct ieee80211_supported_band *sband; - struct mt76_dev *mdev = &dev->mt76; - struct ieee80211_tx_info *info; - struct rate_info rate = {}; - struct sk_buff_head list; - u32 txrate, txs, mode; - struct sk_buff *skb; - bool cck = false; - - mt76_tx_status_lock(mdev, &list); - skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); - if (!skb) - goto out; - - info = IEEE80211_SKB_CB(skb); - txs = le32_to_cpu(txs_data[0]); - if (!(txs & MT_TXS0_ACK_ERROR_MASK)) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.ampdu_len = 1; - info->status.ampdu_ack_len = !!(info->flags & - IEEE80211_TX_STAT_ACK); - - info->status.rates[0].idx = -1; - - if (!wcid->sta) - goto out; - - txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); - - rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); - rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; - - if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) - stats->tx_nss[rate.nss - 1]++; - if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) - stats->tx_mcs[rate.mcs]++; - - mode = FIELD_GET(MT_TX_RATE_MODE, txrate); - switch (mode) { - case MT_PHY_TYPE_CCK: - cck = true; - fallthrough; - case MT_PHY_TYPE_OFDM: - if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mphy.sband_5g.sband; - else - sband = &dev->mphy.sband_2g.sband; - - rate.mcs = mt76_get_rate(dev->mphy.dev, sband, rate.mcs, cck); - rate.legacy = sband->bitrates[rate.mcs].bitrate; - break; - case MT_PHY_TYPE_HT: - case MT_PHY_TYPE_HT_GF: - rate.mcs += (rate.nss - 1) * 8; - if (rate.mcs > 31) - goto out; - - rate.flags = RATE_INFO_FLAGS_MCS; - if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) - rate.flags |= RATE_INFO_FLAGS_SHORT_GI; - break; - case MT_PHY_TYPE_VHT: - if (rate.mcs > 9) - goto out; - - rate.flags = RATE_INFO_FLAGS_VHT_MCS; - break; - case MT_PHY_TYPE_HE_SU: - case MT_PHY_TYPE_HE_EXT_SU: - case MT_PHY_TYPE_HE_TB: - case MT_PHY_TYPE_HE_MU: - if (rate.mcs > 11) - goto out; - - rate.he_gi = wcid->rate.he_gi; - rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); - rate.flags = RATE_INFO_FLAGS_HE_MCS; - break; - default: - goto out; - } - stats->tx_mode[mode]++; - - switch (FIELD_GET(MT_TXS0_BW, txs)) { - case IEEE80211_STA_RX_BW_160: - rate.bw = RATE_INFO_BW_160; - stats->tx_bw[3]++; - break; - case IEEE80211_STA_RX_BW_80: - rate.bw = RATE_INFO_BW_80; - stats->tx_bw[2]++; - break; - case IEEE80211_STA_RX_BW_40: - rate.bw = RATE_INFO_BW_40; - stats->tx_bw[1]++; - break; - default: - rate.bw = RATE_INFO_BW_20; - stats->tx_bw[0]++; - break; - } - wcid->rate = rate; - -out: - if (skb) - mt76_tx_status_skb_done(mdev, skb, &list); - mt76_tx_status_unlock(mdev, &list); - - return !!skb; -} - -static void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) +void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) { struct mt7921_sta *msta = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; - u32 txs; u8 pid; - txs = le32_to_cpu(txs_data[0]); - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) return; - txs = le32_to_cpu(txs_data[2]); - wcidx = FIELD_GET(MT_TXS2_WCID, txs); - - txs = le32_to_cpu(txs_data[3]); - pid = FIELD_GET(MT_TXS3_PID, txs); + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); + pid = le32_get_bits(txs_data[3], MT_TXS3_PID); if (pid < MT_PACKET_ID_FIRST) return; @@ -1096,12 +538,12 @@ static void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) if (!wcid) goto out; - mt7921_mac_add_txs_skb(dev, wcid, pid, txs_data); + msta = container_of(wcid, struct mt7921_sta, wcid); + mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); if (!wcid->sta) goto out; - msta = container_of(wcid, struct mt7921_sta, wcid); spin_lock_bh(&dev->sta_poll_lock); if (list_empty(&msta->poll_list)) list_add_tail(&msta->poll_list, &dev->sta_poll_list); @@ -1111,6 +553,134 @@ out: rcu_read_unlock(); } +void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, bool clear_status, + struct list_head *free_list) +{ + struct mt76_dev *mdev = &dev->mt76; + __le32 *txwi; + u16 wcid_idx; + + mt76_connac_txp_skb_unmap(mdev, t); + if (!t->skb) + goto out; + + txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); + if (sta) { + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7921_tx_check_aggr(sta, txwi); + + wcid_idx = wcid->idx; + } else { + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + } + + __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); +out: + t->skb = NULL; + mt76_put_txwi(mdev, t); +} +EXPORT_SYMBOL_GPL(mt7921_txwi_free); + +static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) +{ + struct mt76_connac_tx_free *free = data; + __le32 *tx_info = (__le32 *)(data + sizeof(*free)); + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + struct ieee80211_sta *sta = NULL; + struct sk_buff *skb, *tmp; + void *end = data + len; + LIST_HEAD(free_list); + bool wake = false; + u8 i, count; + + /* clean DMA queues and unmap buffers first */ + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); + + count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); + if (WARN_ON_ONCE((void *)&tx_info[count] > end)) + return; + + for (i = 0; i < count; i++) { + u32 msdu, info = le32_to_cpu(tx_info[i]); + u8 stat; + + /* 1'b1: new wcid pair. + * 1'b0: msdu_id with the same 'wcid pair' as above. + */ + if (info & MT_TX_FREE_PAIR) { + struct mt7921_sta *msta; + struct mt76_wcid *wcid; + u16 idx; + + count++; + idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); + wcid = rcu_dereference(dev->mt76.wcid[idx]); + sta = wcid_to_sta(wcid); + if (!sta) + continue; + + msta = container_of(wcid, struct mt7921_sta, wcid); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->poll_list)) + list_add_tail(&msta->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + continue; + } + + msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); + stat = FIELD_GET(MT_TX_FREE_STATUS, info); + + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; + + mt7921_txwi_free(dev, txwi, sta, stat, &free_list); + } + + if (wake) + mt76_set_tx_blocked(&dev->mt76, false); + + list_for_each_entry_safe(skb, tmp, &free_list, list) { + skb_list_del_init(skb); + napi_consume_skb(skb, 1); + } + + rcu_read_lock(); + mt7921_mac_sta_poll(dev); + rcu_read_unlock(); + + mt76_worker_schedule(&dev->mt76.tx_worker); +} + +bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + __le32 *rxd = (__le32 *)data; + __le32 *end = (__le32 *)&rxd[len / 4]; + enum rx_pkt_type type; + + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */ + mt7921_mac_tx_free(dev, data, len); /* mmio */ + return false; + case PKT_TYPE_TXS: + for (rxd += 2; rxd + 8 <= end; rxd += 8) + mt7921_mac_add_txs(dev, rxd); + return false; + default: + return true; + } +} +EXPORT_SYMBOL_GPL(mt7921_rx_check); + void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb) { @@ -1120,13 +690,18 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, enum rx_pkt_type type; u16 flag; - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); - flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0])); + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG); if (type == PKT_TYPE_RX_EVENT && flag == 0x1) type = PKT_TYPE_NORMAL_MCU; switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */ + mt7921_mac_tx_free(dev, skb->data, skb->len); + napi_consume_skb(skb, 1); + break; case PKT_TYPE_RX_EVENT: mt7921_mcu_rx_event(dev, skb); break; @@ -1271,12 +846,21 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct mt7921_dev *dev = mvif->phy->dev; + struct ieee80211_hw *hw = mt76_hw(dev); if (vif->type == NL80211_IFTYPE_STATION) ieee80211_disconnect(vif, true); mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); mt7921_mcu_set_tx(dev, vif); + + if (vif->type == NL80211_IFTYPE_AP) { + mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid, + true); + mt7921_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); + mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); + } } /* system error recovery */ @@ -1286,9 +870,9 @@ void mt7921_mac_reset_work(struct work_struct *work) reset_work); struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; - int i; + int i, ret; - dev_err(dev->mt76.dev, "chip reset\n"); + dev_dbg(dev->mt76.dev, "chip reset\n"); dev->hw_full_reset = true; ieee80211_stop_queues(hw); @@ -1296,11 +880,14 @@ void mt7921_mac_reset_work(struct work_struct *work) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - mutex_lock(&dev->mt76.mutex); - for (i = 0; i < 10; i++) - if (!mt7921_dev_reset(dev)) + for (i = 0; i < 10; i++) { + mutex_lock(&dev->mt76.mutex); + ret = mt7921_dev_reset(dev); + mutex_unlock(&dev->mt76.mutex); + + if (!ret) break; - mutex_unlock(&dev->mt76.mutex); + } if (i == 10) dev_err(dev->mt76.dev, "chip reset failed\n"); @@ -1314,6 +901,7 @@ void mt7921_mac_reset_work(struct work_struct *work) } dev->hw_full_reset = false; + pm->suspended = false; ieee80211_wake_queues(hw); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, @@ -1324,6 +912,7 @@ void mt7921_mac_reset_work(struct work_struct *work) void mt7921_reset(struct mt76_dev *mdev) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt76_connac_pm *pm = &dev->pm; if (!dev->hw_init_done) return; @@ -1331,8 +920,12 @@ void mt7921_reset(struct mt76_dev *mdev) if (dev->hw_full_reset) return; + if (pm->suspended) + return; + queue_work(dev->mt76.wq, &dev->reset_work); } +EXPORT_SYMBOL_GPL(mt7921_reset); void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) { @@ -1436,10 +1029,12 @@ void mt7921_pm_wake_work(struct work_struct *work) mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); mt76_worker_schedule(&mdev->sdio.txrx_worker); } else { + local_bh_disable(); mt76_for_each_q_rx(mdev, i) napi_schedule(&mdev->napi[i]); + local_bh_enable(); mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - mt7921_mcu_tx_cleanup(dev); + mt76_connac_tx_cleanup(mdev); } if (test_bit(MT76_STATE_RUNNING, &mphy->state)) ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, @@ -1462,7 +1057,16 @@ void mt7921_pm_power_save_work(struct work_struct *work) delta = dev->pm.idle_timeout; if (test_bit(MT76_HW_SCANNING, &mphy->state) || - test_bit(MT76_HW_SCHED_SCANNING, &mphy->state)) + test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) || + dev->fw_assert) + goto out; + + if (mutex_is_locked(&dev->mt76.mutex)) + /* if mt76 mutex is held we should not put the device + * to sleep since we are currently accessing device + * register map. We need to wait for the next power_save + * trigger. + */ goto out; if (time_is_after_jiffies(dev->pm.last_activity + delta)) { @@ -1506,7 +1110,7 @@ void mt7921_coredump_work(struct work_struct *work) if (!skb) break; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { dev_kfree_skb(skb); continue; @@ -1524,3 +1128,120 @@ void mt7921_coredump_work(struct work_struct *work) mt7921_reset(&dev->mt76); } + +/* usb_sdio */ +static void +mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, + enum mt76_txq_id qid, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, int pid, + struct sk_buff *skb) +{ + __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); + + memset(txwi, 0, MT_SDIO_TXD_SIZE); + mt76_connac2_mac_write_txwi(&dev->mt76, txwi, skb, wcid, key, pid, qid, 0); + skb_push(skb, MT_SDIO_TXD_SIZE); +} + +int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct sk_buff *skb = tx_info->skb; + int err, pad, pktid, type; + + if (unlikely(tx_info->skb->len <= ETH_HLEN)) + return -EINVAL; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + if (sta) { + struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + + if (time_after(jiffies, msta->last_txs + HZ / 4)) { + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + msta->last_txs = jiffies; + } + } + + pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); + mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb); + + type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0; + mt7921_skb_add_usb_sdio_hdr(dev, skb, type); + pad = round_up(skb->len, 4) - skb->len; + if (mt76_is_usb(mdev)) + pad += 4; + + err = mt76_skb_adjust_pad(skb, pad); + if (err) + /* Release pktid in case of error. */ + idr_remove(&wcid->pktid, pktid); + + return err; +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_prepare_skb); + +void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e) +{ + __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); + unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; + struct ieee80211_sta *sta; + struct mt76_wcid *wcid; + u16 idx; + + idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(mdev->wcid[idx]); + sta = wcid_to_sta(wcid); + + if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7921_tx_check_aggr(sta, txwi); + + skb_pull(e->skb, headroom); + mt76_tx_complete_skb(mdev, e->wcid, e->skb); +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb); + +bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + + mt7921_mutex_acquire(dev); + mt7921_mac_sta_poll(dev); + mt7921_mutex_release(dev); + + return false; +} +EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data); + +#if IS_ENABLED(CONFIG_IPV6) +void mt7921_set_ipv6_ns_work(struct work_struct *work) +{ + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + ipv6_ns_work); + struct sk_buff *skb; + int ret = 0; + + do { + skb = skb_dequeue(&dev->ipv6_ns_list); + + if (!skb) + break; + + mt7921_mutex_acquire(dev); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(OFFLOAD), true); + mt7921_mutex_release(dev); + + } while (!ret); + + if (ret) + skb_queue_purge(&dev->ipv6_ns_list); +} +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h index 544a1c33126a..8afec600364f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h @@ -4,6 +4,8 @@ #ifndef __MT7921_MAC_H #define __MT7921_MAC_H +#include "../mt76_connac2_mac.h" + #define MT_CT_PARSE_LEN 72 #define MT_CT_DMA_BUF_NUM 2 @@ -27,290 +29,6 @@ enum rx_pkt_type { PKT_TYPE_NORMAL_MCU, }; -/* RXD DW1 */ -#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0) -#define MT_RXD1_NORMAL_GROUP_1 BIT(11) -#define MT_RXD1_NORMAL_GROUP_2 BIT(12) -#define MT_RXD1_NORMAL_GROUP_3 BIT(13) -#define MT_RXD1_NORMAL_GROUP_4 BIT(14) -#define MT_RXD1_NORMAL_GROUP_5 BIT(15) -#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16) -#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) -#define MT_RXD1_NORMAL_CM BIT(23) -#define MT_RXD1_NORMAL_CLM BIT(24) -#define MT_RXD1_NORMAL_ICV_ERR BIT(25) -#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) -#define MT_RXD1_NORMAL_FCS_ERR BIT(27) -#define MT_RXD1_NORMAL_BAND_IDX BIT(28) -#define MT_RXD1_NORMAL_SPP_EN BIT(29) -#define MT_RXD1_NORMAL_ADD_OM BIT(30) -#define MT_RXD1_NORMAL_SEC_DONE BIT(31) - -/* RXD DW2 */ -#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) -#define MT_RXD2_NORMAL_CO_ANT BIT(6) -#define MT_RXD2_NORMAL_BF_CQI BIT(7) -#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) -#define MT_RXD2_NORMAL_HDR_TRANS BIT(13) -#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14) -#define MT_RXD2_NORMAL_TID GENMASK(19, 16) -#define MT_RXD2_NORMAL_MU_BAR BIT(21) -#define MT_RXD2_NORMAL_SW_BIT BIT(22) -#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) -#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) -#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) -#define MT_RXD2_NORMAL_INT_FRAME BIT(26) -#define MT_RXD2_NORMAL_FRAG BIT(27) -#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) -#define MT_RXD2_NORMAL_NDATA BIT(29) -#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) -#define MT_RXD2_NORMAL_BF_REPORT BIT(31) - -/* RXD DW3 */ -#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) -#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) -#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) -#define MT_RXD3_NORMAL_U2M BIT(0) -#define MT_RXD3_NORMAL_HTC_VLD BIT(0) -#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19) -#define MT_RXD3_NORMAL_BEACON_MC BIT(20) -#define MT_RXD3_NORMAL_BEACON_UC BIT(21) -#define MT_RXD3_NORMAL_AMSDU BIT(22) -#define MT_RXD3_NORMAL_MESH BIT(23) -#define MT_RXD3_NORMAL_MHCP BIT(24) -#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25) -#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26) -#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27) -#define MT_RXD3_NORMAL_MORE BIT(28) -#define MT_RXD3_NORMAL_UNWANT BIT(29) -#define MT_RXD3_NORMAL_RX_DROP BIT(30) -#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) - -/* RXD DW4 */ -#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) -#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) -#define MT_RXD4_MID_AMSDU_FRAME BIT(1) -#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) -#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9) -#define MT_RXD4_NORMAL_CLS BIT(10) -#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11) -#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13) -#define MT_RXD4_NORMAL_WOL GENMASK(18, 14) -#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19) -#define MT_RXD3_NORMAL_PF_MODE BIT(29) -#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) - -/* RXD GROUP4 */ -#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0) -#define MT_RXD6_TA_LO GENMASK(31, 16) - -#define MT_RXD7_TA_HI GENMASK(31, 0) - -#define MT_RXD8_SEQ_CTRL GENMASK(15, 0) -#define MT_RXD8_QOS_CTL GENMASK(31, 16) - -#define MT_RXD9_HT_CONTROL GENMASK(31, 0) - -/* P-RXV DW0 */ -#define MT_PRXV_TX_RATE GENMASK(6, 0) -#define MT_PRXV_TX_DCM BIT(4) -#define MT_PRXV_TX_ER_SU_106T BIT(5) -#define MT_PRXV_NSTS GENMASK(9, 7) -#define MT_PRXV_TXBF BIT(10) -#define MT_PRXV_HT_AD_CODE BIT(11) -#define MT_PRXV_FRAME_MODE GENMASK(14, 12) -#define MT_PRXV_SGI GENMASK(16, 15) -#define MT_PRXV_STBC GENMASK(23, 22) -#define MT_PRXV_TX_MODE GENMASK(27, 24) -#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28) - -/* P-RXV DW1 */ -#define MT_PRXV_RCPI3 GENMASK(31, 24) -#define MT_PRXV_RCPI2 GENMASK(23, 16) -#define MT_PRXV_RCPI1 GENMASK(15, 8) -#define MT_PRXV_RCPI0 GENMASK(7, 0) -#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0) - -/* C-RXV */ -#define MT_CRXV_HT_STBC GENMASK(1, 0) -#define MT_CRXV_TX_MODE GENMASK(7, 4) -#define MT_CRXV_FRAME_MODE GENMASK(10, 8) -#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) -#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) -#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) -#define MT_CRXV_HE_PE_DISAMBIG BIT(23) -#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) -#define MT_CRXV_HE_UPLINK BIT(31) - -#define MT_CRXV_HE_RU0 GENMASK(7, 0) -#define MT_CRXV_HE_RU1 GENMASK(15, 8) -#define MT_CRXV_HE_RU2 GENMASK(23, 16) -#define MT_CRXV_HE_RU3 GENMASK(31, 24) -#define MT_CRXV_HE_MU_AID GENMASK(30, 20) - -#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) -#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) -#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) -#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) - -#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0) -#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6) -#define MT_CRXV_HE_BEAM_CHNG BIT(13) -#define MT_CRXV_HE_DOPPLER BIT(16) - -#define MT_CRXV_SNR GENMASK(18, 13) -#define MT_CRXV_FOE_LO GENMASK(31, 19) -#define MT_CRXV_FOE_HI GENMASK(6, 0) -#define MT_CRXV_FOE_SHIFT 13 - -enum tx_header_format { - MT_HDR_FORMAT_802_3, - MT_HDR_FORMAT_CMD, - MT_HDR_FORMAT_802_11, - MT_HDR_FORMAT_802_11_EXT, -}; - -enum tx_pkt_type { - MT_TX_TYPE_CT, - MT_TX_TYPE_SF, - MT_TX_TYPE_CMD, - MT_TX_TYPE_FW, -}; - -enum tx_port_idx { - MT_TX_PORT_IDX_LMAC, - MT_TX_PORT_IDX_MCU -}; - -enum tx_mcu_port_q_idx { - MT_TX_MCU_PORT_RX_Q0 = 0x20, - MT_TX_MCU_PORT_RX_Q1, - MT_TX_MCU_PORT_RX_Q2, - MT_TX_MCU_PORT_RX_Q3, - MT_TX_MCU_PORT_RX_FWDL = 0x3e -}; - -#define MT_CT_INFO_APPLY_TXD BIT(0) -#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) -#define MT_CT_INFO_MGMT_FRAME BIT(2) -#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) -#define MT_CT_INFO_HSR2_TX BIT(4) -#define MT_CT_INFO_FROM_HOST BIT(7) - -#define MT_TXD_SIZE (8 * 4) - -#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4) -#define MT_SDIO_TAIL_SIZE 8 -#define MT_SDIO_HDR_SIZE 4 - -#define MT_TXD0_Q_IDX GENMASK(31, 25) -#define MT_TXD0_PKT_FMT GENMASK(24, 23) -#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) -#define MT_TXD0_TX_BYTES GENMASK(15, 0) - -#define MT_TXD1_LONG_FORMAT BIT(31) -#define MT_TXD1_TGID BIT(30) -#define MT_TXD1_OWN_MAC GENMASK(29, 24) -#define MT_TXD1_AMSDU BIT(23) -#define MT_TXD1_TID GENMASK(22, 20) -#define MT_TXD1_HDR_PAD GENMASK(19, 18) -#define MT_TXD1_HDR_FORMAT GENMASK(17, 16) -#define MT_TXD1_HDR_INFO GENMASK(15, 11) -#define MT_TXD1_ETH_802_3 BIT(15) -#define MT_TXD1_VTA BIT(10) -#define MT_TXD1_WLAN_IDX GENMASK(9, 0) - -#define MT_TXD2_FIX_RATE BIT(31) -#define MT_TXD2_FIXED_RATE BIT(30) -#define MT_TXD2_POWER_OFFSET GENMASK(29, 24) -#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) -#define MT_TXD2_FRAG GENMASK(15, 14) -#define MT_TXD2_HTC_VLD BIT(13) -#define MT_TXD2_DURATION BIT(12) -#define MT_TXD2_BIP BIT(11) -#define MT_TXD2_MULTICAST BIT(10) -#define MT_TXD2_RTS BIT(9) -#define MT_TXD2_SOUNDING BIT(8) -#define MT_TXD2_NDPA BIT(7) -#define MT_TXD2_NDP BIT(6) -#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) -#define MT_TXD2_SUB_TYPE GENMASK(3, 0) - -#define MT_TXD3_SN_VALID BIT(31) -#define MT_TXD3_PN_VALID BIT(30) -#define MT_TXD3_SW_POWER_MGMT BIT(29) -#define MT_TXD3_BA_DISABLE BIT(28) -#define MT_TXD3_SEQ GENMASK(27, 16) -#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) -#define MT_TXD3_TX_COUNT GENMASK(10, 6) -#define MT_TXD3_TIMING_MEASURE BIT(5) -#define MT_TXD3_DAS BIT(4) -#define MT_TXD3_EEOSP BIT(3) -#define MT_TXD3_EMRD BIT(2) -#define MT_TXD3_PROTECT_FRAME BIT(1) -#define MT_TXD3_NO_ACK BIT(0) - -#define MT_TXD4_PN_LOW GENMASK(31, 0) - -#define MT_TXD5_PN_HIGH GENMASK(31, 16) -#define MT_TXD5_MD BIT(15) -#define MT_TXD5_ADD_BA BIT(14) -#define MT_TXD5_TX_STATUS_HOST BIT(10) -#define MT_TXD5_TX_STATUS_MCU BIT(9) -#define MT_TXD5_TX_STATUS_FMT BIT(8) -#define MT_TXD5_PID GENMASK(7, 0) - -#define MT_TXD6_TX_IBF BIT(31) -#define MT_TXD6_TX_EBF BIT(30) -#define MT_TXD6_TX_RATE GENMASK(29, 16) -#define MT_TXD6_SGI GENMASK(15, 14) -#define MT_TXD6_HELTF GENMASK(13, 12) -#define MT_TXD6_LDPC BIT(11) -#define MT_TXD6_SPE_ID_IDX BIT(10) -#define MT_TXD6_ANT_ID GENMASK(7, 4) -#define MT_TXD6_DYN_BW BIT(3) -#define MT_TXD6_FIXED_BW BIT(2) -#define MT_TXD6_BW GENMASK(1, 0) - -#define MT_TXD7_TXD_LEN GENMASK(31, 30) -#define MT_TXD7_UDP_TCP_SUM BIT(29) -#define MT_TXD7_IP_SUM BIT(28) - -#define MT_TXD7_TYPE GENMASK(21, 20) -#define MT_TXD7_SUB_TYPE GENMASK(19, 16) - -#define MT_TXD7_PSE_FID GENMASK(27, 16) -#define MT_TXD7_SPE_IDX GENMASK(15, 11) -#define MT_TXD7_HW_AMSDU BIT(10) -#define MT_TXD7_TX_TIME GENMASK(9, 0) - -#define MT_TX_RATE_STBC BIT(13) -#define MT_TX_RATE_NSS GENMASK(12, 10) -#define MT_TX_RATE_MODE GENMASK(9, 6) -#define MT_TX_RATE_SU_EXT_TONE BIT(5) -#define MT_TX_RATE_DCM BIT(4) -#define MT_TX_RATE_IDX GENMASK(3, 0) - -#define MT_TXP_MAX_BUF_NUM 6 - -struct mt7921_txp { - __le16 flags; - __le16 token; - u8 bss_idx; - __le16 rept_wds_wcid; - u8 nbuf; - __le32 buf[MT_TXP_MAX_BUF_NUM]; - __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed __aligned(4); - -struct mt7921_tx_free { - __le16 rx_byte_cnt; - __le16 ctrl; - u8 txd_cnt; - u8 rsv[3]; - __le32 info[]; -} __packed __aligned(4); - #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) #define MT_TX_FREE_LATENCY GENMASK(12, 0) @@ -321,56 +39,6 @@ struct mt7921_tx_free { /* will support this field in further revision */ #define MT_TX_FREE_RATE GENMASK(13, 0) -#define MT_TXS0_BW GENMASK(30, 29) -#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) -#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) -#define MT_TXS0_TX_RATE GENMASK(13, 0) - -#define MT_TXS2_WCID GENMASK(25, 16) - -#define MT_TXS3_PID GENMASK(31, 24) - -static inline struct mt7921_txp_common * -mt7921_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - u8 *txwi; - - if (!t) - return NULL; - - txwi = mt76_get_txwi_ptr(dev, t); - - return (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE); -} - -#define MT_HW_TXP_MAX_MSDU_NUM 4 -#define MT_HW_TXP_MAX_BUF_NUM 4 - -#define MT_MSDU_ID_VALID BIT(15) - -#define MT_TXD_LEN_MASK GENMASK(11, 0) -#define MT_TXD_LEN_MSDU_LAST BIT(14) -#define MT_TXD_LEN_AMSDU_LAST BIT(15) -#define MT_TXD_LEN_LAST BIT(15) - -struct mt7921_txp_ptr { - __le32 buf0; - __le16 len0; - __le16 len1; - __le32 buf1; -} __packed __aligned(4); - -struct mt7921_hw_txp { - __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; - struct mt7921_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; -} __packed __aligned(4); - -struct mt7921_txp_common { - union { - struct mt7921_hw_txp hw; - }; -}; - #define MT_WTBL_TXRX_CAP_RATE_OFFSET 7 #define MT_WTBL_TXRX_RATE_G2_HE 24 #define MT_WTBL_TXRX_RATE_G2 12 diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 633c6d2a57ac..7e409ac7d9a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -5,6 +5,7 @@ #include <linux/platform_device.h> #include <linux/pci.h> #include <linux/module.h> +#include <net/ipv6.h> #include "mt7921.h" #include "mcu.h" @@ -12,7 +13,7 @@ static void mt7921_gen_ppe_thresh(u8 *he_ppet, int nss) { u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; + static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, @@ -53,6 +54,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, switch (i) { case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: break; default: continue; @@ -86,6 +88,23 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; switch (i) { + case NL80211_IFTYPE_AP: + he_cap_elem->mac_cap_info[2] |= + IEEE80211_HE_MAC_CAP2_BSR; + he_cap_elem->mac_cap_info[4] |= + IEEE80211_HE_MAC_CAP4_BQR; + he_cap_elem->mac_cap_info[5] |= + IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX; + he_cap_elem->phy_cap_info[3] |= + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; + he_cap_elem->phy_cap_info[6] |= + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; + break; case NL80211_IFTYPE_STATION: he_cap_elem->mac_cap_info[1] |= IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; @@ -128,11 +147,23 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; + + 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[8] |= + IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | + IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU; + } break; } he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); + if (is_mt7922(phy->mt76->dev)) { + he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); + he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); + } memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & @@ -140,7 +171,8 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, mt7921_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US; + u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, + IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); } if (band == NL80211_BAND_6GHZ) { @@ -166,7 +198,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, if (vht_cap->cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN) cap |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; - data->he_6ghz_capa.capa = cpu_to_le16(cap); + data[idx].he_6ghz_capa.capa = cpu_to_le16(cap); } idx++; } @@ -221,11 +253,11 @@ int __mt7921_start(struct mt7921_phy *phy) if (err) return err; - err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); if (err) return err; - err = mt76_connac_mcu_set_rate_txpower(phy->mt76); + err = mt7921_set_tx_sar_pwr(mphy->hw, NULL); if (err) return err; @@ -251,7 +283,7 @@ static int mt7921_start(struct ieee80211_hw *hw) return err; } -static void mt7921_stop(struct ieee80211_hw *hw) +void mt7921_stop(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); @@ -260,6 +292,7 @@ static void mt7921_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&dev->pm.ps_work); cancel_work_sync(&dev->pm.wake_work); + cancel_work_sync(&dev->reset_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); mt7921_mutex_acquire(dev); @@ -267,6 +300,7 @@ static void mt7921_stop(struct ieee80211_hw *hw) mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); mt7921_mutex_release(dev); } +EXPORT_SYMBOL_GPL(mt7921_stop); static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) @@ -279,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, mt7921_mutex_acquire(dev); - mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -288,21 +322,21 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, mvif->mt76.omac_idx = mvif->mt76.idx; mvif->phy = phy; mvif->mt76.band_idx = 0; - mvif->mt76.wmm_idx = mvif->mt76.idx % MT7921_MAX_WMM_SETS; + mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); if (ret) goto out; - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); idx = MT7921_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; - mvif->sta.wcid.ext_phy = mvif->mt76.band_idx; + mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; mt76_packet_id_init(&mvif->sta.wcid); @@ -315,15 +349,10 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } - if (vif->type != NL80211_IFTYPE_AP && - (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) - vif->offload_flags = 0; - - vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; - + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; out: mt7921_mutex_release(dev); @@ -345,7 +374,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt7921_mutex_release(dev); @@ -369,7 +398,7 @@ static int mt7921_set_channel(struct mt7921_phy *phy) mt76_set_channel(phy->mt76); - ret = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); + ret = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH)); if (ret) goto out; @@ -445,24 +474,82 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); - err = mt7921_mcu_add_key(dev, vif, msta, key, cmd); + err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, + key, MCU_UNI_CMD(STA_REC_UPDATE), + &msta->wcid, cmd); if (err) goto out; if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || key->cipher == WLAN_CIPHER_SUITE_WEP40) - err = mt7921_mcu_add_key(dev, vif, mvif->wep_sta, key, cmd); + err = mt76_connac_mcu_add_key(&dev->mt76, vif, + &mvif->wep_sta->bip, + key, MCU_UNI_CMD(STA_REC_UPDATE), + &mvif->wep_sta->wcid, cmd); out: mt7921_mutex_release(dev); return err; } +static void +mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt7921_dev *dev = priv; + struct ieee80211_hw *hw = mt76_hw(dev); + bool pm_enable = dev->pm.enable; + int err; + + err = mt7921_mcu_set_beacon_filter(dev, vif, pm_enable); + if (err < 0) + return; + + if (pm_enable) { + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + ieee80211_hw_set(hw, CONNECTION_MONITOR); + } else { + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; + __clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags); + } +} + +static void +mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt7921_dev *dev = priv; + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + mt7921_mcu_set_sniffer(dev, vif, monitor); + pm->enable = pm->enable_user && !monitor; + pm->ds_enable = pm->ds_enable_user && !monitor; + + mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); + + if (monitor) + mt7921_mcu_set_beacon_filter(dev, vif, false); +} + +void mt7921_set_runtime_pm(struct mt7921_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + pm->enable = pm->enable_user && !monitor; + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_pm_interface_iter, dev); + pm->ds_enable = pm->ds_enable_user && !monitor; + mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); +} + static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); - int ret; + int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); @@ -474,36 +561,34 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) mt7921_mutex_acquire(dev); - if (changed & IEEE80211_CONF_CHANGE_POWER) - mt76_connac_mcu_set_rate_txpower(phy->mt76); + if (changed & IEEE80211_CONF_CHANGE_POWER) { + ret = mt7921_set_tx_sar_pwr(hw, NULL); + if (ret) + goto out; + } if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); - - if (!enabled) - phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; - else - phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - - mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN, - enabled); - mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7921_sniffer_interface_iter, dev); + dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0)); } +out: mt7921_mutex_release(dev); - return 0; + return ret; } static int -mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; /* no need to update right away, we'll get BSS_CHANGED_QOS */ - queue = mt7921_lmac_mapping(dev, queue); + queue = mt76_connac_lmac_mapping(queue); mvif->queue_params[queue] = *params; return 0; @@ -515,7 +600,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | MT_WF_RFCR1_DROP_BF_POLL | MT_WF_RFCR1_DROP_BA | @@ -525,23 +609,23 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - phy->rxfilter &= ~(_hw); \ - phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + dev->mt76.rxfilter &= ~(_hw); \ + dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) mt7921_mutex_acquire(dev); - phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); + dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | @@ -555,7 +639,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); + mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter); if (*total_flags & FIF_CONTROL) mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags); @@ -568,7 +652,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = mt7921_hw_dev(hw); @@ -584,6 +668,11 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, } } + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, + info->enable_beacon); + /* ensure that enable txcmd_mode after bss_info */ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7921_mcu_set_tx(dev, vif); @@ -594,8 +683,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_ASSOC); - if (dev->pm.enable) - mt7921_mcu_set_beacon_filter(dev, vif, info->assoc); + mt7921_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); } if (changed & BSS_CHANGED_ARP_FILTER) { @@ -624,7 +712,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; - msta->wcid.ext_phy = mvif->mt76.band_idx; + msta->wcid.phy_idx = mvif->mt76.band_idx; msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; msta->last_txs = jiffies; @@ -664,6 +752,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7921_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); @@ -957,7 +1046,7 @@ mt7921_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) if (msta->vif->mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->stats); + mt76_ethtool_worker(wi, &msta->wcid.stats); } static @@ -1094,7 +1183,7 @@ void mt7921_scan_work(struct work_struct *work) scan_work.work); while (true) { - struct mt7921_mcu_rxd *rxd; + struct mt76_connac2_mcu_rxd *rxd; struct sk_buff *skb; spin_lock_bh(&phy->dev->mt76.lock); @@ -1104,7 +1193,7 @@ void mt7921_scan_work(struct work_struct *work) if (!skb) break; - rxd = (struct mt7921_mcu_rxd *)skb->data; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; if (rxd->eid == MCU_EVENT_SCHED_SCAN_DONE) { ieee80211_sched_scan_results(phy->mt76->hw); } else if (test_and_clear_bit(MT76_HW_SCANNING, @@ -1238,7 +1327,6 @@ static int mt7921_suspend(struct ieee80211_hw *hw, { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); - int err; cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -1249,34 +1337,24 @@ static int mt7921_suspend(struct ieee80211_hw *hw, mt7921_mutex_acquire(dev); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); - - set_bit(MT76_STATE_SUSPEND, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, - mt76_connac_mcu_set_suspend_iter, + mt7921_mcu_set_suspend_iter, &dev->mphy); - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); - mt7921_mutex_release(dev); - return err; + return 0; } static int mt7921_resume(struct ieee80211_hw *hw) { struct mt7921_dev *dev = mt7921_hw_dev(hw); struct mt7921_phy *phy = mt7921_hw_phy(hw); - int err; mt7921_mutex_acquire(dev); - err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); - if (err < 0) - goto out; - set_bit(MT76_STATE_RUNNING, &phy->mt76->state); - clear_bit(MT76_STATE_SUSPEND, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt76_connac_mcu_set_suspend_iter, @@ -1284,11 +1362,10 @@ static int mt7921_resume(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, MT7921_WATCHDOG_TIME); -out: mt7921_mutex_release(dev); - return err; + return 0; } static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled) @@ -1328,52 +1405,172 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; struct mt7921_dev *dev = mt7921_hw_dev(hw); + mt7921_mutex_acquire(dev); + if (enabled) set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); else clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, - MCU_UNI_CMD_STA_REC_UPDATE); + MCU_UNI_CMD(STA_REC_UPDATE)); + + mt7921_mutex_release(dev); +} + +#if IS_ENABLED(CONFIG_IPV6) +static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct inet6_dev *idev) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_dev *dev = mvif->phy->dev; + struct inet6_ifaddr *ifa; + struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; + struct sk_buff *skb; + u8 i, idx = 0; + + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arpns; + } req_hdr = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arpns = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), + .mode = 2, /* update */ + .option = 1, /* update only */ + }, + }; + + read_lock_bh(&idev->lock); + list_for_each_entry(ifa, &idev->addr_list, if_list) { + if (ifa->flags & IFA_F_TENTATIVE) + continue; + ns_addrs[idx] = ifa->addr; + if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN) + break; + } + read_unlock_bh(&idev->lock); + + if (!idx) + return; + + req_hdr.arpns.ips_num = idx; + req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv) + + idx * sizeof(struct in6_addr)); + skb = __mt76_mcu_msg_alloc(&dev->mt76, &req_hdr, + sizeof(req_hdr) + idx * sizeof(struct in6_addr), + sizeof(req_hdr), GFP_ATOMIC); + if (!skb) + return; + + for (i = 0; i < idx; i++) + skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr)); + + skb_queue_tail(&dev->ipv6_ns_list, skb); + + ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work); +} +#endif + +int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt76_phy *mphy = hw->priv; + int err; + + if (sar) { + err = mt76_init_sar_power(hw, sar); + if (err) + return err; + } + + mt7921_init_acpi_sar_power(mt7921_hw_phy(hw), !sar); + + err = mt76_connac_mcu_set_rate_txpower(mphy); + + return err; } static int mt7921_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { - const struct cfg80211_sar_capa *capa = hw->wiphy->sar_capa; struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt76_freq_range_power *data, *frp; - struct mt76_phy *mphy = hw->priv; int err; - u32 i; - - if (sar->type != NL80211_SAR_TYPE_POWER || !sar->num_sub_specs) - return -EINVAL; mt7921_mutex_acquire(dev); + err = mt7921_set_tx_sar_pwr(hw, sar); + mt7921_mutex_release(dev); + + return err; +} + +static void +mt7921_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct mt7921_dev *dev = mt7921_hw_dev(hw); - data = mphy->frp; + mt7921_mutex_acquire(dev); + mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); + mt7921_mutex_release(dev); +} - for (i = 0; i < sar->num_sub_specs; i++) { - u32 index = sar->sub_specs[i].freq_range_index; - /* SAR specifies power limitaton in 0.25dbm */ - s32 power = sar->sub_specs[i].power >> 1; +static int +mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt7921_dev *dev = mt7921_hw_dev(hw); + int err; - if (power > 127 || power < -127) - power = 127; + mt7921_mutex_acquire(dev); - frp = &data[index]; - frp->range = &capa->freq_ranges[index]; - frp->power = power; - } + err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, + true); + if (err) + goto out; - err = mt76_connac_mcu_set_rate_txpower(mphy); + err = mt7921_mcu_set_bss_pm(dev, vif, true); + if (err) + goto out; + err = mt7921_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); +out: mt7921_mutex_release(dev); return err; } +static void +mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt7921_dev *dev = mt7921_hw_dev(hw); + int err; + + mt7921_mutex_acquire(dev); + + err = mt7921_mcu_set_bss_pm(dev, vif, false); + if (err) + goto out; + + mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false); + +out: + mt7921_mutex_release(dev); +} + const struct ieee80211_ops mt7921_ops = { .tx = mt7921_tx, .start = mt7921_start, @@ -1384,14 +1581,20 @@ const struct ieee80211_ops mt7921_ops = { .conf_tx = mt7921_conf_tx, .configure_filter = mt7921_configure_filter, .bss_info_changed = mt7921_bss_info_changed, + .start_ap = mt7921_start_ap, + .stop_ap = mt7921_stop_ap, .sta_state = mt7921_sta_state, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7921_set_key, .sta_set_decap_offload = mt7921_sta_set_decap_offload, +#if IS_ENABLED(CONFIG_IPV6) + .ipv6_addr_change = mt7921_ipv6_addr_change, +#endif /* CONFIG_IPV6 */ .ampdu_action = mt7921_ampdu_action, .set_rts_threshold = mt7921_set_rts_threshold, .wake_tx_queue = mt76_wake_tx_queue, .release_buffered_frames = mt76_release_buffered_frames, + .channel_switch_beacon = mt7921_channel_switch_beacon, .get_txpower = mt76_get_txpower, .get_stats = mt7921_get_stats, .get_et_sset_count = mt7921_get_et_sset_count, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 6ada1ebe7d68..67bf92969a7b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1,146 +1,20 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 MediaTek Inc. */ -#include <linux/firmware.h> #include <linux/fs.h> +#include <linux/firmware.h> #include "mt7921.h" #include "mt7921_trace.h" +#include "eeprom.h" #include "mcu.h" #include "mac.h" -struct mt7921_patch_hdr { - char build_date[16]; - char platform[4]; - __be32 hw_sw_ver; - __be32 patch_ver; - __be16 checksum; - u16 reserved; - struct { - __be32 patch_ver; - __be32 subsys; - __be32 feature; - __be32 n_region; - __be32 crc; - u32 reserved[11]; - } desc; -} __packed; - -struct mt7921_patch_sec { - __be32 type; - __be32 offs; - __be32 size; - union { - __be32 spec[13]; - struct { - __be32 addr; - __be32 len; - __be32 sec_key_idx; - __be32 align_len; - u32 reserved[9]; - } info; - }; -} __packed; - -struct mt7921_fw_trailer { - u8 chip_id; - u8 eco_code; - u8 n_region; - u8 format_ver; - u8 format_flag; - u8 reserved[2]; - char fw_ver[10]; - char build_date[15]; - u32 crc; -} __packed; - -struct mt7921_fw_region { - __le32 decomp_crc; - __le32 decomp_len; - __le32 decomp_blk_sz; - u8 reserved[4]; - __le32 addr; - __le32 len; - u8 feature_set; - u8 reserved1[15]; -} __packed; - #define MT_STA_BFER BIT(0) #define MT_STA_BFEE BIT(1) -#define FW_FEATURE_SET_ENCRYPT BIT(0) -#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) -#define FW_FEATURE_ENCRY_MODE BIT(4) -#define FW_FEATURE_OVERRIDE_ADDR BIT(5) - -#define DL_MODE_ENCRYPT BIT(0) -#define DL_MODE_KEY_IDX GENMASK(2, 1) -#define DL_MODE_RESET_SEC_IV BIT(3) -#define DL_MODE_WORKING_PDA_CR4 BIT(4) -#define DL_CONFIG_ENCRY_MODE_SEL BIT(6) -#define DL_MODE_NEED_RSP BIT(31) - -#define FW_START_OVERRIDE BIT(0) -#define FW_START_WORKING_PDA_CR4 BIT(2) - -#define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0) -#define PATCH_SEC_TYPE_MASK GENMASK(15, 0) -#define PATCH_SEC_TYPE_INFO 0x2 - -#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24) -#define PATCH_SEC_ENC_TYPE_PLAIN 0x00 -#define PATCH_SEC_ENC_TYPE_AES 0x01 -#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02 -#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0) -#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0) - -#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) -#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) - -static enum mcu_cipher_type -mt7921_mcu_get_cipher(int cipher) -{ - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - return MCU_CIPHER_WEP40; - case WLAN_CIPHER_SUITE_WEP104: - return MCU_CIPHER_WEP104; - case WLAN_CIPHER_SUITE_TKIP: - return MCU_CIPHER_TKIP; - case WLAN_CIPHER_SUITE_AES_CMAC: - return MCU_CIPHER_BIP_CMAC_128; - case WLAN_CIPHER_SUITE_CCMP: - return MCU_CIPHER_AES_CCMP; - case WLAN_CIPHER_SUITE_CCMP_256: - return MCU_CIPHER_CCMP_256; - case WLAN_CIPHER_SUITE_GCMP: - return MCU_CIPHER_GCMP; - case WLAN_CIPHER_SUITE_GCMP_256: - return MCU_CIPHER_GCMP_256; - case WLAN_CIPHER_SUITE_SMS4: - return MCU_CIPHER_WAPI; - default: - return MCU_CIPHER_NONE; - } -} - -static u8 mt7921_mcu_chan_bw(struct cfg80211_chan_def *chandef) -{ - static const u8 width_to_bw[] = { - [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ, - [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ, - [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ, - [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ, - [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ, - [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, - [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, - [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, - }; - - if (chandef->width >= ARRAY_SIZE(width_to_bw)) - return 0; - - return width_to_bw[chandef->width]; -} +static bool mt7921_disable_clc; +module_param_named(disable_clc, mt7921_disable_clc, bool, 0644); +MODULE_PARM_DESC(disable_clc, "disable CLC support"); static int mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb) @@ -151,7 +25,7 @@ mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb) if (!skb) return -EINVAL; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); res = (struct mt7921_mcu_eeprom_info *)skb->data; buf = dev->eeprom.data + le32_to_cpu(res->addr); @@ -163,8 +37,8 @@ mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb) int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq) { - struct mt7921_mcu_rxd *rxd; - int mcu_cmd = cmd & MCU_CMD_MASK; + int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); + struct mt76_connac2_mcu_rxd *rxd; int ret = 0; if (!skb) { @@ -175,28 +49,25 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, return -ETIMEDOUT; } - rxd = (struct mt7921_mcu_rxd *)skb->data; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; if (seq != rxd->seq) return -EAGAIN; - switch (cmd) { - case MCU_CMD_PATCH_SEM_CONTROL: + if (cmd == MCU_CMD(PATCH_SEM_CONTROL) || + cmd == MCU_CMD(PATCH_FINISH_REQ)) { skb_pull(skb, sizeof(*rxd) - 4); ret = *skb->data; - break; - case MCU_EXT_CMD_GET_TEMP: + } else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) { skb_pull(skb, sizeof(*rxd) + 4); ret = le32_to_cpu(*(__le32 *)skb->data); - break; - case MCU_EXT_CMD_EFUSE_ACCESS: + } else if (cmd == MCU_EXT_CMD(EFUSE_ACCESS)) { ret = mt7921_mcu_parse_eeprom(mdev, skb); - break; - case MCU_UNI_CMD_DEV_INFO_UPDATE: - case MCU_UNI_CMD_BSS_INFO_UPDATE: - case MCU_UNI_CMD_STA_REC_UPDATE: - case MCU_UNI_CMD_HIF_CTRL: - case MCU_UNI_CMD_OFFLOAD: - case MCU_UNI_CMD_SUSPEND: { + } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) || + cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) || + cmd == MCU_UNI_CMD(STA_REC_UPDATE) || + cmd == MCU_UNI_CMD(HIF_CTRL) || + cmd == MCU_UNI_CMD(OFFLOAD) || + cmd == MCU_UNI_CMD(SUSPEND)) { struct mt7921_mcu_uni_event *event; skb_pull(skb, sizeof(*rxd)); @@ -205,119 +76,83 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, /* skip invalid event */ if (mcu_cmd != event->cid) ret = -EAGAIN; - break; - } - case MCU_CMD_REG_READ: { + } else if (cmd == MCU_CE_QUERY(REG_READ)) { struct mt7921_mcu_reg_event *event; skb_pull(skb, sizeof(*rxd)); event = (struct mt7921_mcu_reg_event *)skb->data; ret = (int)le32_to_cpu(event->val); - break; - } - default: - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); - break; + } else { + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); } return ret; } EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response); -int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, int *wait_seq) +static int mt7921_mcu_read_eeprom(struct mt7921_dev *dev, u32 offset, u8 *val) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - int txd_len, mcu_cmd = cmd & MCU_CMD_MASK; - struct mt7921_uni_txd *uni_txd; - struct mt7921_mcu_txd *mcu_txd; - __le32 *txd; - u32 val; - u8 seq; - - switch (cmd) { - case MCU_UNI_CMD_HIF_CTRL: - case MCU_UNI_CMD_SUSPEND: - case MCU_UNI_CMD_OFFLOAD: - mdev->mcu.timeout = HZ / 3; - break; - default: - mdev->mcu.timeout = 3 * HZ; - break; - } + struct mt7921_mcu_eeprom_info *res, req = { + .addr = cpu_to_le32(round_down(offset, + MT7921_EEPROM_BLOCK_SIZE)), + }; + struct sk_buff *skb; + int ret; - seq = ++dev->mt76.mcu.msg_seq & 0xf; - if (!seq) - seq = ++dev->mt76.mcu.msg_seq & 0xf; + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_ACCESS), + &req, sizeof(req), true, &skb); + if (ret) + return ret; - if (cmd == MCU_CMD_FW_SCATTER) - goto exit; + res = (struct mt7921_mcu_eeprom_info *)skb->data; + *val = res->data[offset % MT7921_EEPROM_BLOCK_SIZE]; + dev_kfree_skb(skb); - txd_len = cmd & MCU_UNI_PREFIX ? sizeof(*uni_txd) : sizeof(*mcu_txd); - txd = (__le32 *)skb_push(skb, txd_len); + return 0; +} - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | - FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) | - FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0); - txd[0] = cpu_to_le32(val); +#ifdef CONFIG_PM - val = MT_TXD1_LONG_FORMAT | - FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD); - txd[1] = cpu_to_le32(val); +static int +mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev, + struct ieee80211_vif *vif, bool suspend) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arpns; + } req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arpns = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), + .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)), + .mode = suspend, + }, + }; - if (cmd & MCU_UNI_PREFIX) { - uni_txd = (struct mt7921_uni_txd *)txd; - uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); - uni_txd->option = MCU_CMD_UNI_EXT_ACK; - uni_txd->cid = cpu_to_le16(mcu_cmd); - uni_txd->s2d_index = MCU_S2D_H2N; - uni_txd->pkt_type = MCU_PKT_ID; - uni_txd->seq = seq; + return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req), + true); +} - goto exit; - } +void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + if (IS_ENABLED(CONFIG_IPV6)) { + struct mt76_phy *phy = priv; - mcu_txd = (struct mt7921_mcu_txd *)txd; - mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); - mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, - MT_TX_MCU_PORT_RX_Q0)); - mcu_txd->pkt_type = MCU_PKT_ID; - mcu_txd->seq = seq; - - switch (cmd & ~MCU_CMD_MASK) { - case MCU_FW_PREFIX: - mcu_txd->set_query = MCU_Q_NA; - mcu_txd->cid = mcu_cmd; - break; - case MCU_CE_PREFIX: - if (cmd & MCU_QUERY_MASK) - mcu_txd->set_query = MCU_Q_QUERY; - else - mcu_txd->set_query = MCU_Q_SET; - mcu_txd->cid = mcu_cmd; - break; - default: - mcu_txd->cid = MCU_CMD_EXT_CID; - if (cmd & MCU_QUERY_PREFIX || cmd == MCU_EXT_CMD_EFUSE_ACCESS) - mcu_txd->set_query = MCU_Q_QUERY; - else - mcu_txd->set_query = MCU_Q_SET; - mcu_txd->ext_cid = mcu_cmd; - mcu_txd->ext_cid_ack = 1; - break; + mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif, + !test_bit(MT76_STATE_RUNNING, + &phy->state)); } - mcu_txd->s2d_index = MCU_S2D_H2N; - WARN_ON(cmd == MCU_EXT_CMD_EFUSE_ACCESS && - mcu_txd->set_query != MCU_Q_QUERY); - -exit: - if (wait_seq) - *wait_seq = seq; - - return 0; + mt76_connac_mcu_set_suspend_iter(priv, mac, vif); } -EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message); + +#endif /* CONFIG_PM */ static void mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) @@ -343,7 +178,8 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac, if (mvif->idx != event->bss_idx) return; - if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER)) + if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) || + vif->type != NL80211_IFTYPE_STATION) return; ieee80211_connection_loss(vif); @@ -355,7 +191,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb) struct mt76_connac_beacon_loss_event *event; struct mt76_phy *mphy = &dev->mt76.phy; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); event = (struct mt76_connac_beacon_loss_event *)skb->data; ieee80211_iterate_active_interfaces_atomic(mphy->hw, @@ -369,7 +205,7 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb) struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_mcu_bss_event *event; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); event = (struct mt76_connac_mcu_bss_event *)skb->data; if (event->is_absent) ieee80211_stop_queues(mphy->hw); @@ -389,7 +225,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) u8 content[512]; } __packed * msg; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); msg = (struct mt7921_debug_msg *)skb->data; if (msg->type == 3) { /* fw log */ @@ -412,17 +248,29 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) u8 reserved[3]; } __packed * event; - skb_pull(skb, sizeof(struct mt7921_mcu_rxd)); + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); event = (struct mt7921_mcu_lp_event *)skb->data; trace_lp_event(dev, event->state); } static void +mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) +{ + struct mt7921_mcu_tx_done_event *event; + + skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); + event = (struct mt7921_mcu_tx_done_event *)skb->data; + + mt7921_mac_add_txs(dev, event->txs); +} + +static void mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) { - struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data; + struct mt76_connac2_mcu_rxd *rxd; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; switch (rxd->eid) { case MCU_EVENT_BSS_BEACON_LOSS: mt7921_mcu_connection_loss_event(dev, skb); @@ -445,6 +293,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) case MCU_EVENT_LP_INFO: mt7921_mcu_low_power_event(dev, skb); break; + case MCU_EVENT_TX_DONE: + mt7921_mcu_tx_done_event(dev, skb); + break; default: break; } @@ -453,12 +304,12 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) { - struct mt7921_mcu_rxd *rxd; + struct mt76_connac2_mcu_rxd *rxd; if (skb_linearize(skb)) return; - rxd = (struct mt7921_mcu_rxd *)skb->data; + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; if (rxd->eid == 0x6) { mt76_mcu_rx_event(&dev->mt76, skb); @@ -481,95 +332,6 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) } /** starec & wtbl **/ -static int -mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb, - struct ieee80211_key_conf *key, enum set_key_cmd cmd) -{ - struct mt7921_sta_key_conf *bip = &msta->bip; - struct sta_rec_sec *sec; - struct tlv *tlv; - u32 len = sizeof(*sec); - - tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); - - sec = (struct sta_rec_sec *)tlv; - sec->add = cmd; - - if (cmd == SET_KEY) { - struct sec_key *sec_key; - u8 cipher; - - cipher = mt7921_mcu_get_cipher(key->cipher); - if (cipher == MCU_CIPHER_NONE) - return -EOPNOTSUPP; - - sec_key = &sec->key[0]; - sec_key->cipher_len = sizeof(*sec_key); - - if (cipher == MCU_CIPHER_BIP_CMAC_128) { - sec_key->cipher_id = MCU_CIPHER_AES_CCMP; - sec_key->key_id = bip->keyidx; - sec_key->key_len = 16; - memcpy(sec_key->key, bip->key, 16); - - sec_key = &sec->key[1]; - sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; - sec_key->cipher_len = sizeof(*sec_key); - sec_key->key_len = 16; - memcpy(sec_key->key, key->key, 16); - - sec->n_cipher = 2; - } else { - sec_key->cipher_id = cipher; - sec_key->key_id = key->keyidx; - sec_key->key_len = key->keylen; - memcpy(sec_key->key, key->key, key->keylen); - - 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); - } - - /* store key_conf for BIP batch update */ - if (cipher == MCU_CIPHER_AES_CCMP) { - memcpy(bip->key, key->key, key->keylen); - bip->keyidx = key->keyidx; - } - - len -= sizeof(*sec_key); - sec->n_cipher = 1; - } - } else { - len -= sizeof(sec->key); - sec->n_cipher = 0; - } - sec->len = cpu_to_le16(len); - - return 0; -} - -int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif, - struct mt7921_sta *msta, struct ieee80211_key_conf *key, - enum set_key_cmd cmd) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct sk_buff *skb; - int ret; - - skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, - &msta->wcid); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - ret = mt7921_mcu_sta_key_tlv(msta, skb, key, cmd); - if (ret) - return ret; - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); -} - int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, struct ieee80211_ampdu_params *params, bool enable) @@ -580,6 +342,7 @@ int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, msta->wcid.amsdu = false; return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, + MCU_UNI_CMD(STA_REC_UPDATE), enable, true); } @@ -590,261 +353,112 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv; return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, + MCU_UNI_CMD(STA_REC_UPDATE), enable, false); } -int mt7921_mcu_restart(struct mt76_dev *dev) -{ - struct { - u8 power_mode; - u8 rsv[3]; - } req = { - .power_mode = 1, - }; - - return mt76_mcu_send_msg(dev, MCU_CMD_NIC_POWER_CTRL, &req, - sizeof(req), false); -} -EXPORT_SYMBOL_GPL(mt7921_mcu_restart); - -static u32 mt7921_get_data_mode(struct mt7921_dev *dev, u32 info) +static char *mt7921_patch_name(struct mt7921_dev *dev) { - u32 mode = DL_MODE_NEED_RSP; - - if (info == PATCH_SEC_NOT_SUPPORT) - return mode; + char *ret; - switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) { - case PATCH_SEC_ENC_TYPE_PLAIN: - break; - case PATCH_SEC_ENC_TYPE_AES: - mode |= DL_MODE_ENCRYPT; - mode |= FIELD_PREP(DL_MODE_KEY_IDX, - (info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX; - mode |= DL_MODE_RESET_SEC_IV; - break; - case PATCH_SEC_ENC_TYPE_SCRAMBLE: - mode |= DL_MODE_ENCRYPT; - mode |= DL_CONFIG_ENCRY_MODE_SEL; - mode |= DL_MODE_RESET_SEC_IV; - break; - default: - dev_err(dev->mt76.dev, "Encryption type not support!\n"); - } + if (is_mt7922(&dev->mt76)) + ret = MT7922_ROM_PATCH; + else + ret = MT7921_ROM_PATCH; - return mode; + return ret; } -static char *mt7921_patch_name(struct mt7921_dev *dev) +static char *mt7921_ram_name(struct mt7921_dev *dev) { char *ret; if (is_mt7922(&dev->mt76)) - ret = MT7922_ROM_PATCH; + ret = MT7922_FIRMWARE_WM; else - ret = MT7921_ROM_PATCH; + ret = MT7921_FIRMWARE_WM; return ret; } -static int mt7921_load_patch(struct mt7921_dev *dev) +static int mt7921_load_clc(struct mt7921_dev *dev, const char *fw_name) { - const struct mt7921_patch_hdr *hdr; - const struct firmware *fw = NULL; - int i, ret, sem, max_len; - - max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096; + const struct mt76_connac2_fw_trailer *hdr; + const struct mt76_connac2_fw_region *region; + const struct mt7921_clc *clc; + struct mt76_dev *mdev = &dev->mt76; + struct mt7921_phy *phy = &dev->phy; + const struct firmware *fw; + int ret, i, len, offset = 0; + u8 *clc_base = NULL, hw_encap = 0; - sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true); - switch (sem) { - case PATCH_IS_DL: + if (mt7921_disable_clc || + mt76_is_usb(&dev->mt76)) return 0; - case PATCH_NOT_DL_SEM_SUCCESS: - break; - default: - dev_err(dev->mt76.dev, "Failed to get patch semaphore\n"); - return -EAGAIN; + + if (mt76_is_mmio(&dev->mt76)) { + ret = mt7921_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap); + if (ret) + return ret; + hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP); } - ret = request_firmware(&fw, mt7921_patch_name(dev), dev->mt76.dev); + ret = request_firmware(&fw, fw_name, mdev->dev); if (ret) - goto out; + return ret; if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); + dev_err(mdev->dev, "Invalid firmware\n"); ret = -EINVAL; goto out; } - hdr = (const struct mt7921_patch_hdr *)(fw->data); - - dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", - be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); - - for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { - struct mt7921_patch_sec *sec; - const u8 *dl; - u32 len, addr, mode; - u32 sec_info = 0; - - sec = (struct mt7921_patch_sec *)(fw->data + sizeof(*hdr) + - i * sizeof(*sec)); - if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) != - PATCH_SEC_TYPE_INFO) { - ret = -EINVAL; - goto out; - } - - addr = be32_to_cpu(sec->info.addr); - len = be32_to_cpu(sec->info.len); - dl = fw->data + be32_to_cpu(sec->offs); - sec_info = be32_to_cpu(sec->info.sec_key_idx); - mode = mt7921_get_data_mode(dev, sec_info); - - ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len, - mode); - if (ret) { - dev_err(dev->mt76.dev, "Download request failed\n"); - goto out; - } - - ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, - dl, len, max_len); - if (ret) { - dev_err(dev->mt76.dev, "Failed to send patch\n"); - goto out; - } - } - - ret = mt76_connac_mcu_start_patch(&dev->mt76); - if (ret) - dev_err(dev->mt76.dev, "Failed to start patch\n"); - -out: - sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false); - switch (sem) { - case PATCH_REL_SEM_SUCCESS: - break; - default: - ret = -EAGAIN; - dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); - break; - } - release_firmware(fw); - - return ret; -} - -static u32 mt7921_mcu_gen_dl_mode(u8 feature_set, bool is_wa) -{ - u32 ret = 0; - - ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? - (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; - ret |= (feature_set & FW_FEATURE_ENCRY_MODE) ? - DL_CONFIG_ENCRY_MODE_SEL : 0; - ret |= FIELD_PREP(DL_MODE_KEY_IDX, - FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); - ret |= DL_MODE_NEED_RSP; - ret |= is_wa ? DL_MODE_WORKING_PDA_CR4 : 0; - - return ret; -} - -static int -mt7921_mcu_send_ram_firmware(struct mt7921_dev *dev, - const struct mt7921_fw_trailer *hdr, - const u8 *data, bool is_wa) -{ - int i, offset = 0, max_len; - u32 override = 0, option = 0; - - max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096; - + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); for (i = 0; i < hdr->n_region; i++) { - const struct mt7921_fw_region *region; - int err; - u32 len, addr, mode; - - region = (const struct mt7921_fw_region *)((const u8 *)hdr - - (hdr->n_region - i) * sizeof(*region)); - mode = mt7921_mcu_gen_dl_mode(region->feature_set, is_wa); + region = (const void *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); len = le32_to_cpu(region->len); - addr = le32_to_cpu(region->addr); - if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) - override = addr; - - err = mt76_connac_mcu_init_download(&dev->mt76, addr, len, - mode); - if (err) { - dev_err(dev->mt76.dev, "Download request failed\n"); - return err; + /* check if we have valid buffer size */ + if (offset + len > fw->size) { + dev_err(mdev->dev, "Invalid firmware region\n"); + ret = -EINVAL; + goto out; } - err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, - data + offset, len, max_len); - if (err) { - dev_err(dev->mt76.dev, "Failed to send firmware.\n"); - return err; + if ((region->feature_set & FW_FEATURE_NON_DL) && + region->type == FW_TYPE_CLC) { + clc_base = (u8 *)(fw->data + offset); + break; } - offset += len; } - if (override) - option |= FW_START_OVERRIDE; - - if (is_wa) - option |= FW_START_WORKING_PDA_CR4; - - return mt76_connac_mcu_start_firmware(&dev->mt76, override, option); -} - -static char *mt7921_ram_name(struct mt7921_dev *dev) -{ - char *ret; - - if (is_mt7922(&dev->mt76)) - ret = MT7922_FIRMWARE_WM; - else - ret = MT7921_FIRMWARE_WM; - - return ret; -} - -static int mt7921_load_ram(struct mt7921_dev *dev) -{ - const struct mt7921_fw_trailer *hdr; - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, mt7921_ram_name(dev), dev->mt76.dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; + if (!clc_base) goto out; - } - hdr = (const struct mt7921_fw_trailer *)(fw->data + fw->size - - sizeof(*hdr)); + for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) { + clc = (const struct mt7921_clc *)(clc_base + offset); - dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); + /* do not init buf again if chip reset triggered */ + if (phy->clc[clc->idx]) + continue; - ret = mt7921_mcu_send_ram_firmware(dev, hdr, fw->data, false); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); - goto out; - } + /* header content sanity */ + if (clc->idx == MT7921_CLC_POWER && + u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap) + continue; - snprintf(dev->mt76.hw->wiphy->fw_version, - sizeof(dev->mt76.hw->wiphy->fw_version), - "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc, + le32_to_cpu(clc->len), + GFP_KERNEL); + if (!phy->clc[clc->idx]) { + ret = -ENOMEM; + goto out; + } + } + ret = mt7921_mcu_set_clc(dev, "00", ENVIRON_INDOOR); out: release_firmware(fw); @@ -861,11 +475,18 @@ static int mt7921_load_firmware(struct mt7921_dev *dev) goto fw_loaded; } - ret = mt7921_load_patch(dev); + ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev)); if (ret) return ret; - ret = mt7921_load_ram(dev); + if (mt76_is_sdio(&dev->mt76)) { + /* activate again */ + ret = __mt7921_mcu_fw_pmctrl(dev); + if (!ret) + ret = __mt7921_mcu_drv_pmctrl(dev); + } + + ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL); if (ret) return ret; @@ -882,7 +503,7 @@ fw_loaded: dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; #endif /* CONFIG_PM */ - dev_err(dev->mt76.dev, "Firmware init done\n"); + dev_dbg(dev->mt76.dev, "Firmware init done\n"); return 0; } @@ -896,8 +517,8 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) .ctrl_val = ctrl }; - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FWLOG_2_HOST, &data, - sizeof(data), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(FWLOG_2_HOST), + &data, sizeof(data), false); } int mt7921_run_firmware(struct mt7921_dev *dev) @@ -913,45 +534,36 @@ int mt7921_run_firmware(struct mt7921_dev *dev) return err; set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + err = mt7921_load_clc(dev, mt7921_ram_name(dev)); + if (err) + return err; + return mt7921_mcu_fw_log_2_host(dev, 1); } EXPORT_SYMBOL_GPL(mt7921_run_firmware); -void mt7921_mcu_exit(struct mt7921_dev *dev) -{ - skb_queue_purge(&dev->mt76.mcu.res_q); -} -EXPORT_SYMBOL_GPL(mt7921_mcu_exit); - int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) { -#define WMM_AIFS_SET BIT(0) -#define WMM_CW_MIN_SET BIT(1) -#define WMM_CW_MAX_SET BIT(2) -#define WMM_TXOP_SET BIT(3) -#define WMM_PARAM_SET GENMASK(3, 0) -#define TX_CMD_MODE 1 + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct edca { - u8 queue; - u8 set; - u8 aifs; - u8 cw_min; + __le16 cw_min; __le16 cw_max; __le16 txop; - }; + __le16 aifs; + u8 guardtime; + u8 acm; + } __packed; struct mt7921_mcu_tx { - u8 total; - u8 action; - u8 valid; - u8 mode; - struct edca edca[IEEE80211_NUM_ACS]; + u8 bss_idx; + u8 qos; + u8 wmm_idx; + u8 pad; } __packed req = { - .valid = true, - .mode = TX_CMD_MODE, - .total = IEEE80211_NUM_ACS, + .bss_idx = mvif->mt76.idx, + .qos = vif->bss_conf.qos, + .wmm_idx = mvif->mt76.wmm_idx, }; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct mu_edca { u8 cw_min; u8 cw_max; @@ -975,30 +587,29 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) .qos = vif->bss_conf.qos, .wmm_idx = mvif->mt76.wmm_idx, }; + static const int to_aci[] = { 1, 0, 2, 3 }; int ac, ret; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac]; - struct edca *e = &req.edca[ac]; + struct edca *e = &req.edca[to_aci[ac]]; - e->set = WMM_PARAM_SET; - e->queue = ac + mvif->mt76.wmm_idx * MT7921_MAX_WMM_SETS; - e->aifs = q->aifs; + e->aifs = cpu_to_le16(q->aifs); e->txop = cpu_to_le16(q->txop); if (q->cw_min) - e->cw_min = fls(q->cw_min); + e->cw_min = cpu_to_le16(q->cw_min); else - e->cw_min = 5; + e->cw_min = cpu_to_le16(5); if (q->cw_max) - e->cw_max = cpu_to_le16(fls(q->cw_max)); + e->cw_max = cpu_to_le16(q->cw_max); else e->cw_max = cpu_to_le16(10); } - ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, - sizeof(req), true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_EDCA_PARMS), &req, + sizeof(req), false); if (ret) return ret; @@ -1008,7 +619,6 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { struct ieee80211_he_mu_edca_param_ac_rec *q; struct mu_edca *e; - int to_aci[] = {1, 0, 2, 3}; if (!mvif->queue_params[ac].mu_edca) break; @@ -1022,8 +632,8 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) e->timer = q->mu_edca_timer; } - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_MU_EDCA_PARMS, &req_mu, - sizeof(req_mu), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_MU_EDCA_PARMS), + &req_mu, sizeof(req_mu), false); } int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) @@ -1051,7 +661,7 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) } __packed req = { .control_ch = chandef->chan->hw_value, .center_ch = ieee80211_frequency_to_channel(freq1), - .bw = mt7921_mcu_chan_bw(chandef), + .bw = mt76_connac_chan_bw(chandef), .tx_streams_num = hweight8(phy->mt76->antenna_mask), .rx_streams = phy->mt76->antenna_mask, .band_idx = phy != &dev->phy, @@ -1062,15 +672,18 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) else req.channel_band = chandef->chan->band; - if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (cmd == MCU_EXT_CMD(SET_RX_PATH) || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + req.switch_reason = CH_SWITCH_NORMAL; + else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; - else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + else if (!cfg80211_reg_can_beacon(dev->mt76.hw->wiphy, chandef, + NL80211_IFTYPE_AP)) req.switch_reason = CH_SWITCH_DFS; else req.switch_reason = CH_SWITCH_NORMAL; - if (cmd == MCU_EXT_CMD_CHANNEL_SWITCH) + if (cmd == MCU_EXT_CMD(CHANNEL_SWITCH)) req.rx_streams = hweight8(req.rx_streams); if (chandef->width == NL80211_CHAN_WIDTH_80P80) { @@ -1093,34 +706,11 @@ int mt7921_mcu_set_eeprom(struct mt7921_dev *dev) .format = EE_FORMAT_WHOLE, }; - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE), &req, sizeof(req), true); } EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom); -int mt7921_mcu_get_eeprom(struct mt7921_dev *dev, u32 offset) -{ - struct mt7921_mcu_eeprom_info req = { - .addr = cpu_to_le32(round_down(offset, 16)), - }; - struct mt7921_mcu_eeprom_info *res; - struct sk_buff *skb; - int ret; - u8 *buf; - - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, - sizeof(req), true, &skb); - if (ret) - return ret; - - res = (struct mt7921_mcu_eeprom_info *)skb->data; - buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); - memcpy(buf, res->data, 16); - dev_kfree_skb(skb); - - return 0; -} - int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; @@ -1147,14 +737,14 @@ int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) .ps = { .tag = cpu_to_le16(UNI_BSS_INFO_PS), .len = cpu_to_le16(sizeof(struct ps_tlv)), - .ps_state = vif->bss_conf.ps ? 2 : 0, + .ps_state = vif->cfg.ps ? 2 : 0, }, }; if (vif->type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; - return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), &ps_req, sizeof(ps_req), true); } @@ -1190,11 +780,11 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, if (vif->type != NL80211_IFTYPE_STATION) return 0; - return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), &bcnft_req, sizeof(bcnft_req), true); } -static int +int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable) { @@ -1211,7 +801,7 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, u8 pad; } req = { .bss_idx = mvif->mt76.idx, - .aid = cpu_to_le16(vif->bss_conf.aid), + .aid = cpu_to_le16(vif->cfg.aid), .dtim_period = vif->bss_conf.dtim_period, .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), }; @@ -1223,16 +813,13 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, }; int err; - if (vif->type != NL80211_IFTYPE_STATION) - return 0; - - err = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, &req_hdr, - sizeof(req_hdr), false); + err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT), + &req_hdr, sizeof(req_hdr), false); if (err < 0 || !enable) return err; - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED), + &req, sizeof(req), false); } int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, @@ -1245,7 +832,7 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, .sta = sta, .vif = vif, .enable = enable, - .cmd = MCU_UNI_CMD_STA_REC_UPDATE, + .cmd = MCU_UNI_CMD(STA_REC_UPDATE), .state = state, .offload_fw = true, .rcpi = to_rcpi(rssi), @@ -1307,7 +894,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct ieee80211_hw *hw = mt76_hw(dev); int err; if (enable) { @@ -1315,8 +901,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, if (err) return err; - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - ieee80211_hw_set(hw, CONNECTION_MONITOR); mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); return 0; @@ -1326,8 +910,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, if (err) return err; - vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; - __clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags); mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); return 0; @@ -1342,7 +924,7 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) struct sk_buff *skb; int ret; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CMD_GET_TXPWR, + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CE_CMD(GET_TXPWR), &req, sizeof(req), true, &skb); if (ret) return ret; @@ -1355,3 +937,194 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) return 0; } + +int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct { + struct { + u8 band_idx; + u8 pad[3]; + } __packed hdr; + struct sniffer_enable_tlv { + __le16 tag; + __le16 len; + u8 enable; + u8 pad[3]; + } __packed enable; + } req = { + .hdr = { + .band_idx = mvif->band_idx, + }, + .enable = { + .tag = cpu_to_le16(0), + .len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)), + .enable = enable, + }, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), + true); +} + +int +mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct ieee80211_mutable_offsets offs; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcn_content_tlv { + __le16 tag; + __le16 len; + __le16 tim_ie_pos; + __le16 csa_ie_pos; + __le16 bcc_ie_pos; + /* 0: disable beacon offload + * 1: enable beacon offload + * 2: update probe respond offload + */ + u8 enable; + /* 0: legacy format (TXD + payload) + * 1: only cap field IE + */ + u8 type; + __le16 pkt_len; + u8 pkt[512]; + } __packed beacon_tlv; + } req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .beacon_tlv = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), + .len = cpu_to_le16(sizeof(struct bcn_content_tlv)), + .enable = enable, + }, + }; + struct sk_buff *skb; + + /* support enable/update process only + * disable flow would be handled in bss stop handler automatically + */ + if (!enable) + return -EOPNOTSUPP; + + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "beacon size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + mt76_connac2_mac_write_txwi(&dev->mt76, (__le32 *)(req.beacon_tlv.pkt), + skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON); + memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + + if (offs.cntdwn_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4; + req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs); + } + dev_kfree_skb(skb); + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &req, sizeof(req), true); +} + +static +int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, + enum environment_cap env_cap, + struct mt7921_clc *clc, + u8 idx) +{ + struct sk_buff *skb; + struct { + u8 ver; + u8 pad0; + __le16 len; + u8 idx; + u8 env; + u8 pad1[2]; + u8 alpha2[2]; + u8 type[2]; + u8 rsvd[64]; + } __packed req = { + .idx = idx, + .env = env_cap, + }; + int ret, valid_cnt = 0; + u8 i, *pos; + + if (!clc) + return 0; + + pos = clc->data; + for (i = 0; i < clc->nr_country; i++) { + struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos; + u16 len = le16_to_cpu(rule->len); + + pos += len + sizeof(*rule); + if (rule->alpha2[0] != alpha2[0] || + rule->alpha2[1] != alpha2[1]) + continue; + + memcpy(req.alpha2, rule->alpha2, 2); + memcpy(req.type, rule->type, 2); + + req.len = cpu_to_le16(sizeof(req) + len); + skb = __mt76_mcu_msg_alloc(&dev->mt76, &req, + le16_to_cpu(req.len), + sizeof(req), GFP_KERNEL); + if (!skb) + return -ENOMEM; + skb_put_data(skb, rule->data, len); + + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_CE_CMD(SET_CLC), false); + if (ret < 0) + return ret; + valid_cnt++; + } + + if (!valid_cnt) + return -ENOENT; + + return 0; +} + +int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, + enum environment_cap env_cap) +{ + struct mt7921_phy *phy = (struct mt7921_phy *)&dev->phy; + int i, ret; + + /* submit all clc config */ + for (i = 0; i < ARRAY_SIZE(phy->clc); i++) { + ret = __mt7921_mcu_set_clc(dev, alpha2, env_cap, + phy->clc[i], i); + + /* If no country found, set "00" as default */ + if (ret == -ENOENT) + ret = __mt7921_mcu_set_clc(dev, "00", + ENVIRON_INDOOR, + phy->clc[i], i); + if (ret < 0) + return ret; + } + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index edc0c73f8c01..96dc870fd35e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -6,115 +6,42 @@ #include "../mt76_connac_mcu.h" -struct mt7921_mcu_txd { - __le32 txd[8]; - - __le16 len; - __le16 pq_id; - - u8 cid; - u8 pkt_type; - u8 set_query; /* FW don't care */ - u8 seq; - - u8 uc_d2b0_rev; - u8 ext_cid; - u8 s2d_index; - u8 ext_cid_ack; - - u32 reserved[5]; -} __packed __aligned(4); - -/** - * struct mt7921_uni_txd - mcu command descriptor for firmware v3 - * @txd: hardware descriptor - * @len: total length not including txd - * @cid: command identifier - * @pkt_type: must be 0xa0 (cmd packet by long format) - * @frag_n: fragment number - * @seq: sequence number - * @checksum: 0 mean there is no checksum - * @s2d_index: index for command source and destination - * Definition | value | note - * CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM - * CMD_S2D_IDX_C2N | 0x01 | command from WA to WM - * CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA - * CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM - * - * @option: command option - * BIT[0]: UNI_CMD_OPT_BIT_ACK - * set to 1 to request a fw reply - * if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY - * is set, mcu firmware will send response event EID = 0x01 - * (UNI_EVENT_ID_CMD_RESULT) to the host. - * BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD - * 0: original command - * 1: unified command - * BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY - * 0: QUERY command - * 1: SET command - */ -struct mt7921_uni_txd { - __le32 txd[8]; - - /* DW1 */ - __le16 len; - __le16 cid; - - /* DW2 */ - u8 reserved; - u8 pkt_type; - u8 frag_n; - u8 seq; - - /* DW3 */ - __le16 checksum; - u8 s2d_index; - u8 option; - - /* DW4 */ - u8 reserved2[4]; -} __packed __aligned(4); - -/* event table */ -enum { - MCU_EVENT_REG_ACCESS = 0x05, - MCU_EVENT_LP_INFO = 0x07, - MCU_EVENT_SCAN_DONE = 0x0d, - MCU_EVENT_TX_DONE = 0x0f, - MCU_EVENT_BSS_ABSENCE = 0x11, - MCU_EVENT_BSS_BEACON_LOSS = 0x13, - MCU_EVENT_CH_PRIVILEGE = 0x18, - MCU_EVENT_SCHED_SCAN_DONE = 0x23, - MCU_EVENT_DBG_MSG = 0x27, - MCU_EVENT_TXPWR = 0xd0, - MCU_EVENT_COREDUMP = 0xf0, -}; +struct mt7921_mcu_tx_done_event { + u8 pid; + u8 status; + __le16 seq; + + u8 wlan_idx; + u8 tx_cnt; + __le16 tx_rate; + + u8 flag; + u8 tid; + u8 rsp_rate; + u8 mcs; + + u8 bw; + u8 tx_pwr; + u8 reason; + u8 rsv0[1]; + + __le32 delay; + __le32 timestamp; + __le32 applied_flag; + u8 txs[28]; + + u8 rsv1[32]; +} __packed; /* ext event table */ enum { MCU_EXT_EVENT_RATE_REPORT = 0x87, }; -struct mt7921_mcu_rxd { - __le32 rxd[6]; - - __le16 len; - __le16 pkt_type_id; - - u8 eid; - u8 seq; - __le16 __rsv; - - u8 ext_eid; - u8 __rsv1[2]; - u8 s2d_index; -}; - struct mt7921_mcu_eeprom_info { __le32 addr; __le32 valid; - u8 data[16]; + u8 data[MT7921_EEPROM_BLOCK_SIZE]; } __packed; #define MT_RA_RATE_NSS GENMASK(8, 6) @@ -123,23 +50,6 @@ struct mt7921_mcu_eeprom_info { #define MT_RA_RATE_DCM_EN BIT(4) #define MT_RA_RATE_BW GENMASK(14, 13) -#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) -#define MCU_PKT_ID 0xa0 - -enum { - MCU_Q_QUERY, - MCU_Q_SET, - MCU_Q_RESERVED, - MCU_Q_NA -}; - -enum { - MCU_S2D_H2N, - MCU_S2D_C2N, - MCU_S2D_H2C, - MCU_S2D_H2CN -}; - struct mt7921_mcu_uni_event { u8 cid; u8 pad[3]; @@ -147,109 +57,10 @@ struct mt7921_mcu_uni_event { } __packed; enum { - PATCH_NOT_DL_SEM_FAIL, - PATCH_IS_DL, - PATCH_NOT_DL_SEM_SUCCESS, - PATCH_REL_SEM_SUCCESS -}; - -enum { - FW_STATE_INITIAL, - FW_STATE_FW_DOWNLOAD, - FW_STATE_NORMAL_OPERATION, - FW_STATE_NORMAL_TRX, - FW_STATE_WACPU_RDY = 7 -}; - -enum { - EE_MODE_EFUSE, - EE_MODE_BUFFER, -}; - -enum { - EE_FORMAT_BIN, - EE_FORMAT_WHOLE, - EE_FORMAT_MULTIPLE, -}; - -enum { - MCU_PHY_STATE_TX_RATE, - MCU_PHY_STATE_RX_RATE, - MCU_PHY_STATE_RSSI, - MCU_PHY_STATE_CONTENTION_RX_RATE, - MCU_PHY_STATE_OFDMLQ_CNINFO, -}; - -struct sec_key { - u8 cipher_id; - u8 cipher_len; - u8 key_id; - u8 key_len; - u8 key[32]; -} __packed; - -struct sta_rec_sec { - __le16 tag; - __le16 len; - u8 add; - u8 n_cipher; - u8 rsv[2]; - - struct sec_key key[2]; -} __packed; - -enum mcu_cipher_type { - MCU_CIPHER_NONE = 0, - MCU_CIPHER_WEP40, - MCU_CIPHER_WEP104, - MCU_CIPHER_WEP128, - MCU_CIPHER_TKIP, - MCU_CIPHER_AES_CCMP, - MCU_CIPHER_CCMP_256, - MCU_CIPHER_GCMP, - MCU_CIPHER_GCMP_256, - MCU_CIPHER_WAPI, - MCU_CIPHER_BIP_CMAC_128, -}; - -enum { - CH_SWITCH_NORMAL = 0, - CH_SWITCH_SCAN = 3, - CH_SWITCH_MCC = 4, - CH_SWITCH_DFS = 5, - CH_SWITCH_BACKGROUND_SCAN_START = 6, - CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, - CH_SWITCH_BACKGROUND_SCAN_STOP = 8, - CH_SWITCH_SCAN_BYPASS_DPD = 9 -}; - -enum { - THERMAL_SENSOR_TEMP_QUERY, - THERMAL_SENSOR_MANUAL_CTRL, - THERMAL_SENSOR_INFO_QUERY, - THERMAL_SENSOR_TASK_CTRL, -}; - -enum { MT_EBF = BIT(0), /* explicit beamforming */ MT_IBF = BIT(1) /* implicit beamforming */ }; -#define STA_CAP_WMM BIT(0) -#define STA_CAP_SGI_20 BIT(4) -#define STA_CAP_SGI_40 BIT(5) -#define STA_CAP_TX_STBC BIT(6) -#define STA_CAP_RX_STBC BIT(7) -#define STA_CAP_VHT_SGI_80 BIT(16) -#define STA_CAP_VHT_SGI_160 BIT(17) -#define STA_CAP_VHT_TX_STBC BIT(18) -#define STA_CAP_VHT_RX_STBC BIT(19) -#define STA_CAP_VHT_LDPC BIT(23) -#define STA_CAP_LDPC BIT(24) -#define STA_CAP_HT BIT(26) -#define STA_CAP_VHT BIT(27) -#define STA_CAP_HE BIT(28) - struct mt7921_mcu_reg_event { __le32 reg; __le32 val; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index e9c7c3a19507..eaba114a9c7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -8,9 +8,9 @@ #include <linux/ktime.h> #include "../mt76_connac_mcu.h" #include "regs.h" +#include "acpi_sar.h" #define MT7921_MAX_INTERFACES 4 -#define MT7921_MAX_WMM_SETS 4 #define MT7921_WTBL_SIZE 20 #define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1) #define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \ @@ -30,6 +30,7 @@ #define MT7921_DRV_OWN_RETRY_COUNT 10 #define MT7921_MCU_INIT_RETRY_COUNT 10 +#define MT7921_WFSYS_INIT_RETRY_COUNT 2 #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" @@ -40,6 +41,8 @@ #define MT7921_EEPROM_SIZE 3584 #define MT7921_TOKEN_SIZE 8192 +#define MT7921_EEPROM_BLOCK_SIZE 16 + #define MT7921_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7921_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ @@ -89,11 +92,6 @@ enum mt7921_rxq_id { MT7921_RXQ_MCU_WM = 0, }; -struct mt7921_sta_key_conf { - s8 keyidx; - u8 key[16]; -}; - struct mt7921_sta { struct mt76_wcid wcid; /* must be first */ @@ -104,9 +102,8 @@ struct mt7921_sta { unsigned long last_txs; unsigned long ampdu_state; - struct mt76_sta_stats stats; - struct mt7921_sta_key_conf bip; + struct mt76_connac_sta_key_conf bip; }; DECLARE_EWMA(rssi, 10, 8); @@ -153,13 +150,35 @@ struct mib_stats { u32 tx_amsdu_cnt; }; +enum { + MT7921_CLC_POWER, + MT7921_CLC_CHAN, + MT7921_CLC_MAX_NUM, +}; + +struct mt7921_clc_rule { + u8 alpha2[2]; + u8 type[2]; + __le16 len; + u8 data[]; +} __packed; + +struct mt7921_clc { + __le32 len; + u8 idx; + u8 ver; + u8 nr_country; + u8 type; + u8 rsv[8]; + u8 data[]; +}; + struct mt7921_phy { struct mt76_phy *mt76; struct mt7921_dev *dev; struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; - u32 rxfilter; u64 omac_mask; u16 noise; @@ -176,6 +195,11 @@ struct mt7921_phy { struct sk_buff_head scan_event_list; struct delayed_work scan_work; +#ifdef CONFIG_ACPI + struct mt7921_acpi_sar *acpisar; +#endif + + struct mt7921_clc *clc[MT7921_CLC_MAX_NUM]; }; #define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) @@ -209,11 +233,17 @@ struct mt7921_dev { struct list_head sta_poll_list; spinlock_t sta_poll_lock; + struct work_struct init_work; + u8 fw_debug; struct mt76_connac_pm pm; struct mt76_connac_coredump coredump; const struct mt7921_hif_ops *hif_ops; + + struct work_struct ipv6_ns_work; + /* IPv6 addresses for WoWLAN */ + struct sk_buff_head ipv6_ns_list; }; enum { @@ -246,16 +276,6 @@ struct mt7921_txpwr { } data[TXPWR_MAX_NUM]; }; -enum { - MT_LMAC_AC00, - MT_LMAC_AC01, - MT_LMAC_AC02, - MT_LMAC_AC03, - MT_LMAC_ALTX0 = 0x10, - MT_LMAC_BMC0, - MT_LMAC_BCN0, -}; - static inline struct mt7921_phy * mt7921_hw_phy(struct ieee80211_hw *hw) { @@ -277,14 +297,7 @@ mt7921_hw_dev(struct ieee80211_hw *hw) #define mt7921_mutex_release(dev) \ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) -static inline u8 mt7921_lmac_mapping(struct mt7921_dev *dev, u8 ac) -{ - /* LMAC uses the reverse order of mac80211 AC indexes */ - return 3 - ac; -} - extern const struct ieee80211_ops mt7921_ops; -extern struct pci_driver mt7921_pci_driver; u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); @@ -296,21 +309,18 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force); int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev); void mt7921_dma_cleanup(struct mt7921_dev *dev); int mt7921_run_firmware(struct mt7921_dev *dev); -int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif, - struct mt7921_sta *msta, struct ieee80211_key_conf *key, - enum set_key_cmd cmd); +int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool enable); int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state); int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd); int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif); int mt7921_mcu_set_eeprom(struct mt7921_dev *dev); -int mt7921_mcu_get_eeprom(struct mt7921_dev *dev, u32 offset); int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl); void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb); -void mt7921_mcu_exit(struct mt7921_dev *dev); static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask) { @@ -361,23 +371,20 @@ static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev) return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); } -static inline void mt7921_mcu_tx_cleanup(struct mt7921_dev *dev) -{ - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false); -} - -static inline void mt7921_skb_add_sdio_hdr(struct sk_buff *skb, - enum mt7921_sdio_pkt_type type) +static inline void +mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, + int type) { - u32 hdr; + u32 hdr, len; - hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, skb->len + sizeof(hdr)) | + len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr); + hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) | FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type); put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr))); } +void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt7921_dev *dev); bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); void mt7921_mac_reset_counters(struct mt7921_phy *phy); @@ -398,9 +405,8 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info); void mt7921_tx_worker(struct mt76_worker *w); -void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); -int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc); void mt7921_tx_token_put(struct mt7921_dev *dev); +bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); @@ -424,7 +430,6 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev); void mt7921_pm_wake_work(struct work_struct *work); void mt7921_pm_power_save_work(struct work_struct *work); -bool mt7921_wait_for_mcu_init(struct mt7921_dev *dev); void mt7921_coredump_work(struct work_struct *work); int mt7921_wfsys_reset(struct mt7921_dev *dev); int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr); @@ -432,35 +437,75 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, struct netlink_callback *cb, void *data, int len); -void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_key_conf *key, int pid, - bool beacon); -void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi); +void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, bool clear_status, + struct list_head *free_list); void mt7921_mac_sta_poll(struct mt7921_dev *dev); -int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, int *wait_seq); int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); -int mt7921_mcu_restart(struct mt76_dev *dev); -void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb); +int mt7921e_driver_own(struct mt7921_dev *dev); int mt7921e_mac_reset(struct mt7921_dev *dev); int mt7921e_mcu_init(struct mt7921_dev *dev); int mt7921s_wfsys_reset(struct mt7921_dev *dev); int mt7921s_mac_reset(struct mt7921_dev *dev); int mt7921s_init_reset(struct mt7921_dev *dev); +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_init(struct mt7921_dev *dev); int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - enum mt76_txq_id qid, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, - struct mt76_tx_info *tx_info); -void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); -bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update); +void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); +void mt7921_set_runtime_pm(struct mt7921_dev *dev); +void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif); +void mt7921_set_ipv6_ns_work(struct work_struct *work); + +int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, + bool enable); + +int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); +void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e); +bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); + +/* usb */ +#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) +#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) + +int mt7921u_mcu_power_on(struct mt7921_dev *dev); +int mt7921u_wfsys_reset(struct mt7921_dev *dev); +int mt7921u_dma_init(struct mt7921_dev *dev, bool resume); +int mt7921u_init_reset(struct mt7921_dev *dev); +int mt7921u_mac_reset(struct mt7921_dev *dev); +int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable); +#ifdef CONFIG_ACPI +int mt7921_init_acpi_sar(struct mt7921_dev *dev); +int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default); +#else +static inline int +mt7921_init_acpi_sar(struct mt7921_dev *dev) +{ + return 0; +} + +static inline int +mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) +{ + return 0; +} +#endif +int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar); + +int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, + enum environment_cap env_cap); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 305b63fa1a8a..8a53d8f286db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -15,6 +15,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961) }, { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7922) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616) }, { }, }; @@ -103,6 +105,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) int i; struct mt76_connac_pm *pm = &dev->pm; + cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); @@ -113,10 +116,110 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) mt7921_mcu_drv_pmctrl(dev); mt7921_dma_cleanup(dev); mt7921_wfsys_reset(dev); - mt7921_mcu_exit(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); tasklet_disable(&dev->irq_tasklet); - mt76_free_device(&dev->mt76); +} + +static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) +{ + static const struct mt76_connac_reg_map fixed_map[] = { + { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x820ed000, 0x24800, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820e4000, 0x21000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e7000, 0x21e00, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820eb000, 0x24200, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820e2000, 0x20800, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x20c00, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e5000, 0x21400, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */ + { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */ + { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */ + { 0x54000000, 0x02000, 0x01000 }, /* WFDMA PCIE0 MCU DMA0 */ + { 0x55000000, 0x03000, 0x01000 }, /* WFDMA PCIE0 MCU DMA1 */ + { 0x58000000, 0x06000, 0x01000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + { 0x59000000, 0x07000, 0x01000 }, /* WFDMA PCIE1 MCU DMA1 */ + { 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */ + { 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */ + { 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */ + { 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */ + { 0x820c0000, 0x08000, 0x04000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x0c000, 0x02000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x0e000, 0x01000 }, /* WF_UMAC_TOP (PP) */ + { 0x820cd000, 0x0f000, 0x01000 }, /* WF_MDP_TOP */ + { 0x74030000, 0x10000, 0x10000 }, /* PCIE_MAC_IREG */ + { 0x820ce000, 0x21c00, 0x00200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820cf000, 0x22000, 0x01000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820e0000, 0x20000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x20400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e9000, 0x23400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x24000, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820ec000, 0x24600, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820f0000, 0xa0000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0xa0600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0xa0800, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0xa0c00, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0xa1000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0xa1400, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0xa1e00, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0xa3400, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0xa4000, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0xa4200, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0xa4600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0xa4800, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + }; + int i; + + if (addr < 0x100000) + return addr; + + for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { + u32 ofs; + + if (addr < fixed_map[i].phys) + continue; + + ofs = addr - fixed_map[i].phys; + if (ofs > fixed_map[i].size) + continue; + + return fixed_map[i].maps + ofs; + } + + if ((addr >= 0x18000000 && addr < 0x18c00000) || + (addr >= 0x70000000 && addr < 0x78000000) || + (addr >= 0x7c000000 && addr < 0x7c400000)) + return mt7921_reg_map_l1(dev, addr); + + dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n", + addr); + + return 0; +} + +static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + u32 addr = __mt7921_reg_addr(dev, offset); + + return dev->bus_ops->rr(mdev, addr); +} + +static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + u32 addr = __mt7921_reg_addr(dev, offset); + + dev->bus_ops->wr(mdev, addr, val); +} + +static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + u32 addr = __mt7921_reg_addr(dev, offset); + + return dev->bus_ops->rmw(mdev, addr, mask, val); } static int mt7921_pci_probe(struct pci_dev *pdev, @@ -124,15 +227,16 @@ static int mt7921_pci_probe(struct pci_dev *pdev, { static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7921_txp_common), + .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp), .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, .token_size = MT7921_TOKEN_SIZE, .tx_prepare_skb = mt7921e_tx_prepare_skb, - .tx_complete_skb = mt7921e_tx_complete_skb, - .rx_skb = mt7921e_queue_rx_skb, + .tx_complete_skb = mt76_connac_tx_complete_skb, + .rx_check = mt7921_rx_check, + .rx_skb = mt7921_queue_rx_skb, .rx_poll_complete = mt7921_rx_poll_complete, .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, @@ -140,7 +244,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .sta_remove = mt7921_mac_sta_remove, .update_survey = mt7921_update_channel, }; - static const struct mt7921_hif_ops mt7921_pcie_ops = { .init_reset = mt7921e_init_reset, .reset = mt7921e_mac_reset, @@ -149,6 +252,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .fw_own = mt7921e_mcu_fw_pmctrl, }; + struct mt76_bus_ops *bus_ops; struct mt7921_dev *dev; struct mt76_dev *mdev; int ret; @@ -181,14 +285,37 @@ static int mt7921_pci_probe(struct pci_dev *pdev, goto err_free_pci_vec; } + pci_set_drvdata(pdev, mdev); + dev = container_of(mdev, struct mt7921_dev, mt76); dev->hif_ops = &mt7921_pcie_ops; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + dev->bus_ops = dev->mt76.bus; + bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), + GFP_KERNEL); + if (!bus_ops) { + ret = -ENOMEM; + goto err_free_dev; + } + + bus_ops->rr = mt7921_rr; + bus_ops->wr = mt7921_wr; + bus_ops->rmw = mt7921_rmw; + dev->mt76.bus = bus_ops; + + ret = __mt7921e_mcu_drv_pmctrl(dev); + if (ret) + goto err_free_dev; + mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) | (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); - dev_err(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); @@ -226,19 +353,20 @@ static void mt7921_pci_remove(struct pci_dev *pdev) mt7921e_unregister_device(dev); devm_free_irq(&pdev->dev, pdev->irq, dev); + mt76_free_device(&dev->mt76); pci_free_irq_vectors(pdev); } -#ifdef CONFIG_PM -static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int mt7921_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; - bool hif_suspend; int i, err; pm->suspended = true; + flush_work(&dev->reset_work); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); @@ -246,12 +374,9 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (err < 0) goto restore_suspend; - hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state); - if (hif_suspend) { - err = mt76_connac_mcu_set_hif_suspend(mdev, true); - if (err) - goto restore_suspend; - } + err = mt76_connac_mcu_set_hif_suspend(mdev, true); + if (err) + goto restore_suspend; /* always enable deep sleep during suspend to reduce * power consumption @@ -265,8 +390,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) napi_disable(&mdev->napi[i]); } - pci_enable_wake(pdev, pci_choose_state(pdev, state), true); - /* wait until dma is idle */ mt76_poll(dev, MT_WFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | @@ -286,11 +409,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (err) goto restore_napi; - pci_save_state(pdev); - err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); - if (err) - goto restore_napi; - return 0; restore_napi: @@ -302,32 +420,28 @@ restore_napi: if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(&dev->mt76, false); - if (hif_suspend) - mt76_connac_mcu_set_hif_suspend(mdev, false); + mt76_connac_mcu_set_hif_suspend(mdev, false); restore_suspend: pm->suspended = false; + if (err < 0) + mt7921_reset(&dev->mt76); + return err; } -static int mt7921_pci_resume(struct pci_dev *pdev) +static int mt7921_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; int i, err; - pm->suspended = false; - err = pci_set_power_state(pdev, PCI_D0); - if (err) - return err; - - pci_restore_state(pdev); - err = mt7921_mcu_drv_pmctrl(dev); if (err < 0) - return err; + goto failed; mt7921_wpdma_reinit_cond(dev); @@ -356,22 +470,24 @@ static int mt7921_pci_resume(struct pci_dev *pdev) if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(&dev->mt76, false); - if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state)) - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + err = mt76_connac_mcu_set_hif_suspend(mdev, false); +failed: + pm->suspended = false; + + if (err < 0) + mt7921_reset(&dev->mt76); return err; } -#endif /* CONFIG_PM */ -struct pci_driver mt7921_pci_driver = { +static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume); + +static struct pci_driver mt7921_pci_driver = { .name = KBUILD_MODNAME, .id_table = mt7921_pci_device_table, .probe = mt7921_pci_probe, .remove = mt7921_pci_remove, -#ifdef CONFIG_PM - .suspend = mt7921_pci_suspend, - .resume = mt7921_pci_resume, -#endif /* CONFIG_PM */ + .driver.pm = pm_sleep_ptr(&mt7921_pm_ops), }; module_pci_driver(mt7921_pci_driver); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index f9547d27356e..8dd60408b117 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -5,37 +5,6 @@ #include "../dma.h" #include "mac.h" -static void -mt7921_write_hw_txp(struct mt7921_dev *dev, struct mt76_tx_info *tx_info, - void *txp_ptr, u32 id) -{ - struct mt7921_hw_txp *txp = txp_ptr; - struct mt7921_txp_ptr *ptr = &txp->ptr[0]; - int i, nbuf = tx_info->nbuf - 1; - - tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); - tx_info->nbuf = 1; - - txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); - - for (i = 0; i < nbuf; i++) { - u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK; - u32 addr = tx_info->buf[i + 1].addr; - - if (i == nbuf - 1) - len |= MT_TXD_LEN_LAST; - - if (i & 1) { - ptr->buf1 = cpu_to_le32(addr); - ptr->len1 = cpu_to_le16(len); - ptr++; - } else { - ptr->buf0 = cpu_to_le32(addr); - ptr->len0 = cpu_to_le16(len); - } - } -} - int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, @@ -44,8 +13,8 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; + struct mt76_connac_hw_txp *txp; struct mt76_txwi_cache *t; - struct mt7921_txp_common *txp; int id, pid; u8 *txwi = (u8 *)txwi_ptr; @@ -72,198 +41,18 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, } pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - mt7921_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, - pid, false); + mt76_connac2_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key, + pid, qid, 0); - txp = (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE); - memset(txp, 0, sizeof(struct mt7921_txp_common)); - mt7921_write_hw_txp(dev, tx_info, txp, id); + txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE); + memset(txp, 0, sizeof(struct mt76_connac_hw_txp)); + mt76_connac_write_hw_txp(mdev, tx_info, txp, id); tx_info->skb = DMA_DUMMY_DATA; return 0; } -static void -mt7921_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - struct mt7921_txp_common *txp; - int i; - - txp = mt7921_txwi_to_txp(dev, t); - - for (i = 0; i < ARRAY_SIZE(txp->hw.ptr); i++) { - struct mt7921_txp_ptr *ptr = &txp->hw.ptr[i]; - bool last; - u16 len; - - len = le16_to_cpu(ptr->len0); - last = len & MT_TXD_LEN_LAST; - len &= MT_TXD_LEN_MASK; - dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, - DMA_TO_DEVICE); - if (last) - break; - - len = le16_to_cpu(ptr->len1); - last = len & MT_TXD_LEN_LAST; - len &= MT_TXD_LEN_MASK; - dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, - DMA_TO_DEVICE); - if (last) - break; - } -} - -static void -mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, - struct list_head *free_list) -{ - struct mt76_dev *mdev = &dev->mt76; - __le32 *txwi; - u16 wcid_idx; - - mt7921_txp_skb_unmap(mdev, t); - if (!t->skb) - goto out; - - txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); - if (sta) { - struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; - - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); - - wcid_idx = wcid->idx; - } else { - wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); - } - - __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); - -out: - t->skb = NULL; - mt76_put_txwi(mdev, t); -} - -static void -mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb) -{ - struct mt7921_tx_free *free = (struct mt7921_tx_free *)skb->data; - struct mt76_dev *mdev = &dev->mt76; - struct mt76_txwi_cache *txwi; - struct ieee80211_sta *sta = NULL; - LIST_HEAD(free_list); - struct sk_buff *tmp; - bool wake = false; - u8 i, count; - - /* clean DMA queues and unmap buffers first */ - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); - - /* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, - * to the time ack is received or dropped by hw (air + hw queue time). - * Should avoid accessing WTBL to get Tx airtime, and use it instead. - */ - count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl)); - for (i = 0; i < count; i++) { - u32 msdu, info = le32_to_cpu(free->info[i]); - u8 stat; - - /* 1'b1: new wcid pair. - * 1'b0: msdu_id with the same 'wcid pair' as above. - */ - if (info & MT_TX_FREE_PAIR) { - struct mt7921_sta *msta; - struct mt76_wcid *wcid; - u16 idx; - - count++; - idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); - wcid = rcu_dereference(dev->mt76.wcid[idx]); - sta = wcid_to_sta(wcid); - if (!sta) - continue; - - msta = container_of(wcid, struct mt7921_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); - continue; - } - - msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); - stat = FIELD_GET(MT_TX_FREE_STATUS, info); - - txwi = mt76_token_release(mdev, msdu, &wake); - if (!txwi) - continue; - - mt7921_txwi_free(dev, txwi, sta, stat, &free_list); - } - - if (wake) - mt76_set_tx_blocked(&dev->mt76, false); - - napi_consume_skb(skb, 1); - - list_for_each_entry_safe(skb, tmp, &free_list, list) { - skb_list_del_init(skb); - napi_consume_skb(skb, 1); - } - - rcu_read_lock(); - mt7921_mac_sta_poll(dev); - rcu_read_unlock(); - - mt76_worker_schedule(&dev->mt76.tx_worker); -} - -void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - __le32 *rxd = (__le32 *)skb->data; - enum rx_pkt_type type; - - type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); - - switch (type) { - case PKT_TYPE_TXRX_NOTIFY: - mt7921_mac_tx_free(dev, skb); - break; - default: - mt7921_queue_rx_skb(mdev, q, skb); - break; - } -} - -void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - if (!e->txwi) { - dev_kfree_skb_any(e->skb); - return; - } - - /* error path */ - if (e->skb == DMA_DUMMY_DATA) { - struct mt76_txwi_cache *t; - struct mt7921_txp_common *txp; - u16 token; - - txp = mt7921_txwi_to_txp(mdev, e->txwi); - token = le16_to_cpu(txp->hw.msdu_id[0]) & ~MT_MSDU_ID_VALID; - t = mt76_token_put(mdev, token); - e->skb = t ? t->skb : NULL; - } - - if (e->skb) - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - void mt7921_tx_token_put(struct mt7921_dev *dev) { struct mt76_txwi_cache *txwi; @@ -314,6 +103,7 @@ int mt7921e_mac_reset(struct mt7921_dev *dev) } local_bh_enable(); + dev->fw_assert = false; clear_bit(MT76_MCU_RESET, &dev->mphy.state); mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, @@ -321,6 +111,10 @@ int mt7921e_mac_reset(struct mt7921_dev *dev) MT_INT_MCU_CMD); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + err = mt7921e_driver_own(dev); + if (err) + goto out; + err = mt7921_run_firmware(dev); if (err) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c index 583a89a34734..86340d3205c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c @@ -4,7 +4,7 @@ #include "mt7921.h" #include "mcu.h" -static int mt7921e_driver_own(struct mt7921_dev *dev) +int mt7921e_driver_own(struct mt7921_dev *dev) { u32 reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); @@ -26,11 +26,13 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, enum mt76_mcuq_id txq = MT_MCUQ_WM; int ret; - ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq); + ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq); if (ret) return ret; - if (cmd == MCU_CMD_FW_SCATTER) + mdev->mcu.timeout = 3 * HZ; + + if (cmd == MCU_CMD(FW_SCATTER)) txq = MT_MCUQ_FWDL; return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); @@ -39,10 +41,10 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int mt7921e_mcu_init(struct mt7921_dev *dev) { static const struct mt76_mcu_ops mt7921_mcu_ops = { - .headroom = sizeof(struct mt7921_mcu_txd), + .headroom = sizeof(struct mt76_connac2_mcu_txd), .mcu_skb_send_msg = mt7921_mcu_send_message, .mcu_parse_response = mt7921_mcu_parse_response, - .mcu_restart = mt7921_mcu_restart, + .mcu_restart = mt76_connac_mcu_restart, }; int err; @@ -52,6 +54,8 @@ int mt7921e_mcu_init(struct mt7921_dev *dev) if (err) return err; + mt76_rmw_field(dev, MT_PCIE_MAC_PM, MT_PCIE_MAC_PM_L0S_DIS, 1); + err = mt7921_run_firmware(dev); mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); @@ -59,10 +63,8 @@ int mt7921e_mcu_init(struct mt7921_dev *dev) return err; } -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) +int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) { - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; int i, err = 0; for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { @@ -75,9 +77,21 @@ int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) if (i == MT7921_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "driver own failed\n"); err = -EIO; - goto out; } + return err; +} + +int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err; + + err = __mt7921e_mcu_drv_pmctrl(dev); + if (err < 0) + goto out; + mt7921_wpdma_reinit_cond(dev); clear_bit(MT76_STATE_PM, &mphy->state); @@ -92,7 +106,7 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; - int i, err = 0; + int i; for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN); @@ -104,12 +118,12 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev) if (i == MT7921_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "firmware own failed\n"); clear_bit(MT76_STATE_PM, &mphy->state); - err = -EIO; + return -EIO; } pm->stats.last_doze_event = jiffies; pm->stats.awake_time += pm->stats.last_doze_event - pm->stats.last_wake_event; - return err; + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index cbd38122c510..c65582acfa55 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -17,13 +17,12 @@ #define MT_PLE_BASE 0x820c0000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) -#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0) -#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4) -#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8) -#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc) +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) +#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) +#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) +#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) -#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \ - ((n) << 2)) +#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) #define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) #define MT_MDP_BASE 0x820cd000 @@ -354,6 +353,7 @@ #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) #define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) #define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) +#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) #define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) #define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) @@ -378,6 +378,9 @@ #define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) #define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) +#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) +#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) + #define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) #define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) #define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) @@ -426,6 +429,10 @@ #define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) #define MT_WFDMA_NEED_REINIT BIT(1) +#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) +#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) +#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) + #define MT_HW_BOUND 0x70010020 #define MT_HW_CHIPID 0x70010200 #define MT_HW_REV 0x70010204 @@ -433,13 +440,17 @@ #define MT_PCIE_MAC_BASE 0x10000 #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) +#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194) +#define MT_PCIE_MAC_PM_L0S_DIS BIT(8) -#define MT_DMA_SHDL(ofs) (0xd6000 + (ofs)) +#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) #define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) #define MT_DMASHDL_DMASHDL_BYPASS BIT(28) #define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) #define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) +#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) #define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) +#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) #define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) #define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) #define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) @@ -454,6 +465,46 @@ #define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) +#define MT_WFDMA_HOST_CONFIG 0x7c027030 +#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) + +#define MT_UMAC(ofs) (0x74000000 + (ofs)) +#define MT_UDMA_TX_QSEL MT_UMAC(0x008) +#define MT_FW_DL_EN BIT(3) + +#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) +#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) +#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) + +#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) +#define MT_WL_RX_AGG_TO GENMASK(7, 0) +#define MT_WL_RX_AGG_LMT GENMASK(15, 8) +#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) +#define MT_WL_TX_DPH_CHK_EN BIT(17) +#define MT_WL_RX_MPSZ_PAD0 BIT(18) +#define MT_WL_RX_FLUSH BIT(19) +#define MT_TICK_1US_EN BIT(20) +#define MT_WL_RX_AGG_EN BIT(21) +#define MT_WL_RX_EN BIT(22) +#define MT_WL_TX_EN BIT(23) +#define MT_WL_RX_BUSY BIT(30) +#define MT_WL_TX_BUSY BIT(31) + +#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) +#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) +#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) + +#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) +#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) + +#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) +#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) +#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) +#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) + +#define MT_CONN_STATUS 0x7c053c10 +#define MT_WIFI_PATCH_DL_STATE BIT(0) + #define MT_CONN_ON_LPCTL 0x7c060010 #define PCIE_LPCR_HOST_OWN_SYNC BIT(2) #define PCIE_LPCR_HOST_CLR_OWN BIT(1) @@ -464,6 +515,12 @@ #define WFSYS_SW_INIT_DONE BIT(4) #define MT_CONN_ON_MISC 0x7c0600f0 +#define MT_TOP_MISC2_FW_PWR_ON BIT(0) #define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) +#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) +#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) +#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) +#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index ddf0eeb8b688..3b25a06fd946 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -41,13 +41,14 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; + cancel_work_sync(&dev->init_work); mt76_unregister_device(&dev->mt76); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); mt76s_deinit(&dev->mt76); mt7921s_wfsys_reset(dev); - mt7921_mcu_exit(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); mt76_free_device(&dev->mt76); } @@ -58,10 +59,17 @@ static int mt7921s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr) struct mt7921_sdio_intr *irq_data = sdio->intr_data; int i, err; + sdio_claim_host(sdio->func); err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data)); + sdio_release_host(sdio->func); + if (err < 0) return err; + if (irq_data->rx.num[0] > 16 || + irq_data->rx.num[1] > 128) + return -EINVAL; + intr->isr = irq_data->isr; intr->rec_mb = irq_data->rec_mb; intr->tx.wtqcr = irq_data->tx.wtqcr; @@ -84,10 +92,11 @@ static int mt7921s_probe(struct sdio_func *func, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, - .tx_prepare_skb = mt7921s_tx_prepare_skb, - .tx_complete_skb = mt7921s_tx_complete_skb, - .tx_status_data = mt7921s_tx_status_data, + .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, + .tx_complete_skb = mt7921_usb_sdio_tx_complete_skb, + .tx_status_data = mt7921_usb_sdio_tx_status_data, .rx_skb = mt7921_queue_rx_skb, + .rx_check = mt7921_rx_check, .sta_ps = mt7921_sta_ps, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, @@ -114,7 +123,7 @@ static int mt7921s_probe(struct sdio_func *func, struct mt7921_dev *dev; struct mt76_dev *mdev; - int ret, i; + int ret; mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops, &drv_ops); @@ -147,16 +156,6 @@ static int mt7921s_probe(struct sdio_func *func, goto error; } - for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) { - mdev->sdio.xmit_buf[i] = devm_kmalloc(mdev->dev, - MT76S_XMIT_BUF_SZ, - GFP_KERNEL); - if (!mdev->sdio.xmit_buf[i]) { - ret = -ENOMEM; - goto error; - } - } - ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MAIN); if (ret) goto error; @@ -196,17 +195,18 @@ static void mt7921s_remove(struct sdio_func *func) mt7921s_unregister_device(dev); } -#ifdef CONFIG_PM static int mt7921s_suspend(struct device *__dev) { struct sdio_func *func = dev_to_sdio_func(__dev); struct mt7921_dev *dev = sdio_get_drvdata(func); struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; - bool hif_suspend; int err; pm->suspended = true; + set_bit(MT76_STATE_SUSPEND, &mdev->phy.state); + + flush_work(&dev->reset_work); cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); @@ -214,13 +214,6 @@ static int mt7921s_suspend(struct device *__dev) if (err < 0) goto restore_suspend; - hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state); - if (hif_suspend) { - err = mt76_connac_mcu_set_hif_suspend(mdev, true); - if (err) - goto restore_suspend; - } - /* always enable deep sleep during suspend to reduce * power consumption */ @@ -228,37 +221,50 @@ static int mt7921s_suspend(struct device *__dev) mt76_txq_schedule_all(&dev->mphy); mt76_worker_disable(&mdev->tx_worker); - mt76_worker_disable(&mdev->sdio.txrx_worker); mt76_worker_disable(&mdev->sdio.status_worker); - mt76_worker_disable(&mdev->sdio.net_worker); cancel_work_sync(&mdev->sdio.stat_work); clear_bit(MT76_READING_STATS, &dev->mphy.state); - mt76_tx_status_check(mdev, true); - err = mt7921_mcu_fw_pmctrl(dev); + mt76_worker_schedule(&mdev->sdio.txrx_worker); + wait_event_timeout(dev->mt76.sdio.wait, + mt76s_txqs_empty(&dev->mt76), 5 * HZ); + + /* It is supposed that SDIO bus is idle at the point */ + err = mt76_connac_mcu_set_hif_suspend(mdev, true); if (err) goto restore_worker; + mt76_worker_disable(&mdev->sdio.txrx_worker); + mt76_worker_disable(&mdev->sdio.net_worker); + + err = mt7921_mcu_fw_pmctrl(dev); + if (err) + goto restore_txrx_worker; + sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); return 0; +restore_txrx_worker: + mt76_worker_enable(&mdev->sdio.net_worker); + mt76_worker_enable(&mdev->sdio.txrx_worker); + mt76_connac_mcu_set_hif_suspend(mdev, false); + restore_worker: mt76_worker_enable(&mdev->tx_worker); - mt76_worker_enable(&mdev->sdio.txrx_worker); mt76_worker_enable(&mdev->sdio.status_worker); - mt76_worker_enable(&mdev->sdio.net_worker); if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(mdev, false); - if (hif_suspend) - mt76_connac_mcu_set_hif_suspend(mdev, false); - restore_suspend: + clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state); pm->suspended = false; + if (err < 0) + mt7921_reset(&dev->mt76); + return err; } @@ -270,11 +276,11 @@ static int mt7921s_resume(struct device *__dev) struct mt76_dev *mdev = &dev->mt76; int err; - pm->suspended = false; + clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state); err = mt7921_mcu_drv_pmctrl(dev); if (err < 0) - return err; + goto failed; mt76_worker_enable(&mdev->tx_worker); mt76_worker_enable(&mdev->sdio.txrx_worker); @@ -285,32 +291,28 @@ static int mt7921s_resume(struct device *__dev) if (!pm->ds_enable) mt76_connac_mcu_set_deep_sleep(mdev, false); - if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state)) - err = mt76_connac_mcu_set_hif_suspend(mdev, false); + err = mt76_connac_mcu_set_hif_suspend(mdev, false); +failed: + pm->suspended = false; + + if (err < 0) + mt7921_reset(&dev->mt76); return err; } -static const struct dev_pm_ops mt7921s_pm_ops = { - .suspend = mt7921s_suspend, - .resume = mt7921s_resume, -}; -#endif - MODULE_DEVICE_TABLE(sdio, mt7921s_table); MODULE_FIRMWARE(MT7921_FIRMWARE_WM); MODULE_FIRMWARE(MT7921_ROM_PATCH); +static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume); + static struct sdio_driver mt7921s_driver = { .name = KBUILD_MODNAME, .probe = mt7921s_probe, .remove = mt7921s_remove, .id_table = mt7921s_table, -#ifdef CONFIG_PM - .drv = { - .pm = &mt7921s_pm_ops, - } -#endif + .drv.pm = pm_sleep_ptr(&mt7921s_pm_ops), }; module_sdio_driver(mt7921s_driver); MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index bdec508b6b9f..1b3adb3d91e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -60,7 +60,11 @@ int mt7921s_wfsys_reset(struct mt7921_dev *dev) sdio_release_host(sdio->func); + clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + /* activate mt7921s again */ + mt7921s_mcu_drv_pmctrl(dev); + mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE); mt7921s_mcu_fw_pmctrl(dev); mt7921s_mcu_drv_pmctrl(dev); @@ -81,7 +85,6 @@ int mt7921s_init_reset(struct mt7921_dev *dev) mt7921s_wfsys_reset(dev); mt76_worker_enable(&dev->mt76.sdio.txrx_worker); - clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); clear_bit(MT76_MCU_RESET, &dev->mphy.state); mt7921s_enable_irq(&dev->mt76); @@ -114,7 +117,6 @@ int mt7921s_mac_reset(struct mt7921_dev *dev) mt76_worker_enable(&dev->mt76.sdio.net_worker); dev->fw_assert = false; - clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); clear_bit(MT76_MCU_RESET, &dev->mphy.state); mt7921s_enable_irq(&dev->mt76); @@ -138,86 +140,3 @@ out: return err; } - -static void -mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, - enum mt76_txq_id qid, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key, int pid, - struct sk_buff *skb) -{ - __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); - - memset(txwi, 0, MT_SDIO_TXD_SIZE); - mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false); - skb_push(skb, MT_SDIO_TXD_SIZE); -} - -int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - enum mt76_txq_id qid, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, - struct mt76_tx_info *tx_info) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); - struct ieee80211_key_conf *key = info->control.hw_key; - struct sk_buff *skb = tx_info->skb; - int err, pad, pktid; - - if (unlikely(tx_info->skb->len <= ETH_HLEN)) - return -EINVAL; - - if (!wcid) - wcid = &dev->mt76.global_wcid; - - if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - - if (time_after(jiffies, msta->last_txs + HZ / 4)) { - info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->last_txs = jiffies; - } - } - - pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); - mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb); - - mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA); - pad = round_up(skb->len, 4) - skb->len; - - err = mt76_skb_adjust_pad(skb, pad); - if (err) - /* Release pktid in case of error. */ - idr_remove(&wcid->pktid, pktid); - - return err; -} - -void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); - unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - struct ieee80211_sta *sta; - struct mt76_wcid *wcid; - u16 idx; - - idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1])); - wcid = rcu_dereference(mdev->wcid[idx]); - sta = wcid_to_sta(wcid); - - if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); - - skb_pull(e->skb, headroom); - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - -bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - - mt7921_mutex_acquire(dev); - mt7921_mac_sta_poll(dev); - mt7921_mutex_release(dev); - - return 0; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 437cddad9a90..5c1489766d9f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -29,14 +29,16 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, if (dev->fw_assert) return -EBUSY; - ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq); + ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq); if (ret) return ret; - if (cmd == MCU_CMD_FW_SCATTER) + mdev->mcu.timeout = 3 * HZ; + + if (cmd == MCU_CMD(FW_SCATTER)) type = MT7921_SDIO_FWDL; - mt7921_skb_add_sdio_hdr(skb, type); + mt7921_skb_add_usb_sdio_hdr(dev, skb, type); pad = round_up(skb->len, 4) - skb->len; __skb_put_zero(skb, pad); @@ -49,10 +51,31 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return ret; } +static u32 mt7921s_read_rm3r(struct mt7921_dev *dev) +{ + struct mt76_sdio *sdio = &dev->mt76.sdio; + + return sdio_readl(sdio->func, MCR_D2HRM3R, NULL); +} + +static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) +{ + struct mt76_sdio *sdio = &dev->mt76.sdio; + u32 val; + + val = sdio_readl(sdio->func, MCR_D2HRM3R, NULL); + if (val) + sdio_writel(sdio->func, H2D_SW_INT_CLEAR_MAILBOX_ACK, + MCR_WSICR, NULL); + + return val; +} + int mt7921s_mcu_init(struct mt7921_dev *dev) { static const struct mt76_mcu_ops mt7921s_mcu_ops = { - .headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd), + .headroom = MT_SDIO_HDR_SIZE + + sizeof(struct mt76_connac2_mcu_txd), .tailroom = MT_SDIO_TAIL_SIZE, .mcu_skb_send_msg = mt7921s_mcu_send_message, .mcu_parse_response = mt7921_mcu_parse_response, @@ -79,8 +102,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; - int err = 0; u32 status; + int err; sdio_claim_host(func); @@ -88,12 +111,17 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000); + + if (!err && test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) + err = readx_poll_timeout(mt7921s_read_rm3r, dev, status, + status & D2HRM3R_IS_DRIVER_OWN, + 2000, 1000000); + sdio_release_host(func); if (err < 0) { dev_err(dev->mt76.dev, "driver own failed\n"); - err = -EIO; - goto out; + return -EIO; } clear_bit(MT76_STATE_PM, &mphy->state); @@ -101,8 +129,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) pm->stats.last_wake_event = jiffies; pm->stats.doze_time += pm->stats.last_wake_event - pm->stats.last_doze_event; -out: - return err; + + return 0; } int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) @@ -110,26 +138,38 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; - int err = 0; u32 status; + int err; sdio_claim_host(func); + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { + err = readx_poll_timeout(mt7921s_clear_rm3r_drv_own, + dev, status, + !(status & D2HRM3R_IS_DRIVER_OWN), + 2000, 1000000); + if (err < 0) { + dev_err(dev->mt76.dev, "mailbox ACK not cleared\n"); + goto out; + } + } + sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL); err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000); +out: sdio_release_host(func); if (err < 0) { dev_err(dev->mt76.dev, "firmware own failed\n"); clear_bit(MT76_STATE_PM, &mphy->state); - err = -EIO; + return -EIO; } pm->stats.last_doze_event = jiffies; pm->stats.awake_time += pm->stats.last_doze_event - pm->stats.last_wake_event; - return err; + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c index 8bd43879dd6f..bdec8684ce94 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c @@ -66,7 +66,7 @@ mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req) if (!mt76_testmode_enabled(phy)) goto out; - ret = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TEST_CTRL, &cmd, + ret = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(TEST_CTRL), &cmd, sizeof(cmd), false); if (ret) goto out; @@ -95,7 +95,7 @@ mt7921_tm_query(struct mt7921_dev *dev, struct mt7921_tm_cmd *req, struct sk_buff *skb; int ret; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CMD_TEST_CTRL, + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CE_CMD(TEST_CTRL), &cmd, sizeof(cmd), true, &skb); if (ret) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c new file mode 100644 index 000000000000..29c0ee330dbe --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. + * + * Author: Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> + +#include "mt7921.h" +#include "mcu.h" +#include "mac.h" + +static const struct usb_device_id mt7921u_device_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff) }, + { }, +}; + +static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + +static void mt7921u_copy(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + +int mt7921u_mcu_power_on(struct mt7921_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, + MT_TOP_MISC2_FW_PWR_ON, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return ret; +} + +static int +mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *seq) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + u32 pad, ep; + int ret; + + ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq); + if (ret) + return ret; + + mdev->mcu.timeout = 3 * HZ; + + if (cmd != MCU_CMD(FW_SCATTER)) + ep = MT_EP_OUT_INBAND_CMD; + else + ep = MT_EP_OUT_AC_BE; + + mt7921_skb_add_usb_sdio_hdr(dev, skb, 0); + pad = round_up(skb->len, 4) + 4 - skb->len; + __skb_put_zero(skb, pad); + + ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL, + 1000, ep); + dev_kfree_skb(skb); + + return ret; +} + +static int mt7921u_mcu_init(struct mt7921_dev *dev) +{ + static const struct mt76_mcu_ops mcu_ops = { + .headroom = MT_SDIO_HDR_SIZE + + sizeof(struct mt76_connac2_mcu_txd), + .tailroom = MT_USB_TAIL_SIZE, + .mcu_skb_send_msg = mt7921u_mcu_send_message, + .mcu_parse_response = mt7921_mcu_parse_response, + .mcu_restart = mt76_connac_mcu_restart, + }; + int ret; + + dev->mt76.mcu_ops = &mcu_ops; + + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + ret = mt7921_run_firmware(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + return 0; +} + +static void mt7921u_stop(struct ieee80211_hw *hw) +{ + struct mt7921_dev *dev = mt7921_hw_dev(hw); + + mt76u_stop_tx(&dev->mt76); + mt7921_stop(hw); +} + +static void mt7921u_cleanup(struct mt7921_dev *dev) +{ + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + mt7921u_wfsys_reset(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); + mt76u_queues_deinit(&dev->mt76); +} + +static int mt7921u_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + .txwi_size = MT_SDIO_TXD_SIZE, + .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb, + .tx_complete_skb = mt7921_usb_sdio_tx_complete_skb, + .tx_status_data = mt7921_usb_sdio_tx_status_data, + .rx_skb = mt7921_queue_rx_skb, + .rx_check = mt7921_rx_check, + .sta_ps = mt7921_sta_ps, + .sta_add = mt7921_mac_sta_add, + .sta_assoc = mt7921_mac_sta_assoc, + .sta_remove = mt7921_mac_sta_remove, + .update_survey = mt7921_update_channel, + }; + static const struct mt7921_hif_ops hif_ops = { + .mcu_init = mt7921u_mcu_init, + .init_reset = mt7921u_init_reset, + .reset = mt7921u_mac_reset, + }; + static struct mt76_bus_ops bus_ops = { + .rr = mt7921u_rr, + .wr = mt7921u_wr, + .rmw = mt7921u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt7921u_copy, + .type = MT76_BUS_USB, + }; + struct usb_device *udev = interface_to_usbdev(usb_intf); + struct ieee80211_ops *ops; + struct ieee80211_hw *hw; + struct mt7921_dev *dev; + struct mt76_dev *mdev; + int ret; + + ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops), + GFP_KERNEL); + if (!ops) + return -ENOMEM; + + ops->stop = mt7921u_stop; + + mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7921_dev, mt76); + dev->hif_ops = &hif_ops; + + udev = usb_get_dev(udev); + usb_reset_device(udev); + + usb_set_intfdata(usb_intf, dev); + + ret = __mt76u_init(mdev, usb_intf, &bus_ops); + if (ret < 0) + goto error; + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) { + ret = mt7921u_wfsys_reset(dev); + if (ret) + goto error; + } + + ret = mt7921u_mcu_power_on(dev); + if (ret) + goto error; + + ret = mt76u_alloc_mcu_queue(&dev->mt76); + if (ret) + goto error; + + ret = mt76u_alloc_queues(&dev->mt76); + if (ret) + goto error; + + ret = mt7921u_dma_init(dev, false); + if (ret) + return ret; + + hw = mt76_hw(dev); + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1; + + ret = mt7921_register_device(dev); + if (ret) + goto error; + + return 0; + +error: + mt76u_queues_deinit(&dev->mt76); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); + + return ret; +} + +static void mt7921u_disconnect(struct usb_interface *usb_intf) +{ + struct mt7921_dev *dev = usb_get_intfdata(usb_intf); + + cancel_work_sync(&dev->init_work); + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return; + + mt76_unregister_device(&dev->mt76); + mt7921u_cleanup(dev); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); +} + +#ifdef CONFIG_PM +static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt76_connac_pm *pm = &dev->pm; + int err; + + pm->suspended = true; + flush_work(&dev->reset_work); + + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + if (err) + goto failed; + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + return 0; + +failed: + pm->suspended = false; + + if (err < 0) + mt7921_reset(&dev->mt76); + + return err; +} + +static int mt7921u_resume(struct usb_interface *intf) +{ + struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt76_connac_pm *pm = &dev->pm; + bool reinit = true; + int err, i; + + for (i = 0; i < 10; i++) { + u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT); + + if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) { + reinit = false; + break; + } + if (val & MT_WF_SW_SER_DONE_SUSPEND) { + mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0); + break; + } + + msleep(20); + } + + if (reinit || mt7921_dma_need_reinit(dev)) { + err = mt7921u_dma_init(dev, true); + if (err) + goto failed; + } + + err = mt76u_resume_rx(&dev->mt76); + if (err < 0) + goto failed; + + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); +failed: + pm->suspended = false; + + if (err < 0) + mt7921_reset(&dev->mt76); + + return err; +} +#endif /* CONFIG_PM */ + +MODULE_DEVICE_TABLE(usb, mt7921u_device_table); +MODULE_FIRMWARE(MT7921_FIRMWARE_WM); +MODULE_FIRMWARE(MT7921_ROM_PATCH); + +static struct usb_driver mt7921u_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7921u_device_table, + .probe = mt7921u_probe, + .disconnect = mt7921u_disconnect, +#ifdef CONFIG_PM + .suspend = mt7921u_suspend, + .resume = mt7921u_resume, + .reset_resume = mt7921u_resume, +#endif /* CONFIG_PM */ + .soft_unbind = 1, + .disable_hub_initiated_lpm = 1, +}; +module_usb_driver(mt7921u_driver); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c new file mode 100644 index 000000000000..efbd3954c883 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2022 MediaTek Inc. + * + * Author: Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> + +#include "mt7921.h" +#include "mcu.h" +#include "mac.h" + +static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, + USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE, + USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static void mt7921u_dma_prefetch(struct mt7921_dev *dev) +{ + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_BASE_PTR_MASK, 0x80); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_BASE_PTR_MASK, 0xc0); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_BASE_PTR_MASK, 0x100); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_BASE_PTR_MASK, 0x140); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_BASE_PTR_MASK, 0x180); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_BASE_PTR_MASK, 0x280); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_BASE_PTR_MASK, 0x2c0); +} + +static void mt7921u_wfdma_init(struct mt7921_dev *dev) +{ + mt7921u_dma_prefetch(dev); + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | + MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + /* disable dmashdl */ + mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + +static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev) +{ + if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) + return -ETIMEDOUT; + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + return 0; +} + +static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) +{ + u32 val; + + /* usb endpoint reset opt + * bits[4,9]: out blk ep 4-9 + * bits[20,21]: in blk ep 4-5 + * bits[22]: in int ep 6 + */ + val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); + if (reset) + val |= GENMASK(9, 4) | GENMASK(22, 20); + else + val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); + mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); +} + +int mt7921u_dma_init(struct mt7921_dev *dev, bool resume) +{ + int err; + + mt7921u_wfdma_init(dev); + + mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); + + mt76_set(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_EN | MT_WL_TX_EN | + MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); + mt76_clear(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); + mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); + + if (resume) + return 0; + + err = mt7921u_dma_rx_evt_ep4(dev); + if (err) + return err; + + mt7921u_epctl_rst_opt(dev, false); + + return 0; +} + +int mt7921u_wfsys_reset(struct mt7921_dev *dev) +{ + u32 val; + int i; + + mt7921u_epctl_rst_opt(dev, false); + + val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + usleep_range(10, 20); + + val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); + for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) { + val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); + if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) + break; + + msleep(100); + } + + if (i == MT7921_WFSYS_INIT_RETRY_COUNT) + return -ETIMEDOUT; + + return 0; +} + +int mt7921u_init_reset(struct mt7921_dev *dev) +{ + set_bit(MT76_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt7921u_wfsys_reset(dev); + + clear_bit(MT76_RESET, &dev->mphy.state); + + return mt76u_resume_rx(&dev->mt76); +} + +int mt7921u_mac_reset(struct mt7921_dev *dev) +{ + int err; + + mt76_txq_schedule_all(&dev->mphy); + mt76_worker_disable(&dev->mt76.tx_worker); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt7921u_wfsys_reset(dev); + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + err = mt76u_resume_rx(&dev->mt76); + if (err) + goto out; + + err = mt7921u_mcu_power_on(dev); + if (err) + goto out; + + err = mt7921u_dma_init(dev, false); + if (err) + goto out; + + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_run_firmware(dev); + if (err) + goto out; + + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7921_mac_init(dev); + if (err) + goto out; + + err = __mt7921_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; +} diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index c99acc21225e..0ec308f99af5 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -12,6 +12,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mmc/sdio_func.h> +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> #include <linux/sched.h> #include <linux/kthread.h> @@ -305,12 +307,12 @@ int mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, - MT_NUM_RX_ENTRIES, sizeof(*q->entry), + MT76S_NUM_RX_ENTRIES, sizeof(*q->entry), GFP_KERNEL); if (!q->entry) return -ENOMEM; - q->ndesc = MT_NUM_RX_ENTRIES; + q->ndesc = MT76S_NUM_RX_ENTRIES; q->head = q->tail = 0; q->queued = 0; @@ -328,12 +330,12 @@ static struct mt76_queue *mt76s_alloc_tx_queue(struct mt76_dev *dev) spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, - MT_NUM_TX_ENTRIES, sizeof(*q->entry), + MT76S_NUM_TX_ENTRIES, sizeof(*q->entry), GFP_KERNEL); if (!q->entry) return ERR_PTR(-ENOMEM); - q->ndesc = MT_NUM_TX_ENTRIES; + q->ndesc = MT76S_NUM_TX_ENTRIES; return q; } @@ -348,7 +350,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev) if (IS_ERR(q)) return PTR_ERR(q); - q->qid = i; dev->phy.q_tx[i] = q; } @@ -356,7 +357,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev) if (IS_ERR(q)) return PTR_ERR(q); - q->qid = MT_MCUQ_WM; dev->q_mcu[MT_MCUQ_WM] = q; return 0; @@ -478,13 +478,14 @@ static void mt76s_status_worker(struct mt76_worker *w) if (ndata_frames > 0) resched = true; - if (dev->drv->tx_status_data && - !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) - queue_work(dev->wq, &dev->sdio.stat_work); + if (dev->drv->tx_status_data && ndata_frames > 0 && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state) && + !test_bit(MT76_STATE_SUSPEND, &dev->phy.state)) + ieee80211_queue_work(dev->hw, &dev->sdio.stat_work); } while (nframes > 0); if (resched) - mt76_worker_schedule(&dev->sdio.txrx_worker); + mt76_worker_schedule(&dev->tx_worker); } static void mt76s_tx_status_data(struct work_struct *work) @@ -507,15 +508,15 @@ static void mt76s_tx_status_data(struct work_struct *work) } if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state)) - queue_work(dev->wq, &sdio->stat_work); + ieee80211_queue_work(dev->hw, &sdio->stat_work); else clear_bit(MT76_READING_STATS, &dev->phy.state); } static int mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta) + enum mt76_txq_id qid, struct sk_buff *skb, + struct mt76_wcid *wcid, struct ieee80211_sta *sta) { struct mt76_tx_info tx_info = { .skb = skb, @@ -527,7 +528,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, return -ENOSPC; skb->prev = skb->next = NULL; - err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info); + err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); if (err < 0) return err; @@ -626,6 +627,7 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, const struct mt76_bus_ops *bus_ops) { struct mt76_sdio *sdio = &dev->sdio; + u32 host_max_cap; int err; err = mt76_worker_setup(dev->hw, &sdio->status_worker, @@ -647,7 +649,16 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, dev->bus = bus_ops; dev->sdio.func = func; - return 0; + host_max_cap = min_t(u32, func->card->host->max_req_size, + func->cur_blksize * + func->card->host->max_blk_count); + dev->sdio.xmit_buf_sz = min_t(u32, host_max_cap, MT76S_XMIT_BUF_SZ); + dev->sdio.xmit_buf = devm_kmalloc(dev->dev, dev->sdio.xmit_buf_sz, + GFP_KERNEL); + if (!dev->sdio.xmit_buf) + err = -ENOMEM; + + return err; } EXPORT_SYMBOL_GPL(mt76s_init); diff --git a/drivers/net/wireless/mediatek/mt76/sdio.h b/drivers/net/wireless/mediatek/mt76/sdio.h index 99db4ad93b7c..27d5d2077eba 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.h +++ b/drivers/net/wireless/mediatek/mt76/sdio.h @@ -65,6 +65,7 @@ #define MCR_H2DSM0R 0x0070 #define H2D_SW_INT_READ BIT(16) #define H2D_SW_INT_WRITE BIT(17) +#define H2D_SW_INT_CLEAR_MAILBOX_ACK BIT(22) #define MCR_H2DSM1R 0x0074 #define MCR_D2HRM0R 0x0078 @@ -109,6 +110,7 @@ #define MCR_H2DSM2R 0x0160 /* supported in CONNAC2 */ #define MCR_H2DSM3R 0x0164 /* supported in CONNAC2 */ #define MCR_D2HRM3R 0x0174 /* supported in CONNAC2 */ +#define D2HRM3R_IS_DRIVER_OWN BIT(0) #define MCR_WTQCR8 0x0190 /* supported in CONNAC2 */ #define MCR_WTQCR9 0x0194 /* supported in CONNAC2 */ #define MCR_WTQCR10 0x0198 /* supported in CONNAC2 */ diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c index 649a56790b89..bfc4de50a4d2 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c @@ -85,7 +85,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid, struct mt76_sdio *sdio = &dev->sdio; int len = 0, err, i; struct page *page; - u8 *buf; + u8 *buf, *end; for (i = 0; i < intr->rx.num[qid]; i++) len += round_up(intr->rx.len[qid][i] + 4, 4); @@ -102,27 +102,39 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid, buf = page_address(page); + sdio_claim_host(sdio->func); err = sdio_readsb(sdio->func, buf, MCR_WRDR(qid), len); + sdio_release_host(sdio->func); + if (err < 0) { dev_err(dev->dev, "sdio read data failed:%d\n", err); put_page(page); return err; } - for (i = 0; i < intr->rx.num[qid]; i++) { + end = buf + len; + i = 0; + + while (i < intr->rx.num[qid] && buf < end) { int index = (q->head + i) % q->ndesc; struct mt76_queue_entry *e = &q->entry[index]; __le32 *rxd = (__le32 *)buf; /* parse rxd to get the actual packet length */ - len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0])); - e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4)); - if (!e->skb) - break; - + len = le32_get_bits(rxd[0], GENMASK(15, 0)); + + /* Optimized path for TXS */ + if (!dev->drv->rx_check || dev->drv->rx_check(dev, buf, len)) { + e->skb = mt76s_build_rx_skb(buf, len, + round_up(len + 4, 4)); + if (!e->skb) + break; + + if (q->queued + i + 1 == q->ndesc) + break; + i++; + } buf += round_up(len + 4, 4); - if (q->queued + i + 1 == q->ndesc) - break; } put_page(page); @@ -214,7 +226,10 @@ static int __mt76s_xmit_queue(struct mt76_dev *dev, u8 *data, int len) if (len > sdio->func->cur_blksize) len = roundup(len, sdio->func->cur_blksize); + sdio_claim_host(sdio->func); err = sdio_writesb(sdio->func, MCR_WTDR1, data, len); + sdio_release_host(sdio->func); + if (err) dev_err(dev->dev, "sdio write failed: %d\n", err); @@ -223,12 +238,11 @@ static int __mt76s_xmit_queue(struct mt76_dev *dev, u8 *data, int len) static int mt76s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) { - int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; + int err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; bool mcu = q == dev->q_mcu[MT_MCUQ_WM]; struct mt76_sdio *sdio = &dev->sdio; u8 pad; - qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid; while (q->first != q->head) { struct mt76_queue_entry *e = &q->entry[q->first]; struct sk_buff *iter; @@ -249,27 +263,25 @@ static int mt76s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) } pad = roundup(e->skb->len, 4) - e->skb->len; - if (len + e->skb->len + pad + 4 > MT76S_XMIT_BUF_SZ) + if (len + e->skb->len + pad + 4 > dev->sdio.xmit_buf_sz) break; if (mt76s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz, &ple_sz)) break; - memcpy(sdio->xmit_buf[qid] + len, e->skb->data, - skb_headlen(e->skb)); + memcpy(sdio->xmit_buf + len, e->skb->data, skb_headlen(e->skb)); len += skb_headlen(e->skb); nframes++; skb_walk_frags(e->skb, iter) { - memcpy(sdio->xmit_buf[qid] + len, iter->data, - iter->len); + memcpy(sdio->xmit_buf + len, iter->data, iter->len); len += iter->len; nframes++; } if (unlikely(pad)) { - memset(sdio->xmit_buf[qid] + len, 0, pad); + memset(sdio->xmit_buf + len, 0, pad); len += pad; } next: @@ -278,8 +290,8 @@ next: } if (nframes) { - memset(sdio->xmit_buf[qid] + len, 0, 4); - err = __mt76s_xmit_queue(dev, sdio->xmit_buf[qid], len + 4); + memset(sdio->xmit_buf + len, 0, 4); + err = __mt76s_xmit_queue(dev, sdio->xmit_buf, len + 4); if (err) return err; } @@ -298,6 +310,7 @@ void mt76s_txrx_worker(struct mt76_sdio *sdio) /* disable interrupt */ sdio_claim_host(sdio->func); sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL); + sdio_release_host(sdio->func); do { nframes = 0; @@ -317,7 +330,8 @@ void mt76s_txrx_worker(struct mt76_sdio *sdio) if (ret > 0) nframes += ret; - if (test_bit(MT76_MCU_RESET, &dev->phy.state)) { + if (test_bit(MT76_MCU_RESET, &dev->phy.state) || + test_bit(MT76_STATE_SUSPEND, &dev->phy.state)) { if (!mt76s_txqs_empty(dev)) continue; else @@ -326,6 +340,7 @@ void mt76s_txrx_worker(struct mt76_sdio *sdio) } while (nframes > 0); /* enable interrupt */ + sdio_claim_host(sdio->func); sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL); sdio_release_host(sdio->func); } @@ -340,6 +355,7 @@ void mt76s_sdio_irq(struct sdio_func *func) test_bit(MT76_MCU_RESET, &dev->phy.state)) return; + sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL); mt76_worker_schedule(&sdio->txrx_worker); } EXPORT_SYMBOL_GPL(mt76s_sdio_irq); diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 66afc2b0a935..0accc71a91c9 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: ISC /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */ + +#include <linux/random.h> #include "mt76.h" const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { @@ -50,8 +52,8 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy) q->queued < q->ndesc / 2) { int ret; - ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid, - NULL); + ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb), + wcid, NULL); if (ret < 0) break; @@ -101,7 +103,6 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len) u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_FROMDS; struct mt76_testmode_data *td = &phy->test; - bool ext_phy = phy != &phy->dev->phy; struct sk_buff **frag_tail, *head; struct ieee80211_tx_info *info; struct ieee80211_hdr *hdr; @@ -124,21 +125,21 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len) if (!head) return -ENOMEM; - hdr = __skb_put_zero(head, head_len); + hdr = __skb_put_zero(head, sizeof(*hdr)); hdr->frame_control = cpu_to_le16(fc); - memcpy(hdr->addr1, phy->macaddr, sizeof(phy->macaddr)); - memcpy(hdr->addr2, phy->macaddr, sizeof(phy->macaddr)); - memcpy(hdr->addr3, phy->macaddr, sizeof(phy->macaddr)); + memcpy(hdr->addr1, td->addr[0], ETH_ALEN); + memcpy(hdr->addr2, td->addr[1], ETH_ALEN); + memcpy(hdr->addr3, td->addr[2], ETH_ALEN); skb_set_queue_mapping(head, IEEE80211_AC_BE); + get_random_bytes(__skb_put(head, head_len - sizeof(*hdr)), + head_len - sizeof(*hdr)); info = IEEE80211_SKB_CB(head); info->flags = IEEE80211_TX_CTL_INJECTED | IEEE80211_TX_CTL_NO_ACK | IEEE80211_TX_CTL_NO_PS_BUFFER; - if (ext_phy) - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); frag_tail = &skb_shinfo(head)->frag_list; for (i = 0; i < nfrags; i++) { @@ -157,7 +158,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len) return -ENOMEM; } - __skb_put_zero(frag, frag_len); + get_random_bytes(__skb_put(frag, frag_len), frag_len); head->len += frag->len; head->data_len += frag->len; @@ -318,6 +319,10 @@ mt76_testmode_init_defaults(struct mt76_phy *phy) td->tx_count = 1; td->tx_rate_mode = MT76_TM_TX_MODE_OFDM; td->tx_rate_nss = 1; + + memcpy(td->addr[0], phy->macaddr, ETH_ALEN); + memcpy(td->addr[1], phy->macaddr, ETH_ALEN); + memcpy(td->addr[2], phy->macaddr, ETH_ALEN); } static int @@ -405,7 +410,6 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_dev *dev = phy->dev; struct mt76_testmode_data *td = &phy->test; struct nlattr *tb[NUM_MT76_TM_ATTRS]; - bool ext_phy = phy != &dev->phy; u32 state; int err; int i; @@ -443,8 +447,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) || - mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, - 1 << (ext_phy * 2), phy->antenna_mask << (ext_phy * 2)) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], + &td->tx_antenna_mask, 0, 0xff) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_SPE_IDX], &td->tx_spe_idx, 0, 27) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE], &td->tx_duty_cycle, 0, 99) || @@ -493,6 +497,20 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } } + if (tb[MT76_TM_ATTR_MAC_ADDRS]) { + struct nlattr *cur; + int idx = 0; + int rem; + + nla_for_each_nested(cur, tb[MT76_TM_ATTR_MAC_ADDRS], rem) { + if (nla_len(cur) != ETH_ALEN || idx >= 3) + goto out; + + memcpy(td->addr[idx], nla_data(cur), ETH_ALEN); + idx++; + } + } + if (dev->test_ops->set_params) { err = dev->test_ops->set_params(phy, tb, state); if (err) @@ -635,6 +653,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, nla_nest_end(msg, a); } + if (mt76_testmode_param_present(td, MT76_TM_ATTR_MAC_ADDRS)) { + a = nla_nest_start(msg, MT76_TM_ATTR_MAC_ADDRS); + if (!a) + goto out; + + for (i = 0; i < 3; i++) + if (nla_put(msg, i, ETH_ALEN, td->addr[i])) + goto out; + + nla_nest_end(msg, a); + } + err = 0; out: diff --git a/drivers/net/wireless/mediatek/mt76/testmode.h b/drivers/net/wireless/mediatek/mt76/testmode.h index d1f9c036dd1f..0590c35c7126 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.h +++ b/drivers/net/wireless/mediatek/mt76/testmode.h @@ -7,6 +7,8 @@ #define MT76_TM_TIMEOUT 10 +#include <net/netlink.h> + /** * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA * @@ -45,6 +47,8 @@ * @MT76_TM_ATTR_TX_TIME: packet transmission time, in unit of us (u32) * * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested) + * + * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested) */ enum mt76_testmode_attr { MT76_TM_ATTR_UNSPEC, @@ -81,6 +85,8 @@ enum mt76_testmode_attr { MT76_TM_ATTR_DRV_DATA, + MT76_TM_ATTR_MAC_ADDRS, + /* keep last */ NUM_MT76_TM_ATTRS, MT76_TM_ATTR_MAX = NUM_MT76_TM_ATTRS - 1, diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 6b8c9dc80542..6c054850363f 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -60,15 +60,20 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list) .skb = skb, .info = IEEE80211_SKB_CB(skb), }; + struct ieee80211_rate_status rs = {}; struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); struct mt76_wcid *wcid; wcid = rcu_dereference(dev->wcid[cb->wcid]); if (wcid) { status.sta = wcid_to_sta(wcid); - - if (status.sta) - status.rate = &wcid->rate; + if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) { + rs.rate_idx = wcid->rate; + status.rates = &rs; + status.n_rates = 1; + } else { + status.n_rates = 0; + } } hw = mt76_tx_status_get_hw(dev, skb); @@ -120,7 +125,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, memset(cb, 0, sizeof(*cb)); - if (!wcid) + if (!wcid || !rcu_access_pointer(dev->wcid[wcid->idx])) return MT_PACKET_ID_NO_ACK; if (info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -285,7 +290,7 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb, int idx; non_aql = !info->tx_time_est; - idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta); + idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta); if (idx < 0 || !sta) return idx; @@ -311,7 +316,6 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct mt76_queue *q; int qid = skb_get_queue_mapping(skb); - bool ext_phy = phy != &dev->phy; if (mt76_testmode_enabled(phy)) { ieee80211_free_txskb(phy->hw, skb); @@ -328,16 +332,13 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, !ieee80211_is_data(hdr->frame_control) && !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { qid = MT_TXQ_PSD; - skb_set_queue_mapping(skb, qid); } if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(info->control.vif, sta, skb, info->control.rates, 1); - if (ext_phy) - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); q = phy->q_tx[qid]; spin_lock_bh(&q->lock); @@ -352,7 +353,6 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct ieee80211_tx_info *info; - bool ext_phy = phy != &phy->dev->phy; struct sk_buff *skb; skb = ieee80211_tx_dequeue(phy->hw, txq); @@ -360,8 +360,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq) return NULL; info = IEEE80211_SKB_CB(skb); - if (ext_phy) - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); return skb; } @@ -436,12 +435,11 @@ mt76_txq_stopped(struct mt76_queue *q) static int mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, - struct mt76_txq *mtxq) + struct mt76_txq *mtxq, struct mt76_wcid *wcid) { struct mt76_dev *dev = phy->dev; struct ieee80211_txq *txq = mtxq_to_txq(mtxq); enum mt76_txq_id qid = mt76_txq_get_qid(txq); - struct mt76_wcid *wcid = mtxq->wcid; struct ieee80211_tx_info *info; struct sk_buff *skb; int n_frames = 1; @@ -463,7 +461,9 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); + spin_lock(&q->lock); idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); + spin_unlock(&q->lock); if (idx < 0) return idx; @@ -483,14 +483,18 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); + spin_lock(&q->lock); idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); + spin_unlock(&q->lock); if (idx < 0) break; n_frames++; } while (1); + spin_lock(&q->lock); dev->queue_ops->kick(dev, q); + spin_unlock(&q->lock); return n_frames; } @@ -521,12 +525,10 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) break; mtxq = (struct mt76_txq *)txq->drv_priv; - wcid = mtxq->wcid; - if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags)) + wcid = rcu_dereference(dev->wcid[mtxq->wcid]); + if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags)) continue; - spin_lock_bh(&q->lock); - if (mtxq->send_bar && mtxq->aggr) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct ieee80211_sta *sta = txq->sta; @@ -535,15 +537,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) u8 tid = txq->tid; mtxq->send_bar = false; - spin_unlock_bh(&q->lock); ieee80211_send_bar(vif, sta->addr, tid, agg_ssn); - spin_lock_bh(&q->lock); } if (!mt76_txq_stopped(q)) - n_frames = mt76_txq_send_burst(phy, q, mtxq); - - spin_unlock_bh(&q->lock); + n_frames = mt76_txq_send_burst(phy, q, mtxq, wcid); ieee80211_return_txq(phy->hw, txq, false); @@ -563,6 +561,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) if (qid >= 4) return; + local_bh_disable(); rcu_read_lock(); do { @@ -572,6 +571,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) } while (len > 0); rcu_read_unlock(); + local_bh_enable(); } EXPORT_SYMBOL_GPL(mt76_txq_schedule); @@ -586,15 +586,25 @@ EXPORT_SYMBOL_GPL(mt76_txq_schedule_all); void mt76_tx_worker_run(struct mt76_dev *dev) { - mt76_txq_schedule_all(&dev->phy); - if (dev->phy2) - mt76_txq_schedule_all(dev->phy2); + struct mt76_phy *phy; + int i; + + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { + phy = dev->phys[i]; + if (!phy) + continue; + + mt76_txq_schedule_all(phy); + } #ifdef CONFIG_NL80211_TESTMODE - if (dev->phy.test.tx_pending) - mt76_testmode_tx_pending(&dev->phy); - if (dev->phy2 && dev->phy2->test.tx_pending) - mt76_testmode_tx_pending(dev->phy2); + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { + phy = dev->phys[i]; + if (!phy || !phy->test.tx_pending) + continue; + + mt76_testmode_tx_pending(phy); + } #endif } EXPORT_SYMBOL_GPL(mt76_tx_worker_run); @@ -697,17 +707,23 @@ EXPORT_SYMBOL_GPL(mt76_queue_tx_complete); void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked) { - struct mt76_phy *phy = &dev->phy, *phy2 = dev->phy2; - struct mt76_queue *q, *q2 = NULL; + struct mt76_phy *phy = &dev->phy; + struct mt76_queue *q = phy->q_tx[0]; - q = phy->q_tx[0]; if (blocked == q->blocked) return; q->blocked = blocked; - if (phy2) { - q2 = phy2->q_tx[0]; - q2->blocked = blocked; + + phy = dev->phys[MT_BAND1]; + if (phy) { + q = phy->q_tx[0]; + q->blocked = blocked; + } + phy = dev->phys[MT_BAND2]; + if (phy) { + q = phy->q_tx[0]; + q->blocked = blocked; } if (!blocked) @@ -721,12 +737,17 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) spin_lock_bh(&dev->token_lock); - token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size, - GFP_ATOMIC); + token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); if (token >= 0) dev->token_count++; - if (dev->token_count >= dev->drv->token_size - MT76_TOKEN_FREE_THR) +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + if (mtk_wed_device_active(&dev->mmio.wed) && + token >= dev->mmio.wed.wlan.token_start) + dev->wed_token_count++; +#endif + + if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR) __mt76_set_tx_blocked(dev, true); spin_unlock_bh(&dev->token_lock); @@ -743,10 +764,18 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake) spin_lock_bh(&dev->token_lock); txwi = idr_remove(&dev->token, token); - if (txwi) + if (txwi) { dev->token_count--; - if (dev->token_count < dev->drv->token_size - MT76_TOKEN_FREE_THR && +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + if (mtk_wed_device_active(&dev->mmio.wed) && + token >= dev->mmio.wed.wlan.token_start && + --dev->wed_token_count == 0) + wake_up(&dev->tx_wait); +#endif + } + + if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR && dev->phy.q_tx[0]->blocked) *wake = true; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 0a7006c8959b..4c4033bb1bb3 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -15,9 +15,8 @@ static bool disable_usb_sg; module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644); MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support"); -static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, - u8 req_type, u16 val, u16 offset, - void *buf, size_t len) +int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, + u16 val, u16 offset, void *buf, size_t len) { struct usb_interface *uintf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(uintf); @@ -45,6 +44,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, req, offset, ret); return ret; } +EXPORT_SYMBOL_GPL(__mt76u_vendor_request); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, @@ -62,22 +62,21 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, } EXPORT_SYMBOL_GPL(mt76u_vendor_request); -static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr) +u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr) { struct mt76_usb *usb = &dev->usb; u32 data = ~0; int ret; - ret = __mt76u_vendor_request(dev, req, - USB_DIR_IN | USB_TYPE_VENDOR, - addr >> 16, addr, usb->data, - sizeof(__le32)); + ret = __mt76u_vendor_request(dev, req, req_type, addr >> 16, + addr, usb->data, sizeof(__le32)); if (ret == sizeof(__le32)) data = get_unaligned_le32(usb->data); trace_usb_reg_rr(dev, addr, data); return data; } +EXPORT_SYMBOL_GPL(___mt76u_rr); static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) { @@ -95,7 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) break; } - return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK); + return ___mt76u_rr(dev, req, USB_DIR_IN | USB_TYPE_VENDOR, + addr & ~MT_VEND_TYPE_MASK); } static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) @@ -109,29 +109,17 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) return ret; } -static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void ___mt76u_wr(struct mt76_dev *dev, u8 req, - u32 addr, u32 val) +void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type, + u32 addr, u32 val) { struct mt76_usb *usb = &dev->usb; put_unaligned_le32(val, usb->data); - __mt76u_vendor_request(dev, req, - USB_DIR_OUT | USB_TYPE_VENDOR, - addr >> 16, addr, usb->data, - sizeof(__le32)); + __mt76u_vendor_request(dev, req, req_type, addr >> 16, + addr, usb->data, sizeof(__le32)); trace_usb_reg_wr(dev, addr, val); } +EXPORT_SYMBOL_GPL(___mt76u_wr); static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) { @@ -145,7 +133,8 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) req = MT_VEND_MULTI_WRITE; break; } - ___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val); + ___mt76u_wr(dev, req, USB_DIR_OUT | USB_TYPE_VENDOR, + addr & ~MT_VEND_TYPE_MASK, val); } static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) @@ -155,13 +144,6 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) mutex_unlock(&dev->usb.usb_ctrl_mtx); } -static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) { @@ -173,17 +155,6 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, return val; } -static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, - u32 mask, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask; - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return val; -} - static void mt76u_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) { @@ -216,33 +187,8 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset, mutex_unlock(&usb->usb_ctrl_mtx); } -static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset, - const void *data, int len) -{ - struct mt76_usb *usb = &dev->usb; - int ret, i = 0, batch_len; - const u8 *val = data; - - len = round_up(len, 4); - mutex_lock(&usb->usb_ctrl_mtx); - while (i < len) { - batch_len = min_t(int, usb->data_len, len - i); - memcpy(usb->data, val + i, batch_len); - ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | USB_TYPE_VENDOR, - (offset + i) >> 16, offset + i, - usb->data, batch_len); - if (ret < 0) - break; - - i += batch_len; - } - mutex_unlock(&usb->usb_ctrl_mtx); -} - -static void -mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, - void *data, int len) +void mt76u_read_copy(struct mt76_dev *dev, u32 offset, + void *data, int len) { struct mt76_usb *usb = &dev->usb; int i = 0, batch_len, ret; @@ -264,6 +210,7 @@ mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, } mutex_unlock(&usb->usb_ctrl_mtx); } +EXPORT_SYMBOL_GPL(mt76u_read_copy); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val) @@ -581,6 +528,11 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, head_room = drv_flags & MT_DRV_RX_DMA_HDR ? 0 : MT_DMA_HDR_LEN; data_len = min_t(int, len, data_len - head_room); + + if (len == data_len && + dev->drv->rx_check && !dev->drv->rx_check(dev, data, data_len)) + return 0; + skb = mt76u_build_rx_skb(dev, data, data_len, buf_size); if (!skb) return 0; @@ -898,8 +850,8 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, static int mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta) + enum mt76_txq_id qid, struct sk_buff *skb, + struct mt76_wcid *wcid, struct ieee80211_sta *sta) { struct mt76_tx_info tx_info = { .skb = skb, @@ -911,7 +863,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, return -ENOSPC; skb->prev = skb->next = NULL; - err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info); + err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); if (err < 0) return err; @@ -990,7 +942,6 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) spin_lock_init(&q->lock); q->hw_idx = mt76u_ac_to_hwq(dev, i); - q->qid = i; dev->phy.q_tx[i] = q; @@ -1112,27 +1063,16 @@ static const struct mt76_queue_ops usb_queue_ops = { .kick = mt76u_tx_kick, }; -int mt76u_init(struct mt76_dev *dev, - struct usb_interface *intf, bool ext) +int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + struct mt76_bus_ops *ops) { - static struct mt76_bus_ops mt76u_ops = { - .read_copy = mt76u_read_copy_ext, - .wr_rp = mt76u_wr_rp, - .rd_rp = mt76u_rd_rp, - .type = MT76_BUS_USB, - }; struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; int err; - mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; - mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; - mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw; - mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; - INIT_WORK(&usb->stat_work, mt76u_tx_status_data); - usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); + usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0)); if (usb->data_len < 32) usb->data_len = 32; @@ -1141,7 +1081,7 @@ int mt76u_init(struct mt76_dev *dev, return -ENOMEM; mutex_init(&usb->usb_ctrl_mtx); - dev->bus = &mt76u_ops; + dev->bus = ops; dev->queue_ops = &usb_queue_ops; dev_set_drvdata(&udev->dev, dev); @@ -1167,6 +1107,23 @@ int mt76u_init(struct mt76_dev *dev, return 0; } +EXPORT_SYMBOL_GPL(__mt76u_init); + +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf) +{ + static struct mt76_bus_ops bus_ops = { + .rr = mt76u_rr, + .wr = mt76u_wr, + .rmw = mt76u_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt76u_copy, + .wr_rp = mt76u_wr_rp, + .rd_rp = mt76u_rd_rp, + .type = MT76_BUS_USB, + }; + + return __mt76u_init(dev, intf, &bus_ops); +} EXPORT_SYMBOL_GPL(mt76u_init); MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |