mdss_debug_xlog.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* Copyright (c) 2014, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/delay.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/ktime.h>
  16. #include <linux/debugfs.h>
  17. #include "mdss.h"
  18. #include "mdss_mdp.h"
  19. #include "mdss_debug.h"
  20. #define MDSS_XLOG_ENTRY 256
  21. #define MDSS_XLOG_MAX_DATA 6
  22. #define MDSS_XLOG_BUF_MAX 512
  23. struct tlog {
  24. u32 tick;
  25. const char *name;
  26. u32 data[MDSS_XLOG_MAX_DATA];
  27. u32 data_cnt;
  28. };
  29. struct mdss_dbg_xlog {
  30. struct tlog logs[MDSS_XLOG_ENTRY];
  31. int first;
  32. int last;
  33. spinlock_t xlock;
  34. } mdss_dbg_xlog;
  35. static int mdss_xlog_dump_open(struct inode *inode, struct file *file)
  36. {
  37. /* non-seekable */
  38. file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
  39. file->private_data = inode->i_private;
  40. return 0;
  41. }
  42. static ssize_t mdss_xlog_dump_read(struct file *file, char __user *buff,
  43. size_t count, loff_t *ppos)
  44. {
  45. MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1", "edp", "hdmi", "panic");
  46. return 0;
  47. }
  48. static const struct file_operations mdss_xlog_fops = {
  49. .open = mdss_xlog_dump_open,
  50. .read = mdss_xlog_dump_read,
  51. };
  52. int mdss_create_xlog_debug(struct mdss_debug_data *mdd)
  53. {
  54. spin_lock_init(&mdss_dbg_xlog.xlock);
  55. mdd->logd.xlog = debugfs_create_dir("xlog", mdd->root);
  56. if (IS_ERR_OR_NULL(mdd->logd.xlog)) {
  57. pr_err("debugfs_create_dir fail, error %ld\n",
  58. PTR_ERR(mdd->logd.xlog));
  59. mdd->logd.xlog = NULL;
  60. return -ENODEV;
  61. }
  62. debugfs_create_file("dump", 0644, mdd->logd.xlog, NULL,
  63. &mdss_xlog_fops);
  64. debugfs_create_bool("enable", 0644, mdd->logd.xlog,
  65. &mdd->logd.xlog_enable);
  66. debugfs_create_bool("panic", 0644, mdd->logd.xlog,
  67. &mdd->logd.panic_on_err);
  68. debugfs_create_bool("reg_dump", 0644, mdd->logd.xlog,
  69. &mdd->logd.enable_reg_dump);
  70. return 0;
  71. }
  72. void mdss_xlog(const char *name, ...)
  73. {
  74. struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  75. struct mdss_debug_data *mdd = mdata->debug_inf.debug_data;
  76. unsigned long flags;
  77. int i, val = 0;
  78. va_list args;
  79. struct tlog *log;
  80. ktime_t time;
  81. if (!mdd->logd.xlog_enable)
  82. return;
  83. spin_lock_irqsave(&mdss_dbg_xlog.xlock, flags);
  84. time = ktime_get();
  85. log = &mdss_dbg_xlog.logs[mdss_dbg_xlog.first];
  86. log->tick = ktime_to_us(time);
  87. log->name = name;
  88. log->data_cnt = 0;
  89. va_start(args, name);
  90. for (i = 0; i < MDSS_XLOG_MAX_DATA; i++) {
  91. val = va_arg(args, int);
  92. if (val == DATA_LIMITER)
  93. break;
  94. log->data[i] = val;
  95. }
  96. va_end(args);
  97. log->data_cnt = i;
  98. mdss_dbg_xlog.last = mdss_dbg_xlog.first;
  99. mdss_dbg_xlog.first++;
  100. mdss_dbg_xlog.first %= MDSS_XLOG_ENTRY;
  101. spin_unlock_irqrestore(&mdss_dbg_xlog.xlock, flags);
  102. }
  103. void mdss_xlog_dump(void)
  104. {
  105. struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  106. struct mdss_debug_data *mdd = mdata->debug_inf.debug_data;
  107. int i, n, d_cnt, off;
  108. unsigned long flags;
  109. struct tlog *log;
  110. char xlog_buf[MDSS_XLOG_BUF_MAX];
  111. if (!mdd->logd.xlog_enable)
  112. return;
  113. spin_lock_irqsave(&mdss_dbg_xlog.xlock, flags);
  114. i = mdss_dbg_xlog.first;
  115. for (n = 0; n < MDSS_XLOG_ENTRY; n++) {
  116. log = &mdss_dbg_xlog.logs[i];
  117. off = snprintf(xlog_buf, MDSS_XLOG_BUF_MAX, "%-32s => %08d: ",
  118. log->name, log->tick);
  119. for (d_cnt = 0; d_cnt < log->data_cnt;) {
  120. off += snprintf((xlog_buf + off),
  121. (MDSS_XLOG_BUF_MAX - off),
  122. "%x ", log->data[d_cnt]);
  123. d_cnt++;
  124. }
  125. pr_err("%s\n", xlog_buf);
  126. i = (i + 1) % MDSS_XLOG_ENTRY;
  127. }
  128. spin_unlock_irqrestore(&mdss_dbg_xlog.xlock, flags);
  129. }
  130. void mdss_xlog_tout_handler(const char *name, ...)
  131. {
  132. struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  133. struct mdss_debug_data *mdd = mdata->debug_inf.debug_data;
  134. struct mdss_debug_base *blk_base, *tmp;
  135. int i, dead = 0;
  136. va_list args;
  137. char *blk_name = NULL;
  138. if (!mdd->logd.xlog_enable)
  139. return;
  140. va_start(args, name);
  141. for (i = 0; i < MDSS_XLOG_MAX_DATA; i++) {
  142. blk_name = va_arg(args, char*);
  143. if (IS_ERR_OR_NULL(blk_name))
  144. break;
  145. list_for_each_entry_safe(blk_base, tmp, &mdd->base_list, head) {
  146. if (blk_base->name &&
  147. !strcmp(blk_base->name, blk_name) &&
  148. mdd->logd.enable_reg_dump) {
  149. pr_info("\n%s : =========%s DUMP=========\n",
  150. __func__, blk_base->name);
  151. mdss_dump_reg(blk_base->base,
  152. blk_base->max_offset);
  153. }
  154. }
  155. if (!strcmp(blk_name, "panic"))
  156. dead = 1;
  157. }
  158. va_end(args);
  159. MDSS_XLOG(0xffff, 0xffff, 0xffff, 0xffff, 0xffff);
  160. mdss_xlog_dump();
  161. if (dead && mdd->logd.panic_on_err)
  162. panic(name);
  163. }