blob: 3dfafef814a98968ea1bfd3e876b41d97b12cab9 [file] [log] [blame]
Saravana Kannancedb32e2014-01-22 00:15:33 -08001/*
Junjie Wudb57bca2015-07-08 10:19:34 -07002 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
Saravana Kannancedb32e2014-01-22 00:15:33 -08003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "cache-hwmon: " fmt
15
16#include <linux/kernel.h>
17#include <linux/sizes.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/io.h>
21#include <linux/delay.h>
22#include <linux/ktime.h>
23#include <linux/time.h>
24#include <linux/err.h>
25#include <linux/errno.h>
26#include <linux/mutex.h>
27#include <linux/interrupt.h>
28#include <linux/platform_device.h>
29#include <linux/of.h>
30#include <linux/devfreq.h>
Junjie Wucd8a2952014-10-30 12:13:03 -070031#include <trace/events/power.h>
Saravana Kannancedb32e2014-01-22 00:15:33 -080032#include "governor.h"
33#include "governor_cache_hwmon.h"
34
Junjie Wu211bbef2014-10-17 13:13:52 -070035struct cache_hwmon_node {
36 unsigned int cycles_per_low_req;
37 unsigned int cycles_per_med_req;
38 unsigned int cycles_per_high_req;
39 unsigned int min_busy;
40 unsigned int max_busy;
41 unsigned int tolerance_mrps;
42 unsigned int guard_band_mhz;
43 unsigned int decay_rate;
44 unsigned long prev_mhz;
45 ktime_t prev_ts;
Junjie Wu21d559a2014-10-20 15:47:07 -070046 bool mon_started;
Junjie Wu211bbef2014-10-17 13:13:52 -070047 struct list_head list;
48 void *orig_data;
49 struct cache_hwmon *hw;
50 struct attribute_group *attr_grp;
51};
52
53static LIST_HEAD(cache_hwmon_list);
54static DEFINE_MUTEX(list_lock);
55
56static int use_cnt;
Junjie Wudb57bca2015-07-08 10:19:34 -070057static DEFINE_MUTEX(register_lock);
58
59static DEFINE_MUTEX(monitor_lock);
Junjie Wu211bbef2014-10-17 13:13:52 -070060
Saravana Kannancedb32e2014-01-22 00:15:33 -080061#define show_attr(name) \
62static ssize_t show_##name(struct device *dev, \
63 struct device_attribute *attr, char *buf) \
64{ \
Junjie Wu211bbef2014-10-17 13:13:52 -070065 struct devfreq *df = to_devfreq(dev); \
66 struct cache_hwmon_node *hw = df->data; \
67 return snprintf(buf, PAGE_SIZE, "%u\n", hw->name); \
Saravana Kannancedb32e2014-01-22 00:15:33 -080068}
69
70#define store_attr(name, _min, _max) \
71static ssize_t store_##name(struct device *dev, \
72 struct device_attribute *attr, const char *buf, \
73 size_t count) \
74{ \
75 int ret; \
76 unsigned int val; \
Junjie Wu211bbef2014-10-17 13:13:52 -070077 struct devfreq *df = to_devfreq(dev); \
78 struct cache_hwmon_node *hw = df->data; \
Saravana Kannancedb32e2014-01-22 00:15:33 -080079 ret = kstrtoint(buf, 10, &val); \
80 if (ret) \
81 return ret; \
82 val = max(val, _min); \
83 val = min(val, _max); \
Junjie Wu211bbef2014-10-17 13:13:52 -070084 hw->name = val; \
Saravana Kannancedb32e2014-01-22 00:15:33 -080085 return count; \
86}
87
88#define gov_attr(__attr, min, max) \
89show_attr(__attr) \
90store_attr(__attr, (min), (max)) \
91static DEVICE_ATTR(__attr, 0644, show_##__attr, store_##__attr)
92
Saravana Kannancedb32e2014-01-22 00:15:33 -080093#define MIN_MS 10U
94#define MAX_MS 500U
Saravana Kannancedb32e2014-01-22 00:15:33 -080095
Junjie Wu211bbef2014-10-17 13:13:52 -070096static struct cache_hwmon_node *find_hwmon_node(struct devfreq *df)
97{
98 struct cache_hwmon_node *node, *found = NULL;
99
100 mutex_lock(&list_lock);
101 list_for_each_entry(node, &cache_hwmon_list, list)
102 if (node->hw->dev == df->dev.parent ||
103 node->hw->of_node == df->dev.parent->of_node) {
104 found = node;
105 break;
106 }
107 mutex_unlock(&list_lock);
108
109 return found;
110}
111
112static unsigned long measure_mrps_and_set_irq(struct cache_hwmon_node *node,
Saravana Kannancedb32e2014-01-22 00:15:33 -0800113 struct mrps_stats *stat)
114{
115 ktime_t ts;
116 unsigned int us;
Junjie Wu211bbef2014-10-17 13:13:52 -0700117 struct cache_hwmon *hw = node->hw;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800118
119 /*
120 * Since we are stopping the counters, we don't want this short work
121 * to be interrupted by other tasks and cause the measurements to be
122 * wrong. Not blocking interrupts to avoid affecting interrupt
123 * latency and since they should be short anyway because they run in
124 * atomic context.
125 */
126 preempt_disable();
127
128 ts = ktime_get();
Junjie Wu211bbef2014-10-17 13:13:52 -0700129 us = ktime_to_us(ktime_sub(ts, node->prev_ts));
Saravana Kannancedb32e2014-01-22 00:15:33 -0800130 if (!us)
131 us = 1;
132
Junjie Wu211bbef2014-10-17 13:13:52 -0700133 hw->meas_mrps_and_set_irq(hw, node->tolerance_mrps, us, stat);
134 node->prev_ts = ts;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800135
136 preempt_enable();
137
Junjie Wucd8a2952014-10-30 12:13:03 -0700138 trace_cache_hwmon_meas(dev_name(hw->df->dev.parent), stat->mrps[HIGH],
139 stat->mrps[MED], stat->mrps[LOW],
140 stat->busy_percent, us);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800141 return 0;
142}
143
Junjie Wu211bbef2014-10-17 13:13:52 -0700144static void compute_cache_freq(struct cache_hwmon_node *node,
145 struct mrps_stats *mrps, unsigned long *freq)
Saravana Kannancedb32e2014-01-22 00:15:33 -0800146{
147 unsigned long new_mhz;
148 unsigned int busy;
149
Junjie Wucd8a2952014-10-30 12:13:03 -0700150 new_mhz = mrps->mrps[HIGH] * node->cycles_per_high_req
151 + mrps->mrps[MED] * node->cycles_per_med_req
152 + mrps->mrps[LOW] * node->cycles_per_low_req;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800153
Junjie Wu211bbef2014-10-17 13:13:52 -0700154 busy = max(node->min_busy, mrps->busy_percent);
155 busy = min(node->max_busy, busy);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800156
157 new_mhz *= 100;
158 new_mhz /= busy;
159
Junjie Wu211bbef2014-10-17 13:13:52 -0700160 if (new_mhz < node->prev_mhz) {
161 new_mhz = new_mhz * node->decay_rate + node->prev_mhz
162 * (100 - node->decay_rate);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800163 new_mhz /= 100;
164 }
Junjie Wu211bbef2014-10-17 13:13:52 -0700165 node->prev_mhz = new_mhz;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800166
Junjie Wu211bbef2014-10-17 13:13:52 -0700167 new_mhz += node->guard_band_mhz;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800168 *freq = new_mhz * 1000;
Junjie Wucd8a2952014-10-30 12:13:03 -0700169 trace_cache_hwmon_update(dev_name(node->hw->df->dev.parent), *freq);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800170}
171
172#define TOO_SOON_US (1 * USEC_PER_MSEC)
Junjie Wu21d559a2014-10-20 15:47:07 -0700173int update_cache_hwmon(struct cache_hwmon *hwmon)
Saravana Kannancedb32e2014-01-22 00:15:33 -0800174{
Junjie Wu21d559a2014-10-20 15:47:07 -0700175 struct cache_hwmon_node *node;
176 struct devfreq *df;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800177 ktime_t ts;
178 unsigned int us;
179 int ret;
180
Junjie Wu21d559a2014-10-20 15:47:07 -0700181 if (!hwmon)
182 return -EINVAL;
183 df = hwmon->df;
184 if (!df)
185 return -ENODEV;
186 node = df->data;
187 if (!node)
188 return -ENODEV;
Junjie Wudb57bca2015-07-08 10:19:34 -0700189
190 mutex_lock(&monitor_lock);
191 if (!node->mon_started) {
192 mutex_unlock(&monitor_lock);
Junjie Wu21d559a2014-10-20 15:47:07 -0700193 return -EBUSY;
Junjie Wudb57bca2015-07-08 10:19:34 -0700194 }
Saravana Kannancedb32e2014-01-22 00:15:33 -0800195
Junjie Wu21d559a2014-10-20 15:47:07 -0700196 dev_dbg(df->dev.parent, "Got update request\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800197 devfreq_monitor_stop(df);
198
199 /*
200 * Don't recalc cache freq if the interrupt comes right after a
201 * previous cache freq calculation. This is done for two reasons:
202 *
203 * 1. Sampling the cache request during a very short duration can
204 * result in a very inaccurate measurement due to very short
205 * bursts.
206 * 2. This can only happen if the limit was hit very close to the end
207 * of the previous sample period. Which means the current cache
208 * request estimate is not very off and doesn't need to be
209 * readjusted.
210 */
211 ts = ktime_get();
Junjie Wu211bbef2014-10-17 13:13:52 -0700212 us = ktime_to_us(ktime_sub(ts, node->prev_ts));
Saravana Kannancedb32e2014-01-22 00:15:33 -0800213 if (us > TOO_SOON_US) {
214 mutex_lock(&df->lock);
215 ret = update_devfreq(df);
216 if (ret)
Junjie Wu211bbef2014-10-17 13:13:52 -0700217 dev_err(df->dev.parent,
Junjie Wu21d559a2014-10-20 15:47:07 -0700218 "Unable to update freq on request!\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800219 mutex_unlock(&df->lock);
220 }
221
222 devfreq_monitor_start(df);
223
Junjie Wudb57bca2015-07-08 10:19:34 -0700224 mutex_unlock(&monitor_lock);
Junjie Wu21d559a2014-10-20 15:47:07 -0700225 return 0;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800226}
227
228static int devfreq_cache_hwmon_get_freq(struct devfreq *df,
229 unsigned long *freq)
230{
231 struct mrps_stats stat;
Junjie Wu211bbef2014-10-17 13:13:52 -0700232 struct cache_hwmon_node *node = df->data;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800233
Junjie Wu211bbef2014-10-17 13:13:52 -0700234 memset(&stat, 0, sizeof(stat));
235 measure_mrps_and_set_irq(node, &stat);
236 compute_cache_freq(node, &stat, freq);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800237
238 return 0;
239}
240
241gov_attr(cycles_per_low_req, 1U, 100U);
242gov_attr(cycles_per_med_req, 1U, 100U);
243gov_attr(cycles_per_high_req, 1U, 100U);
244gov_attr(min_busy, 1U, 100U);
245gov_attr(max_busy, 1U, 100U);
246gov_attr(tolerance_mrps, 0U, 100U);
247gov_attr(guard_band_mhz, 0U, 500U);
248gov_attr(decay_rate, 0U, 100U);
249
250static struct attribute *dev_attr[] = {
251 &dev_attr_cycles_per_low_req.attr,
252 &dev_attr_cycles_per_med_req.attr,
253 &dev_attr_cycles_per_high_req.attr,
254 &dev_attr_min_busy.attr,
255 &dev_attr_max_busy.attr,
256 &dev_attr_tolerance_mrps.attr,
257 &dev_attr_guard_band_mhz.attr,
258 &dev_attr_decay_rate.attr,
259 NULL,
260};
261
262static struct attribute_group dev_attr_group = {
263 .name = "cache_hwmon",
264 .attrs = dev_attr,
265};
266
267static int start_monitoring(struct devfreq *df)
268{
269 int ret;
270 struct mrps_stats mrps;
Junjie Wu211bbef2014-10-17 13:13:52 -0700271 struct device *dev = df->dev.parent;
272 struct cache_hwmon_node *node;
273 struct cache_hwmon *hw;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800274
Junjie Wu211bbef2014-10-17 13:13:52 -0700275 node = find_hwmon_node(df);
276 if (!node) {
277 dev_err(dev, "Unable to find HW monitor!\n");
278 return -ENODEV;
279 }
280 hw = node->hw;
281 hw->df = df;
282 node->orig_data = df->data;
283 df->data = node;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800284
Junjie Wu211bbef2014-10-17 13:13:52 -0700285 node->prev_ts = ktime_get();
286 node->prev_mhz = 0;
Junjie Wucd8a2952014-10-30 12:13:03 -0700287 mrps.mrps[HIGH] = (df->previous_freq / 1000) - node->guard_band_mhz;
288 mrps.mrps[HIGH] /= node->cycles_per_high_req;
289 mrps.mrps[MED] = mrps.mrps[LOW] = 0;
Junjie Wu211bbef2014-10-17 13:13:52 -0700290
291 ret = hw->start_hwmon(hw, &mrps);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800292 if (ret) {
Junjie Wu211bbef2014-10-17 13:13:52 -0700293 dev_err(dev, "Unable to start HW monitor!\n");
294 goto err_start;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800295 }
296
Junjie Wudb57bca2015-07-08 10:19:34 -0700297 mutex_lock(&monitor_lock);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800298 devfreq_monitor_start(df);
Junjie Wu21d559a2014-10-20 15:47:07 -0700299 node->mon_started = true;
Junjie Wudb57bca2015-07-08 10:19:34 -0700300 mutex_unlock(&monitor_lock);
Saravana Kannancedb32e2014-01-22 00:15:33 -0800301
302 ret = sysfs_create_group(&df->dev.kobj, &dev_attr_group);
303 if (ret) {
Junjie Wu211bbef2014-10-17 13:13:52 -0700304 dev_err(dev, "Error creating sys entries!\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800305 goto sysfs_fail;
306 }
307
308 return 0;
309
310sysfs_fail:
Junjie Wudb57bca2015-07-08 10:19:34 -0700311 mutex_lock(&monitor_lock);
Junjie Wu21d559a2014-10-20 15:47:07 -0700312 node->mon_started = false;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800313 devfreq_monitor_stop(df);
Junjie Wudb57bca2015-07-08 10:19:34 -0700314 mutex_unlock(&monitor_lock);
Junjie Wu211bbef2014-10-17 13:13:52 -0700315 hw->stop_hwmon(hw);
316err_start:
317 df->data = node->orig_data;
318 node->orig_data = NULL;
319 hw->df = NULL;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800320 return ret;
321}
322
323static void stop_monitoring(struct devfreq *df)
324{
Junjie Wu211bbef2014-10-17 13:13:52 -0700325 struct cache_hwmon_node *node = df->data;
326 struct cache_hwmon *hw = node->hw;
327
Saravana Kannancedb32e2014-01-22 00:15:33 -0800328 sysfs_remove_group(&df->dev.kobj, &dev_attr_group);
Junjie Wudb57bca2015-07-08 10:19:34 -0700329 mutex_lock(&monitor_lock);
Junjie Wu21d559a2014-10-20 15:47:07 -0700330 node->mon_started = false;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800331 devfreq_monitor_stop(df);
Junjie Wudb57bca2015-07-08 10:19:34 -0700332 mutex_unlock(&monitor_lock);
Junjie Wu211bbef2014-10-17 13:13:52 -0700333 hw->stop_hwmon(hw);
334 df->data = node->orig_data;
335 node->orig_data = NULL;
336 hw->df = NULL;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800337}
338
339static int devfreq_cache_hwmon_ev_handler(struct devfreq *df,
340 unsigned int event, void *data)
341{
342 int ret;
Junjie Wu211bbef2014-10-17 13:13:52 -0700343 unsigned int sample_ms;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800344
345 switch (event) {
346 case DEVFREQ_GOV_START:
347 sample_ms = df->profile->polling_ms;
348 sample_ms = max(MIN_MS, sample_ms);
349 sample_ms = min(MAX_MS, sample_ms);
350 df->profile->polling_ms = sample_ms;
351
352 ret = start_monitoring(df);
353 if (ret)
354 return ret;
355
Junjie Wu211bbef2014-10-17 13:13:52 -0700356 dev_dbg(df->dev.parent, "Enabled Cache HW monitor governor\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800357 break;
358
359 case DEVFREQ_GOV_STOP:
360 stop_monitoring(df);
Junjie Wu211bbef2014-10-17 13:13:52 -0700361 dev_dbg(df->dev.parent, "Disabled Cache HW monitor governor\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800362 break;
363
364 case DEVFREQ_GOV_INTERVAL:
365 sample_ms = *(unsigned int *)data;
366 sample_ms = max(MIN_MS, sample_ms);
367 sample_ms = min(MAX_MS, sample_ms);
368 devfreq_interval_update(df, &sample_ms);
369 break;
370 }
371
372 return 0;
373}
374
375static struct devfreq_governor devfreq_cache_hwmon = {
376 .name = "cache_hwmon",
377 .get_target_freq = devfreq_cache_hwmon_get_freq,
378 .event_handler = devfreq_cache_hwmon_ev_handler,
379};
380
Junjie Wu211bbef2014-10-17 13:13:52 -0700381int register_cache_hwmon(struct device *dev, struct cache_hwmon *hwmon)
Saravana Kannancedb32e2014-01-22 00:15:33 -0800382{
Junjie Wu211bbef2014-10-17 13:13:52 -0700383 int ret = 0;
384 struct cache_hwmon_node *node;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800385
Junjie Wu211bbef2014-10-17 13:13:52 -0700386 if (!hwmon->dev && !hwmon->of_node)
387 return -EINVAL;
388
389 node = devm_kzalloc(dev, sizeof(*node), GFP_KERNEL);
390 if (!node)
391 return -ENOMEM;
392
393 node->cycles_per_med_req = 20;
394 node->cycles_per_high_req = 35;
395 node->min_busy = 100;
396 node->max_busy = 100;
397 node->tolerance_mrps = 5;
398 node->guard_band_mhz = 100;
399 node->decay_rate = 90;
400 node->hw = hwmon;
401 node->attr_grp = &dev_attr_group;
402
Junjie Wudb57bca2015-07-08 10:19:34 -0700403 mutex_lock(&register_lock);
Junjie Wu211bbef2014-10-17 13:13:52 -0700404 if (!use_cnt) {
405 ret = devfreq_add_governor(&devfreq_cache_hwmon);
406 if (!ret)
407 use_cnt++;
408 }
Junjie Wudb57bca2015-07-08 10:19:34 -0700409 mutex_unlock(&register_lock);
Junjie Wu211bbef2014-10-17 13:13:52 -0700410
411 if (!ret) {
412 dev_info(dev, "Cache HWmon governor registered.\n");
413 } else {
414 dev_err(dev, "Failed to add Cache HWmon governor\n");
Saravana Kannancedb32e2014-01-22 00:15:33 -0800415 return ret;
416 }
417
Junjie Wu211bbef2014-10-17 13:13:52 -0700418 mutex_lock(&list_lock);
419 list_add_tail(&node->list, &cache_hwmon_list);
420 mutex_unlock(&list_lock);
421
422 return ret;
Saravana Kannancedb32e2014-01-22 00:15:33 -0800423}
424
425MODULE_DESCRIPTION("HW monitor based cache freq driver");
426MODULE_LICENSE("GPL v2");