static int acpicpu_once_detach(void) { struct acpicpu_softc *sc; if (acpicpu_count != 0) return EDEADLK; cpufreq_deregister(); if (acpicpu_log != NULL) sysctl_teardown(&acpicpu_log); if (acpicpu_sc != NULL) kmem_free(acpicpu_sc, maxcpus * sizeof(*sc)); return 0; }
int cpufreq_register(struct cpufreq *cf) { uint32_t c, i, j, k, m; int rv; if (cold != 0) return EBUSY; 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); KASSERT(cf->cf_state_count < CPUFREQ_STATE_MAX); mutex_enter(&cpufreq_lock); if (cf_backend->cf_init != false) { mutex_exit(&cpufreq_lock); return EALREADY; } 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; cf_backend->cf_set_freq = cf->cf_set_freq; (void)strlcpy(cf_backend->cf_name, cf->cf_name, sizeof(cf->cf_name)); /* * Sanity check the values and verify descending order. */ for (c = i = 0; i < cf->cf_state_count; i++) { CTASSERT(CPUFREQ_STATE_ENABLED != 0); CTASSERT(CPUFREQ_STATE_DISABLED != 0); 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 >= cf->cf_state[j].cfs_freq) { k = 1; break; } } if (k != 0) continue; 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; c++; } cf_backend->cf_state_count = c; if (cf_backend->cf_state_count == 0) { mutex_exit(&cpufreq_lock); cpufreq_deregister(); return EINVAL; } rv = cpufreq_latency(); if (rv != 0) { mutex_exit(&cpufreq_lock); cpufreq_deregister(); return rv; } m = cpufreq_get_max(); cpufreq_set_all_raw(m); mutex_exit(&cpufreq_lock); return 0; }