Commit e50d4d71 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

wifi: mt76: Add mt76_dma_get_rxdmad_c_buf utility routione



Introduce mt76_dma_get_rxdmad_c_buf routine to process packets received
by HW-RRO v3.1 module.
This is a preliminary patch to introduce SW path for HW-RRO v3.1 module
available on MT7992 chipset.

Co-developed-by: default avatarRex Lu <rex.lu@mediatek.com>
Signed-off-by: default avatarRex Lu <rex.lu@mediatek.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250909-mt7996-rro-rework-v5-15-7d66f6eb7795@kernel.org


Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 7b3c83dd
Loading
Loading
Loading
Loading
+55 −3
Original line number Diff line number Diff line
@@ -427,15 +427,61 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
		wake_up(&dev->tx_wait);
}

static void *
mt76_dma_get_rxdmad_c_buf(struct mt76_dev *dev, struct mt76_queue *q,
			  int idx, int *len, bool *more)
{
	struct mt76_queue_entry *e = &q->entry[idx];
	struct mt76_rro_rxdmad_c *dmad = e->buf;
	u32 data1 = le32_to_cpu(dmad->data1);
	u32 data2 = le32_to_cpu(dmad->data2);
	struct mt76_txwi_cache *t;
	u16 rx_token_id;
	u8 ind_reason;
	void *buf;

	rx_token_id = FIELD_GET(RRO_RXDMAD_DATA2_RX_TOKEN_ID_MASK, data2);
	t = mt76_rx_token_release(dev, rx_token_id);
	if (!t)
		return ERR_PTR(-EAGAIN);

	q = &dev->q_rx[t->qid];
	dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
				SKB_WITH_OVERHEAD(q->buf_size),
				page_pool_get_dma_dir(q->page_pool));

	if (len)
		*len = FIELD_GET(RRO_RXDMAD_DATA1_SDL0_MASK, data1);
	if (more)
		*more = !FIELD_GET(RRO_RXDMAD_DATA1_LS_MASK, data1);

	buf = t->ptr;
	ind_reason = FIELD_GET(RRO_RXDMAD_DATA2_IND_REASON_MASK, data2);
	if (ind_reason == MT_DMA_WED_IND_REASON_REPEAT ||
	    ind_reason == MT_DMA_WED_IND_REASON_OLDPKT) {
		mt76_put_page_pool_buf(buf, false);
		buf = ERR_PTR(-EAGAIN);
	}
	t->ptr = NULL;
	t->dma_addr = 0;

	mt76_put_rxwi(dev, t);

	return buf;
}

static void *
mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
		 int *len, u32 *info, bool *more, bool *drop)
		 int *len, u32 *info, bool *more, bool *drop, bool flush)
{
	struct mt76_queue_entry *e = &q->entry[idx];
	struct mt76_desc *desc = &q->desc[idx];
	u32 ctrl, desc_info, buf1;
	void *buf = e->buf;

	if (mt76_queue_is_wed_rro_rxdmad_c(q) && !flush)
		buf = mt76_dma_get_rxdmad_c_buf(dev, q, idx, len, more);

	if (mt76_queue_is_wed_rro(q))
		goto done;

@@ -516,7 +562,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
	q->tail = (q->tail + 1) % q->ndesc;
	q->queued--;

	return mt76_dma_get_buf(dev, q, idx, len, info, more, drop);
	return mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);
}

static int
@@ -885,10 +931,16 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
		if (!data)
			break;

		if (PTR_ERR(data) == -EAGAIN) {
			done++;
			continue;
		}

		if (mt76_queue_is_wed_rro_ind(q) && dev->drv->rx_rro_ind_process)
			dev->drv->rx_rro_ind_process(dev, data);

		if (mt76_queue_is_wed_rro(q)) {
		if (mt76_queue_is_wed_rro(q) &&
		    !mt76_queue_is_wed_rro_rxdmad_c(q)) {
			done++;
			continue;
		}
+15 −0
Original line number Diff line number Diff line
@@ -58,6 +58,21 @@ struct mt76_wed_rro_desc {
	__le32 buf1;
} __packed __aligned(4);

/* data1 */
#define RRO_RXDMAD_DATA1_LS_MASK		BIT(30)
#define RRO_RXDMAD_DATA1_SDL0_MASK		GENMASK(29, 16)
/* data2 */
#define RRO_RXDMAD_DATA2_RX_TOKEN_ID_MASK	GENMASK(31, 16)
#define RRO_RXDMAD_DATA2_IND_REASON_MASK	GENMASK(15, 12)
/* data3 */
#define RRO_RXDMAD_DATA3_MAGIC_CNT_MASK		GENMASK(31, 28)
struct mt76_rro_rxdmad_c {
	__le32 data0;
	__le32 data1;
	__le32 data2;
	__le32 data3;
};

enum mt76_qsel {
	MT_QSEL_MGMT,
	MT_QSEL_HCCA,
+8 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define MT_WED_RRO_Q_DATA(_n)	__MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n)
#define MT_WED_RRO_Q_MSDU_PG(_n)	__MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n)
#define MT_WED_RRO_Q_IND	__MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
#define MT_WED_RRO_Q_RXDMAD_C	__MT_WED_RRO_Q(MT76_WED_RRO_Q_RXDMAD_C, 0)

struct mt76_dev;
struct mt76_phy;
@@ -71,6 +72,7 @@ enum mt76_wed_type {
	MT76_WED_RRO_Q_DATA,
	MT76_WED_RRO_Q_MSDU_PG,
	MT76_WED_RRO_Q_IND,
	MT76_WED_RRO_Q_RXDMAD_C,
};

struct mt76_bus_ops {
@@ -1794,6 +1796,12 @@ static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND;
}

static inline bool mt76_queue_is_wed_rro_rxdmad_c(struct mt76_queue *q)
{
	return mt76_queue_is_wed_rro(q) &&
	       FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_RXDMAD_C;
}

static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q)
{
	return mt76_queue_is_wed_rro(q) &&