mic_debugfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2013 Intel Corporation.
  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, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * The full GNU General Public License is included in this distribution in
  16. * the file called "COPYING".
  17. *
  18. * Intel MIC Host driver.
  19. *
  20. */
  21. #include <linux/debugfs.h>
  22. #include <linux/pci.h>
  23. #include <linux/seq_file.h>
  24. #include <linux/mic_common.h>
  25. #include "../common/mic_dev.h"
  26. #include "mic_device.h"
  27. #include "mic_smpt.h"
  28. #include "mic_virtio.h"
  29. /* Debugfs parent dir */
  30. static struct dentry *mic_dbg;
  31. /**
  32. * mic_log_buf_show - Display MIC kernel log buffer.
  33. *
  34. * log_buf addr/len is read from System.map by user space
  35. * and populated in sysfs entries.
  36. */
  37. static int mic_log_buf_show(struct seq_file *s, void *unused)
  38. {
  39. void __iomem *log_buf_va;
  40. int __iomem *log_buf_len_va;
  41. struct mic_device *mdev = s->private;
  42. void *kva;
  43. int size;
  44. unsigned long aper_offset;
  45. if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
  46. goto done;
  47. /*
  48. * Card kernel will never be relocated and any kernel text/data mapping
  49. * can be translated to phys address by subtracting __START_KERNEL_map.
  50. */
  51. aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
  52. log_buf_len_va = mdev->aper.va + aper_offset;
  53. aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
  54. log_buf_va = mdev->aper.va + aper_offset;
  55. size = ioread32(log_buf_len_va);
  56. kva = kmalloc(size, GFP_KERNEL);
  57. if (!kva)
  58. goto done;
  59. mutex_lock(&mdev->mic_mutex);
  60. memcpy_fromio(kva, log_buf_va, size);
  61. switch (mdev->state) {
  62. case MIC_ONLINE:
  63. /* Fall through */
  64. case MIC_SHUTTING_DOWN:
  65. seq_write(s, kva, size);
  66. break;
  67. default:
  68. break;
  69. }
  70. mutex_unlock(&mdev->mic_mutex);
  71. kfree(kva);
  72. done:
  73. return 0;
  74. }
  75. static int mic_log_buf_open(struct inode *inode, struct file *file)
  76. {
  77. return single_open(file, mic_log_buf_show, inode->i_private);
  78. }
  79. static int mic_log_buf_release(struct inode *inode, struct file *file)
  80. {
  81. return single_release(inode, file);
  82. }
  83. static const struct file_operations log_buf_ops = {
  84. .owner = THIS_MODULE,
  85. .open = mic_log_buf_open,
  86. .read = seq_read,
  87. .llseek = seq_lseek,
  88. .release = mic_log_buf_release
  89. };
  90. static int mic_smpt_show(struct seq_file *s, void *pos)
  91. {
  92. int i;
  93. struct mic_device *mdev = s->private;
  94. unsigned long flags;
  95. seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
  96. mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
  97. seq_puts(s, "====================================================\n");
  98. if (mdev->smpt) {
  99. struct mic_smpt_info *smpt_info = mdev->smpt;
  100. spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  101. for (i = 0; i < smpt_info->info.num_reg; i++) {
  102. seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
  103. " ", i, smpt_info->entry[i].dma_addr,
  104. smpt_info->entry[i].ref_count);
  105. }
  106. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  107. }
  108. seq_puts(s, "====================================================\n");
  109. return 0;
  110. }
  111. static int mic_smpt_debug_open(struct inode *inode, struct file *file)
  112. {
  113. return single_open(file, mic_smpt_show, inode->i_private);
  114. }
  115. static int mic_smpt_debug_release(struct inode *inode, struct file *file)
  116. {
  117. return single_release(inode, file);
  118. }
  119. static const struct file_operations smpt_file_ops = {
  120. .owner = THIS_MODULE,
  121. .open = mic_smpt_debug_open,
  122. .read = seq_read,
  123. .llseek = seq_lseek,
  124. .release = mic_smpt_debug_release
  125. };
  126. static int mic_soft_reset_show(struct seq_file *s, void *pos)
  127. {
  128. struct mic_device *mdev = s->private;
  129. mic_stop(mdev, true);
  130. return 0;
  131. }
  132. static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
  133. {
  134. return single_open(file, mic_soft_reset_show, inode->i_private);
  135. }
  136. static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
  137. {
  138. return single_release(inode, file);
  139. }
  140. static const struct file_operations soft_reset_ops = {
  141. .owner = THIS_MODULE,
  142. .open = mic_soft_reset_debug_open,
  143. .read = seq_read,
  144. .llseek = seq_lseek,
  145. .release = mic_soft_reset_debug_release
  146. };
  147. static int mic_post_code_show(struct seq_file *s, void *pos)
  148. {
  149. struct mic_device *mdev = s->private;
  150. u32 reg = mdev->ops->get_postcode(mdev);
  151. seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
  152. return 0;
  153. }
  154. static int mic_post_code_debug_open(struct inode *inode, struct file *file)
  155. {
  156. return single_open(file, mic_post_code_show, inode->i_private);
  157. }
  158. static int mic_post_code_debug_release(struct inode *inode, struct file *file)
  159. {
  160. return single_release(inode, file);
  161. }
  162. static const struct file_operations post_code_ops = {
  163. .owner = THIS_MODULE,
  164. .open = mic_post_code_debug_open,
  165. .read = seq_read,
  166. .llseek = seq_lseek,
  167. .release = mic_post_code_debug_release
  168. };
  169. static int mic_dp_show(struct seq_file *s, void *pos)
  170. {
  171. struct mic_device *mdev = s->private;
  172. struct mic_device_desc *d;
  173. struct mic_device_ctrl *dc;
  174. struct mic_vqconfig *vqconfig;
  175. __u32 *features;
  176. __u8 *config;
  177. struct mic_bootparam *bootparam = mdev->dp;
  178. int i, j;
  179. seq_printf(s, "Bootparam: magic 0x%x\n",
  180. bootparam->magic);
  181. seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
  182. bootparam->h2c_shutdown_db);
  183. seq_printf(s, "Bootparam: h2c_config_db %d\n",
  184. bootparam->h2c_config_db);
  185. seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
  186. bootparam->c2h_shutdown_db);
  187. seq_printf(s, "Bootparam: shutdown_status %d\n",
  188. bootparam->shutdown_status);
  189. seq_printf(s, "Bootparam: shutdown_card %d\n",
  190. bootparam->shutdown_card);
  191. seq_printf(s, "Bootparam: tot_nodes %d\n",
  192. bootparam->tot_nodes);
  193. seq_printf(s, "Bootparam: node_id %d\n",
  194. bootparam->node_id);
  195. seq_printf(s, "Bootparam: c2h_scif_db %d\n",
  196. bootparam->c2h_scif_db);
  197. seq_printf(s, "Bootparam: h2c_scif_db %d\n",
  198. bootparam->h2c_scif_db);
  199. seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
  200. bootparam->scif_host_dma_addr);
  201. seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
  202. bootparam->scif_card_dma_addr);
  203. for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
  204. i += mic_total_desc_size(d)) {
  205. d = mdev->dp + i;
  206. dc = (void *)d + mic_aligned_desc_size(d);
  207. /* end of list */
  208. if (d->type == 0)
  209. break;
  210. if (d->type == -1)
  211. continue;
  212. seq_printf(s, "Type %d ", d->type);
  213. seq_printf(s, "Num VQ %d ", d->num_vq);
  214. seq_printf(s, "Feature Len %d\n", d->feature_len);
  215. seq_printf(s, "Config Len %d ", d->config_len);
  216. seq_printf(s, "Shutdown Status %d\n", d->status);
  217. for (j = 0; j < d->num_vq; j++) {
  218. vqconfig = mic_vq_config(d) + j;
  219. seq_printf(s, "vqconfig[%d]: ", j);
  220. seq_printf(s, "address 0x%llx ", vqconfig->address);
  221. seq_printf(s, "num %d ", vqconfig->num);
  222. seq_printf(s, "used address 0x%llx\n",
  223. vqconfig->used_address);
  224. }
  225. features = (__u32 *)mic_vq_features(d);
  226. seq_printf(s, "Features: Host 0x%x ", features[0]);
  227. seq_printf(s, "Guest 0x%x\n", features[1]);
  228. config = mic_vq_configspace(d);
  229. for (j = 0; j < d->config_len; j++)
  230. seq_printf(s, "config[%d]=%d\n", j, config[j]);
  231. seq_puts(s, "Device control:\n");
  232. seq_printf(s, "Config Change %d ", dc->config_change);
  233. seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
  234. seq_printf(s, "Guest Ack %d ", dc->guest_ack);
  235. seq_printf(s, "Host ack %d\n", dc->host_ack);
  236. seq_printf(s, "Used address updated %d ",
  237. dc->used_address_updated);
  238. seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
  239. seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
  240. seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
  241. }
  242. return 0;
  243. }
  244. static int mic_dp_debug_open(struct inode *inode, struct file *file)
  245. {
  246. return single_open(file, mic_dp_show, inode->i_private);
  247. }
  248. static int mic_dp_debug_release(struct inode *inode, struct file *file)
  249. {
  250. return single_release(inode, file);
  251. }
  252. static const struct file_operations dp_ops = {
  253. .owner = THIS_MODULE,
  254. .open = mic_dp_debug_open,
  255. .read = seq_read,
  256. .llseek = seq_lseek,
  257. .release = mic_dp_debug_release
  258. };
  259. static int mic_vdev_info_show(struct seq_file *s, void *unused)
  260. {
  261. struct mic_device *mdev = s->private;
  262. struct list_head *pos, *tmp;
  263. struct mic_vdev *mvdev;
  264. int i, j;
  265. mutex_lock(&mdev->mic_mutex);
  266. list_for_each_safe(pos, tmp, &mdev->vdev_list) {
  267. mvdev = list_entry(pos, struct mic_vdev, list);
  268. seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
  269. mvdev->virtio_id,
  270. mic_vdevup(mvdev) ? "UP" : "DOWN",
  271. mvdev->in_bytes,
  272. mvdev->out_bytes);
  273. for (i = 0; i < MIC_MAX_VRINGS; i++) {
  274. struct vring_desc *desc;
  275. struct vring_avail *avail;
  276. struct vring_used *used;
  277. struct mic_vringh *mvr = &mvdev->mvr[i];
  278. struct vringh *vrh = &mvr->vrh;
  279. int num = vrh->vring.num;
  280. if (!num)
  281. continue;
  282. desc = vrh->vring.desc;
  283. seq_printf(s, "vring i %d avail_idx %d",
  284. i, mvr->vring.info->avail_idx & (num - 1));
  285. seq_printf(s, " vring i %d avail_idx %d\n",
  286. i, mvr->vring.info->avail_idx);
  287. seq_printf(s, "vrh i %d weak_barriers %d",
  288. i, vrh->weak_barriers);
  289. seq_printf(s, " last_avail_idx %d last_used_idx %d",
  290. vrh->last_avail_idx, vrh->last_used_idx);
  291. seq_printf(s, " completed %d\n", vrh->completed);
  292. for (j = 0; j < num; j++) {
  293. seq_printf(s, "desc[%d] addr 0x%llx len %d",
  294. j, desc->addr, desc->len);
  295. seq_printf(s, " flags 0x%x next %d\n",
  296. desc->flags, desc->next);
  297. desc++;
  298. }
  299. avail = vrh->vring.avail;
  300. seq_printf(s, "avail flags 0x%x idx %d\n",
  301. vringh16_to_cpu(vrh, avail->flags),
  302. vringh16_to_cpu(vrh, avail->idx) & (num - 1));
  303. seq_printf(s, "avail flags 0x%x idx %d\n",
  304. vringh16_to_cpu(vrh, avail->flags),
  305. vringh16_to_cpu(vrh, avail->idx));
  306. for (j = 0; j < num; j++)
  307. seq_printf(s, "avail ring[%d] %d\n",
  308. j, avail->ring[j]);
  309. used = vrh->vring.used;
  310. seq_printf(s, "used flags 0x%x idx %d\n",
  311. vringh16_to_cpu(vrh, used->flags),
  312. vringh16_to_cpu(vrh, used->idx) & (num - 1));
  313. seq_printf(s, "used flags 0x%x idx %d\n",
  314. vringh16_to_cpu(vrh, used->flags),
  315. vringh16_to_cpu(vrh, used->idx));
  316. for (j = 0; j < num; j++)
  317. seq_printf(s, "used ring[%d] id %d len %d\n",
  318. j, vringh32_to_cpu(vrh,
  319. used->ring[j].id),
  320. vringh32_to_cpu(vrh,
  321. used->ring[j].len));
  322. }
  323. }
  324. mutex_unlock(&mdev->mic_mutex);
  325. return 0;
  326. }
  327. static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
  328. {
  329. return single_open(file, mic_vdev_info_show, inode->i_private);
  330. }
  331. static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
  332. {
  333. return single_release(inode, file);
  334. }
  335. static const struct file_operations vdev_info_ops = {
  336. .owner = THIS_MODULE,
  337. .open = mic_vdev_info_debug_open,
  338. .read = seq_read,
  339. .llseek = seq_lseek,
  340. .release = mic_vdev_info_debug_release
  341. };
  342. static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
  343. {
  344. struct mic_device *mdev = s->private;
  345. int reg;
  346. int i, j;
  347. u16 entry;
  348. u16 vector;
  349. struct pci_dev *pdev = container_of(mdev->sdev->parent,
  350. struct pci_dev, dev);
  351. if (pci_dev_msi_enabled(pdev)) {
  352. for (i = 0; i < mdev->irq_info.num_vectors; i++) {
  353. if (pdev->msix_enabled) {
  354. entry = mdev->irq_info.msix_entries[i].entry;
  355. vector = mdev->irq_info.msix_entries[i].vector;
  356. } else {
  357. entry = 0;
  358. vector = pdev->irq;
  359. }
  360. reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
  361. seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
  362. "IRQ:", vector, "Entry:", entry, i, reg);
  363. seq_printf(s, "%-10s", "offset:");
  364. for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
  365. seq_printf(s, "%4d ", j);
  366. seq_puts(s, "\n");
  367. seq_printf(s, "%-10s", "count:");
  368. for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
  369. seq_printf(s, "%4d ",
  370. (mdev->irq_info.mic_msi_map[i] &
  371. BIT(j)) ? 1 : 0);
  372. seq_puts(s, "\n\n");
  373. }
  374. } else {
  375. seq_puts(s, "MSI/MSIx interrupts not enabled\n");
  376. }
  377. return 0;
  378. }
  379. static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file)
  380. {
  381. return single_open(file, mic_msi_irq_info_show, inode->i_private);
  382. }
  383. static int
  384. mic_msi_irq_info_debug_release(struct inode *inode, struct file *file)
  385. {
  386. return single_release(inode, file);
  387. }
  388. static const struct file_operations msi_irq_info_ops = {
  389. .owner = THIS_MODULE,
  390. .open = mic_msi_irq_info_debug_open,
  391. .read = seq_read,
  392. .llseek = seq_lseek,
  393. .release = mic_msi_irq_info_debug_release
  394. };
  395. /**
  396. * mic_create_debug_dir - Initialize MIC debugfs entries.
  397. */
  398. void mic_create_debug_dir(struct mic_device *mdev)
  399. {
  400. if (!mic_dbg)
  401. return;
  402. mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
  403. if (!mdev->dbg_dir)
  404. return;
  405. debugfs_create_file("log_buf", 0444, mdev->dbg_dir, mdev, &log_buf_ops);
  406. debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
  407. debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, mdev,
  408. &soft_reset_ops);
  409. debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
  410. &post_code_ops);
  411. debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops);
  412. debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev,
  413. &vdev_info_ops);
  414. debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
  415. &msi_irq_info_ops);
  416. }
  417. /**
  418. * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
  419. */
  420. void mic_delete_debug_dir(struct mic_device *mdev)
  421. {
  422. if (!mdev->dbg_dir)
  423. return;
  424. debugfs_remove_recursive(mdev->dbg_dir);
  425. }
  426. /**
  427. * mic_init_debugfs - Initialize global debugfs entry.
  428. */
  429. void __init mic_init_debugfs(void)
  430. {
  431. mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
  432. if (!mic_dbg)
  433. pr_err("can't create debugfs dir\n");
  434. }
  435. /**
  436. * mic_exit_debugfs - Uninitialize global debugfs entry
  437. */
  438. void mic_exit_debugfs(void)
  439. {
  440. debugfs_remove(mic_dbg);
  441. }