aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/batman-adv/log.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2009-11-09 21:20:10 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 12:23:22 -0800
commit5beef3c9bf7f967a4a70ddb0108fd3e459fed133 (patch)
treeef6e8f8e9b7a7febef2e478139b38f92b93e4ef2 /drivers/staging/batman-adv/log.c
parentStaging: rtl8192u: depends on USB (diff)
downloadlinux-dev-5beef3c9bf7f967a4a70ddb0108fd3e459fed133.tar.xz
linux-dev-5beef3c9bf7f967a4a70ddb0108fd3e459fed133.zip
staging: batman-adv meshing protocol
B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is a routing protocol for multi-hop ad-hoc mesh networks. The networks may be wired or wireless. See http://www.open-mesh.org/ for more information and user space tools. This is the first submission for inclusion in staging. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv/log.c')
-rw-r--r--drivers/staging/batman-adv/log.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/drivers/staging/batman-adv/log.c b/drivers/staging/batman-adv/log.c
new file mode 100644
index 000000000000..f37c7f01a9f5
--- /dev/null
+++ b/drivers/staging/batman-adv/log.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "log.h"
+
+#define LOG_BUF_MASK (log_buf_len-1)
+#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
+
+static char log_buf[LOG_BUF_LEN];
+static int log_buf_len = LOG_BUF_LEN;
+static unsigned long log_start;
+static unsigned long log_end;
+uint8_t log_level;
+
+static DEFINE_SPINLOCK(logbuf_lock);
+
+const struct file_operations proc_log_operations = {
+ .open = log_open,
+ .release = log_release,
+ .read = log_read,
+ .write = log_write,
+ .poll = log_poll,
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(log_wait);
+
+static void emit_log_char(char c)
+{
+ LOG_BUF(log_end) = c;
+ log_end++;
+
+ if (log_end - log_start > log_buf_len)
+ log_start = log_end - log_buf_len;
+}
+
+static int fdebug_log(char *fmt, ...)
+{
+ int printed_len;
+ char *p;
+ va_list args;
+ static char debug_log_buf[256];
+ unsigned long flags;
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+ va_start(args, fmt);
+ printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt,
+ args);
+ va_end(args);
+
+ for (p = debug_log_buf; *p != 0; p++)
+ emit_log_char(*p);
+
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ wake_up(&log_wait);
+
+ return 0;
+}
+
+int debug_log(int type, char *fmt, ...)
+{
+ va_list args;
+ int retval = 0;
+ char tmp_log_buf[256];
+
+ /* only critical information get into the official kernel log */
+ if (type == LOG_TYPE_CRIT) {
+ va_start(args, fmt);
+ vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
+ printk(KERN_ERR "batman-adv: %s", tmp_log_buf);
+ va_end(args);
+ }
+
+ if ((type == LOG_TYPE_CRIT) || (log_level & type)) {
+ va_start(args, fmt);
+ vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
+ fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf);
+ va_end(args);
+ }
+
+ return retval;
+}
+
+int log_open(struct inode *inode, struct file *file)
+{
+ inc_module_count();
+ return 0;
+}
+
+int log_release(struct inode *inode, struct file *file)
+{
+ dec_module_count();
+ return 0;
+}
+
+ssize_t log_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ int error, i = 0;
+ char c;
+ unsigned long flags;
+
+ if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start))
+ return -EAGAIN;
+
+ if ((!buf) || (count < 0))
+ return -EINVAL;
+
+ if (count == 0)
+ return 0;
+
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+
+ error = wait_event_interruptible(log_wait, (log_start - log_end));
+
+ if (error)
+ return error;
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+
+ while ((!error) && (log_start != log_end) && (i < count)) {
+ c = LOG_BUF(log_start);
+
+ log_start++;
+
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ error = __put_user(c, buf);
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+
+ buf++;
+ i++;
+
+ }
+
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ if (!error)
+ return i;
+
+ return error;
+}
+
+ssize_t log_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ return count;
+}
+
+unsigned int log_poll(struct file *file, poll_table *wait)
+{
+ poll_wait(file, &log_wait, wait);
+
+ if (log_end - log_start)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}