aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2006-06-29 18:13:40 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-29 19:37:44 -0400
commit4fa97dcf9d48b02934c60a48873199850351e760 (patch)
treeeac7bda737afe4d723b12d8ae67dfe35d14098a7
parent3676463178401293d625a102a00da0473fa33a1b (diff)
[SERIAL] sunzilog: Fix bugs in device deregristration.
1) Need to unregister 2 ports per of_device. 2) Need to of_iounmap() 1 mapping per of_device. 3) Need to free up the IRQ only after all devices have been unregistered. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/serial/sunzilog.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index cbdf9d605b3f..98342eeba734 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1335,9 +1335,10 @@ static int __devinit zs_get_instance(struct device_node *dp)
1335 return ret; 1335 return ret;
1336} 1336}
1337 1337
1338static int zilog_irq = -1;
1339
1338static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match) 1340static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
1339{ 1341{
1340 static int zilog_irq = -1;
1341 struct of_device *op = to_of_device(&dev->dev); 1342 struct of_device *op = to_of_device(&dev->dev);
1342 struct uart_sunzilog_port *up; 1343 struct uart_sunzilog_port *up;
1343 struct zilog_layout __iomem *rp; 1344 struct zilog_layout __iomem *rp;
@@ -1413,24 +1414,33 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
1413 } 1414 }
1414 } 1415 }
1415 1416
1417 dev_set_drvdata(&dev->dev, &up[0]);
1418
1416 return 0; 1419 return 0;
1417} 1420}
1418 1421
1419static int __devexit zs_remove(struct of_device *dev) 1422static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
1420{ 1423{
1421 struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
1422 struct zilog_channel __iomem *channel;
1423
1424 if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) { 1424 if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
1425#ifdef CONFIG_SERIO 1425#ifdef CONFIG_SERIO
1426 serio_unregister_port(&up->serio); 1426 serio_unregister_port(&up->serio);
1427#endif 1427#endif
1428 } else 1428 } else
1429 uart_remove_one_port(&sunzilog_reg, &up->port); 1429 uart_remove_one_port(&sunzilog_reg, &up->port);
1430}
1430 1431
1431 channel = ZILOG_CHANNEL_FROM_PORT(&up->port); 1432static int __devexit zs_remove(struct of_device *dev)
1433{
1434 struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
1435 struct zilog_layout __iomem *regs;
1436
1437 zs_remove_one(&up[0]);
1438 zs_remove_one(&up[1]);
1432 1439
1433 of_iounmap(channel, sizeof(struct zilog_channel)); 1440 regs = sunzilog_chip_regs[up[0].port.line / 2];
1441 of_iounmap(regs, sizeof(struct zilog_layout));
1442
1443 dev_set_drvdata(&dev->dev, NULL);
1434 1444
1435 return 0; 1445 return 0;
1436} 1446}
@@ -1489,6 +1499,11 @@ static void __exit sunzilog_exit(void)
1489{ 1499{
1490 of_unregister_driver(&zs_driver); 1500 of_unregister_driver(&zs_driver);
1491 1501
1502 if (zilog_irq != -1) {
1503 free_irq(zilog_irq, sunzilog_irq_chain);
1504 zilog_irq = -1;
1505 }
1506
1492 if (NUM_SUNZILOG) { 1507 if (NUM_SUNZILOG) {
1493 uart_unregister_driver(&sunzilog_reg); 1508 uart_unregister_driver(&sunzilog_reg);
1494 sunzilog_free_tables(); 1509 sunzilog_free_tables();