Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jul 2015 03:06:12 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r286061 - releng/10.2/sys/dev/uart
Message-ID:  <201507300306.t6U36Cpe088818@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Thu Jul 30 03:06:11 2015
New Revision: 286061
URL: https://svnweb.freebsd.org/changeset/base/286061

Log:
  MFC: r285843 (r286059 in stable/10)
  
  - Since r253161, uart_intr() abuses FILTER_SCHEDULE_THREAD for signaling
    uart_bus_attach() during its test that 20 iterations weren't sufficient
    for clearing all pending interrupts, assuming this means that hardware
    is broken and doesn't deassert interrupts. However, under pressure, 20
    iterations also can be insufficient for clearing all pending interrupts,
    leading to a panic as intr_event_handle() tries to schedule an interrupt
    handler not registered. Solve this by introducing a flag that is set in
    test mode and otherwise restores pre-r253161 behavior of uart_intr(). The
    approach of additionally registering uart_intr() as handler as suggested
    in PR 194979 is not taken as that in turn would abuse special pccard and
    pccbb handling code of intr_event_handle(). [1]
  - Const'ify uart_driver_name.
  - Fix some minor style bugs.
  
  PR:		194979 [1]
  Reviewed by:	marcel (earlier version)
  Approved by:	re (gjb)

Modified:
  releng/10.2/sys/dev/uart/uart_bus.h
  releng/10.2/sys/dev/uart/uart_core.c
Directory Properties:
  releng/10.2/   (props changed)

Modified: releng/10.2/sys/dev/uart/uart_bus.h
==============================================================================
--- releng/10.2/sys/dev/uart/uart_bus.h	Thu Jul 30 02:45:35 2015	(r286060)
+++ releng/10.2/sys/dev/uart/uart_bus.h	Thu Jul 30 03:06:11 2015	(r286061)
@@ -98,6 +98,7 @@ struct uart_softc {
 	int		sc_polled:1;	/* This UART has no interrupts. */
 	int		sc_txbusy:1;	/* This UART is transmitting. */
 	int		sc_isquelch:1;	/* This UART has input squelched. */
+	int		sc_testintr:1;	/* This UART is under int. testing. */
 
 	struct uart_devinfo *sc_sysdev;	/* System device (or NULL). */
 
@@ -134,7 +135,7 @@ struct uart_softc {
 };
 
 extern devclass_t uart_devclass;
-extern char uart_driver_name[];
+extern const char uart_driver_name[];
 
 int uart_bus_attach(device_t dev);
 int uart_bus_detach(device_t dev);
@@ -156,14 +157,16 @@ void uart_tty_intr(void *arg);
 static __inline int
 uart_rx_empty(struct uart_softc *sc)
 {
+
 	return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0);
 }
 
 static __inline int
 uart_rx_full(struct uart_softc *sc)
 {
-	return ((sc->sc_rxput + 1 < sc->sc_rxbufsz)
-	    ? (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0));
+
+	return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ?
+	    (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0));
 }
 
 static __inline int

Modified: releng/10.2/sys/dev/uart/uart_core.c
==============================================================================
--- releng/10.2/sys/dev/uart/uart_core.c	Thu Jul 30 02:45:35 2015	(r286060)
+++ releng/10.2/sys/dev/uart/uart_core.c	Thu Jul 30 03:06:11 2015	(r286061)
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
 #include "uart_if.h"
 
 devclass_t uart_devclass;
-char uart_driver_name[] = "uart";
+const char uart_driver_name[] = "uart";
 
 SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs =
     SLIST_HEAD_INITIALIZER(uart_sysdevs);
@@ -248,13 +248,14 @@ static int
 uart_intr(void *arg)
 {
 	struct uart_softc *sc = arg;
-	int cnt, ipend;
+	int cnt, ipend, testintr;
 
 	if (sc->sc_leaving)
 		return (FILTER_STRAY);
 
 	cnt = 0;
-	while (cnt < 20 && (ipend = UART_IPEND(sc)) != 0) {
+	testintr = sc->sc_testintr;
+	while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) {
 		cnt++;
 		if (ipend & SER_INT_OVERRUN)
 			uart_intr_overrun(sc);
@@ -265,7 +266,7 @@ uart_intr(void *arg)
 		if (ipend & SER_INT_SIGCHG)
 			uart_intr_sigchg(sc);
 		if (ipend & SER_INT_TXIDLE)
-			uart_intr_txidle(sc);		
+			uart_intr_txidle(sc);
 	}
 
 	if (sc->sc_polled) {
@@ -274,7 +275,8 @@ uart_intr(void *arg)
 	}
 
 	return ((cnt == 0) ? FILTER_STRAY :
-	    ((cnt == 20) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED));
+	    ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD :
+	    FILTER_HANDLED));
 }
 
 serdev_intr_t *
@@ -421,7 +423,7 @@ uart_bus_attach(device_t dev)
 	/*
 	 * Protect ourselves against interrupts while we're not completely
 	 * finished attaching and initializing. We don't expect interrupts
-	 * until after UART_ATTACH() though.
+	 * until after UART_ATTACH(), though.
 	 */
 	sc->sc_leaving = 1;
 
@@ -501,7 +503,9 @@ uart_bus_attach(device_t dev)
 	pps_init(&sc->sc_pps);
 
 	sc->sc_leaving = 0;
+	sc->sc_testintr = 1;
 	filt = uart_intr(sc);
+	sc->sc_testintr = 0;
 
 	/*
 	 * Don't use interrupts if we couldn't clear any pending interrupt



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