aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Belyakov <abelyako@mail.ru>2008-09-25 09:53:24 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-09-26 20:56:18 -0400
commit3afe7eb37f4d47f31d30a81c1b42ca02eab01e44 (patch)
tree7e860adfbe462b3570dfcb1f4b18dabffabf1908
parentef89a8801321e0d0665c327c9d77d602ef764c87 (diff)
[MTD] [NOR] fix cfi_cmdset_0001 FL_SYNCING race (take 2)
The patch fixes CFI issue with multipartitional devices leading to the set of errors or even deadlock. The problem is CFI FL_SYNCING state race with flash operations (e.g. erase suspend). It is reproduced by running intensive writes on one JFFS2 partition and simultaneously performing mount/unmount cycle on another partition of the same chip. Signed-off-by: Alexander Belyakov <abelyako@googlemail.com> Acked-by: Nicolas Pitre <nico@cam.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 5157e3cb4b9e..c93a8be5d5f1 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -725,6 +725,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
725 struct cfi_pri_intelext *cfip = cfi->cmdset_priv; 725 struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
726 unsigned long timeo = jiffies + HZ; 726 unsigned long timeo = jiffies + HZ;
727 727
728 /* Prevent setting state FL_SYNCING for chip in suspended state. */
729 if (mode == FL_SYNCING && chip->oldstate != FL_READY)
730 goto sleep;
731
728 switch (chip->state) { 732 switch (chip->state) {
729 733
730 case FL_STATUS: 734 case FL_STATUS:
@@ -830,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
830 DECLARE_WAITQUEUE(wait, current); 834 DECLARE_WAITQUEUE(wait, current);
831 835
832 retry: 836 retry:
833 if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING 837 if (chip->priv &&
834 || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { 838 (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
839 || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
835 /* 840 /*
836 * OK. We have possibility for contention on the write/erase 841 * OK. We have possibility for contention on the write/erase
837 * operations which are global to the real chip and not per 842 * operations which are global to the real chip and not per
@@ -881,6 +886,14 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
881 return ret; 886 return ret;
882 } 887 }
883 spin_lock(&shared->lock); 888 spin_lock(&shared->lock);
889
890 /* We should not own chip if it is already
891 * in FL_SYNCING state. Put contender and retry. */
892 if (chip->state == FL_SYNCING) {
893 put_chip(map, contender, contender->start);
894 spin_unlock(contender->mutex);
895 goto retry;
896 }
884 spin_unlock(contender->mutex); 897 spin_unlock(contender->mutex);
885 } 898 }
886 899