@@ -1007,6 +1007,108 @@ static void cache_drop(struct kunit *test)
10071007 KUNIT_EXPECT_MEMEQ (test , & data -> vals [param -> from_reg ], rval , sizeof (rval ));
10081008}
10091009
1010+ static void cache_drop_with_non_contiguous_ranges (struct kunit * test )
1011+ {
1012+ const struct regmap_test_param * param = test -> param_value ;
1013+ struct regmap * map ;
1014+ struct regmap_config config ;
1015+ struct regmap_ram_data * data ;
1016+ unsigned int val [4 ][BLOCK_TEST_SIZE ];
1017+ unsigned int reg ;
1018+ const int num_ranges = ARRAY_SIZE (val ) * 2 ;
1019+ int rangeidx , i ;
1020+
1021+ static_assert (ARRAY_SIZE (val ) == 4 );
1022+
1023+ config = test_regmap_config ;
1024+ config .max_register = param -> from_reg + (num_ranges * BLOCK_TEST_SIZE );
1025+
1026+ map = gen_regmap (test , & config , & data );
1027+ KUNIT_ASSERT_FALSE (test , IS_ERR (map ));
1028+ if (IS_ERR (map ))
1029+ return ;
1030+
1031+ for (i = 0 ; i < config .max_register + 1 ; i ++ )
1032+ data -> written [i ] = false;
1033+
1034+ /* Create non-contiguous cache blocks by writing every other range */
1035+ get_random_bytes (& val , sizeof (val ));
1036+ for (rangeidx = 0 ; rangeidx < num_ranges ; rangeidx += 2 ) {
1037+ reg = param -> from_reg + (rangeidx * BLOCK_TEST_SIZE );
1038+ KUNIT_EXPECT_EQ (test , 0 , regmap_bulk_write (map , reg ,
1039+ & val [rangeidx / 2 ],
1040+ BLOCK_TEST_SIZE ));
1041+ KUNIT_EXPECT_MEMEQ (test , & data -> vals [reg ],
1042+ & val [rangeidx / 2 ], sizeof (val [rangeidx / 2 ]));
1043+ }
1044+
1045+ /* Check that odd ranges weren't written */
1046+ for (rangeidx = 1 ; rangeidx < num_ranges ; rangeidx += 2 ) {
1047+ reg = param -> from_reg + (rangeidx * BLOCK_TEST_SIZE );
1048+ for (i = 0 ; i < BLOCK_TEST_SIZE ; i ++ )
1049+ KUNIT_EXPECT_FALSE (test , data -> written [reg + i ]);
1050+ }
1051+
1052+ /* Drop range 2 */
1053+ reg = param -> from_reg + (2 * BLOCK_TEST_SIZE );
1054+ KUNIT_EXPECT_EQ (test , 0 , regcache_drop_region (map , reg , reg + BLOCK_TEST_SIZE - 1 ));
1055+
1056+ /* Drop part of range 4 */
1057+ reg = param -> from_reg + (4 * BLOCK_TEST_SIZE );
1058+ KUNIT_EXPECT_EQ (test , 0 , regcache_drop_region (map , reg + 3 , reg + 5 ));
1059+
1060+ /* Mark dirty and reset mock registers to 0 */
1061+ regcache_mark_dirty (map );
1062+ for (i = 0 ; i < config .max_register + 1 ; i ++ ) {
1063+ data -> vals [i ] = 0 ;
1064+ data -> written [i ] = false;
1065+ }
1066+
1067+ /* The registers that were dropped from range 4 should now remain at 0 */
1068+ val [4 / 2 ][3 ] = 0 ;
1069+ val [4 / 2 ][4 ] = 0 ;
1070+ val [4 / 2 ][5 ] = 0 ;
1071+
1072+ /* Sync and check that the expected register ranges were written */
1073+ KUNIT_EXPECT_EQ (test , 0 , regcache_sync (map ));
1074+
1075+ /* Check that odd ranges weren't written */
1076+ for (rangeidx = 1 ; rangeidx < num_ranges ; rangeidx += 2 ) {
1077+ reg = param -> from_reg + (rangeidx * BLOCK_TEST_SIZE );
1078+ for (i = 0 ; i < BLOCK_TEST_SIZE ; i ++ )
1079+ KUNIT_EXPECT_FALSE (test , data -> written [reg + i ]);
1080+ }
1081+
1082+ /* Check that even ranges (except 2 and 4) were written */
1083+ for (rangeidx = 0 ; rangeidx < num_ranges ; rangeidx += 2 ) {
1084+ if ((rangeidx == 2 ) || (rangeidx == 4 ))
1085+ continue ;
1086+
1087+ reg = param -> from_reg + (rangeidx * BLOCK_TEST_SIZE );
1088+ for (i = 0 ; i < BLOCK_TEST_SIZE ; i ++ )
1089+ KUNIT_EXPECT_TRUE (test , data -> written [reg + i ]);
1090+
1091+ KUNIT_EXPECT_MEMEQ (test , & data -> vals [reg ],
1092+ & val [rangeidx / 2 ], sizeof (val [rangeidx / 2 ]));
1093+ }
1094+
1095+ /* Check that range 2 wasn't written */
1096+ reg = param -> from_reg + (2 * BLOCK_TEST_SIZE );
1097+ for (i = 0 ; i < BLOCK_TEST_SIZE ; i ++ )
1098+ KUNIT_EXPECT_FALSE (test , data -> written [reg + i ]);
1099+
1100+ /* Check that range 4 was partially written */
1101+ reg = param -> from_reg + (4 * BLOCK_TEST_SIZE );
1102+ for (i = 0 ; i < BLOCK_TEST_SIZE ; i ++ )
1103+ KUNIT_EXPECT_EQ (test , data -> written [reg + i ], i < 3 || i > 5 );
1104+
1105+ KUNIT_EXPECT_MEMEQ (test , & data -> vals [reg ], & val [4 / 2 ], sizeof (val [4 / 2 ]));
1106+
1107+ /* Nothing before param->from_reg should have been written */
1108+ for (i = 0 ; i < param -> from_reg ; i ++ )
1109+ KUNIT_EXPECT_FALSE (test , data -> written [i ]);
1110+ }
1111+
10101112static void cache_drop_all_and_sync_marked_dirty (struct kunit * test )
10111113{
10121114 const struct regmap_test_param * param = test -> param_value ;
@@ -1663,6 +1765,7 @@ static struct kunit_case regmap_test_cases[] = {
16631765 KUNIT_CASE_PARAM (cache_sync_readonly , real_cache_types_gen_params ),
16641766 KUNIT_CASE_PARAM (cache_sync_patch , real_cache_types_gen_params ),
16651767 KUNIT_CASE_PARAM (cache_drop , sparse_cache_types_gen_params ),
1768+ KUNIT_CASE_PARAM (cache_drop_with_non_contiguous_ranges , sparse_cache_types_gen_params ),
16661769 KUNIT_CASE_PARAM (cache_drop_all_and_sync_marked_dirty , sparse_cache_types_gen_params ),
16671770 KUNIT_CASE_PARAM (cache_drop_all_and_sync_no_defaults , sparse_cache_types_gen_params ),
16681771 KUNIT_CASE_PARAM (cache_drop_all_and_sync_has_defaults , sparse_cache_types_gen_params ),
0 commit comments