blob: 9fd2fecdec54b801d56272f3311b2953bb3d1898 [file] [log] [blame]
From d1e33a9f806288794fbf10f04edf2d90ee937de0 Mon Sep 17 00:00:00 2001
From: Cloud Hsu <cloudhsu@google.com>
Date: Tue, 22 Apr 2025 13:04:41 +0800
Subject: [PATCH 1/1] Prevent processing stale DMA data on spurious interrupt
The do...while loop processing DMA data could incorrectly handle
spurious interrupts where no new data was available (wptr == rptr). The
loop would still execute once, incrementing rptr, causing it to process
the entire buffer as stale data and cause the kfifo overflow to drop
data. We have observed this issue on the AMD platform. Replace
do...while loop with while loop to avoid this issue. The drawback of
this fix is that it cannot handle the (wptr == rptr) situation. However,
it is unlikely to happen with a DMA buffer size of 256K Bytes.
The following log shows when the problem occurs.
aspeed_pcc_dma_isr > postcode_cnt: 7773564
aspeed_pcc_dma_isr > kfifo size: 262144
aspeed_pcc_dma_isr > wptr: 29d7c, rptr: 29d7c
aspeed_pcc_dma_isr > spurious interrupt
aspeed_pcc_dma_isr > postcode_cnt: 8035708
aspeed_pcc_dma_isr > kfifo size: 262144
Signed-off-by: Cloud Hsu <cloudhsu@google.com>
---
drivers/soc/aspeed/aspeed-lpc-pcc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/aspeed/aspeed-lpc-pcc.c b/drivers/soc/aspeed/aspeed-lpc-pcc.c
index 038fad83fa76..433e2b80c5cf 100644
--- a/drivers/soc/aspeed/aspeed-lpc-pcc.c
+++ b/drivers/soc/aspeed/aspeed-lpc-pcc.c
@@ -178,14 +178,14 @@ static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg)
wptr = (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR);
rptr = pcc->dma.rptr;
- do {
+ while (rptr != wptr) {
if (kfifo_is_full(fifo))
kfifo_skip(fifo);
kfifo_put(fifo, pcc->dma.virt[rptr]);
rptr = (rptr + 1) % pcc->dma.size;
- } while (rptr != wptr);
+ }
pcc->dma.rptr = rptr;
--
2.49.0.805.g082f7c87e0-goog