diff options
-rw-r--r-- | share/man/man9/firmware.9 | 33 | ||||
-rw-r--r-- | share/man/man9/timeout.9 | 26 | ||||
-rw-r--r-- | sys/kern/kern_timeout.c | 15 | ||||
-rw-r--r-- | sys/sys/callout.h | 4 |
4 files changed, 65 insertions, 13 deletions
diff --git a/share/man/man9/firmware.9 b/share/man/man9/firmware.9 index 3dc33f8..e010159 100644 --- a/share/man/man9/firmware.9 +++ b/share/man/man9/firmware.9 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 6, 2006 +.Dd May 18, 2008 .Os .Dt FIRMWARE 9 .Sh NAME @@ -31,6 +31,7 @@ .Nm firmware_unregister , .Nm firmware_get , .Nm firmware_put +.Nm firmware_drain .Nd firmware image loading and management .Sh SYNOPSIS .In sys/param.h @@ -59,6 +60,8 @@ struct firmware { .Fn firmware_get "const char *imagename" .Ft void .Fn firmware_put "const struct firmware *fp" "int flags" +.Ft void +.Fn firmware_drain "void" .Sh DESCRIPTION The .Nm firmware @@ -137,8 +140,11 @@ This involves the linker subsystem and disk access, so .Fn firmware_get must not be called with any locks (except for .Va Giant ) . -The caller must also have a process context so filesystem state such as -the root vnode is defined (e.g. you cannot load from a taskqueue thread). +Note also that if the firmware image is loaded from a filesystem +it must already be mounted. +In particular this means that it may be necessary to defer requests +from a driver attach method unless it is known the root filesystem is +already mounted. .Pp On success, .Fn firmware_get @@ -154,6 +160,21 @@ argument may be set to to indicate that firmware_put is free to reclaim resources associated with the firmware image if this is the last reference. +By default a firmware image will be deferred to a +.Xr taskqueue 9 +thread so the call may be done while holding a lock. +In certain cases, such as on driver detach, this cannot be allowed. +If the +.Dv FIRMWARE_WAIT +flag is or'd into +.Fa flags +then +.Fn firmware_put +will wait for the asynchronous operation to complete. +This can also be accomplished by calling the +.Fn firmware_drain +routine after +.Fn firmware_put . .Sh FIRMWARE LOADING MECHANISMS As mentioned before, any component of the system can register firmware images at any time by simply calling @@ -238,11 +259,7 @@ IxNpeMicrocode.fwo optional npe_fw \\ clean "IxNpeMicrocode.fwo" IxNpeMicrocode.dat optional npe_fw \\ dependency ".PHONY" \\ - compile-with "if [ -e $S/arm/xscale/ixp425/IxNpeMicrocode.dat ]; \\ - then \\ - ln -sf $S/arm/xscale/ixp425/IxNpeMicrocode.dat .; \\ - else echo 'WARNING, no IxNpeMicrocode.dat file; you must obtain this from the Intel web site'; false; \\ - fi" \\ + compile-with "uudecode < $S/contrib/dev/npe/IxNpeMicrocode.dat.uu" \\ no-obj no-implicit-rule \\ clean "IxNpeMicrocode.dat" .Ed diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9 index 9c37632..e6d911d 100644 --- a/share/man/man9/timeout.9 +++ b/share/man/man9/timeout.9 @@ -36,7 +36,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 20, 2007 +.Dd August 2, 2008 .Dt TIMEOUT 9 .Os .Sh NAME @@ -49,6 +49,7 @@ .Nm callout_stop , .Nm callout_drain , .Nm callout_reset , +.Nm callout_schedule , .Nm callout_pending , .Nm callout_active , .Nm callout_deactivate @@ -83,6 +84,8 @@ struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle) .Ft int .Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg" .Ft int +.Fn callout_schedule "struct callout *c" "int ticks" +.Ft int .Fn callout_pending "struct callout *c" .Ft int .Fn callout_active "struct callout *c" @@ -191,9 +194,10 @@ The functions .Fn callout_init_mtx , .Fn callout_init_rw , .Fn callout_stop , -.Fn callout_drain -and +.Fn callout_drain , .Fn callout_reset +and +.Fn callout_schedule are low-level routines for clients who wish to allocate their own callout structures. .Pp @@ -201,9 +205,10 @@ The function .Fn callout_init initializes a callout so it can be passed to .Fn callout_stop , -.Fn callout_drain +.Fn callout_drain , +.Fn callout_reset or -.Fn callout_reset +.Fn callout_schedule without any side effects. If the .Fa mpsafe @@ -294,6 +299,17 @@ If there was already a pending callout and it was rescheduled, then will return a non-zero value. If the callout has an associated mutex, then that mutex must be held when this function is called. +The function +.Fn callout_schedule +(re)schedules an existing callout for a new period of time; +it is equivalent to calling +.Fn callout_reset +with the +.Fa func +and +.Fa arg +parameters extracted from the callout structure (though possibly with +lower overhead). .Pp The macros .Fn callout_pending , diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index ec540c5..fe05d2c 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -616,6 +616,21 @@ retry: return (cancelled); } +/* + * Common idioms that can be optimized in the future. + */ +int +callout_schedule_on(struct callout *c, int to_ticks, int cpu) +{ + return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, cpu); +} + +int +callout_schedule(struct callout *c, int to_ticks) +{ + return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, c->c_cpu); +} + int _callout_stop_safe(c, safe) struct callout *c; diff --git a/sys/sys/callout.h b/sys/sys/callout.h index f472839..2d43d14 100644 --- a/sys/sys/callout.h +++ b/sys/sys/callout.h @@ -89,6 +89,10 @@ int callout_reset_on(struct callout *, int, void (*)(void *), void *, int); callout_reset_on((c), (on_tick), (fn), (arg), (c)->c_cpu) #define callout_reset_curcpu(c, on_tick, fn, arg) \ callout_reset_on((c), (on_tick), (fn), (arg), PCPU_GET(cpuid)) +int callout_schedule(struct callout *, int); +int callout_schedule_on(struct callout *, int, int); +#define callout_schedule_curcpu(c, on_tick) \ + callout_schedule_on((c), (on_tick), PCPU_GET(cpuid)) #define callout_stop(c) _callout_stop_safe(c, 0) int _callout_stop_safe(struct callout *, int); void callout_tick(void); |