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 --- |