[PATCH 0/3] regmap: Add interface for checking if a register is cached
HDA has a use case for checking if a register is present in the cache which it awkwardly open codes with use of _cache_only() and a read, provide a direct API for this.
--- Mark Brown (3): regmap: Let users check if a register is cached regmap: Provide test for regcache_reg_present() ALSA: hda: Use regcache_reg_cached() rather than open coding
drivers/base/regmap/regcache.c | 23 ++++++++++++++++++++++ drivers/base/regmap/regmap-kunit.c | 40 ++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 1 + sound/hda/hdac_regmap.c | 9 +++------ 4 files changed, 67 insertions(+), 6 deletions(-) --- base-commit: 3953d5c79c21defa716624a8623c4157c0f2fee0 change-id: 20230716-regmap-cache-check-6f6939f41ed5
Best regards,
The HDA driver has a use case for checking if a register is cached which it bodges in awkwardly and unclearly. Provide an API which allows it to directly do what it's trying to do.
Signed-off-by: Mark Brown broonie@kernel.org --- drivers/base/regmap/regcache.c | 23 +++++++++++++++++++++++ include/linux/regmap.h | 1 + 2 files changed, 24 insertions(+)
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 28bc3ae9458a..4d25a906b688 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -561,6 +561,29 @@ void regcache_cache_bypass(struct regmap *map, bool enable) } EXPORT_SYMBOL_GPL(regcache_cache_bypass);
+/** + * regcache_reg_cached - Check if a register is cached + * + * @map: map to check + * @reg: register to check + * + * Reports if a register is cached. + */ +bool regcache_reg_cached(struct regmap *map, unsigned int reg) +{ + unsigned int val; + int ret; + + map->lock(map->lock_arg); + + ret = regcache_read(map, reg, &val); + + map->unlock(map->lock_arg); + + return ret == 0; +} +EXPORT_SYMBOL_GPL(regcache_reg_cached); + void regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val) { diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 8fc0b3ebce44..c9182a47736e 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -1287,6 +1287,7 @@ int regcache_drop_region(struct regmap *map, unsigned int min, void regcache_cache_only(struct regmap *map, bool enable); void regcache_cache_bypass(struct regmap *map, bool enable); void regcache_mark_dirty(struct regmap *map); +bool regcache_reg_cached(struct regmap *map, unsigned int reg);
bool regmap_check_range_table(struct regmap *map, unsigned int reg, const struct regmap_access_table *table);
Provide a KUnit test for the newly added API.
Signed-off-by: Mark Brown broonie@kernel.org --- drivers/base/regmap/regmap-kunit.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c index 24257aa9004d..8dd96a55d976 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -833,6 +833,45 @@ static void cache_drop(struct kunit *test) regmap_exit(map); }
+static void cache_present(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->read[i] = false; + + /* No defaults so no registers cached. */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, i)); + + /* We didn't trigger any reads */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, data->read[i]); + + /* Fill the cache */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val)); + + /* Now everything should be cached */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, i)); + + regmap_exit(map); +} + struct raw_test_types { const char *name;
@@ -1172,6 +1211,7 @@ static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params), + KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params), KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
The HDA driver intentionally drops repeated writes to registers in some circumstances, beyond the suppression of noop writes that regmap does in regmap_update_bits(). It does this by checking if the register is cached before doing a regmap_update_bits(), now we have an API for querying this directly use it directly rather than trying a read in cache only mode making the code a little clearer.
Signed-off-by: Mark Brown broonie@kernel.org --- sound/hda/hdac_regmap.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c index 9b1bcabd8414..97cee096a286 100644 --- a/sound/hda/hdac_regmap.c +++ b/sound/hda/hdac_regmap.c @@ -556,17 +556,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw); static int reg_raw_update_once(struct hdac_device *codec, unsigned int reg, unsigned int mask, unsigned int val) { - unsigned int orig; - int err; + int err = 0;
if (!codec->regmap) return reg_raw_update(codec, reg, mask, val);
mutex_lock(&codec->regmap_lock); - regcache_cache_only(codec->regmap, true); - err = regmap_read(codec->regmap, reg, &orig); - regcache_cache_only(codec->regmap, false); - if (err < 0) + /* Discard any updates to already initialised registers. */ + if (!regcache_reg_cached(codec->regmap, reg)) err = regmap_update_bits(codec->regmap, reg, mask, val); mutex_unlock(&codec->regmap_lock); return err;
On Mon, 17 Jul 2023 22:33:02 +0200, Mark Brown wrote:
HDA has a use case for checking if a register is present in the cache which it awkwardly open codes with use of _cache_only() and a read, provide a direct API for this.
Mark Brown (3): regmap: Let users check if a register is cached regmap: Provide test for regcache_reg_present() ALSA: hda: Use regcache_reg_cached() rather than open coding
Reviewed-by: Takashi Iwai tiwai@suse.de
I suppose you'll take those from regmap.git?
thanks,
Takashi
drivers/base/regmap/regcache.c | 23 ++++++++++++++++++++++ drivers/base/regmap/regmap-kunit.c | 40 ++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 1 + sound/hda/hdac_regmap.c | 9 +++------ 4 files changed, 67 insertions(+), 6 deletions(-)
base-commit: 3953d5c79c21defa716624a8623c4157c0f2fee0 change-id: 20230716-regmap-cache-check-6f6939f41ed5
Best regards,
Mark Brown broonie@kernel.org
On Tue, Jul 18, 2023 at 07:46:42AM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Mark Brown (3): regmap: Let users check if a register is cached regmap: Provide test for regcache_reg_present() ALSA: hda: Use regcache_reg_cached() rather than open coding
Reviewed-by: Takashi Iwai tiwai@suse.de
I suppose you'll take those from regmap.git?
Sure, it's probably easiest (and there's some annoying overlap with some other work in there that'd make for conflicts otherwise).
On Mon, 17 Jul 2023 21:33:02 +0100, Mark Brown wrote:
HDA has a use case for checking if a register is present in the cache which it awkwardly open codes with use of _cache_only() and a read, provide a direct API for this.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next
Thanks!
[1/3] regmap: Let users check if a register is cached commit: 78908f45ccf1dc2f4d5fb395c460fdbbf7e9ac3a [2/3] regmap: Provide test for regcache_reg_present() commit: d881ee5a872fd539a8c693e4c8656b9343c9aae0 [3/3] ALSA: hda: Use regcache_reg_cached() rather than open coding commit: 99aae70551f99536936438bbcfc562df69eeb79c
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Takashi Iwai