[SERIAL] sunzilog: Register IRQ after all devices have been probed.

Otherwise we will deref half-initialized channel pointers
and crash in the interrupt handler.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2006-07-17 21:07:17 -07:00
parent 3932932956
commit 67e23a1e60
1 changed files with 35 additions and 11 deletions

View File

@ -1336,12 +1336,11 @@ static int __devinit zs_get_instance(struct device_node *dp)
static int zilog_irq = -1; static int zilog_irq = -1;
static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match) static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
{ {
struct of_device *op = to_of_device(&dev->dev);
struct uart_sunzilog_port *up; struct uart_sunzilog_port *up;
struct zilog_layout __iomem *rp; struct zilog_layout __iomem *rp;
int inst = zs_get_instance(dev->node); int inst = zs_get_instance(op->node);
int err; int err;
sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
@ -1413,7 +1412,7 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
} }
} }
dev_set_drvdata(&dev->dev, &up[0]); dev_set_drvdata(&op->dev, &up[0]);
return 0; return 0;
} }
@ -1462,18 +1461,19 @@ static struct of_platform_driver zs_driver = {
static int __init sunzilog_init(void) static int __init sunzilog_init(void)
{ {
struct device_node *dp; struct device_node *dp;
int err; int err, uart_count;
NUM_SUNZILOG = 0; NUM_SUNZILOG = 0;
for_each_node_by_name(dp, "zs") for_each_node_by_name(dp, "zs")
NUM_SUNZILOG++; NUM_SUNZILOG++;
uart_count = 0;
if (NUM_SUNZILOG) { if (NUM_SUNZILOG) {
int uart_count; int uart_count;
err = sunzilog_alloc_tables(); err = sunzilog_alloc_tables();
if (err) if (err)
return err; goto out;
/* Subtract 1 for keyboard, 1 for mouse. */ /* Subtract 1 for keyboard, 1 for mouse. */
uart_count = (NUM_SUNZILOG * 2) - 2; uart_count = (NUM_SUNZILOG * 2) - 2;
@ -1481,17 +1481,41 @@ static int __init sunzilog_init(void)
sunzilog_reg.nr = uart_count; sunzilog_reg.nr = uart_count;
sunzilog_reg.minor = sunserial_current_minor; sunzilog_reg.minor = sunserial_current_minor;
err = uart_register_driver(&sunzilog_reg); err = uart_register_driver(&sunzilog_reg);
if (err) { if (err)
sunzilog_free_tables(); goto out_free_tables;
return err;
}
sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
sunzilog_reg.cons = SUNZILOG_CONSOLE(); sunzilog_reg.cons = SUNZILOG_CONSOLE();
sunserial_current_minor += uart_count; sunserial_current_minor += uart_count;
} }
return of_register_driver(&zs_driver, &of_bus_type); err = of_register_driver(&zs_driver, &of_bus_type);
if (err)
goto out_unregister_uart;
if (zilog_irq != -1) {
err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
"zs", sunzilog_irq_chain);
if (err)
goto out_unregister_driver;
}
out:
return err;
out_unregister_driver:
of_unregister_driver(&zs_driver);
out_unregister_uart:
if (NUM_SUNZILOG) {
uart_unregister_driver(&sunzilog_reg);
sunzilog_reg.cons = NULL;
}
out_free_tables:
sunzilog_free_tables();
goto out;
} }
static void __exit sunzilog_exit(void) static void __exit sunzilog_exit(void)