diff mbox

occ: Fix potential race when clearing occ interrupt status

Message ID 1424138850.28071.650883082111.1.gpush@pablo
State Superseded
Headers show

Commit Message

Jeremy Kerr Feb. 17, 2015, 2:07 a.m. UTC
Currently, the occ_interrupt handler will clear the interrupt bit along
with the interrupt reason. If an irq has occurred between the read and
the clear, we'll mask out interrupt bit for that new event

This change checks the reason bits after clearing the interrupt bit. If
any are set, we re-set the interrupt bit to trigger another interrupt.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
 hw/occ.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Benjamin Herrenschmidt Feb. 17, 2015, 2:25 a.m. UTC | #1
On Tue, 2015-02-17 at 10:07 +0800, Jeremy Kerr wrote:
> +       rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
> +       if (!rc && ireg & OCB_OCI_OCIMISC_MASK)
> +               xscom_write(chip_id, OCB_OCI_OCCMISC_OR, OCB_OCI_OCIMISC_IRQ);
>  }

I prefer if you used () above, ie

	if (!rc && (ireg & OCB_OCI...))


I realize that && has the lowest precedence above but still ...

Cheers,
Ben.
diff mbox

Patch

diff --git a/hw/occ.c b/hw/occ.c
index 5d0e34d..53b4625 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -533,6 +533,8 @@  static struct fsp_client fsp_occ_client = {
 #define OCB_OCI_OCIMISC_IRQ		PPC_BIT(0)
 #define OCB_OCI_OCIMISC_IRQ_TMGT	PPC_BIT(1)
 #define OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY	PPC_BIT(15)
+#define OCB_OCI_OCIMISC_MASK		(OCB_OCI_OCIMISC_IRQ_TMGT | \
+					 OCB_OCI_OCIMISC_IRQ_OPAL_DUMMY )
 
 void occ_send_dummy_interrupt(void)
 {
@@ -570,6 +572,14 @@  void occ_interrupt(uint32_t chip_id)
 	/* Dispatch */
 	if (ireg & OCB_OCI_OCIMISC_IRQ_TMGT)
 		occ_tmgt_interrupt();
+
+	/* We may have masked-out OCB_OCI_OCIMISC_IRQ in the previous
+	 * OCCMISC_AND write. Check if there are any new source bits set,
+	 * and trigger another interrupt if so.
+	 */
+	rc = xscom_read(chip_id, OCB_OCI_OCCMISC, &ireg);
+	if (!rc && ireg & OCB_OCI_OCIMISC_MASK)
+		xscom_write(chip_id, OCB_OCI_OCCMISC_OR, OCB_OCI_OCIMISC_IRQ);
 }
 
 void occ_fsp_init(void)