Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Aug 2006 12:18:05 GMT
From:      Paolo Pisati <piso@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 104682 for review
Message-ID:  <200608211218.k7LCI57T080662@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=104682

Change 104682 by piso@piso_newluxor on 2006/08/21 12:17:22

	Make the stray logic MI: the only MD parts
	remaining is the function that scans&return all
	the interrupt events (in i386 is walk_intr_src()),
	and 2 low level interrupt functions (ie_enable() and
	ie_pending()).
	
	Moreover, struct intr_event got a new field:
	
	int		(*ie_pending)(void *);
	
	much like ie_enable(), but this time it points
	to the low level code that checks if an interrupt source
	is still pending, and intr_event_create() was extended 
	to accept *ie_pending() while declaring a new interrupt 
	event.

Affected files ...

.. //depot/projects/soc2006/intr_filter/amd64/amd64/intr_machdep.c#6 edit
.. //depot/projects/soc2006/intr_filter/arm/arm/intr.c#5 edit
.. //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#12 edit
.. //depot/projects/soc2006/intr_filter/ia64/ia64/interrupt.c#6 edit
.. //depot/projects/soc2006/intr_filter/kern/kern_intr.c#15 edit
.. //depot/projects/soc2006/intr_filter/powerpc/powerpc/intr_machdep.c#7 edit
.. //depot/projects/soc2006/intr_filter/sparc64/sparc64/intr_machdep.c#7 edit
.. //depot/projects/soc2006/intr_filter/sys/interrupt.h#6 edit

Differences ...

==== //depot/projects/soc2006/intr_filter/amd64/amd64/intr_machdep.c#6 (text+ko) ====

@@ -88,7 +88,9 @@
 	if (interrupt_sources[vector] != NULL)
 		return (EEXIST);
 	error = intr_event_create(&isrc->is_event, isrc, 0,
-	    (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
+	    (mask_fn)isrc->is_pic->pic_enable_source, 
+	    (int (*)(void *))isrc->is_pic->pic_source_pending, 
+	    "irq%d:", vector);
 	if (error)
 		return (error);
 	mtx_lock_spin(&intr_table_lock);

==== //depot/projects/soc2006/intr_filter/arm/arm/intr.c#5 (text+ko) ====

@@ -69,7 +69,7 @@
 	event = intr_events[irq];
 	if (event == NULL) {
 		error = intr_event_create(&event, (void *)irq, 0,
-		    (void (*)(void *))arm_unmask_irq, "intr%d:", irq);
+		    (void (*)(void *))arm_unmask_irq, NULL, "intr%d:", irq);
 		if (error)
 			return;
 		intr_events[irq] = event;

==== //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#12 (text+ko) ====

@@ -64,8 +64,7 @@
 static struct intsrc *interrupt_sources[NUM_IO_INTS];
 static struct mtx intr_table_lock;
 
-static struct callout callout_handle;
-static int backoff = 1;
+extern struct callout stray_callout_handle;
 
 #ifdef SMP
 static int assign_cpu;
@@ -99,7 +98,9 @@
 	if (interrupt_sources[vector] != NULL)
 		return (EEXIST);
 	error = intr_event_create(&isrc->is_event, isrc, 0,
-	    (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
+	    (mask_fn)isrc->is_pic->pic_enable_source, 
+	    (int (*)(void *))isrc->is_pic->pic_source_pending,
+	    "irq%d:", vector);
 	if (error)
 		return (error);
 	mtx_lock_spin(&intr_table_lock);
@@ -176,69 +177,22 @@
 	return (isrc->is_pic->pic_config_intr(isrc, trig, pol));
 }
 
-static struct intsrc *
+/* Stray detection MD code */
+static struct intr_event *
 walk_intr_src(void) {
+	struct intsrc *isrc;
 	static int i = 0;
 
 	for (; i<NUM_IO_INTS; ) {
 		int j = i++;
-		if (interrupt_sources[j] != NULL)
-			return (interrupt_sources[j]);
+		isrc = interrupt_sources[j];
+		if (isrc != NULL)
+			return (isrc->is_event);
 	}
 	i = 0;
 	return (NULL);
 }
 
-static void
-stray_detection(void *_arg) 
-{
-	struct intsrc *isrc;
-	struct intr_event *ie;
-	void *(*walk_src)(void) = _arg;
-	int thread;
-
-/* 
- * XXX adding a parameter to struct intr_event, will make this MI, but
- * to do that it's necessary to break intr_event_create and add an arg like:
- *
- * 	int (*is_pending)(void *);
- *
- * in that case, walk_src will return a "struct intr_event *", and...
- */
-
-	/* analyze all the interrupt sources... */
-	while ((isrc = walk_src()) != NULL) {
-		ie = isrc->is_event;
-		/* is this interrupt marked as being throttled? */
-		if (ie != NULL && ie->ie_count == INT_MAX) {
-			/* and is the interrupt still pending? */
-			/* XXX ... here we'll call "ie->is_pending(ie->ie_source)" */
-			if (isrc->is_pic->pic_source_pending(isrc)) {
-				/* 
-				 * yes, it's still pending: call filters...
-				 */
-				thread = intr_filter_loop(ie, NULL /* XXX frame */ );
-				if (thread & FILTER_STRAY) {
-					/* 
-					 * no filter claimed the intr, 
-					 * backoff with a longer timeout 
-					 */
-					backoff++; // XXX we need thresholds...
-					callout_reset(&callout_handle, hz*backoff, 
-						      &stray_detection, _arg);
-					continue;
-				}
-			}
-			/*
-			 * a filter claimed the intr, or the intr was not
-			 * pending anymore: unmask it
-			 */
-			ie->ie_count = 0;
-			ie->ie_enable(ie->ie_source);
-		}
-	}
-}
-
 void
 intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
 {
@@ -304,7 +258,7 @@
 		printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", ie->ie_name);
 		ie->ie_count = INT_MAX;    
 		mtx_lock_spin(&intr_table_lock);
-		callout_reset(&callout_handle, hz, &stray_detection, &walk_intr_src);
+		callout_reset(&stray_callout_handle, hz, &stray_detection, &walk_intr_src);
 		mtx_unlock_spin(&intr_table_lock);
 	}
 
@@ -392,7 +346,7 @@
 	intrcnt_setname("???", 0);
 	intrcnt_index = 1;
 	mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
-	callout_init_mtx(&callout_handle, &intr_table_lock, 0);
+	callout_init_mtx(&stray_callout_handle, &intr_table_lock, 0);
 	// XXX - we don't drain the callout...
 }
 SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)

==== //depot/projects/soc2006/intr_filter/ia64/ia64/interrupt.c#6 (text+ko) ====

@@ -320,7 +320,7 @@
 			bcopy(name, intrname, strlen(name));
 		}
 		errcode = intr_event_create(&i->event, (void *)vector, 0,
-		    (void (*)(void *))ia64_send_eoi, "intr:");
+		    (void (*)(void *))ia64_send_eoi, NULL, "intr:");
 		if (errcode) {
 			free(i, M_DEVBUF);
 			return errcode;

==== //depot/projects/soc2006/intr_filter/kern/kern_intr.c#15 (text+ko) ====

@@ -58,6 +58,10 @@
 #include <ddb/db_sym.h>
 #endif
 
+/* Stray detection */
+struct callout stray_callout_handle;
+static int backoff = 1;
+
 /*
  * Describe an interrupt thread.  There is one of these per interrupt event.
  */
@@ -228,7 +232,7 @@
 
 int
 intr_event_create(struct intr_event **event, void *source, int flags,
-    void (*enable)(void *), const char *fmt, ...)
+    void (*enable)(void *), int (*pending)(void *), const char *fmt, ...)
 {
 	struct intr_event *ie;
 	va_list ap;
@@ -239,6 +243,7 @@
 	ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO);
 	ie->ie_source = source;
 	ie->ie_enable = enable;
+	ie->ie_pending = pending;	
 	ie->ie_flags = flags;
 	TAILQ_INIT(&ie->ie_handlers);
 	mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
@@ -561,7 +566,7 @@
 			return (EINVAL);
 	} else {
 		error = intr_event_create(&ie, NULL, IE_SOFT, NULL,
-		    "swi%d:", pri);
+		    NULL, "swi%d:", pri);
 		if (error)
 			return (error);
 		if (eventp != NULL)
@@ -826,7 +831,44 @@
 	return (FILTER_STRAY);
 }
 
+/* Stray storm detection */
+void
+stray_detection(void *_arg) 
+{
+	struct intr_event *ie;
+	void *(*walk_src)(void) = _arg;
+	int thread;
 
+	/* analyze all the interrupt sources... */
+	while ((ie = walk_src()) != NULL) {
+		/* is this interrupt marked as being throttled? */
+		if (ie != NULL && ie->ie_count == INT_MAX) {
+			/* and is the interrupt still pending? */
+			if (ie->ie_pending(ie->ie_source)) {
+				/* 
+				 * yes, it's still pending: call filters...
+				 */
+				thread = intr_filter_loop(ie, NULL /* XXX frame */ );
+				if (thread & FILTER_STRAY) {
+					/* 
+					 * no filter claimed the intr, 
+					 * backoff with a longer timeout 
+					 */
+					backoff++; // XXX we need thresholds...
+					callout_reset(&stray_callout_handle, hz*backoff, 
+						      &stray_detection, _arg);
+					continue;
+				}
+			}
+			/*
+			 * a filter claimed the intr, or the intr was not
+			 * pending anymore: unmask it
+			 */
+			ie->ie_count = 0;
+			ie->ie_enable(ie->ie_source);
+		}
+	}
+}
 
 #ifdef DDB
 /*

==== //depot/projects/soc2006/intr_filter/powerpc/powerpc/intr_machdep.c#7 (text+ko) ====

@@ -185,7 +185,7 @@
 	mtx_unlock_spin(&intr_table_lock);
 	if (event == NULL) {
 		error = intr_event_create(&event, (void *)irq, 0,
-		    (void (*)(void *))irq_enable, "irq%d:", irq);
+		    (void (*)(void *))irq_enable, NULL, "irq%d:", irq);
 		if (error)
 			return (error);
 

==== //depot/projects/soc2006/intr_filter/sparc64/sparc64/intr_machdep.c#7 (text+ko) ====

@@ -275,7 +275,7 @@
 	mtx_unlock_spin(&intr_table_lock);
 	if (ie == NULL) {
 		errcode = intr_event_create(&ie, (void *)(intptr_t)vec, 0, NULL,
-		    "vec%d:", vec);
+		    NULL, "vec%d:", vec);
 		if (errcode)
 			return (errcode);
 		mtx_lock_spin(&intr_table_lock);

==== //depot/projects/soc2006/intr_filter/sys/interrupt.h#6 (text+ko) ====

@@ -74,6 +74,7 @@
 	void		*ie_source;	/* Cookie used by MD code. */
 	struct intr_thread *ie_thread;	/* Thread we are connected to. */
 	void		(*ie_enable)(void *);
+	int		(*ie_pending)(void *);
 	int		ie_flags;
 	int		ie_count;	/* Loop counter. */
 	int		ie_warned;	/* Warned about interrupt storm. */
@@ -115,13 +116,15 @@
 void	db_dump_intr_event(struct intr_event *ie, int handlers);
 #endif
 int     intr_filter_loop(struct intr_event *ie, struct trapframe *frame);
+void    stray_detection(void *_arg);
 u_char	intr_priority(enum intr_type flags);
 int	intr_event_add_handler(struct intr_event *ie, const char *name,
 	    driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri, enum intr_type flags,
 	    void **cookiep);
 int	intr_event_create(struct intr_event **event, void *source,
-	    int flags, void (*enable)(void *), const char *fmt, ...)
-	    __printflike(5, 6);
+	    int flags, void (*enable)(void *), int (*pending)(void *),
+            const char *fmt, ...)
+	    __printflike(6, 7);
 int	intr_event_destroy(struct intr_event *ie);
 int	intr_event_remove_handler(void *cookie);
 int	intr_event_schedule_thread(struct intr_event *ie);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608211218.k7LCI57T080662>