Module Name: src Committed By: jruoho Date: Fri Sep 30 04:01:21 UTC 2011
Modified Files: src/sys/kern: subr_cpufreq.c src/sys/sys: cpufreq.h Log Message: Fix bugs noted by alnsn@. Namely, preallocate the global structure in order to avoid locking issues during deregistration. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/kern/subr_cpufreq.c cvs rdiff -u -r1.2 -r1.3 src/sys/sys/cpufreq.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/subr_cpufreq.c diff -u src/sys/kern/subr_cpufreq.c:1.2 src/sys/kern/subr_cpufreq.c:1.3 --- src/sys/kern/subr_cpufreq.c:1.2 Wed Sep 28 15:52:48 2011 +++ src/sys/kern/subr_cpufreq.c Fri Sep 30 04:01:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_cpufreq.c,v 1.2 2011/09/28 15:52:48 jruoho Exp $ */ +/* $NetBSD: subr_cpufreq.c,v 1.3 2011/09/30 04:01:21 jruoho Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_cpufreq.c,v 1.2 2011/09/28 15:52:48 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_cpufreq.c,v 1.3 2011/09/30 04:01:21 jruoho Exp $"); #include <sys/param.h> #include <sys/cpu.h> @@ -48,23 +48,25 @@ static void cpufreq_get_state_raw(uint3 static void cpufreq_set_raw(struct cpu_info *, uint32_t); static void cpufreq_set_all_raw(uint32_t); -static kmutex_t cpufreq_lock __cacheline_aligned; -static struct cpufreq *cf_backend __read_mostly = NULL; +static kmutex_t cpufreq_lock __cacheline_aligned; +static struct cpufreq *cf_backend __read_mostly = NULL; void cpufreq_init(void) { mutex_init(&cpufreq_lock, MUTEX_DEFAULT, IPL_NONE); + cf_backend = kmem_zalloc(sizeof(*cf_backend), KM_SLEEP); } int cpufreq_register(struct cpufreq *cf) { - uint32_t count, i, j, k, m; + uint32_t c, i, j, k, m; int rv; KASSERT(cf != NULL); + KASSERT(cf_backend != NULL); KASSERT(cf->cf_get_freq != NULL); KASSERT(cf->cf_set_freq != NULL); KASSERT(cf->cf_state_count > 0); @@ -72,19 +74,12 @@ cpufreq_register(struct cpufreq *cf) mutex_enter(&cpufreq_lock); - if (cf_backend != NULL) { + if (cf_backend->cf_init != false) { mutex_exit(&cpufreq_lock); return EALREADY; } - mutex_exit(&cpufreq_lock); - cf_backend = kmem_zalloc(sizeof(*cf), KM_SLEEP); - - if (cf_backend == NULL) - return ENOMEM; - - mutex_enter(&cpufreq_lock); - + cf_backend->cf_init = true; cf_backend->cf_mp = cf->cf_mp; cf_backend->cf_cookie = cf->cf_cookie; cf_backend->cf_get_freq = cf->cf_get_freq; @@ -95,7 +90,7 @@ cpufreq_register(struct cpufreq *cf) /* * Sanity check the values and verify descending order. */ - for (count = i = 0; i < cf->cf_state_count; i++) { + for (c = i = 0; i < cf->cf_state_count; i++) { CTASSERT(CPUFREQ_STATE_ENABLED != 0); CTASSERT(CPUFREQ_STATE_DISABLED != 0); @@ -103,6 +98,11 @@ cpufreq_register(struct cpufreq *cf) if (cf->cf_state[i].cfs_freq == 0) continue; + if (cf->cf_state[i].cfs_freq > 9999 && + cf->cf_state[i].cfs_freq != CPUFREQ_STATE_ENABLED && + cf->cf_state[i].cfs_freq != CPUFREQ_STATE_DISABLED) + continue; + for (j = k = 0; j < i; j++) { if (cf->cf_state[i].cfs_freq >= @@ -115,14 +115,14 @@ cpufreq_register(struct cpufreq *cf) if (k != 0) continue; - cf_backend->cf_state[i].cfs_index = count; - cf_backend->cf_state[i].cfs_freq = cf->cf_state[i].cfs_freq; - cf_backend->cf_state[i].cfs_power = cf->cf_state[i].cfs_power; + cf_backend->cf_state[c].cfs_index = c; + cf_backend->cf_state[c].cfs_freq = cf->cf_state[i].cfs_freq; + cf_backend->cf_state[c].cfs_power = cf->cf_state[i].cfs_power; - count++; + c++; } - cf_backend->cf_state_count = count; + cf_backend->cf_state_count = c; if (cf_backend->cf_state_count == 0) { mutex_exit(&cpufreq_lock); @@ -150,15 +150,8 @@ cpufreq_deregister(void) { mutex_enter(&cpufreq_lock); - - if (cf_backend == NULL) { - mutex_exit(&cpufreq_lock); - return; - } - + memset(cf_backend, 0, sizeof(*cf_backend)); mutex_exit(&cpufreq_lock); - kmem_free(cf_backend, sizeof(*cf_backend)); - cf_backend = NULL; } static int @@ -225,13 +218,12 @@ cpufreq_latency(void) void cpufreq_suspend(struct cpu_info *ci) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; uint32_t l, s; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (cf == NULL) { + if (cf->cf_init != true) { mutex_exit(&cpufreq_lock); return; } @@ -248,12 +240,11 @@ cpufreq_suspend(struct cpu_info *ci) void cpufreq_resume(struct cpu_info *ci) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (cf == NULL || cf->cf_state_saved == 0) { + if (cf->cf_init != true || cf->cf_state_saved == 0) { mutex_exit(&cpufreq_lock); return; } @@ -265,13 +256,12 @@ cpufreq_resume(struct cpu_info *ci) uint32_t cpufreq_get(struct cpu_info *ci) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; uint32_t freq; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (cf == NULL) { + if (cf->cf_init != true) { mutex_exit(&cpufreq_lock); return 0; } @@ -287,7 +277,7 @@ cpufreq_get_max(void) { struct cpufreq *cf = cf_backend; - KASSERT(cf != NULL); + KASSERT(cf->cf_init != false); KASSERT(mutex_owned(&cpufreq_lock) != 0); return cf->cf_state[0].cfs_freq; @@ -298,7 +288,7 @@ cpufreq_get_min(void) { struct cpufreq *cf = cf_backend; - KASSERT(cf != NULL); + KASSERT(cf->cf_init != false); KASSERT(mutex_owned(&cpufreq_lock) != 0); return cf->cf_state[cf->cf_state_count - 1].cfs_freq; @@ -311,7 +301,7 @@ cpufreq_get_raw(struct cpu_info *ci) uint32_t freq = 0; uint64_t xc; - KASSERT(cf != NULL); + KASSERT(cf->cf_init != false); KASSERT(mutex_owned(&cpufreq_lock) != 0); xc = xc_unicast(0, (*cf->cf_get_freq), cf->cf_cookie, &freq, ci); @@ -321,17 +311,18 @@ cpufreq_get_raw(struct cpu_info *ci) } int -cpufreq_get_backend(struct cpufreq *cf) +cpufreq_get_backend(struct cpufreq *dst) { + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - if (cf_backend == NULL || cf == NULL) { + if (cf->cf_init != true || dst == NULL) { mutex_exit(&cpufreq_lock); return ENODEV; } - (void)memcpy(cf, cf_backend, sizeof(*cf)); + memcpy(dst, cf, sizeof(*cf)); mutex_exit(&cpufreq_lock); return 0; @@ -340,12 +331,11 @@ cpufreq_get_backend(struct cpufreq *cf) int cpufreq_get_state(uint32_t freq, struct cpufreq_state *cfs) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (cf == NULL || cfs == NULL) { + if (cf->cf_init != true || cfs == NULL) { mutex_exit(&cpufreq_lock); return ENODEV; } @@ -359,12 +349,11 @@ cpufreq_get_state(uint32_t freq, struct int cpufreq_get_state_index(uint32_t index, struct cpufreq_state *cfs) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (cf == NULL || cfs == NULL) { + if (cf->cf_init != true || cfs == NULL) { mutex_exit(&cpufreq_lock); return ENODEV; } @@ -374,7 +363,7 @@ cpufreq_get_state_index(uint32_t index, return EINVAL; } - (void)memcpy(cfs, &cf->cf_state[index], sizeof(*cfs)); + memcpy(cfs, &cf->cf_state[index], sizeof(*cfs)); mutex_exit(&cpufreq_lock); return 0; @@ -386,8 +375,8 @@ cpufreq_get_state_raw(uint32_t freq, str struct cpufreq *cf = cf_backend; uint32_t f, hi, i = 0, lo = 0; - KASSERT(cf != NULL && cfs != NULL); KASSERT(mutex_owned(&cpufreq_lock) != 0); + KASSERT(cf->cf_init != false && cfs != NULL); hi = cf->cf_state_count; @@ -405,18 +394,17 @@ cpufreq_get_state_raw(uint32_t freq, str } } - (void)memcpy(cfs, &cf->cf_state[i], sizeof(*cfs)); + memcpy(cfs, &cf->cf_state[i], sizeof(*cfs)); } void cpufreq_set(struct cpu_info *ci, uint32_t freq) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (__predict_false(cf == NULL)) { + if (__predict_false(cf->cf_init != true)) { mutex_exit(&cpufreq_lock); return; } @@ -431,7 +419,7 @@ cpufreq_set_raw(struct cpu_info *ci, uin struct cpufreq *cf = cf_backend; uint64_t xc; - KASSERT(cf != NULL); + KASSERT(cf->cf_init != false); KASSERT(mutex_owned(&cpufreq_lock) != 0); xc = xc_unicast(0, (*cf->cf_set_freq), cf->cf_cookie, &freq, ci); @@ -441,12 +429,11 @@ cpufreq_set_raw(struct cpu_info *ci, uin void cpufreq_set_all(uint32_t freq) { - struct cpufreq *cf; + struct cpufreq *cf = cf_backend; mutex_enter(&cpufreq_lock); - cf = cf_backend; - if (__predict_false(cf == NULL)) { + if (__predict_false(cf->cf_init != true)) { mutex_exit(&cpufreq_lock); return; } @@ -461,7 +448,7 @@ cpufreq_set_all_raw(uint32_t freq) struct cpufreq *cf = cf_backend; uint64_t xc; - KASSERT(cf != NULL); + KASSERT(cf->cf_init != false); KASSERT(mutex_owned(&cpufreq_lock) != 0); xc = xc_broadcast(0, (*cf->cf_set_freq), cf->cf_cookie, &freq); @@ -484,15 +471,15 @@ cpufreq_set_lower(struct cpu_info *ci) static void cpufreq_set_step(struct cpu_info *ci, int32_t step) { + struct cpufreq *cf = cf_backend; struct cpufreq_state cfs; - struct cpufreq *cf; uint32_t freq; int32_t index; mutex_enter(&cpufreq_lock); cf = cf_backend; - if (__predict_false(cf == NULL)) { + if (__predict_false(cf->cf_init != true)) { mutex_exit(&cpufreq_lock); return; } Index: src/sys/sys/cpufreq.h diff -u src/sys/sys/cpufreq.h:1.2 src/sys/sys/cpufreq.h:1.3 --- src/sys/sys/cpufreq.h:1.2 Wed Sep 28 15:52:47 2011 +++ src/sys/sys/cpufreq.h Fri Sep 30 04:01:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpufreq.h,v 1.2 2011/09/28 15:52:47 jruoho Exp $ */ +/* $NetBSD: cpufreq.h,v 1.3 2011/09/30 04:01:21 jruoho Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ #endif #define CPUFREQ_NAME_MAX 16 -#define CPUFREQ_STATE_MAX 64 +#define CPUFREQ_STATE_MAX 32 #define CPUFREQ_LATENCY_MAX UINT16_MAX /* Maximum per-CPU latency */ #define CPUFREQ_STATE_ENABLED UINT32_MAX @@ -67,6 +67,7 @@ struct cpufreq { #ifdef _KERNEL bool cf_mp; + bool cf_init; void *cf_cookie; xcfunc_t cf_get_freq; xcfunc_t cf_set_freq;