From 01ed5990aef062b97e91680895804b9689c8076b Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 1 Apr 2006 19:04:54 +0000 Subject: Don't hold the hardware mutex across getc(). It can wait indefinitely for a character to be received. Instead let getc() do any necesary locking. --- sys/dev/uart/uart_cpu.h | 8 ++------ sys/dev/uart/uart_dev_ns8250.c | 20 +++++++++++++++----- sys/dev/uart/uart_dev_sab82532.c | 16 ++++++++++++---- sys/dev/uart/uart_dev_z8530.c | 21 ++++++++++++++++----- 4 files changed, 45 insertions(+), 20 deletions(-) (limited to 'sys/dev/uart') diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h index 310d6b9..a3f0dcb 100644 --- a/sys/dev/uart/uart_cpu.h +++ b/sys/dev/uart/uart_cpu.h @@ -42,7 +42,7 @@ struct uart_ops { void (*term)(struct uart_bas *); void (*putc)(struct uart_bas *, int); int (*poll)(struct uart_bas *); - int (*getc)(struct uart_bas *); + int (*getc)(struct uart_bas *, struct mtx *); }; extern struct uart_ops uart_i8251_ops; @@ -150,12 +150,8 @@ uart_poll(struct uart_devinfo *di) static __inline int uart_getc(struct uart_devinfo *di) { - int res; - uart_lock(di->hwmtx); - res = di->ops.getc(&di->bas); - uart_unlock(di->hwmtx); - return (res); + return (di->ops.getc(&di->bas, di->hwmtx)); } #endif /* _DEV_UART_CPU_H_ */ diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 378639f..adb4502 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -217,7 +217,7 @@ static void ns8250_init(struct uart_bas *bas, int, int, int, int); static void ns8250_term(struct uart_bas *bas); static void ns8250_putc(struct uart_bas *bas, int); static int ns8250_poll(struct uart_bas *bas); -static int ns8250_getc(struct uart_bas *bas); +static int ns8250_getc(struct uart_bas *bas, struct mtx *); struct uart_ops uart_ns8250_ops = { .probe = ns8250_probe, @@ -321,16 +321,26 @@ ns8250_poll(struct uart_bas *bas) } static int -ns8250_getc(struct uart_bas *bas) +ns8250_getc(struct uart_bas *bas, struct mtx *hwmtx) { - int delay; + int c, delay; + + uart_lock(hwmtx); /* 1/10th the time to transmit 1 character (estimate). */ delay = ns8250_delay(bas); - while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) + while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) { + uart_unlock(hwmtx); DELAY(delay); - return (uart_getreg(bas, REG_DATA)); + uart_lock(hwmtx); + } + + c = uart_getreg(bas, REG_DATA); + + uart_unlock(hwmtx); + + return (c); } /* diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c index 927a681..9ef0bd1 100644 --- a/sys/dev/uart/uart_dev_sab82532.c +++ b/sys/dev/uart/uart_dev_sab82532.c @@ -174,7 +174,7 @@ static void sab82532_init(struct uart_bas *bas, int, int, int, int); static void sab82532_term(struct uart_bas *bas); static void sab82532_putc(struct uart_bas *bas, int); static int sab82532_poll(struct uart_bas *bas); -static int sab82532_getc(struct uart_bas *bas); +static int sab82532_getc(struct uart_bas *bas, struct mtx *); struct uart_ops uart_sab82532_ops = { .probe = sab82532_probe, @@ -307,20 +307,25 @@ sab82532_poll(struct uart_bas *bas) { if (uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE) - return (sab82532_getc(bas)); + return (sab82532_getc(bas, NULL)); return (-1); } static int -sab82532_getc(struct uart_bas *bas) +sab82532_getc(struct uart_bas *bas, struct mtx *hwmtx) { int c, delay; + uart_lock(hwmtx); + /* 1/10th the time to transmit 1 character (estimate). */ delay = sab82532_delay(bas); - while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE)) + while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE)) { + uart_unlock(hwmtx); DELAY(delay); + uart_lock(hwmtx); + } while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) ; @@ -338,6 +343,9 @@ sab82532_getc(struct uart_bas *bas) ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC); uart_barrier(bas); + + uart_unlock(hwmtx); + return (c); } diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index 09895eb..4bde071 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -178,7 +178,7 @@ static void z8530_init(struct uart_bas *bas, int, int, int, int); static void z8530_term(struct uart_bas *bas); static void z8530_putc(struct uart_bas *bas, int); static int z8530_poll(struct uart_bas *bas); -static int z8530_getc(struct uart_bas *bas); +static int z8530_getc(struct uart_bas *bas, struct mtx *); struct uart_ops uart_z8530_ops = { .probe = z8530_probe, @@ -229,12 +229,23 @@ z8530_poll(struct uart_bas *bas) } static int -z8530_getc(struct uart_bas *bas) +z8530_getc(struct uart_bas *bas, struct mtx *hwmtx) { + int c; - while (!(uart_getreg(bas, REG_CTRL) & BES_RXA)) - ; - return (uart_getreg(bas, REG_DATA)); + uart_lock(hwmtx); + + while (!(uart_getreg(bas, REG_CTRL) & BES_RXA)) { + uart_unlock(hwmtx); + DELAY(10); + uart_lock(hwmtx); + } + + c = uart_getreg(bas, REG_DATA); + + uart_unlock(hwmtx); + + return (c); } /* -- cgit v1.1