Commit 4e8688b2 authored by David Eger's avatar David Eger Committed by Linus Torvalds

[PATCH] pmac_zilog: serial minors taken failure path fix

I've tracked down the core issue giving me the oops wrt pmac_zilog.

When you have two serial drivers, (e.g. 8250 and PMAC_ZILOG) they both say

"I want to reserve X ports starting with major TTY_MAJOR and minor 64".

By the time pmac_zilog gets there, the ports it requests are already
reserved.  Unfortunately, init_pmz() doesn't check for pmz_register()
failure, and so it merrily goes on to register the half-initialized
pmac_zilog driver with the power management subsystem.

This path provides a proper failure path.

Also: 

Restore ppc configs now that I know people use AT Keyboards on CHRP and PReP
machines, and the zilog driver is no longer Oops'ing.
Signed-off-by: default avatarDavid Eger <eger@havoc.gtf.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d96a9bf5
......@@ -689,7 +689,7 @@ CONFIG_SERIO_SERPORT=y
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
......@@ -724,8 +724,8 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_CORE is not set
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_PMACZILOG=y
# CONFIG_SERIAL_PMACZILOG_CONSOLE is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
......
......@@ -1433,6 +1433,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
ioremap(np->addrs[np->n_addrs - 1].address, 0x1000);
if (uap->rx_dma_regs == NULL) {
iounmap((void *)uap->tx_dma_regs);
uap->tx_dma_regs = NULL;
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
goto no_dma;
}
......@@ -1490,7 +1491,6 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
uap->port.ops = &pmz_pops;
uap->port.type = PORT_PMAC_ZILOG;
uap->port.flags = 0;
spin_lock_init(&uap->port.lock);
/* Setup some valid baud rate information in the register
* shadows so we don't write crap there before baud rate is
......@@ -1508,10 +1508,13 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
{
struct device_node *np;
iounmap((void *)uap->control_reg);
np = uap->node;
iounmap((void *)uap->rx_dma_regs);
iounmap((void *)uap->tx_dma_regs);
iounmap((void *)uap->control_reg);
uap->node = NULL;
of_node_put(np);
memset(uap, 0, sizeof(struct uart_pmac_port));
}
/*
......@@ -1798,7 +1801,7 @@ static int __init pmz_register(void)
* Register this driver with the serial core
*/
rc = uart_register_driver(&pmz_uart_reg);
if (rc != 0)
if (rc)
return rc;
/*
......@@ -1808,10 +1811,19 @@ static int __init pmz_register(void)
struct uart_pmac_port *uport = &pmz_ports[i];
/* NULL node may happen on wallstreet */
if (uport->node != NULL)
uart_add_one_port(&pmz_uart_reg, &uport->port);
rc = uart_add_one_port(&pmz_uart_reg, &uport->port);
if (rc)
goto err_out;
}
return 0;
err_out:
while (i-- > 0) {
struct uart_pmac_port *uport = &pmz_ports[i];
uart_remove_one_port(&pmz_uart_reg, &uport->port);
}
uart_unregister_driver(&pmz_uart_reg);
return rc;
}
static struct of_match pmz_match[] =
......@@ -1841,6 +1853,7 @@ static struct macio_driver pmz_driver =
static int __init init_pmz(void)
{
int rc, i;
printk(KERN_INFO "%s\n", version);
/*
......@@ -1862,7 +1875,16 @@ static int __init init_pmz(void)
/*
* Now we register with the serial layer
*/
pmz_register();
rc = pmz_register();
if (rc) {
printk(KERN_ERR
"pmac_zilog: Error registering serial device, disabling pmac_zilog.\n"
"pmac_zilog: Did another serial driver already claim the minors?\n");
/* effectively "pmz_unprobe()" */
for (i=0; i < pmz_ports_count; i++)
pmz_dispose_port(&pmz_ports[i]);
return rc;
}
/*
* Then we register the macio driver itself
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment