| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|---|
| 2 | /* | 
|---|
| 3 | * drivers/cpufreq/cpufreq_governor.h | 
|---|
| 4 | * | 
|---|
| 5 | * Header file for CPUFreq governors common code | 
|---|
| 6 | * | 
|---|
| 7 | * Copyright	(C) 2001 Russell King | 
|---|
| 8 | *		(C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. | 
|---|
| 9 | *		(C) 2003 Jun Nakajima <jun.nakajima@intel.com> | 
|---|
| 10 | *		(C) 2009 Alexander Clouter <alex@digriz.org.uk> | 
|---|
| 11 | *		(c) 2012 Viresh Kumar <viresh.kumar@linaro.org> | 
|---|
| 12 | */ | 
|---|
| 13 |  | 
|---|
| 14 | #ifndef _CPUFREQ_GOVERNOR_H | 
|---|
| 15 | #define _CPUFREQ_GOVERNOR_H | 
|---|
| 16 |  | 
|---|
| 17 | #include <linux/atomic.h> | 
|---|
| 18 | #include <linux/irq_work.h> | 
|---|
| 19 | #include <linux/cpufreq.h> | 
|---|
| 20 | #include <linux/sched/cpufreq.h> | 
|---|
| 21 | #include <linux/kernel_stat.h> | 
|---|
| 22 | #include <linux/module.h> | 
|---|
| 23 | #include <linux/mutex.h> | 
|---|
| 24 |  | 
|---|
| 25 | /* Ondemand Sampling types */ | 
|---|
| 26 | enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; | 
|---|
| 27 |  | 
|---|
| 28 | /* | 
|---|
| 29 | * Abbreviations: | 
|---|
| 30 | * dbs: used as a shortform for demand based switching It helps to keep variable | 
|---|
| 31 | *	names smaller, simpler | 
|---|
| 32 | * cdbs: common dbs | 
|---|
| 33 | * od_*: On-demand governor | 
|---|
| 34 | * cs_*: Conservative governor | 
|---|
| 35 | */ | 
|---|
| 36 |  | 
|---|
| 37 | /* Governor demand based switching data (per-policy or global). */ | 
|---|
| 38 | struct dbs_data { | 
|---|
| 39 | struct gov_attr_set attr_set; | 
|---|
| 40 | struct dbs_governor *gov; | 
|---|
| 41 | void *tuners; | 
|---|
| 42 | unsigned int ignore_nice_load; | 
|---|
| 43 | unsigned int sampling_rate; | 
|---|
| 44 | unsigned int sampling_down_factor; | 
|---|
| 45 | unsigned int up_threshold; | 
|---|
| 46 | unsigned int io_is_busy; | 
|---|
| 47 | }; | 
|---|
| 48 |  | 
|---|
| 49 | static inline struct dbs_data *to_dbs_data(struct gov_attr_set *attr_set) | 
|---|
| 50 | { | 
|---|
| 51 | return container_of(attr_set, struct dbs_data, attr_set); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | #define gov_show_one(_gov, file_name)					\ | 
|---|
| 55 | static ssize_t file_name##_show						\ | 
|---|
| 56 | (struct gov_attr_set *attr_set, char *buf)				\ | 
|---|
| 57 | {									\ | 
|---|
| 58 | struct dbs_data *dbs_data = to_dbs_data(attr_set);		\ | 
|---|
| 59 | struct _gov##_dbs_tuners *tuners = dbs_data->tuners;		\ | 
|---|
| 60 | return sprintf(buf, "%u\n", tuners->file_name);			\ | 
|---|
| 61 | } | 
|---|
| 62 |  | 
|---|
| 63 | #define gov_show_one_common(file_name)					\ | 
|---|
| 64 | static ssize_t file_name##_show						\ | 
|---|
| 65 | (struct gov_attr_set *attr_set, char *buf)				\ | 
|---|
| 66 | {									\ | 
|---|
| 67 | struct dbs_data *dbs_data = to_dbs_data(attr_set);		\ | 
|---|
| 68 | return sprintf(buf, "%u\n", dbs_data->file_name);		\ | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | #define gov_attr_ro(_name)						\ | 
|---|
| 72 | static struct governor_attr _name = __ATTR_RO(_name) | 
|---|
| 73 |  | 
|---|
| 74 | #define gov_attr_rw(_name)						\ | 
|---|
| 75 | static struct governor_attr _name = __ATTR_RW(_name) | 
|---|
| 76 |  | 
|---|
| 77 | /* Common to all CPUs of a policy */ | 
|---|
| 78 | struct policy_dbs_info { | 
|---|
| 79 | struct cpufreq_policy *policy; | 
|---|
| 80 | /* | 
|---|
| 81 | * Per policy mutex that serializes load evaluation from limit-change | 
|---|
| 82 | * and work-handler. | 
|---|
| 83 | */ | 
|---|
| 84 | struct mutex update_mutex; | 
|---|
| 85 |  | 
|---|
| 86 | u64 last_sample_time; | 
|---|
| 87 | s64 sample_delay_ns; | 
|---|
| 88 | atomic_t work_count; | 
|---|
| 89 | struct irq_work irq_work; | 
|---|
| 90 | struct work_struct work; | 
|---|
| 91 | /* dbs_data may be shared between multiple policy objects */ | 
|---|
| 92 | struct dbs_data *dbs_data; | 
|---|
| 93 | struct list_head list; | 
|---|
| 94 | /* Multiplier for increasing sample delay temporarily. */ | 
|---|
| 95 | unsigned int rate_mult; | 
|---|
| 96 | unsigned int idle_periods;	/* For conservative */ | 
|---|
| 97 | /* Status indicators */ | 
|---|
| 98 | bool is_shared;		/* This object is used by multiple CPUs */ | 
|---|
| 99 | bool work_in_progress;	/* Work is being queued up or in progress */ | 
|---|
| 100 | }; | 
|---|
| 101 |  | 
|---|
| 102 | static inline void gov_update_sample_delay(struct policy_dbs_info *policy_dbs, | 
|---|
| 103 | unsigned int delay_us) | 
|---|
| 104 | { | 
|---|
| 105 | policy_dbs->sample_delay_ns = delay_us * NSEC_PER_USEC; | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | /* Per cpu structures */ | 
|---|
| 109 | struct cpu_dbs_info { | 
|---|
| 110 | u64 prev_cpu_idle; | 
|---|
| 111 | u64 prev_update_time; | 
|---|
| 112 | u64 prev_cpu_nice; | 
|---|
| 113 | /* | 
|---|
| 114 | * Used to keep track of load in the previous interval. However, when | 
|---|
| 115 | * explicitly set to zero, it is used as a flag to ensure that we copy | 
|---|
| 116 | * the previous load to the current interval only once, upon the first | 
|---|
| 117 | * wake-up from idle. | 
|---|
| 118 | */ | 
|---|
| 119 | unsigned int prev_load; | 
|---|
| 120 | struct update_util_data update_util; | 
|---|
| 121 | struct policy_dbs_info *policy_dbs; | 
|---|
| 122 | }; | 
|---|
| 123 |  | 
|---|
| 124 | /* Common Governor data across policies */ | 
|---|
| 125 | struct dbs_governor { | 
|---|
| 126 | struct cpufreq_governor gov; | 
|---|
| 127 | struct kobj_type kobj_type; | 
|---|
| 128 |  | 
|---|
| 129 | /* | 
|---|
| 130 | * Common data for platforms that don't set | 
|---|
| 131 | * CPUFREQ_HAVE_GOVERNOR_PER_POLICY | 
|---|
| 132 | */ | 
|---|
| 133 | struct dbs_data *gdbs_data; | 
|---|
| 134 |  | 
|---|
| 135 | unsigned int (*gov_dbs_update)(struct cpufreq_policy *policy); | 
|---|
| 136 | struct policy_dbs_info *(*alloc)(void); | 
|---|
| 137 | void (*free)(struct policy_dbs_info *policy_dbs); | 
|---|
| 138 | int (*init)(struct dbs_data *dbs_data); | 
|---|
| 139 | void (*exit)(struct dbs_data *dbs_data); | 
|---|
| 140 | void (*start)(struct cpufreq_policy *policy); | 
|---|
| 141 | }; | 
|---|
| 142 |  | 
|---|
| 143 | static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy) | 
|---|
| 144 | { | 
|---|
| 145 | return container_of(policy->governor, struct dbs_governor, gov); | 
|---|
| 146 | } | 
|---|
| 147 |  | 
|---|
| 148 | /* Governor callback routines */ | 
|---|
| 149 | int cpufreq_dbs_governor_init(struct cpufreq_policy *policy); | 
|---|
| 150 | void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy); | 
|---|
| 151 | int cpufreq_dbs_governor_start(struct cpufreq_policy *policy); | 
|---|
| 152 | void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy); | 
|---|
| 153 | void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy); | 
|---|
| 154 |  | 
|---|
| 155 | #define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_)			\ | 
|---|
| 156 | {								\ | 
|---|
| 157 | .name = _name_,						\ | 
|---|
| 158 | .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING,			\ | 
|---|
| 159 | .owner = THIS_MODULE,					\ | 
|---|
| 160 | .init = cpufreq_dbs_governor_init,			\ | 
|---|
| 161 | .exit = cpufreq_dbs_governor_exit,			\ | 
|---|
| 162 | .start = cpufreq_dbs_governor_start,			\ | 
|---|
| 163 | .stop = cpufreq_dbs_governor_stop,			\ | 
|---|
| 164 | .limits = cpufreq_dbs_governor_limits,			\ | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | /* Governor specific operations */ | 
|---|
| 168 | struct od_ops { | 
|---|
| 169 | unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, | 
|---|
| 170 | unsigned int freq_next, unsigned int relation); | 
|---|
| 171 | }; | 
|---|
| 172 |  | 
|---|
| 173 | unsigned int dbs_update(struct cpufreq_policy *policy); | 
|---|
| 174 | void od_register_powersave_bias_handler(unsigned int (*f) | 
|---|
| 175 | (struct cpufreq_policy *, unsigned int, unsigned int), | 
|---|
| 176 | unsigned int powersave_bias); | 
|---|
| 177 | void od_unregister_powersave_bias_handler(void); | 
|---|
| 178 | ssize_t sampling_rate_store(struct gov_attr_set *attr_set, const char *buf, | 
|---|
| 179 | size_t count); | 
|---|
| 180 | void gov_update_cpu_data(struct dbs_data *dbs_data); | 
|---|
| 181 | #endif /* _CPUFREQ_GOVERNOR_H */ | 
|---|
| 182 |  | 
|---|