Deleted Added
full compact
kern_cpu.c (149239) kern_cpu.c (149607)
1/*-
2 * Copyright (c) 2004-2005 Nate Lawson (SDG)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004-2005 Nate Lawson (SDG)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/kern/kern_cpu.c 149239 2005-08-18 16:41:25Z ume $");
28__FBSDID("$FreeBSD: head/sys/kern/kern_cpu.c 149607 2005-08-30 04:45:32Z njl $");
29
30#include <sys/param.h>
31#include <sys/bus.h>
32#include <sys/cpu.h>
33#include <sys/eventhandler.h>
34#include <sys/kernel.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>

--- 608 unchanged lines hidden (view full) ---

645cpufreq_expand_set(struct cpufreq_softc *sc, struct cf_setting_array *set_arr)
646{
647 struct cf_level *fill, *search;
648 struct cf_setting *set;
649 int i;
650
651 CF_MTX_ASSERT(&sc->lock);
652
29
30#include <sys/param.h>
31#include <sys/bus.h>
32#include <sys/cpu.h>
33#include <sys/eventhandler.h>
34#include <sys/kernel.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>

--- 608 unchanged lines hidden (view full) ---

645cpufreq_expand_set(struct cpufreq_softc *sc, struct cf_setting_array *set_arr)
646{
647 struct cf_level *fill, *search;
648 struct cf_setting *set;
649 int i;
650
651 CF_MTX_ASSERT(&sc->lock);
652
653 TAILQ_FOREACH(search, &sc->all_levels, link) {
654 /* Skip this level if we've already modified it. */
655 for (i = 0; i < search->rel_count; i++) {
656 if (search->rel_set[i].dev == set_arr->sets[0].dev)
657 break;
658 }
659 if (i != search->rel_count) {
660 CF_DEBUG("skipping modified level, freq %d (dev %s)\n",
661 search->total_set.freq,
662 device_get_nameunit(search->rel_set[i].dev));
663 continue;
664 }
665
653 /*
654 * Walk the set of all existing levels in reverse. This is so we
655 * create derived states from the lowest absolute settings first
656 * and discard duplicates created from higher absolute settings.
657 * For instance, a level of 50 Mhz derived from 100 Mhz + 50% is
658 * preferable to 200 Mhz + 25% because absolute settings are more
659 * efficient since they often change the voltage as well.
660 */
661 TAILQ_FOREACH_REVERSE(search, &sc->all_levels, cf_level_lst, link) {
666 /* Add each setting to the level, duplicating if necessary. */
667 for (i = 0; i < set_arr->count; i++) {
668 set = &set_arr->sets[i];
669
670 /*
671 * If this setting is less than 100%, split the level
672 * into two and add this setting to the new level.
673 */
674 fill = search;
662 /* Add each setting to the level, duplicating if necessary. */
663 for (i = 0; i < set_arr->count; i++) {
664 set = &set_arr->sets[i];
665
666 /*
667 * If this setting is less than 100%, split the level
668 * into two and add this setting to the new level.
669 */
670 fill = search;
675 if (set->freq < 10000)
671 if (set->freq < 10000) {
676 fill = cpufreq_dup_set(sc, search, set);
677
672 fill = cpufreq_dup_set(sc, search, set);
673
678 /*
679 * The new level was a duplicate of an existing level
680 * so we freed it. Go to the next setting.
681 */
682 if (fill == NULL)
683 continue;
674 /*
675 * The new level was a duplicate of an existing
676 * level or its absolute setting is too high
677 * so we freed it. For example, we discard a
678 * derived level of 1000 MHz/25% if a level
679 * of 500 MHz/100% already exists.
680 */
681 if (fill == NULL)
682 break;
683 }
684
685 /* Add this setting to the existing or new level. */
686 KASSERT(fill->rel_count < MAX_SETTINGS,
687 ("cpufreq: too many relative drivers (%d)",
688 MAX_SETTINGS));
689 fill->rel_set[fill->rel_count] = *set;
690 fill->rel_count++;
691 CF_DEBUG(

--- 50 unchanged lines hidden (view full) ---

742 if (fill->rel_set[i - 1].dev != set->dev)
743 break;
744 CF_DEBUG("removed last relative driver: %s\n",
745 device_get_nameunit(set->dev));
746 fill->rel_count--;
747 }
748
749 /*
684
685 /* Add this setting to the existing or new level. */
686 KASSERT(fill->rel_count < MAX_SETTINGS,
687 ("cpufreq: too many relative drivers (%d)",
688 MAX_SETTINGS));
689 fill->rel_set[fill->rel_count] = *set;
690 fill->rel_count++;
691 CF_DEBUG(

--- 50 unchanged lines hidden (view full) ---

742 if (fill->rel_set[i - 1].dev != set->dev)
743 break;
744 CF_DEBUG("removed last relative driver: %s\n",
745 device_get_nameunit(set->dev));
746 fill->rel_count--;
747 }
748
749 /*
750 * Insert the new level in sorted order. If we find a duplicate,
751 * free the new level. We can do this since any existing level will
752 * be guaranteed to have the same or less settings and thus consume
753 * less power. For example, a level with one absolute setting of
754 * 800 Mhz uses less power than one composed of an absolute setting
755 * of 1600 Mhz and a relative setting at 50%.
750 * Insert the new level in sorted order. If it is a duplicate of an
751 * existing level (1) or has an absolute setting higher than the
752 * existing level (2), do not add it. We can do this since any such
753 * level is guaranteed use less power. For example (1), a level with
754 * one absolute setting of 800 Mhz uses less power than one composed
755 * of an absolute setting of 1600 Mhz and a relative setting at 50%.
756 * Also for example (2), a level of 800 Mhz/75% is preferable to
757 * 1600 Mhz/25% even though the latter has a lower total frequency.
756 */
757 list = &sc->all_levels;
758 */
759 list = &sc->all_levels;
758 if (TAILQ_EMPTY(list)) {
759 CF_DEBUG("dup done, inserted %d at head\n", fill_set->freq);
760 TAILQ_INSERT_HEAD(list, fill, link);
761 } else {
762 TAILQ_FOREACH_REVERSE(itr, list, cf_level_lst, link) {
763 itr_set = &itr->total_set;
764 if (CPUFREQ_CMP(fill_set->freq, itr_set->freq)) {
765 CF_DEBUG(
766 "dup done, freeing new level %d, matches %d\n",
767 fill_set->freq, itr_set->freq);
768 free(fill, M_TEMP);
769 fill = NULL;
770 break;
771 } else if (fill_set->freq < itr_set->freq) {
772 CF_DEBUG(
773 "dup done, inserting new level %d after %d\n",
774 fill_set->freq, itr_set->freq);
775 TAILQ_INSERT_AFTER(list, itr, fill, link);
776 sc->all_count++;
777 break;
778 }
760 KASSERT(!TAILQ_EMPTY(list), ("all levels list empty in dup set"));
761 TAILQ_FOREACH_REVERSE(itr, list, cf_level_lst, link) {
762 itr_set = &itr->total_set;
763 if (fill_set->freq < itr_set->freq &&
764 !CPUFREQ_CMP(fill_set->freq, itr_set->freq) &&
765 fill->abs_set.freq <= itr->abs_set.freq) {
766 CF_DEBUG(
767 "dup done, inserting new level %d after %d\n",
768 fill_set->freq, itr_set->freq);
769 TAILQ_INSERT_AFTER(list, itr, fill, link);
770 sc->all_count++;
771 break;
779 }
780 }
781
772 }
773 }
774
775 /* We didn't find a good place for this new level so free it. */
776 if (itr == NULL) {
777 CF_DEBUG("dup set freeing new level %d (not optimal)\n",
778 fill_set->freq);
779 free(fill, M_TEMP);
780 fill = NULL;
781 }
782
782 return (fill);
783}
784
785static int
786cpufreq_curr_sysctl(SYSCTL_HANDLER_ARGS)
787{
788 struct cpufreq_softc *sc;
789 struct cf_level *levels;

--- 194 unchanged lines hidden ---
783 return (fill);
784}
785
786static int
787cpufreq_curr_sysctl(SYSCTL_HANDLER_ARGS)
788{
789 struct cpufreq_softc *sc;
790 struct cf_level *levels;

--- 194 unchanged lines hidden ---