| 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 |
| |