0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018
0019 #include <linux/cpumask.h>
0020 #include <linux/cpufreq.h>
0021 #include <linux/cpuhotplug.h>
0022 #include <linux/dtpm.h>
0023 #include <linux/energy_model.h>
0024 #include <linux/of.h>
0025 #include <linux/pm_qos.h>
0026 #include <linux/slab.h>
0027 #include <linux/units.h>
0028
0029 struct dtpm_cpu {
0030 struct dtpm dtpm;
0031 struct freq_qos_request qos_req;
0032 int cpu;
0033 };
0034
0035 static DEFINE_PER_CPU(struct dtpm_cpu *, dtpm_per_cpu);
0036
0037 static struct dtpm_cpu *to_dtpm_cpu(struct dtpm *dtpm)
0038 {
0039 return container_of(dtpm, struct dtpm_cpu, dtpm);
0040 }
0041
0042 static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit)
0043 {
0044 struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm);
0045 struct em_perf_domain *pd = em_cpu_get(dtpm_cpu->cpu);
0046 struct cpumask cpus;
0047 unsigned long freq;
0048 u64 power;
0049 int i, nr_cpus;
0050
0051 cpumask_and(&cpus, cpu_online_mask, to_cpumask(pd->cpus));
0052 nr_cpus = cpumask_weight(&cpus);
0053
0054 for (i = 0; i < pd->nr_perf_states; i++) {
0055
0056 power = pd->table[i].power * nr_cpus;
0057
0058 if (power > power_limit)
0059 break;
0060 }
0061
0062 freq = pd->table[i - 1].frequency;
0063
0064 freq_qos_update_request(&dtpm_cpu->qos_req, freq);
0065
0066 power_limit = pd->table[i - 1].power * nr_cpus;
0067
0068 return power_limit;
0069 }
0070
0071 static u64 scale_pd_power_uw(struct cpumask *pd_mask, u64 power)
0072 {
0073 unsigned long max, sum_util = 0;
0074 int cpu;
0075
0076
0077
0078
0079
0080 max = arch_scale_cpu_capacity(cpumask_first(pd_mask));
0081
0082 for_each_cpu_and(cpu, pd_mask, cpu_online_mask)
0083 sum_util += sched_cpu_util(cpu);
0084
0085 return (power * ((sum_util << 10) / max)) >> 10;
0086 }
0087
0088 static u64 get_pd_power_uw(struct dtpm *dtpm)
0089 {
0090 struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm);
0091 struct em_perf_domain *pd;
0092 struct cpumask *pd_mask;
0093 unsigned long freq;
0094 int i;
0095
0096 pd = em_cpu_get(dtpm_cpu->cpu);
0097
0098 pd_mask = em_span_cpus(pd);
0099
0100 freq = cpufreq_quick_get(dtpm_cpu->cpu);
0101
0102 for (i = 0; i < pd->nr_perf_states; i++) {
0103
0104 if (pd->table[i].frequency < freq)
0105 continue;
0106
0107 return scale_pd_power_uw(pd_mask, pd->table[i].power *
0108 MICROWATT_PER_MILLIWATT);
0109 }
0110
0111 return 0;
0112 }
0113
0114 static int update_pd_power_uw(struct dtpm *dtpm)
0115 {
0116 struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm);
0117 struct em_perf_domain *em = em_cpu_get(dtpm_cpu->cpu);
0118 struct cpumask cpus;
0119 int nr_cpus;
0120
0121 cpumask_and(&cpus, cpu_online_mask, to_cpumask(em->cpus));
0122 nr_cpus = cpumask_weight(&cpus);
0123
0124 dtpm->power_min = em->table[0].power;
0125 dtpm->power_min *= MICROWATT_PER_MILLIWATT;
0126 dtpm->power_min *= nr_cpus;
0127
0128 dtpm->power_max = em->table[em->nr_perf_states - 1].power;
0129 dtpm->power_max *= MICROWATT_PER_MILLIWATT;
0130 dtpm->power_max *= nr_cpus;
0131
0132 return 0;
0133 }
0134
0135 static void pd_release(struct dtpm *dtpm)
0136 {
0137 struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm);
0138 struct cpufreq_policy *policy;
0139
0140 if (freq_qos_request_active(&dtpm_cpu->qos_req))
0141 freq_qos_remove_request(&dtpm_cpu->qos_req);
0142
0143 policy = cpufreq_cpu_get(dtpm_cpu->cpu);
0144 if (policy) {
0145 for_each_cpu(dtpm_cpu->cpu, policy->related_cpus)
0146 per_cpu(dtpm_per_cpu, dtpm_cpu->cpu) = NULL;
0147 }
0148
0149 kfree(dtpm_cpu);
0150 }
0151
0152 static struct dtpm_ops dtpm_ops = {
0153 .set_power_uw = set_pd_power_limit,
0154 .get_power_uw = get_pd_power_uw,
0155 .update_power_uw = update_pd_power_uw,
0156 .release = pd_release,
0157 };
0158
0159 static int cpuhp_dtpm_cpu_offline(unsigned int cpu)
0160 {
0161 struct dtpm_cpu *dtpm_cpu;
0162
0163 dtpm_cpu = per_cpu(dtpm_per_cpu, cpu);
0164 if (dtpm_cpu)
0165 dtpm_update_power(&dtpm_cpu->dtpm);
0166
0167 return 0;
0168 }
0169
0170 static int cpuhp_dtpm_cpu_online(unsigned int cpu)
0171 {
0172 struct dtpm_cpu *dtpm_cpu;
0173
0174 dtpm_cpu = per_cpu(dtpm_per_cpu, cpu);
0175 if (dtpm_cpu)
0176 return dtpm_update_power(&dtpm_cpu->dtpm);
0177
0178 return 0;
0179 }
0180
0181 static int __dtpm_cpu_setup(int cpu, struct dtpm *parent)
0182 {
0183 struct dtpm_cpu *dtpm_cpu;
0184 struct cpufreq_policy *policy;
0185 struct em_perf_domain *pd;
0186 char name[CPUFREQ_NAME_LEN];
0187 int ret = -ENOMEM;
0188
0189 dtpm_cpu = per_cpu(dtpm_per_cpu, cpu);
0190 if (dtpm_cpu)
0191 return 0;
0192
0193 policy = cpufreq_cpu_get(cpu);
0194 if (!policy)
0195 return 0;
0196
0197 pd = em_cpu_get(cpu);
0198 if (!pd || em_is_artificial(pd))
0199 return -EINVAL;
0200
0201 dtpm_cpu = kzalloc(sizeof(*dtpm_cpu), GFP_KERNEL);
0202 if (!dtpm_cpu)
0203 return -ENOMEM;
0204
0205 dtpm_init(&dtpm_cpu->dtpm, &dtpm_ops);
0206 dtpm_cpu->cpu = cpu;
0207
0208 for_each_cpu(cpu, policy->related_cpus)
0209 per_cpu(dtpm_per_cpu, cpu) = dtpm_cpu;
0210
0211 snprintf(name, sizeof(name), "cpu%d-cpufreq", dtpm_cpu->cpu);
0212
0213 ret = dtpm_register(name, &dtpm_cpu->dtpm, parent);
0214 if (ret)
0215 goto out_kfree_dtpm_cpu;
0216
0217 ret = freq_qos_add_request(&policy->constraints,
0218 &dtpm_cpu->qos_req, FREQ_QOS_MAX,
0219 pd->table[pd->nr_perf_states - 1].frequency);
0220 if (ret)
0221 goto out_dtpm_unregister;
0222
0223 return 0;
0224
0225 out_dtpm_unregister:
0226 dtpm_unregister(&dtpm_cpu->dtpm);
0227 dtpm_cpu = NULL;
0228
0229 out_kfree_dtpm_cpu:
0230 for_each_cpu(cpu, policy->related_cpus)
0231 per_cpu(dtpm_per_cpu, cpu) = NULL;
0232 kfree(dtpm_cpu);
0233
0234 return ret;
0235 }
0236
0237 static int dtpm_cpu_setup(struct dtpm *dtpm, struct device_node *np)
0238 {
0239 int cpu;
0240
0241 cpu = of_cpu_node_to_id(np);
0242 if (cpu < 0)
0243 return 0;
0244
0245 return __dtpm_cpu_setup(cpu, dtpm);
0246 }
0247
0248 static int dtpm_cpu_init(void)
0249 {
0250 int ret;
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 ret = cpuhp_setup_state(CPUHP_AP_DTPM_CPU_DEAD, "dtpm_cpu:offline",
0274 NULL, cpuhp_dtpm_cpu_offline);
0275 if (ret < 0)
0276 return ret;
0277
0278 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "dtpm_cpu:online",
0279 cpuhp_dtpm_cpu_online, NULL);
0280 if (ret < 0)
0281 return ret;
0282
0283 return 0;
0284 }
0285
0286 static void dtpm_cpu_exit(void)
0287 {
0288 cpuhp_remove_state_nocalls(CPUHP_AP_ONLINE_DYN);
0289 cpuhp_remove_state_nocalls(CPUHP_AP_DTPM_CPU_DEAD);
0290 }
0291
0292 struct dtpm_subsys_ops dtpm_cpu_ops = {
0293 .name = KBUILD_MODNAME,
0294 .init = dtpm_cpu_init,
0295 .exit = dtpm_cpu_exit,
0296 .setup = dtpm_cpu_setup,
0297 };