Skip to content

Commit c57f1ec

Browse files
maciej-w-rozyckigregkh
authored andcommitted
serial: dz: Fix bootconsole handover lockup
commit 7f127b2 upstream. Calling dz_reset() in the course of setting up the serial device causes line parameters to be reset and the transmitter disabled. We've been lucky in that no message is usually produced to the kernel log between this call and the later call to uart_set_options() in the course of console setup done by dz_serial_console_init(), or the system would hang as the console output handler in the firmware tried to access a port the transmitter of which has been disabled and line parameters messed up. This will change with the next change to the driver, so fix dz_reset() such that line parameters are set for 9600n8 console operation as with the system firmware and the transmitter re-enabled after reset. This also means dz_pm() serves no purpose anymore, so drop it. Fixes: e6ee512 ("dz.c: Resource management") Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk> Cc: stable@vger.kernel.org # v2.6.25+ Link: https://patch.msgid.link/alpine.DEB.2.21.2605062302010.46195@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 60d725a commit c57f1ec

1 file changed

Lines changed: 12 additions & 24 deletions

File tree

  • drivers/tty/serial

drivers/tty/serial/dz.c

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,18 @@ static void dz_reset(struct dz_port *dport)
571571
while (dz_in(dport, DZ_CSR) & DZ_CLR);
572572
iob();
573573

574+
/*
575+
* Set parameters across all lines such as not to interfere
576+
* with the initial PROM-based console. Otherwise any output
577+
* produced before the console handover would cause the system
578+
* firmware to produce rubbish.
579+
*/
580+
for (int line = 0; line < DZ_NB_PORT; line++)
581+
dz_out(dport, DZ_LPR, DZ_B9600 | DZ_CS8 | line);
582+
583+
/* Re-enable transmission for the initial PROM-based console. */
584+
dz_out(dport, DZ_TCR, tcr);
585+
574586
/* Enable scanning. */
575587
dz_out(dport, DZ_CSR, DZ_MSE);
576588

@@ -654,26 +666,6 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
654666
uart_port_unlock_irqrestore(&dport->port, flags);
655667
}
656668

657-
/*
658-
* Hack alert!
659-
* Required solely so that the initial PROM-based console
660-
* works undisturbed in parallel with this one.
661-
*/
662-
static void dz_pm(struct uart_port *uport, unsigned int state,
663-
unsigned int oldstate)
664-
{
665-
struct dz_port *dport = to_dport(uport);
666-
unsigned long flags;
667-
668-
uart_port_lock_irqsave(&dport->port, &flags);
669-
if (state < 3)
670-
dz_start_tx(&dport->port);
671-
else
672-
dz_stop_tx(&dport->port);
673-
uart_port_unlock_irqrestore(&dport->port, flags);
674-
}
675-
676-
677669
static const char *dz_type(struct uart_port *uport)
678670
{
679671
return "DZ";
@@ -769,7 +761,6 @@ static const struct uart_ops dz_ops = {
769761
.startup = dz_startup,
770762
.shutdown = dz_shutdown,
771763
.set_termios = dz_set_termios,
772-
.pm = dz_pm,
773764
.type = dz_type,
774765
.release_port = dz_release_port,
775766
.request_port = dz_request_port,
@@ -894,10 +885,7 @@ static int __init dz_console_setup(struct console *co, char *options)
894885
if (ret)
895886
return ret;
896887

897-
spin_lock_init(&dport->port.lock); /* For dz_pm(). */
898-
899888
dz_reset(dport);
900-
dz_pm(uport, 0, -1);
901889

902890
if (options)
903891
uart_parse_options(options, &baud, &parity, &bits, &flow);

0 commit comments

Comments
 (0)