From cab17dccb6026f9f33717db72f528f3b84d7393f Mon Sep 17 00:00:00 2001
From: David Herrmann <dh.herrmann@googlemail.com>
Date: Sat, 16 Jun 2012 23:07:50 +0200
Subject: [PATCH 06/10] fblog: allow enabling/disabling fblog on runtime

A sysfs file called "active" can be used to enable and disable fblog on
runtime. For example, the init-process can run "echo '0' >.../active"
after booting the system. This will allow other applications like X11 to
use the graphics subsystem. During shutdown, we can write '1' to get
system messages again.

When disabling fblog, we remove all framebuffers and will prevent new
hotplugged framebuffers from being added. When enabling fblog again, we
rescan the system for all framebuffers and resume operating.

The sysfs file is not registered, yet, as we do not have a "struct device"
yet. This will follow shortly, though.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
 Documentation/ABI/testing/sysfs-fblog |    9 ++++++
 drivers/video/console/fblog.c         |   49 +++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-fblog

diff --git a/Documentation/ABI/testing/sysfs-fblog b/Documentation/ABI/testing/sysfs-fblog
new file mode 100644
index 0000000..596393c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fblog
@@ -0,0 +1,9 @@
+What:		/sys/class/graphics/fblog/active
+Date:		June 2012
+KernelVersion:	3.6
+Contact:	David Herrmann <dh.herrmann@googlemail.com>
+Description:	Enable/Disable fblog. When setting this to 0, fblog will stop
+		writing to framebuffers and other applications can use the
+		graphics subsystem. When setting this to 1, fblog will rescan
+		the system for all framebuffers and resume drawing the kernel
+		log onto all framebuffers.
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
index 7d4032e..9b05c56 100644
--- a/drivers/video/console/fblog.c
+++ b/drivers/video/console/fblog.c
@@ -92,6 +92,7 @@ struct fblog_fb {
 };
 
 static struct fblog_fb *fblog_fbs[FB_MAX];
+static atomic_t fblog_active;
 
 static void fblog_buf_resize(struct fblog_buf *buf, size_t width,
 			     size_t height)
@@ -338,6 +339,8 @@ static void fblog_register(struct fb_info *info)
 	const struct fb_videomode *mode;
 	unsigned int width, height;
 
+	if (!atomic_read(&fblog_active))
+		return;
 	if (!info || info->node < 0 || info->node >= FB_MAX)
 		return;
 	if (!registered_fb[info->node] || fblog_fbs[info->node])
@@ -428,6 +431,52 @@ static void fblog_refresh(struct fblog_fb *fb)
 	fblog_redraw(fb);
 }
 
+static void fblog_activate(void)
+{
+	if (atomic_read(&fblog_active))
+		return;
+
+	atomic_set(&fblog_active, 1);
+	fblog_register_all();
+}
+
+static void fblog_deactivate(void)
+{
+	if (!atomic_read(&fblog_active))
+		return;
+
+	atomic_set(&fblog_active, 0);
+	fblog_unregister_all();
+}
+
+static ssize_t fblog_dev_active_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&fblog_active));
+}
+
+static ssize_t fblog_dev_active_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf,
+				      size_t count)
+{
+	unsigned long num;
+
+	num = simple_strtoul(buf, NULL, 10);
+	console_lock();
+	if (num)
+		fblog_activate();
+	else
+		fblog_deactivate();
+	console_unlock();
+
+	return count;
+}
+
+static DEVICE_ATTR(active, S_IRUGO | S_IWUSR | S_IWGRP, fblog_dev_active_show,
+		   fblog_dev_active_store);
+
 static int __init fblog_init(void)
 {
 	return 0;
-- 
1.7.10.4

