Date: Tue, 28 Mar 2006 19:25:59 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 94198 for review Message-ID: <200603281925.k2SJPxHq055034@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=94198 Change 94198 by marcel@marcel_nfs on 2006/03/28 19:25:52 Have the sysdev methods grab and release the hardware lock. This prevents system console output tos with the hardware when the TTY layer is already doing that. By default there's no mutex associated with the sysdev, but when bus enumation links a sysdev to a softc, the hardware mutex is shared between them. Alternatively: put the mutex in the BAS. Pointed out by: grehan@ Discussed with: grehan@ Affected files ... .. //depot/projects/uart/dev/uart/uart_core.c#47 edit .. //depot/projects/uart/dev/uart/uart_cpu.h#16 edit Differences ... ==== //depot/projects/uart/dev/uart/uart_core.c#47 (text+ko) ==== @@ -205,7 +205,7 @@ if (sc->sc_opened) uart_sched_softih(sc, SER_INT_SIGCHG); - return (0); + return (1); } /* @@ -480,6 +480,9 @@ if (error) goto fail; + if (sc->sc_sysdev != NULL) + sc->sc_sysdev->hwmtx = &sc->sc_hwmtx; + sc->sc_leaving = 0; uart_intr(sc); return (0); @@ -509,6 +512,9 @@ sc->sc_leaving = 1; + if (sc->sc_sysdev != NULL) + sc->sc_sysdev->hwmtx = NULL; + UART_DETACH(sc); if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL) ==== //depot/projects/uart/dev/uart/uart_cpu.h#16 (text+ko) ==== @@ -29,6 +29,10 @@ #ifndef _DEV_UART_CPU_H_ #define _DEV_UART_CPU_H_ +#include <sys/kdb.h> +#include <sys/lock.h> +#include <sys/mutex.h> + /* * Low-level operations for use by console and/or debug port support. */ @@ -68,6 +72,7 @@ int (*attach)(struct uart_softc*); int (*detach)(struct uart_softc*); void *cookie; /* Type dependent use. */ + struct mtx *hwmtx; }; int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); @@ -80,41 +85,77 @@ * Operations for low-level access to the UART. Primarily for use * by console and debug port logic. */ + +static __inline void +uart_lock_spin(struct mtx *hwmtx) +{ + if (!kdb_active && hwmtx != NULL) + mtx_lock_spin(hwmtx); +} + +static __inline void +uart_unlock_spin(struct mtx *hwmtx) +{ + if (!kdb_active && hwmtx != NULL) + mtx_unlock_spin(hwmtx); +} + static __inline int uart_probe(struct uart_devinfo *di) { - return (di->ops.probe(&di->bas)); + int res; + + uart_lock_spin(di->hwmtx); + res = di->ops.probe(&di->bas); + uart_unlock_spin(di->hwmtx); + return (res); } static __inline void uart_init(struct uart_devinfo *di) { + uart_lock_spin(di->hwmtx); di->ops.init(&di->bas, di->baudrate, di->databits, di->stopbits, di->parity); + uart_unlock_spin(di->hwmtx); } static __inline void uart_term(struct uart_devinfo *di) { + uart_lock_spin(di->hwmtx); di->ops.term(&di->bas); + uart_unlock_spin(di->hwmtx); } static __inline void uart_putc(struct uart_devinfo *di, int c) { + uart_lock_spin(di->hwmtx); di->ops.putc(&di->bas, c); + uart_unlock_spin(di->hwmtx); } static __inline int uart_poll(struct uart_devinfo *di) { - return (di->ops.poll(&di->bas)); + int res; + + uart_lock_spin(di->hwmtx); + res = di->ops.poll(&di->bas); + uart_unlock_spin(di->hwmtx); + return (res); } static __inline int uart_getc(struct uart_devinfo *di) { - return (di->ops.getc(&di->bas)); + int res; + + uart_lock_spin(di->hwmtx); + res = di->ops.getc(&di->bas); + uart_unlock_spin(di->hwmtx); + return (res); } #endif /* _DEV_UART_CPU_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603281925.k2SJPxHq055034>