From owner-svn-src-projects@FreeBSD.ORG Wed Oct 27 23:18:26 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 04F201065674; Wed, 27 Oct 2010 23:18:26 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E79968FC0C; Wed, 27 Oct 2010 23:18:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9RNIPt9043363; Wed, 27 Oct 2010 23:18:25 GMT (envelope-from jeff@svn.freebsd.org) Received: (from jeff@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9RNIPAT043359; Wed, 27 Oct 2010 23:18:25 GMT (envelope-from jeff@svn.freebsd.org) Message-Id: <201010272318.o9RNIPAT043359@svn.freebsd.org> From: Jeff Roberson Date: Wed, 27 Oct 2010 23:18:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214435 - in projects/ofed/head/sys: kern ofed/include/linux sys X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Oct 2010 23:18:26 -0000 Author: jeff Date: Wed Oct 27 23:18:25 2010 New Revision: 214435 URL: http://svn.freebsd.org/changeset/base/214435 Log: - Add intr_drain(), a mechanism to wait for any interrupt handlers currently running on an ithread to complete. This is used to synchronize the release of state that may be accessed by interrupt context. - Use intr_drain() in synchronize_irq(). Discussed with: jhb Sponsored by: Isilon Systems, iX Systems, and Panasas. Modified: projects/ofed/head/sys/kern/kern_intr.c projects/ofed/head/sys/ofed/include/linux/hardirq.h projects/ofed/head/sys/sys/interrupt.h Modified: projects/ofed/head/sys/kern/kern_intr.c ============================================================================== --- projects/ofed/head/sys/kern/kern_intr.c Wed Oct 27 21:01:53 2010 (r214434) +++ projects/ofed/head/sys/kern/kern_intr.c Wed Oct 27 23:18:25 2010 (r214435) @@ -74,6 +74,7 @@ struct intr_thread { /* Interrupt thread flags kept in it_flags */ #define IT_DEAD 0x000001 /* Thread is waiting to exit. */ +#define IT_WAIT 0x000001 /* Thread is waiting for completion. */ struct intr_entropy { struct thread *td; @@ -739,6 +740,38 @@ intr_handler_source(void *cookie) return (ie->ie_source); } +/* + * Sleep until an ithread finishes executing an interrupt handler. + * + * XXX Doesn't currently handle interrupt filters or fast interrupt + * handlers. + */ +void +intr_drain(int irq) +{ + struct mtx *mtx; + struct intr_event *ie; + struct intr_thread *ithd; + struct thread *td; + + ie = intr_lookup(irq); + if (ie == NULL) + return; + if (ie->ie_thread == NULL) + return; + ithd = ie->ie_thread; + td = ithd->it_thread; + thread_lock(td); + mtx = td->td_lock; + if (!TD_AWAITING_INTR(td)) { + ithd->it_flags |= IT_WAIT; + msleep_spin(ithd, mtx, "isync", 0); + } + mtx_unlock_spin(mtx); + return; +} + + #ifndef INTR_FILTER int intr_event_remove_handler(void *cookie) @@ -1275,6 +1308,7 @@ ithread_loop(void *arg) struct intr_event *ie; struct thread *td; struct proc *p; + int wake; td = curthread; p = td->td_proc; @@ -1283,6 +1317,7 @@ ithread_loop(void *arg) ("%s: ithread and proc linkage out of sync", __func__)); ie = ithd->it_event; ie->ie_count = 0; + wake = 0; /* * As long as we have interrupts outstanding, go through the @@ -1323,12 +1358,20 @@ ithread_loop(void *arg) * set again, so we have to check it again. */ thread_lock(td); - if (!ithd->it_need && !(ithd->it_flags & IT_DEAD)) { + if (!ithd->it_need && !(ithd->it_flags & (IT_DEAD | IT_WAIT))) { TD_SET_IWAIT(td); ie->ie_count = 0; mi_switch(SW_VOL | SWT_IWAIT, NULL); } + if (ithd->it_flags & IT_WAIT) { + wake = 1; + ithd->it_flags &= ~IT_WAIT; + } thread_unlock(td); + if (wake) { + wakeup(ithd); + wake = 0; + } } } @@ -1439,6 +1482,7 @@ ithread_loop(void *arg) struct thread *td; struct proc *p; int priv; + int wake; td = curthread; p = td->td_proc; @@ -1449,6 +1493,7 @@ ithread_loop(void *arg) ("%s: ithread and proc linkage out of sync", __func__)); ie = ithd->it_event; ie->ie_count = 0; + wake = 0; /* * As long as we have interrupts outstanding, go through the @@ -1492,12 +1537,20 @@ ithread_loop(void *arg) * set again, so we have to check it again. */ thread_lock(td); - if (!ithd->it_need && !(ithd->it_flags & IT_DEAD)) { + if (!ithd->it_need && !(ithd->it_flags & (IT_DEAD | IT_WAIT))) { TD_SET_IWAIT(td); ie->ie_count = 0; mi_switch(SW_VOL | SWT_IWAIT, NULL); } + if (ithd->it_flags & IT_WAIT) { + wake = 1; + ithd->it_flags &= ~IT_WAIT; + } thread_unlock(td); + if (wake) { + wakeup(ithd); + wake = 0; + } } } Modified: projects/ofed/head/sys/ofed/include/linux/hardirq.h ============================================================================== --- projects/ofed/head/sys/ofed/include/linux/hardirq.h Wed Oct 27 21:01:53 2010 (r214434) +++ projects/ofed/head/sys/ofed/include/linux/hardirq.h Wed Oct 27 23:18:25 2010 (r214435) @@ -28,6 +28,12 @@ #ifndef _LINUX_HARDIRQ_H_ #define _LINUX_HARDIRQ_H_ -#define synchronize_irq(irq) printf("synchronize_irq: Unimplemented\n") +#include + +#include +#include +#include + +#define synchronize_irq(irq) intr_drain((irq)) #endif /* _LINUX_HARDIRQ_H_ */ Modified: projects/ofed/head/sys/sys/interrupt.h ============================================================================== --- projects/ofed/head/sys/sys/interrupt.h Wed Oct 27 21:01:53 2010 (r214434) +++ projects/ofed/head/sys/sys/interrupt.h Wed Oct 27 23:18:25 2010 (r214435) @@ -177,6 +177,7 @@ int intr_event_remove_handler(void *cook int intr_getaffinity(int irq, void *mask); void *intr_handler_source(void *cookie); int intr_setaffinity(int irq, void *mask); +void intr_drain(int irq); int swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler, void *arg, int pri, enum intr_type flags, void **cookiep);