svn commit: r246016 - head/sys/dev/uart

Colin Percival cperciva at FreeBSD.org
Sun Jan 27 23:33:43 UTC 2013


Author: cperciva
Date: Sun Jan 27 23:33:42 2013
New Revision: 246016
URL: http://svnweb.freebsd.org/changeset/base/246016

Log:
  Add a loader tunable "hw.broken_txfifo" which enables a workaround for a
  bug in old versions of QEMU (and Xen, and other places using QEMU code).
  On those buggy emulated UARTs, the "TX idle" interrupt gets lost; with
  this workaround, we spinwait for the TX to happen and then send ourselves
  the interrupt.  It's ugly but it works, while minimizing the impact on
  the code for the !broken_txfifo case.
  
  MFC after:	2 weeks

Modified:
  head/sys/dev/uart/uart_dev_ns8250.c

Modified: head/sys/dev/uart/uart_dev_ns8250.c
==============================================================================
--- head/sys/dev/uart/uart_dev_ns8250.c	Sun Jan 27 23:21:51 2013	(r246015)
+++ head/sys/dev/uart/uart_dev_ns8250.c	Sun Jan 27 23:33:42 2013	(r246016)
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
 #include <machine/bus.h>
 
 #include <dev/uart/uart.h>
@@ -845,6 +847,11 @@ ns8250_bus_setsig(struct uart_softc *sc,
 	return (0);
 }
 
+static int broken_txfifo = 0;
+SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
+	&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
+TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
+
 static int
 ns8250_bus_transmit(struct uart_softc *sc)
 {
@@ -862,7 +869,12 @@ ns8250_bus_transmit(struct uart_softc *s
 		uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
 		uart_barrier(bas);
 	}
-	sc->sc_txbusy = 1;
+	if (broken_txfifo)
+		ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+	else
+		sc->sc_txbusy = 1;
 	uart_unlock(sc->sc_hwmtx);
+	if (broken_txfifo)
+		uart_sched_softih(sc, SER_INT_TXIDLE);
 	return (0);
 }


More information about the svn-src-all mailing list