Commit cc0c72e1 authored by Håvard Skinnemoen's avatar Håvard Skinnemoen Committed by David Woodhouse

[MTD] [NAND] atmel_nand: Clean up and fix probe() error path

This fixes several bugs in the atmel_nand_probe() error path, including
at least one memory leak.
Signed-off-by: default avatarHåvard Skinnemoen <haavard.skinnemoen@atmel.com>
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 3c3796cc
...@@ -371,6 +371,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -371,6 +371,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
int num_partitions = 0; int num_partitions = 0;
#endif #endif
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
return -ENXIO;
}
/* Allocate memory for the device structure (and zero it) */ /* Allocate memory for the device structure (and zero it) */
host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL);
if (!host) { if (!host) {
...@@ -378,17 +384,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -378,17 +384,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n");
return -ENXIO;
}
host->io_base = ioremap(mem->start, mem->end - mem->start + 1); host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
if (host->io_base == NULL) { if (host->io_base == NULL) {
printk(KERN_ERR "atmel_nand: ioremap failed\n"); printk(KERN_ERR "atmel_nand: ioremap failed\n");
kfree(host); res = -EIO;
return -EIO; goto err_nand_ioremap;
} }
mtd = &host->mtd; mtd = &host->mtd;
...@@ -446,14 +446,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -446,14 +446,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if (gpio_get_value(host->board->det_pin)) { if (gpio_get_value(host->board->det_pin)) {
printk ("No SmartMedia card inserted.\n"); printk ("No SmartMedia card inserted.\n");
res = ENXIO; res = ENXIO;
goto out; goto err_no_card;
} }
} }
/* first scan to find the device and get the page size */ /* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1)) { if (nand_scan_ident(mtd, 1)) {
res = -ENXIO; res = -ENXIO;
goto out; goto err_scan_ident;
} }
if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) { if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
...@@ -498,7 +498,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -498,7 +498,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
/* second phase scan */ /* second phase scan */
if (nand_scan_tail(mtd)) { if (nand_scan_tail(mtd)) {
res = -ENXIO; res = -ENXIO;
goto out; goto err_scan_tail;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
...@@ -514,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -514,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if ((!partitions) || (num_partitions == 0)) { if ((!partitions) || (num_partitions == 0)) {
printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
res = ENXIO; res = ENXIO;
goto release; goto err_no_partitions;
} }
res = add_mtd_partitions(mtd, partitions, num_partitions); res = add_mtd_partitions(mtd, partitions, num_partitions);
...@@ -526,17 +526,19 @@ static int __init atmel_nand_probe(struct platform_device *pdev) ...@@ -526,17 +526,19 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
return res; return res;
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
release: err_no_partitions:
#endif #endif
nand_release(mtd); nand_release(mtd);
err_scan_tail:
out: err_scan_ident:
iounmap(host->ecc); err_no_card:
err_ecc_ioremap:
atmel_nand_disable(host); atmel_nand_disable(host);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
if (host->ecc)
iounmap(host->ecc);
err_ecc_ioremap:
iounmap(host->io_base); iounmap(host->io_base);
err_nand_ioremap:
kfree(host); kfree(host);
return res; return res;
} }
...@@ -553,8 +555,9 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev) ...@@ -553,8 +555,9 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev)
atmel_nand_disable(host); atmel_nand_disable(host);
if (host->ecc)
iounmap(host->ecc);
iounmap(host->io_base); iounmap(host->io_base);
iounmap(host->ecc);
kfree(host); kfree(host);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment