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:
Родитель
b8664b3762
Коммит
8ae664184c
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче