mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
ef89a88013
commit
3afe7eb37f
|
@ -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;
|
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
|
||||||
unsigned long timeo = jiffies + HZ;
|
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) {
|
switch (chip->state) {
|
||||||
|
|
||||||
case FL_STATUS:
|
case FL_STATUS:
|
||||||
|
@ -830,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
|
if (chip->priv &&
|
||||||
|| mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
|
(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
|
* OK. We have possibility for contention on the write/erase
|
||||||
* operations which are global to the real chip and not per
|
* 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
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
spin_lock(&shared->lock);
|
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);
|
spin_unlock(contender->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue