/arch/arm/mach-fsm/qdsp5/evlog.h

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C++ Header · 125 lines · 94 code · 15 blank · 16 comment · 7 complexity · 2440b122e22e6237a72815a225fd8f1e MD5 · raw file

  1. /* arch/arm/mach-msm/qdsp5/evlog.h
  2. *
  3. * simple event log debugging facility
  4. *
  5. * Copyright (C) 2008 Google, Inc.
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/fs.h>
  18. #include <linux/hrtimer.h>
  19. #include <linux/debugfs.h>
  20. #define EV_LOG_ENTRY_NAME(n) n##_entry
  21. #define DECLARE_LOG(_name, _size, _str) \
  22. static struct ev_entry EV_LOG_ENTRY_NAME(_name)[_size]; \
  23. static struct ev_log _name = { \
  24. .name = #_name, \
  25. .strings = _str, \
  26. .num_strings = ARRAY_SIZE(_str), \
  27. .entry = EV_LOG_ENTRY_NAME(_name), \
  28. .max = ARRAY_SIZE(EV_LOG_ENTRY_NAME(_name)), \
  29. }
  30. struct ev_entry {
  31. ktime_t when;
  32. uint32_t id;
  33. uint32_t arg;
  34. };
  35. struct ev_log {
  36. struct ev_entry *entry;
  37. unsigned max;
  38. unsigned next;
  39. unsigned fault;
  40. const char **strings;
  41. unsigned num_strings;
  42. const char *name;
  43. };
  44. static char ev_buf[4096];
  45. static ssize_t ev_log_read(struct file *file, char __user *buf,
  46. size_t count, loff_t *ppos)
  47. {
  48. struct ev_log *log = file->private_data;
  49. struct ev_entry *entry;
  50. unsigned long flags;
  51. int size = 0;
  52. unsigned n, id, max;
  53. ktime_t now, t;
  54. max = log->max;
  55. now = ktime_get();
  56. local_irq_save(flags);
  57. n = (log->next - 1) & (max - 1);
  58. entry = log->entry;
  59. while (n != log->next) {
  60. t = ktime_sub(now, entry[n].when);
  61. id = entry[n].id;
  62. if (id) {
  63. const char *str;
  64. if (id < log->num_strings)
  65. str = log->strings[id];
  66. else
  67. str = "UNKNOWN";
  68. size += scnprintf(ev_buf + size, 4096 - size,
  69. "%8d.%03d %08x %s\n",
  70. t.tv.sec, t.tv.nsec / 1000000,
  71. entry[n].arg, str);
  72. }
  73. n = (n - 1) & (max - 1);
  74. }
  75. log->fault = 0;
  76. local_irq_restore(flags);
  77. return simple_read_from_buffer(buf, count, ppos, ev_buf, size);
  78. }
  79. static void ev_log_write(struct ev_log *log, unsigned id, unsigned arg)
  80. {
  81. struct ev_entry *entry;
  82. unsigned long flags;
  83. local_irq_save(flags);
  84. if (log->fault) {
  85. if (log->fault == 1)
  86. goto done;
  87. log->fault--;
  88. }
  89. entry = log->entry + log->next;
  90. entry->when = ktime_get();
  91. entry->id = id;
  92. entry->arg = arg;
  93. log->next = (log->next + 1) & (log->max - 1);
  94. done:
  95. local_irq_restore(flags);
  96. }
  97. static int ev_log_open(struct inode *inode, struct file *file)
  98. {
  99. file->private_data = inode->i_private;
  100. return 0;
  101. }
  102. static const struct file_operations ev_log_ops = {
  103. .read = ev_log_read,
  104. .open = ev_log_open,
  105. };
  106. static int ev_log_init(struct ev_log *log)
  107. {
  108. debugfs_create_file(log->name, 0444, 0, log, &ev_log_ops);
  109. return 0;
  110. }