Commit 950d0abb authored by Bo Jiao's avatar Bo Jiao Committed by Felix Fietkau

wifi: mt76: mt7996: add wed rx support

Similar to MT7915, enable Wireless Ethernet Ditpatcher for MT7996
to offload traffic received from the WLAN nic and transmitted on the
LAN one
Co-developed-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Co-developed-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: default avatarBo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent b8b36f47
...@@ -189,7 +189,10 @@ static void ...@@ -189,7 +189,10 @@ static void
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
{ {
Q_WRITE(q, desc_base, q->desc_dma); Q_WRITE(q, desc_base, q->desc_dma);
Q_WRITE(q, ring_size, q->ndesc); if (q->flags & MT_QFLAG_WED_RRO_EN)
Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
else
Q_WRITE(q, ring_size, q->ndesc);
q->head = Q_READ(q, dma_idx); q->head = Q_READ(q, dma_idx);
q->tail = q->head; q->tail = q->head;
} }
...@@ -198,14 +201,16 @@ static void ...@@ -198,14 +201,16 @@ static void
__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
bool reset_idx) bool reset_idx)
{ {
int i;
if (!q || !q->ndesc) if (!q || !q->ndesc)
return; return;
/* clear descriptors */ if (!mt76_queue_is_wed_rro_ind(q)) {
for (i = 0; i < q->ndesc; i++) int i;
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
/* clear descriptors */
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
}
if (reset_idx) { if (reset_idx) {
Q_WRITE(q, cpu_idx, 0); Q_WRITE(q, cpu_idx, 0);
...@@ -224,13 +229,22 @@ static int ...@@ -224,13 +229,22 @@ static int
mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf *buf, void *data) struct mt76_queue_buf *buf, void *data)
{ {
struct mt76_desc *desc = &q->desc[q->head];
struct mt76_queue_entry *entry = &q->entry[q->head]; struct mt76_queue_entry *entry = &q->entry[q->head];
struct mt76_txwi_cache *txwi = NULL; struct mt76_txwi_cache *txwi = NULL;
struct mt76_desc *desc;
u32 buf1 = 0, ctrl; u32 buf1 = 0, ctrl;
int idx = q->head; int idx = q->head;
int rx_token; int rx_token;
if (mt76_queue_is_wed_rro_ind(q)) {
struct mt76_wed_rro_desc *rro_desc;
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
data = &rro_desc[q->head];
goto done;
}
desc = &q->desc[q->head];
ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
if (mt76_queue_is_wed_rx(q)) { if (mt76_queue_is_wed_rx(q)) {
...@@ -253,6 +267,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -253,6 +267,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
WRITE_ONCE(desc->info, 0); WRITE_ONCE(desc->info, 0);
done:
entry->dma_addr[0] = buf->addr; entry->dma_addr[0] = buf->addr;
entry->dma_len[0] = buf->len; entry->dma_len[0] = buf->len;
entry->txwi = txwi; entry->txwi = txwi;
...@@ -401,19 +416,26 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, ...@@ -401,19 +416,26 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
{ {
struct mt76_queue_entry *e = &q->entry[idx]; struct mt76_queue_entry *e = &q->entry[idx];
struct mt76_desc *desc = &q->desc[idx]; struct mt76_desc *desc = &q->desc[idx];
void *buf; u32 ctrl, desc_info, buf1;
void *buf = e->buf;
if (mt76_queue_is_wed_rro_ind(q))
goto done;
ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
if (len) { if (len) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
*len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl); *len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
*more = !(ctrl & MT_DMA_CTL_LAST_SEC0); *more = !(ctrl & MT_DMA_CTL_LAST_SEC0);
} }
desc_info = le32_to_cpu(desc->info);
if (info) if (info)
*info = le32_to_cpu(desc->info); *info = desc_info;
buf1 = le32_to_cpu(desc->buf1);
mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
if (mt76_queue_is_wed_rx(q)) { if (mt76_queue_is_wed_rx(q)) {
u32 buf1 = le32_to_cpu(desc->buf1);
u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1); u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token); struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
...@@ -429,23 +451,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, ...@@ -429,23 +451,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
t->ptr = NULL; t->ptr = NULL;
mt76_put_rxwi(dev, t); mt76_put_rxwi(dev, t);
if (drop)
if (drop) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
MT_DMA_CTL_DROP));
*drop |= !!(buf1 & MT_DMA_CTL_WO_DROP); *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
}
} else { } else {
buf = e->buf;
e->buf = NULL;
dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
SKB_WITH_OVERHEAD(q->buf_size), SKB_WITH_OVERHEAD(q->buf_size),
page_pool_get_dma_dir(q->page_pool)); page_pool_get_dma_dir(q->page_pool));
} }
done:
e->buf = NULL;
return buf; return buf;
} }
...@@ -459,11 +474,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, ...@@ -459,11 +474,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
if (!q->queued) if (!q->queued)
return NULL; return NULL;
if (flush) if (mt76_queue_is_wed_rro_data(q))
q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
return NULL; return NULL;
if (!mt76_queue_is_wed_rro_ind(q)) {
if (flush)
q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
return NULL;
}
q->tail = (q->tail + 1) % q->ndesc; q->tail = (q->tail + 1) % q->ndesc;
q->queued--; q->queued--;
...@@ -615,11 +635,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -615,11 +635,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
spin_lock_bh(&q->lock); spin_lock_bh(&q->lock);
while (q->queued < q->ndesc - 1) { while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf = {};
enum dma_data_direction dir; enum dma_data_direction dir;
struct mt76_queue_buf qbuf;
dma_addr_t addr; dma_addr_t addr;
int offset; int offset;
void *buf; void *buf = NULL;
if (mt76_queue_is_wed_rro_ind(q))
goto done;
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
if (!buf) if (!buf)
...@@ -630,6 +653,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -630,6 +653,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
dma_sync_single_for_device(dev->dma_dev, addr, len, dir); dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
qbuf.addr = addr + q->buf_offset; qbuf.addr = addr + q->buf_offset;
done:
qbuf.len = len - q->buf_offset; qbuf.len = len - q->buf_offset;
qbuf.skip_unmap = false; qbuf.skip_unmap = false;
if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
...@@ -639,7 +663,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -639,7 +663,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
frames++; frames++;
} }
if (frames) if (frames || mt76_queue_is_wed_rx(q))
mt76_dma_kick_queue(dev, q); mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock); spin_unlock_bh(&q->lock);
...@@ -650,8 +674,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -650,8 +674,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
{ {
#ifdef CONFIG_NET_MEDIATEK_SOC_WED #ifdef CONFIG_NET_MEDIATEK_SOC_WED
int ret, type, ring; int ret = 0, type, ring;
u8 flags; u16 flags;
if (!q || !q->ndesc) if (!q || !q->ndesc)
return -EINVAL; return -EINVAL;
...@@ -678,7 +702,6 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) ...@@ -678,7 +702,6 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
q->flags = 0; q->flags = 0;
mt76_dma_queue_reset(dev, q); mt76_dma_queue_reset(dev, q);
mt76_dma_rx_fill(dev, q, false); mt76_dma_rx_fill(dev, q, false);
q->flags = flags;
ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
if (!ret) if (!ret)
...@@ -690,9 +713,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) ...@@ -690,9 +713,31 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
if (!ret) if (!ret)
q->wed_regs = q->wed->rx_ring[ring].reg_base; q->wed_regs = q->wed->rx_ring[ring].reg_base;
break; break;
case MT76_WED_RRO_Q_DATA:
q->flags &= ~MT_QFLAG_WED;
__mt76_dma_queue_reset(dev, q, false);
mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
q->head = q->ndesc - 1;
q->queued = q->head;
break;
case MT76_WED_RRO_Q_MSDU_PG:
q->flags &= ~MT_QFLAG_WED;
__mt76_dma_queue_reset(dev, q, false);
mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
q->head = q->ndesc - 1;
q->queued = q->head;
break;
case MT76_WED_RRO_Q_IND:
q->flags &= ~MT_QFLAG_WED;
mt76_dma_queue_reset(dev, q);
mt76_dma_rx_fill(dev, q, false);
mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break;
} }
q->flags = flags;
return ret; return ret;
#else #else
...@@ -716,11 +761,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -716,11 +761,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
q->buf_size = bufsize; q->buf_size = bufsize;
q->hw_idx = idx; q->hw_idx = idx;
size = q->ndesc * sizeof(struct mt76_desc); size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc)
q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL); : sizeof(struct mt76_desc);
q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size,
&q->desc_dma, GFP_KERNEL);
if (!q->desc) if (!q->desc)
return -ENOMEM; return -ENOMEM;
if (mt76_queue_is_wed_rro_ind(q)) {
struct mt76_wed_rro_desc *rro_desc;
int i;
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
for (i = 0; i < q->ndesc; i++) {
struct mt76_wed_rro_ind *cmd;
cmd = (struct mt76_wed_rro_ind *)&rro_desc[i];
cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1;
}
}
size = q->ndesc * sizeof(*q->entry); size = q->ndesc * sizeof(*q->entry);
q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
if (!q->entry) if (!q->entry)
...@@ -734,8 +794,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -734,8 +794,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (ret) if (ret)
return ret; return ret;
if (!mt76_queue_is_wed_tx_free(q)) if (mtk_wed_device_active(&dev->mmio.wed)) {
mt76_dma_queue_reset(dev, q); if ((mtk_wed_get_rx_capa(&dev->mmio.wed) && mt76_queue_is_wed_rro(q)) ||
mt76_queue_is_wed_tx_free(q))
return 0;
}
mt76_dma_queue_reset(dev, q);
return 0; return 0;
} }
...@@ -757,7 +822,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) ...@@ -757,7 +822,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
if (!buf) if (!buf)
break; break;
mt76_put_page_pool_buf(buf, false); if (!mt76_queue_is_wed_rro(q))
mt76_put_page_pool_buf(buf, false);
} while (1); } while (1);
spin_lock_bh(&q->lock); spin_lock_bh(&q->lock);
...@@ -773,13 +839,16 @@ static void ...@@ -773,13 +839,16 @@ static void
mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
{ {
struct mt76_queue *q = &dev->q_rx[qid]; struct mt76_queue *q = &dev->q_rx[qid];
int i;
if (!q->ndesc) if (!q->ndesc)
return; return;
for (i = 0; i < q->ndesc; i++) if (!mt76_queue_is_wed_rro_ind(q)) {
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); int i;
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
}
mt76_dma_rx_cleanup(dev, q); mt76_dma_rx_cleanup(dev, q);
...@@ -991,6 +1060,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev) ...@@ -991,6 +1060,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
mt76_for_each_q_rx(dev, i) { mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i]; struct mt76_queue *q = &dev->q_rx[i];
if (mtk_wed_device_active(&dev->mmio.wed) &&
mt76_queue_is_wed_rro(q))
continue;
netif_napi_del(&dev->napi[i]); netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q); mt76_dma_rx_cleanup(dev, q);
......
...@@ -23,8 +23,17 @@ ...@@ -23,8 +23,17 @@
#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11) #define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
#define MT_DMA_PPE_ENTRY GENMASK(30, 16) #define MT_DMA_PPE_ENTRY GENMASK(30, 16)
#define MT_DMA_INFO_DMA_FRAG BIT(9)
#define MT_DMA_INFO_PPE_VLD BIT(31) #define MT_DMA_INFO_PPE_VLD BIT(31)
#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
#define MT_DMA_CTL_VER_MASK BIT(7)
#define MT_DMA_RRO_EN BIT(13)
#define MT_DMA_WED_IND_CMD_CNT 8
#define MT_DMA_WED_IND_REASON GENMASK(15, 12)
#define MT_DMA_HDR_LEN 4 #define MT_DMA_HDR_LEN 4
#define MT_RX_INFO_LEN 4 #define MT_RX_INFO_LEN 4
#define MT_FCE_INFO_LEN 4 #define MT_FCE_INFO_LEN 4
...@@ -37,6 +46,11 @@ struct mt76_desc { ...@@ -37,6 +46,11 @@ struct mt76_desc {
__le32 info; __le32 info;
} __packed __aligned(4); } __packed __aligned(4);
struct mt76_wed_rro_desc {
__le32 buf0;
__le32 buf1;
} __packed __aligned(4);
enum mt76_qsel { enum mt76_qsel {
MT_QSEL_MGMT, MT_QSEL_MGMT,
MT_QSEL_HCCA, MT_QSEL_HCCA,
...@@ -54,9 +68,38 @@ enum mt76_mcu_evt_type { ...@@ -54,9 +68,38 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP, EVT_EVENT_DFS_DETECT_RSP,
}; };
enum mt76_dma_wed_ind_reason {
MT_DMA_WED_IND_REASON_NORMAL,
MT_DMA_WED_IND_REASON_REPEAT,
MT_DMA_WED_IND_REASON_OLDPKT,
};
int mt76_dma_rx_poll(struct napi_struct *napi, int budget); int mt76_dma_rx_poll(struct napi_struct *napi, int budget);
void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev);
int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset); int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset);
static inline void
mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info)
{
if (!drop)
return;
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
if (!(ctrl & MT_DMA_CTL_VER_MASK))
return;
switch (FIELD_GET(MT_DMA_WED_IND_REASON, buf1)) {
case MT_DMA_WED_IND_REASON_REPEAT:
*drop = true;
break;
case MT_DMA_WED_IND_REASON_OLDPKT:
*drop = !(info & MT_DMA_INFO_DMA_FRAG);
break;
default:
*drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
break;
}
}
#endif #endif
...@@ -31,13 +31,20 @@ ...@@ -31,13 +31,20 @@
#define MT_QFLAG_WED_RING GENMASK(1, 0) #define MT_QFLAG_WED_RING GENMASK(1, 0)
#define MT_QFLAG_WED_TYPE GENMASK(4, 2) #define MT_QFLAG_WED_TYPE GENMASK(4, 2)
#define MT_QFLAG_WED BIT(5) #define MT_QFLAG_WED BIT(5)
#define MT_QFLAG_WED_RRO BIT(6)
#define MT_QFLAG_WED_RRO_EN BIT(7)
#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
FIELD_PREP(MT_QFLAG_WED_RING, _n)) FIELD_PREP(MT_QFLAG_WED_RING, _n))
#define __MT_WED_RRO_Q(_type, _n) (MT_QFLAG_WED_RRO | __MT_WED_Q(_type, _n))
#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n) #define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
#define MT_WED_Q_RX(_n) __MT_WED_Q(MT76_WED_Q_RX, _n) #define MT_WED_Q_RX(_n) __MT_WED_Q(MT76_WED_Q_RX, _n)
#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0) #define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
#define MT_WED_RRO_Q_DATA(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n)
#define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n)
#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
struct mt76_dev; struct mt76_dev;
struct mt76_phy; struct mt76_phy;
...@@ -59,6 +66,9 @@ enum mt76_wed_type { ...@@ -59,6 +66,9 @@ enum mt76_wed_type {
MT76_WED_Q_TX, MT76_WED_Q_TX,
MT76_WED_Q_TXFREE, MT76_WED_Q_TXFREE,
MT76_WED_Q_RX, MT76_WED_Q_RX,
MT76_WED_RRO_Q_DATA,
MT76_WED_RRO_Q_MSDU_PG,
MT76_WED_RRO_Q_IND,
}; };
struct mt76_bus_ops { struct mt76_bus_ops {
...@@ -194,6 +204,7 @@ struct mt76_queue { ...@@ -194,6 +204,7 @@ struct mt76_queue {
spinlock_t lock; spinlock_t lock;
spinlock_t cleanup_lock; spinlock_t cleanup_lock;
struct mt76_queue_entry *entry; struct mt76_queue_entry *entry;
struct mt76_rro_desc *rro_desc;
struct mt76_desc *desc; struct mt76_desc *desc;
u16 first; u16 first;
...@@ -207,7 +218,7 @@ struct mt76_queue { ...@@ -207,7 +218,7 @@ struct mt76_queue {
u8 buf_offset; u8 buf_offset;
u8 hw_idx; u8 hw_idx;
u8 flags; u16 flags;
struct mtk_wed_device *wed; struct mtk_wed_device *wed;
u32 wed_regs; u32 wed_regs;
...@@ -364,6 +375,17 @@ struct mt76_txq { ...@@ -364,6 +375,17 @@ struct mt76_txq {
bool aggr; bool aggr;
}; };
struct mt76_wed_rro_ind {
u32 se_id : 12;
u32 rsv : 4;
u32 start_sn : 12;
u32 ind_reason : 4;
u32 ind_cnt : 13;
u32 win_sz : 3;
u32 rsv2 : 13;
u32 magic_cnt : 3;
};
struct mt76_txwi_cache { struct mt76_txwi_cache {
struct list_head list; struct list_head list;
dma_addr_t dma_addr; dma_addr_t dma_addr;
...@@ -1581,10 +1603,32 @@ static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q) ...@@ -1581,10 +1603,32 @@ static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q)
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE; FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
} }
static inline bool mt76_queue_is_wed_rro(struct mt76_queue *q)
{
return q->flags & MT_QFLAG_WED_RRO;
}
static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
{
return mt76_queue_is_wed_rro(q) &&
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND;
}
static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q)
{
return mt76_queue_is_wed_rro(q) &&
(FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA ||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_MSDU_PG);
}
static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q) static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
{ {
return (q->flags & MT_QFLAG_WED) && if (!(q->flags & MT_QFLAG_WED))
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX; return false;
return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX ||
mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q);
} }
struct mt76_txwi_cache * struct mt76_txwi_cache *
......
...@@ -65,6 +65,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev) ...@@ -65,6 +65,29 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2); RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI); RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
if (dev->has_rro) {
/* band0 */
RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
MT7996_RXQ_RRO_BAND0);
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
MT7996_RXQ_MSDU_PG_BAND0);
RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
MT7996_RXQ_TXFREE0);
/* band1 */
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
MT7996_RXQ_MSDU_PG_BAND1);
/* band2 */
RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
MT7996_RXQ_RRO_BAND2);
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
MT7996_RXQ_MSDU_PG_BAND2);
RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
MT7996_RXQ_TXFREE2);
RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
MT7996_RXQ_RRO_IND);
}
/* data tx queue */ /* data tx queue */
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0); TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1); TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
...@@ -93,6 +116,24 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs) ...@@ -93,6 +116,24 @@ static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10)); mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10)); mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10));
if (dev->has_rro) {
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
PREFETCH(0x3a0, 0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
PREFETCH(0x4a0, 0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
PREFETCH(0x5a0, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
PREFETCH(0x5e0, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
PREFETCH(0x620, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
PREFETCH(0x660, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
PREFETCH(0x6a0, 0x4));
}
#undef PREFETCH
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE); mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
} }
...@@ -150,6 +191,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset) ...@@ -150,6 +191,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
{ {
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 hif1_ofs = 0; u32 hif1_ofs = 0;
u32 irq_mask; u32 irq_mask;
...@@ -158,11 +200,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) ...@@ -158,11 +200,16 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
/* enable WFDMA Tx/Rx */ /* enable WFDMA Tx/Rx */
if (!reset) { if (!reset) {
mt76_set(dev, MT_WFDMA0_GLO_CFG, if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
MT_WFDMA0_GLO_CFG_TX_DMA_EN | mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_RX_DMA_EN | MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | MT_WFDMA0_GLO_CFG_OMIT_TX_INFO);
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); else
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 (dev->hif2) if (dev->hif2)
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
...@@ -184,12 +231,12 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset) ...@@ -184,12 +231,12 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
if (dev->tbtc_support) if (dev->tbtc_support)
irq_mask |= MT_INT_BAND2_RX_DONE; irq_mask |= MT_INT_BAND2_RX_DONE;
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) { if (mtk_wed_device_active(wed) && wed_reset) {
u32 wed_irq_mask = irq_mask; u32 wed_irq_mask = irq_mask;
wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); mtk_wed_device_start(wed, wed_irq_mask);
} }
irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
...@@ -266,13 +313,85 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) ...@@ -266,13 +313,85 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
/* fix hardware limitation, pcie1's rx ring3 is not available /* fix hardware limitation, pcie1's rx ring3 is not available
* so, redirect pcie0 rx ring3 interrupt to pcie1 * so, redirect pcie0 rx ring3 interrupt to pcie1
*/ */
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL, if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
MT_WFDMA0_RX_INT_SEL_RING3); dev->has_rro)
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
MT_WFDMA0_RX_INT_SEL_RING6);
else
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
MT_WFDMA0_RX_INT_SEL_RING3);
} }
mt7996_dma_start(dev, reset, true); mt7996_dma_start(dev, reset, true);
} }
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt7996_dma_rro_init(struct mt7996_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
u32 irq_mask;
int ret;
/* ind cmd */
mdev->q_rx[MT_RXQ_RRO_IND].flags = MT_WED_RRO_Q_IND;
mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_IND],
MT_RXQ_ID(MT_RXQ_RRO_IND),
MT7996_RX_RING_SIZE,
0, MT_RXQ_RRO_IND_RING_BASE);
if (ret)
return ret;
/* rx msdu page queue for band0 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags =
MT_WED_RRO_Q_MSDU_PG(0) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
if (ret)
return ret;
if (dev->dbdc_support) {
/* rx msdu page queue for band1 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags =
MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
if (ret)
return ret;
}
if (dev->tbtc_support) {
/* rx msdu page queue for band2 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags =
MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
if (ret)
return ret;
}
irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE |
MT_INT_TX_DONE_BAND2;
mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);
mt7996_irq_enable(dev, irq_mask);
return 0;
}
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
int mt7996_dma_init(struct mt7996_dev *dev) int mt7996_dma_init(struct mt7996_dev *dev)
{ {
struct mtk_wed_device *wed = &dev->mt76.mmio.wed; struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
...@@ -356,7 +475,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) ...@@ -356,7 +475,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
return ret; return ret;
/* tx free notify event from WA for band0 */ /* tx free notify event from WA for band0 */
if (mtk_wed_device_active(wed)) { if (mtk_wed_device_active(wed) && !dev->has_rro) {
dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE; dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed; dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
} }
...@@ -372,9 +491,6 @@ int mt7996_dma_init(struct mt7996_dev *dev) ...@@ -372,9 +491,6 @@ int mt7996_dma_init(struct mt7996_dev *dev)
if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) { if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
/* rx data queue for band2 */ /* rx data queue for band2 */
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs; rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
if (mtk_wed_device_active(wed))
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2);
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2], ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
MT_RXQ_ID(MT_RXQ_BAND2), MT_RXQ_ID(MT_RXQ_BAND2),
MT7996_RX_RING_SIZE, MT7996_RX_RING_SIZE,
...@@ -386,7 +502,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) ...@@ -386,7 +502,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
/* tx free notify event from WA for band2 /* tx free notify event from WA for band2
* use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1 * use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
*/ */
if (mtk_wed_device_active(wed_hif2)) { if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) {
dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE; dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2; dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2;
} }
...@@ -400,6 +516,60 @@ int mt7996_dma_init(struct mt7996_dev *dev) ...@@ -400,6 +516,60 @@ int mt7996_dma_init(struct mt7996_dev *dev)
return ret; return ret;
} }
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
dev->has_rro) {
/* rx rro data queue for band0 */
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags =
MT_WED_RRO_Q_DATA(0) | MT_QFLAG_WED_RRO_EN;
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
MT_RXQ_ID(MT_RXQ_RRO_BAND0),
MT7996_RX_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0));
if (ret)
return ret;
/* tx free notify event from WA for band0 */
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
MT7996_RX_MCU_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
if (ret)
return ret;
if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
/* rx rro data queue for band2 */
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
MT_RXQ_ID(MT_RXQ_RRO_BAND2),
MT7996_RX_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
if (ret)
return ret;
/* tx free notify event from MAC for band2 */
if (mtk_wed_device_active(wed_hif2)) {
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].wed = wed_hif2;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2],
MT_RXQ_ID(MT_RXQ_TXFREE_BAND2),
MT7996_RX_MCU_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs);
if (ret)
return ret;
}
}
ret = mt76_init_queues(dev, mt76_dma_rx_poll); ret = mt76_init_queues(dev, mt76_dma_rx_poll);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -320,8 +320,17 @@ void mt7996_mac_init(struct mt7996_dev *dev) ...@@ -320,8 +320,17 @@ void mt7996_mac_init(struct mt7996_dev *dev)
/* rro module init */ /* rro module init */
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2); mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3); if (dev->has_rro) {
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1); u16 timeout;
timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128;
mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
} else {
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
}
mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
MCU_WA_PARAM_HW_PATH_HIF_VER, MCU_WA_PARAM_HW_PATH_HIF_VER,
...@@ -475,6 +484,163 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev) ...@@ -475,6 +484,163 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
msleep(20); msleep(20);
} }
static int mt7996_wed_rro_init(struct mt7996_dev *dev)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
struct mt7996_wed_rro_addr *addr;
void *ptr;
int i;
if (!dev->has_rro)
return 0;
if (!mtk_wed_device_active(wed))
return 0;
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_BA_BITMAP_CR_SIZE,
&dev->wed_rro.ba_bitmap[i].phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.ba_bitmap[i].ptr = ptr;
}
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
int j;
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr),
&dev->wed_rro.addr_elem[i].phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.addr_elem[i].ptr = ptr;
memset(dev->wed_rro.addr_elem[i].ptr, 0,
MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr));
addr = dev->wed_rro.addr_elem[i].ptr;
for (j = 0; j < MT7996_RRO_WINDOW_MAX_SIZE; j++) {
addr->signature = 0xff;
addr++;
}
wed->wlan.ind_cmd.addr_elem_phys[i] =
dev->wed_rro.addr_elem[i].phy_addr;
}
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
&dev->wed_rro.session.phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.session.ptr = ptr;
addr = dev->wed_rro.session.ptr;
for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
addr->signature = 0xff;
addr++;
}
/* rro hw init */
/* TODO: remove line after WM has set */
mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
/* setup BA bitmap cache address */
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
dev->wed_rro.ba_bitmap[0].phy_addr);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
dev->wed_rro.ba_bitmap[1].phy_addr);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
/* setup Address element address */
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4);
reg += 4;
}
/* setup Address element address - separate address segment mode */
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
/* particular session configure */
/* use max session idx + 1 as particular session id */
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
MT_RRO_PARTICULAR_CONFG_EN |
FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION));
/* interrupt enable */
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
/* rro ind cmd queue init */
return mt7996_dma_rro_init(dev);
#else
return 0;
#endif
}
static void mt7996_wed_rro_free(struct mt7996_dev *dev)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int i;
if (!dev->has_rro)
return;
if (!mtk_wed_device_active(&dev->mt76.mmio.wed))
return;
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
if (!dev->wed_rro.ba_bitmap[i].ptr)
continue;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_BA_BITMAP_CR_SIZE,
dev->wed_rro.ba_bitmap[i].ptr,
dev->wed_rro.ba_bitmap[i].phy_addr);
}
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
if (!dev->wed_rro.addr_elem[i].ptr)
continue;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_SIZE *
sizeof(struct mt7996_wed_rro_addr),
dev->wed_rro.addr_elem[i].ptr,
dev->wed_rro.addr_elem[i].phy_addr);
}
if (!dev->wed_rro.session.ptr)
return;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_LEN *
sizeof(struct mt7996_wed_rro_addr),
dev->wed_rro.session.ptr,
dev->wed_rro.session.phy_addr);
#endif
}
static int mt7996_init_hardware(struct mt7996_dev *dev) static int mt7996_init_hardware(struct mt7996_dev *dev)
{ {
int ret, idx; int ret, idx;
...@@ -496,6 +662,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev) ...@@ -496,6 +662,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
if (ret) if (ret)
return ret; return ret;
ret = mt7996_wed_rro_init(dev);
if (ret)
return ret;
ret = mt7996_eeprom_init(dev); ret = mt7996_eeprom_init(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -934,6 +1104,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev) ...@@ -934,6 +1104,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1); mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
mt7996_coredump_unregister(dev); mt7996_coredump_unregister(dev);
mt76_unregister_device(&dev->mt76); mt76_unregister_device(&dev->mt76);
mt7996_wed_rro_free(dev);
mt7996_mcu_exit(dev); mt7996_mcu_exit(dev);
mt7996_tx_token_put(dev); mt7996_tx_token_put(dev);
mt7996_dma_cleanup(dev); mt7996_dma_cleanup(dev);
......
...@@ -449,8 +449,36 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, ...@@ -449,8 +449,36 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
return 0; return 0;
} }
static void
mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
struct mt7996_sta *msta, struct sk_buff *skb,
u32 info)
{
struct ieee80211_vif *vif;
struct wireless_dev *wdev;
if (!msta || !msta->vif)
return;
if (!mt76_queue_is_wed_rx(q))
return;
if (!(info & MT_DMA_INFO_PPE_VLD))
return;
vif = container_of((void *)msta->vif, struct ieee80211_vif,
drv_priv);
wdev = ieee80211_vif_to_wdev(vif);
skb->dev = wdev->netdev;
mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
FIELD_GET(MT_DMA_PPE_ENTRY, info));
}
static int static int
mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info)
{ {
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_phy *mphy = &dev->mt76.phy;
...@@ -475,7 +503,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) ...@@ -475,7 +503,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
u16 seq_ctrl = 0; u16 seq_ctrl = 0;
__le16 fc = 0; __le16 fc = 0;
int idx; int idx;
u8 hw_aggr = false;
struct mt7996_sta *msta = NULL;
hw_aggr = status->aggr;
memset(status, 0, sizeof(*status)); memset(status, 0, sizeof(*status));
band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1); band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
...@@ -502,8 +533,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) ...@@ -502,8 +533,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
if (status->wcid) { if (status->wcid) {
struct mt7996_sta *msta;
msta = container_of(status->wcid, struct mt7996_sta, wcid); msta = container_of(status->wcid, struct mt7996_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock); spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->wcid.poll_list)) if (list_empty(&msta->wcid.poll_list))
...@@ -708,12 +737,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) ...@@ -708,12 +737,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
} }
} else { } else {
status->flag |= RX_FLAG_8023; status->flag |= RX_FLAG_8023;
mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
*info);
} }
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
if (!status->wcid || !ieee80211_is_data_qos(fc)) if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
return 0; return 0;
status->aggr = unicast && status->aggr = unicast &&
...@@ -1448,7 +1479,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, ...@@ -1448,7 +1479,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
dev_kfree_skb(skb); dev_kfree_skb(skb);
break; break;
case PKT_TYPE_NORMAL: case PKT_TYPE_NORMAL:
if (!mt7996_mac_fill_rx(dev, skb)) { if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
mt76_rx(&dev->mt76, q, skb); mt76_rx(&dev->mt76, q, skb);
return; return;
} }
......
...@@ -963,7 +963,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) ...@@ -963,7 +963,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
} }
static int static int
mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif,
struct ieee80211_ampdu_params *params, struct ieee80211_ampdu_params *params,
bool enable, bool tx) bool enable, bool tx)
{ {
...@@ -972,7 +972,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, ...@@ -972,7 +972,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
struct sk_buff *skb; struct sk_buff *skb;
struct tlv *tlv; struct tlv *tlv;
skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mvif, wcid,
MT7996_STA_UPDATE_MAX_SIZE); MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
...@@ -986,8 +986,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, ...@@ -986,8 +986,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
ba->ba_en = enable << params->tid; ba->ba_en = enable << params->tid;
ba->amsdu = params->amsdu; ba->amsdu = params->amsdu;
ba->tid = params->tid; ba->tid = params->tid;
ba->ba_rdd_rro = !tx && enable && dev->has_rro;
return mt76_mcu_skb_send_msg(dev, skb, return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
} }
...@@ -1002,8 +1003,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev, ...@@ -1002,8 +1003,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
if (enable && !params->amsdu) if (enable && !params->amsdu)
msta->wcid.amsdu = false; msta->wcid.amsdu = false;
return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, true);
enable, true);
} }
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
...@@ -1013,8 +1013,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev, ...@@ -1013,8 +1013,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv; struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
struct mt7996_vif *mvif = msta->vif; struct mt7996_vif *mvif = msta->vif;
return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, false);
enable, false);
} }
static void static void
...@@ -4023,10 +4022,8 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) ...@@ -4023,10 +4022,8 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
{ {
struct { struct {
u8 __rsv1[4]; u8 __rsv1[4];
__le16 tag; __le16 tag;
__le16 len; __le16 len;
union { union {
struct { struct {
u8 type; u8 type;
...@@ -4041,6 +4038,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) ...@@ -4041,6 +4038,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
u8 path; u8 path;
u8 __rsv2[3]; u8 __rsv2[3];
} __packed txfree_path; } __packed txfree_path;
struct {
__le16 flush_one;
__le16 flush_all;
u8 __rsv2[4];
} __packed timeout;
}; };
} __packed req = { } __packed req = {
.tag = cpu_to_le16(tag), .tag = cpu_to_le16(tag),
...@@ -4057,6 +4059,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val) ...@@ -4057,6 +4059,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
case UNI_RRO_SET_TXFREE_PATH: case UNI_RRO_SET_TXFREE_PATH:
req.txfree_path.path = val; req.txfree_path.path = val;
break; break;
case UNI_RRO_SET_FLUSH_TIMEOUT:
req.timeout.flush_one = cpu_to_le16(val);
req.timeout.flush_all = cpu_to_le16(2 * val);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -669,6 +669,8 @@ enum { ...@@ -669,6 +669,8 @@ enum {
UNI_RRO_GET_BA_SESSION_TABLE, UNI_RRO_GET_BA_SESSION_TABLE,
UNI_RRO_SET_BYPASS_MODE, UNI_RRO_SET_BYPASS_MODE,
UNI_RRO_SET_TXFREE_PATH, UNI_RRO_SET_TXFREE_PATH,
UNI_RRO_DEL_BA_SESSION,
UNI_RRO_SET_FLUSH_TIMEOUT
}; };
enum{ enum{
......
...@@ -207,6 +207,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, ...@@ -207,6 +207,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
if (!wed_enable) if (!wed_enable)
return 0; return 0;
dev->has_rro = true;
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
if (hif2) if (hif2)
...@@ -228,14 +230,27 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, ...@@ -228,14 +230,27 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs + wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
MT_TXQ_RING_BASE(0) + MT_TXQ_RING_BASE(0) +
MT7996_TXQ_BAND2 * MT_RING_SIZE; MT7996_TXQ_BAND2 * MT_RING_SIZE;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + if (dev->has_rro) {
MT_RXQ_RING_BASE(0) + wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE; MT_RXQ_RING_BASE(0) +
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1; MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
} else {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
}
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
MT7996_RXQ_BAND0 * MT_RING_SIZE;
wed->wlan.id = 0x7991; wed->wlan.id = 0x7991;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1; wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
} else { } else {
wed->wlan.hw_rro = dev->has_rro; /* default on */
wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR; wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR; wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) + wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
...@@ -247,6 +262,16 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, ...@@ -247,6 +262,16 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) + MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
MT7996_RXQ_BAND0 * MT_RING_SIZE; MT7996_RXQ_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
wed->wlan.rx_nbuf = 65536; wed->wlan.rx_nbuf = 65536;
wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576; wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576;
wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE); wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
...@@ -254,11 +279,25 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, ...@@ -254,11 +279,25 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1; wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1; wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1; wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1; wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; if (dev->has_rro) {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
} else {
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
}
dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
} }
wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE; wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
...@@ -273,8 +312,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, ...@@ -273,8 +312,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
wed->wlan.offload_enable = mt76_mmio_wed_offload_enable; wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
wed->wlan.offload_disable = mt76_mmio_wed_offload_disable; wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
dev->mt76.rx_token_size += wed->wlan.rx_npkt;
if (mtk_wed_device_attach(wed)) if (mtk_wed_device_attach(wed))
return 0; return 0;
...@@ -434,10 +471,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) ...@@ -434,10 +471,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance) irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
{ {
struct mt7996_dev *dev = dev_instance; struct mt7996_dev *dev = dev_instance;
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
if (mtk_wed_device_active(wed)) if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_irq_set_mask(wed, 0); mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
else else
mt76_wr(dev, MT_INT_MASK_CSR, 0); mt76_wr(dev, MT_INT_MASK_CSR, 0);
......
...@@ -50,6 +50,22 @@ ...@@ -50,6 +50,22 @@
#define MT7996_BASIC_RATES_TBL 11 #define MT7996_BASIC_RATES_TBL 11
#define MT7996_BEACON_RATES_TBL 25 #define MT7996_BEACON_RATES_TBL 25
#define MT7996_RRO_MAX_SESSION 1024
#define MT7996_RRO_WINDOW_MAX_LEN 1024
#define MT7996_RRO_ADDR_ELEM_LEN 128
#define MT7996_RRO_BA_BITMAP_LEN 2
#define MT7996_RRO_BA_BITMAP_CR_SIZE ((MT7996_RRO_MAX_SESSION * 128) / \
MT7996_RRO_BA_BITMAP_LEN)
#define MT7996_RRO_BA_BITMAP_SESSION_SIZE (MT7996_RRO_MAX_SESSION / \
MT7996_RRO_ADDR_ELEM_LEN)
#define MT7996_RRO_WINDOW_MAX_SIZE (MT7996_RRO_WINDOW_MAX_LEN * \
MT7996_RRO_BA_BITMAP_SESSION_SIZE)
#define MT7996_RX_BUF_SIZE (1800 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
struct mt7996_vif; struct mt7996_vif;
struct mt7996_sta; struct mt7996_sta;
struct mt7996_dfs_pulse; struct mt7996_dfs_pulse;
...@@ -79,6 +95,16 @@ enum mt7996_rxq_id { ...@@ -79,6 +95,16 @@ enum mt7996_rxq_id {
MT7996_RXQ_BAND0 = 4, MT7996_RXQ_BAND0 = 4,
MT7996_RXQ_BAND1 = 4,/* unused */ MT7996_RXQ_BAND1 = 4,/* unused */
MT7996_RXQ_BAND2 = 5, MT7996_RXQ_BAND2 = 5,
MT7996_RXQ_RRO_BAND0 = 8,
MT7996_RXQ_RRO_BAND1 = 8,/* unused */
MT7996_RXQ_RRO_BAND2 = 6,
MT7996_RXQ_MSDU_PG_BAND0 = 10,
MT7996_RXQ_MSDU_PG_BAND1 = 11,
MT7996_RXQ_MSDU_PG_BAND2 = 12,
MT7996_RXQ_TXFREE0 = 9,
MT7996_RXQ_TXFREE1 = 9,
MT7996_RXQ_TXFREE2 = 7,
MT7996_RXQ_RRO_IND = 0,
}; };
struct mt7996_twt_flow { struct mt7996_twt_flow {
...@@ -147,6 +173,15 @@ struct mt7996_hif { ...@@ -147,6 +173,15 @@ struct mt7996_hif {
int irq; int irq;
}; };
struct mt7996_wed_rro_addr {
u32 head_low;
u32 head_high : 4;
u32 count: 11;
u32 oor: 1;
u32 rsv : 8;
u32 signature : 8;
};
struct mt7996_phy { struct mt7996_phy {
struct mt76_phy *mt76; struct mt76_phy *mt76;
struct mt7996_dev *dev; struct mt7996_dev *dev;
...@@ -226,6 +261,22 @@ struct mt7996_dev { ...@@ -226,6 +261,22 @@ struct mt7996_dev {
bool tbtc_support:1; bool tbtc_support:1;
bool flash_mode:1; bool flash_mode:1;
bool has_eht:1; bool has_eht:1;
bool has_rro:1;
struct {
struct {
void *ptr;
dma_addr_t phy_addr;
} ba_bitmap[MT7996_RRO_BA_BITMAP_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} addr_elem[MT7996_RRO_ADDR_ELEM_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} session;
} wed_rro;
bool ibf; bool ibf;
u8 fw_debug_wm; u8 fw_debug_wm;
...@@ -506,4 +557,8 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); ...@@ -506,4 +557,8 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir); int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
#endif #endif
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt7996_dma_rro_init(struct mt7996_dev *dev);
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
#endif #endif
...@@ -39,6 +39,38 @@ enum base_rev { ...@@ -39,6 +39,38 @@ enum base_rev {
#define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)]) #define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
/* RRO TOP */
#define MT_RRO_TOP_BASE 0xA000
#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8)
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C)
#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31)
#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C)
#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60)
#define MT_RRO_PARTICULAR_CONFG_EN BIT(31)
#define MT_RRO_PARTICULAR_SID GENMASK(30, 16)
#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70)
#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74)
#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204)
#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0)
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
#define MT_MCU_INT_EVENT 0x2108 #define MT_MCU_INT_EVENT 0x2108
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
...@@ -398,6 +430,7 @@ enum base_rev { ...@@ -398,6 +430,7 @@ enum base_rev {
#define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300) #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_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300)
#define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500) #define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \ #define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
MT_MCUQ_ID(q) * 0x4) MT_MCUQ_ID(q) * 0x4)
...@@ -425,6 +458,14 @@ enum base_rev { ...@@ -425,6 +458,14 @@ enum base_rev {
#define MT_INT_MCU_CMD BIT(29) #define MT_INT_MCU_CMD BIT(29)
#define MT_INT_RX_TXFREE_EXT BIT(26) #define MT_INT_RX_TXFREE_EXT BIT(26)
#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
#define MT_INT_RX_DONE_RRO_IND BIT(11)
#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
#define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)]) #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_TX_MCU(q) (dev->q_int_mask[(q)])
...@@ -432,20 +473,31 @@ enum base_rev { ...@@ -432,20 +473,31 @@ enum base_rev {
MT_INT_RX(MT_RXQ_MCU_WA)) MT_INT_RX(MT_RXQ_MCU_WA))
#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \ #define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
MT_INT_RX(MT_RXQ_MAIN_WA)) MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \ #define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
MT_INT_RX(MT_RXQ_BAND1_WA) | \ MT_INT_RX(MT_RXQ_BAND1_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA)) MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \ #define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \
MT_INT_RX(MT_RXQ_BAND2_WA) | \ MT_INT_RX(MT_RXQ_BAND2_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA)) MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
MT_INT_RX(MT_RXQ_RRO_BAND1) | \
MT_INT_RX(MT_RXQ_RRO_BAND2) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \ #define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
MT_INT_BAND0_RX_DONE | \ MT_INT_BAND0_RX_DONE | \
MT_INT_BAND1_RX_DONE | \ MT_INT_BAND1_RX_DONE | \
MT_INT_BAND2_RX_DONE) MT_INT_BAND2_RX_DONE | \
MT_INT_RRO_RX_DONE)
#define MT_INT_TX_DONE_FWDL BIT(26) #define MT_INT_TX_DONE_FWDL BIT(26)
#define MT_INT_TX_DONE_MCU_WM BIT(27) #define MT_INT_TX_DONE_MCU_WM BIT(27)
...@@ -558,6 +610,8 @@ enum base_rev { ...@@ -558,6 +610,8 @@ enum base_rev {
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) #define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
#define MT_HW_REV 0x70010204 #define MT_HW_REV 0x70010204
#define MT_HW_REV1 0x8a00
#define MT_WF_SUBSYS_RST 0x70028600 #define MT_WF_SUBSYS_RST 0x70028600
/* PCIE MAC */ /* PCIE MAC */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment