aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMadalin Bucur <madalin.bucur@nxp.com>2018-12-21 09:41:42 -0500
committerLi Yang <leoyang.li@nxp.com>2019-01-18 17:48:35 -0500
commit89857a8a5c89a406b967ab2be7bd2ccdbe75e73d (patch)
tree2f681909969d9cc805649765bed039b09508f644
parentbfeffd155283772bbe78c6a05dec7c0128ee500c (diff)
soc: fsl: qbman: avoid race in clearing QMan interrupt
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>
-rw-r--r--drivers/soc/fsl/qbman/qman.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index 52c153cd795a..636f83f781f5 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work);
1143static irqreturn_t portal_isr(int irq, void *ptr) 1143static irqreturn_t portal_isr(int irq, void *ptr)
1144{ 1144{
1145 struct qman_portal *p = ptr; 1145 struct qman_portal *p = ptr;
1146
1147 u32 clear = QM_DQAVAIL_MASK | p->irq_sources;
1148 u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources; 1146 u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources;
1147 u32 clear = 0;
1149 1148
1150 if (unlikely(!is)) 1149 if (unlikely(!is))
1151 return IRQ_NONE; 1150 return IRQ_NONE;
1152 1151
1153 /* DQRR-handling if it's interrupt-driven */ 1152 /* DQRR-handling if it's interrupt-driven */
1154 if (is & QM_PIRQ_DQRI) 1153 if (is & QM_PIRQ_DQRI) {
1155 __poll_portal_fast(p, QMAN_POLL_LIMIT); 1154 __poll_portal_fast(p, QMAN_POLL_LIMIT);
1155 clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI;
1156 }
1156 /* Handling of anything else that's interrupt-driven */ 1157 /* Handling of anything else that's interrupt-driven */
1157 clear |= __poll_portal_slow(p, is); 1158 clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW;
1158 qm_out(&p->p, QM_REG_ISR, clear); 1159 qm_out(&p->p, QM_REG_ISR, clear);
1159 return IRQ_HANDLED; 1160 return IRQ_HANDLED;
1160} 1161}