Index: kern/kern_intr.c =================================================================== --- kern/kern_intr.c +++ kern/kern_intr.c @@ -95,9 +95,6 @@ SYSCTL_INT(_hw, OID_AUTO, intr_storm_threshold, CTLFLAG_RWTUN, &intr_storm_threshold, 0, "Number of consecutive interrupts before storm protection is enabled"); -static int intr_epoch_batch = 1000; -SYSCTL_INT(_hw, OID_AUTO, intr_epoch_batch, CTLFLAG_RWTUN, &intr_epoch_batch, - 0, "Maximum interrupt handler executions without re-entering epoch(9)"); static TAILQ_HEAD(, intr_event) event_list = TAILQ_HEAD_INITIALIZER(event_list); static struct mtx event_lock; @@ -119,9 +116,7 @@ { u_char pri; - flags &= (INTR_TYPE_TTY | INTR_TYPE_BIO | INTR_TYPE_NET | - INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK | INTR_TYPE_AV); - switch (flags) { + switch (flags & INTR_TYPE_MASK) { case INTR_TYPE_TTY: pri = PI_TTY; break; @@ -145,10 +140,9 @@ break; default: /* We didn't specify an interrupt level. */ - panic("intr_priority: no interrupt type in flags"); + panic("intr_priority: Invalid interrupt flags(0x%08x)", flags); } - - return pri; + return (pri); } /* @@ -591,9 +585,17 @@ ih->ih_flags |= IH_MPSAFE; if (flags & INTR_ENTROPY) ih->ih_flags |= IH_ENTROPY; - if (flags & INTR_TYPE_NET) - ih->ih_flags |= IH_NET; - + if (flags & INTR_EPOCH) { + switch (flags & INTR_TYPE_MASK) { + case INTR_TYPE_NET: + ih->ih_epoch = net_epoch_preempt; + break; + default: + free(ih, M_ITHREAD); + return (EINVAL); + } + MPASS(ih->ih_epoch != NULL); + } /* We can only have one exclusive handler in a event. */ mtx_lock(&ie->ie_lock); if (!CK_SLIST_EMPTY(&ie->ie_handlers)) { @@ -1089,6 +1091,7 @@ intr_event_execute_handlers(struct proc *p, struct intr_event *ie) { struct intr_handler *ih, *ihn, *ihp; + struct epoch_tracker et; ihp = NULL; CK_SLIST_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) { @@ -1149,7 +1152,11 @@ if (!(ih->ih_flags & IH_MPSAFE)) mtx_lock(&Giant); + if (ih->ih_epoch != NULL) + epoch_enter_preempt(ih->ih_epoch, &et); ih->ih_handler(ih->ih_argument); + if (ih->ih_epoch != NULL) + epoch_exit_preempt(ih->ih_epoch, &et); if (!(ih->ih_flags & IH_MPSAFE)) mtx_unlock(&Giant); } @@ -1202,12 +1209,11 @@ static void ithread_loop(void *arg) { - struct epoch_tracker et; struct intr_thread *ithd; struct intr_event *ie; struct thread *td; struct proc *p; - int wake, epoch_count; + int wake; td = curthread; p = td->td_proc; @@ -1242,21 +1248,8 @@ * that the load of ih_need in ithread_execute_handlers() * is ordered after the load of it_need here. */ - if (ie->ie_hflags & IH_NET) { - epoch_count = 0; - NET_EPOCH_ENTER(et); - } - while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0) { + while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0) ithread_execute_handlers(p, ie); - if ((ie->ie_hflags & IH_NET) && - ++epoch_count >= intr_epoch_batch) { - NET_EPOCH_EXIT(et); - epoch_count = 0; - NET_EPOCH_ENTER(et); - } - } - if (ie->ie_hflags & IH_NET) - NET_EPOCH_EXIT(et); WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread"); mtx_assert(&Giant, MA_NOTOWNED); Index: sys/bus.h =================================================================== --- sys/bus.h +++ sys/bus.h @@ -272,9 +272,11 @@ INTR_TYPE_MISC = 16, INTR_TYPE_CLK = 32, INTR_TYPE_AV = 64, + INTR_TYPE_MASK = 127, /* sum of all interrupt types */ INTR_EXCL = 256, /* exclusive interrupt */ INTR_MPSAFE = 512, /* this interrupt is SMP safe */ INTR_ENTROPY = 1024, /* this interrupt provides entropy */ + INTR_EPOCH = 2048, /* interrupt handler needs epoch */ INTR_MD1 = 4096, /* flag reserved for MD use */ INTR_MD2 = 8192, /* flag reserved for MD use */ INTR_MD3 = 16384, /* flag reserved for MD use */ Index: sys/interrupt.h =================================================================== --- sys/interrupt.h +++ sys/interrupt.h @@ -37,6 +37,7 @@ struct intr_event; struct intr_thread; +struct epoch; struct trapframe; /* @@ -49,6 +50,7 @@ driver_filter_t *ih_filter; /* Filter handler function. */ driver_intr_t *ih_handler; /* Threaded handler function. */ void *ih_argument; /* Argument to pass to handlers. */ + struct epoch *ih_epoch; /* Epoch needed by handler. */ int ih_flags; char ih_name[MAXCOMLEN + 1]; /* Name of handler. */ struct intr_event *ih_event; /* Event we are connected to. */ @@ -58,7 +60,6 @@ }; /* Interrupt handle flags kept in ih_flags */ -#define IH_NET 0x00000001 /* Network. */ #define IH_EXCLUSIVE 0x00000002 /* Exclusive interrupt. */ #define IH_ENTROPY 0x00000004 /* Device is a good entropy source. */ #define IH_DEAD 0x00000008 /* Handler should be removed. */ Index: sys/param.h =================================================================== --- sys/param.h +++ sys/param.h @@ -60,7 +60,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1300076 /* Master, propagated to newvers */ +#define __FreeBSD_version 1300077 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,