summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-09-17 01:41:21 +0000
committermarcel <marcel@FreeBSD.org>2003-09-17 01:41:21 +0000
commit96dbeb7199a05e6fb1bc00cdfcd8727467423d09 (patch)
tree976d5fcb92d42c5763ac054fcd83a3a3ba593d98
parent25d51778fc93c3659f92b88183b9b4f4814bc3f4 (diff)
downloadFreeBSD-src-96dbeb7199a05e6fb1bc00cdfcd8727467423d09.zip
FreeBSD-src-96dbeb7199a05e6fb1bc00cdfcd8727467423d09.tar.gz
Add locking to the hardware drivers. I intended to figure out more
precisely where locking would be needed before adding it, but it seems uart(4) draws slightly too much attention to have it without locking for too long. The lock added is a spinlock that protects access to the underlying hardware. As a first and obvious stab at this, each method of the hardware interface grabs the lock. Roughly speaking this serializes the methods. Exceptions are the probe, attach and detach methods.
-rw-r--r--sys/dev/uart/uart_bus.h2
-rw-r--r--sys/dev/uart/uart_core.c2
-rw-r--r--sys/dev/uart/uart_dev_i8251.c42
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c42
-rw-r--r--sys/dev/uart/uart_dev_sab82532.c28
-rw-r--r--sys/dev/uart/uart_dev_z8530.c25
-rw-r--r--sys/dev/uart/uart_if.m3
7 files changed, 117 insertions, 27 deletions
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h
index bd0bab7..dde9ff8 100644
--- a/sys/dev/uart/uart_bus.h
+++ b/sys/dev/uart/uart_bus.h
@@ -113,6 +113,8 @@ struct uart_softc {
struct uart_bas sc_bas;
device_t sc_dev;
+ struct mtx sc_hwmtx; /* Spinlock protecting hardware. */
+
struct resource *sc_rres; /* Register resource. */
int sc_rrid;
int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 883bea2..dd4f91c 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -309,6 +309,8 @@ uart_bus_attach(device_t dev)
*/
sc->sc_leaving = 1;
+ mtx_init(&sc->sc_hwmtx, "uart_hwmtx", NULL, MTX_SPIN);
+
/*
* Re-allocate. We expect that the softc contains the information
* collected by uart_bus_probe() intact.
diff --git a/sys/dev/uart/uart_dev_i8251.c b/sys/dev/uart/uart_dev_i8251.c
index a953b98..9e9a5b2 100644
--- a/sys/dev/uart/uart_dev_i8251.c
+++ b/sys/dev/uart/uart_dev_i8251.c
@@ -427,15 +427,19 @@ i8251_bus_flush(struct uart_softc *sc, int what)
{
struct i8251_softc *i8251 = (struct i8251_softc*)sc;
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
if (sc->sc_hasfifo) {
i8251_flush(bas, what);
uart_setreg(bas, REG_FCR, i8251->fcr);
uart_barrier(bas);
- return (0);
- }
- return (i8251_drain(bas, what));
+ error = 0;
+ } else
+ error = i8251_drain(bas, what);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -447,7 +451,9 @@ i8251_bus_getsig(struct uart_softc *sc)
do {
old = sc->sc_hwsig;
sig = old;
+ mtx_lock_spin(&sc->sc_hwmtx);
msr = uart_getreg(&sc->sc_bas, REG_MSR);
+ mtx_unlock_spin(&sc->sc_hwmtx);
SIGCHG(msr & MSR_DSR, sig, UART_SIG_DSR, UART_SIG_DDSR);
SIGCHG(msr & MSR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
SIGCHG(msr & MSR_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
@@ -461,9 +467,12 @@ static int
i8251_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct uart_bas *bas;
+ int error;
uint8_t lcr;
bas = &sc->sc_bas;
+ error = 0;
+ mtx_lock_spin(&sc->sc_hwmtx);
switch (request) {
case UART_IOCTL_BREAK:
lcr = uart_getreg(bas, REG_LCR);
@@ -475,9 +484,11 @@ i8251_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
uart_barrier(bas);
break;
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- return (0);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -488,13 +499,16 @@ i8251_bus_ipend(struct uart_softc *sc)
uint8_t iir, lsr;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
iir = uart_getreg(bas, REG_IIR);
- if (iir & IIR_NOPEND)
+ if (iir & IIR_NOPEND) {
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
-
+ }
ipend = 0;
if (iir & IIR_RXRDY) {
lsr = uart_getreg(bas, REG_LSR);
+ mtx_unlock_spin(&sc->sc_hwmtx);
if (lsr & LSR_OE)
ipend |= UART_IPEND_OVERRUN;
if (lsr & LSR_BI)
@@ -502,12 +516,12 @@ i8251_bus_ipend(struct uart_softc *sc)
if (lsr & LSR_RXRDY)
ipend |= UART_IPEND_RXREADY;
} else {
+ mtx_unlock_spin(&sc->sc_hwmtx);
if (iir & IIR_TXRDY)
ipend |= UART_IPEND_TXIDLE;
else
ipend |= UART_IPEND_SIGCHG;
}
-
return ((sc->sc_leaving) ? 0 : ipend);
}
@@ -516,9 +530,13 @@ i8251_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
- return (i8251_param(bas, baudrate, databits, stopbits, parity));
+ mtx_lock_spin(&sc->sc_hwmtx);
+ error = i8251_param(bas, baudrate, databits, stopbits, parity);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -661,6 +679,7 @@ i8251_bus_receive(struct uart_softc *sc)
uint8_t lsr;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while (!uart_rx_full(sc)) {
lsr = uart_getreg(bas, REG_LSR);
if ((lsr & LSR_RXRDY) == 0)
@@ -672,6 +691,7 @@ i8251_bus_receive(struct uart_softc *sc)
xc |= UART_STAT_PARERR;
uart_rx_put(sc, xc);
}
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -695,6 +715,7 @@ i8251_bus_setsig(struct uart_softc *sc, int sig)
UART_SIG_DRTS);
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ mtx_lock_spin(&sc->sc_hwmtx);
i8251->mcr &= ~(MCR_DTR|MCR_RTS);
if (new & UART_SIG_DTR)
i8251->mcr |= MCR_DTR;
@@ -702,6 +723,7 @@ i8251_bus_setsig(struct uart_softc *sc, int sig)
i8251->mcr |= MCR_RTS;
uart_setreg(bas, REG_MCR, i8251->mcr);
uart_barrier(bas);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -713,6 +735,7 @@ i8251_bus_transmit(struct uart_softc *sc)
int i;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
;
uart_setreg(bas, REG_IER, i8251->ier | IER_ETXRDY);
@@ -722,5 +745,6 @@ i8251_bus_transmit(struct uart_softc *sc)
uart_barrier(bas);
}
sc->sc_txbusy = 1;
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index ada5710..7c4d264 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -427,15 +427,19 @@ ns8250_bus_flush(struct uart_softc *sc, int what)
{
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
if (sc->sc_hasfifo) {
ns8250_flush(bas, what);
uart_setreg(bas, REG_FCR, ns8250->fcr);
uart_barrier(bas);
- return (0);
- }
- return (ns8250_drain(bas, what));
+ error = 0;
+ } else
+ error = ns8250_drain(bas, what);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -447,7 +451,9 @@ ns8250_bus_getsig(struct uart_softc *sc)
do {
old = sc->sc_hwsig;
sig = old;
+ mtx_lock_spin(&sc->sc_hwmtx);
msr = uart_getreg(&sc->sc_bas, REG_MSR);
+ mtx_unlock_spin(&sc->sc_hwmtx);
SIGCHG(msr & MSR_DSR, sig, UART_SIG_DSR, UART_SIG_DDSR);
SIGCHG(msr & MSR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
SIGCHG(msr & MSR_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
@@ -461,9 +467,12 @@ static int
ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct uart_bas *bas;
+ int error;
uint8_t efr, lcr;
bas = &sc->sc_bas;
+ error = 0;
+ mtx_lock_spin(&sc->sc_hwmtx);
switch (request) {
case UART_IOCTL_BREAK:
lcr = uart_getreg(bas, REG_LCR);
@@ -505,9 +514,11 @@ ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
uart_barrier(bas);
break;
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- return (0);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -518,13 +529,16 @@ ns8250_bus_ipend(struct uart_softc *sc)
uint8_t iir, lsr;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
iir = uart_getreg(bas, REG_IIR);
- if (iir & IIR_NOPEND)
+ if (iir & IIR_NOPEND) {
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
-
+ }
ipend = 0;
if (iir & IIR_RXRDY) {
lsr = uart_getreg(bas, REG_LSR);
+ mtx_unlock_spin(&sc->sc_hwmtx);
if (lsr & LSR_OE)
ipend |= UART_IPEND_OVERRUN;
if (lsr & LSR_BI)
@@ -532,12 +546,12 @@ ns8250_bus_ipend(struct uart_softc *sc)
if (lsr & LSR_RXRDY)
ipend |= UART_IPEND_RXREADY;
} else {
+ mtx_unlock_spin(&sc->sc_hwmtx);
if (iir & IIR_TXRDY)
ipend |= UART_IPEND_TXIDLE;
else
ipend |= UART_IPEND_SIGCHG;
}
-
return ((sc->sc_leaving) ? 0 : ipend);
}
@@ -546,9 +560,13 @@ ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
- return (ns8250_param(bas, baudrate, databits, stopbits, parity));
+ mtx_lock_spin(&sc->sc_hwmtx);
+ error = ns8250_param(bas, baudrate, databits, stopbits, parity);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -697,6 +715,7 @@ ns8250_bus_receive(struct uart_softc *sc)
uint8_t lsr;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while (!uart_rx_full(sc)) {
lsr = uart_getreg(bas, REG_LSR);
if ((lsr & LSR_RXRDY) == 0)
@@ -708,6 +727,7 @@ ns8250_bus_receive(struct uart_softc *sc)
xc |= UART_STAT_PARERR;
uart_rx_put(sc, xc);
}
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -731,6 +751,7 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
UART_SIG_DRTS);
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ mtx_lock_spin(&sc->sc_hwmtx);
ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
if (new & UART_SIG_DTR)
ns8250->mcr |= MCR_DTR;
@@ -738,6 +759,7 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
ns8250->mcr |= MCR_RTS;
uart_setreg(bas, REG_MCR, ns8250->mcr);
uart_barrier(bas);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -749,6 +771,7 @@ ns8250_bus_transmit(struct uart_softc *sc)
int i;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
;
uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
@@ -758,5 +781,6 @@ ns8250_bus_transmit(struct uart_softc *sc)
uart_barrier(bas);
}
sc->sc_txbusy = 1;
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c
index 5345e97..ec1c9f5 100644
--- a/sys/dev/uart/uart_dev_sab82532.c
+++ b/sys/dev/uart/uart_dev_sab82532.c
@@ -425,7 +425,9 @@ static int
sab82532_bus_flush(struct uart_softc *sc, int what)
{
+ mtx_lock_spin(&sc->sc_hwmtx);
sab82532_flush(&sc->sc_bas, what);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -440,6 +442,7 @@ sab82532_bus_getsig(struct uart_softc *sc)
do {
old = sc->sc_hwsig;
sig = old;
+ mtx_lock_spin(&sc->sc_hwmtx);
star = uart_getreg(bas, SAB_STAR);
SIGCHG(star & SAB_STAR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
vstr = uart_getreg(bas, SAB_VSTR);
@@ -447,6 +450,7 @@ sab82532_bus_getsig(struct uart_softc *sc)
pvr = uart_getreg(bas, SAB_PVR);
pvr &= (IS_CHANNEL_A(bas)) ? SAB_PVR_DSR_A : SAB_PVR_DSR_B;
SIGCHG(~pvr, sig, UART_SIG_DSR, UART_SIG_DDSR);
+ mtx_unlock_spin(&sc->sc_hwmtx);
new = sig & ~UART_SIGMASK_DELTA;
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
return (sig);
@@ -457,8 +461,11 @@ sab82532_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct uart_bas *bas;
uint8_t dafo, mode;
+ int error;
bas = &sc->sc_bas;
+ error = 0;
+ mtx_lock_spin(&sc->sc_hwmtx);
switch (request) {
case UART_IOCTL_BREAK:
dafo = uart_getreg(bas, SAB_DAFO);
@@ -491,9 +498,11 @@ sab82532_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
uart_barrier(bas);
break;
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- return (0);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -504,16 +513,17 @@ sab82532_bus_ipend(struct uart_softc *sc)
uint8_t isr0, isr1;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
isr0 = uart_getreg(bas, SAB_ISR0);
isr1 = uart_getreg(bas, SAB_ISR1);
uart_barrier(bas);
-
if (isr0 & SAB_ISR0_TIME) {
while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
;
uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
uart_barrier(bas);
}
+ mtx_unlock_spin(&sc->sc_hwmtx);
ipend = 0;
if (isr1 & SAB_ISR1_BRKT)
@@ -535,9 +545,13 @@ sab82532_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
- return (sab82532_param(bas, baudrate, databits, stopbits, parity));
+ mtx_lock_spin(&sc->sc_hwmtx);
+ error = sab82532_param(bas, baudrate, databits, stopbits, parity);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -584,6 +598,7 @@ sab82532_bus_receive(struct uart_softc *sc)
uint8_t s;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
if (uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE) {
rbcl = uart_getreg(bas, SAB_RBCL) & 31;
if (rbcl == 0)
@@ -607,6 +622,7 @@ sab82532_bus_receive(struct uart_softc *sc)
;
uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC);
uart_barrier(bas);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -631,6 +647,7 @@ sab82532_bus_setsig(struct uart_softc *sc, int sig)
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ mtx_lock_spin(&sc->sc_hwmtx);
/* Set DTR pin. */
pvr = uart_getreg(bas, SAB_PVR);
if (new & UART_SIG_DTR)
@@ -647,6 +664,7 @@ sab82532_bus_setsig(struct uart_softc *sc, int sig)
mode |= SAB_MODE_FRTS;
uart_setreg(bas, SAB_MODE, mode);
uart_barrier(bas);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -657,6 +675,7 @@ sab82532_bus_transmit(struct uart_softc *sc)
int i;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_XFW))
;
for (i = 0; i < sc->sc_txdatasz; i++)
@@ -666,5 +685,6 @@ sab82532_bus_transmit(struct uart_softc *sc)
;
uart_setreg(bas, SAB_CMDR, SAB_CMDR_XF);
sc->sc_txbusy = 1;
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c
index a7c6e25..319783a 100644
--- a/sys/dev/uart/uart_dev_z8530.c
+++ b/sys/dev/uart/uart_dev_z8530.c
@@ -334,15 +334,15 @@ z8530_bus_flush(struct uart_softc *sc, int what)
static int
z8530_bus_getsig(struct uart_softc *sc)
{
- struct uart_bas *bas;
uint32_t new, old, sig;
uint8_t bes;
- bas = &sc->sc_bas;
do {
old = sc->sc_hwsig;
sig = old;
- bes = uart_getmreg(bas, RR_BES);
+ mtx_lock_spin(&sc->sc_hwmtx);
+ bes = uart_getmreg(&sc->sc_bas, RR_BES);
+ mtx_unlock_spin(&sc->sc_hwmtx);
SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
new = sig & ~UART_SIGMASK_DELTA;
@@ -355,8 +355,11 @@ z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct z8530_softc *z8530 = (struct z8530_softc*)sc;
struct uart_bas *bas;
+ int error;
bas = &sc->sc_bas;
+ error = 0;
+ mtx_lock_spin(&sc->sc_hwmtx);
switch (request) {
case UART_IOCTL_BREAK:
if (data)
@@ -367,9 +370,11 @@ z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
uart_barrier(bas);
break;
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- return (0);
+ mtx_unlock_spin(&sc->sc_hwmtx);
+ return (error);
}
static int
@@ -382,6 +387,7 @@ z8530_bus_ipend(struct uart_softc *sc)
bas = &sc->sc_bas;
ipend = 0;
+ mtx_lock_spin(&sc->sc_hwmtx);
uart_setreg(bas, REG_CTRL, CR_RSTIUS);
uart_barrier(bas);
bes = uart_getmreg(bas, RR_BES);
@@ -405,6 +411,7 @@ z8530_bus_ipend(struct uart_softc *sc)
uart_setreg(bas, REG_CTRL, CR_RSTERR);
ipend |= UART_IPEND_OVERRUN;
}
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (ipend);
}
@@ -415,8 +422,10 @@ z8530_bus_param(struct uart_softc *sc, int baudrate, int databits,
struct z8530_softc *z8530 = (struct z8530_softc*)sc;
int error;
+ mtx_lock_spin(&sc->sc_hwmtx);
error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity,
&z8530->tpc);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (error);
}
@@ -447,6 +456,7 @@ z8530_bus_receive(struct uart_softc *sc)
uint8_t bes, src;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
bes = uart_getmreg(bas, RR_BES);
while ((bes & BES_RXA) && !uart_rx_full(sc)) {
src = uart_getmreg(bas, RR_SRC);
@@ -460,6 +470,7 @@ z8530_bus_receive(struct uart_softc *sc)
uart_setreg(bas, REG_CTRL, CR_RSTERR);
bes = uart_getmreg(bas, RR_BES);
}
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -484,6 +495,7 @@ z8530_bus_setsig(struct uart_softc *sc, int sig)
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ mtx_lock_spin(&sc->sc_hwmtx);
if (new & UART_SIG_DTR)
z8530->tpc |= TPC_DTR;
else
@@ -494,6 +506,7 @@ z8530_bus_setsig(struct uart_softc *sc, int sig)
z8530->tpc &= ~TPC_RTS;
uart_setmreg(bas, WR_TPC, z8530->tpc);
uart_barrier(bas);
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
@@ -503,10 +516,12 @@ z8530_bus_transmit(struct uart_softc *sc)
struct uart_bas *bas;
bas = &sc->sc_bas;
+ mtx_lock_spin(&sc->sc_hwmtx);
while (!(uart_getmreg(bas, RR_BES) & BES_TXE))
;
uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]);
uart_barrier(bas);
sc->sc_txbusy = 1;
+ mtx_unlock_spin(&sc->sc_hwmtx);
return (0);
}
diff --git a/sys/dev/uart/uart_if.m b/sys/dev/uart/uart_if.m
index 772883d..762c16e 100644
--- a/sys/dev/uart/uart_if.m
+++ b/sys/dev/uart/uart_if.m
@@ -24,6 +24,9 @@
#
# $FreeBSD$
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
OpenPOWER on IntegriCloud