mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
regmap: kunit: Add test for cache sync interaction with ranges
Hector Martin reports that since when doing a cache sync we enable cache bypass if the selector register for a range is cached then we might leave the physical selector register pointing to a different value to that which we have in the cache. If we then try to write to the page that our cache tells us is selected we will not update the selector register and write to the wrong page. Add a test case covering this. Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20231023-regmap-test-window-cache-v1-2-d8a71f441968@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
fabe32cc1e
commit
6a2e332c2c
@ -442,12 +442,20 @@ static struct regmap_range_cfg test_range = {
|
||||
.range_max = 40,
|
||||
};
|
||||
|
||||
static bool test_range_volatile(struct device *dev, unsigned int reg)
|
||||
static bool test_range_window_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (reg >= test_range.window_start &&
|
||||
reg <= test_range.window_start + test_range.window_len)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool test_range_all_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (test_range_window_volatile(dev, reg))
|
||||
return true;
|
||||
|
||||
if (reg >= test_range.range_min && reg <= test_range.range_max)
|
||||
return true;
|
||||
|
||||
@ -465,7 +473,7 @@ static void basic_ranges(struct kunit *test)
|
||||
|
||||
config = test_regmap_config;
|
||||
config.cache_type = t->type;
|
||||
config.volatile_reg = test_range_volatile;
|
||||
config.volatile_reg = test_range_all_volatile;
|
||||
config.ranges = &test_range;
|
||||
config.num_ranges = 1;
|
||||
config.max_register = test_range.range_max;
|
||||
@ -875,6 +883,59 @@ static void cache_present(struct kunit *test)
|
||||
regmap_exit(map);
|
||||
}
|
||||
|
||||
/* Check that caching the window register works with sync */
|
||||
static void cache_range_window_reg(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;
|
||||
config.volatile_reg = test_range_window_volatile;
|
||||
config.ranges = &test_range;
|
||||
config.num_ranges = 1;
|
||||
config.max_register = test_range.range_max;
|
||||
|
||||
map = gen_regmap(&config, &data);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
|
||||
/* Write new values to the entire range */
|
||||
for (i = test_range.range_min; i <= test_range.range_max; i++)
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0));
|
||||
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 2);
|
||||
|
||||
/* Write to the first register in the range to reset the page */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 0);
|
||||
|
||||
/* Trigger a cache sync */
|
||||
regcache_mark_dirty(map);
|
||||
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
|
||||
|
||||
/* Write to the first register again, the page should be reset */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 0);
|
||||
|
||||
/* Trigger another cache sync */
|
||||
regcache_mark_dirty(map);
|
||||
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
|
||||
|
||||
/* Write to the last register again, the page should be reset */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 2);
|
||||
}
|
||||
|
||||
struct raw_test_types {
|
||||
const char *name;
|
||||
|
||||
@ -1217,6 +1278,7 @@ static struct kunit_case regmap_test_cases[] = {
|
||||
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(cache_range_window_reg, real_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),
|
||||
|
Loading…
Reference in New Issue
Block a user