diff options
author | Håvard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-06-06 12:04:54 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2008-06-07 03:43:11 -0400 |
commit | cc0c72e173db70a3a864994b05ebbe59b79b888f (patch) | |
tree | 5d898582e8266251c135a786fcb59a1fe3048629 /drivers/mtd/nand/atmel_nand.c | |
parent | 3c3796cc32b6e53653a5eb868dc959b8c2779db9 (diff) |
[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: Håvard Skinnemoen <haavard.skinnemoen@atmel.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand/atmel_nand.c')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 675a82ca77f5..325ce29f53fc 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -371,6 +371,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
371 | int num_partitions = 0; | 371 | int num_partitions = 0; |
372 | #endif | 372 | #endif |
373 | 373 | ||
374 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
375 | if (!mem) { | ||
376 | printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); | ||
377 | return -ENXIO; | ||
378 | } | ||
379 | |||
374 | /* Allocate memory for the device structure (and zero it) */ | 380 | /* Allocate memory for the device structure (and zero it) */ |
375 | host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); | 381 | host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); |
376 | if (!host) { | 382 | if (!host) { |
@@ -378,17 +384,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
378 | return -ENOMEM; | 384 | return -ENOMEM; |
379 | } | 385 | } |
380 | 386 | ||
381 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
382 | if (!mem) { | ||
383 | printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); | ||
384 | return -ENXIO; | ||
385 | } | ||
386 | |||
387 | host->io_base = ioremap(mem->start, mem->end - mem->start + 1); | 387 | host->io_base = ioremap(mem->start, mem->end - mem->start + 1); |
388 | if (host->io_base == NULL) { | 388 | if (host->io_base == NULL) { |
389 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); | 389 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); |
390 | kfree(host); | 390 | res = -EIO; |
391 | return -EIO; | 391 | goto err_nand_ioremap; |
392 | } | 392 | } |
393 | 393 | ||
394 | mtd = &host->mtd; | 394 | mtd = &host->mtd; |
@@ -446,14 +446,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
446 | if (gpio_get_value(host->board->det_pin)) { | 446 | if (gpio_get_value(host->board->det_pin)) { |
447 | printk ("No SmartMedia card inserted.\n"); | 447 | printk ("No SmartMedia card inserted.\n"); |
448 | res = ENXIO; | 448 | res = ENXIO; |
449 | goto out; | 449 | goto err_no_card; |
450 | } | 450 | } |
451 | } | 451 | } |
452 | 452 | ||
453 | /* first scan to find the device and get the page size */ | 453 | /* first scan to find the device and get the page size */ |
454 | if (nand_scan_ident(mtd, 1)) { | 454 | if (nand_scan_ident(mtd, 1)) { |
455 | res = -ENXIO; | 455 | res = -ENXIO; |
456 | goto out; | 456 | goto err_scan_ident; |
457 | } | 457 | } |
458 | 458 | ||
459 | if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) { | 459 | if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) { |
@@ -498,7 +498,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
498 | /* second phase scan */ | 498 | /* second phase scan */ |
499 | if (nand_scan_tail(mtd)) { | 499 | if (nand_scan_tail(mtd)) { |
500 | res = -ENXIO; | 500 | res = -ENXIO; |
501 | goto out; | 501 | goto err_scan_tail; |
502 | } | 502 | } |
503 | 503 | ||
504 | #ifdef CONFIG_MTD_PARTITIONS | 504 | #ifdef CONFIG_MTD_PARTITIONS |
@@ -514,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
514 | if ((!partitions) || (num_partitions == 0)) { | 514 | if ((!partitions) || (num_partitions == 0)) { |
515 | printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); | 515 | printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); |
516 | res = ENXIO; | 516 | res = ENXIO; |
517 | goto release; | 517 | goto err_no_partitions; |
518 | } | 518 | } |
519 | 519 | ||
520 | res = add_mtd_partitions(mtd, partitions, num_partitions); | 520 | res = add_mtd_partitions(mtd, partitions, num_partitions); |
@@ -526,17 +526,19 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
526 | return res; | 526 | return res; |
527 | 527 | ||
528 | #ifdef CONFIG_MTD_PARTITIONS | 528 | #ifdef CONFIG_MTD_PARTITIONS |
529 | release: | 529 | err_no_partitions: |
530 | #endif | 530 | #endif |
531 | nand_release(mtd); | 531 | nand_release(mtd); |
532 | 532 | err_scan_tail: | |
533 | out: | 533 | err_scan_ident: |
534 | iounmap(host->ecc); | 534 | err_no_card: |
535 | |||
536 | err_ecc_ioremap: | ||
537 | atmel_nand_disable(host); | 535 | atmel_nand_disable(host); |
538 | platform_set_drvdata(pdev, NULL); | 536 | platform_set_drvdata(pdev, NULL); |
537 | if (host->ecc) | ||
538 | iounmap(host->ecc); | ||
539 | err_ecc_ioremap: | ||
539 | iounmap(host->io_base); | 540 | iounmap(host->io_base); |
541 | err_nand_ioremap: | ||
540 | kfree(host); | 542 | kfree(host); |
541 | return res; | 543 | return res; |
542 | } | 544 | } |
@@ -553,8 +555,9 @@ static int __devexit atmel_nand_remove(struct platform_device *pdev) | |||
553 | 555 | ||
554 | atmel_nand_disable(host); | 556 | atmel_nand_disable(host); |
555 | 557 | ||
558 | if (host->ecc) | ||
559 | iounmap(host->ecc); | ||
556 | iounmap(host->io_base); | 560 | iounmap(host->io_base); |
557 | iounmap(host->ecc); | ||
558 | kfree(host); | 561 | kfree(host); |
559 | 562 | ||
560 | return 0; | 563 | return 0; |