]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
regmap: kunit: add noinc write test
authorBen Wolsieffer <ben.wolsieffer@hefring.com>
Thu, 2 Nov 2023 20:30:39 +0000 (16:30 -0400)
committerMark Brown <broonie@kernel.org>
Mon, 13 Nov 2023 01:26:18 +0000 (01:26 +0000)
Add a test for writing to a noinc register, which verifies that the
write does not touch adjacent registers. This test succeeds with [1]
applied and fails without it.

[1] 984a4afdc87a ("regmap: prevent noinc writes from clobbering cache")

Signed-off-by: Ben Wolsieffer <ben.wolsieffer@hefring.com>
Link: https://lore.kernel.org/r/20231102203039.3069305-2-ben.wolsieffer@hefring.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/base/regmap/regmap-kunit.c

index e14cc03a17f6c72c142c3ecccbfd11290b619c4f..026bdcb45127f530093cb4041f734d222e2fb005 100644 (file)
@@ -1186,6 +1186,65 @@ static void raw_write(struct kunit *test)
        regmap_exit(map);
 }
 
+static bool reg_zero(struct device *dev, unsigned int reg)
+{
+       return reg == 0;
+}
+
+static bool ram_reg_zero(struct regmap_ram_data *data, unsigned int reg)
+{
+       return reg == 0;
+}
+
+static void raw_noinc_write(struct kunit *test)
+{
+       struct raw_test_types *t = (struct raw_test_types *)test->param_value;
+       struct regmap *map;
+       struct regmap_config config;
+       struct regmap_ram_data *data;
+       unsigned int val, val_test, val_last;
+       u16 val_array[BLOCK_TEST_SIZE];
+
+       config = raw_regmap_config;
+       config.volatile_reg = reg_zero;
+       config.writeable_noinc_reg = reg_zero;
+       config.readable_noinc_reg = reg_zero;
+
+       map = gen_raw_regmap(&config, t, &data);
+       KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+       if (IS_ERR(map))
+               return;
+
+       data->noinc_reg = ram_reg_zero;
+
+       get_random_bytes(&val_array, sizeof(val_array));
+
+       if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
+               val_test = be16_to_cpu(val_array[1]) + 100;
+               val_last = be16_to_cpu(val_array[BLOCK_TEST_SIZE - 1]);
+       } else {
+               val_test = le16_to_cpu(val_array[1]) + 100;
+               val_last = le16_to_cpu(val_array[BLOCK_TEST_SIZE - 1]);
+       }
+
+       /* Put some data into the register following the noinc register */
+       KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 1, val_test));
+
+       /* Write some data to the noinc register */
+       KUNIT_EXPECT_EQ(test, 0, regmap_noinc_write(map, 0, val_array,
+                                                   sizeof(val_array)));
+
+       /* We should read back the last value written */
+       KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &val));
+       KUNIT_ASSERT_EQ(test, val_last, val);
+
+       /* Make sure we didn't touch the register after the noinc register */
+       KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 1, &val));
+       KUNIT_ASSERT_EQ(test, val_test, val);
+
+       regmap_exit(map);
+}
+
 static void raw_sync(struct kunit *test)
 {
        struct raw_test_types *t = (struct raw_test_types *)test->param_value;
@@ -1284,6 +1343,7 @@ static struct kunit_case regmap_test_cases[] = {
        KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
        KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params),
        KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
+       KUNIT_CASE_PARAM(raw_noinc_write, raw_test_types_gen_params),
        KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
        {}
 };