svn commit: r334340 - in head/sys: dev/uart kern sys x86/acpica

Andriy Gapon avg at FreeBSD.org
Tue May 29 16:16:25 UTC 2018


Author: avg
Date: Tue May 29 16:16:24 2018
New Revision: 334340
URL: https://svnweb.freebsd.org/changeset/base/334340

Log:
  add support for console resuming, implement it for uart, use on x86
  
  This change adds a new optional console method cn_resume and a kernel
  console interface cnresume.  Consoles that may need to re-initialize
  their hardware after suspend (e.g., because firmware does not care to do
  it) will implement cn_resume.  Note that it is called in rather early
  environment not unlike early boot, so the same restrictions apply.
  Platform specific code, for platforms that support hardware suspend,
  should call cnresume early after resume, before any console output is
  expected.
  
  This change fixes a problem with a system of mine failing to resume when
  a serial console is used.  I found that the serial port was in a strange
  configuration and an attempt to write to it likely resulted in an
  infinite loop.
  
  To avoid adding cn_resume method to every console driver, CONSOLE_DRIVER
  macro has been extended to support optional methods.
  
  Reviewed by:	imp, mav
  MFC after:	3 weeks
  Differential Revision: https://reviews.freebsd.org/D15552

Modified:
  head/sys/dev/uart/uart_tty.c
  head/sys/kern/kern_cons.c
  head/sys/sys/cons.h
  head/sys/x86/acpica/acpi_wakeup.c

Modified: head/sys/dev/uart/uart_tty.c
==============================================================================
--- head/sys/dev/uart/uart_tty.c	Tue May 29 16:04:53 2018	(r334339)
+++ head/sys/dev/uart/uart_tty.c	Tue May 29 16:16:24 2018	(r334340)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 
 static cn_probe_t uart_cnprobe;
 static cn_init_t uart_cninit;
+static cn_init_t uart_cnresume;
 static cn_term_t uart_cnterm;
 static cn_getc_t uart_cngetc;
 static cn_putc_t uart_cnputc;
@@ -69,7 +70,10 @@ static tsw_modem_t uart_tty_modem;
 static tsw_free_t uart_tty_free;
 static tsw_busy_t uart_tty_busy;
 
-CONSOLE_DRIVER(uart);
+CONSOLE_DRIVER(
+	uart,
+	.cn_resume = uart_cnresume,
+);
 
 static struct uart_devinfo uart_console;
 
@@ -112,6 +116,13 @@ uart_cninit(struct consdev *cp)
 	di->type = UART_DEV_CONSOLE;
 	uart_add_sysdev(di);
 	uart_init(di);
+}
+
+static void
+uart_cnresume(struct consdev *cp)
+{
+
+	uart_init(cp->cn_arg);
 }
 
 static void

Modified: head/sys/kern/kern_cons.c
==============================================================================
--- head/sys/kern/kern_cons.c	Tue May 29 16:04:53 2018	(r334339)
+++ head/sys/kern/kern_cons.c	Tue May 29 16:16:24 2018	(r334340)
@@ -384,6 +384,19 @@ cnungrab()
 	}
 }
 
+void
+cnresume()
+{
+	struct cn_device *cnd;
+	struct consdev *cn;
+
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
+		cn = cnd->cnd_cn;
+		if (cn->cn_ops->cn_resume != NULL)
+			cn->cn_ops->cn_resume(cn);
+	}
+}
+
 /*
  * Low level console routines.
  */

Modified: head/sys/sys/cons.h
==============================================================================
--- head/sys/sys/cons.h	Tue May 29 16:04:53 2018	(r334339)
+++ head/sys/sys/cons.h	Tue May 29 16:16:24 2018	(r334340)
@@ -66,6 +66,8 @@ struct consdev_ops {
 				/* grab console for exclusive kernel use */
 	cn_ungrab_t	*cn_ungrab;
 				/* ungrab console */
+	cn_init_t	*cn_resume;
+				/* set up console after sleep, optional */
 };
 
 struct consdev {
@@ -105,8 +107,9 @@ extern	struct tty *constty;	/* Temporary virtual conso
 	};								\
 	DATA_SET(cons_set, name)
 
-#define	CONSOLE_DRIVER(name)						\
+#define	CONSOLE_DRIVER(name, ...)					\
 	static const struct consdev_ops name##_consdev_ops = {		\
+		/* Mandatory methods. */				\
 		.cn_probe = name##_cnprobe,				\
 		.cn_init = name##_cninit,				\
 		.cn_term = name##_cnterm,				\
@@ -114,6 +117,8 @@ extern	struct tty *constty;	/* Temporary virtual conso
 		.cn_putc = name##_cnputc,				\
 		.cn_grab = name##_cngrab,				\
 		.cn_ungrab = name##_cnungrab,				\
+		/* Optional fields. */					\
+		__VA_ARGS__						\
 	};								\
 	CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL)
 
@@ -126,6 +131,7 @@ void	cnremove(struct consdev *);
 void	cnselect(struct consdev *);
 void	cngrab(void);
 void	cnungrab(void);
+void	cnresume(void);
 int	cncheckc(void);
 int	cngetc(void);
 void	cngets(char *, size_t, int);

Modified: head/sys/x86/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/x86/acpica/acpi_wakeup.c	Tue May 29 16:04:53 2018	(r334339)
+++ head/sys/x86/acpica/acpi_wakeup.c	Tue May 29 16:16:24 2018	(r334340)
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/memrange.h>
 #include <sys/smp.h>
 #include <sys/systm.h>
+#include <sys/cons.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -296,6 +297,12 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
 		for (;;)
 			ia32_pause();
 	} else {
+		/*
+		 * Re-initialize console hardware as soon as possibe.
+		 * No console output (e.g. printf) is allowed before
+		 * this point.
+		 */
+		cnresume();
 #ifdef __amd64__
 		fpuresume(susppcbs[0]->sp_fpususpend);
 #else


More information about the svn-src-all mailing list