/drivers/media/video/samsung/mali_r3p0_lsi/linux/mali_kernel_sysfs.c

https://bitbucket.org/zozo123/boeffla-kernel-jb-u6-s3 · C · 1282 lines · 1026 code · 207 blank · 49 comment · 174 complexity · a62406fb52019bc09e0fed79e359c524 MD5 · raw file

  1. /**
  2. * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
  3. *
  4. * This program is free software and is provided to you under the terms of the GNU General Public License version 2
  5. * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
  6. *
  7. * A copy of the licence is included with the program, and can also be obtained from Free Software
  8. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  9. */
  10. /**
  11. * @file mali_kernel_sysfs.c
  12. * Implementation of some sysfs data exports
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/fs.h>
  16. #include <linux/device.h>
  17. #include <linux/version.h>
  18. #include <linux/module.h>
  19. #include <linux/slab.h>
  20. #include "mali_kernel_license.h"
  21. #include "mali_kernel_common.h"
  22. #include "mali_kernel_linux.h"
  23. #include "mali_ukk.h"
  24. #if MALI_LICENSE_IS_GPL
  25. #include <linux/seq_file.h>
  26. #include <linux/debugfs.h>
  27. #include <asm/uaccess.h>
  28. #include <linux/module.h>
  29. #include "mali_kernel_sysfs.h"
  30. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  31. #include <linux/slab.h>
  32. #include "mali_osk_profiling.h"
  33. #endif
  34. #include "mali_pm.h"
  35. #include "mali_cluster.h"
  36. #include "mali_group.h"
  37. #include "mali_gp.h"
  38. #include "mali_pp.h"
  39. #include "mali_l2_cache.h"
  40. #include "mali_hw_core.h"
  41. #include "mali_kernel_core.h"
  42. #include "mali_user_settings_db.h"
  43. #include "mali_device_pause_resume.h"
  44. #define POWER_BUFFER_SIZE 3
  45. static struct dentry *mali_debugfs_dir = NULL;
  46. typedef enum
  47. {
  48. _MALI_DEVICE_SUSPEND,
  49. _MALI_DEVICE_RESUME,
  50. _MALI_DEVICE_DVFS_PAUSE,
  51. _MALI_DEVICE_DVFS_RESUME,
  52. _MALI_MAX_EVENTS
  53. } _mali_device_debug_power_events;
  54. static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
  55. [_MALI_DEVICE_SUSPEND] = "suspend",
  56. [_MALI_DEVICE_RESUME] = "resume",
  57. [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
  58. [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
  59. };
  60. static u32 virtual_power_status_register=0;
  61. static char pwr_buf[POWER_BUFFER_SIZE];
  62. static int open_copy_private_data(struct inode *inode, struct file *filp)
  63. {
  64. filp->private_data = inode->i_private;
  65. return 0;
  66. }
  67. static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  68. {
  69. char buf[64];
  70. int r;
  71. u32 val;
  72. struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
  73. if (0 == src_id)
  74. {
  75. val = mali_gp_core_get_counter_src0(gp_core);
  76. }
  77. else
  78. {
  79. val = mali_gp_core_get_counter_src1(gp_core);
  80. }
  81. if (MALI_HW_CORE_NO_COUNTER == val)
  82. {
  83. r = sprintf(buf, "-1\n");
  84. }
  85. else
  86. {
  87. r = sprintf(buf, "%u\n", val);
  88. }
  89. return simple_read_from_buffer(ubuf, cnt, gpos, buf, r);
  90. }
  91. static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  92. {
  93. struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
  94. char buf[64];
  95. long val;
  96. int ret;
  97. if (cnt >= sizeof(buf))
  98. {
  99. return -EINVAL;
  100. }
  101. if (copy_from_user(&buf, ubuf, cnt))
  102. {
  103. return -EFAULT;
  104. }
  105. buf[cnt] = 0;
  106. ret = strict_strtol(buf, 10, &val);
  107. if (ret < 0)
  108. {
  109. return ret;
  110. }
  111. if (val < 0)
  112. {
  113. /* any negative input will disable counter */
  114. val = MALI_HW_CORE_NO_COUNTER;
  115. }
  116. if (0 == src_id)
  117. {
  118. if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
  119. {
  120. return 0;
  121. }
  122. }
  123. else
  124. {
  125. if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
  126. {
  127. return 0;
  128. }
  129. }
  130. *gpos += cnt;
  131. return cnt;
  132. }
  133. static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  134. {
  135. char buf[64];
  136. long val;
  137. int ret;
  138. u32 ci;
  139. struct mali_cluster *cluster;
  140. if (cnt >= sizeof(buf))
  141. {
  142. return -EINVAL;
  143. }
  144. if (copy_from_user(&buf, ubuf, cnt))
  145. {
  146. return -EFAULT;
  147. }
  148. buf[cnt] = 0;
  149. ret = strict_strtol(buf, 10, &val);
  150. if (ret < 0)
  151. {
  152. return ret;
  153. }
  154. if (val < 0)
  155. {
  156. /* any negative input will disable counter */
  157. val = MALI_HW_CORE_NO_COUNTER;
  158. }
  159. ci = 0;
  160. cluster = mali_cluster_get_global_cluster(ci);
  161. while (NULL != cluster)
  162. {
  163. u32 gi = 0;
  164. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  165. while (NULL != group)
  166. {
  167. struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
  168. if (NULL != gp_core)
  169. {
  170. if (0 == src_id)
  171. {
  172. if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
  173. {
  174. return 0;
  175. }
  176. }
  177. else
  178. {
  179. if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
  180. {
  181. return 0;
  182. }
  183. }
  184. }
  185. /* try next group */
  186. gi++;
  187. group = mali_cluster_get_group(cluster, gi);
  188. }
  189. /* try next cluster */
  190. ci++;
  191. cluster = mali_cluster_get_global_cluster(ci);
  192. }
  193. *gpos += cnt;
  194. return cnt;
  195. }
  196. static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
  197. {
  198. return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0);
  199. }
  200. static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
  201. {
  202. return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1);
  203. }
  204. static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  205. {
  206. return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
  207. }
  208. static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  209. {
  210. return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
  211. }
  212. static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  213. {
  214. return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
  215. }
  216. static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  217. {
  218. return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
  219. }
  220. static const struct file_operations gp_gpx_counter_src0_fops = {
  221. .owner = THIS_MODULE,
  222. .open = open_copy_private_data,
  223. .read = gp_gpx_counter_src0_read,
  224. .write = gp_gpx_counter_src0_write,
  225. };
  226. static const struct file_operations gp_gpx_counter_src1_fops = {
  227. .owner = THIS_MODULE,
  228. .open = open_copy_private_data,
  229. .read = gp_gpx_counter_src1_read,
  230. .write = gp_gpx_counter_src1_write,
  231. };
  232. static const struct file_operations gp_all_counter_src0_fops = {
  233. .owner = THIS_MODULE,
  234. .write = gp_all_counter_src0_write,
  235. };
  236. static const struct file_operations gp_all_counter_src1_fops = {
  237. .owner = THIS_MODULE,
  238. .write = gp_all_counter_src1_write,
  239. };
  240. static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  241. {
  242. char buf[64];
  243. int r;
  244. u32 val;
  245. struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
  246. if (0 == src_id)
  247. {
  248. val = mali_pp_core_get_counter_src0(pp_core);
  249. }
  250. else
  251. {
  252. val = mali_pp_core_get_counter_src1(pp_core);
  253. }
  254. if (MALI_HW_CORE_NO_COUNTER == val)
  255. {
  256. r = sprintf(buf, "-1\n");
  257. }
  258. else
  259. {
  260. r = sprintf(buf, "%u\n", val);
  261. }
  262. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  263. }
  264. static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  265. {
  266. struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
  267. char buf[64];
  268. long val;
  269. int ret;
  270. if (cnt >= sizeof(buf))
  271. {
  272. return -EINVAL;
  273. }
  274. if (copy_from_user(&buf, ubuf, cnt))
  275. {
  276. return -EFAULT;
  277. }
  278. buf[cnt] = 0;
  279. ret = strict_strtol(buf, 10, &val);
  280. if (ret < 0)
  281. {
  282. return ret;
  283. }
  284. if (val < 0)
  285. {
  286. /* any negative input will disable counter */
  287. val = MALI_HW_CORE_NO_COUNTER;
  288. }
  289. if (0 == src_id)
  290. {
  291. if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
  292. {
  293. return 0;
  294. }
  295. }
  296. else
  297. {
  298. if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
  299. {
  300. return 0;
  301. }
  302. }
  303. *ppos += cnt;
  304. return cnt;
  305. }
  306. static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  307. {
  308. char buf[64];
  309. long val;
  310. int ret;
  311. u32 ci;
  312. struct mali_cluster *cluster;
  313. if (cnt >= sizeof(buf))
  314. {
  315. return -EINVAL;
  316. }
  317. if (copy_from_user(&buf, ubuf, cnt))
  318. {
  319. return -EFAULT;
  320. }
  321. buf[cnt] = 0;
  322. ret = strict_strtol(buf, 10, &val);
  323. if (ret < 0)
  324. {
  325. return ret;
  326. }
  327. if (val < 0)
  328. {
  329. /* any negative input will disable counter */
  330. val = MALI_HW_CORE_NO_COUNTER;
  331. }
  332. ci = 0;
  333. cluster = mali_cluster_get_global_cluster(ci);
  334. while (NULL != cluster)
  335. {
  336. u32 gi = 0;
  337. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  338. while (NULL != group)
  339. {
  340. struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
  341. if (NULL != pp_core)
  342. {
  343. if (0 == src_id)
  344. {
  345. if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
  346. {
  347. return 0;
  348. }
  349. }
  350. else
  351. {
  352. if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
  353. {
  354. return 0;
  355. }
  356. }
  357. }
  358. /* try next group */
  359. gi++;
  360. group = mali_cluster_get_group(cluster, gi);
  361. }
  362. /* try next cluster */
  363. ci++;
  364. cluster = mali_cluster_get_global_cluster(ci);
  365. }
  366. *ppos += cnt;
  367. return cnt;
  368. }
  369. static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  370. {
  371. return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
  372. }
  373. static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  374. {
  375. return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
  376. }
  377. static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  378. {
  379. return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  380. }
  381. static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  382. {
  383. return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  384. }
  385. static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  386. {
  387. return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  388. }
  389. static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  390. {
  391. return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  392. }
  393. static const struct file_operations pp_ppx_counter_src0_fops = {
  394. .owner = THIS_MODULE,
  395. .open = open_copy_private_data,
  396. .read = pp_ppx_counter_src0_read,
  397. .write = pp_ppx_counter_src0_write,
  398. };
  399. static const struct file_operations pp_ppx_counter_src1_fops = {
  400. .owner = THIS_MODULE,
  401. .open = open_copy_private_data,
  402. .read = pp_ppx_counter_src1_read,
  403. .write = pp_ppx_counter_src1_write,
  404. };
  405. static const struct file_operations pp_all_counter_src0_fops = {
  406. .owner = THIS_MODULE,
  407. .write = pp_all_counter_src0_write,
  408. };
  409. static const struct file_operations pp_all_counter_src1_fops = {
  410. .owner = THIS_MODULE,
  411. .write = pp_all_counter_src1_write,
  412. };
  413. static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  414. {
  415. char buf[64];
  416. int r;
  417. u32 val;
  418. struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
  419. if (0 == src_id)
  420. {
  421. val = mali_l2_cache_core_get_counter_src0(l2_core);
  422. }
  423. else
  424. {
  425. val = mali_l2_cache_core_get_counter_src1(l2_core);
  426. }
  427. if (MALI_HW_CORE_NO_COUNTER == val)
  428. {
  429. r = sprintf(buf, "-1\n");
  430. }
  431. else
  432. {
  433. r = sprintf(buf, "%u\n", val);
  434. }
  435. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  436. }
  437. static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  438. {
  439. struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
  440. char buf[64];
  441. long val;
  442. int ret;
  443. if (cnt >= sizeof(buf))
  444. {
  445. return -EINVAL;
  446. }
  447. if (copy_from_user(&buf, ubuf, cnt))
  448. {
  449. return -EFAULT;
  450. }
  451. buf[cnt] = 0;
  452. ret = strict_strtol(buf, 10, &val);
  453. if (ret < 0)
  454. {
  455. return ret;
  456. }
  457. if (val < 0)
  458. {
  459. /* any negative input will disable counter */
  460. val = MALI_HW_CORE_NO_COUNTER;
  461. }
  462. if (0 == src_id)
  463. {
  464. if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val))
  465. {
  466. return 0;
  467. }
  468. }
  469. else
  470. {
  471. if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val))
  472. {
  473. return 0;
  474. }
  475. }
  476. *ppos += cnt;
  477. return cnt;
  478. }
  479. static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  480. {
  481. char buf[64];
  482. long val;
  483. int ret;
  484. u32 l2_id;
  485. struct mali_l2_cache_core *l2_cache;
  486. if (cnt >= sizeof(buf))
  487. {
  488. return -EINVAL;
  489. }
  490. if (copy_from_user(&buf, ubuf, cnt))
  491. {
  492. return -EFAULT;
  493. }
  494. buf[cnt] = 0;
  495. ret = strict_strtol(buf, 10, &val);
  496. if (ret < 0)
  497. {
  498. return ret;
  499. }
  500. if (val < 0)
  501. {
  502. /* any negative input will disable counter */
  503. val = MALI_HW_CORE_NO_COUNTER;
  504. }
  505. l2_id = 0;
  506. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  507. while (NULL != l2_cache)
  508. {
  509. if (0 == src_id)
  510. {
  511. if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val))
  512. {
  513. return 0;
  514. }
  515. }
  516. else
  517. {
  518. if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val))
  519. {
  520. return 0;
  521. }
  522. }
  523. /* try next L2 */
  524. l2_id++;
  525. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  526. }
  527. *ppos += cnt;
  528. return cnt;
  529. }
  530. static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  531. {
  532. return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
  533. }
  534. static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  535. {
  536. return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
  537. }
  538. static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  539. {
  540. return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  541. }
  542. static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  543. {
  544. return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  545. }
  546. static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  547. {
  548. return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  549. }
  550. static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  551. {
  552. return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  553. }
  554. static const struct file_operations l2_l2x_counter_src0_fops = {
  555. .owner = THIS_MODULE,
  556. .open = open_copy_private_data,
  557. .read = l2_l2x_counter_src0_read,
  558. .write = l2_l2x_counter_src0_write,
  559. };
  560. static const struct file_operations l2_l2x_counter_src1_fops = {
  561. .owner = THIS_MODULE,
  562. .open = open_copy_private_data,
  563. .read = l2_l2x_counter_src1_read,
  564. .write = l2_l2x_counter_src1_write,
  565. };
  566. static const struct file_operations l2_all_counter_src0_fops = {
  567. .owner = THIS_MODULE,
  568. .write = l2_all_counter_src0_write,
  569. };
  570. static const struct file_operations l2_all_counter_src1_fops = {
  571. .owner = THIS_MODULE,
  572. .write = l2_all_counter_src1_write,
  573. };
  574. static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  575. {
  576. memset(pwr_buf,0,POWER_BUFFER_SIZE);
  577. virtual_power_status_register = 0;
  578. if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
  579. {
  580. mali_pm_os_suspend();
  581. /* @@@@ assuming currently suspend is successful later on to tune as per previous*/
  582. virtual_power_status_register =1;
  583. }
  584. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME])))
  585. {
  586. mali_pm_os_resume();
  587. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  588. virtual_power_status_register = 1;
  589. }
  590. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])))
  591. {
  592. mali_bool power_on;
  593. mali_dev_pause(&power_on);
  594. if (!power_on)
  595. {
  596. virtual_power_status_register = 2;
  597. mali_dev_resume();
  598. }
  599. else
  600. {
  601. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  602. virtual_power_status_register =1;
  603. }
  604. }
  605. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])))
  606. {
  607. mali_dev_resume();
  608. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  609. virtual_power_status_register = 1;
  610. }
  611. *ppos += cnt;
  612. sprintf(pwr_buf, "%d",virtual_power_status_register);
  613. return cnt;
  614. }
  615. static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  616. {
  617. return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
  618. }
  619. static loff_t power_events_seek(struct file *file, loff_t offset, int orig)
  620. {
  621. file->f_pos = offset;
  622. return 0;
  623. }
  624. static const struct file_operations power_events_fops = {
  625. .owner = THIS_MODULE,
  626. .read = power_events_read,
  627. .write = power_events_write,
  628. .llseek = power_events_seek,
  629. };
  630. #if MALI_STATE_TRACKING
  631. static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
  632. {
  633. u32 len = 0;
  634. u32 size;
  635. char *buf;
  636. size = seq_get_buf(seq_file, &buf);
  637. if(!size)
  638. {
  639. return -ENOMEM;
  640. }
  641. /* Create the internal state dump. */
  642. len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
  643. len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
  644. len += _mali_kernel_core_dump_state(buf + len, size - len);
  645. seq_commit(seq_file, len);
  646. return 0;
  647. }
  648. static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
  649. {
  650. return single_open(file, mali_seq_internal_state_show, NULL);
  651. }
  652. static const struct file_operations mali_seq_internal_state_fops = {
  653. .owner = THIS_MODULE,
  654. .open = mali_seq_internal_state_open,
  655. .read = seq_read,
  656. .llseek = seq_lseek,
  657. .release = single_release,
  658. };
  659. #endif /* MALI_STATE_TRACKING */
  660. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  661. static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  662. {
  663. char buf[64];
  664. int r;
  665. r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0);
  666. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  667. }
  668. static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  669. {
  670. char buf[64];
  671. unsigned long val;
  672. int ret;
  673. if (cnt >= sizeof(buf))
  674. {
  675. return -EINVAL;
  676. }
  677. if (copy_from_user(&buf, ubuf, cnt))
  678. {
  679. return -EFAULT;
  680. }
  681. buf[cnt] = 0;
  682. ret = strict_strtoul(buf, 10, &val);
  683. if (ret < 0)
  684. {
  685. return ret;
  686. }
  687. if (val != 0)
  688. {
  689. u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
  690. /* check if we are already recording */
  691. if (MALI_TRUE == _mali_osk_profiling_is_recording())
  692. {
  693. MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
  694. return -EFAULT;
  695. }
  696. /* check if we need to clear out an old recording first */
  697. if (MALI_TRUE == _mali_osk_profiling_have_recording())
  698. {
  699. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear())
  700. {
  701. MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
  702. return -EFAULT;
  703. }
  704. }
  705. /* start recording profiling data */
  706. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
  707. {
  708. MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
  709. return -EFAULT;
  710. }
  711. MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
  712. }
  713. else
  714. {
  715. /* stop recording profiling data */
  716. u32 count = 0;
  717. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count))
  718. {
  719. MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
  720. return -EFAULT;
  721. }
  722. MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
  723. }
  724. *ppos += cnt;
  725. return cnt;
  726. }
  727. static const struct file_operations profiling_record_fops = {
  728. .owner = THIS_MODULE,
  729. .read = profiling_record_read,
  730. .write = profiling_record_write,
  731. };
  732. static void *profiling_events_start(struct seq_file *s, loff_t *pos)
  733. {
  734. loff_t *spos;
  735. /* check if we have data avaiable */
  736. if (MALI_TRUE != _mali_osk_profiling_have_recording())
  737. {
  738. return NULL;
  739. }
  740. spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
  741. if (NULL == spos)
  742. {
  743. return NULL;
  744. }
  745. *spos = *pos;
  746. return spos;
  747. }
  748. static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
  749. {
  750. loff_t *spos = v;
  751. /* check if we have data avaiable */
  752. if (MALI_TRUE != _mali_osk_profiling_have_recording())
  753. {
  754. return NULL;
  755. }
  756. /* check if the next entry actually is avaiable */
  757. if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1))
  758. {
  759. return NULL;
  760. }
  761. *pos = ++*spos;
  762. return spos;
  763. }
  764. static void profiling_events_stop(struct seq_file *s, void *v)
  765. {
  766. kfree(v);
  767. }
  768. static int profiling_events_show(struct seq_file *seq_file, void *v)
  769. {
  770. loff_t *spos = v;
  771. u32 index;
  772. u64 timestamp;
  773. u32 event_id;
  774. u32 data[5];
  775. index = (u32)*spos;
  776. /* Retrieve all events */
  777. if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, &timestamp, &event_id, data))
  778. {
  779. seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
  780. return 0;
  781. }
  782. return 0;
  783. }
  784. static const struct seq_operations profiling_events_seq_ops = {
  785. .start = profiling_events_start,
  786. .next = profiling_events_next,
  787. .stop = profiling_events_stop,
  788. .show = profiling_events_show
  789. };
  790. static int profiling_events_open(struct inode *inode, struct file *file)
  791. {
  792. return seq_open(file, &profiling_events_seq_ops);
  793. }
  794. static const struct file_operations profiling_events_fops = {
  795. .owner = THIS_MODULE,
  796. .open = profiling_events_open,
  797. .read = seq_read,
  798. .llseek = seq_lseek,
  799. .release = seq_release,
  800. };
  801. #endif
  802. static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  803. {
  804. char buf[64];
  805. size_t r;
  806. u32 mem = _mali_ukk_report_memory_usage();
  807. r = snprintf(buf, 64, "%u\n", mem);
  808. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  809. }
  810. static const struct file_operations memory_usage_fops = {
  811. .owner = THIS_MODULE,
  812. .read = memory_used_read,
  813. };
  814. static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  815. {
  816. unsigned long val;
  817. int ret;
  818. _mali_uk_user_setting_t setting;
  819. char buf[32];
  820. cnt = min(cnt, sizeof(buf) - 1);
  821. if (copy_from_user(buf, ubuf, cnt))
  822. {
  823. return -EFAULT;
  824. }
  825. buf[cnt] = '\0';
  826. ret = strict_strtoul(buf, 10, &val);
  827. if (0 != ret)
  828. {
  829. return ret;
  830. }
  831. /* Update setting */
  832. setting = (_mali_uk_user_setting_t)(filp->private_data);
  833. mali_set_user_setting(setting, val);
  834. *ppos += cnt;
  835. return cnt;
  836. }
  837. static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  838. {
  839. char buf[64];
  840. size_t r;
  841. u32 value;
  842. _mali_uk_user_setting_t setting;
  843. setting = (_mali_uk_user_setting_t)(filp->private_data);
  844. value = mali_get_user_setting(setting);
  845. r = snprintf(buf, 64, "%u\n", value);
  846. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  847. }
  848. static const struct file_operations user_settings_fops = {
  849. .owner = THIS_MODULE,
  850. .open = open_copy_private_data,
  851. .read = user_settings_read,
  852. .write = user_settings_write,
  853. };
  854. static int mali_sysfs_user_settings_register(void)
  855. {
  856. struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
  857. if (mali_user_settings_dir != NULL)
  858. {
  859. int i;
  860. for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++)
  861. {
  862. debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
  863. }
  864. }
  865. return 0;
  866. }
  867. int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
  868. {
  869. int err = 0;
  870. struct device * mdev;
  871. device->mali_class = class_create(THIS_MODULE, mali_dev_name);
  872. if (IS_ERR(device->mali_class))
  873. {
  874. err = PTR_ERR(device->mali_class);
  875. goto init_class_err;
  876. }
  877. mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
  878. if (IS_ERR(mdev))
  879. {
  880. err = PTR_ERR(mdev);
  881. goto init_mdev_err;
  882. }
  883. mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
  884. if(ERR_PTR(-ENODEV) == mali_debugfs_dir)
  885. {
  886. /* Debugfs not supported. */
  887. mali_debugfs_dir = NULL;
  888. }
  889. else
  890. {
  891. if(NULL != mali_debugfs_dir)
  892. {
  893. /* Debugfs directory created successfully; create files now */
  894. struct dentry *mali_power_dir;
  895. struct dentry *mali_gp_dir;
  896. struct dentry *mali_pp_dir;
  897. struct dentry *mali_l2_dir;
  898. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  899. struct dentry *mali_profiling_dir;
  900. #endif
  901. mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
  902. if (mali_power_dir != NULL)
  903. {
  904. debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops);
  905. }
  906. mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
  907. if (mali_gp_dir != NULL)
  908. {
  909. struct dentry *mali_gp_all_dir;
  910. u32 ci;
  911. struct mali_cluster *cluster;
  912. mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir);
  913. if (mali_gp_all_dir != NULL)
  914. {
  915. debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops);
  916. debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops);
  917. }
  918. ci = 0;
  919. cluster = mali_cluster_get_global_cluster(ci);
  920. while (NULL != cluster)
  921. {
  922. u32 gi = 0;
  923. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  924. while (NULL != group)
  925. {
  926. struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
  927. if (NULL != gp_core)
  928. {
  929. struct dentry *mali_gp_gpx_dir;
  930. mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
  931. if (NULL != mali_gp_gpx_dir)
  932. {
  933. debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
  934. debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
  935. }
  936. break; /* no need to look for any other GP cores */
  937. }
  938. /* try next group */
  939. gi++;
  940. group = mali_cluster_get_group(cluster, gi);
  941. }
  942. /* try next cluster */
  943. ci++;
  944. cluster = mali_cluster_get_global_cluster(ci);
  945. }
  946. }
  947. mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
  948. if (mali_pp_dir != NULL)
  949. {
  950. struct dentry *mali_pp_all_dir;
  951. u32 ci;
  952. struct mali_cluster *cluster;
  953. mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir);
  954. if (mali_pp_all_dir != NULL)
  955. {
  956. debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops);
  957. debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops);
  958. }
  959. ci = 0;
  960. cluster = mali_cluster_get_global_cluster(ci);
  961. while (NULL != cluster)
  962. {
  963. u32 gi = 0;
  964. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  965. while (NULL != group)
  966. {
  967. struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
  968. if (NULL != pp_core)
  969. {
  970. char buf[16];
  971. struct dentry *mali_pp_ppx_dir;
  972. _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
  973. mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
  974. if (NULL != mali_pp_ppx_dir)
  975. {
  976. debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
  977. debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
  978. }
  979. }
  980. /* try next group */
  981. gi++;
  982. group = mali_cluster_get_group(cluster, gi);
  983. }
  984. /* try next cluster */
  985. ci++;
  986. cluster = mali_cluster_get_global_cluster(ci);
  987. }
  988. }
  989. mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
  990. if (mali_l2_dir != NULL)
  991. {
  992. struct dentry *mali_l2_all_dir;
  993. u32 l2_id;
  994. struct mali_l2_cache_core *l2_cache;
  995. mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
  996. if (mali_l2_all_dir != NULL)
  997. {
  998. debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
  999. debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
  1000. }
  1001. l2_id = 0;
  1002. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  1003. while (NULL != l2_cache)
  1004. {
  1005. char buf[16];
  1006. struct dentry *mali_l2_l2x_dir;
  1007. _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
  1008. mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
  1009. if (NULL != mali_l2_l2x_dir)
  1010. {
  1011. debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
  1012. debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
  1013. }
  1014. /* try next L2 */
  1015. l2_id++;
  1016. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  1017. }
  1018. }
  1019. debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
  1020. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  1021. mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
  1022. if (mali_profiling_dir != NULL)
  1023. {
  1024. struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
  1025. if (mali_profiling_proc_dir != NULL)
  1026. {
  1027. struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
  1028. if (mali_profiling_proc_default_dir != NULL)
  1029. {
  1030. debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
  1031. }
  1032. }
  1033. debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
  1034. debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
  1035. }
  1036. #endif
  1037. #if MALI_STATE_TRACKING
  1038. debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
  1039. #endif
  1040. if (mali_sysfs_user_settings_register())
  1041. {
  1042. /* Failed to create the debugfs entries for the user settings DB. */
  1043. MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
  1044. }
  1045. }
  1046. }
  1047. /* Success! */
  1048. return 0;
  1049. /* Error handling */
  1050. init_mdev_err:
  1051. class_destroy(device->mali_class);
  1052. init_class_err:
  1053. return err;
  1054. }
  1055. int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
  1056. {
  1057. if(NULL != mali_debugfs_dir)
  1058. {
  1059. debugfs_remove_recursive(mali_debugfs_dir);
  1060. }
  1061. device_destroy(device->mali_class, dev);
  1062. class_destroy(device->mali_class);
  1063. return 0;
  1064. }
  1065. #else
  1066. /* Dummy implementations for non-GPL */
  1067. int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
  1068. {
  1069. return 0;
  1070. }
  1071. int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
  1072. {
  1073. return 0;
  1074. }
  1075. #endif