1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-28 08:02:54 +00:00

Yank crufty INTR_FILTER option

It was introduced to the tree in r169320 and r169321 in May 2007.

It never got much use and never became a kernel default.  The code
duplicates the default path quite a bit, with slight modifications.  Just
yank out the cruft.  Whatever goals were being aimed for can probably be met
within the existing framework, without a flag day option.

Mostly mechanical change: 'unifdef -m -UINTR_FILTER'.

Reviewed by:	mmacy
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D15546
This commit is contained in:
Conrad Meyer 2018-05-24 17:06:00 +00:00
parent 810c4dcddf
commit a0638b33f7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=334170
5 changed files with 1 additions and 569 deletions

View File

@ -52,7 +52,6 @@ options CD9660 # ISO 9660 Filesystem
options PSEUDOFS # Pseudo-filesystem framework
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options INTR_FILTER
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores

View File

@ -904,9 +904,6 @@ HWPMC_DEBUG opt_global.h
HWPMC_HOOKS
HWPMC_MIPS_BACKTRACE opt_hwpmc_hooks.h
# Interrupt filtering
INTR_FILTER
# 802.11 support layer
IEEE80211_DEBUG opt_wlan.h
IEEE80211_DEBUG_REFCNT opt_wlan.h

View File

@ -57,8 +57,6 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
#include <dev/asmc/asmcvar.h>
#include "opt_intr_filter.h"
/*
* Device interface.
*/
@ -85,9 +83,6 @@ static int asmc_temp_getvalue(device_t dev, const char *key);
static int asmc_sms_read(device_t, const char *key, int16_t *val);
static void asmc_sms_calibrate(device_t dev);
static int asmc_sms_intrfast(void *arg);
#ifdef INTR_FILTER
static void asmc_sms_handler(void *arg);
#endif
static void asmc_sms_printintr(device_t dev, uint8_t);
static void asmc_sms_task(void *arg, int pending);
#ifdef DEBUG
@ -563,13 +558,11 @@ asmc_attach(device_t dev)
* We only need to do this for the non INTR_FILTER case.
*/
sc->sc_sms_tq = NULL;
#ifndef INTR_FILTER
TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc);
sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK,
taskqueue_thread_enqueue, &sc->sc_sms_tq);
taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq",
device_get_nameunit(dev));
#endif
/*
* Allocate an IRQ for the SMS.
*/
@ -584,11 +577,7 @@ asmc_attach(device_t dev)
ret = bus_setup_intr(dev, sc->sc_irq,
INTR_TYPE_MISC | INTR_MPSAFE,
#ifdef INTR_FILTER
asmc_sms_intrfast, asmc_sms_handler,
#else
asmc_sms_intrfast, NULL,
#endif
dev, &sc->sc_cookie);
if (ret) {
@ -1241,23 +1230,10 @@ asmc_sms_intrfast(void *arg)
sc->sc_sms_intrtype = type;
asmc_sms_printintr(dev, type);
#ifdef INTR_FILTER
return (FILTER_SCHEDULE_THREAD | FILTER_HANDLED);
#else
taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task);
#endif
return (FILTER_HANDLED);
}
#ifdef INTR_FILTER
static void
asmc_sms_handler(void *arg)
{
struct asmc_softc *sc = device_get_softc(arg);
asmc_sms_task(sc, 0);
}
#endif
static void

View File

@ -101,24 +101,11 @@ static struct mtx event_lock;
MTX_SYSINIT(intr_event_list, &event_lock, "intr event list", MTX_DEF);
static void intr_event_update(struct intr_event *ie);
#ifdef INTR_FILTER
static int intr_event_schedule_thread(struct intr_event *ie,
struct intr_thread *ithd);
static int intr_filter_loop(struct intr_event *ie,
struct trapframe *frame, struct intr_thread **ithd);
static struct intr_thread *ithread_create(const char *name,
struct intr_handler *ih);
#else
static int intr_event_schedule_thread(struct intr_event *ie);
static struct intr_thread *ithread_create(const char *name);
#endif
static void ithread_destroy(struct intr_thread *ithread);
static void ithread_execute_handlers(struct proc *p,
struct intr_event *ie);
#ifdef INTR_FILTER
static void priv_ithread_execute_handler(struct proc *p,
struct intr_handler *ih);
#endif
static void ithread_loop(void *);
static void ithread_update(struct intr_thread *ithd);
static void start_softintr(void *);
@ -506,7 +493,6 @@ intr_event_destroy(struct intr_event *ie)
return (0);
}
#ifndef INTR_FILTER
static struct intr_thread *
ithread_create(const char *name)
{
@ -530,31 +516,6 @@ ithread_create(const char *name)
CTR2(KTR_INTR, "%s: created %s", __func__, name);
return (ithd);
}
#else
static struct intr_thread *
ithread_create(const char *name, struct intr_handler *ih)
{
struct intr_thread *ithd;
struct thread *td;
int error;
ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO);
error = kproc_kthread_add(ithread_loop, ih, &intrproc,
&td, RFSTOPPED | RFHIGHPID,
0, "intr", "%s", name);
if (error)
panic("kproc_create() failed with %d", error);
thread_lock(td);
sched_class(td, PRI_ITHD);
TD_SET_IWAIT(td);
thread_unlock(td);
td->td_pflags |= TDP_ITHREAD;
ithd->it_thread = td;
CTR2(KTR_INTR, "%s: created %s", __func__, name);
return (ithd);
}
#endif
static void
ithread_destroy(struct intr_thread *ithread)
@ -572,7 +533,6 @@ ithread_destroy(struct intr_thread *ithread)
thread_unlock(td);
}
#ifndef INTR_FILTER
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,
@ -646,90 +606,6 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
*cookiep = ih;
return (0);
}
#else
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)
{
struct intr_handler *ih, *temp_ih;
struct intr_thread *it;
if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
return (EINVAL);
/* Allocate and populate an interrupt handler structure. */
ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO);
ih->ih_filter = filter;
ih->ih_handler = handler;
ih->ih_argument = arg;
strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
ih->ih_event = ie;
ih->ih_pri = pri;
if (flags & INTR_EXCL)
ih->ih_flags = IH_EXCLUSIVE;
if (flags & INTR_MPSAFE)
ih->ih_flags |= IH_MPSAFE;
if (flags & INTR_ENTROPY)
ih->ih_flags |= IH_ENTROPY;
/* We can only have one exclusive handler in a event. */
mtx_lock(&ie->ie_lock);
if (!TAILQ_EMPTY(&ie->ie_handlers)) {
if ((flags & INTR_EXCL) ||
(TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
mtx_unlock(&ie->ie_lock);
free(ih, M_ITHREAD);
return (EINVAL);
}
}
/* For filtered handlers, create a private ithread to run on. */
if (filter != NULL && handler != NULL) {
mtx_unlock(&ie->ie_lock);
it = ithread_create("intr: newborn", ih);
mtx_lock(&ie->ie_lock);
it->it_event = ie;
ih->ih_thread = it;
ithread_update(it); /* XXX - do we really need this?!?!? */
} else { /* Create the global per-event thread if we need one. */
while (ie->ie_thread == NULL && handler != NULL) {
if (ie->ie_flags & IE_ADDING_THREAD)
msleep(ie, &ie->ie_lock, 0, "ithread", 0);
else {
ie->ie_flags |= IE_ADDING_THREAD;
mtx_unlock(&ie->ie_lock);
it = ithread_create("intr: newborn", ih);
mtx_lock(&ie->ie_lock);
ie->ie_flags &= ~IE_ADDING_THREAD;
ie->ie_thread = it;
it->it_event = ie;
ithread_update(it);
wakeup(ie);
}
}
}
/* Add the new handler to the event in priority order. */
TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) {
if (temp_ih->ih_pri > ih->ih_pri)
break;
}
if (temp_ih == NULL)
TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next);
else
TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
intr_event_update(ie);
CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
ie->ie_name);
mtx_unlock(&ie->ie_lock);
if (cookiep != NULL)
*cookiep = ih;
return (0);
}
#endif
/*
* Append a description preceded by a ':' to the name of the specified
@ -846,7 +722,6 @@ _intr_drain(int irq)
}
#ifndef INTR_FILTER
int
intr_event_remove_handler(void *cookie)
{
@ -997,168 +872,6 @@ intr_event_schedule_thread(struct intr_event *ie)
return (0);
}
#else
int
intr_event_remove_handler(void *cookie)
{
struct intr_handler *handler = (struct intr_handler *)cookie;
struct intr_event *ie;
struct intr_thread *it;
#ifdef INVARIANTS
struct intr_handler *ih;
#endif
#ifdef notyet
int dead;
#endif
if (handler == NULL)
return (EINVAL);
ie = handler->ih_event;
KASSERT(ie != NULL,
("interrupt handler \"%s\" has a NULL interrupt event",
handler->ih_name));
mtx_lock(&ie->ie_lock);
CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
ie->ie_name);
#ifdef INVARIANTS
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
if (ih == handler)
goto ok;
mtx_unlock(&ie->ie_lock);
panic("interrupt handler \"%s\" not found in interrupt event \"%s\"",
ih->ih_name, ie->ie_name);
ok:
#endif
/*
* If there are no ithreads (per event and per handler), then
* just remove the handler and return.
* XXX: Note that an INTR_FAST handler might be running on another CPU!
*/
if (ie->ie_thread == NULL && handler->ih_thread == NULL) {
TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
mtx_unlock(&ie->ie_lock);
free(handler, M_ITHREAD);
return (0);
}
/* Private or global ithread? */
it = (handler->ih_thread) ? handler->ih_thread : ie->ie_thread;
/*
* If the interrupt thread is already running, then just mark this
* handler as being dead and let the ithread do the actual removal.
*
* During a cold boot while cold is set, msleep() does not sleep,
* so we have to remove the handler here rather than letting the
* thread do it.
*/
thread_lock(it->it_thread);
if (!TD_AWAITING_INTR(it->it_thread) && !cold) {
handler->ih_flags |= IH_DEAD;
/*
* Ensure that the thread will process the handler list
* again and remove this handler if it has already passed
* it on the list.
*
* The release part of the following store ensures
* that the update of ih_flags is ordered before the
* it_need setting. See the comment before
* atomic_cmpset_acq(&ithd->it_need, ...) operation in
* the ithread_execute_handlers().
*/
atomic_store_rel_int(&it->it_need, 1);
} else
TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
thread_unlock(it->it_thread);
while (handler->ih_flags & IH_DEAD)
msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
/*
* At this point, the handler has been disconnected from the event,
* so we can kill the private ithread if any.
*/
if (handler->ih_thread) {
ithread_destroy(handler->ih_thread);
handler->ih_thread = NULL;
}
intr_event_update(ie);
#ifdef notyet
/*
* XXX: This could be bad in the case of ppbus(8). Also, I think
* this could lead to races of stale data when servicing an
* interrupt.
*/
dead = 1;
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (handler != NULL) {
dead = 0;
break;
}
}
if (dead) {
ithread_destroy(ie->ie_thread);
ie->ie_thread = NULL;
}
#endif
mtx_unlock(&ie->ie_lock);
free(handler, M_ITHREAD);
return (0);
}
static int
intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it)
{
struct intr_entropy entropy;
struct thread *td;
struct thread *ctd;
struct proc *p;
/*
* If no ithread or no handlers, then we have a stray interrupt.
*/
if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) || it == NULL)
return (EINVAL);
ctd = curthread;
td = it->it_thread;
p = td->td_proc;
/*
* If any of the handlers for this ithread claim to be good
* sources of entropy, then gather some.
*/
if (ie->ie_flags & IE_ENTROPY) {
entropy.event = (uintptr_t)ie;
entropy.td = ctd;
random_harvest_queue(&entropy, sizeof(entropy), 2, RANDOM_INTERRUPT);
}
KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name));
/*
* Set it_need to tell the thread to keep running if it is already
* running. Then, lock the thread and see if we actually need to
* put it on the runqueue.
*
* Use store_rel to arrange that the store to ih_need in
* swi_sched() is before the store to it_need and prepare for
* transfer of this order to loads in the ithread.
*/
atomic_store_rel_int(&it->it_need, 1);
thread_lock(td);
if (TD_AWAITING_INTR(td)) {
CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid,
td->td_name);
TD_CLR_IWAIT(td);
sched_add(td, SRQ_INTR);
} else {
CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d",
__func__, p->p_pid, td->td_name, it->it_need, td->td_state);
}
thread_unlock(td);
return (0);
}
#endif
/*
* Allow interrupt event binding for software interrupt handlers -- a no-op,
@ -1231,11 +944,7 @@ swi_sched(void *cookie, int flags)
if (!(flags & SWI_DELAY)) {
VM_CNT_INC(v_soft);
#ifdef INTR_FILTER
error = intr_event_schedule_thread(ie, ie->ie_thread);
#else
error = intr_event_schedule_thread(ie);
#endif
KASSERT(error == 0, ("stray software interrupt"));
}
}
@ -1253,38 +962,6 @@ swi_remove(void *cookie)
return (intr_event_remove_handler(cookie));
}
#ifdef INTR_FILTER
static void
priv_ithread_execute_handler(struct proc *p, struct intr_handler *ih)
{
struct intr_event *ie;
ie = ih->ih_event;
/*
* If this handler is marked for death, remove it from
* the list of handlers and wake up the sleeper.
*/
if (ih->ih_flags & IH_DEAD) {
mtx_lock(&ie->ie_lock);
TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
ih->ih_flags &= ~IH_DEAD;
wakeup(ih);
mtx_unlock(&ie->ie_lock);
return;
}
/* Execute this handler. */
CTR6(KTR_INTR, "%s: pid %d exec %p(%p) for %s flg=%x",
__func__, p->p_pid, (void *)ih->ih_handler, ih->ih_argument,
ih->ih_name, ih->ih_flags);
if (!(ih->ih_flags & IH_MPSAFE))
mtx_lock(&Giant);
ih->ih_handler(ih->ih_argument);
if (!(ih->ih_flags & IH_MPSAFE))
mtx_unlock(&Giant);
}
#endif
/*
* This is a public function for use by drivers that mux interrupt
@ -1380,7 +1057,6 @@ ithread_execute_handlers(struct proc *p, struct intr_event *ie)
ie->ie_post_ithread(ie->ie_source);
}
#ifndef INTR_FILTER
/*
* This is the main code for interrupt threads.
*/
@ -1554,222 +1230,6 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
td->td_intr_nesting_level--;
return (0);
}
#else
/*
* This is the main code for interrupt threads.
*/
static void
ithread_loop(void *arg)
{
struct intr_thread *ithd;
struct intr_handler *ih;
struct intr_event *ie;
struct thread *td;
struct proc *p;
int priv;
int wake;
td = curthread;
p = td->td_proc;
ih = (struct intr_handler *)arg;
priv = (ih->ih_thread != NULL) ? 1 : 0;
ithd = (priv) ? ih->ih_thread : ih->ih_event->ie_thread;
KASSERT(ithd->it_thread == td,
("%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
* list of handlers, giving each one a go at it.
*/
for (;;) {
/*
* If we are an orphaned thread, then just die.
*/
if (ithd->it_flags & IT_DEAD) {
CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__,
p->p_pid, td->td_name);
free(ithd, M_ITHREAD);
kthread_exit();
}
/*
* Service interrupts. If another interrupt arrives while
* we are running, it will set it_need to note that we
* should make another pass.
*
* The load_acq part of the following cmpset ensures
* that the load of ih_need in ithread_execute_handlers()
* is ordered after the load of it_need here.
*/
while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0) {
if (priv)
priv_ithread_execute_handler(p, ih);
else
ithread_execute_handlers(p, ie);
}
WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
mtx_assert(&Giant, MA_NOTOWNED);
/*
* Processed all our interrupts. Now get the sched
* lock. This may take a while and it_need may get
* set again, so we have to check it again.
*/
thread_lock(td);
if (atomic_load_acq_int(&ithd->it_need) == 0 &&
(ithd->it_flags & (IT_DEAD | IT_WAIT)) == 0) {
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;
}
}
}
/*
* Main loop for interrupt filter.
*
* Some architectures (i386, amd64 and arm) require the optional frame
* parameter, and use it as the main argument for fast handler execution
* when ih_argument == NULL.
*
* Return value:
* o FILTER_STRAY: No filter recognized the event, and no
* filter-less handler is registered on this
* line.
* o FILTER_HANDLED: A filter claimed the event and served it.
* o FILTER_SCHEDULE_THREAD: No filter claimed the event, but there's at
* least one filter-less handler on this line.
* o FILTER_HANDLED |
* FILTER_SCHEDULE_THREAD: A filter claimed the event, and asked for
* scheduling the per-handler ithread.
*
* In case an ithread has to be scheduled, in *ithd there will be a
* pointer to a struct intr_thread containing the thread to be
* scheduled.
*/
static int
intr_filter_loop(struct intr_event *ie, struct trapframe *frame,
struct intr_thread **ithd)
{
struct intr_handler *ih;
void *arg;
int ret, thread_only;
ret = 0;
thread_only = 0;
TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
/*
* Execute fast interrupt handlers directly.
* To support clock handlers, if a handler registers
* with a NULL argument, then we pass it a pointer to
* a trapframe as its argument.
*/
arg = ((ih->ih_argument == NULL) ? frame : ih->ih_argument);
CTR5(KTR_INTR, "%s: exec %p/%p(%p) for %s", __func__,
ih->ih_filter, ih->ih_handler, arg, ih->ih_name);
if (ih->ih_filter != NULL)
ret = ih->ih_filter(arg);
else {
thread_only = 1;
continue;
}
KASSERT(ret == FILTER_STRAY ||
((ret & (FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) != 0 &&
(ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
("%s: incorrect return value %#x from %s", __func__, ret,
ih->ih_name));
if (ret & FILTER_STRAY)
continue;
else {
*ithd = ih->ih_thread;
return (ret);
}
}
/*
* No filters handled the interrupt and we have at least
* one handler without a filter. In this case, we schedule
* all of the filter-less handlers to run in the ithread.
*/
if (thread_only) {
*ithd = ie->ie_thread;
return (FILTER_SCHEDULE_THREAD);
}
return (FILTER_STRAY);
}
/*
* Main interrupt handling body.
*
* Input:
* o ie: the event connected to this interrupt.
* o frame: some archs (i.e. i386) pass a frame to some.
* handlers as their main argument.
* Return value:
* o 0: everything ok.
* o EINVAL: stray interrupt.
*/
int
intr_event_handle(struct intr_event *ie, struct trapframe *frame)
{
struct intr_thread *ithd;
struct trapframe *oldframe;
struct thread *td;
int thread;
ithd = NULL;
td = curthread;
if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
return (EINVAL);
td->td_intr_nesting_level++;
thread = 0;
critical_enter();
oldframe = td->td_intr_frame;
td->td_intr_frame = frame;
thread = intr_filter_loop(ie, frame, &ithd);
if (thread & FILTER_HANDLED) {
if (ie->ie_post_filter != NULL)
ie->ie_post_filter(ie->ie_source);
} else {
if (ie->ie_pre_ithread != NULL)
ie->ie_pre_ithread(ie->ie_source);
}
td->td_intr_frame = oldframe;
critical_exit();
/* Interrupt storm logic */
if (thread & FILTER_STRAY) {
ie->ie_count++;
if (ie->ie_count < intr_storm_threshold)
printf("Interrupt stray detection not present\n");
}
/* Schedule an ithread if needed. */
if (thread & FILTER_SCHEDULE_THREAD) {
if (intr_event_schedule_thread(ie, ithd) != 0)
panic("%s: impossible stray interrupt", __func__);
}
td->td_intr_nesting_level--;
return (0);
}
#endif
#ifdef DDB
/*

View File

@ -3,6 +3,6 @@
.PATH: ${SRCTOP}/sys/dev/asmc
KMOD= asmc
SRCS= asmc.c opt_acpi.h opt_intr_filter.h acpi_if.h bus_if.h device_if.h
SRCS= asmc.c opt_acpi.h acpi_if.h bus_if.h device_if.h
.include <bsd.kmod.mk>