Date: Wed, 27 Oct 2010 23:18:25 +0000 (UTC) From: Jeff Roberson <jeff@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r214435 - in projects/ofed/head/sys: kern ofed/include/linux sys Message-ID: <201010272318.o9RNIPAT043359@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <linux/types.h> + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/interrupt.h> + +#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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010272318.o9RNIPAT043359>