hidma_dbg.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Qualcomm Technologies HIDMA debug file
  3. *
  4. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 and
  8. * only version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/debugfs.h>
  16. #include <linux/device.h>
  17. #include <linux/list.h>
  18. #include <linux/pm_runtime.h>
  19. #include "hidma.h"
  20. static void hidma_ll_chstats(struct seq_file *s, void *llhndl, u32 tre_ch)
  21. {
  22. struct hidma_lldev *lldev = llhndl;
  23. struct hidma_tre *tre;
  24. u32 length;
  25. dma_addr_t src_start;
  26. dma_addr_t dest_start;
  27. u32 *tre_local;
  28. if (tre_ch >= lldev->nr_tres) {
  29. dev_err(lldev->dev, "invalid TRE number in chstats:%d", tre_ch);
  30. return;
  31. }
  32. tre = &lldev->trepool[tre_ch];
  33. seq_printf(s, "------Channel %d -----\n", tre_ch);
  34. seq_printf(s, "allocated=%d\n", atomic_read(&tre->allocated));
  35. seq_printf(s, "queued = 0x%x\n", tre->queued);
  36. seq_printf(s, "err_info = 0x%x\n", tre->err_info);
  37. seq_printf(s, "err_code = 0x%x\n", tre->err_code);
  38. seq_printf(s, "status = 0x%x\n", tre->status);
  39. seq_printf(s, "idx = 0x%x\n", tre->idx);
  40. seq_printf(s, "dma_sig = 0x%x\n", tre->dma_sig);
  41. seq_printf(s, "dev_name=%s\n", tre->dev_name);
  42. seq_printf(s, "callback=%p\n", tre->callback);
  43. seq_printf(s, "data=%p\n", tre->data);
  44. seq_printf(s, "tre_index = 0x%x\n", tre->tre_index);
  45. tre_local = &tre->tre_local[0];
  46. src_start = tre_local[HIDMA_TRE_SRC_LOW_IDX];
  47. src_start = ((u64) (tre_local[HIDMA_TRE_SRC_HI_IDX]) << 32) + src_start;
  48. dest_start = tre_local[HIDMA_TRE_DEST_LOW_IDX];
  49. dest_start += ((u64) (tre_local[HIDMA_TRE_DEST_HI_IDX]) << 32);
  50. length = tre_local[HIDMA_TRE_LEN_IDX];
  51. seq_printf(s, "src=%pap\n", &src_start);
  52. seq_printf(s, "dest=%pap\n", &dest_start);
  53. seq_printf(s, "length = 0x%x\n", length);
  54. }
  55. static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
  56. {
  57. struct hidma_lldev *lldev = llhndl;
  58. seq_puts(s, "------Device -----\n");
  59. seq_printf(s, "lldev init = 0x%x\n", lldev->initialized);
  60. seq_printf(s, "trch_state = 0x%x\n", lldev->trch_state);
  61. seq_printf(s, "evch_state = 0x%x\n", lldev->evch_state);
  62. seq_printf(s, "chidx = 0x%x\n", lldev->chidx);
  63. seq_printf(s, "nr_tres = 0x%x\n", lldev->nr_tres);
  64. seq_printf(s, "trca=%p\n", lldev->trca);
  65. seq_printf(s, "tre_ring=%p\n", lldev->tre_ring);
  66. seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
  67. seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
  68. seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
  69. seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
  70. seq_printf(s, "evca=%p\n", lldev->evca);
  71. seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
  72. seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
  73. seq_printf(s, "evre_ring_size = 0x%x\n", lldev->evre_ring_size);
  74. seq_printf(s, "evre_processed_off = 0x%x\n", lldev->evre_processed_off);
  75. seq_printf(s, "tre_write_offset = 0x%x\n", lldev->tre_write_offset);
  76. }
  77. /*
  78. * hidma_chan_stats: display HIDMA channel statistics
  79. *
  80. * Display the statistics for the current HIDMA virtual channel device.
  81. */
  82. static int hidma_chan_stats(struct seq_file *s, void *unused)
  83. {
  84. struct hidma_chan *mchan = s->private;
  85. struct hidma_desc *mdesc;
  86. struct hidma_dev *dmadev = mchan->dmadev;
  87. pm_runtime_get_sync(dmadev->ddev.dev);
  88. seq_printf(s, "paused=%u\n", mchan->paused);
  89. seq_printf(s, "dma_sig=%u\n", mchan->dma_sig);
  90. seq_puts(s, "prepared\n");
  91. list_for_each_entry(mdesc, &mchan->prepared, node)
  92. hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
  93. seq_puts(s, "active\n");
  94. list_for_each_entry(mdesc, &mchan->active, node)
  95. hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
  96. seq_puts(s, "completed\n");
  97. list_for_each_entry(mdesc, &mchan->completed, node)
  98. hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
  99. hidma_ll_devstats(s, mchan->dmadev->lldev);
  100. pm_runtime_mark_last_busy(dmadev->ddev.dev);
  101. pm_runtime_put_autosuspend(dmadev->ddev.dev);
  102. return 0;
  103. }
  104. /*
  105. * hidma_dma_info: display HIDMA device info
  106. *
  107. * Display the info for the current HIDMA device.
  108. */
  109. static int hidma_dma_info(struct seq_file *s, void *unused)
  110. {
  111. struct hidma_dev *dmadev = s->private;
  112. resource_size_t sz;
  113. seq_printf(s, "nr_descriptors=%d\n", dmadev->nr_descriptors);
  114. seq_printf(s, "dev_trca=%p\n", &dmadev->dev_trca);
  115. seq_printf(s, "dev_trca_phys=%pa\n", &dmadev->trca_resource->start);
  116. sz = resource_size(dmadev->trca_resource);
  117. seq_printf(s, "dev_trca_size=%pa\n", &sz);
  118. seq_printf(s, "dev_evca=%p\n", &dmadev->dev_evca);
  119. seq_printf(s, "dev_evca_phys=%pa\n", &dmadev->evca_resource->start);
  120. sz = resource_size(dmadev->evca_resource);
  121. seq_printf(s, "dev_evca_size=%pa\n", &sz);
  122. return 0;
  123. }
  124. static int hidma_chan_stats_open(struct inode *inode, struct file *file)
  125. {
  126. return single_open(file, hidma_chan_stats, inode->i_private);
  127. }
  128. static int hidma_dma_info_open(struct inode *inode, struct file *file)
  129. {
  130. return single_open(file, hidma_dma_info, inode->i_private);
  131. }
  132. static const struct file_operations hidma_chan_fops = {
  133. .open = hidma_chan_stats_open,
  134. .read = seq_read,
  135. .llseek = seq_lseek,
  136. .release = single_release,
  137. };
  138. static const struct file_operations hidma_dma_fops = {
  139. .open = hidma_dma_info_open,
  140. .read = seq_read,
  141. .llseek = seq_lseek,
  142. .release = single_release,
  143. };
  144. void hidma_debug_uninit(struct hidma_dev *dmadev)
  145. {
  146. debugfs_remove_recursive(dmadev->debugfs);
  147. debugfs_remove_recursive(dmadev->stats);
  148. }
  149. int hidma_debug_init(struct hidma_dev *dmadev)
  150. {
  151. int rc = 0;
  152. int chidx = 0;
  153. struct list_head *position = NULL;
  154. dmadev->debugfs = debugfs_create_dir(dev_name(dmadev->ddev.dev), NULL);
  155. if (!dmadev->debugfs) {
  156. rc = -ENODEV;
  157. return rc;
  158. }
  159. /* walk through the virtual channel list */
  160. list_for_each(position, &dmadev->ddev.channels) {
  161. struct hidma_chan *chan;
  162. chan = list_entry(position, struct hidma_chan,
  163. chan.device_node);
  164. sprintf(chan->dbg_name, "chan%d", chidx);
  165. chan->debugfs = debugfs_create_dir(chan->dbg_name,
  166. dmadev->debugfs);
  167. if (!chan->debugfs) {
  168. rc = -ENOMEM;
  169. goto cleanup;
  170. }
  171. chan->stats = debugfs_create_file("stats", S_IRUGO,
  172. chan->debugfs, chan,
  173. &hidma_chan_fops);
  174. if (!chan->stats) {
  175. rc = -ENOMEM;
  176. goto cleanup;
  177. }
  178. chidx++;
  179. }
  180. dmadev->stats = debugfs_create_file("stats", S_IRUGO,
  181. dmadev->debugfs, dmadev,
  182. &hidma_dma_fops);
  183. if (!dmadev->stats) {
  184. rc = -ENOMEM;
  185. goto cleanup;
  186. }
  187. return 0;
  188. cleanup:
  189. hidma_debug_uninit(dmadev);
  190. return rc;
  191. }