aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-07-18 00:07:17 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-21 17:18:08 -0400
commit67e23a1e60b6bc0a090407d0fc060166ab558b72 (patch)
treea690bed9a849ba177b046e76cb85f3209650ae55
parent39329329565a5e24f0a5523eef3a9dd941e0b29d (diff)
[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>
-rw-r--r--drivers/serial/sunzilog.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index a1456d9352cb..496810c50947 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1336,12 +1336,11 @@ static int __devinit zs_get_instance(struct device_node *dp)
1336 1336
1337static int zilog_irq = -1; 1337static int zilog_irq = -1;
1338 1338
1339static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match) 1339static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
1340{ 1340{
1341 struct of_device *op = to_of_device(&dev->dev);
1342 struct uart_sunzilog_port *up; 1341 struct uart_sunzilog_port *up;
1343 struct zilog_layout __iomem *rp; 1342 struct zilog_layout __iomem *rp;
1344 int inst = zs_get_instance(dev->node); 1343 int inst = zs_get_instance(op->node);
1345 int err; 1344 int err;
1346 1345
1347 sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, 1346 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 *
1413 } 1412 }
1414 } 1413 }
1415 1414
1416 dev_set_drvdata(&dev->dev, &up[0]); 1415 dev_set_drvdata(&op->dev, &up[0]);
1417 1416
1418 return 0; 1417 return 0;
1419} 1418}
@@ -1462,18 +1461,19 @@ static struct of_platform_driver zs_driver = {
1462static int __init sunzilog_init(void) 1461static int __init sunzilog_init(void)
1463{ 1462{
1464 struct device_node *dp; 1463 struct device_node *dp;
1465 int err; 1464 int err, uart_count;
1466 1465
1467 NUM_SUNZILOG = 0; 1466 NUM_SUNZILOG = 0;
1468 for_each_node_by_name(dp, "zs") 1467 for_each_node_by_name(dp, "zs")
1469 NUM_SUNZILOG++; 1468 NUM_SUNZILOG++;
1470 1469
1470 uart_count = 0;
1471 if (NUM_SUNZILOG) { 1471 if (NUM_SUNZILOG) {
1472 int uart_count; 1472 int uart_count;
1473 1473
1474 err = sunzilog_alloc_tables(); 1474 err = sunzilog_alloc_tables();
1475 if (err) 1475 if (err)
1476 return err; 1476 goto out;
1477 1477
1478 /* Subtract 1 for keyboard, 1 for mouse. */ 1478 /* Subtract 1 for keyboard, 1 for mouse. */
1479 uart_count = (NUM_SUNZILOG * 2) - 2; 1479 uart_count = (NUM_SUNZILOG * 2) - 2;
@@ -1481,17 +1481,41 @@ static int __init sunzilog_init(void)
1481 sunzilog_reg.nr = uart_count; 1481 sunzilog_reg.nr = uart_count;
1482 sunzilog_reg.minor = sunserial_current_minor; 1482 sunzilog_reg.minor = sunserial_current_minor;
1483 err = uart_register_driver(&sunzilog_reg); 1483 err = uart_register_driver(&sunzilog_reg);
1484 if (err) { 1484 if (err)
1485 sunzilog_free_tables(); 1485 goto out_free_tables;
1486 return err; 1486
1487 }
1488 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; 1487 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
1489 sunzilog_reg.cons = SUNZILOG_CONSOLE(); 1488 sunzilog_reg.cons = SUNZILOG_CONSOLE();
1490 1489
1491 sunserial_current_minor += uart_count; 1490 sunserial_current_minor += uart_count;
1492 } 1491 }
1493 1492
1494 return of_register_driver(&zs_driver, &of_bus_type); 1493 err = of_register_driver(&zs_driver, &of_bus_type);
1494 if (err)
1495 goto out_unregister_uart;
1496
1497 if (zilog_irq != -1) {
1498 err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
1499 "zs", sunzilog_irq_chain);
1500 if (err)
1501 goto out_unregister_driver;
1502 }
1503
1504out:
1505 return err;
1506
1507out_unregister_driver:
1508 of_unregister_driver(&zs_driver);
1509
1510out_unregister_uart:
1511 if (NUM_SUNZILOG) {
1512 uart_unregister_driver(&sunzilog_reg);
1513 sunzilog_reg.cons = NULL;
1514 }
1515
1516out_free_tables:
1517 sunzilog_free_tables();
1518 goto out;
1495} 1519}
1496 1520
1497static void __exit sunzilog_exit(void) 1521static void __exit sunzilog_exit(void)