rk: add console write by thread support
author黄涛 <huangtao@rock-chips.com>
Wed, 25 Jul 2012 06:08:28 +0000 (14:08 +0800)
committer黄涛 <huangtao@rock-chips.com>
Wed, 25 Jul 2012 06:08:50 +0000 (14:08 +0800)
arch/arm/common/fiq_debugger.c
arch/arm/include/asm/fiq_debugger.h
arch/arm/plat-rk/Kconfig
arch/arm/plat-rk/rk_fiq_debugger.c

index 9617d374df4b82bb0525570697e45667ae9a1e2b..114c98e4d0bab7cc2520264ccf3945aa9f5af1b5 100644 (file)
@@ -1086,6 +1086,13 @@ static void debug_console_write(struct console *co,
        if (!state->console_enable && !state->syslog_dumping)
                return;
 
+#ifdef CONFIG_RK_CONSOLE_THREAD
+       if (state->pdata->console_write) {
+               state->pdata->console_write(state->pdev, s, count);
+               return;
+       }
+#endif
+
        debug_uart_enable(state);
        while (count--) {
                if (*s == '\n')
index 4d274883ba6a3eab7309a824d7b1f5c72a13a1fb..38a82f1ee3541b8d47bbc9c0ce3191e53702cd4a 100644 (file)
@@ -59,6 +59,10 @@ struct fiq_debugger_pdata {
 
        void (*force_irq)(struct platform_device *pdev, unsigned int irq);
        void (*force_irq_ack)(struct platform_device *pdev, unsigned int irq);
+
+#ifdef CONFIG_RK_CONSOLE_THREAD
+       void (*console_write)(struct platform_device *pdev, const char *s, unsigned int count);
+#endif
 };
 
 #endif
index 58e73499aea28588cb044bf29b17501bc65a76f7..c14ce225ac5db478015a9be5793f5ca0c1c458c9 100644 (file)
@@ -146,6 +146,13 @@ config RK_DEBUG_UART
        help
          Select a UART for debugging. -1 disable.
 
+config RK_CONSOLE_THREAD
+       bool "Console write by thread"
+       depends on FIQ_DEBUGGER_CONSOLE
+       default y
+       help
+         Normal kernel printk will write out to UART by "kconsole" kthread
+
 config RK_SRAM_DMA
        bool "Sound DMA buffer in internal SRAM"
        depends on ARCH_RK30
index 7461f06676a9cd62032a5ca7d1917f865c213c1b..55f409914a00b8f2ad891c8109ba20001f7633f0 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <linux/stacktrace.h>
 #include <linux/uaccess.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
 #include <asm/fiq_debugger.h>
 #include <asm/hardware/gic.h>
 #include <plat/rk_fiq_debugger.h>
@@ -36,6 +38,9 @@ struct rk_fiq_debugger {
        struct fiq_debugger_pdata pdata;
        void __iomem *debug_port_base;
        bool break_seen;
+#ifdef CONFIG_RK_CONSOLE_THREAD
+       struct task_struct *console_task;
+#endif
 };
 
 static inline void rk_fiq_write(struct rk_fiq_debugger *t,
@@ -122,6 +127,61 @@ static void debug_flush(struct platform_device *pdev)
                cpu_relax();
 }
 
+#ifdef CONFIG_RK_CONSOLE_THREAD
+static DEFINE_KFIFO(fifo, unsigned char, SZ_64K);
+
+static int console_thread(void *data)
+{
+       struct platform_device *pdev = data;
+       struct rk_fiq_debugger *t;
+       unsigned char c;
+       t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+       while (1) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+               if (kthread_should_stop())
+                       break;
+               set_current_state(TASK_RUNNING);
+               while (kfifo_get(&fifo, &c))
+                       debug_putc(pdev, c);
+               debug_flush(pdev);
+       }
+
+       return 0;
+}
+
+static void console_write(struct platform_device *pdev, const char *s, unsigned int count)
+{
+       unsigned char c, r = '\r';
+       static bool oops = false;
+       struct rk_fiq_debugger *t;
+       t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+       if (oops_in_progress || oops) {
+               while (kfifo_get(&fifo, &c))
+                       debug_putc(pdev, c);
+               while (count--) {
+                       if (*s == '\n') {
+                               debug_putc(pdev, r);
+                       }
+                       debug_putc(pdev, *s++);
+               }
+               debug_flush(pdev);
+               oops = true;
+               return;
+       }
+
+       while (count--) {
+               if (*s == '\n') {
+                       kfifo_put(&fifo, &r);
+               }
+               kfifo_put(&fifo, s++);
+       }
+       wake_up_process(t->console_task);
+}
+#endif
+
 static void fiq_enable(struct platform_device *pdev, unsigned int irq, bool on)
 {
        if (on)
@@ -199,6 +259,15 @@ void rk_serial_debug_init(void __iomem *base, int irq, int signal_irq, int wakeu
                res_count++;
        }
 
+#ifdef CONFIG_RK_CONSOLE_THREAD
+       t->console_task = kthread_create(console_thread, pdev, "kconsole");
+       if (!IS_ERR(t->console_task)) {
+               struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+               t->pdata.console_write = console_write;
+               sched_setscheduler_nocheck(t->console_task, SCHED_FIFO, &param);
+       }
+#endif
+
        pdev->name = "fiq_debugger";
        pdev->id = rk_fiq_debugger_id++;
        pdev->dev.platform_data = &t->pdata;