blob: 3c50c4e26c0e1fd19b038ed99995ee129418e0fc [file] [log] [blame]
Oleg Pereletb906a192017-01-04 09:50:02 -08001/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/errno.h>
14#include <linux/module.h>
15#include <linux/devfreq.h>
16#include <linux/math64.h>
17#include <linux/spinlock.h>
18#include <linux/slab.h>
19#include <linux/io.h>
20#include <linux/ftrace.h>
21#include <linux/mm.h>
22#include <linux/msm_adreno_devfreq.h>
23#include <asm/cacheflush.h>
24#include <soc/qcom/scm.h>
25#include "governor.h"
26
27static DEFINE_SPINLOCK(tz_lock);
28static DEFINE_SPINLOCK(sample_lock);
29static DEFINE_SPINLOCK(suspend_lock);
30/*
31 * FLOOR is 5msec to capture up to 3 re-draws
32 * per frame for 60fps content.
33 */
34#define FLOOR 5000
35/*
36 * MIN_BUSY is 1 msec for the sample to be sent
37 */
38#define MIN_BUSY 1000
39#define MAX_TZ_VERSION 0
40
41/*
42 * CEILING is 50msec, larger than any standard
43 * frame length, but less than the idle timer.
44 */
45#define CEILING 50000
46#define TZ_RESET_ID 0x3
47#define TZ_UPDATE_ID 0x4
48#define TZ_INIT_ID 0x6
49
50#define TZ_RESET_ID_64 0x7
51#define TZ_UPDATE_ID_64 0x8
52#define TZ_INIT_ID_64 0x9
53
54#define TZ_V2_UPDATE_ID_64 0xA
55#define TZ_V2_INIT_ID_64 0xB
56#define TZ_V2_INIT_CA_ID_64 0xC
57#define TZ_V2_UPDATE_WITH_CA_ID_64 0xD
58
59#define TAG "msm_adreno_tz: "
60
61static u64 suspend_time;
62static u64 suspend_start;
63static unsigned long acc_total, acc_relative_busy;
64
65static struct msm_adreno_extended_profile *partner_gpu_profile;
66static void do_partner_start_event(struct work_struct *work);
67static void do_partner_stop_event(struct work_struct *work);
68static void do_partner_suspend_event(struct work_struct *work);
69static void do_partner_resume_event(struct work_struct *work);
70
71static struct workqueue_struct *workqueue;
72
73/*
74 * Returns GPU suspend time in millisecond.
75 */
76u64 suspend_time_ms(void)
77{
78 u64 suspend_sampling_time;
79 u64 time_diff = 0;
80
81 if (suspend_start == 0)
82 return 0;
83
84 suspend_sampling_time = (u64)ktime_to_ms(ktime_get());
85 time_diff = suspend_sampling_time - suspend_start;
86 /* Update the suspend_start sample again */
87 suspend_start = suspend_sampling_time;
88 return time_diff;
89}
90
91static ssize_t gpu_load_show(struct device *dev,
92 struct device_attribute *attr,
93 char *buf)
94{
95 unsigned long sysfs_busy_perc = 0;
96 /*
97 * Average out the samples taken since last read
98 * This will keep the average value in sync with
99 * with the client sampling duration.
100 */
101 spin_lock(&sample_lock);
102 if (acc_total)
103 sysfs_busy_perc = (acc_relative_busy * 100) / acc_total;
104
105 /* Reset the parameters */
106 acc_total = 0;
107 acc_relative_busy = 0;
108 spin_unlock(&sample_lock);
109 return snprintf(buf, PAGE_SIZE, "%lu\n", sysfs_busy_perc);
110}
111
112/*
113 * Returns the time in ms for which gpu was in suspend state
114 * since last time the entry is read.
115 */
116static ssize_t suspend_time_show(struct device *dev,
117 struct device_attribute *attr,
118 char *buf)
119{
120 u64 time_diff = 0;
121
122 spin_lock(&suspend_lock);
123 time_diff = suspend_time_ms();
124 /*
125 * Adding the previous suspend time also as the gpu
126 * can go and come out of suspend states in between
127 * reads also and we should have the total suspend
128 * since last read.
129 */
130 time_diff += suspend_time;
131 suspend_time = 0;
132 spin_unlock(&suspend_lock);
133
134 return snprintf(buf, PAGE_SIZE, "%llu\n", time_diff);
135}
136
137static DEVICE_ATTR(gpu_load, 0444, gpu_load_show, NULL);
138
139static DEVICE_ATTR(suspend_time, 0444,
140 suspend_time_show,
141 NULL);
142
143static const struct device_attribute *adreno_tz_attr_list[] = {
144 &dev_attr_gpu_load,
145 &dev_attr_suspend_time,
146 NULL
147};
148
149void compute_work_load(struct devfreq_dev_status *stats,
150 struct devfreq_msm_adreno_tz_data *priv,
151 struct devfreq *devfreq)
152{
153 spin_lock(&sample_lock);
154 /*
155 * Keep collecting the stats till the client
156 * reads it. Average of all samples and reset
157 * is done when the entry is read
158 */
159 acc_total += stats->total_time;
160 acc_relative_busy += (stats->busy_time * stats->current_frequency) /
161 devfreq->profile->freq_table[0];
162 spin_unlock(&sample_lock);
163}
164
165/* Trap into the TrustZone, and call funcs there. */
166static int __secure_tz_reset_entry2(unsigned int *scm_data, u32 size_scm_data,
167 bool is_64)
168{
169 int ret;
170 /* sync memory before sending the commands to tz */
171 __iowmb();
172
173 if (!is_64) {
174 spin_lock(&tz_lock);
175 ret = scm_call_atomic2(SCM_SVC_IO, TZ_RESET_ID, scm_data[0],
176 scm_data[1]);
177 spin_unlock(&tz_lock);
178 } else {
179 if (is_scm_armv8()) {
180 struct scm_desc desc = {0};
181
182 desc.arginfo = 0;
183 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS,
184 TZ_RESET_ID_64), &desc);
185 } else {
186 ret = scm_call(SCM_SVC_DCVS, TZ_RESET_ID_64, scm_data,
187 size_scm_data, NULL, 0);
188 }
189 }
190 return ret;
191}
192
193static int __secure_tz_update_entry3(unsigned int *scm_data, u32 size_scm_data,
194 int *val, u32 size_val, struct devfreq_msm_adreno_tz_data *priv)
195{
196 int ret;
197 /* sync memory before sending the commands to tz */
198 __iowmb();
199
200 if (!priv->is_64) {
201 spin_lock(&tz_lock);
202 ret = scm_call_atomic3(SCM_SVC_IO, TZ_UPDATE_ID,
203 scm_data[0], scm_data[1], scm_data[2]);
204 spin_unlock(&tz_lock);
205 *val = ret;
206 } else {
207 if (is_scm_armv8()) {
208 unsigned int cmd_id;
209 struct scm_desc desc = {0};
210
211 desc.args[0] = scm_data[0];
212 desc.args[1] = scm_data[1];
213 desc.args[2] = scm_data[2];
214
215 if (!priv->ctxt_aware_enable) {
216 desc.arginfo = SCM_ARGS(3);
217 cmd_id = TZ_V2_UPDATE_ID_64;
218 } else {
219 /* Add context count infomration to update*/
220 desc.args[3] = scm_data[3];
221 desc.arginfo = SCM_ARGS(4);
222 cmd_id = TZ_V2_UPDATE_WITH_CA_ID_64;
223 }
224 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS, cmd_id),
225 &desc);
226 *val = desc.ret[0];
227 } else {
228 ret = scm_call(SCM_SVC_DCVS, TZ_UPDATE_ID_64, scm_data,
229 size_scm_data, val, size_val);
230 }
231 }
232 return ret;
233}
234
235static int tz_init_ca(struct devfreq_msm_adreno_tz_data *priv)
236{
237 unsigned int tz_ca_data[2];
238 struct scm_desc desc = {0};
Deepak Kumarb668b4e2017-01-25 18:53:55 +0530239 u8 *tz_buf;
Oleg Pereletb906a192017-01-04 09:50:02 -0800240 int ret;
241
242 /* Set data for TZ */
243 tz_ca_data[0] = priv->bin.ctxt_aware_target_pwrlevel;
244 tz_ca_data[1] = priv->bin.ctxt_aware_busy_penalty;
245
246 tz_buf = kzalloc(PAGE_ALIGN(sizeof(tz_ca_data)), GFP_KERNEL);
247 if (!tz_buf)
248 return -ENOMEM;
249
250 memcpy(tz_buf, tz_ca_data, sizeof(tz_ca_data));
251 /* Ensure memcpy completes execution */
252 mb();
253 dmac_flush_range(tz_buf,
254 tz_buf + PAGE_ALIGN(sizeof(tz_ca_data)));
255
256 desc.args[0] = virt_to_phys(tz_buf);
257 desc.args[1] = sizeof(tz_ca_data);
258 desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
259
260 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS,
261 TZ_V2_INIT_CA_ID_64),
262 &desc);
263
264 kzfree(tz_buf);
265
266 return ret;
267}
268
269static int tz_init(struct devfreq_msm_adreno_tz_data *priv,
270 unsigned int *tz_pwrlevels, u32 size_pwrlevels,
271 unsigned int *version, u32 size_version)
272{
273 int ret;
274 /* Make sure all CMD IDs are avaialble */
275 if (scm_is_call_available(SCM_SVC_DCVS, TZ_INIT_ID)) {
276 ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels,
277 size_pwrlevels, NULL, 0);
278 *version = 0;
279
280 } else if (scm_is_call_available(SCM_SVC_DCVS, TZ_INIT_ID_64) &&
281 scm_is_call_available(SCM_SVC_DCVS, TZ_UPDATE_ID_64) &&
282 scm_is_call_available(SCM_SVC_DCVS, TZ_RESET_ID_64)) {
283 struct scm_desc desc = {0};
Deepak Kumarb668b4e2017-01-25 18:53:55 +0530284 u8 *tz_buf;
Oleg Pereletb906a192017-01-04 09:50:02 -0800285
286 if (!is_scm_armv8()) {
287 ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID_64,
288 tz_pwrlevels, size_pwrlevels,
289 version, size_version);
290 if (!ret)
291 priv->is_64 = true;
292 return ret;
293 }
294
295 tz_buf = kzalloc(PAGE_ALIGN(size_pwrlevels), GFP_KERNEL);
296 if (!tz_buf)
297 return -ENOMEM;
298 memcpy(tz_buf, tz_pwrlevels, size_pwrlevels);
299 /* Ensure memcpy completes execution */
300 mb();
301 dmac_flush_range(tz_buf, tz_buf + PAGE_ALIGN(size_pwrlevels));
302
303 desc.args[0] = virt_to_phys(tz_buf);
304 desc.args[1] = size_pwrlevels;
305 desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
306
307 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS, TZ_V2_INIT_ID_64),
308 &desc);
309 *version = desc.ret[0];
310 if (!ret)
311 priv->is_64 = true;
312 kzfree(tz_buf);
313 } else
314 ret = -EINVAL;
315
316 /* Initialize context aware feature, if enabled. */
317 if (!ret && priv->ctxt_aware_enable) {
318 if (priv->is_64 &&
319 (scm_is_call_available(SCM_SVC_DCVS,
320 TZ_V2_INIT_CA_ID_64)) &&
321 (scm_is_call_available(SCM_SVC_DCVS,
322 TZ_V2_UPDATE_WITH_CA_ID_64))) {
323 ret = tz_init_ca(priv);
324 /*
325 * If context aware feature intialization fails,
326 * just print an error message and return
327 * success as normal DCVS will still work.
328 */
329 if (ret) {
330 pr_err(TAG "tz: context aware DCVS init failed\n");
331 priv->ctxt_aware_enable = false;
332 return 0;
333 }
334 } else {
335 pr_warn(TAG "tz: context aware DCVS not supported\n");
336 priv->ctxt_aware_enable = false;
337 }
338 }
339
340 return ret;
341}
342
343static inline int devfreq_get_freq_level(struct devfreq *devfreq,
344 unsigned long freq)
345{
346 int lev;
347
348 for (lev = 0; lev < devfreq->profile->max_state; lev++)
349 if (freq == devfreq->profile->freq_table[lev])
350 return lev;
351
352 return -EINVAL;
353}
354
355static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq)
356{
357 int result = 0;
358 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
359 struct devfreq_dev_status stats;
360 int val, level = 0;
361 unsigned int scm_data[4];
362 int context_count = 0;
363
364 /* keeps stats.private_data == NULL */
365 result = devfreq->profile->get_dev_status(devfreq->dev.parent, &stats);
366 if (result) {
367 pr_err(TAG "get_status failed %d\n", result);
368 return result;
369 }
370
371 *freq = stats.current_frequency;
372 priv->bin.total_time += stats.total_time;
373 priv->bin.busy_time += stats.busy_time;
374
375 if (stats.private_data)
376 context_count = *((int *)stats.private_data);
377
378 /* Update the GPU load statistics */
379 compute_work_load(&stats, priv, devfreq);
380 /*
381 * Do not waste CPU cycles running this algorithm if
382 * the GPU just started, or if less than FLOOR time
383 * has passed since the last run or the gpu hasn't been
384 * busier than MIN_BUSY.
385 */
386 if ((stats.total_time == 0) ||
387 (priv->bin.total_time < FLOOR) ||
388 (unsigned int) priv->bin.busy_time < MIN_BUSY) {
389 return 0;
390 }
391
392 level = devfreq_get_freq_level(devfreq, stats.current_frequency);
393 if (level < 0) {
394 pr_err(TAG "bad freq %ld\n", stats.current_frequency);
395 return level;
396 }
397
398 /*
399 * If there is an extended block of busy processing,
400 * increase frequency. Otherwise run the normal algorithm.
401 */
402 if (!priv->disable_busy_time_burst &&
403 priv->bin.busy_time > CEILING) {
404 val = -1 * level;
405 } else {
406
407 scm_data[0] = level;
408 scm_data[1] = priv->bin.total_time;
409 scm_data[2] = priv->bin.busy_time;
410 scm_data[3] = context_count;
411 __secure_tz_update_entry3(scm_data, sizeof(scm_data),
412 &val, sizeof(val), priv);
413 }
414 priv->bin.total_time = 0;
415 priv->bin.busy_time = 0;
416
417 /*
418 * If the decision is to move to a different level, make sure the GPU
419 * frequency changes.
420 */
421 if (val) {
422 level += val;
423 level = max(level, 0);
424 level = min_t(int, level, devfreq->profile->max_state - 1);
425 }
426
427 *freq = devfreq->profile->freq_table[level];
428 return 0;
429}
430
431static int tz_notify(struct notifier_block *nb, unsigned long type, void *devp)
432{
433 int result = 0;
434 struct devfreq *devfreq = devp;
435
436 switch (type) {
437 case ADRENO_DEVFREQ_NOTIFY_IDLE:
438 case ADRENO_DEVFREQ_NOTIFY_RETIRE:
439 mutex_lock(&devfreq->lock);
440 result = update_devfreq(devfreq);
441 mutex_unlock(&devfreq->lock);
442 /* Nofifying partner bus governor if any */
443 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq) {
444 mutex_lock(&partner_gpu_profile->bus_devfreq->lock);
445 update_devfreq(partner_gpu_profile->bus_devfreq);
446 mutex_unlock(&partner_gpu_profile->bus_devfreq->lock);
447 }
448 break;
449 /* ignored by this governor */
450 case ADRENO_DEVFREQ_NOTIFY_SUBMIT:
451 default:
452 break;
453 }
454 return notifier_from_errno(result);
455}
456
457static int tz_start(struct devfreq *devfreq)
458{
459 struct devfreq_msm_adreno_tz_data *priv;
460 unsigned int tz_pwrlevels[MSM_ADRENO_MAX_PWRLEVELS + 1];
461 int i, out, ret;
462 unsigned int version;
463
464 struct msm_adreno_extended_profile *gpu_profile = container_of(
465 (devfreq->profile),
466 struct msm_adreno_extended_profile,
467 profile);
468
469 /*
470 * Assuming that we have only one instance of the adreno device
471 * connected to this governor,
472 * can safely restore the pointer to the governor private data
473 * from the container of the device profile
474 */
475 devfreq->data = gpu_profile->private_data;
476 partner_gpu_profile = gpu_profile;
477
478 priv = devfreq->data;
479 priv->nb.notifier_call = tz_notify;
480
481 out = 1;
482 if (devfreq->profile->max_state < MSM_ADRENO_MAX_PWRLEVELS) {
483 for (i = 0; i < devfreq->profile->max_state; i++)
484 tz_pwrlevels[out++] = devfreq->profile->freq_table[i];
485 tz_pwrlevels[0] = i;
486 } else {
487 pr_err(TAG "tz_pwrlevels[] is too short\n");
488 return -EINVAL;
489 }
490
491 INIT_WORK(&gpu_profile->partner_start_event_ws,
492 do_partner_start_event);
493 INIT_WORK(&gpu_profile->partner_stop_event_ws,
494 do_partner_stop_event);
495 INIT_WORK(&gpu_profile->partner_suspend_event_ws,
496 do_partner_suspend_event);
497 INIT_WORK(&gpu_profile->partner_resume_event_ws,
498 do_partner_resume_event);
499
500 ret = tz_init(priv, tz_pwrlevels, sizeof(tz_pwrlevels), &version,
501 sizeof(version));
502 if (ret != 0 || version > MAX_TZ_VERSION) {
503 pr_err(TAG "tz_init failed\n");
504 return ret;
505 }
506
507 for (i = 0; adreno_tz_attr_list[i] != NULL; i++)
508 device_create_file(&devfreq->dev, adreno_tz_attr_list[i]);
509
510 return kgsl_devfreq_add_notifier(devfreq->dev.parent, &priv->nb);
511}
512
513static int tz_stop(struct devfreq *devfreq)
514{
515 int i;
516 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
517
518 kgsl_devfreq_del_notifier(devfreq->dev.parent, &priv->nb);
519
520 for (i = 0; adreno_tz_attr_list[i] != NULL; i++)
521 device_remove_file(&devfreq->dev, adreno_tz_attr_list[i]);
522
523 flush_workqueue(workqueue);
524
525 /* leaving the governor and cleaning the pointer to private data */
526 devfreq->data = NULL;
527 partner_gpu_profile = NULL;
528 return 0;
529}
530
531static int tz_suspend(struct devfreq *devfreq)
532{
533 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
534 unsigned int scm_data[2] = {0, 0};
535
536 __secure_tz_reset_entry2(scm_data, sizeof(scm_data), priv->is_64);
537
538 priv->bin.total_time = 0;
539 priv->bin.busy_time = 0;
540 return 0;
541}
542
543static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data)
544{
545 int result;
546
547 struct msm_adreno_extended_profile *gpu_profile = container_of(
548 (devfreq->profile),
549 struct msm_adreno_extended_profile,
550 profile);
Oleg Pereletb906a192017-01-04 09:50:02 -0800551
552 switch (event) {
553 case DEVFREQ_GOV_START:
554 result = tz_start(devfreq);
555 break;
556
557 case DEVFREQ_GOV_STOP:
558 /* Queue the stop work before the TZ is stopped */
559 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq)
560 queue_work(workqueue,
561 &gpu_profile->partner_stop_event_ws);
562 spin_lock(&suspend_lock);
563 suspend_start = 0;
564 spin_unlock(&suspend_lock);
565 result = tz_stop(devfreq);
566 break;
567
568 case DEVFREQ_GOV_SUSPEND:
569 result = tz_suspend(devfreq);
570 if (!result) {
571 spin_lock(&suspend_lock);
572 /* Collect the start sample for suspend time */
573 suspend_start = (u64)ktime_to_ms(ktime_get());
574 spin_unlock(&suspend_lock);
575 }
576 break;
577
578 case DEVFREQ_GOV_RESUME:
579 spin_lock(&suspend_lock);
580 suspend_time += suspend_time_ms();
581 /* Reset the suspend_start when gpu resumes */
582 suspend_start = 0;
583 spin_unlock(&suspend_lock);
584 /* fallthrough */
585 case DEVFREQ_GOV_INTERVAL:
586 /* fallthrough, this governor doesn't use polling */
587 default:
588 result = 0;
589 break;
590 }
591
592 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq)
593 switch (event) {
594 case DEVFREQ_GOV_START:
595 queue_work(workqueue,
596 &gpu_profile->partner_start_event_ws);
597 break;
598 case DEVFREQ_GOV_SUSPEND:
599 queue_work(workqueue,
600 &gpu_profile->partner_suspend_event_ws);
601 break;
602 case DEVFREQ_GOV_RESUME:
603 queue_work(workqueue,
604 &gpu_profile->partner_resume_event_ws);
605 break;
606 }
607
608 return result;
609}
610
611static void _do_partner_event(struct work_struct *work, unsigned int event)
612{
613 struct devfreq *bus_devfreq;
614
615 if (partner_gpu_profile == NULL)
616 return;
617
618 bus_devfreq = partner_gpu_profile->bus_devfreq;
619
620 if (bus_devfreq != NULL &&
621 bus_devfreq->governor &&
622 bus_devfreq->governor->event_handler)
623 bus_devfreq->governor->event_handler(bus_devfreq, event, NULL);
624}
625
626static void do_partner_start_event(struct work_struct *work)
627{
628 _do_partner_event(work, DEVFREQ_GOV_START);
629}
630
631static void do_partner_stop_event(struct work_struct *work)
632{
633 _do_partner_event(work, DEVFREQ_GOV_STOP);
634}
635
636static void do_partner_suspend_event(struct work_struct *work)
637{
638 _do_partner_event(work, DEVFREQ_GOV_SUSPEND);
639}
640
641static void do_partner_resume_event(struct work_struct *work)
642{
643 _do_partner_event(work, DEVFREQ_GOV_RESUME);
644}
645
646
647static struct devfreq_governor msm_adreno_tz = {
648 .name = "msm-adreno-tz",
649 .get_target_freq = tz_get_target_freq,
650 .event_handler = tz_handler,
651};
652
653static int __init msm_adreno_tz_init(void)
654{
655 workqueue = create_freezable_workqueue("governor_msm_adreno_tz_wq");
656
657 if (workqueue == NULL)
658 return -ENOMEM;
659
660 return devfreq_add_governor(&msm_adreno_tz);
661}
662subsys_initcall(msm_adreno_tz_init);
663
664static void __exit msm_adreno_tz_exit(void)
665{
666 int ret = devfreq_remove_governor(&msm_adreno_tz);
667
668 if (ret)
669 pr_err(TAG "failed to remove governor %d\n", ret);
670
671 if (workqueue != NULL)
672 destroy_workqueue(workqueue);
673}
674
675module_exit(msm_adreno_tz_exit);
676
677MODULE_LICENSE("GPL v2");