diff options
author | Mark Brown <broonie@kernel.org> | 2024-09-24 12:08:53 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2024-09-30 01:11:09 +0200 |
commit | 42afe80caff040525252af6e9601287777d144fe (patch) | |
tree | 452801fae89ef151b1c60541f69cfe1897aa8deb /drivers/base | |
parent | 21e9a1dd01b17095192ea86decc0c2081451612e (diff) | |
download | lwn-42afe80caff040525252af6e9601287777d144fe.tar.gz lwn-42afe80caff040525252af6e9601287777d144fe.zip |
regmap: Specifically test writing 0 as a value to sparse caches
Since 0 can look a lot like a NULL pointer when used in a cache some clever
data structures might potentially introduce bugs specific to handling it.
Add some explicit testing of storing 0 as a value in a sparse cache, at the
minute there are no issues and this will stop any appearing in the future.
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://patch.msgid.link/20240924-regcache-zero-value-v1-1-8a1224214b52@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/regmap-kunit.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c index 4bf3f1e59ed7..a42c7386b210 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -1499,6 +1499,48 @@ static void cache_present(struct kunit *test) KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, param->from_reg + i)); } +static void cache_write_zero(struct kunit *test) +{ + const struct regmap_test_param *param = test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + + map = gen_regmap(test, &config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->read[param->from_reg + i] = false; + + /* No defaults so no registers cached. */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, param->from_reg + i)); + + /* We didn't trigger any reads */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, data->read[param->from_reg + i]); + + /* Write a zero value */ + KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 1, 0)); + + /* Read that zero value back */ + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 1, &val)); + KUNIT_EXPECT_EQ(test, 0, val); + + /* From the cache? */ + KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, 1)); + + /* Try to throw it away */ + KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 1, 1)); + KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, 1)); +} + /* Check that caching the window register works with sync */ static void cache_range_window_reg(struct kunit *test) { @@ -2012,6 +2054,7 @@ static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(cache_drop_all_and_sync_no_defaults, sparse_cache_types_gen_params), KUNIT_CASE_PARAM(cache_drop_all_and_sync_has_defaults, sparse_cache_types_gen_params), KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params), + KUNIT_CASE_PARAM(cache_write_zero, sparse_cache_types_gen_params), KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_only_gen_params), KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params), |