qaic_debugfs.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
  3. /* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
  4. #include <linux/debugfs.h>
  5. #include <linux/device.h>
  6. #include <linux/fs.h>
  7. #include <linux/list.h>
  8. #include <linux/mhi.h>
  9. #include <linux/mutex.h>
  10. #include <linux/overflow.h>
  11. #include <linux/pci.h>
  12. #include <linux/seq_file.h>
  13. #include <linux/sprintf.h>
  14. #include <linux/string.h>
  15. #include <linux/types.h>
  16. #include <linux/workqueue.h>
  17. #include "qaic.h"
  18. #include "qaic_debugfs.h"
  19. #define BOOTLOG_POOL_SIZE 16
  20. #define BOOTLOG_MSG_SIZE 512
  21. #define QAIC_DBC_DIR_NAME 9
  22. struct bootlog_msg {
  23. /* Buffer for bootlog messages */
  24. char str[BOOTLOG_MSG_SIZE];
  25. /* Root struct of device, used to access device resources */
  26. struct qaic_device *qdev;
  27. /* Work struct to schedule work coming on QAIC_LOGGING channel */
  28. struct work_struct work;
  29. };
  30. struct bootlog_page {
  31. /* Node in list of bootlog pages maintained by root device struct */
  32. struct list_head node;
  33. /* Total size of the buffer that holds the bootlogs. It is PAGE_SIZE */
  34. unsigned int size;
  35. /* Offset for the next bootlog */
  36. unsigned int offset;
  37. };
  38. static int bootlog_show(struct seq_file *s, void *unused)
  39. {
  40. struct bootlog_page *page;
  41. struct qaic_device *qdev;
  42. void *page_end;
  43. void *log;
  44. qdev = s->private;
  45. mutex_lock(&qdev->bootlog_mutex);
  46. list_for_each_entry(page, &qdev->bootlog, node) {
  47. log = page + 1;
  48. page_end = (void *)page + page->offset;
  49. while (log < page_end) {
  50. seq_printf(s, "%s", (char *)log);
  51. log += strlen(log) + 1;
  52. }
  53. }
  54. mutex_unlock(&qdev->bootlog_mutex);
  55. return 0;
  56. }
  57. static int bootlog_fops_open(struct inode *inode, struct file *file)
  58. {
  59. return single_open(file, bootlog_show, inode->i_private);
  60. }
  61. static const struct file_operations bootlog_fops = {
  62. .owner = THIS_MODULE,
  63. .open = bootlog_fops_open,
  64. .read = seq_read,
  65. .llseek = seq_lseek,
  66. .release = single_release,
  67. };
  68. static int read_dbc_fifo_size(struct seq_file *s, void *unused)
  69. {
  70. struct dma_bridge_chan *dbc = s->private;
  71. seq_printf(s, "%u\n", dbc->nelem);
  72. return 0;
  73. }
  74. static int fifo_size_open(struct inode *inode, struct file *file)
  75. {
  76. return single_open(file, read_dbc_fifo_size, inode->i_private);
  77. }
  78. static const struct file_operations fifo_size_fops = {
  79. .owner = THIS_MODULE,
  80. .open = fifo_size_open,
  81. .read = seq_read,
  82. .llseek = seq_lseek,
  83. .release = single_release,
  84. };
  85. static int read_dbc_queued(struct seq_file *s, void *unused)
  86. {
  87. struct dma_bridge_chan *dbc = s->private;
  88. u32 tail = 0, head = 0;
  89. qaic_data_get_fifo_info(dbc, &head, &tail);
  90. if (head == U32_MAX || tail == U32_MAX)
  91. seq_printf(s, "%u\n", 0);
  92. else if (head > tail)
  93. seq_printf(s, "%u\n", dbc->nelem - head + tail);
  94. else
  95. seq_printf(s, "%u\n", tail - head);
  96. return 0;
  97. }
  98. static int queued_open(struct inode *inode, struct file *file)
  99. {
  100. return single_open(file, read_dbc_queued, inode->i_private);
  101. }
  102. static const struct file_operations queued_fops = {
  103. .owner = THIS_MODULE,
  104. .open = queued_open,
  105. .read = seq_read,
  106. .llseek = seq_lseek,
  107. .release = single_release,
  108. };
  109. void qaic_debugfs_init(struct qaic_drm_device *qddev)
  110. {
  111. struct qaic_device *qdev = qddev->qdev;
  112. struct dentry *debugfs_root;
  113. struct dentry *debugfs_dir;
  114. char name[QAIC_DBC_DIR_NAME];
  115. u32 i;
  116. debugfs_root = to_drm(qddev)->debugfs_root;
  117. debugfs_create_file("bootlog", 0400, debugfs_root, qdev, &bootlog_fops);
  118. /*
  119. * 256 dbcs per device is likely the max we will ever see and lets static checking see a
  120. * reasonable range.
  121. */
  122. for (i = 0; i < qdev->num_dbc && i < 256; ++i) {
  123. snprintf(name, QAIC_DBC_DIR_NAME, "dbc%03u", i);
  124. debugfs_dir = debugfs_create_dir(name, debugfs_root);
  125. debugfs_create_file("fifo_size", 0400, debugfs_dir, &qdev->dbc[i], &fifo_size_fops);
  126. debugfs_create_file("queued", 0400, debugfs_dir, &qdev->dbc[i], &queued_fops);
  127. }
  128. }
  129. static struct bootlog_page *alloc_bootlog_page(struct qaic_device *qdev)
  130. {
  131. struct bootlog_page *page;
  132. page = (struct bootlog_page *)devm_get_free_pages(&qdev->pdev->dev, GFP_KERNEL, 0);
  133. if (!page)
  134. return page;
  135. page->size = PAGE_SIZE;
  136. page->offset = sizeof(*page);
  137. list_add_tail(&page->node, &qdev->bootlog);
  138. return page;
  139. }
  140. static int reset_bootlog(struct qaic_device *qdev)
  141. {
  142. struct bootlog_page *page;
  143. struct bootlog_page *i;
  144. mutex_lock(&qdev->bootlog_mutex);
  145. list_for_each_entry_safe(page, i, &qdev->bootlog, node) {
  146. list_del(&page->node);
  147. devm_free_pages(&qdev->pdev->dev, (unsigned long)page);
  148. }
  149. page = alloc_bootlog_page(qdev);
  150. mutex_unlock(&qdev->bootlog_mutex);
  151. if (!page)
  152. return -ENOMEM;
  153. return 0;
  154. }
  155. static void *bootlog_get_space(struct qaic_device *qdev, unsigned int size)
  156. {
  157. struct bootlog_page *page;
  158. page = list_last_entry(&qdev->bootlog, struct bootlog_page, node);
  159. if (size_add(size, sizeof(*page)) > page->size)
  160. return NULL;
  161. if (page->offset + size > page->size) {
  162. page = alloc_bootlog_page(qdev);
  163. if (!page)
  164. return NULL;
  165. }
  166. return (void *)page + page->offset;
  167. }
  168. static void bootlog_commit(struct qaic_device *qdev, unsigned int size)
  169. {
  170. struct bootlog_page *page;
  171. page = list_last_entry(&qdev->bootlog, struct bootlog_page, node);
  172. page->offset += size;
  173. }
  174. static void bootlog_log(struct work_struct *work)
  175. {
  176. struct bootlog_msg *msg = container_of(work, struct bootlog_msg, work);
  177. unsigned int len = strlen(msg->str) + 1;
  178. struct qaic_device *qdev = msg->qdev;
  179. void *log;
  180. mutex_lock(&qdev->bootlog_mutex);
  181. log = bootlog_get_space(qdev, len);
  182. if (log) {
  183. memcpy(log, msg, len);
  184. bootlog_commit(qdev, len);
  185. }
  186. mutex_unlock(&qdev->bootlog_mutex);
  187. if (mhi_queue_buf(qdev->bootlog_ch, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT))
  188. devm_kfree(&qdev->pdev->dev, msg);
  189. }
  190. static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
  191. {
  192. struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev));
  193. struct bootlog_msg *msg;
  194. int i, ret;
  195. qdev->bootlog_wq = alloc_ordered_workqueue("qaic_bootlog", 0);
  196. if (!qdev->bootlog_wq) {
  197. ret = -ENOMEM;
  198. goto out;
  199. }
  200. ret = reset_bootlog(qdev);
  201. if (ret)
  202. goto destroy_workqueue;
  203. ret = mhi_prepare_for_transfer(mhi_dev);
  204. if (ret)
  205. goto destroy_workqueue;
  206. for (i = 0; i < BOOTLOG_POOL_SIZE; i++) {
  207. msg = devm_kzalloc(&qdev->pdev->dev, sizeof(*msg), GFP_KERNEL);
  208. if (!msg) {
  209. ret = -ENOMEM;
  210. goto mhi_unprepare;
  211. }
  212. msg->qdev = qdev;
  213. INIT_WORK(&msg->work, bootlog_log);
  214. ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT);
  215. if (ret)
  216. goto mhi_unprepare;
  217. }
  218. dev_set_drvdata(&mhi_dev->dev, qdev);
  219. qdev->bootlog_ch = mhi_dev;
  220. return 0;
  221. mhi_unprepare:
  222. mhi_unprepare_from_transfer(mhi_dev);
  223. destroy_workqueue:
  224. flush_workqueue(qdev->bootlog_wq);
  225. destroy_workqueue(qdev->bootlog_wq);
  226. out:
  227. return ret;
  228. }
  229. static void qaic_bootlog_mhi_remove(struct mhi_device *mhi_dev)
  230. {
  231. struct qaic_device *qdev;
  232. qdev = dev_get_drvdata(&mhi_dev->dev);
  233. mhi_unprepare_from_transfer(qdev->bootlog_ch);
  234. flush_workqueue(qdev->bootlog_wq);
  235. destroy_workqueue(qdev->bootlog_wq);
  236. qdev->bootlog_ch = NULL;
  237. }
  238. static void qaic_bootlog_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
  239. {
  240. }
  241. static void qaic_bootlog_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
  242. {
  243. struct qaic_device *qdev = dev_get_drvdata(&mhi_dev->dev);
  244. struct bootlog_msg *msg = mhi_result->buf_addr;
  245. if (mhi_result->transaction_status) {
  246. devm_kfree(&qdev->pdev->dev, msg);
  247. return;
  248. }
  249. /* Force a null at the end of the transferred string */
  250. msg->str[mhi_result->bytes_xferd - 1] = 0;
  251. queue_work(qdev->bootlog_wq, &msg->work);
  252. }
  253. static const struct mhi_device_id qaic_bootlog_mhi_match_table[] = {
  254. { .chan = "QAIC_LOGGING", },
  255. {},
  256. };
  257. static struct mhi_driver qaic_bootlog_mhi_driver = {
  258. .id_table = qaic_bootlog_mhi_match_table,
  259. .remove = qaic_bootlog_mhi_remove,
  260. .probe = qaic_bootlog_mhi_probe,
  261. .ul_xfer_cb = qaic_bootlog_mhi_ul_xfer_cb,
  262. .dl_xfer_cb = qaic_bootlog_mhi_dl_xfer_cb,
  263. .driver = {
  264. .name = "qaic_bootlog",
  265. },
  266. };
  267. int qaic_bootlog_register(void)
  268. {
  269. return mhi_driver_register(&qaic_bootlog_mhi_driver);
  270. }
  271. void qaic_bootlog_unregister(void)
  272. {
  273. mhi_driver_unregister(&qaic_bootlog_mhi_driver);
  274. }