serial console vs suspend
Ian Lepore
ian at freebsd.org
Thu May 17 13:26:05 UTC 2018
On Thu, 2018-05-17 at 10:54 +0300, Andriy Gapon wrote:
>
> It seems that the serial console, or rather a UART used by it, may require
> re-initialization after waking up (from suspend to RAM). At least one of my
> systems fails to wake up properly if I configure the serial console. I've done
> some experimenting with cu (and without the console) and the UART seems to be in
> some weird state, it echoes back the input and does not send anything on the
> wire. I guess that trying to print to the serial console while the UART is in
> that state results in a hang.
>
> To test the theory I made this hack and it does help:
> Index: sys/dev/uart/uart_tty.c
> ===================================================================
> --- sys/dev/uart/uart_tty.c (revision 333667)
> +++ sys/dev/uart/uart_tty.c (working copy)
> @@ -114,6 +114,13 @@ uart_cninit(struct consdev *cp)
> uart_init(di);
> }
>
> +void uart_resume(void);
> +void
> +uart_resume(void)
> +{
> + uart_init(&uart_console);
> +}
> +
> static void
> uart_cnterm(struct consdev *cp)
> {
> Index: sys/x86/acpica/acpi_wakeup.c
> ===================================================================
> --- sys/x86/acpica/acpi_wakeup.c (revision 333667)
> +++ sys/x86/acpica/acpi_wakeup.c (working copy)
> @@ -204,6 +205,8 @@ acpi_wakeup_cpus(struct acpi_softc *sc)
> }
> #endif
>
> +extern void uart_resume(void);
> +
> int
> acpi_sleep_machdep(struct acpi_softc *sc, int state)
> {
> @@ -300,6 +303,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int stat
> #else
> npxresume(susppcbs[0]->sp_fpususpend);
> #endif
> + uart_resume();
> }
>
> return (1); /* wakeup successfully */
>
>
> ===================================================================
>
> This is quick and dirty, of course.
> I think that this should go through the console layer.
> And, obviously, not all consoles actually need such a reinit.
>
> So, maybe:
> cnresume()
> {
> for each console {
> if cn->cn_ops->cn_resume != NULL
> cn->cn_ops->cn_resume(cn)
> }
> }
>
> uart_resume(struct consdev *cp)
> {
> uart_init(cp->cn_arg);
> }
>
> What do you think?
>
> Hmm, it looks like CONSOLE_DRIVER() does not allow to omit a console method.
> So, will I have to add a dummy resume to all console drivers?
Why should it go through the console layer? If the uart hardware needs
some re-init on resume, won't that be true whether the uart is serving
as a console, a dial-in terminal, or the interface to wifi or bluetooth
chip?
-- Ian
More information about the freebsd-current
mailing list