diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2005-02-22 16:56:49 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-05-23 06:42:49 -0400 |
commit | 3b88775c7504dfdedd5f267cb8f02999e380222a (patch) | |
tree | 366ff196cff794ad135075f0c18ca68367c3099f /drivers/mtd | |
parent | dfd61294403cce7ca2263674f420c3417093cb56 (diff) |
[MTD] NAND: Check command timeout
Check timeout while we wait for the command to finish. No worry about a
false result. This prevents deadlocking when detecting an unknown number
of chips and is useful for removable media too.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index acd5ec193ff1..4d7c916c74fc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -59,7 +59,7 @@ | |||
59 | * The AG-AND chips have nice features for speed improvement, | 59 | * The AG-AND chips have nice features for speed improvement, |
60 | * which are not supported yet. Read / program 4 pages in one go. | 60 | * which are not supported yet. Read / program 4 pages in one go. |
61 | * | 61 | * |
62 | * $Id: nand_base.c,v 1.133 2005/02/16 09:39:35 gleixner Exp $ | 62 | * $Id: nand_base.c,v 1.134 2005/02/22 21:56:46 gleixner Exp $ |
63 | * | 63 | * |
64 | * This program is free software; you can redistribute it and/or modify | 64 | * This program is free software; you can redistribute it and/or modify |
65 | * it under the terms of the GNU General Public License version 2 as | 65 | * it under the terms of the GNU General Public License version 2 as |
@@ -509,6 +509,22 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i | |||
509 | return nand_isbad_bbt (mtd, ofs, allowbbt); | 509 | return nand_isbad_bbt (mtd, ofs, allowbbt); |
510 | } | 510 | } |
511 | 511 | ||
512 | /* | ||
513 | * Wait for the ready pin, after a command | ||
514 | * The timeout is catched later. | ||
515 | */ | ||
516 | static void nand_wait_ready(struct mtd_info *mtd) | ||
517 | { | ||
518 | struct nand_chip *this = mtd->priv; | ||
519 | unsigned long timeo = jiffies + 2; | ||
520 | |||
521 | /* wait until command is processed or timeout occures */ | ||
522 | do { | ||
523 | if (this->dev_ready(mtd)) | ||
524 | return; | ||
525 | } while (time_before(jiffies, timeo)); | ||
526 | } | ||
527 | |||
512 | /** | 528 | /** |
513 | * nand_command - [DEFAULT] Send command to NAND device | 529 | * nand_command - [DEFAULT] Send command to NAND device |
514 | * @mtd: MTD device structure | 530 | * @mtd: MTD device structure |
@@ -604,12 +620,11 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
604 | return; | 620 | return; |
605 | } | 621 | } |
606 | } | 622 | } |
607 | |||
608 | /* Apply this short delay always to ensure that we do wait tWB in | 623 | /* Apply this short delay always to ensure that we do wait tWB in |
609 | * any case on any machine. */ | 624 | * any case on any machine. */ |
610 | ndelay (100); | 625 | ndelay (100); |
611 | /* wait until command is processed */ | 626 | |
612 | while (!this->dev_ready(mtd)); | 627 | nand_wait_ready(mtd); |
613 | } | 628 | } |
614 | 629 | ||
615 | /** | 630 | /** |
@@ -720,12 +735,12 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
720 | return; | 735 | return; |
721 | } | 736 | } |
722 | } | 737 | } |
723 | 738 | ||
724 | /* Apply this short delay always to ensure that we do wait tWB in | 739 | /* Apply this short delay always to ensure that we do wait tWB in |
725 | * any case on any machine. */ | 740 | * any case on any machine. */ |
726 | ndelay (100); | 741 | ndelay (100); |
727 | /* wait until command is processed */ | 742 | |
728 | while (!this->dev_ready(mtd)); | 743 | nand_wait_ready(mtd); |
729 | } | 744 | } |
730 | 745 | ||
731 | /** | 746 | /** |
@@ -1011,7 +1026,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int | |||
1011 | if (!this->dev_ready) | 1026 | if (!this->dev_ready) |
1012 | udelay (this->chip_delay); | 1027 | udelay (this->chip_delay); |
1013 | else | 1028 | else |
1014 | while (!this->dev_ready(mtd)); | 1029 | nand_wait_ready(mtd); |
1015 | 1030 | ||
1016 | /* All done, return happy */ | 1031 | /* All done, return happy */ |
1017 | if (!numpages) | 1032 | if (!numpages) |
@@ -1302,7 +1317,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1302 | if (!this->dev_ready) | 1317 | if (!this->dev_ready) |
1303 | udelay (this->chip_delay); | 1318 | udelay (this->chip_delay); |
1304 | else | 1319 | else |
1305 | while (!this->dev_ready(mtd)); | 1320 | nand_wait_ready(mtd); |
1306 | 1321 | ||
1307 | if (read == len) | 1322 | if (read == len) |
1308 | break; | 1323 | break; |
@@ -1401,7 +1416,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
1401 | if (!this->dev_ready) | 1416 | if (!this->dev_ready) |
1402 | udelay (this->chip_delay); | 1417 | udelay (this->chip_delay); |
1403 | else | 1418 | else |
1404 | while (!this->dev_ready(mtd)); | 1419 | nand_wait_ready(mtd); |
1405 | 1420 | ||
1406 | /* Read more ? */ | 1421 | /* Read more ? */ |
1407 | if (i < len) { | 1422 | if (i < len) { |
@@ -1481,7 +1496,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1481 | if (!this->dev_ready) | 1496 | if (!this->dev_ready) |
1482 | udelay (this->chip_delay); | 1497 | udelay (this->chip_delay); |
1483 | else | 1498 | else |
1484 | while (!this->dev_ready(mtd)); | 1499 | nand_wait_ready(mtd); |
1485 | 1500 | ||
1486 | /* Check, if the chip supports auto page increment */ | 1501 | /* Check, if the chip supports auto page increment */ |
1487 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | 1502 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) |