soc: rockchip: rk_fiq_debugger: better console thread print

- Print by message other than by byte.
  Make messages more readable.
- Sleep while block other than busy loop.
  Reduce cpu usage while print a lot of messages.
- Show how many messages dropped.
  Let people know that the messages are not complete.
- Wake up console_task when needed.
  Reduce unneeded call wake_up_process.

Change-Id: I508d2f5b6671695413b01bc167d768ec9b614934
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang
2018-04-23 19:45:49 +08:00
parent 09aeb6ebfb
commit cea2a68180

View File

@@ -207,26 +207,95 @@ static void debug_flush(struct platform_device *pdev)
#ifdef CONFIG_RK_CONSOLE_THREAD
#define FIFO_SIZE SZ_64K
#define LINE_MAX 1024
static DEFINE_KFIFO(fifo, unsigned char, FIFO_SIZE);
static char console_buf[LINE_MAX]; /* avoid FRAME WARN */
static bool console_thread_stop;
static unsigned int console_dropped_messages;
static void console_putc(struct platform_device *pdev, unsigned int c)
{
struct rk_fiq_debugger *t;
unsigned int count = 500;
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
while (!(rk_fiq_read(t, UART_USR) & UART_USR_TX_FIFO_NOT_FULL) &&
count--)
usleep_range(200, 210);
/* If uart is always busy, maybe it is abnormal, reinit it */
if ((count == 0) && (rk_fiq_read(t, UART_USR) & UART_USR_BUSY))
debug_port_init(pdev);
rk_fiq_write(t, c, UART_TX);
}
static void console_flush(struct platform_device *pdev)
{
struct rk_fiq_debugger *t;
unsigned int count = 500;
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
while (!(rk_fiq_read_lsr(t) & UART_LSR_TEMT) && count--)
usleep_range(200, 210);
/* If uart is always busy, maybe it is abnormal, reinit it */
if ((count == 0) && (rk_fiq_read(t, UART_USR) & UART_USR_BUSY))
debug_port_init(pdev);
}
static void console_put(struct platform_device *pdev,
const char *s, unsigned int count)
{
while (count--) {
if (*s == '\n')
console_putc(pdev, '\r');
console_putc(pdev, *s++);
}
}
static void debug_put(struct platform_device *pdev,
const char *s, unsigned int count)
{
while (count--) {
if (*s == '\n')
debug_putc(pdev, '\r');
debug_putc(pdev, *s++);
}
}
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);
char *buf = console_buf;
unsigned int len;
while (1) {
unsigned int dropped;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (kfifo_is_empty(&fifo))
schedule();
if (kthread_should_stop())
break;
set_current_state(TASK_RUNNING);
while (!console_thread_stop && kfifo_get(&fifo, &c))
debug_putc(pdev, c);
while (!console_thread_stop) {
len = kfifo_out(&fifo, buf, LINE_MAX);
if (!len)
break;
console_put(pdev, buf, len);
}
dropped = console_dropped_messages;
if (dropped && !console_thread_stop) {
console_dropped_messages = 0;
smp_wmb();
len = snprintf(buf, LINE_MAX,
"** %u console messages dropped **\n",
dropped);
console_put(pdev, buf, len);
}
if (!console_thread_stop)
debug_flush(pdev);
console_flush(pdev);
}
return 0;
@@ -235,8 +304,9 @@ static int console_thread(void *data)
static void console_write(struct platform_device *pdev, const char *s, unsigned int count)
{
unsigned int fifo_count = FIFO_SIZE;
unsigned char c, r = '\r';
unsigned char c;
struct rk_fiq_debugger *t;
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
if (console_thread_stop ||
@@ -249,23 +319,21 @@ static void console_write(struct platform_device *pdev, const char *s, unsigned
smp_wmb();
debug_flush(pdev);
while (fifo_count-- && kfifo_get(&fifo, &c))
debug_putc(pdev, c);
}
while (count--) {
if (*s == '\n') {
debug_putc(pdev, r);
}
debug_putc(pdev, *s++);
debug_put(pdev, &c, 1);
}
debug_put(pdev, s, count);
debug_flush(pdev);
} else {
while (count--) {
if (*s == '\n') {
kfifo_put(&fifo, r);
}
kfifo_put(&fifo, *s++);
} else if (count) {
unsigned int ret = 0;
if (kfifo_len(&fifo) + count < FIFO_SIZE)
ret = kfifo_in(&fifo, s, count);
if (!ret) {
console_dropped_messages++;
smp_wmb();
} else {
wake_up_process(t->console_task);
}
wake_up_process(t->console_task);
}
}
#endif