diff options
author | Ivan Djelic <ivan.djelic@parrot.com> | 2012-04-17 07:11:53 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-05-13 23:54:00 -0400 |
commit | a9c465f07c2dcd515d20b96f93470762f9ae08b6 (patch) | |
tree | 032b37acddd9c54b34adfdc3acf03a48a30e0453 /drivers/mtd/nand/omap2.c | |
parent | e25da1c07dfb318628a8a86f0967914dc4fd135e (diff) |
mtd: nand: omap: fix race condition in omap_wait()
If a context switch occurs in function omap_wait() just before the
while loop is entered, then upon return from context switch the
timeout may already have elapsed: in that case, status is never
read from NAND device, and omap_wait() returns an error.
This failure has been experimentally observed during stress tests.
This patch ensures a NAND status read is always performed before
returning, as in the generic nand_wait() function.
Signed-off-by: Ivan Djelic <ivan.djelic@parrot.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/omap2.c')
-rw-r--r-- | drivers/mtd/nand/omap2.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ab56069fa31f..05d3562ec748 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -881,7 +881,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
881 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 881 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
882 | mtd); | 882 | mtd); |
883 | unsigned long timeo = jiffies; | 883 | unsigned long timeo = jiffies; |
884 | int status = NAND_STATUS_FAIL, state = this->state; | 884 | int status, state = this->state; |
885 | 885 | ||
886 | if (state == FL_ERASING) | 886 | if (state == FL_ERASING) |
887 | timeo += (HZ * 400) / 1000; | 887 | timeo += (HZ * 400) / 1000; |
@@ -896,6 +896,8 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
896 | break; | 896 | break; |
897 | cond_resched(); | 897 | cond_resched(); |
898 | } | 898 | } |
899 | |||
900 | status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); | ||
899 | return status; | 901 | return status; |
900 | } | 902 | } |
901 | 903 | ||