linux/drivers/staging/dream/qdsp5/evlog.h
<<
>>
Prefs
   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
  18#include <linux/fs.h>
  19#include <linux/hrtimer.h>
  20#include <linux/debugfs.h>
  21
  22#define EV_LOG_ENTRY_NAME(n) n##_entry
  23
  24#define DECLARE_LOG(_name, _size, _str) \
  25static struct ev_entry EV_LOG_ENTRY_NAME(_name)[_size]; \
  26static struct ev_log _name = { \
  27        .name = #_name, \
  28        .strings = _str, \
  29        .num_strings = ARRAY_SIZE(_str), \
  30        .entry = EV_LOG_ENTRY_NAME(_name), \
  31        .max = ARRAY_SIZE(EV_LOG_ENTRY_NAME(_name)), \
  32}
  33
  34struct ev_entry {
  35        ktime_t when;
  36        uint32_t id;
  37        uint32_t arg;
  38};
  39
  40struct ev_log {
  41        struct ev_entry *entry;
  42        unsigned max;
  43        unsigned next;
  44        unsigned fault;
  45        const char **strings;
  46        unsigned num_strings;
  47        const char *name;
  48};
  49
  50static char ev_buf[4096];
  51
  52static ssize_t ev_log_read(struct file *file, char __user *buf,
  53                           size_t count, loff_t *ppos)
  54{
  55        struct ev_log *log = file->private_data;
  56        struct ev_entry *entry;
  57        unsigned long flags;
  58        int size = 0;
  59        unsigned n, id, max;
  60        ktime_t now, t;
  61
  62        max = log->max;
  63        now = ktime_get();
  64        local_irq_save(flags);
  65        n = (log->next - 1) & (max - 1);
  66        entry = log->entry;
  67        while (n != log->next) {
  68                t = ktime_sub(now, entry[n].when);
  69                id = entry[n].id;
  70                if (id) {
  71                        const char *str;
  72                        if (id < log->num_strings)
  73                                str = log->strings[id];
  74                        else
  75                                str = "UNKNOWN";
  76                        size += scnprintf(ev_buf + size, 4096 - size,
  77                                          "%8d.%03d %08x %s\n",
  78                                          t.tv.sec, t.tv.nsec / 1000000,
  79                                          entry[n].arg, str);
  80                }
  81                n = (n - 1) & (max - 1);
  82        }
  83        log->fault = 0;
  84        local_irq_restore(flags);
  85        return simple_read_from_buffer(buf, count, ppos, ev_buf, size);
  86}
  87
  88static void ev_log_write(struct ev_log *log, unsigned id, unsigned arg)
  89{
  90        struct ev_entry *entry;
  91        unsigned long flags;
  92        local_irq_save(flags);
  93
  94        if (log->fault) {
  95                if (log->fault == 1)
  96                        goto done;
  97                log->fault--;
  98        }
  99
 100        entry = log->entry + log->next;
 101        entry->when = ktime_get();
 102        entry->id = id;
 103        entry->arg = arg;
 104        log->next = (log->next + 1) & (log->max - 1);
 105done:
 106        local_irq_restore(flags);
 107}
 108
 109static void ev_log_freeze(struct ev_log *log, unsigned count)
 110{
 111        unsigned long flags;
 112        local_irq_save(flags);
 113        log->fault = count;
 114        local_irq_restore(flags);
 115}
 116
 117static int ev_log_open(struct inode *inode, struct file *file)
 118{
 119        file->private_data = inode->i_private;
 120        return 0;
 121}
 122
 123static const struct file_operations ev_log_ops = {
 124        .read = ev_log_read,
 125        .open = ev_log_open,
 126};
 127
 128static int ev_log_init(struct ev_log *log)
 129{
 130        debugfs_create_file(log->name, 0444, 0, log, &ev_log_ops);
 131        return 0;
 132}
 133
 134