Module Name:    src
Committed By:   jmcneill
Date:           Mon Feb 17 11:14:49 UTC 2025

Modified Files:
        src/sys/arch/powerpc/pic: intr.c picvar.h

Log Message:
powerpc: Don't enable interrupts before calling cascaded intr handler.

Before calling a normal interrupt handler, the pic code adjusts cpl and
enables interrupts. Don't do this with interrupt sources that feed
cascaded pics as the resulting handler will do it anyway, and it can
result in multiple interrupts firing on the parent pic just to service
a single interrupt on the child.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/powerpc/pic/intr.c
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/powerpc/pic/picvar.h

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/pic/intr.c
diff -u src/sys/arch/powerpc/pic/intr.c:1.36 src/sys/arch/powerpc/pic/intr.c:1.37
--- src/sys/arch/powerpc/pic/intr.c:1.36	Sun Feb 16 09:55:00 2025
+++ src/sys/arch/powerpc/pic/intr.c	Mon Feb 17 11:14:49 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.36 2025/02/16 09:55:00 jmcneill Exp $ */
+/*	$NetBSD: intr.c,v 1.37 2025/02/17 11:14:49 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2007 Michael Lorenz
@@ -29,7 +29,7 @@
 #define __INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.36 2025/02/16 09:55:00 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.37 2025/02/17 11:14:49 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_interrupt.h"
@@ -180,10 +180,12 @@ intr_establish_xname(int hwirq, int type
 		    hwirq, type);
 
 	struct intr_source * const is = &intrsources[virq];
+	const bool cascaded = ih_fun == pic_handle_intr;
 
 	switch (is->is_type) {
 	case IST_NONE:
 		is->is_type = type;
+		is->is_cascaded = cascaded;
 		break;
 	case IST_EDGE_FALLING:
 	case IST_EDGE_RISING:
@@ -193,10 +195,15 @@ intr_establish_xname(int hwirq, int type
 			break;
 		/* FALLTHROUGH */
 	case IST_PULSE:
-		if (type != IST_NONE)
+		if (type != IST_NONE) {
 			panic("intr_establish: can't share %s with %s",
 			    intr_typename(is->is_type),
 			    intr_typename(type));
+		}
+		if (cascaded != is->is_cascaded) {
+			panic("intr_establish: can't share cascaded with "
+			    "non-cascaded interrupt");
+		}
 		break;
 	}
 	if (is->is_hand == NULL) {
@@ -519,11 +526,15 @@ again:
 		struct intr_source * const is = &intrsources[virq];
 		struct pic_ops * const pic = is->is_pic;
 
-		splraise(is->is_ipl);
-		mtmsr(emsr);
+		if (!is->is_cascaded) {
+			splraise(is->is_ipl);
+			mtmsr(emsr);
+		}
 		intr_deliver(is, virq);
-		mtmsr(dmsr);
-		ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
+		if (!is->is_cascaded) {
+			mtmsr(dmsr);
+			ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
+		}
 
 		pic->pic_reenable_irq(pic, is->is_hwirq - pic->pic_intrbase,
 		    is->is_type);
@@ -587,11 +598,15 @@ pic_handle_intr(void *cookie)
 			ci->ci_ipending &= ~v_imen;
 			ci->ci_idepth++;
 
-			splraise(is->is_ipl);
-			mtmsr(msr | PSL_EE);
+			if (!is->is_cascaded) {
+				splraise(is->is_ipl);
+				mtmsr(msr | PSL_EE);
+			}
 			intr_deliver(is, virq);
-			mtmsr(msr & ~PSL_EE);
-			ci->ci_cpl = pcpl;
+			if (!is->is_cascaded) {
+				mtmsr(msr & ~PSL_EE);
+				ci->ci_cpl = pcpl;
+			}
 
 			ci->ci_data.cpu_nintr++;
 			ci->ci_idepth--;

Index: src/sys/arch/powerpc/pic/picvar.h
diff -u src/sys/arch/powerpc/pic/picvar.h:1.13 src/sys/arch/powerpc/pic/picvar.h:1.14
--- src/sys/arch/powerpc/pic/picvar.h:1.13	Mon Mar 22 01:36:10 2021
+++ src/sys/arch/powerpc/pic/picvar.h	Mon Feb 17 11:14:49 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: picvar.h,v 1.13 2021/03/22 01:36:10 rin Exp $ */
+/*	$NetBSD: picvar.h,v 1.14 2025/02/17 11:14:49 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2007 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.13 2021/03/22 01:36:10 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.14 2025/02/17 11:14:49 jmcneill Exp $");
 
 #ifndef PIC_VAR_H
 #define PIC_VAR_H
@@ -61,6 +61,7 @@ struct intr_source {
 	imask_t is_mask;
 	struct intrhand *is_hand;
 	struct pic_ops *is_pic;
+	bool is_cascaded;
 	struct evcnt is_ev;
 	char is_evname[16];
 	char is_intrid[INTRIDBUF];

Reply via email to