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;