Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Sep 2003 18:42:09 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 37543 for review
Message-ID:  <200309050142.h851g9Pl068369@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=37543

Change 37543 by marcel@marcel_nfs on 2003/09/04 18:41:32

	Atomically update sc->sc_hwsig. This avoids having to use
	a lock, which pessimizes the common case more than the
	overhead of the cmpset operation.

Affected files ...

.. //depot/projects/uart/dev/uart/uart_bus.h#26 edit
.. //depot/projects/uart/dev/uart/uart_dev_ns8250.c#25 edit
.. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#23 edit
.. //depot/projects/uart/dev/uart/uart_dev_z8530.c#11 edit

Differences ...

==== //depot/projects/uart/dev/uart/uart_bus.h#26 (text+ko) ====

@@ -119,7 +119,7 @@
 	struct uart_devinfo *sc_sysdev;	/* System device (or NULL). */
 
 	int		sc_altbrk;	/* State for alt break sequence. */
-	int		sc_hwsig;	/* Signal state. Used by HW driver. */
+	uint32_t	sc_hwsig;	/* Signal state. Used by HW driver. */
 
 	/* Receiver data. */
 	uint16_t	*sc_rxbuf;

==== //depot/projects/uart/dev/uart/uart_dev_ns8250.c#25 (text+ko) ====

@@ -441,16 +441,19 @@
 static int
 ns8250_bus_getsig(struct uart_softc *sc)
 {
-	int sig;
+	uint32_t new, old, sig;
 	uint8_t msr;
 
-	msr = uart_getreg(&sc->sc_bas, REG_MSR);
-	sig = sc->sc_hwsig;
-	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);
-	SIGCHG(msr & MSR_RI,  sig, UART_SIG_RI,  UART_SIG_DRI);
-	sc->sc_hwsig = sig & ~UART_SIGMASK_DELTA;
+	do {
+		old = sc->sc_hwsig;
+		sig = old;
+		msr = uart_getreg(&sc->sc_bas, REG_MSR);
+		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);
+		SIGCHG(msr & MSR_RI,  sig, UART_SIG_RI,  UART_SIG_DRI);
+		new = sig & ~UART_SIGMASK_DELTA;
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
 	return (sig);
 }
 
@@ -677,20 +680,25 @@
 {
 	struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
 	struct uart_bas *bas;
+	uint32_t new, old;
 
 	bas = &sc->sc_bas;
-	if (sig & UART_SIG_DDTR) {
-		SIGCHG(sig & UART_SIG_DTR, sc->sc_hwsig, UART_SIG_DTR,
-		    UART_SIG_DDTR);
-	}
-	if (sig & UART_SIG_DRTS) {
-		SIGCHG(sig & UART_SIG_RTS, sc->sc_hwsig, UART_SIG_RTS,
-		    UART_SIG_DRTS);
-	}
+	do {
+		old = sc->sc_hwsig;
+		new = old;
+		if (sig & UART_SIG_DDTR) {
+			SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR,
+			    UART_SIG_DDTR);
+		}
+		if (sig & UART_SIG_DRTS) {
+			SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS,
+			    UART_SIG_DRTS);
+		}
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
 	ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
-	if (sc->sc_hwsig & UART_SIG_DTR)
+	if (new & UART_SIG_DTR)
 		ns8250->mcr |= MCR_DTR;
-	if (sc->sc_hwsig & UART_SIG_RTS)
+	if (new & UART_SIG_RTS)
 		ns8250->mcr |= MCR_RTS;
 	uart_setreg(bas, REG_MCR, ns8250->mcr);
 	uart_barrier(bas);

==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#23 (text+ko) ====

@@ -429,19 +429,22 @@
 sab82532_bus_getsig(struct uart_softc *sc)
 {
 	struct uart_bas *bas;
-	int sig;
+	uint32_t new, old, sig;
 	uint8_t pvr, star, vstr;
 
 	bas = &sc->sc_bas;
-	sig = sc->sc_hwsig;
-	star = uart_getreg(bas, SAB_STAR);
-	SIGCHG(star & SAB_STAR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
-	vstr = uart_getreg(bas, SAB_VSTR);
-	SIGCHG(vstr & SAB_VSTR_CD, sig, UART_SIG_DCD, UART_SIG_DDCD);
-	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);
-	sc->sc_hwsig = sig & ~UART_SIGMASK_DELTA;
+	do {
+		old = sc->sc_hwsig;
+		sig = old;
+		star = uart_getreg(bas, SAB_STAR);
+		SIGCHG(star & SAB_STAR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
+		vstr = uart_getreg(bas, SAB_VSTR);
+		SIGCHG(vstr & SAB_VSTR_CD, sig, UART_SIG_DCD, UART_SIG_DDCD);
+		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);
+		new = sig & ~UART_SIGMASK_DELTA;
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
 	return (sig);
 }
 
@@ -607,25 +610,34 @@
 sab82532_bus_setsig(struct uart_softc *sc, int sig)
 {
 	struct uart_bas *bas;
+	uint32_t new, old;
 	uint8_t mode, pvr;
 
 	bas = &sc->sc_bas;
-	if (sig & UART_SIG_DDTR) {
-		SIGCHG(sig & UART_SIG_DTR, sc->sc_hwsig, UART_SIG_DTR,
-		    UART_SIG_DDTR);
-	}
-	if (sig & UART_SIG_DRTS) {
-		SIGCHG(sig & UART_SIG_RTS, sc->sc_hwsig, UART_SIG_RTS,
-		    UART_SIG_DRTS);
-	}
+	do {
+		old = sc->sc_hwsig;
+		new = old;
+		if (sig & UART_SIG_DDTR) {
+			SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR,
+			    UART_SIG_DDTR);
+		}
+		if (sig & UART_SIG_DRTS) {
+			SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS,
+			    UART_SIG_DRTS);
+		}
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+
+	/* Set DTR pin. */
 	pvr = uart_getreg(bas, SAB_PVR);
-	if (sc->sc_hwsig & UART_SIG_DTR)
+	if (new & UART_SIG_DTR)
 		pvr &= (IS_CHANNEL_A(bas)) ? ~SAB_PVR_DTR_A : ~SAB_PVR_DTR_B;
 	else
 		pvr |= (IS_CHANNEL_A(bas)) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B;
 	uart_setreg(bas, SAB_PVR, pvr);
+
+	/* Set RTS pin. */
 	mode = uart_getreg(bas, SAB_MODE);
-	if (sc->sc_hwsig & UART_SIG_RTS)
+	if (new & UART_SIG_RTS)
 		mode &= ~SAB_MODE_FRTS;
 	else
 		mode |= SAB_MODE_FRTS;

==== //depot/projects/uart/dev/uart/uart_dev_z8530.c#11 (text+ko) ====

@@ -334,14 +334,19 @@
 static int
 z8530_bus_getsig(struct uart_softc *sc)
 {
-	int sig;
+	struct uart_bas *bas;
+	uint32_t new, old, sig;
 	uint8_t bes;
 
-	sig = sc->sc_hwsig;
-	bes = uart_getmreg(&sc->sc_bas, RR_BES);
-	SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
-	SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
-	sc->sc_hwsig = sig & ~UART_SIGMASK_DELTA;
+	bas = &sc->sc_bas;
+	do {
+		old = sc->sc_hwsig;
+		sig = old;
+		bes = uart_getmreg(bas, RR_BES);
+		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;
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
 	return (sig);
 }
 
@@ -372,6 +377,7 @@
 {
 	struct uart_bas *bas;
 	int ipend;
+	uint32_t sig;
 	uint8_t bes, src;
 
 	bas = &sc->sc_bas;
@@ -389,9 +395,10 @@
 	}
 	if (bes & BES_RXA)
 		ipend |= UART_IPEND_RXREADY;
-	SIGCHG(bes & BES_CTS, sc->sc_hwsig, UART_SIG_CTS, UART_SIG_DCTS);
-	SIGCHG(bes & BES_DCD, sc->sc_hwsig, UART_SIG_DCD, UART_SIG_DDCD);
-	if (sc->sc_hwsig & UART_SIGMASK_DELTA)
+	sig = sc->sc_hwsig;
+	SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
+	SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
+	if (sig & UART_SIGMASK_DELTA)
 		ipend |= UART_IPEND_SIGCHG;
 	src = uart_getmreg(bas, RR_SRC);
 	if (src & SRC_OVR) {
@@ -461,21 +468,27 @@
 {
 	struct z8530_softc *z8530 = (struct z8530_softc*)sc;
 	struct uart_bas *bas;
+	uint32_t new, old;
 
 	bas = &sc->sc_bas;
-	if (sig & UART_SIG_DDTR) {
-		SIGCHG(sig & UART_SIG_DTR, sc->sc_hwsig, UART_SIG_DTR,
-		    UART_SIG_DDTR);
-	}
-	if (sig & UART_SIG_DRTS) {
-		SIGCHG(sig & UART_SIG_RTS, sc->sc_hwsig, UART_SIG_RTS,
-		    UART_SIG_DRTS);
-	}
-	if (sc->sc_hwsig & UART_SIG_DTR)
+	do {
+		old = sc->sc_hwsig;
+		new = old;
+		if (sig & UART_SIG_DDTR) {
+			SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR,
+			    UART_SIG_DDTR);
+		}
+		if (sig & UART_SIG_DRTS) {
+			SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS,
+			    UART_SIG_DRTS);
+		}
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+
+	if (new & UART_SIG_DTR)
 		z8530->tpc |= TPC_DTR;
 	else
 		z8530->tpc &= ~TPC_DTR;
-	if (sc->sc_hwsig & UART_SIG_RTS)
+	if (new & UART_SIG_RTS)
 		z8530->tpc |= TPC_RTS;
 	else
 		z8530->tpc &= ~TPC_RTS;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309050142.h851g9Pl068369>