Module Name: src
Committed By: knakahara
Date: Thu Dec 8 09:08:49 UTC 2022
Modified Files:
src/sys/dev/ic: com.c
Log Message:
Fix hang up writing /dev/console rarely in specific environments.
Some BMC seems to require these syncronous operations. If not,
it does not send transmit completion interrupts for some reason.
To generate a diff of this commit:
cvs rdiff -u -r1.380 -r1.381 src/sys/dev/ic/com.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/com.c
diff -u src/sys/dev/ic/com.c:1.380 src/sys/dev/ic/com.c:1.381
--- src/sys/dev/ic/com.c:1.380 Sat Dec 3 11:28:38 2022
+++ src/sys/dev/ic/com.c Thu Dec 8 09:08:49 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: com.c,v 1.380 2022/12/03 11:28:38 skrll Exp $ */
+/* $NetBSD: com.c,v 1.381 2022/12/08 09:08:49 knakahara Exp $ */
/*-
* Copyright (c) 1998, 1999, 2004, 2008 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.380 2022/12/03 11:28:38 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.381 2022/12/08 09:08:49 knakahara Exp $");
#include "opt_com.h"
#include "opt_ddb.h"
@@ -206,6 +206,28 @@ static struct consdev comcons = {
.cn_pri = CN_NORMAL
};
+#define CSR_WRITE_1_SYNC(r, o, v) do { \
+ CSR_WRITE_1(r, o, v); \
+ switch(o) { \
+ case COM_REG_IER: \
+ (void)CSR_READ_1(r, COM_REG_IIR); \
+ break; \
+ case COM_REG_TXDATA: \
+ (void)CSR_READ_1(r, COM_REG_TLR); \
+ break; \
+ } \
+ } while(0)
+#define CSR_WRITE_MULTI_SYNC(r, o, p, n) do { \
+ CSR_WRITE_MULTI(r, o, p, n); \
+ switch(o) { \
+ case COM_REG_IER: \
+ (void)CSR_READ_1(r, COM_REG_IIR); \
+ break; \
+ case COM_REG_TXDATA: \
+ (void)CSR_READ_1(r, COM_REG_TLR); \
+ break; \
+ } \
+ } while(0)
const struct cdevsw com_cdevsw = {
.d_open = comopen,
@@ -1961,7 +1983,7 @@ comstart(struct tty *tp)
/* Enable transmit completion interrupts if necessary. */
if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
SET(sc->sc_ier, IER_ETXRDY);
- CSR_WRITE_1(regsp, COM_REG_IER, sc->sc_ier);
+ CSR_WRITE_1_SYNC(regsp, COM_REG_IER, sc->sc_ier);
}
/* Output the first chunk of the contiguous buffer. */
@@ -1971,7 +1993,7 @@ comstart(struct tty *tp)
n = sc->sc_tbc;
if (n > sc->sc_fifolen)
n = sc->sc_fifolen;
- CSR_WRITE_MULTI(regsp, COM_REG_TXDATA, sc->sc_tba, n);
+ CSR_WRITE_MULTI_SYNC(regsp, COM_REG_TXDATA, sc->sc_tba, n);
sc->sc_tbc -= n;
sc->sc_tba += n;
}
@@ -2359,7 +2381,7 @@ again: do {
CLR(sc->sc_ier, IER_ERXRDY);
break;
}
- CSR_WRITE_1(regsp, COM_REG_IER, sc->sc_ier);
+ CSR_WRITE_1_SYNC(regsp, COM_REG_IER, sc->sc_ier);
}
} else {
if ((iir & (IIR_RXRDY|IIR_TXRDY)) == IIR_RXRDY) {
@@ -2443,14 +2465,14 @@ do_tx:
n = sc->sc_tbc;
if (n > sc->sc_fifolen)
n = sc->sc_fifolen;
- CSR_WRITE_MULTI(regsp, COM_REG_TXDATA, sc->sc_tba, n);
+ CSR_WRITE_MULTI_SYNC(regsp, COM_REG_TXDATA, sc->sc_tba, n);
sc->sc_tbc -= n;
sc->sc_tba += n;
} else {
/* Disable transmit completion interrupts if necessary. */
if (ISSET(sc->sc_ier, IER_ETXRDY)) {
CLR(sc->sc_ier, IER_ETXRDY);
- CSR_WRITE_1(regsp, COM_REG_IER, sc->sc_ier);
+ CSR_WRITE_1_SYNC(regsp, COM_REG_IER, sc->sc_ier);
}
if (sc->sc_tx_busy) {
sc->sc_tx_busy = 0;