Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ae66418 authored by Stefani Seibold's avatar Stefani Seibold Committed by David Woodhouse
Browse files

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: default avatarStefani Seibold <stefani@seibold.net>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent b8664b37
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -720,7 +720,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
		chip = &newcfi->chips[0];
		for (i = 0; i < cfi->numchips; i++) {
			shared[i].writing = shared[i].erasing = NULL;
			spin_lock_init(&shared[i].lock);
			mutex_init(&shared[i].lock);
			for (j = 0; j < numparts; j++) {
				*chip = cfi->chips[i];
				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 *contender;
		spin_lock(&shared->lock);
		mutex_lock(&shared->lock);
		contender = shared->writing;
		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.
			 */
			ret = mutex_trylock(&contender->mutex);
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			if (!ret)
				goto retry;
			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);
				return ret;
			}
			spin_lock(&shared->lock);
			mutex_lock(&shared->lock);

			/* We should not own chip if it is already
			 * 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. */
		if (mode == FL_ERASING && shared->erasing
		    && shared->erasing->oldstate == FL_ERASING) {
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			set_current_state(TASK_UNINTERRUPTIBLE);
			add_wait_queue(&chip->wq, &wait);
			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;
		if (mode == FL_ERASING)
			shared->erasing = chip;
		spin_unlock(&shared->lock);
		mutex_unlock(&shared->lock);
	}
	ret = chip_ready(map, chip, adr, mode);
	if (ret == -EAGAIN)
@@ -962,7 +962,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad

	if (chip->priv) {
		struct flchip_shared *shared = chip->priv;
		spin_lock(&shared->lock);
		mutex_lock(&shared->lock);
		if (shared->writing == chip && chip->oldstate == FL_READY) {
			/* We own the ability to write, but we're done */
			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 */
				struct flchip *loaner = shared->writing;
				mutex_lock(&loaner->mutex);
				spin_unlock(&shared->lock);
				mutex_unlock(&shared->lock);
				mutex_unlock(&chip->mutex);
				put_chip(map, loaner, loaner->start);
				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
			 * we don't have ownership to resume anything.
			 */
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			wake_up(&chip->wq);
			return;
		}
		spin_unlock(&shared->lock);
		mutex_unlock(&shared->lock);
	}

	switch(chip->oldstate) {
+10 −10
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
	numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
	for (i = 0; i < numchips; i++) {
		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++) {
			*chip = lpddr->chips[i];
			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 *contender;
		spin_lock(&shared->lock);
		mutex_lock(&shared->lock);
		contender = shared->writing;
		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.
			 */
			ret = mutex_trylock(&contender->mutex);
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			if (!ret)
				goto retry;
			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);
				return ret;
			}
			spin_lock(&shared->lock);
			mutex_lock(&shared->lock);

			/* We should not own chip if it is already in FL_SYNCING
			 * 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. */
		if (mode == FL_ERASING && shared->erasing
		    && shared->erasing->oldstate == FL_ERASING) {
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			set_current_state(TASK_UNINTERRUPTIBLE);
			add_wait_queue(&chip->wq, &wait);
			mutex_unlock(&chip->mutex);
@@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
		shared->writing = chip;
		if (mode == FL_ERASING)
			shared->erasing = chip;
		spin_unlock(&shared->lock);
		mutex_unlock(&shared->lock);
	}

	ret = chip_ready(map, chip, mode);
@@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
{
	if (chip->priv) {
		struct flchip_shared *shared = chip->priv;
		spin_lock(&shared->lock);
		mutex_lock(&shared->lock);
		if (shared->writing == chip && chip->oldstate == FL_READY) {
			/* We own the ability to write, but we're done */
			shared->writing = shared->erasing;
@@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
				/* give back the ownership */
				struct flchip *loaner = shared->writing;
				mutex_lock(&loaner->mutex);
				spin_unlock(&shared->lock);
				mutex_unlock(&shared->lock);
				mutex_unlock(&chip->mutex);
				put_chip(map, loaner);
				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
			 * we don't have ownership to resume anything.
			 */
			spin_unlock(&shared->lock);
			mutex_unlock(&shared->lock);
			wake_up(&chip->wq);
			return;
		}
		spin_unlock(&shared->lock);
		mutex_unlock(&shared->lock);
	}

	switch (chip->oldstate) {
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ struct flchip {
/* This is used to handle contention on write/erase operations
   between partitions of the same physical chip. */
struct flchip_shared {
	spinlock_t lock;
	struct mutex lock;
	struct flchip *writing;
	struct flchip *erasing;
};