mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 18:47:06 +00:00
93 lines
2.9 KiB
Diff
93 lines
2.9 KiB
Diff
|
From 3affa310de523d63e52ea8e2efb3c476df29e414 Mon Sep 17 00:00:00 2001
|
||
|
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||
|
Date: Tue, 29 Oct 2024 13:17:09 +0100
|
||
|
Subject: [PATCH 1/2] net: airoha: Read completion queue data in
|
||
|
airoha_qdma_tx_napi_poll()
|
||
|
|
||
|
In order to avoid any possible race, read completion queue head and
|
||
|
pending entry in airoha_qdma_tx_napi_poll routine instead of doing it in
|
||
|
airoha_irq_handler. Remove unused airoha_tx_irq_queue unused fields.
|
||
|
This is a preliminary patch to add Qdisc offload for airoha_eth driver.
|
||
|
|
||
|
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||
|
Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-1-96ad1686b946@kernel.org
|
||
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||
|
---
|
||
|
drivers/net/ethernet/mediatek/airoha_eth.c | 31 +++++++++-------------
|
||
|
1 file changed, 13 insertions(+), 18 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||
|
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||
|
@@ -752,11 +752,9 @@ struct airoha_tx_irq_queue {
|
||
|
struct airoha_qdma *qdma;
|
||
|
|
||
|
struct napi_struct napi;
|
||
|
- u32 *q;
|
||
|
|
||
|
int size;
|
||
|
- int queued;
|
||
|
- u16 head;
|
||
|
+ u32 *q;
|
||
|
};
|
||
|
|
||
|
struct airoha_hw_stats {
|
||
|
@@ -1656,25 +1654,31 @@ static int airoha_qdma_init_rx(struct ai
|
||
|
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
|
||
|
{
|
||
|
struct airoha_tx_irq_queue *irq_q;
|
||
|
+ int id, done = 0, irq_queued;
|
||
|
struct airoha_qdma *qdma;
|
||
|
struct airoha_eth *eth;
|
||
|
- int id, done = 0;
|
||
|
+ u32 status, head;
|
||
|
|
||
|
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||
|
qdma = irq_q->qdma;
|
||
|
id = irq_q - &qdma->q_tx_irq[0];
|
||
|
eth = qdma->eth;
|
||
|
|
||
|
- while (irq_q->queued > 0 && done < budget) {
|
||
|
- u32 qid, last, val = irq_q->q[irq_q->head];
|
||
|
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id));
|
||
|
+ head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||
|
+ head = head % irq_q->size;
|
||
|
+ irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||
|
+
|
||
|
+ while (irq_queued > 0 && done < budget) {
|
||
|
+ u32 qid, last, val = irq_q->q[head];
|
||
|
struct airoha_queue *q;
|
||
|
|
||
|
if (val == 0xff)
|
||
|
break;
|
||
|
|
||
|
- irq_q->q[irq_q->head] = 0xff; /* mark as done */
|
||
|
- irq_q->head = (irq_q->head + 1) % irq_q->size;
|
||
|
- irq_q->queued--;
|
||
|
+ irq_q->q[head] = 0xff; /* mark as done */
|
||
|
+ head = (head + 1) % irq_q->size;
|
||
|
+ irq_queued--;
|
||
|
done++;
|
||
|
|
||
|
last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||
|
@@ -2026,20 +2030,11 @@ static irqreturn_t airoha_irq_handler(in
|
||
|
|
||
|
if (intr[0] & INT_TX_MASK) {
|
||
|
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||
|
- struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
|
||
|
- u32 status, head;
|
||
|
-
|
||
|
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||
|
continue;
|
||
|
|
||
|
airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
|
||
|
TX_DONE_INT_MASK(i));
|
||
|
-
|
||
|
- status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||
|
- head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||
|
- irq_q->head = head % irq_q->size;
|
||
|
- irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||
|
-
|
||
|
napi_schedule(&qdma->q_tx_irq[i].napi);
|
||
|
}
|
||
|
}
|