Module Name: src Committed By: ryo Date: Tue May 28 05:08:47 UTC 2019
Modified Files: src/sys/arch/arm/amlogic: meson_uart.c Log Message: - since ttyinput (t_linesw->l_rint) should not be called from interrupt context, it has been modified to use softint like other serial drivers. - add spinlock for interrupt. ok jmcneill@. thanks To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/amlogic/meson_uart.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/arch/arm/amlogic/meson_uart.c diff -u src/sys/arch/arm/amlogic/meson_uart.c:1.2 src/sys/arch/arm/amlogic/meson_uart.c:1.3 --- src/sys/arch/arm/amlogic/meson_uart.c:1.2 Sun Jan 20 15:56:40 2019 +++ src/sys/arch/arm/amlogic/meson_uart.c Tue May 28 05:08:47 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: meson_uart.c,v 1.2 2019/01/20 15:56:40 jmcneill Exp $ */ +/* $NetBSD: meson_uart.c,v 1.3 2019/05/28 05:08:47 ryo Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: meson_uart.c,v 1.2 2019/01/20 15:56:40 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: meson_uart.c,v 1.3 2019/05/28 05:08:47 ryo Exp $"); #define cn_trap() \ do { \ @@ -64,6 +64,7 @@ static int meson_uart_match(device_t, cf static void meson_uart_attach(device_t, device_t, void *); static int meson_uart_intr(void *); +static void meson_uart_rxsoft(void *); static int meson_uart_cngetc(dev_t); static void meson_uart_cnputc(dev_t, int); @@ -86,14 +87,20 @@ struct meson_uart_softc { device_t sc_dev; bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; + kmutex_t sc_intr_lock; void *sc_ih; + void *sc_sih; struct tty *sc_tty; int sc_ospeed; + unsigned int sc_rbuf_w; /* write ptr of sc_rbuf[] */ + unsigned int sc_rbuf_r; /* read ptr of sc_rbuf[] */ tcflag_t sc_cflag; u_char sc_buf[1024]; +#define MESON_RBUFSZ 128 /* must be 2^n */ + u_char sc_rbuf[MESON_RBUFSZ]; /* good enough for sizeof RXFIFO */ }; static int meson_uart_console_phandle = -1; @@ -179,6 +186,7 @@ meson_uart_attach(device_t parent, devic return; } + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL); sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_SERIAL, FDT_INTR_MPSAFE, meson_uart_intr, sc); if (sc->sc_ih == NULL) { @@ -187,6 +195,12 @@ meson_uart_attach(device_t parent, devic return; } + sc->sc_sih = softint_establish(SOFTINT_SERIAL, meson_uart_rxsoft, sc); + if (sc->sc_sih == NULL) { + aprint_error(": failed to establish softint\n"); + return; + } + if (meson_uart_cmajor == -1) { /* allocate a major number */ int bmajor = -1, cmajor = -1; @@ -450,6 +464,7 @@ meson_uart_intr(void *priv) struct tty *tp = sc->sc_tty; uint32_t status, c; + mutex_spin_enter(&sc->sc_intr_lock); for (;;) { int cn_trapped = 0; status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, @@ -468,12 +483,33 @@ meson_uart_intr(void *priv) cn_check_magic(tp->t_dev, c & 0xff, meson_uart_cnm_state); if (cn_trapped) continue; - tp->t_linesw->l_rint(c & 0xff, tp); + + if ((sc->sc_rbuf_w - sc->sc_rbuf_r) >= (MESON_RBUFSZ - 1)) + continue; + sc->sc_rbuf[sc->sc_rbuf_w++ & (MESON_RBUFSZ - 1)] = c; } + mutex_spin_exit(&sc->sc_intr_lock); + + if (sc->sc_rbuf_w != sc->sc_rbuf_r) + softint_schedule(sc->sc_sih); return 0; } +static void +meson_uart_rxsoft(void *priv) +{ + struct meson_uart_softc *sc = priv; + struct tty *tp = sc->sc_tty; + int c; + + while (sc->sc_rbuf_w != sc->sc_rbuf_r) { + c = sc->sc_rbuf[sc->sc_rbuf_r++ & (MESON_RBUFSZ - 1)]; + if (tp->t_linesw->l_rint(c & 0xff, tp) == -1) + break; + } +} + static int meson_uart_console_match(int phandle) {