diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/sunsu.c | 35 |
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 | } |