mtd: change struct flchip_shared spinlock locking into mutex

This patch prevent to schedule while atomic by changing the
flchip_shared spinlock into a mutex. This should be save since no atomic
path will use this lock.

It was suggested by Arnd Bergmann and Vasiliy Kulikov.

Signed-off-by: Stefani Seibold <stefani@seibold.net>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Stefani Seibold 2010-08-05 09:19:26 +02:00 коммит произвёл David Woodhouse
Родитель b8664b3762
Коммит 8ae664184c
3 изменённых файлов: 21 добавлений и 21 удалений

Просмотреть файл

@ -720,7 +720,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
chip = &newcfi->chips[0]; chip = &newcfi->chips[0];
for (i = 0; i < cfi->numchips; i++) { for (i = 0; i < cfi->numchips; i++) {
shared[i].writing = shared[i].erasing = NULL; shared[i].writing = shared[i].erasing = NULL;
spin_lock_init(&shared[i].lock); mutex_init(&shared[i].lock);
for (j = 0; j < numparts; j++) { for (j = 0; j < numparts; j++) {
*chip = cfi->chips[i]; *chip = cfi->chips[i];
chip->start += j << partshift; chip->start += j << partshift;
@ -889,7 +889,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
*/ */
struct flchip_shared *shared = chip->priv; struct flchip_shared *shared = chip->priv;
struct flchip *contender; struct flchip *contender;
spin_lock(&shared->lock); mutex_lock(&shared->lock);
contender = shared->writing; contender = shared->writing;
if (contender && contender != chip) { if (contender && contender != chip) {
/* /*
@ -902,7 +902,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* get_chip returns success we're clear to go ahead. * get_chip returns success we're clear to go ahead.
*/ */
ret = mutex_trylock(&contender->mutex); ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
if (!ret) if (!ret)
goto retry; goto retry;
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
@ -917,7 +917,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
mutex_unlock(&contender->mutex); mutex_unlock(&contender->mutex);
return ret; return ret;
} }
spin_lock(&shared->lock); mutex_lock(&shared->lock);
/* We should not own chip if it is already /* We should not own chip if it is already
* in FL_SYNCING state. Put contender and retry. */ * in FL_SYNCING state. Put contender and retry. */
@ -933,7 +933,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* on this chip. Sleep. */ * on this chip. Sleep. */
if (mode == FL_ERASING && shared->erasing if (mode == FL_ERASING && shared->erasing
&& shared->erasing->oldstate == FL_ERASING) { && shared->erasing->oldstate == FL_ERASING) {
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
@ -947,7 +947,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
shared->writing = chip; shared->writing = chip;
if (mode == FL_ERASING) if (mode == FL_ERASING)
shared->erasing = chip; shared->erasing = chip;
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
} }
ret = chip_ready(map, chip, adr, mode); ret = chip_ready(map, chip, adr, mode);
if (ret == -EAGAIN) if (ret == -EAGAIN)
@ -962,7 +962,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
if (chip->priv) { if (chip->priv) {
struct flchip_shared *shared = chip->priv; struct flchip_shared *shared = chip->priv;
spin_lock(&shared->lock); mutex_lock(&shared->lock);
if (shared->writing == chip && chip->oldstate == FL_READY) { if (shared->writing == chip && chip->oldstate == FL_READY) {
/* We own the ability to write, but we're done */ /* We own the ability to write, but we're done */
shared->writing = shared->erasing; shared->writing = shared->erasing;
@ -970,7 +970,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
/* give back ownership to who we loaned it from */ /* give back ownership to who we loaned it from */
struct flchip *loaner = shared->writing; struct flchip *loaner = shared->writing;
mutex_lock(&loaner->mutex); mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
put_chip(map, loaner, loaner->start); put_chip(map, loaner, loaner->start);
mutex_lock(&chip->mutex); mutex_lock(&chip->mutex);
@ -988,11 +988,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
* Don't let the switch below mess things up since * Don't let the switch below mess things up since
* we don't have ownership to resume anything. * we don't have ownership to resume anything.
*/ */
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
wake_up(&chip->wq); wake_up(&chip->wq);
return; return;
} }
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
} }
switch(chip->oldstate) { switch(chip->oldstate) {

Просмотреть файл

@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
for (i = 0; i < numchips; i++) { for (i = 0; i < numchips; i++) {
shared[i].writing = shared[i].erasing = NULL; shared[i].writing = shared[i].erasing = NULL;
spin_lock_init(&shared[i].lock); mutex_init(&shared[i].lock);
for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
*chip = lpddr->chips[i]; *chip = lpddr->chips[i];
chip->start += j << lpddr->chipshift; chip->start += j << lpddr->chipshift;
@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
*/ */
struct flchip_shared *shared = chip->priv; struct flchip_shared *shared = chip->priv;
struct flchip *contender; struct flchip *contender;
spin_lock(&shared->lock); mutex_lock(&shared->lock);
contender = shared->writing; contender = shared->writing;
if (contender && contender != chip) { if (contender && contender != chip) {
/* /*
@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
* get_chip returns success we're clear to go ahead. * get_chip returns success we're clear to go ahead.
*/ */
ret = mutex_trylock(&contender->mutex); ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
if (!ret) if (!ret)
goto retry; goto retry;
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
mutex_unlock(&contender->mutex); mutex_unlock(&contender->mutex);
return ret; return ret;
} }
spin_lock(&shared->lock); mutex_lock(&shared->lock);
/* We should not own chip if it is already in FL_SYNCING /* We should not own chip if it is already in FL_SYNCING
* state. Put contender and retry. */ * state. Put contender and retry. */
@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
Must sleep in such a case. */ Must sleep in such a case. */
if (mode == FL_ERASING && shared->erasing if (mode == FL_ERASING && shared->erasing
&& shared->erasing->oldstate == FL_ERASING) { && shared->erasing->oldstate == FL_ERASING) {
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
shared->writing = chip; shared->writing = chip;
if (mode == FL_ERASING) if (mode == FL_ERASING)
shared->erasing = chip; shared->erasing = chip;
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
} }
ret = chip_ready(map, chip, mode); ret = chip_ready(map, chip, mode);
@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
{ {
if (chip->priv) { if (chip->priv) {
struct flchip_shared *shared = chip->priv; struct flchip_shared *shared = chip->priv;
spin_lock(&shared->lock); mutex_lock(&shared->lock);
if (shared->writing == chip && chip->oldstate == FL_READY) { if (shared->writing == chip && chip->oldstate == FL_READY) {
/* We own the ability to write, but we're done */ /* We own the ability to write, but we're done */
shared->writing = shared->erasing; shared->writing = shared->erasing;
@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
/* give back the ownership */ /* give back the ownership */
struct flchip *loaner = shared->writing; struct flchip *loaner = shared->writing;
mutex_lock(&loaner->mutex); mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
put_chip(map, loaner); put_chip(map, loaner);
mutex_lock(&chip->mutex); mutex_lock(&chip->mutex);
@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip)
* Don't let the switch below mess things up since * Don't let the switch below mess things up since
* we don't have ownership to resume anything. * we don't have ownership to resume anything.
*/ */
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
wake_up(&chip->wq); wake_up(&chip->wq);
return; return;
} }
spin_unlock(&shared->lock); mutex_unlock(&shared->lock);
} }
switch (chip->oldstate) { switch (chip->oldstate) {

Просмотреть файл

@ -92,7 +92,7 @@ struct flchip {
/* This is used to handle contention on write/erase operations /* This is used to handle contention on write/erase operations
between partitions of the same physical chip. */ between partitions of the same physical chip. */
struct flchip_shared { struct flchip_shared {
spinlock_t lock; struct mutex lock;
struct flchip *writing; struct flchip *writing;
struct flchip *erasing; struct flchip *erasing;
}; };