Skip to content

Commit

Permalink
[MTD] [NOR] fix cfi_cmdset_0001 FL_SYNCING race (take 2)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Belyakov authored and David Woodhouse committed Sep 27, 2008
1 parent ef89a88 commit 3afe7eb
Showing 1 changed file with 15 additions and 2 deletions.
17 changes: 15 additions & 2 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
unsigned long timeo = jiffies + HZ;

/* Prevent setting state FL_SYNCING for chip in suspended state. */
if (mode == FL_SYNCING && chip->oldstate != FL_READY)
goto sleep;

switch (chip->state) {

case FL_STATUS:
Expand Down Expand Up @@ -830,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
DECLARE_WAITQUEUE(wait, current);

retry:
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
|| mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
if (chip->priv &&
(mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
|| mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
/*
* OK. We have possibility for contention on the write/erase
* operations which are global to the real chip and not per
Expand Down Expand Up @@ -881,6 +886,14 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
return ret;
}
spin_lock(&shared->lock);

/* We should not own chip if it is already
* in FL_SYNCING state. Put contender and retry. */
if (chip->state == FL_SYNCING) {
put_chip(map, contender, contender->start);
spin_unlock(contender->mutex);
goto retry;
}
spin_unlock(contender->mutex);
}

Expand Down

0 comments on commit 3afe7eb

Please sign in to comment.