Unverified Commit 21f8e482 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Mark Brown
Browse files

regmap: Add can_sleep configuration option



Regmap can't sleep if spinlock is used for the locking protection.
This patch fixes regression caused by a previous commit that switched
regmap to use fsleep() and this broke Amlogic S922X platform.

This patch adds new configuration option for regmap users, allowing to
specify whether regmap operations can sleep and assuming that sleep is
allowed if mutex is used for the regmap locking protection.

Reported-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Fixes: 2b32d2f7 ("regmap: Use flexible sleep")
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Tested-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20200902141843.6591-1-digetx@gmail.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d17343b8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -161,6 +161,9 @@ struct regmap {
	void *selector_work_buf;	/* Scratch buffer used for selector */

	struct hwspinlock *hwlock;

	/* if set, the regmap core can sleep */
	bool can_sleep;
};

struct regcache_ops {
+15 −4
Original line number Diff line number Diff line
@@ -697,11 +697,13 @@ struct regmap *__regmap_init(struct device *dev,

	if (config->disable_locking) {
		map->lock = map->unlock = regmap_lock_unlock_none;
		map->can_sleep = config->can_sleep;
		regmap_debugfs_disable(map);
	} else if (config->lock && config->unlock) {
		map->lock = config->lock;
		map->unlock = config->unlock;
		map->lock_arg = config->lock_arg;
		map->can_sleep = config->can_sleep;
	} else if (config->use_hwlock) {
		map->hwlock = hwspin_lock_request_specific(config->hwlock_id);
		if (!map->hwlock) {
@@ -737,6 +739,7 @@ struct regmap *__regmap_init(struct device *dev,
			mutex_init(&map->mutex);
			map->lock = regmap_lock_mutex;
			map->unlock = regmap_unlock_mutex;
			map->can_sleep = true;
			lockdep_set_class_and_name(&map->mutex,
						   lock_key, lock_name);
		}
@@ -2230,8 +2233,12 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
				if (ret != 0)
					return ret;

				if (regs[i].delay_us)
				if (regs[i].delay_us) {
					if (map->can_sleep)
						fsleep(regs[i].delay_us);
					else
						udelay(regs[i].delay_us);
				}

				base += n;
				n = 0;
@@ -2267,8 +2274,12 @@ static int _regmap_multi_reg_write(struct regmap *map,
			if (ret != 0)
				return ret;

			if (regs[i].delay_us)
			if (regs[i].delay_us) {
				if (map->can_sleep)
					fsleep(regs[i].delay_us);
				else
					udelay(regs[i].delay_us);
			}
		}
		return 0;
	}
+3 −0
Original line number Diff line number Diff line
@@ -342,6 +342,7 @@ typedef void (*regmap_unlock)(void *);
 * @hwlock_id: Specify the hardware spinlock id.
 * @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE,
 *		 HWLOCK_IRQ or 0.
 * @can_sleep: Optional, specifies whether regmap operations can sleep.
 */
struct regmap_config {
	const char *name;
@@ -398,6 +399,8 @@ struct regmap_config {
	bool use_hwlock;
	unsigned int hwlock_id;
	unsigned int hwlock_mode;

	bool can_sleep;
};

/**