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

https://bitbucket.org/zozo123/boeffla-kernel-jb-u6-s3 · C · 1282 lines · 1025 code · 207 blank · 50 comment · 174 complexity · b1c8a3a5c2a5a34730c9563fe921cad7 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 "mali_osk_profiling.h"
  32. #endif
  33. #include "mali_pm.h"
  34. #include "mali_cluster.h"
  35. #include "mali_group.h"
  36. #include "mali_gp.h"
  37. #include "mali_pp.h"
  38. #include "mali_l2_cache.h"
  39. #include "mali_hw_core.h"
  40. #include "mali_kernel_core.h"
  41. #include "mali_user_settings_db.h"
  42. #include "mali_device_pause_resume.h"
  43. #define POWER_BUFFER_SIZE 3
  44. static struct dentry *mali_debugfs_dir = NULL;
  45. typedef enum
  46. {
  47. _MALI_DEVICE_SUSPEND,
  48. _MALI_DEVICE_RESUME,
  49. _MALI_DEVICE_DVFS_PAUSE,
  50. _MALI_DEVICE_DVFS_RESUME,
  51. _MALI_MAX_EVENTS
  52. } _mali_device_debug_power_events;
  53. static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
  54. [_MALI_DEVICE_SUSPEND] = "suspend",
  55. [_MALI_DEVICE_RESUME] = "resume",
  56. [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
  57. [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
  58. };
  59. static u32 virtual_power_status_register=0;
  60. static char pwr_buf[POWER_BUFFER_SIZE];
  61. static int open_copy_private_data(struct inode *inode, struct file *filp)
  62. {
  63. filp->private_data = inode->i_private;
  64. return 0;
  65. }
  66. static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  67. {
  68. char buf[64];
  69. int r;
  70. u32 val;
  71. struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
  72. if (0 == src_id)
  73. {
  74. val = mali_gp_core_get_counter_src0(gp_core);
  75. }
  76. else
  77. {
  78. val = mali_gp_core_get_counter_src1(gp_core);
  79. }
  80. if (MALI_HW_CORE_NO_COUNTER == val)
  81. {
  82. r = sprintf(buf, "-1\n");
  83. }
  84. else
  85. {
  86. r = sprintf(buf, "%u\n", val);
  87. }
  88. return simple_read_from_buffer(ubuf, cnt, gpos, buf, r);
  89. }
  90. static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  91. {
  92. struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
  93. char buf[64];
  94. long val;
  95. int ret;
  96. if (cnt >= sizeof(buf))
  97. {
  98. return -EINVAL;
  99. }
  100. if (copy_from_user(&buf, ubuf, cnt))
  101. {
  102. return -EFAULT;
  103. }
  104. buf[cnt] = 0;
  105. ret = strict_strtol(buf, 10, &val);
  106. if (ret < 0)
  107. {
  108. return ret;
  109. }
  110. if (val < 0)
  111. {
  112. /* any negative input will disable counter */
  113. val = MALI_HW_CORE_NO_COUNTER;
  114. }
  115. if (0 == src_id)
  116. {
  117. if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
  118. {
  119. return 0;
  120. }
  121. }
  122. else
  123. {
  124. if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
  125. {
  126. return 0;
  127. }
  128. }
  129. *gpos += cnt;
  130. return cnt;
  131. }
  132. static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  133. {
  134. char buf[64];
  135. long val;
  136. int ret;
  137. u32 ci;
  138. struct mali_cluster *cluster;
  139. if (cnt >= sizeof(buf))
  140. {
  141. return -EINVAL;
  142. }
  143. if (copy_from_user(&buf, ubuf, cnt))
  144. {
  145. return -EFAULT;
  146. }
  147. buf[cnt] = 0;
  148. ret = strict_strtol(buf, 10, &val);
  149. if (ret < 0)
  150. {
  151. return ret;
  152. }
  153. if (val < 0)
  154. {
  155. /* any negative input will disable counter */
  156. val = MALI_HW_CORE_NO_COUNTER;
  157. }
  158. ci = 0;
  159. cluster = mali_cluster_get_global_cluster(ci);
  160. while (NULL != cluster)
  161. {
  162. u32 gi = 0;
  163. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  164. while (NULL != group)
  165. {
  166. struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
  167. if (NULL != gp_core)
  168. {
  169. if (0 == src_id)
  170. {
  171. if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
  172. {
  173. return 0;
  174. }
  175. }
  176. else
  177. {
  178. if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
  179. {
  180. return 0;
  181. }
  182. }
  183. }
  184. /* try next group */
  185. gi++;
  186. group = mali_cluster_get_group(cluster, gi);
  187. }
  188. /* try next cluster */
  189. ci++;
  190. cluster = mali_cluster_get_global_cluster(ci);
  191. }
  192. *gpos += cnt;
  193. return cnt;
  194. }
  195. static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
  196. {
  197. return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0);
  198. }
  199. static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
  200. {
  201. return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1);
  202. }
  203. static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  204. {
  205. return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
  206. }
  207. static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  208. {
  209. return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
  210. }
  211. static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  212. {
  213. return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
  214. }
  215. static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
  216. {
  217. return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
  218. }
  219. static const struct file_operations gp_gpx_counter_src0_fops = {
  220. .owner = THIS_MODULE,
  221. .open = open_copy_private_data,
  222. .read = gp_gpx_counter_src0_read,
  223. .write = gp_gpx_counter_src0_write,
  224. };
  225. static const struct file_operations gp_gpx_counter_src1_fops = {
  226. .owner = THIS_MODULE,
  227. .open = open_copy_private_data,
  228. .read = gp_gpx_counter_src1_read,
  229. .write = gp_gpx_counter_src1_write,
  230. };
  231. static const struct file_operations gp_all_counter_src0_fops = {
  232. .owner = THIS_MODULE,
  233. .write = gp_all_counter_src0_write,
  234. };
  235. static const struct file_operations gp_all_counter_src1_fops = {
  236. .owner = THIS_MODULE,
  237. .write = gp_all_counter_src1_write,
  238. };
  239. static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  240. {
  241. char buf[64];
  242. int r;
  243. u32 val;
  244. struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
  245. if (0 == src_id)
  246. {
  247. val = mali_pp_core_get_counter_src0(pp_core);
  248. }
  249. else
  250. {
  251. val = mali_pp_core_get_counter_src1(pp_core);
  252. }
  253. if (MALI_HW_CORE_NO_COUNTER == val)
  254. {
  255. r = sprintf(buf, "-1\n");
  256. }
  257. else
  258. {
  259. r = sprintf(buf, "%u\n", val);
  260. }
  261. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  262. }
  263. static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  264. {
  265. struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
  266. char buf[64];
  267. long val;
  268. int ret;
  269. if (cnt >= sizeof(buf))
  270. {
  271. return -EINVAL;
  272. }
  273. if (copy_from_user(&buf, ubuf, cnt))
  274. {
  275. return -EFAULT;
  276. }
  277. buf[cnt] = 0;
  278. ret = strict_strtol(buf, 10, &val);
  279. if (ret < 0)
  280. {
  281. return ret;
  282. }
  283. if (val < 0)
  284. {
  285. /* any negative input will disable counter */
  286. val = MALI_HW_CORE_NO_COUNTER;
  287. }
  288. if (0 == src_id)
  289. {
  290. if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
  291. {
  292. return 0;
  293. }
  294. }
  295. else
  296. {
  297. if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
  298. {
  299. return 0;
  300. }
  301. }
  302. *ppos += cnt;
  303. return cnt;
  304. }
  305. static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  306. {
  307. char buf[64];
  308. long val;
  309. int ret;
  310. u32 ci;
  311. struct mali_cluster *cluster;
  312. if (cnt >= sizeof(buf))
  313. {
  314. return -EINVAL;
  315. }
  316. if (copy_from_user(&buf, ubuf, cnt))
  317. {
  318. return -EFAULT;
  319. }
  320. buf[cnt] = 0;
  321. ret = strict_strtol(buf, 10, &val);
  322. if (ret < 0)
  323. {
  324. return ret;
  325. }
  326. if (val < 0)
  327. {
  328. /* any negative input will disable counter */
  329. val = MALI_HW_CORE_NO_COUNTER;
  330. }
  331. ci = 0;
  332. cluster = mali_cluster_get_global_cluster(ci);
  333. while (NULL != cluster)
  334. {
  335. u32 gi = 0;
  336. struct mali_group *group = mali_cluster_get_group(cluster, gi);
  337. while (NULL != group)
  338. {
  339. struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
  340. if (NULL != pp_core)
  341. {
  342. if (0 == src_id)
  343. {
  344. if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
  345. {
  346. return 0;
  347. }
  348. }
  349. else
  350. {
  351. if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
  352. {
  353. return 0;
  354. }
  355. }
  356. }
  357. /* try next group */
  358. gi++;
  359. group = mali_cluster_get_group(cluster, gi);
  360. }
  361. /* try next cluster */
  362. ci++;
  363. cluster = mali_cluster_get_global_cluster(ci);
  364. }
  365. *ppos += cnt;
  366. return cnt;
  367. }
  368. static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  369. {
  370. return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
  371. }
  372. static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  373. {
  374. return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
  375. }
  376. static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  377. {
  378. return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  379. }
  380. static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  381. {
  382. return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  383. }
  384. static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  385. {
  386. return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  387. }
  388. static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  389. {
  390. return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  391. }
  392. static const struct file_operations pp_ppx_counter_src0_fops = {
  393. .owner = THIS_MODULE,
  394. .open = open_copy_private_data,
  395. .read = pp_ppx_counter_src0_read,
  396. .write = pp_ppx_counter_src0_write,
  397. };
  398. static const struct file_operations pp_ppx_counter_src1_fops = {
  399. .owner = THIS_MODULE,
  400. .open = open_copy_private_data,
  401. .read = pp_ppx_counter_src1_read,
  402. .write = pp_ppx_counter_src1_write,
  403. };
  404. static const struct file_operations pp_all_counter_src0_fops = {
  405. .owner = THIS_MODULE,
  406. .write = pp_all_counter_src0_write,
  407. };
  408. static const struct file_operations pp_all_counter_src1_fops = {
  409. .owner = THIS_MODULE,
  410. .write = pp_all_counter_src1_write,
  411. };
  412. static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  413. {
  414. char buf[64];
  415. int r;
  416. u32 val;
  417. struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
  418. if (0 == src_id)
  419. {
  420. val = mali_l2_cache_core_get_counter_src0(l2_core);
  421. }
  422. else
  423. {
  424. val = mali_l2_cache_core_get_counter_src1(l2_core);
  425. }
  426. if (MALI_HW_CORE_NO_COUNTER == val)
  427. {
  428. r = sprintf(buf, "-1\n");
  429. }
  430. else
  431. {
  432. r = sprintf(buf, "%u\n", val);
  433. }
  434. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  435. }
  436. static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  437. {
  438. struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
  439. char buf[64];
  440. long val;
  441. int ret;
  442. if (cnt >= sizeof(buf))
  443. {
  444. return -EINVAL;
  445. }
  446. if (copy_from_user(&buf, ubuf, cnt))
  447. {
  448. return -EFAULT;
  449. }
  450. buf[cnt] = 0;
  451. ret = strict_strtol(buf, 10, &val);
  452. if (ret < 0)
  453. {
  454. return ret;
  455. }
  456. if (val < 0)
  457. {
  458. /* any negative input will disable counter */
  459. val = MALI_HW_CORE_NO_COUNTER;
  460. }
  461. if (0 == src_id)
  462. {
  463. if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val))
  464. {
  465. return 0;
  466. }
  467. }
  468. else
  469. {
  470. if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val))
  471. {
  472. return 0;
  473. }
  474. }
  475. *ppos += cnt;
  476. return cnt;
  477. }
  478. static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
  479. {
  480. char buf[64];
  481. long val;
  482. int ret;
  483. u32 l2_id;
  484. struct mali_l2_cache_core *l2_cache;
  485. if (cnt >= sizeof(buf))
  486. {
  487. return -EINVAL;
  488. }
  489. if (copy_from_user(&buf, ubuf, cnt))
  490. {
  491. return -EFAULT;
  492. }
  493. buf[cnt] = 0;
  494. ret = strict_strtol(buf, 10, &val);
  495. if (ret < 0)
  496. {
  497. return ret;
  498. }
  499. if (val < 0)
  500. {
  501. /* any negative input will disable counter */
  502. val = MALI_HW_CORE_NO_COUNTER;
  503. }
  504. l2_id = 0;
  505. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  506. while (NULL != l2_cache)
  507. {
  508. if (0 == src_id)
  509. {
  510. if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val))
  511. {
  512. return 0;
  513. }
  514. }
  515. else
  516. {
  517. if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val))
  518. {
  519. return 0;
  520. }
  521. }
  522. /* try next L2 */
  523. l2_id++;
  524. l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
  525. }
  526. *ppos += cnt;
  527. return cnt;
  528. }
  529. static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  530. {
  531. return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
  532. }
  533. static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  534. {
  535. return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
  536. }
  537. static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  538. {
  539. return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  540. }
  541. static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  542. {
  543. return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  544. }
  545. static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  546. {
  547. return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
  548. }
  549. static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  550. {
  551. return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
  552. }
  553. static const struct file_operations l2_l2x_counter_src0_fops = {
  554. .owner = THIS_MODULE,
  555. .open = open_copy_private_data,
  556. .read = l2_l2x_counter_src0_read,
  557. .write = l2_l2x_counter_src0_write,
  558. };
  559. static const struct file_operations l2_l2x_counter_src1_fops = {
  560. .owner = THIS_MODULE,
  561. .open = open_copy_private_data,
  562. .read = l2_l2x_counter_src1_read,
  563. .write = l2_l2x_counter_src1_write,
  564. };
  565. static const struct file_operations l2_all_counter_src0_fops = {
  566. .owner = THIS_MODULE,
  567. .write = l2_all_counter_src0_write,
  568. };
  569. static const struct file_operations l2_all_counter_src1_fops = {
  570. .owner = THIS_MODULE,
  571. .write = l2_all_counter_src1_write,
  572. };
  573. static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  574. {
  575. memset(pwr_buf, 0, POWER_BUFFER_SIZE);
  576. virtual_power_status_register = 0;
  577. if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
  578. {
  579. mali_pm_os_suspend();
  580. /* @@@@ assuming currently suspend is successful later on to tune as per previous*/
  581. virtual_power_status_register =1;
  582. }
  583. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME])))
  584. {
  585. mali_pm_os_resume();
  586. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  587. virtual_power_status_register = 1;
  588. }
  589. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])))
  590. {
  591. mali_bool power_on;
  592. mali_dev_pause(&power_on);
  593. if (!power_on)
  594. {
  595. virtual_power_status_register = 2;
  596. mali_dev_resume();
  597. }
  598. else
  599. {
  600. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  601. virtual_power_status_register =1;
  602. }
  603. }
  604. else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])))
  605. {
  606. mali_dev_resume();
  607. /* @@@@ assuming currently resume is successful later on to tune as per previous */
  608. virtual_power_status_register = 1;
  609. }
  610. *ppos += cnt;
  611. sprintf(pwr_buf, "%d",virtual_power_status_register);
  612. return cnt;
  613. }
  614. static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  615. {
  616. return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
  617. }
  618. static loff_t power_events_seek(struct file *file, loff_t offset, int orig)
  619. {
  620. file->f_pos = offset;
  621. return 0;
  622. }
  623. static const struct file_operations power_events_fops = {
  624. .owner = THIS_MODULE,
  625. .read = power_events_read,
  626. .write = power_events_write,
  627. .llseek = power_events_seek,
  628. };
  629. #if MALI_STATE_TRACKING
  630. static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
  631. {
  632. u32 len = 0;
  633. u32 size;
  634. char *buf;
  635. size = seq_get_buf(seq_file, &buf);
  636. if(!size)
  637. {
  638. return -ENOMEM;
  639. }
  640. /* Create the internal state dump. */
  641. len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
  642. len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
  643. len += _mali_kernel_core_dump_state(buf + len, size - len);
  644. seq_commit(seq_file, len);
  645. return 0;
  646. }
  647. static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
  648. {
  649. return single_open(file, mali_seq_internal_state_show, NULL);
  650. }
  651. static const struct file_operations mali_seq_internal_state_fops = {
  652. .owner = THIS_MODULE,
  653. .open = mali_seq_internal_state_open,
  654. .read = seq_read,
  655. .llseek = seq_lseek,
  656. .release = single_release,
  657. };
  658. #endif /* MALI_STATE_TRACKING */
  659. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  660. static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  661. {
  662. char buf[64];
  663. int r;
  664. r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0);
  665. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  666. }
  667. static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  668. {
  669. char buf[64];
  670. unsigned long val;
  671. int ret;
  672. if (cnt >= sizeof(buf))
  673. {
  674. return -EINVAL;
  675. }
  676. if (copy_from_user(&buf, ubuf, cnt))
  677. {
  678. return -EFAULT;
  679. }
  680. buf[cnt] = 0;
  681. ret = strict_strtoul(buf, 10, &val);
  682. if (ret < 0)
  683. {
  684. return ret;
  685. }
  686. if (val != 0)
  687. {
  688. u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
  689. /* check if we are already recording */
  690. if (MALI_TRUE == _mali_osk_profiling_is_recording())
  691. {
  692. MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
  693. return -EFAULT;
  694. }
  695. /* check if we need to clear out an old recording first */
  696. if (MALI_TRUE == _mali_osk_profiling_have_recording())
  697. {
  698. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear())
  699. {
  700. MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
  701. return -EFAULT;
  702. }
  703. }
  704. /* start recording profiling data */
  705. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
  706. {
  707. MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
  708. return -EFAULT;
  709. }
  710. MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
  711. }
  712. else
  713. {
  714. /* stop recording profiling data */
  715. u32 count = 0;
  716. if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count))
  717. {
  718. MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
  719. return -EFAULT;
  720. }
  721. MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
  722. }
  723. *ppos += cnt;
  724. return cnt;
  725. }
  726. static const struct file_operations profiling_record_fops = {
  727. .owner = THIS_MODULE,
  728. .read = profiling_record_read,
  729. .write = profiling_record_write,
  730. };
  731. static void *profiling_events_start(struct seq_file *s, loff_t *pos)
  732. {
  733. loff_t *spos;
  734. /* check if we have data avaiable */
  735. if (MALI_TRUE != _mali_osk_profiling_have_recording())
  736. {
  737. return NULL;
  738. }
  739. spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
  740. if (NULL == spos)
  741. {
  742. return NULL;
  743. }
  744. *spos = *pos;
  745. return spos;
  746. }
  747. static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
  748. {
  749. loff_t *spos = v;
  750. /* check if we have data avaiable */
  751. if (MALI_TRUE != _mali_osk_profiling_have_recording())
  752. {
  753. return NULL;
  754. }
  755. /* check if the next entry actually is avaiable */
  756. if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1))
  757. {
  758. return NULL;
  759. }
  760. *pos = ++*spos;
  761. return spos;
  762. }
  763. static void profiling_events_stop(struct seq_file *s, void *v)
  764. {
  765. kfree(v);
  766. }
  767. static int profiling_events_show(struct seq_file *seq_file, void *v)
  768. {
  769. loff_t *spos = v;
  770. u32 index;
  771. u64 timestamp;
  772. u32 event_id;
  773. u32 data[5];
  774. index = (u32)*spos;
  775. /* Retrieve all events */
  776. if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, &timestamp, &event_id, data))
  777. {
  778. 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]);
  779. return 0;
  780. }
  781. return 0;
  782. }
  783. static const struct seq_operations profiling_events_seq_ops = {
  784. .start = profiling_events_start,
  785. .next = profiling_events_next,
  786. .stop = profiling_events_stop,
  787. .show = profiling_events_show
  788. };
  789. static int profiling_events_open(struct inode *inode, struct file *file)
  790. {
  791. return seq_open(file, &profiling_events_seq_ops);
  792. }
  793. static const struct file_operations profiling_events_fops = {
  794. .owner = THIS_MODULE,
  795. .open = profiling_events_open,
  796. .read = seq_read,
  797. .llseek = seq_lseek,
  798. .release = seq_release,
  799. };
  800. #endif
  801. static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  802. {
  803. char buf[64];
  804. size_t r;
  805. u32 mem = _mali_ukk_report_memory_usage();
  806. r = snprintf(buf, 64, "%u\n", mem);
  807. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  808. }
  809. static const struct file_operations memory_usage_fops = {
  810. .owner = THIS_MODULE,
  811. .read = memory_used_read,
  812. };
  813. static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
  814. {
  815. u32 val;
  816. int ret;
  817. _mali_uk_user_setting_t setting;
  818. char buf[32];
  819. cnt = min(cnt, sizeof(buf) - 1);
  820. if (copy_from_user(buf, ubuf, cnt))
  821. {
  822. return -EFAULT;
  823. }
  824. buf[cnt] = '\0';
  825. ret = strict_strtoul(buf, 10, &val);
  826. if (0 != ret)
  827. {
  828. return ret;
  829. }
  830. /* Update setting */
  831. setting = (_mali_uk_user_setting_t)(filp->private_data);
  832. mali_set_user_setting(setting, val);
  833. *ppos += cnt;
  834. return cnt;
  835. }
  836. static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
  837. {
  838. char buf[64];
  839. size_t r;
  840. u32 value;
  841. _mali_uk_user_setting_t setting;
  842. setting = (_mali_uk_user_setting_t)(filp->private_data);
  843. value = mali_get_user_setting(setting);
  844. r = snprintf(buf, 64, "%u\n", value);
  845. return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
  846. }
  847. static const struct file_operations user_settings_fops = {
  848. .owner = THIS_MODULE,
  849. .open = open_copy_private_data,
  850. .read = user_settings_read,
  851. .write = user_settings_write,
  852. };
  853. static int mali_sysfs_user_settings_register(void)
  854. {
  855. struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
  856. if (mali_user_settings_dir != NULL)
  857. {
  858. int i;
  859. for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++)
  860. {
  861. debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
  862. }
  863. }
  864. return 0;
  865. }
  866. int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
  867. {
  868. int err = 0;
  869. struct device * mdev;
  870. device->mali_class = class_create(THIS_MODULE, mali_dev_name);
  871. if (IS_ERR(device->mali_class))
  872. {
  873. err = PTR_ERR(device->mali_class);
  874. goto init_class_err;
  875. }
  876. mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
  877. if (IS_ERR(mdev))
  878. {
  879. err = PTR_ERR(mdev);
  880. goto init_mdev_err;
  881. }
  882. mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
  883. if(ERR_PTR(-ENODEV) == mali_debugfs_dir)
  884. {
  885. /* Debugfs not supported. */
  886. mali_debugfs_dir = NULL;
  887. }
  888. else
  889. {
  890. if(NULL != mali_debugfs_dir)
  891. {
  892. /* Debugfs directory created successfully; create files now */
  893. struct dentry *mali_power_dir;
  894. struct dentry *mali_gp_dir;
  895. struct dentry *mali_pp_dir;
  896. struct dentry *mali_l2_dir;
  897. #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  898. struct dentry *mali_profiling_dir;
  899. #endif
  900. /* @@@@ todo: make a nicer solution? */
  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