blob: 50207509d7839edcb9e6f5ac84538c9d7c89d0a0 [file] [log] [blame]
Shrenuj Bansala419c792016-10-20 14:05:11 -07001/* Copyright (c) 2002,2007-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/module.h>
14#include <linux/uaccess.h>
15
16#include "kgsl.h"
17#include "adreno.h"
18#include "adreno_perfcounter.h"
19#include "adreno_pm4types.h"
20#include "a5xx_reg.h"
21
22/* Bit flag for RBMM_PERFCTR_CTL */
23#define RBBM_PERFCTR_CTL_ENABLE 0x00000001
24
25#define VBIF2_PERF_CNT_SEL_MASK 0x7F
26/* offset of clear register from select register */
27#define VBIF2_PERF_CLR_REG_SEL_OFF 8
28/* offset of enable register from select register */
29#define VBIF2_PERF_EN_REG_SEL_OFF 16
30
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +053031/* offset of clear register from select register for GBIF */
32#define GBIF_PERF_CLR_REG_SEL_OFF 1
33
34/* offset of enable register from select register for GBIF*/
35#define GBIF_PERF_EN_REG_SEL_OFF 2
36
37/* offset of clear register from the power enable register for GBIF*/
38#define GBIF_PWR_CLR_REG_EN_OFF 1
39
40/* */
41#define GBIF_PERF_RMW_MASK 0xFF
42/* */
43#define GBIF_PWR_RMW_MASK 0x10000
44
Shrenuj Bansala419c792016-10-20 14:05:11 -070045/* offset of clear register from the enable register */
46#define VBIF2_PERF_PWR_CLR_REG_EN_OFF 8
47
48#define REG_64BIT_VAL(hi, lo, val) (((((uint64_t) hi) << 32) | lo) + val)
49/*
50 * Return true if the countable is used and not broken
51 */
52static inline int active_countable(unsigned int countable)
53{
54 return ((countable != KGSL_PERFCOUNTER_NOT_USED) &&
55 (countable != KGSL_PERFCOUNTER_BROKEN));
56}
57
58/**
59 * adreno_perfcounter_init: Reserve kernel performance counters
60 * @adreno_dev: Pointer to an adreno_device struct
61 *
62 * The kernel needs/wants a certain group of performance counters for
63 * its own activities. Reserve these performance counters at init time
64 * to ensure that they are always reserved for the kernel. The performance
65 * counters used by the kernel can be obtained by the user, but these
66 * performance counters will remain active as long as the device is alive.
67 */
68void adreno_perfcounter_init(struct adreno_device *adreno_dev)
69{
70 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
71
72 if (gpudev->perfcounter_init)
73 gpudev->perfcounter_init(adreno_dev);
74}
75
76/**
77 * adreno_perfcounter_write() - Write the physical performance
78 * counter values.
79 * @adreno_dev - Adreno device whose registers are to be written to.
80 * @reg - register address of the physical counter to which the value is
81 * written to.
82 *
83 * This function loads the 64 bit saved value into the particular physical
84 * counter by enabling the corresponding bit in A3XX_RBBM_PERFCTR_LOAD_CMD*
85 * register.
86 */
87static void adreno_perfcounter_write(struct adreno_device *adreno_dev,
88 struct adreno_perfcount_register *reg)
89{
90 unsigned int val, i;
91 int cmd[] = { ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0,
92 ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1,
93 ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2,
94 ADRENO_REG_RBBM_PERFCTR_LOAD_CMD3 };
95
96 /* If not loadable then return quickly */
97 if (reg->load_bit < 0)
98 return;
99
100 /* Get the offset/cmd for loading */
101 i = reg->load_bit / 32;
102
103 /* Get the register bit offset for loading */
104 val = BIT(reg->load_bit & 31);
105
106 /* Write the saved value to PERFCTR_LOAD_VALUE* registers. */
107 adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
108 ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, reg->value);
109
110 /*
111 * Set the load bit in PERFCTR_LOAD_CMD for the physical counter
112 * we want to restore. The value in PERFCTR_LOAD_VALUE* is loaded
113 * into the corresponding physical counter. The value for the select
114 * register gets cleared once RBBM reads it so no need to clear the
115 * select register afterwards.
116 */
117 adreno_writereg(adreno_dev, cmd[i], val);
118}
119
120/**
121 * adreno_perfcounter_close() - Release counters initialized by
122 * adreno_perfcounter_close
123 * @adreno_dev: Pointer to an adreno_device struct
124 */
125void adreno_perfcounter_close(struct adreno_device *adreno_dev)
126{
127 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
128
129 if (gpudev->perfcounter_close)
130 gpudev->perfcounter_close(adreno_dev);
131}
132
133/**
134 * adreno_perfcounter_restore() - Restore performance counters
135 * @adreno_dev: adreno device to configure
136 *
137 * Load the physical performance counters with 64 bit value which are
138 * saved on GPU power collapse.
139 */
140void adreno_perfcounter_restore(struct adreno_device *adreno_dev)
141{
142 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
143 struct adreno_perfcount_group *group;
144 unsigned int counter, groupid;
145
146 if (counters == NULL)
147 return;
148
149 for (groupid = 0; groupid < counters->group_count; groupid++) {
150 group = &(counters->groups[groupid]);
151
152 /* Restore the counters for the group */
153 for (counter = 0; counter < group->reg_count; counter++) {
154 /* If not active or broken, skip this counter */
155 if (!active_countable(group->regs[counter].countable))
156 continue;
157
158 adreno_perfcounter_write(adreno_dev,
159 &group->regs[counter]);
160 }
161 }
162}
163
164/**
165 * adreno_perfcounter_save() - Save performance counters
166 * @adreno_dev: adreno device to configure
167 *
168 * Save the performance counter values before GPU power collapse.
169 * The saved values are restored on restart.
170 * This ensures physical counters are coherent across power-collapse.
171 */
172inline void adreno_perfcounter_save(struct adreno_device *adreno_dev)
173{
Akhil P Oommen25247372017-10-18 17:35:23 +0530174 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700175 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
176 struct adreno_perfcount_group *group;
177 unsigned int counter, groupid;
Akhil P Oommen25247372017-10-18 17:35:23 +0530178 int ret = 0;
Shrenuj Bansala419c792016-10-20 14:05:11 -0700179
180 if (counters == NULL)
181 return;
182
Akhil P Oommen25247372017-10-18 17:35:23 +0530183 if (gpudev->oob_set)
184 ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
185 OOB_PERFCNTR_CHECK_MASK,
186 OOB_PERFCNTR_CLEAR_MASK);
187
188 /* if oob_set timeout, clear the mask and return */
Kyle Pieferb09325d2017-08-23 16:03:34 -0700189 if (ret)
Akhil P Oommen25247372017-10-18 17:35:23 +0530190 goto done;
Kyle Pieferb09325d2017-08-23 16:03:34 -0700191
Shrenuj Bansala419c792016-10-20 14:05:11 -0700192 for (groupid = 0; groupid < counters->group_count; groupid++) {
193 group = &(counters->groups[groupid]);
194
195 /* Save the counter values for the group */
196 for (counter = 0; counter < group->reg_count; counter++) {
197 /* If not active or broken, skip this counter */
198 if (!active_countable(group->regs[counter].countable))
199 continue;
200
201 /* accumulate values for non-loadable counters */
202 if (group->regs[counter].load_bit >= 0)
203 group->regs[counter].value = 0;
204
205 group->regs[counter].value =
206 group->regs[counter].value +
207 adreno_perfcounter_read(adreno_dev, groupid,
208 counter);
209 }
210 }
Kyle Pieferb09325d2017-08-23 16:03:34 -0700211
Akhil P Oommen25247372017-10-18 17:35:23 +0530212done:
213 if (gpudev->oob_clear)
214 gpudev->oob_clear(adreno_dev, OOB_PERFCNTR_CLEAR_MASK);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700215}
216
217static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
218 unsigned int group, unsigned int counter, unsigned int countable);
219
220/**
221 * adreno_perfcounter_start: Enable performance counters
222 * @adreno_dev: Adreno device to configure
223 *
224 * Ensure all performance counters are enabled that are allocated. Since
225 * the device was most likely stopped, we can't trust that the counters
226 * are still valid so make it so.
227 */
228
229void adreno_perfcounter_start(struct adreno_device *adreno_dev)
230{
231 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
232 struct adreno_perfcount_group *group;
233 unsigned int i, j;
234
235 if (counters == NULL)
236 return;
237 /* group id iter */
238 for (i = 0; i < counters->group_count; i++) {
239 group = &(counters->groups[i]);
240
241 /* countable iter */
242 for (j = 0; j < group->reg_count; j++) {
243 if (!active_countable(group->regs[j].countable))
244 continue;
245
246 /*
247 * The GPU has to be idle before calling the perfcounter
248 * enable function, but since this function is called
249 * during start we already know the GPU is idle.
250 * Since the countable/counter pairs have already been
251 * validated, there is no way for _enable() to fail so
252 * no need to check the return code.
253 */
254 adreno_perfcounter_enable(adreno_dev, i, j,
255 group->regs[j].countable);
256 }
257 }
258}
259
260/**
261 * adreno_perfcounter_read_group() - Determine which countables are in counters
262 * @adreno_dev: Adreno device to configure
263 * @reads: List of kgsl_perfcounter_read_groups
264 * @count: Length of list
265 *
266 * Read the performance counters for the groupid/countable pairs and return
267 * the 64 bit result for each pair
268 */
269
270int adreno_perfcounter_read_group(struct adreno_device *adreno_dev,
271 struct kgsl_perfcounter_read_group __user *reads, unsigned int count)
272{
273 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
274 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
275 struct adreno_perfcount_group *group;
276 struct kgsl_perfcounter_read_group *list = NULL;
277 unsigned int i, j;
278 int ret = 0;
279
280 if (counters == NULL)
281 return -EINVAL;
282
283 /* sanity check params passed in */
284 if (reads == NULL || count == 0 || count > 100)
285 return -EINVAL;
286
287 list = kmalloc_array(count, sizeof(struct kgsl_perfcounter_read_group),
288 GFP_KERNEL);
289 if (!list)
290 return -ENOMEM;
291
292 if (copy_from_user(list, reads,
293 sizeof(struct kgsl_perfcounter_read_group) * count)) {
294 ret = -EFAULT;
295 goto done;
296 }
297
298 mutex_lock(&device->mutex);
Carter Cooper05f2a6b2017-03-20 11:43:11 -0600299
300 ret = adreno_perfcntr_active_oob_get(adreno_dev);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700301 if (ret) {
302 mutex_unlock(&device->mutex);
303 goto done;
304 }
305
306 /* list iterator */
307 for (j = 0; j < count; j++) {
308
309 list[j].value = 0;
310
311 /* Verify that the group ID is within range */
312 if (list[j].groupid >= counters->group_count) {
313 ret = -EINVAL;
314 break;
315 }
316
317 group = &(counters->groups[list[j].groupid]);
318
319 /* group/counter iterator */
320 for (i = 0; i < group->reg_count; i++) {
321 if (group->regs[i].countable == list[j].countable) {
322 list[j].value = adreno_perfcounter_read(
323 adreno_dev, list[j].groupid, i);
324 break;
325 }
326 }
327 }
328
Carter Cooper05f2a6b2017-03-20 11:43:11 -0600329 adreno_perfcntr_active_oob_put(adreno_dev);
330
Shrenuj Bansala419c792016-10-20 14:05:11 -0700331 mutex_unlock(&device->mutex);
332
333 /* write the data */
334 if (ret == 0)
335 if (copy_to_user(reads, list,
336 sizeof(struct kgsl_perfcounter_read_group) * count))
337 ret = -EFAULT;
338
339done:
340 kfree(list);
341 return ret;
342}
343
344/**
345 * adreno_perfcounter_get_groupid() - Get the performance counter ID
346 * @adreno_dev: Adreno device
347 * @name: Performance counter group name string
348 *
349 * Get the groupid based on the name and return this ID
350 */
351
352int adreno_perfcounter_get_groupid(struct adreno_device *adreno_dev,
353 const char *name)
354{
355 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
356 struct adreno_perfcount_group *group;
357 int i;
358
359 if (name == NULL || counters == NULL)
360 return -EINVAL;
361
362 for (i = 0; i < counters->group_count; ++i) {
363 group = &(counters->groups[i]);
364
365 /* make sure there is a name for this group */
366 if (group->name == NULL)
367 continue;
368
369 /* verify name and length */
370 if (strlen(name) == strlen(group->name) &&
371 strcmp(group->name, name) == 0)
372 return i;
373 }
374
375 return -EINVAL;
376}
377
378/**
379 * adreno_perfcounter_get_name() - Get the group name
380 * @adreno_dev: Adreno device
381 * @groupid: Desired performance counter groupid
382 *
383 * Get the name based on the groupid and return it
384 */
385
386const char *adreno_perfcounter_get_name(struct adreno_device *adreno_dev,
387 unsigned int groupid)
388{
389 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
390
391 if (counters != NULL && groupid < counters->group_count)
392 return counters->groups[groupid].name;
393
394 return NULL;
395}
396
397/**
398 * adreno_perfcounter_query_group: Determine which countables are in counters
399 * @adreno_dev: Adreno device to configure
400 * @groupid: Desired performance counter group
401 * @countables: Return list of all countables in the groups counters
402 * @count: Max length of the array
403 * @max_counters: max counters for the groupid
404 *
405 * Query the current state of counters for the group.
406 */
407
408int adreno_perfcounter_query_group(struct adreno_device *adreno_dev,
409 unsigned int groupid, unsigned int __user *countables,
410 unsigned int count, unsigned int *max_counters)
411{
412 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
413 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
414 struct adreno_perfcount_group *group;
415 unsigned int i, t;
416 int ret = 0;
417 unsigned int *buf;
418
419 *max_counters = 0;
420
421 if (counters == NULL || groupid >= counters->group_count)
422 return -EINVAL;
423
424 mutex_lock(&device->mutex);
425
426 group = &(counters->groups[groupid]);
427 *max_counters = group->reg_count;
428
429 /*
430 * if NULL countable or *count of zero, return max reg_count in
431 * *max_counters and return success
432 */
433 if (countables == NULL || count == 0) {
434 mutex_unlock(&device->mutex);
435 return 0;
436 }
437
438 t = min_t(unsigned int, group->reg_count, count);
439
440 buf = kmalloc_array(t, sizeof(unsigned int), GFP_KERNEL);
441 if (buf == NULL) {
442 mutex_unlock(&device->mutex);
443 return -ENOMEM;
444 }
445
446 for (i = 0; i < t; i++)
447 buf[i] = group->regs[i].countable;
448
449 mutex_unlock(&device->mutex);
450
451 if (copy_to_user(countables, buf, sizeof(unsigned int) * t))
452 ret = -EFAULT;
453
454 kfree(buf);
455
456 return ret;
457}
458
459static inline void refcount_group(struct adreno_perfcount_group *group,
460 unsigned int reg, unsigned int flags,
461 unsigned int *lo, unsigned int *hi)
462{
463 if (flags & PERFCOUNTER_FLAG_KERNEL)
464 group->regs[reg].kernelcount++;
465 else
466 group->regs[reg].usercount++;
467
468 if (lo)
469 *lo = group->regs[reg].offset;
470
471 if (hi)
472 *hi = group->regs[reg].offset_hi;
473}
474
475/**
476 * adreno_perfcounter_get: Try to put a countable in an available counter
477 * @adreno_dev: Adreno device to configure
478 * @groupid: Desired performance counter group
479 * @countable: Countable desired to be in a counter
480 * @offset: Return offset of the LO counter assigned
481 * @offset_hi: Return offset of the HI counter assigned
482 * @flags: Used to setup kernel perf counters
483 *
484 * Try to place a countable in an available counter. If the countable is
485 * already in a counter, reference count the counter/countable pair resource
486 * and return success
487 */
488
489int adreno_perfcounter_get(struct adreno_device *adreno_dev,
490 unsigned int groupid, unsigned int countable, unsigned int *offset,
491 unsigned int *offset_hi, unsigned int flags)
492{
493 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
494 struct adreno_perfcount_group *group;
495 unsigned int empty = -1;
496 int ret = 0;
497
498 /* always clear return variables */
499 if (offset)
500 *offset = 0;
501 if (offset_hi)
502 *offset_hi = 0;
503
504 if (counters == NULL)
505 return -EINVAL;
506
507 if (groupid >= counters->group_count)
508 return -EINVAL;
509
510 group = &(counters->groups[groupid]);
511
512 if (group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED) {
513 /*
514 * In fixed groups the countable equals the fixed register the
515 * user wants. First make sure it is in range
516 */
517
518 if (countable >= group->reg_count)
519 return -EINVAL;
520
521 /* If it is already reserved, just increase the refcounts */
522 if ((group->regs[countable].kernelcount != 0) ||
523 (group->regs[countable].usercount != 0)) {
524 refcount_group(group, countable, flags,
525 offset, offset_hi);
526 return 0;
527 }
528
529 empty = countable;
530 } else {
531 unsigned int i;
532
533 /*
534 * Check if the countable is already associated with a counter.
535 * Refcount and return the offset, otherwise, try and find an
536 * empty counter and assign the countable to it.
537 */
538
539 for (i = 0; i < group->reg_count; i++) {
540 if (group->regs[i].countable == countable) {
541 refcount_group(group, i, flags,
542 offset, offset_hi);
543 return 0;
544 } else if (group->regs[i].countable ==
545 KGSL_PERFCOUNTER_NOT_USED) {
546 /* keep track of unused counter */
547 empty = i;
548 }
549 }
550 }
551
552 /* no available counters, so do nothing else */
553 if (empty == -1)
554 return -EBUSY;
555
556 /* initialize the new counter */
557 group->regs[empty].countable = countable;
558
559 /* enable the new counter */
560 ret = adreno_perfcounter_enable(adreno_dev, groupid, empty, countable);
561 if (ret) {
562 /* Put back the perfcounter */
563 if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED))
564 group->regs[empty].countable =
565 KGSL_PERFCOUNTER_NOT_USED;
566 return ret;
567 }
568
569 /* set initial kernel and user count */
570 if (flags & PERFCOUNTER_FLAG_KERNEL) {
571 group->regs[empty].kernelcount = 1;
572 group->regs[empty].usercount = 0;
573 } else {
574 group->regs[empty].kernelcount = 0;
575 group->regs[empty].usercount = 1;
576 }
577
578 if (offset)
579 *offset = group->regs[empty].offset;
580 if (offset_hi)
581 *offset_hi = group->regs[empty].offset_hi;
582
583 return ret;
584}
585
586
587/**
588 * adreno_perfcounter_put: Release a countable from counter resource
589 * @adreno_dev: Adreno device to configure
590 * @groupid: Desired performance counter group
591 * @countable: Countable desired to be freed from a counter
592 * @flags: Flag to determine if kernel or user space request
593 *
594 * Put a performance counter/countable pair that was previously received. If
595 * noone else is using the countable, free up the counter for others.
596 */
597int adreno_perfcounter_put(struct adreno_device *adreno_dev,
598 unsigned int groupid, unsigned int countable, unsigned int flags)
599{
600 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
601 struct adreno_perfcount_group *group;
602 unsigned int i;
603
604 if (counters == NULL || groupid >= counters->group_count)
605 return -EINVAL;
606
607 group = &(counters->groups[groupid]);
608
609 /*
610 * Find if the counter/countable pair is used currently.
611 * Start cycling through registers in the bank.
612 */
613 for (i = 0; i < group->reg_count; i++) {
614 /* check if countable assigned is what we are looking for */
615 if (group->regs[i].countable == countable) {
616 /* found pair, book keep count based on request type */
617 if (flags & PERFCOUNTER_FLAG_KERNEL &&
618 group->regs[i].kernelcount > 0)
619 group->regs[i].kernelcount--;
620 else if (group->regs[i].usercount > 0)
621 group->regs[i].usercount--;
622 else
623 break;
624
625 /* mark available if not used anymore */
626 if (group->regs[i].kernelcount == 0 &&
627 group->regs[i].usercount == 0)
628 group->regs[i].countable =
629 KGSL_PERFCOUNTER_NOT_USED;
630
631 return 0;
632 }
633 }
634
635 return -EINVAL;
636}
637
638static void _perfcounter_enable_vbif(struct adreno_device *adreno_dev,
639 struct adreno_perfcounters *counters, unsigned int counter,
640 unsigned int countable)
641{
642 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
643 struct adreno_perfcount_register *reg;
644
645 reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF].regs[counter];
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530646
647 if (adreno_has_gbif(adreno_dev)) {
Mihir Patelbfb830d2017-10-31 12:36:01 +0530648 unsigned int shift = counter << 3;
649 unsigned int perfctr_mask = 1 << counter;
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530650 /*
651 * Write 1, followed by 0 to CLR register for
652 * clearing the counter
653 */
654 kgsl_regrmw(device, reg->select - GBIF_PERF_CLR_REG_SEL_OFF,
Mihir Patelbfb830d2017-10-31 12:36:01 +0530655 perfctr_mask, perfctr_mask);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530656 kgsl_regrmw(device, reg->select - GBIF_PERF_CLR_REG_SEL_OFF,
Mihir Patelbfb830d2017-10-31 12:36:01 +0530657 perfctr_mask, 0);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530658 /* select the desired countable */
659 kgsl_regrmw(device, reg->select,
660 GBIF_PERF_RMW_MASK << shift, countable << shift);
661 /* enable counter */
662 kgsl_regrmw(device, reg->select - GBIF_PERF_EN_REG_SEL_OFF,
Mihir Patelbfb830d2017-10-31 12:36:01 +0530663 perfctr_mask, perfctr_mask);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530664
665 } else {
666 /*
667 * Write 1, followed by 0 to CLR register for
668 * clearing the counter
669 */
670 kgsl_regwrite(device,
671 reg->select - VBIF2_PERF_CLR_REG_SEL_OFF, 1);
672 kgsl_regwrite(device,
673 reg->select - VBIF2_PERF_CLR_REG_SEL_OFF, 0);
674 kgsl_regwrite(device,
675 reg->select, countable & VBIF2_PERF_CNT_SEL_MASK);
676 /* enable reg is 8 DWORDS before select reg */
677 kgsl_regwrite(device,
678 reg->select - VBIF2_PERF_EN_REG_SEL_OFF, 1);
679 }
Shrenuj Bansala419c792016-10-20 14:05:11 -0700680 reg->value = 0;
681}
682
683static void _perfcounter_enable_vbif_pwr(struct adreno_device *adreno_dev,
684 struct adreno_perfcounters *counters, unsigned int counter)
685{
686 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
687 struct adreno_perfcount_register *reg;
688
689 reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF_PWR].regs[counter];
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530690
691 if (adreno_has_gbif(adreno_dev)) {
Mihir Patelbfb830d2017-10-31 12:36:01 +0530692 unsigned int perfctr_mask = GBIF_PWR_RMW_MASK << counter;
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530693 /*
694 * Write 1, followed by 0 to CLR register for
695 * clearing the counter
696 */
697 kgsl_regrmw(device, reg->select + GBIF_PWR_CLR_REG_EN_OFF,
Mihir Patelbfb830d2017-10-31 12:36:01 +0530698 perfctr_mask, perfctr_mask);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530699 kgsl_regrmw(device, reg->select + GBIF_PWR_CLR_REG_EN_OFF,
Mihir Patelbfb830d2017-10-31 12:36:01 +0530700 perfctr_mask, 0);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530701 /* Enable the counter */
Mihir Patelbfb830d2017-10-31 12:36:01 +0530702 kgsl_regrmw(device, reg->select, perfctr_mask, perfctr_mask);
Rajesh Kemisetti77b82ed2017-09-24 20:42:41 +0530703 } else {
704 /*
705 * Write 1, followed by 0 to CLR register for
706 * clearing the counter
707 */
708 kgsl_regwrite(device, reg->select +
709 VBIF2_PERF_PWR_CLR_REG_EN_OFF, 1);
710 kgsl_regwrite(device, reg->select +
711 VBIF2_PERF_PWR_CLR_REG_EN_OFF, 0);
712 kgsl_regwrite(device, reg->select, 1);
713 }
Shrenuj Bansala419c792016-10-20 14:05:11 -0700714 reg->value = 0;
715}
716
717static void _power_counter_enable_alwayson(struct adreno_device *adreno_dev,
718 struct adreno_perfcounters *counters)
719{
Rajesh Kemisetti434b87c2017-01-27 00:04:10 +0530720 if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
721 return;
722
Shrenuj Bansala419c792016-10-20 14:05:11 -0700723 kgsl_regwrite(KGSL_DEVICE(adreno_dev),
724 A5XX_GPMU_ALWAYS_ON_COUNTER_RESET, 1);
725 counters->groups[KGSL_PERFCOUNTER_GROUP_ALWAYSON_PWR].regs[0].value = 0;
726}
727
728static void _power_counter_enable_gpmu(struct adreno_device *adreno_dev,
729 struct adreno_perfcounters *counters, unsigned int group,
730 unsigned int counter, unsigned int countable)
731{
732 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
733 struct adreno_perfcount_register *reg;
Lynus Vaz76ecd062017-06-01 20:00:53 +0530734 unsigned int shift = (counter << 3) % (sizeof(unsigned int) * 8);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700735
736 if (adreno_is_a530(adreno_dev)) {
737 if (countable > 43)
738 return;
739 } else if (adreno_is_a540(adreno_dev)) {
740 if (countable > 47)
741 return;
Lynus Vaz4fc97e22017-06-01 20:03:35 +0530742 } else if (adreno_is_a6xx(adreno_dev)) {
743 if (countable > 34)
744 return;
Shrenuj Bansala419c792016-10-20 14:05:11 -0700745 } else
746 /* return on platforms that have no GPMU */
747 return;
748
749 reg = &counters->groups[group].regs[counter];
750 kgsl_regrmw(device, reg->select, 0xff << shift, countable << shift);
Lynus Vaz76ecd062017-06-01 20:00:53 +0530751 adreno_writereg(adreno_dev, ADRENO_REG_GPMU_POWER_COUNTER_ENABLE, 1);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700752 reg->value = 0;
753}
754
755static void _power_counter_enable_default(struct adreno_device *adreno_dev,
756 struct adreno_perfcounters *counters, unsigned int group,
757 unsigned int counter, unsigned int countable)
758{
759 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
760 struct adreno_perfcount_register *reg;
761
Rajesh Kemisetti434b87c2017-01-27 00:04:10 +0530762 if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
763 return;
764
Shrenuj Bansala419c792016-10-20 14:05:11 -0700765 reg = &counters->groups[group].regs[counter];
766 kgsl_regwrite(device, reg->select, countable);
Lynus Vaz76ecd062017-06-01 20:00:53 +0530767 adreno_writereg(adreno_dev, ADRENO_REG_GPMU_POWER_COUNTER_ENABLE, 1);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700768 reg->value = 0;
769}
770
Tarun Karrab8bd0242017-11-13 17:30:44 -0800771static inline bool _perfcounter_inline_update(
772 struct adreno_device *adreno_dev, unsigned int group)
773{
774 if (adreno_is_a6xx(adreno_dev)) {
775 if ((group == KGSL_PERFCOUNTER_GROUP_HLSQ) ||
776 (group == KGSL_PERFCOUNTER_GROUP_SP) ||
777 (group == KGSL_PERFCOUNTER_GROUP_TP))
778 return true;
779 else
780 return false;
781 }
782
783 return true;
784}
785
Shrenuj Bansala419c792016-10-20 14:05:11 -0700786static int _perfcounter_enable_default(struct adreno_device *adreno_dev,
787 struct adreno_perfcounters *counters, unsigned int group,
788 unsigned int counter, unsigned int countable)
789{
790 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
791 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
792 struct adreno_perfcount_register *reg;
Tarun Karra1382e512017-10-30 19:41:25 -0700793 struct adreno_perfcount_group *grp;
Shrenuj Bansala419c792016-10-20 14:05:11 -0700794 int i;
795 int ret = 0;
796
797 /*
798 * check whether the countable is valid or not by matching it against
799 * the list on invalid countables
800 */
801 if (gpudev->invalid_countables) {
802 struct adreno_invalid_countables invalid_countable =
803 gpudev->invalid_countables[group];
804 for (i = 0; i < invalid_countable.num_countables; i++)
805 if (countable == invalid_countable.countables[i])
806 return -EACCES;
807 }
Tarun Karra1382e512017-10-30 19:41:25 -0700808 grp = &(counters->groups[group]);
809 reg = &(grp->regs[counter]);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700810
Tarun Karrab8bd0242017-11-13 17:30:44 -0800811 if (_perfcounter_inline_update(adreno_dev, group) &&
812 test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
Shrenuj Bansala419c792016-10-20 14:05:11 -0700813 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffers[0];
814 unsigned int buf[4];
815 unsigned int *cmds = buf;
816 int ret;
817
Tarun Karrab8bd0242017-11-13 17:30:44 -0800818 if (gpudev->perfcounter_update && (grp->flags &
819 ADRENO_PERFCOUNTER_GROUP_RESTORE))
820 gpudev->perfcounter_update(adreno_dev, reg, false);
821
Shrenuj Bansala419c792016-10-20 14:05:11 -0700822 cmds += cp_wait_for_idle(adreno_dev, cmds);
823 *cmds++ = cp_register(adreno_dev, reg->select, 1);
824 *cmds++ = countable;
825 /* submit to highest priority RB always */
Harshdeep Dhattd91388b2017-12-08 15:51:49 -0700826 ret = adreno_ringbuffer_issue_internal_cmds(rb,
827 KGSL_CMD_FLAGS_PMODE, buf, cmds-buf);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700828 if (ret)
829 return ret;
830 /*
831 * schedule dispatcher to make sure rb[0] is run, because
832 * if the current RB is not rb[0] and gpu is idle then
833 * rb[0] will not get scheduled to run
834 */
835 if (adreno_dev->cur_rb != rb)
836 adreno_dispatcher_schedule(device);
837 /* wait for the above commands submitted to complete */
838 ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp,
839 ADRENO_IDLE_TIMEOUT);
840 if (ret) {
841 /*
842 * If we were woken up because of cancelling rb events
843 * either due to soft reset or adreno_stop, ignore the
844 * error and return 0 here. The perfcounter is already
845 * set up in software and it will be programmed in
846 * hardware when we wake up or come up after soft reset,
847 * by adreno_perfcounter_restore.
848 */
849 if (ret == -EAGAIN)
850 ret = 0;
851 else
852 KGSL_DRV_ERR(device,
853 "Perfcounter %u/%u/%u start via commands failed %d\n",
854 group, counter, countable, ret);
855 }
856 } else {
857 /* Select the desired perfcounter */
Tarun Karra1382e512017-10-30 19:41:25 -0700858 if (gpudev->perfcounter_update && (grp->flags &
859 ADRENO_PERFCOUNTER_GROUP_RESTORE))
860 ret = gpudev->perfcounter_update(adreno_dev, reg, true);
861 else
862 kgsl_regwrite(device, reg->select, countable);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700863 }
864
865 if (!ret)
866 reg->value = 0;
Tarun Karra1382e512017-10-30 19:41:25 -0700867 return ret;
Shrenuj Bansala419c792016-10-20 14:05:11 -0700868}
869
870/**
871 * adreno_perfcounter_enable - Configure a performance counter for a countable
872 * @adreno_dev - Adreno device to configure
873 * @group - Desired performance counter group
874 * @counter - Desired performance counter in the group
875 * @countable - Desired countable
876 *
877 * Function is used for adreno cores
878 * Physically set up a counter within a group with the desired countable
879 * Return 0 on success else error code
880 */
881static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
882 unsigned int group, unsigned int counter, unsigned int countable)
883{
884 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
885 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
886
887 if (counters == NULL)
888 return -EINVAL;
889
890 if (group >= counters->group_count)
891 return -EINVAL;
892
893 if (counter >= counters->groups[group].reg_count)
894 return -EINVAL;
895
896 switch (group) {
897 case KGSL_PERFCOUNTER_GROUP_ALWAYSON:
898 /* alwayson counter is global, so init value is 0 */
899 break;
900 case KGSL_PERFCOUNTER_GROUP_PWR:
901 if (gpudev->enable_pwr_counters)
902 return gpudev->enable_pwr_counters(adreno_dev, counter);
903 return 0;
904 case KGSL_PERFCOUNTER_GROUP_VBIF:
905 if (countable > VBIF2_PERF_CNT_SEL_MASK)
906 return -EINVAL;
907 _perfcounter_enable_vbif(adreno_dev, counters, counter,
908 countable);
909 break;
910 case KGSL_PERFCOUNTER_GROUP_VBIF_PWR:
911 _perfcounter_enable_vbif_pwr(adreno_dev, counters, counter);
912 break;
913 case KGSL_PERFCOUNTER_GROUP_SP_PWR:
914 case KGSL_PERFCOUNTER_GROUP_TP_PWR:
915 case KGSL_PERFCOUNTER_GROUP_RB_PWR:
916 case KGSL_PERFCOUNTER_GROUP_CCU_PWR:
917 case KGSL_PERFCOUNTER_GROUP_UCHE_PWR:
918 case KGSL_PERFCOUNTER_GROUP_CP_PWR:
919 _power_counter_enable_default(adreno_dev, counters, group,
920 counter, countable);
921 break;
922 case KGSL_PERFCOUNTER_GROUP_GPMU_PWR:
923 _power_counter_enable_gpmu(adreno_dev, counters, group, counter,
924 countable);
925 break;
926 case KGSL_PERFCOUNTER_GROUP_ALWAYSON_PWR:
927 _power_counter_enable_alwayson(adreno_dev, counters);
928 break;
929 case KGSL_PERFCOUNTER_GROUP_RBBM:
930 /* The following rbbm countable is not reliable on a540 */
931 if (adreno_is_a540(adreno_dev))
932 if (countable == A5XX_RBBM_ALWAYS_COUNT)
933 return -EINVAL;
934 default:
935 return _perfcounter_enable_default(adreno_dev, counters, group,
936 counter, countable);
937 }
938
939 return 0;
940}
941
942static uint64_t _perfcounter_read_alwayson(struct adreno_device *adreno_dev,
943 struct adreno_perfcount_group *group, unsigned int counter)
944{
945 uint64_t val = 0;
946
947 adreno_readreg64(adreno_dev, ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
948 ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &val);
949
950 return val + group->regs[counter].value;
951}
952
953static uint64_t _perfcounter_read_pwr(struct adreno_device *adreno_dev,
954 struct adreno_perfcount_group *group, unsigned int counter)
955{
956 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
957 struct adreno_perfcount_register *reg;
958 unsigned int in = 0, out, lo = 0, hi = 0;
959 unsigned int enable_bit;
960
961 reg = &group->regs[counter];
962
963 /* Remember, counter 0 is not emulated on 5XX */
964 if (adreno_is_a5xx(adreno_dev) && (counter == 0))
965 return -EINVAL;
966
967 if (adreno_is_a3xx(adreno_dev)) {
968 /* On A3XX we need to freeze the counter so we can read it */
969 if (counter == 0)
970 enable_bit = 0x00010000;
971 else
972 enable_bit = 0x00020000;
973
974 /* freeze counter */
975 adreno_readreg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, &in);
976 out = (in & ~enable_bit);
977 adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, out);
978 }
979
980 kgsl_regread(device, reg->offset, &lo);
981 kgsl_regread(device, reg->offset_hi, &hi);
982
983 /* restore the counter control value */
984 if (adreno_is_a3xx(adreno_dev))
985 adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, in);
986
987 return REG_64BIT_VAL(hi, lo, reg->value);
988}
989
990static uint64_t _perfcounter_read_vbif(struct adreno_device *adreno_dev,
991 struct adreno_perfcount_group *group, unsigned int counter)
992{
993 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
994 struct adreno_perfcount_register *reg;
995 unsigned int lo = 0, hi = 0;
996
997 reg = &group->regs[counter];
998
999 /* freeze counter */
1000 if (adreno_is_a3xx(adreno_dev))
1001 kgsl_regwrite(device, reg->select - VBIF2_PERF_EN_REG_SEL_OFF,
1002 0);
1003
1004 kgsl_regread(device, reg->offset, &lo);
1005 kgsl_regread(device, reg->offset_hi, &hi);
1006
1007 /* un-freeze counter */
1008 if (adreno_is_a3xx(adreno_dev))
1009 kgsl_regwrite(device, reg->select - VBIF2_PERF_EN_REG_SEL_OFF,
1010 1);
1011
1012 return REG_64BIT_VAL(hi, lo, reg->value);
1013}
1014
1015static uint64_t _perfcounter_read_vbif_pwr(struct adreno_device *adreno_dev,
1016 struct adreno_perfcount_group *group, unsigned int counter)
1017{
1018 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
1019 struct adreno_perfcount_register *reg;
1020 unsigned int lo = 0, hi = 0;
1021
1022 reg = &group->regs[counter];
1023
1024 /* freeze counter */
1025 if (adreno_is_a3xx(adreno_dev))
1026 kgsl_regwrite(device, reg->select, 0);
1027
1028 kgsl_regread(device, reg->offset, &lo);
1029 kgsl_regread(device, reg->offset_hi, &hi);
1030
1031 /* un-freeze counter */
1032 if (adreno_is_a3xx(adreno_dev))
1033 kgsl_regwrite(device, reg->select, 1);
1034
1035 return REG_64BIT_VAL(hi, lo, reg->value);
1036}
1037
1038static uint64_t _perfcounter_read_pwrcntr(struct adreno_device *adreno_dev,
1039 struct adreno_perfcount_group *group, unsigned int counter)
1040{
1041 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
1042 struct adreno_perfcount_register *reg;
1043 unsigned int lo = 0, hi = 0;
1044
Rajesh Kemisetti434b87c2017-01-27 00:04:10 +05301045 if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
1046 return 0;
1047
Shrenuj Bansala419c792016-10-20 14:05:11 -07001048 reg = &group->regs[counter];
1049
1050 kgsl_regread(device, reg->offset, &lo);
1051 kgsl_regread(device, reg->offset_hi, &hi);
1052
1053 return REG_64BIT_VAL(hi, lo, reg->value);
1054}
1055
1056static uint64_t _perfcounter_read_default(struct adreno_device *adreno_dev,
1057 struct adreno_perfcount_group *group, unsigned int counter)
1058{
1059 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
1060 struct adreno_perfcount_register *reg;
1061 unsigned int lo = 0, hi = 0;
1062 unsigned int in = 0, out;
1063
1064 reg = &group->regs[counter];
1065
1066 /* Freeze the counter */
1067 if (adreno_is_a3xx(adreno_dev)) {
1068 adreno_readreg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_CTL, &in);
1069 out = in & ~RBBM_PERFCTR_CTL_ENABLE;
1070 adreno_writereg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_CTL, out);
1071 }
1072
1073 /* Read the values */
1074 kgsl_regread(device, reg->offset, &lo);
1075 kgsl_regread(device, reg->offset_hi, &hi);
1076
1077 /* Re-Enable the counter */
1078 if (adreno_is_a3xx(adreno_dev))
1079 adreno_writereg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_CTL, in);
1080
1081 return REG_64BIT_VAL(hi, lo, 0);
1082}
1083
1084/**
1085 * adreno_perfcounter_read() - Reads a performance counter
1086 * @adreno_dev: The device on which the counter is running
1087 * @group: The group of the counter
1088 * @counter: The counter within the group
1089 *
1090 * Function is used to read the counter of adreno devices
1091 * Returns the 64 bit counter value on success else 0.
1092 */
1093uint64_t adreno_perfcounter_read(struct adreno_device *adreno_dev,
1094 unsigned int groupid, unsigned int counter)
1095{
1096 struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
1097 struct adreno_perfcount_group *group;
1098
1099 /* Lets hope this doesn't fail. Now subfunctions don't need to check */
1100 if (counters == NULL)
1101 return 0;
1102
1103 if (groupid >= counters->group_count)
1104 return 0;
1105
1106 group = &counters->groups[groupid];
1107
1108 if (counter >= group->reg_count)
1109 return 0;
1110
1111 switch (groupid) {
1112 case KGSL_PERFCOUNTER_GROUP_ALWAYSON:
1113 return _perfcounter_read_alwayson(adreno_dev, group, counter);
1114 case KGSL_PERFCOUNTER_GROUP_VBIF_PWR:
1115 return _perfcounter_read_vbif_pwr(adreno_dev, group, counter);
1116 case KGSL_PERFCOUNTER_GROUP_VBIF:
1117 return _perfcounter_read_vbif(adreno_dev, group, counter);
1118 case KGSL_PERFCOUNTER_GROUP_PWR:
1119 return _perfcounter_read_pwr(adreno_dev, group, counter);
1120 case KGSL_PERFCOUNTER_GROUP_SP_PWR:
1121 case KGSL_PERFCOUNTER_GROUP_TP_PWR:
1122 case KGSL_PERFCOUNTER_GROUP_RB_PWR:
1123 case KGSL_PERFCOUNTER_GROUP_CCU_PWR:
1124 case KGSL_PERFCOUNTER_GROUP_UCHE_PWR:
1125 case KGSL_PERFCOUNTER_GROUP_CP_PWR:
1126 case KGSL_PERFCOUNTER_GROUP_GPMU_PWR:
1127 case KGSL_PERFCOUNTER_GROUP_ALWAYSON_PWR:
1128 return _perfcounter_read_pwrcntr(adreno_dev, group, counter);
1129 default:
1130 return _perfcounter_read_default(adreno_dev, group, counter);
1131 }
1132}