blob: 4937801106cbd495593a171008b8c526a789c37e [file] [log] [blame]
Harshitha Sai Neelati75ce3b1b2019-09-04 17:32:28 +05301/* Copyright (c) 2010-2017, 2019 The Linux Foundation. All rights reserved.
Oleg Pereletb906a192017-01-04 09:50:02 -08002 *
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{
Harshitha Sai Neelati75ce3b1b2019-09-04 17:32:28 +0530153 u64 busy;
154
Oleg Pereletb906a192017-01-04 09:50:02 -0800155 spin_lock(&sample_lock);
156 /*
157 * Keep collecting the stats till the client
158 * reads it. Average of all samples and reset
159 * is done when the entry is read
160 */
161 acc_total += stats->total_time;
Harshitha Sai Neelati75ce3b1b2019-09-04 17:32:28 +0530162 busy = (u64)stats->busy_time * stats->current_frequency;
163 do_div(busy, devfreq->profile->freq_table[0]);
164 acc_relative_busy += busy;
165
Oleg Pereletb906a192017-01-04 09:50:02 -0800166 spin_unlock(&sample_lock);
167}
168
169/* Trap into the TrustZone, and call funcs there. */
170static int __secure_tz_reset_entry2(unsigned int *scm_data, u32 size_scm_data,
171 bool is_64)
172{
173 int ret;
174 /* sync memory before sending the commands to tz */
175 __iowmb();
176
177 if (!is_64) {
178 spin_lock(&tz_lock);
179 ret = scm_call_atomic2(SCM_SVC_IO, TZ_RESET_ID, scm_data[0],
180 scm_data[1]);
181 spin_unlock(&tz_lock);
182 } else {
183 if (is_scm_armv8()) {
184 struct scm_desc desc = {0};
185
186 desc.arginfo = 0;
187 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS,
188 TZ_RESET_ID_64), &desc);
189 } else {
190 ret = scm_call(SCM_SVC_DCVS, TZ_RESET_ID_64, scm_data,
191 size_scm_data, NULL, 0);
192 }
193 }
194 return ret;
195}
196
197static int __secure_tz_update_entry3(unsigned int *scm_data, u32 size_scm_data,
198 int *val, u32 size_val, struct devfreq_msm_adreno_tz_data *priv)
199{
200 int ret;
201 /* sync memory before sending the commands to tz */
202 __iowmb();
203
204 if (!priv->is_64) {
205 spin_lock(&tz_lock);
206 ret = scm_call_atomic3(SCM_SVC_IO, TZ_UPDATE_ID,
207 scm_data[0], scm_data[1], scm_data[2]);
208 spin_unlock(&tz_lock);
209 *val = ret;
210 } else {
211 if (is_scm_armv8()) {
212 unsigned int cmd_id;
213 struct scm_desc desc = {0};
214
215 desc.args[0] = scm_data[0];
216 desc.args[1] = scm_data[1];
217 desc.args[2] = scm_data[2];
218
219 if (!priv->ctxt_aware_enable) {
220 desc.arginfo = SCM_ARGS(3);
221 cmd_id = TZ_V2_UPDATE_ID_64;
222 } else {
223 /* Add context count infomration to update*/
224 desc.args[3] = scm_data[3];
225 desc.arginfo = SCM_ARGS(4);
226 cmd_id = TZ_V2_UPDATE_WITH_CA_ID_64;
227 }
228 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS, cmd_id),
229 &desc);
230 *val = desc.ret[0];
231 } else {
232 ret = scm_call(SCM_SVC_DCVS, TZ_UPDATE_ID_64, scm_data,
233 size_scm_data, val, size_val);
234 }
235 }
236 return ret;
237}
238
239static int tz_init_ca(struct devfreq_msm_adreno_tz_data *priv)
240{
241 unsigned int tz_ca_data[2];
242 struct scm_desc desc = {0};
Deepak Kumarb668b4e2017-01-25 18:53:55 +0530243 u8 *tz_buf;
Oleg Pereletb906a192017-01-04 09:50:02 -0800244 int ret;
245
246 /* Set data for TZ */
247 tz_ca_data[0] = priv->bin.ctxt_aware_target_pwrlevel;
248 tz_ca_data[1] = priv->bin.ctxt_aware_busy_penalty;
249
250 tz_buf = kzalloc(PAGE_ALIGN(sizeof(tz_ca_data)), GFP_KERNEL);
251 if (!tz_buf)
252 return -ENOMEM;
253
254 memcpy(tz_buf, tz_ca_data, sizeof(tz_ca_data));
255 /* Ensure memcpy completes execution */
256 mb();
257 dmac_flush_range(tz_buf,
258 tz_buf + PAGE_ALIGN(sizeof(tz_ca_data)));
259
260 desc.args[0] = virt_to_phys(tz_buf);
261 desc.args[1] = sizeof(tz_ca_data);
262 desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
263
264 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS,
265 TZ_V2_INIT_CA_ID_64),
266 &desc);
267
268 kzfree(tz_buf);
269
270 return ret;
271}
272
273static int tz_init(struct devfreq_msm_adreno_tz_data *priv,
274 unsigned int *tz_pwrlevels, u32 size_pwrlevels,
275 unsigned int *version, u32 size_version)
276{
277 int ret;
278 /* Make sure all CMD IDs are avaialble */
279 if (scm_is_call_available(SCM_SVC_DCVS, TZ_INIT_ID)) {
280 ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels,
281 size_pwrlevels, NULL, 0);
282 *version = 0;
283
284 } else if (scm_is_call_available(SCM_SVC_DCVS, TZ_INIT_ID_64) &&
285 scm_is_call_available(SCM_SVC_DCVS, TZ_UPDATE_ID_64) &&
286 scm_is_call_available(SCM_SVC_DCVS, TZ_RESET_ID_64)) {
287 struct scm_desc desc = {0};
Deepak Kumarb668b4e2017-01-25 18:53:55 +0530288 u8 *tz_buf;
Oleg Pereletb906a192017-01-04 09:50:02 -0800289
290 if (!is_scm_armv8()) {
291 ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID_64,
292 tz_pwrlevels, size_pwrlevels,
293 version, size_version);
294 if (!ret)
295 priv->is_64 = true;
296 return ret;
297 }
298
299 tz_buf = kzalloc(PAGE_ALIGN(size_pwrlevels), GFP_KERNEL);
300 if (!tz_buf)
301 return -ENOMEM;
302 memcpy(tz_buf, tz_pwrlevels, size_pwrlevels);
303 /* Ensure memcpy completes execution */
304 mb();
305 dmac_flush_range(tz_buf, tz_buf + PAGE_ALIGN(size_pwrlevels));
306
307 desc.args[0] = virt_to_phys(tz_buf);
308 desc.args[1] = size_pwrlevels;
309 desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
310
311 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_DCVS, TZ_V2_INIT_ID_64),
312 &desc);
313 *version = desc.ret[0];
314 if (!ret)
315 priv->is_64 = true;
316 kzfree(tz_buf);
317 } else
318 ret = -EINVAL;
319
320 /* Initialize context aware feature, if enabled. */
321 if (!ret && priv->ctxt_aware_enable) {
322 if (priv->is_64 &&
323 (scm_is_call_available(SCM_SVC_DCVS,
324 TZ_V2_INIT_CA_ID_64)) &&
325 (scm_is_call_available(SCM_SVC_DCVS,
326 TZ_V2_UPDATE_WITH_CA_ID_64))) {
327 ret = tz_init_ca(priv);
328 /*
329 * If context aware feature intialization fails,
330 * just print an error message and return
331 * success as normal DCVS will still work.
332 */
333 if (ret) {
334 pr_err(TAG "tz: context aware DCVS init failed\n");
335 priv->ctxt_aware_enable = false;
336 return 0;
337 }
338 } else {
339 pr_warn(TAG "tz: context aware DCVS not supported\n");
340 priv->ctxt_aware_enable = false;
341 }
342 }
343
344 return ret;
345}
346
347static inline int devfreq_get_freq_level(struct devfreq *devfreq,
348 unsigned long freq)
349{
350 int lev;
351
352 for (lev = 0; lev < devfreq->profile->max_state; lev++)
353 if (freq == devfreq->profile->freq_table[lev])
354 return lev;
355
356 return -EINVAL;
357}
358
359static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq)
360{
361 int result = 0;
362 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
363 struct devfreq_dev_status stats;
364 int val, level = 0;
365 unsigned int scm_data[4];
366 int context_count = 0;
367
368 /* keeps stats.private_data == NULL */
369 result = devfreq->profile->get_dev_status(devfreq->dev.parent, &stats);
370 if (result) {
371 pr_err(TAG "get_status failed %d\n", result);
372 return result;
373 }
374
375 *freq = stats.current_frequency;
376 priv->bin.total_time += stats.total_time;
377 priv->bin.busy_time += stats.busy_time;
378
379 if (stats.private_data)
380 context_count = *((int *)stats.private_data);
381
382 /* Update the GPU load statistics */
383 compute_work_load(&stats, priv, devfreq);
384 /*
385 * Do not waste CPU cycles running this algorithm if
386 * the GPU just started, or if less than FLOOR time
387 * has passed since the last run or the gpu hasn't been
388 * busier than MIN_BUSY.
389 */
390 if ((stats.total_time == 0) ||
391 (priv->bin.total_time < FLOOR) ||
392 (unsigned int) priv->bin.busy_time < MIN_BUSY) {
393 return 0;
394 }
395
396 level = devfreq_get_freq_level(devfreq, stats.current_frequency);
397 if (level < 0) {
398 pr_err(TAG "bad freq %ld\n", stats.current_frequency);
399 return level;
400 }
401
402 /*
403 * If there is an extended block of busy processing,
404 * increase frequency. Otherwise run the normal algorithm.
405 */
406 if (!priv->disable_busy_time_burst &&
407 priv->bin.busy_time > CEILING) {
408 val = -1 * level;
409 } else {
410
411 scm_data[0] = level;
412 scm_data[1] = priv->bin.total_time;
413 scm_data[2] = priv->bin.busy_time;
414 scm_data[3] = context_count;
415 __secure_tz_update_entry3(scm_data, sizeof(scm_data),
416 &val, sizeof(val), priv);
417 }
418 priv->bin.total_time = 0;
419 priv->bin.busy_time = 0;
420
421 /*
422 * If the decision is to move to a different level, make sure the GPU
423 * frequency changes.
424 */
425 if (val) {
426 level += val;
427 level = max(level, 0);
428 level = min_t(int, level, devfreq->profile->max_state - 1);
429 }
430
431 *freq = devfreq->profile->freq_table[level];
432 return 0;
433}
434
435static int tz_notify(struct notifier_block *nb, unsigned long type, void *devp)
436{
437 int result = 0;
438 struct devfreq *devfreq = devp;
439
440 switch (type) {
441 case ADRENO_DEVFREQ_NOTIFY_IDLE:
442 case ADRENO_DEVFREQ_NOTIFY_RETIRE:
443 mutex_lock(&devfreq->lock);
444 result = update_devfreq(devfreq);
445 mutex_unlock(&devfreq->lock);
446 /* Nofifying partner bus governor if any */
447 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq) {
448 mutex_lock(&partner_gpu_profile->bus_devfreq->lock);
449 update_devfreq(partner_gpu_profile->bus_devfreq);
450 mutex_unlock(&partner_gpu_profile->bus_devfreq->lock);
451 }
452 break;
453 /* ignored by this governor */
454 case ADRENO_DEVFREQ_NOTIFY_SUBMIT:
455 default:
456 break;
457 }
458 return notifier_from_errno(result);
459}
460
461static int tz_start(struct devfreq *devfreq)
462{
463 struct devfreq_msm_adreno_tz_data *priv;
464 unsigned int tz_pwrlevels[MSM_ADRENO_MAX_PWRLEVELS + 1];
465 int i, out, ret;
466 unsigned int version;
467
468 struct msm_adreno_extended_profile *gpu_profile = container_of(
469 (devfreq->profile),
470 struct msm_adreno_extended_profile,
471 profile);
472
473 /*
474 * Assuming that we have only one instance of the adreno device
475 * connected to this governor,
476 * can safely restore the pointer to the governor private data
477 * from the container of the device profile
478 */
479 devfreq->data = gpu_profile->private_data;
480 partner_gpu_profile = gpu_profile;
481
482 priv = devfreq->data;
483 priv->nb.notifier_call = tz_notify;
484
485 out = 1;
486 if (devfreq->profile->max_state < MSM_ADRENO_MAX_PWRLEVELS) {
487 for (i = 0; i < devfreq->profile->max_state; i++)
488 tz_pwrlevels[out++] = devfreq->profile->freq_table[i];
489 tz_pwrlevels[0] = i;
490 } else {
491 pr_err(TAG "tz_pwrlevels[] is too short\n");
492 return -EINVAL;
493 }
494
495 INIT_WORK(&gpu_profile->partner_start_event_ws,
496 do_partner_start_event);
497 INIT_WORK(&gpu_profile->partner_stop_event_ws,
498 do_partner_stop_event);
499 INIT_WORK(&gpu_profile->partner_suspend_event_ws,
500 do_partner_suspend_event);
501 INIT_WORK(&gpu_profile->partner_resume_event_ws,
502 do_partner_resume_event);
503
504 ret = tz_init(priv, tz_pwrlevels, sizeof(tz_pwrlevels), &version,
505 sizeof(version));
506 if (ret != 0 || version > MAX_TZ_VERSION) {
507 pr_err(TAG "tz_init failed\n");
508 return ret;
509 }
510
511 for (i = 0; adreno_tz_attr_list[i] != NULL; i++)
512 device_create_file(&devfreq->dev, adreno_tz_attr_list[i]);
513
514 return kgsl_devfreq_add_notifier(devfreq->dev.parent, &priv->nb);
515}
516
517static int tz_stop(struct devfreq *devfreq)
518{
519 int i;
520 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
521
522 kgsl_devfreq_del_notifier(devfreq->dev.parent, &priv->nb);
523
524 for (i = 0; adreno_tz_attr_list[i] != NULL; i++)
525 device_remove_file(&devfreq->dev, adreno_tz_attr_list[i]);
526
527 flush_workqueue(workqueue);
528
529 /* leaving the governor and cleaning the pointer to private data */
530 devfreq->data = NULL;
531 partner_gpu_profile = NULL;
532 return 0;
533}
534
535static int tz_suspend(struct devfreq *devfreq)
536{
537 struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
538 unsigned int scm_data[2] = {0, 0};
539
540 __secure_tz_reset_entry2(scm_data, sizeof(scm_data), priv->is_64);
541
542 priv->bin.total_time = 0;
543 priv->bin.busy_time = 0;
544 return 0;
545}
546
547static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data)
548{
549 int result;
550
551 struct msm_adreno_extended_profile *gpu_profile = container_of(
552 (devfreq->profile),
553 struct msm_adreno_extended_profile,
554 profile);
Oleg Pereletb906a192017-01-04 09:50:02 -0800555
556 switch (event) {
557 case DEVFREQ_GOV_START:
558 result = tz_start(devfreq);
559 break;
560
561 case DEVFREQ_GOV_STOP:
562 /* Queue the stop work before the TZ is stopped */
563 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq)
564 queue_work(workqueue,
565 &gpu_profile->partner_stop_event_ws);
566 spin_lock(&suspend_lock);
567 suspend_start = 0;
568 spin_unlock(&suspend_lock);
569 result = tz_stop(devfreq);
570 break;
571
572 case DEVFREQ_GOV_SUSPEND:
573 result = tz_suspend(devfreq);
574 if (!result) {
575 spin_lock(&suspend_lock);
576 /* Collect the start sample for suspend time */
577 suspend_start = (u64)ktime_to_ms(ktime_get());
578 spin_unlock(&suspend_lock);
579 }
580 break;
581
582 case DEVFREQ_GOV_RESUME:
583 spin_lock(&suspend_lock);
584 suspend_time += suspend_time_ms();
585 /* Reset the suspend_start when gpu resumes */
586 suspend_start = 0;
587 spin_unlock(&suspend_lock);
588 /* fallthrough */
589 case DEVFREQ_GOV_INTERVAL:
590 /* fallthrough, this governor doesn't use polling */
591 default:
592 result = 0;
593 break;
594 }
595
596 if (partner_gpu_profile && partner_gpu_profile->bus_devfreq)
597 switch (event) {
598 case DEVFREQ_GOV_START:
599 queue_work(workqueue,
600 &gpu_profile->partner_start_event_ws);
601 break;
602 case DEVFREQ_GOV_SUSPEND:
603 queue_work(workqueue,
604 &gpu_profile->partner_suspend_event_ws);
605 break;
606 case DEVFREQ_GOV_RESUME:
607 queue_work(workqueue,
608 &gpu_profile->partner_resume_event_ws);
609 break;
610 }
611
612 return result;
613}
614
615static void _do_partner_event(struct work_struct *work, unsigned int event)
616{
617 struct devfreq *bus_devfreq;
618
619 if (partner_gpu_profile == NULL)
620 return;
621
622 bus_devfreq = partner_gpu_profile->bus_devfreq;
623
624 if (bus_devfreq != NULL &&
625 bus_devfreq->governor &&
626 bus_devfreq->governor->event_handler)
627 bus_devfreq->governor->event_handler(bus_devfreq, event, NULL);
628}
629
630static void do_partner_start_event(struct work_struct *work)
631{
632 _do_partner_event(work, DEVFREQ_GOV_START);
633}
634
635static void do_partner_stop_event(struct work_struct *work)
636{
637 _do_partner_event(work, DEVFREQ_GOV_STOP);
638}
639
640static void do_partner_suspend_event(struct work_struct *work)
641{
642 _do_partner_event(work, DEVFREQ_GOV_SUSPEND);
643}
644
645static void do_partner_resume_event(struct work_struct *work)
646{
647 _do_partner_event(work, DEVFREQ_GOV_RESUME);
648}
649
650
651static struct devfreq_governor msm_adreno_tz = {
652 .name = "msm-adreno-tz",
653 .get_target_freq = tz_get_target_freq,
654 .event_handler = tz_handler,
655};
656
657static int __init msm_adreno_tz_init(void)
658{
659 workqueue = create_freezable_workqueue("governor_msm_adreno_tz_wq");
660
661 if (workqueue == NULL)
662 return -ENOMEM;
663
664 return devfreq_add_governor(&msm_adreno_tz);
665}
666subsys_initcall(msm_adreno_tz_init);
667
668static void __exit msm_adreno_tz_exit(void)
669{
670 int ret = devfreq_remove_governor(&msm_adreno_tz);
671
672 if (ret)
673 pr_err(TAG "failed to remove governor %d\n", ret);
674
675 if (workqueue != NULL)
676 destroy_workqueue(workqueue);
677}
678
679module_exit(msm_adreno_tz_exit);
680
681MODULE_LICENSE("GPL v2");