adreno_perfcounter.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/slab.h>
  7. #include "adreno.h"
  8. #include "adreno_perfcounter.h"
  9. static inline int active_countable(unsigned int countable)
  10. {
  11. return ((countable != KGSL_PERFCOUNTER_NOT_USED) &&
  12. (countable != KGSL_PERFCOUNTER_BROKEN));
  13. }
  14. /**
  15. * adreno_perfcounter_restore() - Restore performance counters
  16. * @adreno_dev: adreno device to configure
  17. *
  18. * Load the physical performance counters with 64 bit value which are
  19. * saved on GPU power collapse.
  20. */
  21. void adreno_perfcounter_restore(struct adreno_device *adreno_dev)
  22. {
  23. const struct adreno_perfcounters *counters =
  24. ADRENO_PERFCOUNTERS(adreno_dev);
  25. const struct adreno_perfcount_group *group;
  26. unsigned int counter, groupid;
  27. /* Do not save/restore if not requested */
  28. if (counters == NULL || !adreno_dev->perfcounter)
  29. return;
  30. for (groupid = 0; groupid < counters->group_count; groupid++) {
  31. group = &(counters->groups[groupid]);
  32. if (!group->load)
  33. continue;
  34. /* Restore the counters for the group */
  35. for (counter = 0; counter < group->reg_count; counter++) {
  36. /* If not active or broken, skip this counter */
  37. if (!active_countable(group->regs[counter].countable))
  38. continue;
  39. group->load(adreno_dev, &group->regs[counter]);
  40. }
  41. }
  42. }
  43. /**
  44. * adreno_perfcounter_save() - Save performance counters
  45. * @adreno_dev: adreno device to configure
  46. *
  47. * Save the performance counter values before GPU power collapse.
  48. * The saved values are restored on restart.
  49. * This ensures physical counters are coherent across power-collapse.
  50. * This function must be called with the oob_gpu set request.
  51. */
  52. inline void adreno_perfcounter_save(struct adreno_device *adreno_dev)
  53. {
  54. const struct adreno_perfcounters *counters =
  55. ADRENO_PERFCOUNTERS(adreno_dev);
  56. const struct adreno_perfcount_group *group;
  57. unsigned int counter, groupid;
  58. /* Do not save/restore if not requested */
  59. if (counters == NULL || !adreno_dev->perfcounter)
  60. return;
  61. for (groupid = 0; groupid < counters->group_count; groupid++) {
  62. group = &(counters->groups[groupid]);
  63. /* Save the counter values for the group */
  64. for (counter = 0; counter < group->reg_count; counter++) {
  65. /* If not active or broken, skip this counter */
  66. if (!active_countable(group->regs[counter].countable))
  67. continue;
  68. /* accumulate values for non-loadable counters */
  69. if (group->regs[counter].load_bit >= 0)
  70. group->regs[counter].value = 0;
  71. group->regs[counter].value =
  72. group->regs[counter].value +
  73. adreno_perfcounter_read(adreno_dev, groupid,
  74. counter);
  75. }
  76. }
  77. }
  78. static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
  79. unsigned int group, unsigned int counter, unsigned int countable);
  80. /**
  81. * adreno_perfcounter_start: Enable performance counters
  82. * @adreno_dev: Adreno device to configure
  83. *
  84. * Ensure all performance counters are enabled that are allocated. Since
  85. * the device was most likely stopped, we can't trust that the counters
  86. * are still valid so make it so.
  87. */
  88. void adreno_perfcounter_start(struct adreno_device *adreno_dev)
  89. {
  90. const struct adreno_perfcounters *counters =
  91. ADRENO_PERFCOUNTERS(adreno_dev);
  92. const struct adreno_perfcount_group *group;
  93. unsigned int i, j;
  94. if (counters == NULL)
  95. return;
  96. /* group id iter */
  97. for (i = 0; i < counters->group_count; i++) {
  98. group = &(counters->groups[i]);
  99. /* countable iter */
  100. for (j = 0; j < group->reg_count; j++) {
  101. if (!active_countable(group->regs[j].countable))
  102. continue;
  103. /*
  104. * The GPU has to be idle before calling the perfcounter
  105. * enable function, but since this function is called
  106. * during start we already know the GPU is idle.
  107. * Since the countable/counter pairs have already been
  108. * validated, there is no way for _enable() to fail so
  109. * no need to check the return code.
  110. */
  111. adreno_perfcounter_enable(adreno_dev, i, j,
  112. group->regs[j].countable);
  113. }
  114. }
  115. }
  116. /**
  117. * adreno_perfcounter_read_group() - Determine which countables are in counters
  118. * @adreno_dev: Adreno device to configure
  119. * @reads: List of kgsl_perfcounter_read_groups
  120. * @count: Length of list
  121. *
  122. * Read the performance counters for the groupid/countable pairs and return
  123. * the 64 bit result for each pair
  124. */
  125. int adreno_perfcounter_read_group(struct adreno_device *adreno_dev,
  126. struct kgsl_perfcounter_read_group __user *reads, unsigned int count)
  127. {
  128. struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
  129. const struct adreno_perfcounters *counters =
  130. ADRENO_PERFCOUNTERS(adreno_dev);
  131. const struct adreno_perfcount_group *group;
  132. struct kgsl_perfcounter_read_group *list = NULL;
  133. unsigned int i, j;
  134. int ret = 0;
  135. if (counters == NULL)
  136. return -EINVAL;
  137. /* sanity check params passed in */
  138. if (reads == NULL || count == 0 || count > 100)
  139. return -EINVAL;
  140. list = kmalloc_array(count, sizeof(struct kgsl_perfcounter_read_group),
  141. GFP_KERNEL);
  142. if (!list)
  143. return -ENOMEM;
  144. if (copy_from_user(list, reads,
  145. sizeof(struct kgsl_perfcounter_read_group) * count)) {
  146. ret = -EFAULT;
  147. goto done;
  148. }
  149. mutex_lock(&device->mutex);
  150. ret = adreno_perfcntr_active_oob_get(adreno_dev);
  151. if (ret) {
  152. mutex_unlock(&device->mutex);
  153. goto done;
  154. }
  155. /* list iterator */
  156. for (j = 0; j < count; j++) {
  157. list[j].value = 0;
  158. /* Verify that the group ID is within range */
  159. if (list[j].groupid >= counters->group_count) {
  160. ret = -EINVAL;
  161. break;
  162. }
  163. group = &(counters->groups[list[j].groupid]);
  164. /* group/counter iterator */
  165. for (i = 0; i < group->reg_count; i++) {
  166. if (group->regs[i].countable == list[j].countable) {
  167. list[j].value = adreno_perfcounter_read(
  168. adreno_dev, list[j].groupid, i);
  169. break;
  170. }
  171. }
  172. }
  173. adreno_perfcntr_active_oob_put(adreno_dev);
  174. mutex_unlock(&device->mutex);
  175. /* write the data */
  176. if (ret == 0)
  177. if (copy_to_user(reads, list,
  178. sizeof(struct kgsl_perfcounter_read_group) * count))
  179. ret = -EFAULT;
  180. done:
  181. kfree(list);
  182. return ret;
  183. }
  184. /**
  185. * adreno_perfcounter_get_groupid() - Get the performance counter ID
  186. * @adreno_dev: Adreno device
  187. * @name: Performance counter group name string
  188. *
  189. * Get the groupid based on the name and return this ID
  190. */
  191. int adreno_perfcounter_get_groupid(struct adreno_device *adreno_dev,
  192. const char *name)
  193. {
  194. const struct adreno_perfcounters *counters =
  195. ADRENO_PERFCOUNTERS(adreno_dev);
  196. const struct adreno_perfcount_group *group;
  197. int i;
  198. if (name == NULL || counters == NULL)
  199. return -EINVAL;
  200. for (i = 0; i < counters->group_count; ++i) {
  201. group = &(counters->groups[i]);
  202. /* make sure there is a name for this group */
  203. if (group->name == NULL)
  204. continue;
  205. /* verify name and length */
  206. if (strlen(name) == strlen(group->name) &&
  207. strcmp(group->name, name) == 0)
  208. return i;
  209. }
  210. return -EINVAL;
  211. }
  212. /**
  213. * adreno_perfcounter_get_name() - Get the group name
  214. * @adreno_dev: Adreno device
  215. * @groupid: Desired performance counter groupid
  216. *
  217. * Get the name based on the groupid and return it
  218. */
  219. const char *adreno_perfcounter_get_name(struct adreno_device *adreno_dev,
  220. unsigned int groupid)
  221. {
  222. const struct adreno_perfcounters *counters =
  223. ADRENO_PERFCOUNTERS(adreno_dev);
  224. if (counters != NULL && groupid < counters->group_count)
  225. return counters->groups[groupid].name;
  226. return NULL;
  227. }
  228. /**
  229. * adreno_perfcounter_query_group: Determine which countables are in counters
  230. * @adreno_dev: Adreno device to configure
  231. * @groupid: Desired performance counter group
  232. * @countables: Return list of all countables in the groups counters
  233. * @count: Max length of the array
  234. * @max_counters: max counters for the groupid
  235. *
  236. * Query the current state of counters for the group.
  237. */
  238. int adreno_perfcounter_query_group(struct adreno_device *adreno_dev,
  239. unsigned int groupid, unsigned int __user *countables,
  240. unsigned int count, unsigned int *max_counters)
  241. {
  242. struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
  243. const struct adreno_perfcounters *counters =
  244. ADRENO_PERFCOUNTERS(adreno_dev);
  245. const struct adreno_perfcount_group *group;
  246. unsigned int i, t;
  247. int ret = 0;
  248. unsigned int *buf;
  249. *max_counters = 0;
  250. if (counters == NULL || groupid >= counters->group_count)
  251. return -EINVAL;
  252. mutex_lock(&device->mutex);
  253. group = &(counters->groups[groupid]);
  254. *max_counters = group->reg_count;
  255. /*
  256. * if NULL countable or *count of zero, return max reg_count in
  257. * *max_counters and return success
  258. */
  259. if (countables == NULL || count == 0) {
  260. mutex_unlock(&device->mutex);
  261. return 0;
  262. }
  263. t = min_t(unsigned int, group->reg_count, count);
  264. buf = kmalloc_array(t, sizeof(unsigned int), GFP_KERNEL);
  265. if (buf == NULL) {
  266. mutex_unlock(&device->mutex);
  267. return -ENOMEM;
  268. }
  269. for (i = 0; i < t; i++)
  270. buf[i] = group->regs[i].countable;
  271. mutex_unlock(&device->mutex);
  272. if (copy_to_user(countables, buf, sizeof(unsigned int) * t))
  273. ret = -EFAULT;
  274. kfree(buf);
  275. return ret;
  276. }
  277. static inline void refcount_group(const struct adreno_perfcount_group *group,
  278. unsigned int reg, unsigned int flags,
  279. unsigned int *lo, unsigned int *hi)
  280. {
  281. if (flags & PERFCOUNTER_FLAG_KERNEL)
  282. group->regs[reg].kernelcount++;
  283. else
  284. group->regs[reg].usercount++;
  285. if (lo)
  286. *lo = group->regs[reg].offset;
  287. if (hi)
  288. *hi = group->regs[reg].offset_hi;
  289. }
  290. /**
  291. * adreno_perfcounter_get: Try to put a countable in an available counter
  292. * @adreno_dev: Adreno device to configure
  293. * @groupid: Desired performance counter group
  294. * @countable: Countable desired to be in a counter
  295. * @offset: Return offset of the LO counter assigned
  296. * @offset_hi: Return offset of the HI counter assigned
  297. * @flags: Used to setup kernel perf counters
  298. *
  299. * Try to place a countable in an available counter. If the countable is
  300. * already in a counter, reference count the counter/countable pair resource
  301. * and return success
  302. */
  303. int adreno_perfcounter_get(struct adreno_device *adreno_dev,
  304. unsigned int groupid, unsigned int countable, unsigned int *offset,
  305. unsigned int *offset_hi, unsigned int flags)
  306. {
  307. const struct adreno_perfcounters *counters =
  308. ADRENO_PERFCOUNTERS(adreno_dev);
  309. const struct adreno_perfcount_group *group;
  310. unsigned int empty = -1;
  311. int ret = 0;
  312. /* always clear return variables */
  313. if (offset)
  314. *offset = 0;
  315. if (offset_hi)
  316. *offset_hi = 0;
  317. if (counters == NULL)
  318. return -EINVAL;
  319. if (groupid >= counters->group_count)
  320. return -EINVAL;
  321. group = &(counters->groups[groupid]);
  322. if (group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED) {
  323. /*
  324. * In fixed groups the countable equals the fixed register the
  325. * user wants. First make sure it is in range
  326. */
  327. if (countable >= group->reg_count)
  328. return -EINVAL;
  329. /* If it is already reserved, just increase the refcounts */
  330. if ((group->regs[countable].kernelcount != 0) ||
  331. (group->regs[countable].usercount != 0)) {
  332. refcount_group(group, countable, flags,
  333. offset, offset_hi);
  334. return 0;
  335. }
  336. empty = countable;
  337. } else {
  338. unsigned int i;
  339. /*
  340. * Check if the countable is already associated with a counter.
  341. * Refcount and return the offset, otherwise, try and find an
  342. * empty counter and assign the countable to it.
  343. */
  344. for (i = 0; i < group->reg_count; i++) {
  345. if (group->regs[i].countable == countable) {
  346. refcount_group(group, i, flags,
  347. offset, offset_hi);
  348. return 0;
  349. } else if (group->regs[i].countable ==
  350. KGSL_PERFCOUNTER_NOT_USED) {
  351. /* keep track of unused counter */
  352. empty = i;
  353. }
  354. }
  355. }
  356. /* no available counters, so do nothing else */
  357. if (empty == -1)
  358. return -EBUSY;
  359. /* initialize the new counter */
  360. group->regs[empty].countable = countable;
  361. /* enable the new counter */
  362. ret = adreno_perfcounter_enable(adreno_dev, groupid, empty, countable);
  363. if (ret) {
  364. /* Put back the perfcounter */
  365. if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED))
  366. group->regs[empty].countable =
  367. KGSL_PERFCOUNTER_NOT_USED;
  368. return ret;
  369. }
  370. if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_RESTORE))
  371. adreno_dev->no_restore_count++;
  372. /* set initial kernel and user count */
  373. if (flags & PERFCOUNTER_FLAG_KERNEL) {
  374. group->regs[empty].kernelcount = 1;
  375. group->regs[empty].usercount = 0;
  376. } else {
  377. group->regs[empty].kernelcount = 0;
  378. group->regs[empty].usercount = 1;
  379. }
  380. if (offset)
  381. *offset = group->regs[empty].offset;
  382. if (offset_hi)
  383. *offset_hi = group->regs[empty].offset_hi;
  384. return ret;
  385. }
  386. /**
  387. * adreno_perfcounter_put: Release a countable from counter resource
  388. * @adreno_dev: Adreno device to configure
  389. * @groupid: Desired performance counter group
  390. * @countable: Countable desired to be freed from a counter
  391. * @flags: Flag to determine if kernel or user space request
  392. *
  393. * Put a performance counter/countable pair that was previously received. If
  394. * noone else is using the countable, free up the counter for others.
  395. */
  396. int adreno_perfcounter_put(struct adreno_device *adreno_dev,
  397. unsigned int groupid, unsigned int countable, unsigned int flags)
  398. {
  399. const struct adreno_perfcounters *counters =
  400. ADRENO_PERFCOUNTERS(adreno_dev);
  401. const struct adreno_perfcount_group *group;
  402. const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
  403. unsigned int i;
  404. int ret = 0;
  405. if (counters == NULL || groupid >= counters->group_count)
  406. return -EINVAL;
  407. group = &(counters->groups[groupid]);
  408. /*
  409. * Find if the counter/countable pair is used currently.
  410. * Start cycling through registers in the bank.
  411. */
  412. for (i = 0; i < group->reg_count; i++) {
  413. /* check if countable assigned is what we are looking for */
  414. if (group->regs[i].countable == countable) {
  415. /* found pair, book keep count based on request type */
  416. if (flags & PERFCOUNTER_FLAG_KERNEL &&
  417. group->regs[i].kernelcount > 0)
  418. group->regs[i].kernelcount--;
  419. else if (group->regs[i].usercount > 0)
  420. group->regs[i].usercount--;
  421. else
  422. break;
  423. /* mark available if not used anymore */
  424. if (group->regs[i].kernelcount == 0 &&
  425. group->regs[i].usercount == 0) {
  426. if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_RESTORE))
  427. adreno_dev->no_restore_count--;
  428. if (gpudev->perfcounter_remove)
  429. ret = gpudev->perfcounter_remove(adreno_dev,
  430. &group->regs[i], groupid);
  431. if (!ret)
  432. group->regs[i].countable = KGSL_PERFCOUNTER_NOT_USED;
  433. }
  434. return ret;
  435. }
  436. }
  437. return -EINVAL;
  438. }
  439. /**
  440. * adreno_perfcounter_enable - Configure a performance counter for a countable
  441. * @adreno_dev - Adreno device to configure
  442. * @group - Desired performance counter group
  443. * @counter - Desired performance counter in the group
  444. * @countable - Desired countable
  445. *
  446. * Function is used for adreno cores
  447. * Physically set up a counter within a group with the desired countable
  448. * Return 0 on success else error code
  449. */
  450. static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
  451. unsigned int groupid, unsigned int counter, unsigned int countable)
  452. {
  453. const struct adreno_perfcounters *counters =
  454. ADRENO_PERFCOUNTERS(adreno_dev);
  455. const struct adreno_perfcount_group *group;
  456. if (counters == NULL)
  457. return -EINVAL;
  458. if (groupid >= counters->group_count)
  459. return -EINVAL;
  460. group = &counters->groups[groupid];
  461. if (counter >= group->reg_count)
  462. return -EINVAL;
  463. return group->enable(adreno_dev, group, counter, countable);
  464. }
  465. /**
  466. * adreno_perfcounter_read() - Reads a performance counter
  467. * @adreno_dev: The device on which the counter is running
  468. * @group: The group of the counter
  469. * @counter: The counter within the group
  470. *
  471. * Function is used to read the counter of adreno devices
  472. * Returns the 64 bit counter value on success else 0.
  473. */
  474. uint64_t adreno_perfcounter_read(struct adreno_device *adreno_dev,
  475. unsigned int groupid, unsigned int counter)
  476. {
  477. const struct adreno_perfcounters *counters =
  478. ADRENO_PERFCOUNTERS(adreno_dev);
  479. const struct adreno_perfcount_group *group;
  480. /* Lets hope this doesn't fail. Now subfunctions don't need to check */
  481. if (counters == NULL)
  482. return 0;
  483. if (groupid >= counters->group_count)
  484. return 0;
  485. group = &counters->groups[groupid];
  486. if (counter >= group->reg_count)
  487. return 0;
  488. return group->read(adreno_dev, group, counter);
  489. }