aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/sunsu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/sunsu.c')
-rw-r--r--drivers/serial/sunsu.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f9013baba05b..93bdaa3169fc 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1406,25 +1406,35 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
1406 struct device_node *dp = op->node; 1406 struct device_node *dp = op->node;
1407 struct uart_sunsu_port *up; 1407 struct uart_sunsu_port *up;
1408 struct resource *rp; 1408 struct resource *rp;
1409 enum su_type type;
1409 int err; 1410 int err;
1410 1411
1411 if (inst >= UART_NR) 1412 type = su_get_type(dp);
1412 return -EINVAL; 1413 if (type == SU_PORT_PORT) {
1414 if (inst >= UART_NR)
1415 return -EINVAL;
1416 up = &sunsu_ports[inst];
1417 } else {
1418 up = kzalloc(sizeof(*up), GFP_KERNEL);
1419 if (!up)
1420 return -ENOMEM;
1421 }
1413 1422
1414 up = &sunsu_ports[inst];
1415 up->port.line = inst; 1423 up->port.line = inst;
1416 1424
1417 spin_lock_init(&up->port.lock); 1425 spin_lock_init(&up->port.lock);
1418 1426
1419 up->su_type = su_get_type(dp); 1427 up->su_type = type;
1420 1428
1421 rp = &op->resource[0]; 1429 rp = &op->resource[0];
1422 up->port.mapbase = op->resource[0].start; 1430 up->port.mapbase = rp->start;
1423
1424 up->reg_size = (rp->end - rp->start) + 1; 1431 up->reg_size = (rp->end - rp->start) + 1;
1425 up->port.membase = of_ioremap(rp, 0, up->reg_size, "su"); 1432 up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
1426 if (!up->port.membase) 1433 if (!up->port.membase) {
1434 if (type != SU_PORT_PORT)
1435 kfree(up);
1427 return -ENOMEM; 1436 return -ENOMEM;
1437 }
1428 1438
1429 up->port.irq = op->irqs[0]; 1439 up->port.irq = op->irqs[0];
1430 1440
@@ -1436,8 +1446,11 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
1436 err = 0; 1446 err = 0;
1437 if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { 1447 if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
1438 err = sunsu_kbd_ms_init(up); 1448 err = sunsu_kbd_ms_init(up);
1439 if (err) 1449 if (err) {
1450 kfree(up);
1440 goto out_unmap; 1451 goto out_unmap;
1452 }
1453 dev_set_drvdata(&op->dev, up);
1441 1454
1442 return 0; 1455 return 0;
1443 } 1456 }
@@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev)
1476#ifdef CONFIG_SERIO 1489#ifdef CONFIG_SERIO
1477 serio_unregister_port(&up->serio); 1490 serio_unregister_port(&up->serio);
1478#endif 1491#endif
1479 } else if (up->port.type != PORT_UNKNOWN) 1492 kfree(up);
1493 } else if (up->port.type != PORT_UNKNOWN) {
1480 uart_remove_one_port(&sunsu_reg, &up->port); 1494 uart_remove_one_port(&sunsu_reg, &up->port);
1495 }
1496
1497 dev_set_drvdata(&dev->dev, NULL);
1481 1498
1482 return 0; 1499 return 0;
1483} 1500}