Module Name: src
Committed By: rin
Date: Fri Mar 5 05:35:50 UTC 2021
Modified Files:
src/sys/arch/powerpc/ibm4xx: pic_uic.c
Log Message:
Fix hard freeze in pic_handle_intr() for PPC_IBM403.
Not clearly documented in reference manual, but DCR_EXISR register is
not updated immediately after some bits are cleared by mtdcr, no matter
whether sync (= eieio) and/or isync are issued.
Therefore, we have to manage our own status mask in the interrupt handler.
This is what we did in obsoleted powerpc/ibm4xx/intr.c.
With this change, my Explora 451 works just fine with serial console!
Fix for framebuffer console will be committed soon.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/powerpc/ibm4xx/pic_uic.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/powerpc/ibm4xx/pic_uic.c
diff -u src/sys/arch/powerpc/ibm4xx/pic_uic.c:1.8 src/sys/arch/powerpc/ibm4xx/pic_uic.c:1.9
--- src/sys/arch/powerpc/ibm4xx/pic_uic.c:1.8 Sat Feb 27 20:43:58 2021
+++ src/sys/arch/powerpc/ibm4xx/pic_uic.c Fri Mar 5 05:35:50 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: pic_uic.c,v 1.8 2021/02/27 20:43:58 rin Exp $ */
+/* $NetBSD: pic_uic.c,v 1.9 2021/03/05 05:35:50 rin Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pic_uic.c,v 1.8 2021/02/27 20:43:58 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pic_uic.c,v 1.9 2021/03/05 05:35:50 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_ppcarch.h"
@@ -73,6 +73,19 @@ static void uic_establish_irq(struct pic
struct uic {
uint32_t uic_intr_enable; /* cached intr enable mask */
+#ifdef PPC_IBM403
+ /*
+ * Not clearly documented in reference manual, but DCR_EXISR
+ * register is not updated immediately after some bits are
+ * cleared by mtdcr, no matter whether sync (= eieio) and/or
+ * isync are issued.
+ *
+ * Therefore, we have to manage our own status mask in the
+ * interrupt handler; see uic_{ack,get}_irq() for more details.
+ * This is what we did in obsoleted powerpc/ibm4xx/intr.c.
+ */
+ uint32_t uic_intr_status;
+#endif
uint32_t (*uic_mf_intr_status)(void);
uint32_t (*uic_mf_intr_enable)(void);
void (*uic_mt_intr_enable)(uint32_t);
@@ -356,15 +369,26 @@ uic_ack_irq(struct pic_ops *pic, int irq
struct uic * const uic = pic->pic_cookie;
const uint32_t irqmask = IRQ_TO_MASK(irq);
+#ifdef PPC_IBM403
+ uic->uic_intr_status &= ~irqmask;
+#endif
+
(*uic->uic_mt_intr_ack)(irqmask);
}
static int
-uic_get_irq(struct pic_ops *pic, int dummy)
+uic_get_irq(struct pic_ops *pic, int req)
{
struct uic * const uic = pic->pic_cookie;
+#ifdef PPC_IBM403
+ if (req == PIC_GET_IRQ)
+ uic->uic_intr_status = (*uic->uic_mf_intr_status)();
+ const uint32_t irqmask = uic->uic_intr_status;
+#else
const uint32_t irqmask = (*uic->uic_mf_intr_status)();
+#endif
+
if (irqmask == 0)
return 255;
return IRQ_OF_MASK(irqmask);