Merge branch 'pm-cpufreq-sched' into pm-cpufreq
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 8 Apr 2016 23:08:02 +0000 (01:08 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 8 Apr 2016 23:08:02 +0000 (01:08 +0200)
1  2 
drivers/cpufreq/intel_pstate.c

@@@ -64,25 -64,6 +64,25 @@@ static inline int ceiling_fp(int32_t x
        return ret;
  }
  
 +/**
 + * struct sample -    Store performance sample
 + * @core_pct_busy:    Ratio of APERF/MPERF in percent, which is actual
 + *                    performance during last sample period
 + * @busy_scaled:      Scaled busy value which is used to calculate next
 + *                    P state. This can be different than core_pct_busy
 + *                    to account for cpu idle period
 + * @aperf:            Difference of actual performance frequency clock count
 + *                    read from APERF MSR between last and current sample
 + * @mperf:            Difference of maximum performance frequency clock count
 + *                    read from MPERF MSR between last and current sample
 + * @tsc:              Difference of time stamp counter between last and
 + *                    current sample
 + * @freq:             Effective frequency calculated from APERF/MPERF
 + * @time:             Current time from scheduler
 + *
 + * This structure is used in the cpudata structure to store performance sample
 + * data for choosing next P State.
 + */
  struct sample {
        int32_t core_pct_busy;
        int32_t busy_scaled;
        u64 time;
  };
  
 +/**
 + * struct pstate_data - Store P state data
 + * @current_pstate:   Current requested P state
 + * @min_pstate:               Min P state possible for this platform
 + * @max_pstate:               Max P state possible for this platform
 + * @max_pstate_physical:This is physical Max P state for a processor
 + *                    This can be higher than the max_pstate which can
 + *                    be limited by platform thermal design power limits
 + * @scaling:          Scaling factor to  convert frequency to cpufreq
 + *                    frequency units
 + * @turbo_pstate:     Max Turbo P state possible for this platform
 + *
 + * Stores the per cpu model P state limits and current P state.
 + */
  struct pstate_data {
        int     current_pstate;
        int     min_pstate;
        int     turbo_pstate;
  };
  
 +/**
 + * struct vid_data -  Stores voltage information data
 + * @min:              VID data for this platform corresponding to
 + *                    the lowest P state
 + * @max:              VID data corresponding to the highest P State.
 + * @turbo:            VID data for turbo P state
 + * @ratio:            Ratio of (vid max - vid min) /
 + *                    (max P state - Min P State)
 + *
 + * Stores the voltage data for DVFS (Dynamic Voltage and Frequency Scaling)
 + * This data is used in Atom platforms, where in addition to target P state,
 + * the voltage data needs to be specified to select next P State.
 + */
  struct vid_data {
        int min;
        int max;
        int32_t ratio;
  };
  
 +/**
 + * struct _pid -      Stores PID data
 + * @setpoint:         Target set point for busyness or performance
 + * @integral:         Storage for accumulated error values
 + * @p_gain:           PID proportional gain
 + * @i_gain:           PID integral gain
 + * @d_gain:           PID derivative gain
 + * @deadband:         PID deadband
 + * @last_err:         Last error storage for integral part of PID calculation
 + *
 + * Stores PID coefficients and last error for PID controller.
 + */
  struct _pid {
        int setpoint;
        int32_t integral;
        int32_t last_err;
  };
  
 +/**
 + * struct cpudata -   Per CPU instance data storage
 + * @cpu:              CPU number for this instance data
 + * @update_util:      CPUFreq utility callback information
 + * @pstate:           Stores P state limits for this CPU
 + * @vid:              Stores VID limits for this CPU
 + * @pid:              Stores PID parameters for this CPU
 + * @last_sample_time: Last Sample time
 + * @prev_aperf:               Last APERF value read from APERF MSR
 + * @prev_mperf:               Last MPERF value read from MPERF MSR
 + * @prev_tsc:         Last timestamp counter (TSC) value
 + * @prev_cummulative_iowait: IO Wait time difference from last and
 + *                    current sample
 + * @sample:           Storage for storing last Sample data
 + *
 + * This structure stores per CPU instance data for all CPUs.
 + */
  struct cpudata {
        int cpu;
  
  };
  
  static struct cpudata **all_cpu_data;
 +
 +/**
 + * struct pid_adjust_policy - Stores static PID configuration data
 + * @sample_rate_ms:   PID calculation sample rate in ms
 + * @sample_rate_ns:   Sample rate calculation in ns
 + * @deadband:         PID deadband
 + * @setpoint:         PID Setpoint
 + * @p_gain_pct:               PID proportional gain
 + * @i_gain_pct:               PID integral gain
 + * @d_gain_pct:               PID derivative gain
 + *
 + * Stores per CPU model static PID configuration data.
 + */
  struct pstate_adjust_policy {
        int sample_rate_ms;
        s64 sample_rate_ns;
        int i_gain_pct;
  };
  
 +/**
 + * struct pstate_funcs - Per CPU model specific callbacks
 + * @get_max:          Callback to get maximum non turbo effective P state
 + * @get_max_physical: Callback to get maximum non turbo physical P state
 + * @get_min:          Callback to get minimum P state
 + * @get_turbo:                Callback to get turbo P state
 + * @get_scaling:      Callback to get frequency scaling factor
 + * @get_val:          Callback to convert P state to actual MSR write value
 + * @get_vid:          Callback to get VID data for Atom platforms
 + * @get_target_pstate:        Callback to a function to calculate next P state to use
 + *
 + * Core and Atom CPU models have different way to get P State limits. This
 + * structure is used to store those callbacks.
 + */
  struct pstate_funcs {
        int (*get_max)(void);
        int (*get_max_physical)(void);
        int32_t (*get_target_pstate)(struct cpudata *);
  };
  
 +/**
 + * struct cpu_defaults- Per CPU model default config data
 + * @pid_policy:       PID config data
 + * @funcs:            Callback function data
 + */
  struct cpu_defaults {
        struct pstate_adjust_policy pid_policy;
        struct pstate_funcs funcs;
@@@ -258,34 -151,6 +258,34 @@@ static struct pstate_adjust_policy pid_
  static struct pstate_funcs pstate_funcs;
  static int hwp_active;
  
 +
 +/**
 + * struct perf_limits - Store user and policy limits
 + * @no_turbo:         User requested turbo state from intel_pstate sysfs
 + * @turbo_disabled:   Platform turbo status either from msr
 + *                    MSR_IA32_MISC_ENABLE or when maximum available pstate
 + *                    matches the maximum turbo pstate
 + * @max_perf_pct:     Effective maximum performance limit in percentage, this
 + *                    is minimum of either limits enforced by cpufreq policy
 + *                    or limits from user set limits via intel_pstate sysfs
 + * @min_perf_pct:     Effective minimum performance limit in percentage, this
 + *                    is maximum of either limits enforced by cpufreq policy
 + *                    or limits from user set limits via intel_pstate sysfs
 + * @max_perf:         This is a scaled value between 0 to 255 for max_perf_pct
 + *                    This value is used to limit max pstate
 + * @min_perf:         This is a scaled value between 0 to 255 for min_perf_pct
 + *                    This value is used to limit min pstate
 + * @max_policy_pct:   The maximum performance in percentage enforced by
 + *                    cpufreq setpolicy interface
 + * @max_sysfs_pct:    The maximum performance in percentage enforced by
 + *                    intel pstate sysfs interface
 + * @min_policy_pct:   The minimum performance in percentage enforced by
 + *                    cpufreq setpolicy interface
 + * @min_sysfs_pct:    The minimum performance in percentage enforced by
 + *                    intel pstate sysfs interface
 + *
 + * Storage for user and policy defined limits.
 + */
  struct perf_limits {
        int no_turbo;
        int turbo_disabled;
@@@ -1242,8 -1107,6 +1242,6 @@@ static int intel_pstate_init_cpu(unsign
  
        intel_pstate_busy_pid_reset(cpu);
  
-       cpu->update_util.func = intel_pstate_update_util;
        pr_debug("intel_pstate: controlling: cpu %d\n", cpunum);
  
        return 0;
@@@ -1267,29 -1130,16 +1265,30 @@@ static void intel_pstate_set_update_uti
  
        /* Prevent intel_pstate_update_util() from using stale data. */
        cpu->sample.time = 0;
-       cpufreq_set_update_util_data(cpu_num, &cpu->update_util);
+       cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
+                                    intel_pstate_update_util);
  }
  
  static void intel_pstate_clear_update_util_hook(unsigned int cpu)
  {
-       cpufreq_set_update_util_data(cpu, NULL);
+       cpufreq_remove_update_util_hook(cpu);
        synchronize_sched();
  }
  
 +static void intel_pstate_set_performance_limits(struct perf_limits *limits)
 +{
 +      limits->no_turbo = 0;
 +      limits->turbo_disabled = 0;
 +      limits->max_perf_pct = 100;
 +      limits->max_perf = int_tofp(1);
 +      limits->min_perf_pct = 100;
 +      limits->min_perf = int_tofp(1);
 +      limits->max_policy_pct = 100;
 +      limits->max_sysfs_pct = 100;
 +      limits->min_policy_pct = 0;
 +      limits->min_sysfs_pct = 0;
 +}
 +
  static int intel_pstate_set_policy(struct cpufreq_policy *policy)
  {
        if (!policy->cpuinfo.max_freq)
  
        intel_pstate_clear_update_util_hook(policy->cpu);
  
 -      if (policy->policy == CPUFREQ_POLICY_PERFORMANCE &&
 -          policy->max >= policy->cpuinfo.max_freq) {
 -              pr_debug("intel_pstate: set performance\n");
 +      if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
                limits = &performance_limits;
 -              goto out;
 +              if (policy->max >= policy->cpuinfo.max_freq) {
 +                      pr_debug("intel_pstate: set performance\n");
 +                      intel_pstate_set_performance_limits(limits);
 +                      goto out;
 +              }
 +      } else {
 +              pr_debug("intel_pstate: set powersave\n");
 +              limits = &powersave_limits;
        }
  
 -      pr_debug("intel_pstate: set powersave\n");
 -      limits = &powersave_limits;
        limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
        limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
        limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,