From owner-p4-projects@FreeBSD.ORG Mon Aug 21 12:18:10 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 13AF416A4DF; Mon, 21 Aug 2006 12:18:10 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C886F16A4DD for ; Mon, 21 Aug 2006 12:18:09 +0000 (UTC) (envelope-from piso@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9BA5243D67 for ; Mon, 21 Aug 2006 12:18:05 +0000 (GMT) (envelope-from piso@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k7LCI5u8080665 for ; Mon, 21 Aug 2006 12:18:05 GMT (envelope-from piso@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k7LCI57T080662 for perforce@freebsd.org; Mon, 21 Aug 2006 12:18:05 GMT (envelope-from piso@freebsd.org) Date: Mon, 21 Aug 2006 12:18:05 GMT Message-Id: <200608211218.k7LCI57T080662@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to piso@freebsd.org using -f From: Paolo Pisati To: Perforce Change Reviews Cc: Subject: PERFORCE change 104682 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Aug 2006 12:18:10 -0000 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 (; iis_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 #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);