Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_autoconf.c
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Autoconfiguration subroutines. | * Autoconfiguration subroutines. | ||||
*/ | */ | ||||
/* | /* | ||||
* "Interrupt driven config" functions. | * "Interrupt driven config" functions. | ||||
*/ | */ | ||||
static TAILQ_HEAD(, intr_config_hook) intr_config_hook_list = | static STAILQ_HEAD(, intr_config_hook) intr_config_hook_list = | ||||
TAILQ_HEAD_INITIALIZER(intr_config_hook_list); | STAILQ_HEAD_INITIALIZER(intr_config_hook_list); | ||||
static struct intr_config_hook *next_to_notify; | static struct intr_config_hook *next_to_notify; | ||||
static struct mtx intr_config_hook_lock; | static struct mtx intr_config_hook_lock; | ||||
MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF); | MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF); | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void run_interrupt_driven_config_hooks(void); | static void run_interrupt_driven_config_hooks(void); | ||||
/* | /* | ||||
Show All 27 Lines | |||||
{ | { | ||||
struct intr_config_hook *hook_entry; | struct intr_config_hook *hook_entry; | ||||
char namebuf[64]; | char namebuf[64]; | ||||
long offset; | long offset; | ||||
if (warned < 6) { | if (warned < 6) { | ||||
printf("run_interrupt_driven_hooks: still waiting after %d " | printf("run_interrupt_driven_hooks: still waiting after %d " | ||||
"seconds for", warned * WARNING_INTERVAL_SECS); | "seconds for", warned * WARNING_INTERVAL_SECS); | ||||
TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) { | STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) { | ||||
if (linker_search_symbol_name( | if (linker_search_symbol_name( | ||||
(caddr_t)hook_entry->ich_func, namebuf, | (caddr_t)hook_entry->ich_func, namebuf, | ||||
sizeof(namebuf), &offset) == 0) | sizeof(namebuf), &offset) == 0) | ||||
printf(" %s", namebuf); | printf(" %s", namebuf); | ||||
else | else | ||||
printf(" %p", hook_entry->ich_func); | printf(" %p", hook_entry->ich_func); | ||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
Show All 19 Lines | run_interrupt_driven_config_hooks() | ||||
if (running != 0) { | if (running != 0) { | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
return; | return; | ||||
} | } | ||||
running = 1; | running = 1; | ||||
while (next_to_notify != NULL) { | while (next_to_notify != NULL) { | ||||
hook_entry = next_to_notify; | hook_entry = next_to_notify; | ||||
next_to_notify = TAILQ_NEXT(hook_entry, ich_links); | next_to_notify = STAILQ_NEXT(hook_entry, ich_links); | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
(*hook_entry->ich_func)(hook_entry->ich_arg); | (*hook_entry->ich_func)(hook_entry->ich_arg); | ||||
mtx_lock(&intr_config_hook_lock); | mtx_lock(&intr_config_hook_lock); | ||||
} | } | ||||
running = 0; | running = 0; | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
} | } | ||||
static void | static void | ||||
boot_run_interrupt_driven_config_hooks(void *dummy) | boot_run_interrupt_driven_config_hooks(void *dummy) | ||||
{ | { | ||||
int warned; | int warned; | ||||
run_interrupt_driven_config_hooks(); | run_interrupt_driven_config_hooks(); | ||||
/* Block boot processing until all hooks are disestablished. */ | /* Block boot processing until all hooks are disestablished. */ | ||||
TSWAIT("config hooks"); | TSWAIT("config hooks"); | ||||
mtx_lock(&intr_config_hook_lock); | mtx_lock(&intr_config_hook_lock); | ||||
warned = 0; | warned = 0; | ||||
while (!TAILQ_EMPTY(&intr_config_hook_list)) { | while (!STAILQ_EMPTY(&intr_config_hook_list)) { | ||||
if (msleep(&intr_config_hook_list, &intr_config_hook_lock, | if (msleep(&intr_config_hook_list, &intr_config_hook_lock, | ||||
0, "conifhk", WARNING_INTERVAL_SECS * hz) == | 0, "conifhk", WARNING_INTERVAL_SECS * hz) == | ||||
EWOULDBLOCK) { | EWOULDBLOCK) { | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
warned++; | warned++; | ||||
run_interrupt_driven_config_hooks_warning(warned); | run_interrupt_driven_config_hooks_warning(warned); | ||||
mtx_lock(&intr_config_hook_lock); | mtx_lock(&intr_config_hook_lock); | ||||
} | } | ||||
Show All 12 Lines | |||||
*/ | */ | ||||
int | int | ||||
config_intrhook_establish(struct intr_config_hook *hook) | config_intrhook_establish(struct intr_config_hook *hook) | ||||
{ | { | ||||
struct intr_config_hook *hook_entry; | struct intr_config_hook *hook_entry; | ||||
TSHOLD("config hooks"); | TSHOLD("config hooks"); | ||||
mtx_lock(&intr_config_hook_lock); | mtx_lock(&intr_config_hook_lock); | ||||
TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) | STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) | ||||
if (hook_entry == hook) | if (hook_entry == hook) | ||||
break; | break; | ||||
if (hook_entry != NULL) { | if (hook_entry != NULL) { | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
printf("config_intrhook_establish: establishing an " | printf("config_intrhook_establish: establishing an " | ||||
"already established hook.\n"); | "already established hook.\n"); | ||||
return (1); | return (1); | ||||
} | } | ||||
TAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links); | STAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links); | ||||
if (next_to_notify == NULL) | if (next_to_notify == NULL) | ||||
next_to_notify = hook; | next_to_notify = hook; | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
if (cold == 0) | if (cold == 0) | ||||
/* | /* | ||||
* XXX Call from a task since not all drivers expect | * XXX Call from a task since not all drivers expect | ||||
* to be re-entered at the time a hook is established. | * to be re-entered at the time a hook is established. | ||||
*/ | */ | ||||
Show All 19 Lines | |||||
} | } | ||||
void | void | ||||
config_intrhook_disestablish(struct intr_config_hook *hook) | config_intrhook_disestablish(struct intr_config_hook *hook) | ||||
{ | { | ||||
struct intr_config_hook *hook_entry; | struct intr_config_hook *hook_entry; | ||||
mtx_lock(&intr_config_hook_lock); | mtx_lock(&intr_config_hook_lock); | ||||
TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) | STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) | ||||
if (hook_entry == hook) | if (hook_entry == hook) | ||||
break; | break; | ||||
if (hook_entry == NULL) | if (hook_entry == NULL) | ||||
panic("config_intrhook_disestablish: disestablishing an " | panic("config_intrhook_disestablish: disestablishing an " | ||||
"unestablished hook"); | "unestablished hook"); | ||||
if (next_to_notify == hook) | if (next_to_notify == hook) | ||||
next_to_notify = TAILQ_NEXT(hook, ich_links); | next_to_notify = STAILQ_NEXT(hook, ich_links); | ||||
TAILQ_REMOVE(&intr_config_hook_list, hook, ich_links); | STAILQ_REMOVE(&intr_config_hook_list, hook, intr_config_hook, ich_links); | ||||
TSRELEASE("config hooks"); | TSRELEASE("config hooks"); | ||||
/* Wakeup anyone watching the list */ | /* Wakeup anyone watching the list */ | ||||
wakeup(&intr_config_hook_list); | wakeup(&intr_config_hook_list); | ||||
mtx_unlock(&intr_config_hook_lock); | mtx_unlock(&intr_config_hook_lock); | ||||
} | } | ||||
#ifdef DDB | #ifdef DDB | ||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
DB_SHOW_COMMAND(conifhk, db_show_conifhk) | DB_SHOW_COMMAND(conifhk, db_show_conifhk) | ||||
{ | { | ||||
struct intr_config_hook *hook_entry; | struct intr_config_hook *hook_entry; | ||||
char namebuf[64]; | char namebuf[64]; | ||||
long offset; | long offset; | ||||
TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) { | STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) { | ||||
if (linker_ddb_search_symbol_name( | if (linker_ddb_search_symbol_name( | ||||
(caddr_t)hook_entry->ich_func, namebuf, sizeof(namebuf), | (caddr_t)hook_entry->ich_func, namebuf, sizeof(namebuf), | ||||
&offset) == 0) { | &offset) == 0) { | ||||
db_printf("hook: %p at %s+%#lx arg: %p\n", | db_printf("hook: %p at %s+%#lx arg: %p\n", | ||||
hook_entry->ich_func, namebuf, offset, | hook_entry->ich_func, namebuf, offset, | ||||
hook_entry->ich_arg); | hook_entry->ich_arg); | ||||
} else { | } else { | ||||
db_printf("hook: %p at ??+?? arg %p\n", | db_printf("hook: %p at ??+?? arg %p\n", | ||||
hook_entry->ich_func, hook_entry->ich_arg); | hook_entry->ich_func, hook_entry->ich_arg); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#endif /* DDB */ | #endif /* DDB */ |