| From 174993ad4d4e5da02fd9ccaedf7cd586711dda81 Mon Sep 17 00:00:00 2001 |
| From: Madalin Bucur <madalin.bucur@nxp.com> |
| Date: Fri, 21 Dec 2018 16:41:42 +0200 |
| Subject: soc: fsl: qbman: avoid race in clearing QMan interrupt |
| |
| [ Upstream commit 89857a8a5c89a406b967ab2be7bd2ccdbe75e73d ] |
| |
| By clearing all interrupt sources, not only those that |
| already occurred, the existing code may acknowledge by |
| mistake interrupts that occurred after the code checks |
| for them. |
| |
| Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com> |
| Signed-off-by: Roy Pledge <roy.pledge@nxp.com> |
| Signed-off-by: Li Yang <leoyang.li@nxp.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/soc/fsl/qbman/qman.c | 9 +++++---- |
| 1 file changed, 5 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c |
| index 8cc015183043..a4ac6073c555 100644 |
| --- a/drivers/soc/fsl/qbman/qman.c |
| +++ b/drivers/soc/fsl/qbman/qman.c |
| @@ -1081,18 +1081,19 @@ static void qm_mr_process_task(struct work_struct *work); |
| static irqreturn_t portal_isr(int irq, void *ptr) |
| { |
| struct qman_portal *p = ptr; |
| - |
| - u32 clear = QM_DQAVAIL_MASK | p->irq_sources; |
| u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources; |
| + u32 clear = 0; |
| |
| if (unlikely(!is)) |
| return IRQ_NONE; |
| |
| /* DQRR-handling if it's interrupt-driven */ |
| - if (is & QM_PIRQ_DQRI) |
| + if (is & QM_PIRQ_DQRI) { |
| __poll_portal_fast(p, QMAN_POLL_LIMIT); |
| + clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI; |
| + } |
| /* Handling of anything else that's interrupt-driven */ |
| - clear |= __poll_portal_slow(p, is); |
| + clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW; |
| qm_out(&p->p, QM_REG_ISR, clear); |
| return IRQ_HANDLED; |
| } |
| -- |
| 2.19.1 |
| |