ANDROID: ARM: fiq_debugger: lock between tty and console writes
authorColin Cross <ccross@android.com>
Thu, 1 Nov 2012 00:41:39 +0000 (17:41 -0700)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 18 Dec 2017 15:41:22 +0000 (21:11 +0530)
debug_console_write calls debug_uart_flush, which will usually wait
until the serial port fifo empties.  If another thread is continuously
calling fiq_tty_write, the fifo will constantly be refilled and
debug_uart_flush might never return.

Add a spinlock that is locked in debug_console_write and fiq_tty_write
to ensure they can't run at the same time.  This has an extra advantage
of preventing lines from the console and tty from being mixed together.

Also reduce the size returned by fiq_tty_write_room to keep the time
spent with the spinlock held to a reasonable value.

In addition, make sure fiq context can't loop forever by never calling
debug_uart_flush when the console is enabled.

Change-Id: I5712b01f740ca0c84f680d2032c9fa16b7656939
Signed-off-by: Colin Cross <ccross@android.com>
[AmitP: Folded following android-4.9 commit changes into this patch
        b4ffddec3493 ("ANDROID: ARM: fiq_debugger: fix uninitialised spin_lock.")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
arch/arm/common/fiq_debugger.c

index f51119d611d0a5fcdb89ff2480daab964ac92c00..55f96e2da2ffa065b43f45057f3dd5071ea23431 100644 (file)
@@ -87,6 +87,7 @@ struct fiq_debugger_state {
        char work_cmd[DEBUG_MAX];
 
 #ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
+       spinlock_t console_lock;
        struct console console;
        struct tty_struct *tty;
        int tty_open_count;
@@ -689,8 +690,9 @@ static bool debug_fiq_exec(struct fiq_debugger_state *state,
                state->no_sleep = true;
                debug_printf(state, "disabling sleep\n");
        } else if (!strcmp(cmd, "console")) {
-               state->console_enable = true;
                debug_printf(state, "console mode\n");
+               debug_uart_flush(state);
+               state->console_enable = true;
        } else if (!strcmp(cmd, "cpu")) {
                debug_printf(state, "cpu %d\n", state->current_cpu);
        } else if (!strncmp(cmd, "cpu ", 4)) {
@@ -877,7 +879,8 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
                }
                last_c = c;
        }
-       debug_uart_flush(state);
+       if (!state->console_enable)
+               debug_uart_flush(state);
        if (state->pdata->fiq_ack)
                state->pdata->fiq_ack(state->pdev, state->fiq);
 
@@ -961,6 +964,7 @@ static void debug_console_write(struct console *co,
                                const char *s, unsigned int count)
 {
        struct fiq_debugger_state *state;
+       unsigned long flags;
 
        state = container_of(co, struct fiq_debugger_state, console);
 
@@ -968,12 +972,14 @@ static void debug_console_write(struct console *co,
                return;
 
        debug_uart_enable(state);
+       spin_lock_irqsave(&state->console_lock, flags);
        while (count--) {
                if (*s == '\n')
                        debug_putc(state, '\r');
                debug_putc(state, *s++);
        }
        debug_uart_flush(state);
+       spin_unlock_irqrestore(&state->console_lock, flags);
        debug_uart_disable(state);
 }
 
@@ -1014,8 +1020,10 @@ int  fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
                return count;
 
        debug_uart_enable(state);
+       spin_lock_irq(&state->console_lock);
        for (i = 0; i < count; i++)
                debug_putc(state, *buf++);
+       spin_unlock_irq(&state->console_lock);
        debug_uart_disable(state);
 
        return count;
@@ -1023,7 +1031,7 @@ int  fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
 
 int  fiq_tty_write_room(struct tty_struct *tty)
 {
-       return 1024;
+       return 16;
 }
 
 #ifdef CONFIG_CONSOLE_POLL
@@ -1313,6 +1321,7 @@ static int fiq_debugger_probe(struct platform_device *pdev)
                handle_wakeup(state);
 
 #if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
+       spin_lock_init(&state->console_lock);
        state->console = fiq_debugger_console;
        state->console.index = pdev->id;
        if (!console_set_on_cmdline)