Skip to content

Commit 6a2e332

Browse files
committed
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent fabe32c commit 6a2e332

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

drivers/base/regmap/regmap-kunit.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,20 @@ static struct regmap_range_cfg test_range = {
442442
.range_max = 40,
443443
};
444444

445-
static bool test_range_volatile(struct device *dev, unsigned int reg)
445+
static bool test_range_window_volatile(struct device *dev, unsigned int reg)
446446
{
447447
if (reg >= test_range.window_start &&
448448
reg <= test_range.window_start + test_range.window_len)
449449
return true;
450450

451+
return false;
452+
}
453+
454+
static bool test_range_all_volatile(struct device *dev, unsigned int reg)
455+
{
456+
if (test_range_window_volatile(dev, reg))
457+
return true;
458+
451459
if (reg >= test_range.range_min && reg <= test_range.range_max)
452460
return true;
453461

@@ -465,7 +473,7 @@ static void basic_ranges(struct kunit *test)
465473

466474
config = test_regmap_config;
467475
config.cache_type = t->type;
468-
config.volatile_reg = test_range_volatile;
476+
config.volatile_reg = test_range_all_volatile;
469477
config.ranges = &test_range;
470478
config.num_ranges = 1;
471479
config.max_register = test_range.range_max;
@@ -875,6 +883,59 @@ static void cache_present(struct kunit *test)
875883
regmap_exit(map);
876884
}
877885

886+
/* Check that caching the window register works with sync */
887+
static void cache_range_window_reg(struct kunit *test)
888+
{
889+
struct regcache_types *t = (struct regcache_types *)test->param_value;
890+
struct regmap *map;
891+
struct regmap_config config;
892+
struct regmap_ram_data *data;
893+
unsigned int val;
894+
int i;
895+
896+
config = test_regmap_config;
897+
config.cache_type = t->type;
898+
config.volatile_reg = test_range_window_volatile;
899+
config.ranges = &test_range;
900+
config.num_ranges = 1;
901+
config.max_register = test_range.range_max;
902+
903+
map = gen_regmap(&config, &data);
904+
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
905+
if (IS_ERR(map))
906+
return;
907+
908+
/* Write new values to the entire range */
909+
for (i = test_range.range_min; i <= test_range.range_max; i++)
910+
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0));
911+
912+
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
913+
KUNIT_ASSERT_EQ(test, val, 2);
914+
915+
/* Write to the first register in the range to reset the page */
916+
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
917+
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
918+
KUNIT_ASSERT_EQ(test, val, 0);
919+
920+
/* Trigger a cache sync */
921+
regcache_mark_dirty(map);
922+
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
923+
924+
/* Write to the first register again, the page should be reset */
925+
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
926+
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
927+
KUNIT_ASSERT_EQ(test, val, 0);
928+
929+
/* Trigger another cache sync */
930+
regcache_mark_dirty(map);
931+
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
932+
933+
/* Write to the last register again, the page should be reset */
934+
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0));
935+
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
936+
KUNIT_ASSERT_EQ(test, val, 2);
937+
}
938+
878939
struct raw_test_types {
879940
const char *name;
880941

@@ -1217,6 +1278,7 @@ static struct kunit_case regmap_test_cases[] = {
12171278
KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
12181279
KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
12191280
KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
1281+
KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_gen_params),
12201282

12211283
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
12221284
KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),

0 commit comments

Comments
 (0)