diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-11 10:03:33 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-11 10:03:33 +0000 |
commit | 8399dd5e9deda4c73ca24f242031680bf9977a75 (patch) | |
tree | d0e54ea80bb6a2201d4f805fffd7df9812b3b0c9 /sys/dev | |
parent | 870304c2d5d169c1431ad97e72ebdfc8b81f6e98 (diff) |
Fix an issue where output gets stuck when a machine is under load. Also
make sure Tx interrupts are counted.
ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/pluart.c | 49 |
1 files changed, 18 insertions, 31 deletions
diff --git a/sys/dev/ic/pluart.c b/sys/dev/ic/pluart.c index d21f386374e..c427b52e3b4 100644 --- a/sys/dev/ic/pluart.c +++ b/sys/dev/ic/pluart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pluart.c,v 1.3 2019/07/19 00:17:15 cheloha Exp $ */ +/* $OpenBSD: pluart.c,v 1.4 2019/08/11 10:03:32 kettenis Exp $ */ /* * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> * Copyright (c) 2005 Dale Rahn <drahn@dalerahn.com> @@ -188,26 +188,26 @@ pluart_intr(void *arg) bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp = sc->sc_tty; - u_int16_t fr; + u_int16_t is; u_int16_t *p; u_int16_t c; - bus_space_write_4(iot, ioh, UART_ICR, -1); + is = bus_space_read_4(iot, ioh, UART_RIS); + bus_space_write_4(iot, ioh, UART_ICR, is); if (sc->sc_tty == NULL) - return(0); + return 0; - fr = bus_space_read_4(iot, ioh, UART_FR); - if (ISSET(fr, UART_FR_TXFE) && ISSET(tp->t_state, TS_BUSY)) { + if (!ISSET(is, UART_IMSC_RXIM) && !ISSET(is, UART_IMSC_TXIM)) + return 0; + + if (ISSET(is, UART_IMSC_TXIM) && ISSET(tp->t_state, TS_BUSY)) { CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (sc->sc_halt > 0) wakeup(&tp->t_outq); (*linesw[tp->t_line].l_start)(tp); } - if(!ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) - return 0; - p = sc->sc_ibufp; while (ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) { @@ -326,35 +326,22 @@ pluart_start(struct tty *tp) struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; - + u_int16_t fr; int s; + s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) goto out; - if (tp->t_outq.c_cc <= tp->t_lowat) { - if (ISSET(tp->t_state, TS_ASLEEP)) { - CLR(tp->t_state, TS_ASLEEP); - wakeup(&tp->t_outq); - } - if (tp->t_outq.c_cc == 0) - goto out; - selwakeup(&tp->t_wsel); - } + ttwakeupwr(tp); + if (tp->t_outq.c_cc == 0) + goto out; SET(tp->t_state, TS_BUSY); - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { - u_char buffer[64]; /* largest fifo */ - int i, n; - - n = q_to_b(&tp->t_outq, buffer, - min(sc->sc_fifolen, sizeof buffer)); - for (i = 0; i < n; i++) { - bus_space_write_4(iot, ioh, UART_DR, buffer[i]); - } - bzero(buffer, n); - } else if (tp->t_outq.c_cc != 0) + fr = bus_space_read_4(iot, ioh, UART_FR); + while (tp->t_outq.c_cc != 0 && ISSET(fr, UART_FR_TXFE)) { bus_space_write_4(iot, ioh, UART_DR, getc(&tp->t_outq)); - + fr = bus_space_read_4(iot, ioh, UART_FR); + } out: splx(s); } |