PERFORCE change 104682 for review
Paolo Pisati
piso at FreeBSD.org
Mon Aug 21 12:18:10 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=104682
Change 104682 by piso at 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);
More information about the p4-projects
mailing list