Deleted Added
full compact
28c28
< __FBSDID("$FreeBSD: head/sys/kern/kern_cpu.c 149239 2005-08-18 16:41:25Z ume $");
---
> __FBSDID("$FreeBSD: head/sys/kern/kern_cpu.c 149607 2005-08-30 04:45:32Z njl $");
653,665c653,661
< TAILQ_FOREACH(search, &sc->all_levels, link) {
< /* Skip this level if we've already modified it. */
< for (i = 0; i < search->rel_count; i++) {
< if (search->rel_set[i].dev == set_arr->sets[0].dev)
< break;
< }
< if (i != search->rel_count) {
< CF_DEBUG("skipping modified level, freq %d (dev %s)\n",
< search->total_set.freq,
< device_get_nameunit(search->rel_set[i].dev));
< continue;
< }
<
---
> /*
> * Walk the set of all existing levels in reverse. This is so we
> * create derived states from the lowest absolute settings first
> * and discard duplicates created from higher absolute settings.
> * For instance, a level of 50 Mhz derived from 100 Mhz + 50% is
> * preferable to 200 Mhz + 25% because absolute settings are more
> * efficient since they often change the voltage as well.
> */
> TAILQ_FOREACH_REVERSE(search, &sc->all_levels, cf_level_lst, link) {
675c671
< if (set->freq < 10000)
---
> if (set->freq < 10000) {
678,683c674,683
< /*
< * The new level was a duplicate of an existing level
< * so we freed it. Go to the next setting.
< */
< if (fill == NULL)
< continue;
---
> /*
> * The new level was a duplicate of an existing
> * level or its absolute setting is too high
> * so we freed it. For example, we discard a
> * derived level of 1000 MHz/25% if a level
> * of 500 MHz/100% already exists.
> */
> if (fill == NULL)
> break;
> }
750,755c750,757
< * Insert the new level in sorted order. If we find a duplicate,
< * free the new level. We can do this since any existing level will
< * be guaranteed to have the same or less settings and thus consume
< * less power. For example, a level with one absolute setting of
< * 800 Mhz uses less power than one composed of an absolute setting
< * of 1600 Mhz and a relative setting at 50%.
---
> * Insert the new level in sorted order. If it is a duplicate of an
> * existing level (1) or has an absolute setting higher than the
> * existing level (2), do not add it. We can do this since any such
> * level is guaranteed use less power. For example (1), a level with
> * one absolute setting of 800 Mhz uses less power than one composed
> * of an absolute setting of 1600 Mhz and a relative setting at 50%.
> * Also for example (2), a level of 800 Mhz/75% is preferable to
> * 1600 Mhz/25% even though the latter has a lower total frequency.
758,778c760,771
< if (TAILQ_EMPTY(list)) {
< CF_DEBUG("dup done, inserted %d at head\n", fill_set->freq);
< TAILQ_INSERT_HEAD(list, fill, link);
< } else {
< TAILQ_FOREACH_REVERSE(itr, list, cf_level_lst, link) {
< itr_set = &itr->total_set;
< if (CPUFREQ_CMP(fill_set->freq, itr_set->freq)) {
< CF_DEBUG(
< "dup done, freeing new level %d, matches %d\n",
< fill_set->freq, itr_set->freq);
< free(fill, M_TEMP);
< fill = NULL;
< break;
< } else if (fill_set->freq < itr_set->freq) {
< CF_DEBUG(
< "dup done, inserting new level %d after %d\n",
< fill_set->freq, itr_set->freq);
< TAILQ_INSERT_AFTER(list, itr, fill, link);
< sc->all_count++;
< break;
< }
---
> KASSERT(!TAILQ_EMPTY(list), ("all levels list empty in dup set"));
> TAILQ_FOREACH_REVERSE(itr, list, cf_level_lst, link) {
> itr_set = &itr->total_set;
> if (fill_set->freq < itr_set->freq &&
> !CPUFREQ_CMP(fill_set->freq, itr_set->freq) &&
> fill->abs_set.freq <= itr->abs_set.freq) {
> CF_DEBUG(
> "dup done, inserting new level %d after %d\n",
> fill_set->freq, itr_set->freq);
> TAILQ_INSERT_AFTER(list, itr, fill, link);
> sc->all_count++;
> break;
781a775,782
> /* We didn't find a good place for this new level so free it. */
> if (itr == NULL) {
> CF_DEBUG("dup set freeing new level %d (not optimal)\n",
> fill_set->freq);
> free(fill, M_TEMP);
> fill = NULL;
> }
>