From: Rafael J. Wysocki Date: Fri, 12 Aug 2016 20:53:58 +0000 (+0200) Subject: Merge branches 'pm-sleep' and 'pm-cpufreq' X-Git-Tag: v4.8-rc2~9^2 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Flinux.git;a=commitdiff_plain;h=0aeeb3e73f5fd7faef3dce8cb590effd6ee51571 Merge branches 'pm-sleep' and 'pm-cpufreq' * pm-sleep: PM / hibernate: Restore processor state before using per-CPU variables x86/power/64: Always create temporary identity mapping correctly * pm-cpufreq: cpufreq: powernv: Fix crash in gpstate_timer_handler() --- 0aeeb3e73f5fd7faef3dce8cb590effd6ee51571 diff --cc drivers/cpufreq/powernv-cpufreq.c index 87796e0864e9,54c45368e3f1,2fcc879d2b97..d3ffde806629 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@@@ -126,38 -124,20 -126,57 +126,57 @@@@ static int nr_chips static DEFINE_PER_CPU(struct chip *, chip_info); /* - * Note: The set of pstates consists of contiguous integers, the - * smallest of which is indicated by powernv_pstate_info.min, the - * largest of which is indicated by powernv_pstate_info.max. + * Note: + * The set of pstates consists of contiguous integers. + * powernv_pstate_info stores the index of the frequency table for + * max, min and nominal frequencies. It also stores number of + * available frequencies. * - * The nominal pstate is the highest non-turbo pstate in this - * platform. This is indicated by powernv_pstate_info.nominal. + * powernv_pstate_info.nominal indicates the index to the highest + * non-turbo frequency. */ static struct powernv_pstate_info { - int min; - int max; - int nominal; - int nr_pstates; + unsigned int min; + unsigned int max; + unsigned int nominal; + unsigned int nr_pstates; } powernv_pstate_info; + /* Use following macros for conversions between pstate_id and index */ + static inline int idx_to_pstate(unsigned int i) + { ++ if (unlikely(i >= powernv_pstate_info.nr_pstates)) { ++ pr_warn_once("index %u is out of bound\n", i); ++ return powernv_freqs[powernv_pstate_info.nominal].driver_data; ++ } ++ + return powernv_freqs[i].driver_data; + } + + static inline unsigned int pstate_to_idx(int pstate) + { ++ int min = powernv_freqs[powernv_pstate_info.min].driver_data; ++ int max = powernv_freqs[powernv_pstate_info.max].driver_data; ++ ++ if (min > 0) { ++ if (unlikely((pstate < max) || (pstate > min))) { ++ pr_warn_once("pstate %d is out of bound\n", pstate); ++ return powernv_pstate_info.nominal; ++ } ++ } else { ++ if (unlikely((pstate > max) || (pstate < min))) { ++ pr_warn_once("pstate %d is out of bound\n", pstate); ++ return powernv_pstate_info.nominal; ++ } ++ } + /* + * abs() is deliberately used so that is works with + * both monotonically increasing and decreasing + * pstate values + */ + return abs(pstate - idx_to_pstate(powernv_pstate_info.max)); + } + static inline void reset_gpstates(struct cpufreq_policy *policy) { struct global_pstate_info *gpstates = policy->driver_data; @@@@ -583,17 -557,17 -603,17 +602,17 @@@@ void gpstate_timer_handler(unsigned lon gpstates->last_sampled_time += time_diff; gpstates->elapsed_time += time_diff; - freq_data.pstate_id = gpstates->last_lpstate; + freq_data.pstate_id = idx_to_pstate(gpstates->last_lpstate_idx); - if ((gpstates->last_gpstate == freq_data.pstate_id) || + if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) || (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) { - gpstate_id = freq_data.pstate_id; + gpstate_idx = pstate_to_idx(freq_data.pstate_id); reset_gpstates(policy); - gpstates->highest_lpstate = freq_data.pstate_id; + gpstates->highest_lpstate_idx = gpstate_idx; } else { - gpstate_id = calc_global_pstate(gpstates->elapsed_time, - gpstates->highest_lpstate, - freq_data.pstate_id); + gpstate_idx = calc_global_pstate(gpstates->elapsed_time, + gpstates->highest_lpstate_idx, - freq_data.pstate_id); ++ gpstates->last_lpstate_idx); } /*