1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // KUnit tests for cs_dsp.
4 //
5 // Copyright (C) 2024 Cirrus Logic, Inc. and
6 //                    Cirrus Logic International Semiconductor Ltd.
7 
8 #include <kunit/device.h>
9 #include <kunit/resource.h>
10 #include <kunit/test.h>
11 #include <linux/build_bug.h>
12 #include <linux/firmware/cirrus/cs_dsp.h>
13 #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
14 #include <linux/firmware/cirrus/wmfw.h>
15 #include <linux/list.h>
16 #include <linux/random.h>
17 #include <linux/regmap.h>
18 
19 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
20 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_stop_wrapper, cs_dsp_stop, struct cs_dsp *);
21 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
22 
23 struct cs_dsp_test_local {
24 	struct cs_dsp_mock_xm_header *xm_header;
25 	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
26 	int wmfw_version;
27 };
28 
29 struct cs_dsp_ctl_rw_test_param {
30 	int mem_type;
31 	int alg_id;
32 	unsigned int offs_words;
33 	unsigned int len_bytes;
34 	u16 ctl_type;
35 	u16 flags;
36 };
37 
38 static const struct cs_dsp_mock_alg_def cs_dsp_ctl_rw_test_algs[] = {
39 	{
40 		.id = 0xfafa,
41 		.ver = 0x100000,
42 		.xm_base_words = 60,
43 		.xm_size_words = 1000,
44 		.ym_base_words = 0,
45 		.ym_size_words = 1000,
46 		.zm_base_words = 0,
47 		.zm_size_words = 1000,
48 	},
49 	{
50 		.id = 0xb,
51 		.ver = 0x100001,
52 		.xm_base_words = 1060,
53 		.xm_size_words = 1000,
54 		.ym_base_words = 1000,
55 		.ym_size_words = 1000,
56 		.zm_base_words = 1000,
57 		.zm_size_words = 1000,
58 	},
59 	{
60 		.id = 0x9f1234,
61 		.ver = 0x100500,
62 		.xm_base_words = 2060,
63 		.xm_size_words = 32,
64 		.ym_base_words = 2000,
65 		.ym_size_words = 32,
66 		.zm_base_words = 2000,
67 		.zm_size_words = 32,
68 	},
69 	{
70 		.id = 0xff00ff,
71 		.ver = 0x300113,
72 		.xm_base_words = 2100,
73 		.xm_size_words = 32,
74 		.ym_base_words = 2032,
75 		.ym_size_words = 32,
76 		.zm_base_words = 2032,
77 		.zm_size_words = 32,
78 	},
79 };
80 
81 static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
82 	.shortname = "Dummy Coeff",
83 	.type = WMFW_CTL_TYPE_BYTES,
84 	.mem_type = WMFW_ADSP2_YM,
85 	.flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
86 	.length_bytes = 4,
87 };
88 
_find_alg_entry(struct kunit * test,unsigned int alg_id)89 static int _find_alg_entry(struct kunit *test, unsigned int alg_id)
90 {
91 	int i;
92 
93 	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_rw_test_algs); ++i) {
94 		if (cs_dsp_ctl_rw_test_algs[i].id == alg_id)
95 			break;
96 	}
97 
98 	KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(cs_dsp_ctl_rw_test_algs));
99 
100 	return i;
101 }
102 
_get_alg_mem_base_words(struct kunit * test,int alg_index,int mem_type)103 static int _get_alg_mem_base_words(struct kunit *test, int alg_index, int mem_type)
104 {
105 	switch (mem_type) {
106 	case WMFW_ADSP2_XM:
107 		return cs_dsp_ctl_rw_test_algs[alg_index].xm_base_words;
108 	case WMFW_ADSP2_YM:
109 		return cs_dsp_ctl_rw_test_algs[alg_index].ym_base_words;
110 	case WMFW_ADSP2_ZM:
111 		return cs_dsp_ctl_rw_test_algs[alg_index].zm_base_words;
112 	default:
113 		KUNIT_FAIL(test, "Bug in test: illegal memory type %d\n", mem_type);
114 		return 0;
115 	}
116 }
117 
_create_dummy_wmfw(struct kunit * test)118 static struct cs_dsp_mock_wmfw_builder *_create_dummy_wmfw(struct kunit *test)
119 {
120 	struct cs_dsp_test *priv = test->priv;
121 	struct cs_dsp_test_local *local = priv->local;
122 	struct cs_dsp_mock_wmfw_builder *builder;
123 
124 	builder = cs_dsp_mock_wmfw_init(priv, local->wmfw_version);
125 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder);
126 
127 	/* Init an XM header */
128 	cs_dsp_mock_wmfw_add_data_block(builder,
129 					WMFW_ADSP2_XM, 0,
130 					local->xm_header->blob_data,
131 					local->xm_header->blob_size_bytes);
132 
133 	return builder;
134 }
135 
136 /*
137  * Write to a control while the firmware is running.
138  * This should write to the underlying registers.
139  */
cs_dsp_ctl_write_running(struct kunit * test)140 static void cs_dsp_ctl_write_running(struct kunit *test)
141 {
142 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
143 	struct cs_dsp_test *priv = test->priv;
144 	struct cs_dsp_test_local *local = priv->local;
145 	struct cs_dsp *dsp = priv->dsp;
146 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
147 	int alg_idx = _find_alg_entry(test, param->alg_id);
148 	unsigned int reg, alg_base_words;
149 	struct cs_dsp_coeff_ctl *ctl;
150 	struct firmware *wmfw;
151 	u32 *reg_vals, *readback;
152 
153 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
154 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
155 
156 	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
157 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
158 
159 	/* Create some initial register content */
160 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
161 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
162 	reg += (alg_base_words + param->offs_words) *
163 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
164 	memset(reg_vals, 0, param->len_bytes);
165 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
166 
167 	/* Create control pointing to this data */
168 	def.flags = param->flags;
169 	def.mem_type = param->mem_type;
170 	def.offset_dsp_words = param->offs_words;
171 	def.length_bytes = param->len_bytes;
172 
173 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
174 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
175 					      "dummyalg", NULL);
176 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
177 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
178 
179 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
180 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
181 
182 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
183 	KUNIT_ASSERT_NOT_NULL(test, ctl);
184 
185 	/* Start the firmware and add an action to stop it during cleanup */
186 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
187 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
188 
189 	/*
190 	 * Write new data to the control, it should be written to the registers
191 	 * and cs_dsp_coeff_lock_and_write_ctrl() should return 1 to indicate
192 	 * that the control content changed.
193 	 */
194 	get_random_bytes(reg_vals, param->len_bytes);
195 	KUNIT_EXPECT_EQ(test,
196 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
197 			1);
198 	KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
199 	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
200 
201 	/* Drop expected writes and the regmap cache should be clean */
202 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
203 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
204 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
205 }
206 
207 /*
208  * Read from a volatile control while the firmware is running.
209  * This should return the current state of the underlying registers.
210  */
cs_dsp_ctl_read_volatile_running(struct kunit * test)211 static void cs_dsp_ctl_read_volatile_running(struct kunit *test)
212 {
213 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
214 	struct cs_dsp_test *priv = test->priv;
215 	struct cs_dsp_test_local *local = priv->local;
216 	struct cs_dsp *dsp = priv->dsp;
217 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
218 	int alg_idx = _find_alg_entry(test, param->alg_id);
219 	unsigned int reg, alg_base_words;
220 	struct cs_dsp_coeff_ctl *ctl;
221 	struct firmware *wmfw;
222 	u32 *reg_vals, *readback;
223 
224 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
225 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
226 
227 	readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
228 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
229 
230 	/* Create some initial register content */
231 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
232 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
233 	reg += (alg_base_words + param->offs_words) *
234 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
235 	memset(reg_vals, 0, param->len_bytes);
236 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
237 
238 	/* Create control pointing to this data */
239 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
240 	def.mem_type = param->mem_type;
241 	def.offset_dsp_words = param->offs_words;
242 	def.length_bytes = param->len_bytes;
243 
244 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
245 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
246 					      "dummyalg", NULL);
247 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
248 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
249 
250 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
251 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
252 
253 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
254 	KUNIT_ASSERT_NOT_NULL(test, ctl);
255 
256 	/* Start the firmware and add an action to stop it during cleanup */
257 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
258 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
259 
260 	/* Read the control, it should return the current register content */
261 	KUNIT_EXPECT_EQ(test,
262 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
263 			0);
264 	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
265 
266 	/*
267 	 * Change the register content and read the control, it should return
268 	 * the new register content
269 	 */
270 	get_random_bytes(reg_vals, param->len_bytes);
271 	KUNIT_ASSERT_EQ(test, regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes), 0);
272 	KUNIT_EXPECT_EQ(test,
273 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
274 			0);
275 	KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
276 }
277 
278 /*
279  * Read from a volatile control before the firmware is started.
280  * This should return an error.
281  */
cs_dsp_ctl_read_volatile_not_started(struct kunit * test)282 static void cs_dsp_ctl_read_volatile_not_started(struct kunit *test)
283 {
284 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
285 	struct cs_dsp_test *priv = test->priv;
286 	struct cs_dsp_test_local *local = priv->local;
287 	struct cs_dsp *dsp = priv->dsp;
288 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
289 	int alg_idx = _find_alg_entry(test, param->alg_id);
290 	unsigned int reg, alg_base_words;
291 	struct cs_dsp_coeff_ctl *ctl;
292 	struct firmware *wmfw;
293 	u32 *reg_vals;
294 
295 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
296 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
297 
298 	/* Create some initial register content */
299 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
300 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
301 	reg += (alg_base_words + param->offs_words) *
302 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
303 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
304 
305 	/* Create control pointing to this data */
306 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
307 	def.mem_type = param->mem_type;
308 	def.offset_dsp_words = param->offs_words;
309 	def.length_bytes = param->len_bytes;
310 
311 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
312 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
313 					      "dummyalg", NULL);
314 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
315 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
316 
317 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
318 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
319 
320 	/* Read the control, it should return an error */
321 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
322 	KUNIT_ASSERT_NOT_NULL(test, ctl);
323 	KUNIT_EXPECT_LT(test,
324 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
325 			0);
326 }
327 
328 /*
329  * Read from a volatile control after the firmware has stopped.
330  * This should return an error.
331  */
cs_dsp_ctl_read_volatile_stopped(struct kunit * test)332 static void cs_dsp_ctl_read_volatile_stopped(struct kunit *test)
333 {
334 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
335 	struct cs_dsp_test *priv = test->priv;
336 	struct cs_dsp_test_local *local = priv->local;
337 	struct cs_dsp *dsp = priv->dsp;
338 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
339 	int alg_idx = _find_alg_entry(test, param->alg_id);
340 	unsigned int reg, alg_base_words;
341 	struct cs_dsp_coeff_ctl *ctl;
342 	struct firmware *wmfw;
343 	u32 *reg_vals;
344 
345 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
346 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
347 
348 	/* Create some initial register content */
349 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
350 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
351 	reg += (alg_base_words + param->offs_words) *
352 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
353 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
354 
355 	/* Create control pointing to this data */
356 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
357 	def.mem_type = param->mem_type;
358 	def.offset_dsp_words = param->offs_words;
359 	def.length_bytes = param->len_bytes;
360 
361 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
362 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
363 					      "dummyalg", NULL);
364 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
365 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
366 
367 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
368 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
369 
370 	/* Start and stop the firmware */
371 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
372 	cs_dsp_stop(dsp);
373 
374 	/* Read the control, it should return an error */
375 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
376 	KUNIT_ASSERT_NOT_NULL(test, ctl);
377 	KUNIT_EXPECT_LT(test,
378 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
379 			0);
380 }
381 
382 /*
383  * Read from a volatile control after the DSP has been powered down.
384  * This should return an error.
385  */
cs_dsp_ctl_read_volatile_stopped_powered_down(struct kunit * test)386 static void cs_dsp_ctl_read_volatile_stopped_powered_down(struct kunit *test)
387 {
388 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
389 	struct cs_dsp_test *priv = test->priv;
390 	struct cs_dsp_test_local *local = priv->local;
391 	struct cs_dsp *dsp = priv->dsp;
392 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
393 	int alg_idx = _find_alg_entry(test, param->alg_id);
394 	unsigned int reg, alg_base_words;
395 	struct cs_dsp_coeff_ctl *ctl;
396 	struct firmware *wmfw;
397 	u32 *reg_vals;
398 
399 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
400 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
401 
402 	/* Create some initial register content */
403 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
404 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
405 	reg += (alg_base_words + param->offs_words) *
406 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
407 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
408 
409 	/* Create control pointing to this data */
410 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
411 	def.mem_type = param->mem_type;
412 	def.offset_dsp_words = param->offs_words;
413 	def.length_bytes = param->len_bytes;
414 
415 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
416 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
417 					      "dummyalg", NULL);
418 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
419 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
420 
421 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
422 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
423 
424 	/* Start and stop the firmware then power down */
425 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
426 	cs_dsp_stop(dsp);
427 	cs_dsp_power_down(dsp);
428 
429 	/* Read the control, it should return an error */
430 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
431 	KUNIT_ASSERT_NOT_NULL(test, ctl);
432 	KUNIT_EXPECT_LT(test,
433 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
434 			0);
435 }
436 
437 /*
438  * Read from a volatile control when a different firmware is currently
439  * loaded into the DSP.
440  * Should return an error.
441  */
cs_dsp_ctl_read_volatile_not_current_loaded_fw(struct kunit * test)442 static void cs_dsp_ctl_read_volatile_not_current_loaded_fw(struct kunit *test)
443 {
444 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
445 	struct cs_dsp_test *priv = test->priv;
446 	struct cs_dsp_test_local *local = priv->local;
447 	struct cs_dsp *dsp = priv->dsp;
448 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
449 	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
450 	int alg_idx = _find_alg_entry(test, param->alg_id);
451 	unsigned int reg, alg_base_words;
452 	struct cs_dsp_coeff_ctl *ctl;
453 	struct firmware *wmfw;
454 	u32 *reg_vals;
455 
456 	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
457 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
458 
459 	/* Create some DSP data to be read into the control cache */
460 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
461 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
462 	reg += (alg_base_words + param->offs_words) *
463 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
464 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
465 
466 	/* Create control pointing to this data */
467 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
468 	def.mem_type = param->mem_type;
469 	def.offset_dsp_words = param->offs_words;
470 	def.length_bytes = param->len_bytes;
471 
472 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
473 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
474 					      "dummyalg", NULL);
475 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
476 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
477 
478 	/* Power-up DSP */
479 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
480 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
481 
482 	/* Power-down DSP then power-up with a different firmware */
483 	cs_dsp_power_down(dsp);
484 	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
485 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
486 
487 	/* Read the control, it should return an error */
488 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
489 	KUNIT_ASSERT_NOT_NULL(test, ctl);
490 	KUNIT_EXPECT_LT(test,
491 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
492 			0);
493 }
494 
495 /*
496  * Read from a volatile control when a different firmware is currently
497  * running.
498  * Should return an error.
499  */
cs_dsp_ctl_read_volatile_not_current_running_fw(struct kunit * test)500 static void cs_dsp_ctl_read_volatile_not_current_running_fw(struct kunit *test)
501 {
502 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
503 	struct cs_dsp_test *priv = test->priv;
504 	struct cs_dsp_test_local *local = priv->local;
505 	struct cs_dsp *dsp = priv->dsp;
506 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
507 	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
508 	int alg_idx = _find_alg_entry(test, param->alg_id);
509 	unsigned int reg, alg_base_words;
510 	struct cs_dsp_coeff_ctl *ctl;
511 	struct firmware *wmfw;
512 	u32 *reg_vals;
513 
514 	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
515 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
516 
517 	/* Create some DSP data to be read into the control cache */
518 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
519 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
520 	reg += (alg_base_words + param->offs_words) *
521 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
522 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
523 
524 	/* Create control pointing to this data */
525 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
526 	def.mem_type = param->mem_type;
527 	def.offset_dsp_words = param->offs_words;
528 	def.length_bytes = param->len_bytes;
529 
530 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
531 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
532 					      "dummyalg", NULL);
533 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
534 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
535 
536 	/* Power-up DSP */
537 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
538 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
539 
540 	/* Power-down DSP then power-up with a different firmware */
541 	cs_dsp_power_down(dsp);
542 	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
543 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
544 
545 	/* Start the firmware and add an action to stop it during cleanup */
546 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
547 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
548 
549 	/* Read the control, it should return an error */
550 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
551 	KUNIT_ASSERT_NOT_NULL(test, ctl);
552 	KUNIT_EXPECT_LT(test,
553 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, param->len_bytes),
554 			0);
555 }
556 
557 /*
558  * Write to a volatile control before the firmware is started.
559  * This should return an error.
560  */
cs_dsp_ctl_write_volatile_not_started(struct kunit * test)561 static void cs_dsp_ctl_write_volatile_not_started(struct kunit *test)
562 {
563 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
564 	struct cs_dsp_test *priv = test->priv;
565 	struct cs_dsp_test_local *local = priv->local;
566 	struct cs_dsp *dsp = priv->dsp;
567 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
568 	int alg_idx = _find_alg_entry(test, param->alg_id);
569 	unsigned int reg, alg_base_words;
570 	struct cs_dsp_coeff_ctl *ctl;
571 	struct firmware *wmfw;
572 	u32 *reg_vals;
573 
574 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
575 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
576 
577 	/* Create some initial register content */
578 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
579 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
580 	reg += (alg_base_words + param->offs_words) *
581 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
582 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
583 
584 	/* Create control pointing to this data */
585 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
586 	def.mem_type = param->mem_type;
587 	def.offset_dsp_words = param->offs_words;
588 	def.length_bytes = param->len_bytes;
589 
590 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
591 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
592 					      "dummyalg", NULL);
593 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
594 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
595 
596 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
597 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
598 
599 	/* Drop expected writes and the regmap cache should be clean */
600 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
601 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
602 
603 	/* Write the control, it should return an error */
604 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
605 	KUNIT_ASSERT_NOT_NULL(test, ctl);
606 	KUNIT_EXPECT_LT(test,
607 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
608 			0);
609 
610 	/* Should not have been any writes to registers */
611 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
612 }
613 
614 /*
615  * Write to a volatile control after the firmware has stopped.
616  * This should return an error.
617  */
cs_dsp_ctl_write_volatile_stopped(struct kunit * test)618 static void cs_dsp_ctl_write_volatile_stopped(struct kunit *test)
619 {
620 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
621 	struct cs_dsp_test *priv = test->priv;
622 	struct cs_dsp_test_local *local = priv->local;
623 	struct cs_dsp *dsp = priv->dsp;
624 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
625 	int alg_idx = _find_alg_entry(test, param->alg_id);
626 	unsigned int reg, alg_base_words;
627 	struct cs_dsp_coeff_ctl *ctl;
628 	struct firmware *wmfw;
629 	u32 *reg_vals;
630 
631 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
632 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
633 
634 	/* Create some initial register content */
635 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
636 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
637 	reg += (alg_base_words + param->offs_words) *
638 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
639 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
640 
641 	/* Create control pointing to this data */
642 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
643 	def.mem_type = param->mem_type;
644 	def.offset_dsp_words = param->offs_words;
645 	def.length_bytes = param->len_bytes;
646 
647 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
648 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
649 					      "dummyalg", NULL);
650 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
651 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
652 
653 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
654 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
655 
656 	/* Start and stop the firmware */
657 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
658 	cs_dsp_stop(dsp);
659 
660 	/* Drop expected writes and the regmap cache should be clean */
661 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
662 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
663 
664 	/* Write the control, it should return an error */
665 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
666 	KUNIT_ASSERT_NOT_NULL(test, ctl);
667 	KUNIT_EXPECT_LT(test,
668 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
669 			0);
670 
671 	/* Should not have been any writes to registers */
672 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
673 }
674 
675 /*
676  * Write to a volatile control after the DSP has been powered down.
677  * This should return an error.
678  */
cs_dsp_ctl_write_volatile_stopped_powered_down(struct kunit * test)679 static void cs_dsp_ctl_write_volatile_stopped_powered_down(struct kunit *test)
680 {
681 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
682 	struct cs_dsp_test *priv = test->priv;
683 	struct cs_dsp_test_local *local = priv->local;
684 	struct cs_dsp *dsp = priv->dsp;
685 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
686 	int alg_idx = _find_alg_entry(test, param->alg_id);
687 	unsigned int reg, alg_base_words;
688 	struct cs_dsp_coeff_ctl *ctl;
689 	struct firmware *wmfw;
690 	u32 *reg_vals;
691 
692 	reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
693 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
694 
695 	/* Create some initial register content */
696 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
697 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
698 	reg += (alg_base_words + param->offs_words) *
699 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
700 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
701 
702 	/* Create control pointing to this data */
703 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
704 	def.mem_type = param->mem_type;
705 	def.offset_dsp_words = param->offs_words;
706 	def.length_bytes = param->len_bytes;
707 
708 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
709 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
710 					      "dummyalg", NULL);
711 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
712 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
713 
714 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
715 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
716 
717 	/* Start and stop the firmware then power down */
718 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
719 	cs_dsp_stop(dsp);
720 	cs_dsp_power_down(dsp);
721 
722 	/* Drop expected writes and the regmap cache should be clean */
723 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
724 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
725 
726 	/* Write the control, it should return an error */
727 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
728 	KUNIT_ASSERT_NOT_NULL(test, ctl);
729 	KUNIT_EXPECT_LT(test,
730 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
731 			0);
732 
733 	/* Should not have been any writes to registers */
734 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
735 }
736 
737 /*
738  * Write to a volatile control when a different firmware is currently
739  * loaded into the DSP.
740  * Should return an error.
741  */
cs_dsp_ctl_write_volatile_not_current_loaded_fw(struct kunit * test)742 static void cs_dsp_ctl_write_volatile_not_current_loaded_fw(struct kunit *test)
743 {
744 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
745 	struct cs_dsp_test *priv = test->priv;
746 	struct cs_dsp_test_local *local = priv->local;
747 	struct cs_dsp *dsp = priv->dsp;
748 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
749 	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
750 	int alg_idx = _find_alg_entry(test, param->alg_id);
751 	unsigned int reg, alg_base_words;
752 	struct cs_dsp_coeff_ctl *ctl;
753 	struct firmware *wmfw;
754 	u32 *reg_vals;
755 
756 	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
757 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
758 
759 	/* Create some DSP data to be read into the control cache */
760 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
761 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
762 	reg += (alg_base_words + param->offs_words) *
763 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
764 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
765 
766 	/* Create control pointing to this data */
767 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
768 	def.mem_type = param->mem_type;
769 	def.offset_dsp_words = param->offs_words;
770 	def.length_bytes = param->len_bytes;
771 
772 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
773 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
774 					      "dummyalg", NULL);
775 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
776 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
777 
778 	/* Power-up DSP */
779 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
780 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
781 
782 	/* Power-down DSP then power-up with a different firmware */
783 	cs_dsp_power_down(dsp);
784 	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
785 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
786 
787 	/* Drop expected writes and the regmap cache should be clean */
788 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
789 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
790 
791 	/* Write the control, it should return an error */
792 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
793 	KUNIT_ASSERT_NOT_NULL(test, ctl);
794 	KUNIT_EXPECT_LT(test,
795 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
796 			0);
797 
798 	/* Should not have been any writes to registers */
799 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
800 }
801 
802 /*
803  * Write to a volatile control when a different firmware is currently
804  * running.
805  * Should return an error.
806  */
cs_dsp_ctl_write_volatile_not_current_running_fw(struct kunit * test)807 static void cs_dsp_ctl_write_volatile_not_current_running_fw(struct kunit *test)
808 {
809 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
810 	struct cs_dsp_test *priv = test->priv;
811 	struct cs_dsp_test_local *local = priv->local;
812 	struct cs_dsp *dsp = priv->dsp;
813 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
814 	struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
815 	int alg_idx = _find_alg_entry(test, param->alg_id);
816 	unsigned int reg, alg_base_words;
817 	struct cs_dsp_coeff_ctl *ctl;
818 	struct firmware *wmfw;
819 	u32 *reg_vals;
820 
821 	reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
822 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
823 
824 	/* Create some DSP data to be read into the control cache */
825 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
826 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
827 	reg += (alg_base_words + param->offs_words) *
828 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
829 	regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
830 
831 	/* Create control pointing to this data */
832 	def.flags = param->flags | WMFW_CTL_FLAG_VOLATILE;
833 	def.mem_type = param->mem_type;
834 	def.offset_dsp_words = param->offs_words;
835 	def.length_bytes = param->len_bytes;
836 
837 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
838 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
839 					      "dummyalg", NULL);
840 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
841 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
842 
843 	/* Power-up DSP */
844 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
845 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
846 
847 	/* Power-down DSP then power-up with a different firmware */
848 	cs_dsp_power_down(dsp);
849 	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
850 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
851 
852 	/* Start the firmware and add an action to stop it during cleanup */
853 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
854 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
855 
856 	/* Drop expected writes and the regmap cache should be clean */
857 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
858 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
859 
860 	/* Write the control, it should return an error */
861 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
862 	KUNIT_ASSERT_NOT_NULL(test, ctl);
863 	KUNIT_EXPECT_LT(test,
864 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
865 			0);
866 
867 	/* Should not have been any writes to registers */
868 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
869 }
870 
871 /*
872  * Read from an offset into the control data. Should return only the
873  * portion of data from the offset position.
874  */
cs_dsp_ctl_read_with_seek(struct kunit * test)875 static void cs_dsp_ctl_read_with_seek(struct kunit *test)
876 {
877 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
878 	struct cs_dsp_test *priv = test->priv;
879 	struct cs_dsp_test_local *local = priv->local;
880 	struct cs_dsp *dsp = priv->dsp;
881 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
882 	int alg_idx = _find_alg_entry(test, param->alg_id);
883 	unsigned int reg, alg_base_words;
884 	struct cs_dsp_coeff_ctl *ctl;
885 	struct firmware *wmfw;
886 	u32 *reg_vals, *readback;
887 	unsigned int seek_words;
888 
889 	def.flags = param->flags;
890 	def.mem_type = param->mem_type;
891 	def.offset_dsp_words = param->offs_words;
892 	def.length_bytes = 48;
893 
894 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
895 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
896 
897 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
898 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
899 
900 	/* Create some initial register content */
901 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
902 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
903 	reg += (alg_base_words + param->offs_words) *
904 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
905 	get_random_bytes(reg_vals, def.length_bytes);
906 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
907 
908 	/* Create control pointing to this data */
909 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
910 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
911 					      "dummyalg", NULL);
912 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
913 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
914 
915 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
916 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
917 
918 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
919 	KUNIT_ASSERT_NOT_NULL(test, ctl);
920 
921 	/* Start the firmware and add an action to stop it during cleanup */
922 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
923 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
924 
925 	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
926 		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
927 
928 		KUNIT_EXPECT_EQ(test,
929 				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
930 								readback, len_bytes),
931 				0);
932 		KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
933 	}
934 }
935 
936 /*
937  * Read from an offset into the control cache. Should return only the
938  * portion of data from the offset position.
939  * Same as cs_dsp_ctl_read_with_seek() except the control is cached
940  * and the firmware is not running.
941  */
cs_dsp_ctl_read_cache_with_seek(struct kunit * test)942 static void cs_dsp_ctl_read_cache_with_seek(struct kunit *test)
943 {
944 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
945 	struct cs_dsp_test *priv = test->priv;
946 	struct cs_dsp_test_local *local = priv->local;
947 	struct cs_dsp *dsp = priv->dsp;
948 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
949 	int alg_idx = _find_alg_entry(test, param->alg_id);
950 	unsigned int reg, alg_base_words;
951 	struct cs_dsp_coeff_ctl *ctl;
952 	struct firmware *wmfw;
953 	u32 *reg_vals, *readback;
954 	unsigned int seek_words;
955 
956 	def.flags = param->flags;
957 	def.mem_type = param->mem_type;
958 	def.offset_dsp_words = param->offs_words;
959 	def.length_bytes = 48;
960 
961 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
962 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
963 
964 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
965 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
966 
967 	/* Create some initial register content */
968 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
969 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
970 	reg += (alg_base_words + param->offs_words) *
971 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
972 	get_random_bytes(reg_vals, def.length_bytes);
973 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
974 
975 	/* Create control pointing to this data */
976 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
977 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
978 					      "dummyalg", NULL);
979 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
980 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
981 
982 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
983 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
984 
985 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
986 	KUNIT_ASSERT_NOT_NULL(test, ctl);
987 
988 	/* Start and stop the firmware so the read will come from the cache */
989 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
990 	cs_dsp_stop(dsp);
991 
992 	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
993 		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
994 
995 		KUNIT_EXPECT_EQ(test,
996 				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
997 								readback, len_bytes),
998 				0);
999 		KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
1000 	}
1001 }
1002 
1003 /*
1004  * Read less than the full length of data from a control. Should return
1005  * only the requested number of bytes.
1006  */
cs_dsp_ctl_read_truncated(struct kunit * test)1007 static void cs_dsp_ctl_read_truncated(struct kunit *test)
1008 {
1009 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1010 	struct cs_dsp_test *priv = test->priv;
1011 	struct cs_dsp_test_local *local = priv->local;
1012 	struct cs_dsp *dsp = priv->dsp;
1013 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1014 	int alg_idx = _find_alg_entry(test, param->alg_id);
1015 	unsigned int reg, alg_base_words;
1016 	struct cs_dsp_coeff_ctl *ctl;
1017 	struct firmware *wmfw;
1018 	u32 *reg_vals, *readback;
1019 	unsigned int len_bytes;
1020 
1021 	def.flags = param->flags;
1022 	def.mem_type = param->mem_type;
1023 	def.offset_dsp_words = param->offs_words;
1024 	def.length_bytes = 48;
1025 
1026 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1027 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1028 
1029 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1030 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1031 
1032 	/* Create some initial register content */
1033 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1034 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1035 	reg += (alg_base_words + param->offs_words) *
1036 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1037 	get_random_bytes(reg_vals, def.length_bytes);
1038 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1039 
1040 	/* Create control pointing to this data */
1041 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1042 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1043 					      "dummyalg", NULL);
1044 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1045 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1046 
1047 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1048 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1049 
1050 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1051 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1052 
1053 	/* Start the firmware and add an action to stop it during cleanup */
1054 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1055 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1056 
1057 	/* Reads are only allowed to be a multiple of the DSP word length */
1058 	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1059 		memset(readback, 0, def.length_bytes);
1060 		KUNIT_EXPECT_EQ(test,
1061 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, len_bytes),
1062 				0);
1063 		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, len_bytes);
1064 		KUNIT_EXPECT_MEMNEQ(test,
1065 				    (u8 *)readback + len_bytes,
1066 				    (u8 *)reg_vals + len_bytes,
1067 				    def.length_bytes - len_bytes);
1068 	}
1069 }
1070 
1071 /*
1072  * Read less than the full length of data from a cached control.
1073  * Should return only the requested number of bytes.
1074  * Same as cs_dsp_ctl_read_truncated() except the control is cached
1075  * and the firmware is not running.
1076  */
cs_dsp_ctl_read_cache_truncated(struct kunit * test)1077 static void cs_dsp_ctl_read_cache_truncated(struct kunit *test)
1078 {
1079 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1080 	struct cs_dsp_test *priv = test->priv;
1081 	struct cs_dsp_test_local *local = priv->local;
1082 	struct cs_dsp *dsp = priv->dsp;
1083 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1084 	int alg_idx = _find_alg_entry(test, param->alg_id);
1085 	unsigned int reg, alg_base_words;
1086 	struct cs_dsp_coeff_ctl *ctl;
1087 	struct firmware *wmfw;
1088 	u32 *reg_vals, *readback;
1089 	unsigned int len_bytes;
1090 
1091 	def.flags = param->flags;
1092 	def.mem_type = param->mem_type;
1093 	def.offset_dsp_words = param->offs_words;
1094 	def.length_bytes = 48;
1095 
1096 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1097 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1098 
1099 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1100 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1101 
1102 	/* Create some initial register content */
1103 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1104 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1105 	reg += (alg_base_words + param->offs_words) *
1106 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1107 	get_random_bytes(reg_vals, def.length_bytes);
1108 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1109 
1110 	/* Create control pointing to this data */
1111 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1112 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1113 					      "dummyalg", NULL);
1114 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1115 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1116 
1117 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1118 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1119 
1120 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1121 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1122 
1123 	/* Start and stop the firmware so the read will come from the cache */
1124 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1125 	cs_dsp_stop(dsp);
1126 
1127 	/* Reads are only allowed to be a multiple of the DSP word length */
1128 	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1129 		memset(readback, 0, def.length_bytes);
1130 		KUNIT_EXPECT_EQ(test,
1131 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, len_bytes),
1132 				0);
1133 		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, len_bytes);
1134 		KUNIT_EXPECT_MEMNEQ(test,
1135 				    (u8 *)readback + len_bytes,
1136 				    (u8 *)reg_vals + len_bytes,
1137 				    def.length_bytes - len_bytes);
1138 	}
1139 }
1140 
1141 /*
1142  * Write to an offset into the control data. Should only change the
1143  * portion of data from the offset position.
1144  */
cs_dsp_ctl_write_with_seek(struct kunit * test)1145 static void cs_dsp_ctl_write_with_seek(struct kunit *test)
1146 {
1147 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1148 	struct cs_dsp_test *priv = test->priv;
1149 	struct cs_dsp_test_local *local = priv->local;
1150 	struct cs_dsp *dsp = priv->dsp;
1151 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1152 	int alg_idx = _find_alg_entry(test, param->alg_id);
1153 	unsigned int reg, alg_base_words;
1154 	struct cs_dsp_coeff_ctl *ctl;
1155 	struct firmware *wmfw;
1156 	u32 *reg_vals, *readback, *new_data;
1157 	unsigned int seek_words;
1158 
1159 	def.flags = param->flags;
1160 	def.mem_type = param->mem_type;
1161 	def.offset_dsp_words = param->offs_words;
1162 	def.length_bytes = 48;
1163 
1164 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1165 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1166 
1167 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1168 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1169 
1170 	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1171 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1172 
1173 	/* Create some initial register content */
1174 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1175 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1176 	reg += (alg_base_words + param->offs_words) *
1177 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1178 	get_random_bytes(reg_vals, def.length_bytes);
1179 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1180 
1181 	/* Create control pointing to this data */
1182 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1183 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1184 					      "dummyalg", NULL);
1185 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1186 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1187 
1188 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1189 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1190 
1191 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1192 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1193 
1194 	/* Start the firmware and add an action to stop it during cleanup */
1195 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1196 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1197 
1198 	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
1199 		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
1200 
1201 		/* Reset the register values to the test data */
1202 		regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1203 
1204 		get_random_bytes(new_data, def.length_bytes);
1205 		KUNIT_EXPECT_EQ(test,
1206 				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1207 								 new_data, len_bytes),
1208 				1);
1209 		KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, def.length_bytes),
1210 				0);
1211 		/* Initial portion of readback should be unchanged */
1212 		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, seek_words * sizeof(u32));
1213 		KUNIT_EXPECT_MEMEQ(test, &readback[seek_words], new_data, len_bytes);
1214 	}
1215 }
1216 
1217 /*
1218  * Write to an offset into the control cache. Should only change the
1219  * portion of data from the offset position.
1220  * Same as cs_dsp_ctl_write_with_seek() except the control is cached
1221  * and the firmware is not running.
1222  */
cs_dsp_ctl_write_cache_with_seek(struct kunit * test)1223 static void cs_dsp_ctl_write_cache_with_seek(struct kunit *test)
1224 {
1225 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1226 	struct cs_dsp_test *priv = test->priv;
1227 	struct cs_dsp_test_local *local = priv->local;
1228 	struct cs_dsp *dsp = priv->dsp;
1229 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1230 	int alg_idx = _find_alg_entry(test, param->alg_id);
1231 	unsigned int reg, alg_base_words;
1232 	struct cs_dsp_coeff_ctl *ctl;
1233 	struct firmware *wmfw;
1234 	u32 *reg_vals, *readback, *new_data;
1235 	unsigned int seek_words;
1236 
1237 	def.flags = param->flags;
1238 	def.mem_type = param->mem_type;
1239 	def.offset_dsp_words = param->offs_words;
1240 	def.length_bytes = 48;
1241 
1242 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1243 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1244 
1245 	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1246 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1247 
1248 	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1249 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1250 
1251 	/* Create some initial register content */
1252 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1253 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1254 	reg += (alg_base_words + param->offs_words) *
1255 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1256 	get_random_bytes(reg_vals, def.length_bytes);
1257 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1258 
1259 	/* Create control pointing to this data */
1260 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1261 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1262 					      "dummyalg", NULL);
1263 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1264 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1265 
1266 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1267 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1268 
1269 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1270 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1271 
1272 	/* Start and stop the firmware so the read will come from the cache */
1273 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1274 	cs_dsp_stop(dsp);
1275 
1276 	for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
1277 		unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
1278 
1279 		/* Reset the cache to the test data */
1280 		KUNIT_EXPECT_GE(test,
1281 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1282 								 def.length_bytes),
1283 				0);
1284 
1285 		get_random_bytes(new_data, def.length_bytes);
1286 		KUNIT_EXPECT_EQ(test,
1287 				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1288 								 new_data, len_bytes),
1289 				1);
1290 
1291 		memset(readback, 0, def.length_bytes);
1292 		KUNIT_EXPECT_EQ(test,
1293 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1294 								def.length_bytes),
1295 				0);
1296 		/* Initial portion of readback should be unchanged */
1297 		KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, seek_words * sizeof(u32));
1298 		KUNIT_EXPECT_MEMEQ(test, &readback[seek_words], new_data, len_bytes);
1299 	}
1300 }
1301 
1302 /*
1303  * Write less than the full length of data to a control. Should only
1304  * change the requested number of bytes.
1305  */
cs_dsp_ctl_write_truncated(struct kunit * test)1306 static void cs_dsp_ctl_write_truncated(struct kunit *test)
1307 {
1308 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1309 	struct cs_dsp_test *priv = test->priv;
1310 	struct cs_dsp_test_local *local = priv->local;
1311 	struct cs_dsp *dsp = priv->dsp;
1312 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1313 	int alg_idx = _find_alg_entry(test, param->alg_id);
1314 	unsigned int reg, alg_base_words;
1315 	struct cs_dsp_coeff_ctl *ctl;
1316 	struct firmware *wmfw;
1317 	u32 *reg_vals, *readback, *new_data;
1318 	unsigned int len_bytes;
1319 
1320 	def.flags = param->flags;
1321 	def.mem_type = param->mem_type;
1322 	def.offset_dsp_words = param->offs_words;
1323 	def.length_bytes = 48;
1324 
1325 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1326 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1327 
1328 	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1329 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1330 
1331 	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1332 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1333 
1334 	/* Create some initial register content */
1335 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1336 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1337 	reg += (alg_base_words + param->offs_words) *
1338 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1339 	get_random_bytes(reg_vals, def.length_bytes);
1340 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1341 
1342 	/* Create control pointing to this data */
1343 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1344 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1345 					      "dummyalg", NULL);
1346 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1347 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1348 
1349 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1350 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1351 
1352 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1353 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1354 
1355 	/* Start the firmware and add an action to stop it during cleanup */
1356 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1357 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1358 
1359 	/* Writes are only allowed to be a multiple of the DSP word length */
1360 	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1361 		/* Reset the register values to the test data */
1362 		regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1363 
1364 		get_random_bytes(new_data, def.length_bytes);
1365 		KUNIT_EXPECT_EQ(test,
1366 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, new_data, len_bytes),
1367 				1);
1368 
1369 		memset(readback, 0, def.length_bytes);
1370 		KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, def.length_bytes),
1371 				0);
1372 		KUNIT_EXPECT_MEMEQ(test, readback, new_data, len_bytes);
1373 		KUNIT_EXPECT_MEMEQ(test,
1374 				   (u8 *)readback + len_bytes,
1375 				   (u8 *)reg_vals + len_bytes,
1376 				   def.length_bytes - len_bytes);
1377 	}
1378 }
1379 
1380 /*
1381  * Write less than the full length of data to a cached control.
1382  * Should only change the requested number of bytes.
1383  * Same as cs_dsp_ctl_write_truncated() except the control is cached
1384  * and the firmware is not running.
1385  */
cs_dsp_ctl_write_cache_truncated(struct kunit * test)1386 static void cs_dsp_ctl_write_cache_truncated(struct kunit *test)
1387 {
1388 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1389 	struct cs_dsp_test *priv = test->priv;
1390 	struct cs_dsp_test_local *local = priv->local;
1391 	struct cs_dsp *dsp = priv->dsp;
1392 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1393 	int alg_idx = _find_alg_entry(test, param->alg_id);
1394 	unsigned int reg, alg_base_words;
1395 	struct cs_dsp_coeff_ctl *ctl;
1396 	struct firmware *wmfw;
1397 	u32 *reg_vals, *readback, *new_data;
1398 	unsigned int len_bytes;
1399 
1400 	def.flags = param->flags;
1401 	def.mem_type = param->mem_type;
1402 	def.offset_dsp_words = param->offs_words;
1403 	def.length_bytes = 48;
1404 
1405 	reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1406 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1407 
1408 	readback = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1409 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1410 
1411 	new_data = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1412 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_data);
1413 
1414 	/* Create some initial register content */
1415 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1416 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1417 	reg += (alg_base_words + param->offs_words) *
1418 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1419 	get_random_bytes(reg_vals, def.length_bytes);
1420 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1421 
1422 	/* Create control pointing to this data */
1423 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1424 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1425 					      "dummyalg", NULL);
1426 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1427 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1428 
1429 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1430 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1431 
1432 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1433 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1434 
1435 	/* Start and stop the firmware so the read will come from the cache */
1436 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1437 	cs_dsp_stop(dsp);
1438 
1439 	/* Writes are only allowed to be a multiple of the DSP word length */
1440 	for (len_bytes = sizeof(u32); len_bytes < def.length_bytes; len_bytes += sizeof(u32)) {
1441 		/* Reset the cache to the test data */
1442 		KUNIT_EXPECT_GE(test,
1443 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1444 								 def.length_bytes),
1445 				0);
1446 
1447 		get_random_bytes(new_data, def.length_bytes);
1448 		KUNIT_EXPECT_EQ(test,
1449 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, new_data, len_bytes),
1450 				1);
1451 
1452 		memset(readback, 0, def.length_bytes);
1453 		KUNIT_EXPECT_EQ(test,
1454 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1455 								def.length_bytes),
1456 				0);
1457 		KUNIT_EXPECT_MEMEQ(test, readback, new_data, len_bytes);
1458 		KUNIT_EXPECT_MEMEQ(test,
1459 				   (u8 *)readback + len_bytes,
1460 				   (u8 *)reg_vals + len_bytes,
1461 				   def.length_bytes - len_bytes);
1462 	}
1463 }
1464 
1465 /*
1466  * Read from an offset that is beyond the end of the control data.
1467  * Should return an error.
1468  */
cs_dsp_ctl_read_with_seek_oob(struct kunit * test)1469 static void cs_dsp_ctl_read_with_seek_oob(struct kunit *test)
1470 {
1471 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1472 	struct cs_dsp_test *priv = test->priv;
1473 	struct cs_dsp_test_local *local = priv->local;
1474 	struct cs_dsp *dsp = priv->dsp;
1475 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1476 	int alg_idx = _find_alg_entry(test, param->alg_id);
1477 	unsigned int reg, alg_base_words;
1478 	struct cs_dsp_coeff_ctl *ctl;
1479 	struct firmware *wmfw;
1480 	u32 *reg_vals;
1481 	unsigned int seek_words;
1482 
1483 	def.flags = param->flags;
1484 	def.mem_type = param->mem_type;
1485 	def.offset_dsp_words = param->offs_words;
1486 	def.length_bytes = param->len_bytes;
1487 
1488 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1489 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1490 
1491 	/* Create some initial register content */
1492 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1493 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1494 	reg += (alg_base_words + param->offs_words) *
1495 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1496 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1497 
1498 	/* Create control pointing to this data */
1499 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1500 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1501 					      "dummyalg", NULL);
1502 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1503 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1504 
1505 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1506 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1507 
1508 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1509 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1510 
1511 	/* Start the firmware and add an action to stop it during cleanup */
1512 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1513 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1514 
1515 	seek_words = def.length_bytes / sizeof(u32);
1516 	KUNIT_EXPECT_LT(test,
1517 			cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
1518 							reg_vals, def.length_bytes),
1519 			0);
1520 
1521 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1522 		/* Stop firmware and repeat the read from the cache */
1523 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1524 		KUNIT_ASSERT_FALSE(test, dsp->running);
1525 
1526 		KUNIT_EXPECT_LT(test,
1527 				cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
1528 								reg_vals, def.length_bytes),
1529 				0);
1530 	}
1531 }
1532 
1533 /*
1534  * Read more data than the length of the control data.
1535  * Should return an error.
1536  */
cs_dsp_ctl_read_with_length_overflow(struct kunit * test)1537 static void cs_dsp_ctl_read_with_length_overflow(struct kunit *test)
1538 {
1539 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1540 	struct cs_dsp_test *priv = test->priv;
1541 	struct cs_dsp_test_local *local = priv->local;
1542 	struct cs_dsp *dsp = priv->dsp;
1543 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1544 	int alg_idx = _find_alg_entry(test, param->alg_id);
1545 	unsigned int reg, alg_base_words;
1546 	struct cs_dsp_coeff_ctl *ctl;
1547 	struct firmware *wmfw;
1548 	u32 *reg_vals;
1549 
1550 	def.flags = param->flags;
1551 	def.mem_type = param->mem_type;
1552 	def.offset_dsp_words = param->offs_words;
1553 	def.length_bytes = param->len_bytes;
1554 
1555 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1556 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1557 
1558 	/* Create some initial register content */
1559 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1560 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1561 	reg += (alg_base_words + param->offs_words) *
1562 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1563 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1564 
1565 	/* Create control pointing to this data */
1566 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1567 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1568 					      "dummyalg", NULL);
1569 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1570 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1571 
1572 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1573 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1574 
1575 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1576 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1577 
1578 	/* Start the firmware and add an action to stop it during cleanup */
1579 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1580 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1581 
1582 	KUNIT_EXPECT_LT(test,
1583 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals, def.length_bytes + 1),
1584 			0);
1585 
1586 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1587 		/* Stop firmware and repeat the read from the cache */
1588 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1589 		KUNIT_ASSERT_FALSE(test, dsp->running);
1590 
1591 		KUNIT_EXPECT_LT(test,
1592 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, reg_vals,
1593 								def.length_bytes + 1),
1594 				0);
1595 	}
1596 }
1597 
1598 /*
1599  * Read with a seek and length that ends beyond the end of control data.
1600  * Should return an error.
1601  */
cs_dsp_ctl_read_with_seek_and_length_oob(struct kunit * test)1602 static void cs_dsp_ctl_read_with_seek_and_length_oob(struct kunit *test)
1603 {
1604 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1605 	struct cs_dsp_test *priv = test->priv;
1606 	struct cs_dsp_test_local *local = priv->local;
1607 	struct cs_dsp *dsp = priv->dsp;
1608 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1609 	int alg_idx = _find_alg_entry(test, param->alg_id);
1610 	unsigned int reg, alg_base_words;
1611 	struct cs_dsp_coeff_ctl *ctl;
1612 	struct firmware *wmfw;
1613 	u32 *reg_vals;
1614 
1615 	def.flags = param->flags;
1616 	def.mem_type = param->mem_type;
1617 	def.offset_dsp_words = param->offs_words;
1618 	def.length_bytes = param->len_bytes;
1619 
1620 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1621 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1622 
1623 	/* Create some initial register content */
1624 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1625 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1626 	reg += (alg_base_words + param->offs_words) *
1627 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1628 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1629 
1630 	/* Create control pointing to this data */
1631 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1632 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1633 					      "dummyalg", NULL);
1634 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1635 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1636 
1637 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1638 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1639 
1640 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1641 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1642 
1643 	/* Start the firmware and add an action to stop it during cleanup */
1644 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1645 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1646 
1647 	/*
1648 	 * Read full control length but at a start offset of 1 so that
1649 	 * offset + length exceeds the length of the control.
1650 	 */
1651 	KUNIT_EXPECT_LT(test,
1652 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 1, reg_vals, def.length_bytes),
1653 			0);
1654 
1655 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1656 		/* Stop firmware and repeat the read from the cache */
1657 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1658 		KUNIT_ASSERT_FALSE(test, dsp->running);
1659 
1660 		KUNIT_EXPECT_LT(test,
1661 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 1, reg_vals,
1662 								def.length_bytes),
1663 				0);
1664 	}
1665 }
1666 
1667 /*
1668  * Write to an offset that is beyond the end of the control data.
1669  * Should return an error without touching any registers.
1670  */
cs_dsp_ctl_write_with_seek_oob(struct kunit * test)1671 static void cs_dsp_ctl_write_with_seek_oob(struct kunit *test)
1672 {
1673 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1674 	struct cs_dsp_test *priv = test->priv;
1675 	struct cs_dsp_test_local *local = priv->local;
1676 	struct cs_dsp *dsp = priv->dsp;
1677 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1678 	int alg_idx = _find_alg_entry(test, param->alg_id);
1679 	unsigned int reg, alg_base_words;
1680 	struct cs_dsp_coeff_ctl *ctl;
1681 	struct firmware *wmfw;
1682 	u32 *reg_vals;
1683 	unsigned int seek_words;
1684 
1685 	def.flags = param->flags;
1686 	def.mem_type = param->mem_type;
1687 	def.offset_dsp_words = param->offs_words;
1688 	def.length_bytes = param->len_bytes;
1689 
1690 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1691 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1692 
1693 	/* Create some initial register content */
1694 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1695 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1696 	reg += (alg_base_words + param->offs_words) *
1697 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1698 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1699 
1700 	/* Create control pointing to this data */
1701 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1702 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1703 					      "dummyalg", NULL);
1704 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1705 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1706 
1707 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1708 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1709 
1710 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1711 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1712 
1713 	/* Start the firmware and add an action to stop it during cleanup */
1714 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1715 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1716 
1717 	/* Drop expected writes and the regmap cache should be clean */
1718 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1719 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1720 
1721 	get_random_bytes(reg_vals, def.length_bytes);
1722 	seek_words = def.length_bytes / sizeof(u32);
1723 	KUNIT_EXPECT_LT(test,
1724 			cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1725 							 reg_vals, def.length_bytes),
1726 			0);
1727 
1728 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1729 		/* Stop firmware and repeat the write to the cache */
1730 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1731 		KUNIT_ASSERT_FALSE(test, dsp->running);
1732 
1733 		get_random_bytes(reg_vals, def.length_bytes);
1734 		KUNIT_EXPECT_LT(test,
1735 				cs_dsp_coeff_lock_and_write_ctrl(ctl, seek_words,
1736 								 reg_vals, def.length_bytes),
1737 				0);
1738 	}
1739 
1740 	/* Check that it didn't write any registers */
1741 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1742 }
1743 
1744 /*
1745  * Write more data than the length of the control data.
1746  * Should return an error.
1747  */
cs_dsp_ctl_write_with_length_overflow(struct kunit * test)1748 static void cs_dsp_ctl_write_with_length_overflow(struct kunit *test)
1749 {
1750 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1751 	struct cs_dsp_test *priv = test->priv;
1752 	struct cs_dsp_test_local *local = priv->local;
1753 	struct cs_dsp *dsp = priv->dsp;
1754 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1755 	int alg_idx = _find_alg_entry(test, param->alg_id);
1756 	unsigned int reg, alg_base_words;
1757 	struct cs_dsp_coeff_ctl *ctl;
1758 	struct firmware *wmfw;
1759 	u32 *reg_vals;
1760 
1761 	def.flags = param->flags;
1762 	def.mem_type = param->mem_type;
1763 	def.offset_dsp_words = param->offs_words;
1764 	def.length_bytes = param->len_bytes;
1765 
1766 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1767 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1768 
1769 	/* Create some initial register content */
1770 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1771 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1772 	reg += (alg_base_words + param->offs_words) *
1773 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1774 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1775 
1776 	/* Create control pointing to this data */
1777 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1778 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1779 					      "dummyalg", NULL);
1780 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1781 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1782 
1783 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1784 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1785 
1786 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1787 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1788 
1789 	/* Start the firmware and add an action to stop it during cleanup */
1790 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1791 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1792 
1793 	/* Drop expected writes and the regmap cache should be clean */
1794 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1795 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1796 
1797 	get_random_bytes(reg_vals, def.length_bytes);
1798 	KUNIT_EXPECT_LT(test,
1799 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, def.length_bytes + 1),
1800 			0);
1801 
1802 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1803 		/* Stop firmware and repeat the write to the cache */
1804 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1805 		KUNIT_ASSERT_FALSE(test, dsp->running);
1806 
1807 		get_random_bytes(reg_vals, def.length_bytes);
1808 		KUNIT_EXPECT_LT(test,
1809 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1810 								 def.length_bytes + 1),
1811 				0);
1812 	}
1813 
1814 	/* Check that it didn't write any registers */
1815 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1816 }
1817 
1818 /*
1819  * Write with a seek and length that ends beyond the end of control data.
1820  * Should return an error.
1821  */
cs_dsp_ctl_write_with_seek_and_length_oob(struct kunit * test)1822 static void cs_dsp_ctl_write_with_seek_and_length_oob(struct kunit *test)
1823 {
1824 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1825 	struct cs_dsp_test *priv = test->priv;
1826 	struct cs_dsp_test_local *local = priv->local;
1827 	struct cs_dsp *dsp = priv->dsp;
1828 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1829 	int alg_idx = _find_alg_entry(test, param->alg_id);
1830 	unsigned int reg, alg_base_words;
1831 	struct cs_dsp_coeff_ctl *ctl;
1832 	struct firmware *wmfw;
1833 	u32 *reg_vals;
1834 
1835 	def.flags = param->flags;
1836 	def.mem_type = param->mem_type;
1837 	def.offset_dsp_words = param->offs_words;
1838 	def.length_bytes = param->len_bytes;
1839 
1840 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1841 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1842 
1843 	/* Create some initial register content */
1844 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1845 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1846 	reg += (alg_base_words + param->offs_words) *
1847 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1848 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
1849 
1850 	/* Create control pointing to this data */
1851 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1852 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1853 					      "dummyalg", NULL);
1854 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1855 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1856 
1857 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1858 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1859 
1860 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1861 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1862 
1863 	/* Start the firmware and add an action to stop it during cleanup */
1864 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1865 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1866 
1867 	/* Drop expected writes and the regmap cache should be clean */
1868 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1869 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1870 
1871 	/*
1872 	 * Write full control length but at a start offset of 1 so that
1873 	 * offset + length exceeeds the length of the control.
1874 	 */
1875 	get_random_bytes(reg_vals, def.length_bytes);
1876 	KUNIT_EXPECT_LT(test,
1877 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 1, reg_vals, def.length_bytes),
1878 			0);
1879 
1880 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1881 		/* Stop firmware and repeat the write to the cache */
1882 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1883 		KUNIT_ASSERT_FALSE(test, dsp->running);
1884 
1885 		get_random_bytes(reg_vals, def.length_bytes);
1886 		KUNIT_EXPECT_LT(test,
1887 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 1, reg_vals,
1888 								 def.length_bytes),
1889 				0);
1890 	}
1891 
1892 	/* Check that it didn't write any registers */
1893 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1894 }
1895 
1896 /*
1897  * Read from a write-only control. This is legal because controls can
1898  * always be read. Write-only only indicates that it is not useful to
1899  * populate the cache from the DSP memory.
1900  */
cs_dsp_ctl_read_from_writeonly(struct kunit * test)1901 static void cs_dsp_ctl_read_from_writeonly(struct kunit *test)
1902 {
1903 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1904 	struct cs_dsp_test *priv = test->priv;
1905 	struct cs_dsp_test_local *local = priv->local;
1906 	struct cs_dsp *dsp = priv->dsp;
1907 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1908 	int alg_idx = _find_alg_entry(test, param->alg_id);
1909 	struct cs_dsp_coeff_ctl *ctl;
1910 	struct firmware *wmfw;
1911 	u32 *ctl_vals, *readback;
1912 
1913 	/* Sanity check parameters */
1914 	KUNIT_ASSERT_TRUE(test, param->flags & WMFW_CTL_FLAG_WRITEABLE);
1915 	KUNIT_ASSERT_FALSE(test, param->flags & WMFW_CTL_FLAG_READABLE);
1916 
1917 	def.flags = param->flags;
1918 	def.mem_type = param->mem_type;
1919 	def.offset_dsp_words = param->offs_words;
1920 	def.length_bytes = param->len_bytes;
1921 
1922 	ctl_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
1923 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
1924 
1925 	readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1926 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1927 
1928 	/* Create control pointing to this data */
1929 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1930 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
1931 					      "dummyalg", NULL);
1932 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1933 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1934 
1935 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1936 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1937 
1938 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1939 	KUNIT_ASSERT_NOT_NULL(test, ctl);
1940 
1941 	/* Start the firmware and add an action to stop it during cleanup */
1942 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1943 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1944 
1945 	/* Write some test data to the control */
1946 	get_random_bytes(ctl_vals, def.length_bytes);
1947 	KUNIT_EXPECT_EQ(test,
1948 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, def.length_bytes),
1949 			1);
1950 
1951 	/* Read back the data */
1952 	KUNIT_EXPECT_EQ(test,
1953 			cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, def.length_bytes),
1954 			0);
1955 	KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, def.length_bytes);
1956 
1957 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
1958 		/* Stop firmware and repeat the read from the cache */
1959 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1960 		KUNIT_ASSERT_FALSE(test, dsp->running);
1961 
1962 		memset(readback, 0, def.length_bytes);
1963 		KUNIT_EXPECT_EQ(test,
1964 				cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback,
1965 								def.length_bytes),
1966 				0);
1967 		KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, def.length_bytes);
1968 	}
1969 }
1970 
1971 /*
1972  * Write to a read-only control.
1973  * This should return an error without writing registers.
1974  */
cs_dsp_ctl_write_to_readonly(struct kunit * test)1975 static void cs_dsp_ctl_write_to_readonly(struct kunit *test)
1976 {
1977 	const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
1978 	struct cs_dsp_test *priv = test->priv;
1979 	struct cs_dsp_test_local *local = priv->local;
1980 	struct cs_dsp *dsp = priv->dsp;
1981 	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1982 	int alg_idx = _find_alg_entry(test, param->alg_id);
1983 	unsigned int reg, alg_base_words;
1984 	struct cs_dsp_coeff_ctl *ctl;
1985 	struct firmware *wmfw;
1986 	u32 *reg_vals;
1987 
1988 	/* Sanity check parameters */
1989 	KUNIT_ASSERT_FALSE(test, param->flags & WMFW_CTL_FLAG_WRITEABLE);
1990 	KUNIT_ASSERT_TRUE(test, param->flags & WMFW_CTL_FLAG_READABLE);
1991 
1992 	def.flags = param->flags;
1993 	def.mem_type = param->mem_type;
1994 	def.offset_dsp_words = param->offs_words;
1995 	def.length_bytes = param->len_bytes;
1996 
1997 	reg_vals = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
1998 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1999 
2000 	/* Create some initial register content */
2001 	alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2002 	reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2003 	reg += (alg_base_words + param->offs_words) *
2004 		cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2005 	regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
2006 
2007 	/* Create control pointing to this data */
2008 	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2009 					      cs_dsp_ctl_rw_test_algs[alg_idx].id,
2010 					      "dummyalg", NULL);
2011 	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2012 	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2013 
2014 	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2015 	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2016 
2017 	ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2018 	KUNIT_ASSERT_NOT_NULL(test, ctl);
2019 
2020 	/* Start the firmware and add an action to stop it during cleanup */
2021 	KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2022 	KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2023 
2024 	/* Drop expected writes and the regmap cache should be clean */
2025 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2026 	cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
2027 
2028 	get_random_bytes(reg_vals, def.length_bytes);
2029 	KUNIT_EXPECT_LT(test,
2030 			cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, def.length_bytes),
2031 			0);
2032 
2033 	if (!(def.flags & WMFW_CTL_FLAG_VOLATILE)) {
2034 		/* Stop firmware and repeat the write to the cache */
2035 		kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2036 		KUNIT_ASSERT_FALSE(test, dsp->running);
2037 
2038 		get_random_bytes(reg_vals, def.length_bytes);
2039 		KUNIT_EXPECT_LT(test,
2040 				cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
2041 								 def.length_bytes),
2042 				0);
2043 	}
2044 
2045 	/* Check that it didn't write any registers */
2046 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2047 }
2048 
cs_dsp_ctl_rw_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)2049 static int cs_dsp_ctl_rw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2050 					  int wmfw_version)
2051 {
2052 	struct cs_dsp_test *priv;
2053 	struct cs_dsp_test_local *local;
2054 	struct device *test_dev;
2055 	int ret;
2056 
2057 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2058 	if (!priv)
2059 		return -ENOMEM;
2060 
2061 	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2062 	if (!local)
2063 		return -ENOMEM;
2064 
2065 	priv->test = test;
2066 	priv->dsp = dsp;
2067 	test->priv = priv;
2068 	priv->local = local;
2069 	priv->local->wmfw_version = wmfw_version;
2070 
2071 	/* Create dummy struct device */
2072 	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2073 	if (IS_ERR(test_dev))
2074 		return PTR_ERR(test_dev);
2075 
2076 	dsp->dev = get_device(test_dev);
2077 	if (!dsp->dev)
2078 		return -ENODEV;
2079 
2080 	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2081 	if (ret)
2082 		return ret;
2083 
2084 	dev_set_drvdata(dsp->dev, priv);
2085 
2086 	/* Allocate regmap */
2087 	ret = cs_dsp_mock_regmap_init(priv);
2088 	if (ret)
2089 		return ret;
2090 
2091 	/*
2092 	 * There must always be a XM header with at least 1 algorithm, so create
2093 	 * a dummy one that tests can use and extract it to a data blob.
2094 	 */
2095 	local->xm_header = cs_dsp_create_mock_xm_header(priv,
2096 							cs_dsp_ctl_rw_test_algs,
2097 							ARRAY_SIZE(cs_dsp_ctl_rw_test_algs));
2098 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
2099 
2100 	/* Create wmfw builder */
2101 	local->wmfw_builder = _create_dummy_wmfw(test);
2102 
2103 	/* Init cs_dsp */
2104 	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2105 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2106 
2107 	switch (dsp->type) {
2108 	case WMFW_ADSP2:
2109 		ret = cs_dsp_adsp2_init(dsp);
2110 		break;
2111 	case WMFW_HALO:
2112 		ret = cs_dsp_halo_init(dsp);
2113 		break;
2114 	default:
2115 		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2116 		return -EINVAL;
2117 	}
2118 
2119 	if (ret)
2120 		return ret;
2121 
2122 	/* Automatically call cs_dsp_remove() when test case ends */
2123 	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2124 }
2125 
cs_dsp_ctl_rw_test_halo_init(struct kunit * test)2126 static int cs_dsp_ctl_rw_test_halo_init(struct kunit *test)
2127 {
2128 	struct cs_dsp *dsp;
2129 
2130 	/* Fill in cs_dsp and initialize */
2131 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2132 	if (!dsp)
2133 		return -ENOMEM;
2134 
2135 	dsp->num = 1;
2136 	dsp->type = WMFW_HALO;
2137 	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2138 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2139 	dsp->base = cs_dsp_mock_halo_core_base;
2140 	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2141 
2142 	return cs_dsp_ctl_rw_test_common_init(test, dsp, 3);
2143 }
2144 
cs_dsp_ctl_rw_test_adsp2_32bit_init(struct kunit * test,int wmfw_ver)2145 static int cs_dsp_ctl_rw_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
2146 {
2147 	struct cs_dsp *dsp;
2148 
2149 	/* Fill in cs_dsp and initialize */
2150 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2151 	if (!dsp)
2152 		return -ENOMEM;
2153 
2154 	dsp->num = 1;
2155 	dsp->type = WMFW_ADSP2;
2156 	dsp->rev = 1;
2157 	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2158 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2159 	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2160 
2161 	return cs_dsp_ctl_rw_test_common_init(test, dsp, wmfw_ver);
2162 }
2163 
cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1_init(struct kunit * test)2164 static int cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1_init(struct kunit *test)
2165 {
2166 	return cs_dsp_ctl_rw_test_adsp2_32bit_init(test, 1);
2167 }
2168 
cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2_init(struct kunit * test)2169 static int cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2_init(struct kunit *test)
2170 {
2171 	return cs_dsp_ctl_rw_test_adsp2_32bit_init(test, 2);
2172 }
2173 
cs_dsp_ctl_rw_test_adsp2_16bit_init(struct kunit * test,int wmfw_ver)2174 static int cs_dsp_ctl_rw_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
2175 {
2176 	struct cs_dsp *dsp;
2177 
2178 	/* Fill in cs_dsp and initialize */
2179 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2180 	if (!dsp)
2181 		return -ENOMEM;
2182 
2183 	dsp->num = 1;
2184 	dsp->type = WMFW_ADSP2;
2185 	dsp->rev = 0;
2186 	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2187 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2188 	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2189 
2190 	return cs_dsp_ctl_rw_test_common_init(test, dsp, wmfw_ver);
2191 }
2192 
cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1_init(struct kunit * test)2193 static int cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1_init(struct kunit *test)
2194 {
2195 	return cs_dsp_ctl_rw_test_adsp2_16bit_init(test, 1);
2196 }
2197 
cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2_init(struct kunit * test)2198 static int cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2_init(struct kunit *test)
2199 {
2200 	return cs_dsp_ctl_rw_test_adsp2_16bit_init(test, 2);
2201 }
2202 
cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_rw_test_param * param,char * desc)2203 static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_rw_test_param *param,
2204 				      char *desc)
2205 {
2206 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x",
2207 		 param->alg_id, cs_dsp_mem_region_name(param->mem_type),
2208 		 param->offs_words, param->len_bytes, param->flags);
2209 }
2210 
2211 /* All parameters populated, with various lengths */
2212 static const struct cs_dsp_ctl_rw_test_param all_pop_varying_len_cases[] = {
2213 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2214 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 },
2215 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 },
2216 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 },
2217 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 },
2218 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 },
2219 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 },
2220 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 },
2221 };
2222 KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases,
2223 		  cs_dsp_ctl_all_param_desc);
2224 
2225 /* All parameters populated, with various offsets */
2226 static const struct cs_dsp_ctl_rw_test_param all_pop_varying_offset_cases[] = {
2227 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0,   .len_bytes = 4 },
2228 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1,   .len_bytes = 4 },
2229 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2,   .len_bytes = 4 },
2230 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3,   .len_bytes = 4 },
2231 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8,   .len_bytes = 4 },
2232 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10,  .len_bytes = 4 },
2233 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 },
2234 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 },
2235 };
2236 KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases,
2237 		  cs_dsp_ctl_all_param_desc);
2238 
2239 /* All parameters populated, with various X and Y memory regions */
2240 static const struct cs_dsp_ctl_rw_test_param all_pop_varying_xy_cases[] = {
2241 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 },
2242 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2243 };
2244 KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases,
2245 		  cs_dsp_ctl_all_param_desc);
2246 
2247 /* All parameters populated, using ZM */
2248 static const struct cs_dsp_ctl_rw_test_param all_pop_z_cases[] = {
2249 	{ .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 },
2250 };
2251 KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc);
2252 
2253 /* All parameters populated, with various algorithm ids */
2254 static const struct cs_dsp_ctl_rw_test_param all_pop_varying_alg_cases[] = {
2255 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2256 	{ .alg_id = 0xb,      .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2257 	{ .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2258 	{ .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2259 };
2260 KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases,
2261 		  cs_dsp_ctl_all_param_desc);
2262 
2263 /*
2264  * All parameters populated, with all combinations of flags for a
2265  * readable control.
2266  */
2267 static const struct cs_dsp_ctl_rw_test_param all_pop_readable_flags_cases[] = {
2268 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2269 	  .flags = 0
2270 	},
2271 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2272 	  .flags = WMFW_CTL_FLAG_READABLE,
2273 	},
2274 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2275 	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2276 	},
2277 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2278 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2279 	},
2280 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2281 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2282 	},
2283 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2284 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2285 	},
2286 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2287 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2288 	},
2289 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2290 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2291 	},
2292 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2293 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2294 		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2295 	},
2296 };
2297 KUNIT_ARRAY_PARAM(all_pop_readable_flags,
2298 		  all_pop_readable_flags_cases,
2299 		  cs_dsp_ctl_all_param_desc);
2300 
2301 /*
2302  * All parameters populated, with all combinations of flags for a
2303  * read-only control
2304  */
2305 static const struct cs_dsp_ctl_rw_test_param all_pop_readonly_flags_cases[] = {
2306 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2307 	  .flags = WMFW_CTL_FLAG_READABLE,
2308 	},
2309 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2310 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2311 	},
2312 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2313 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2314 	},
2315 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2316 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2317 	},
2318 };
2319 KUNIT_ARRAY_PARAM(all_pop_readonly_flags,
2320 		  all_pop_readonly_flags_cases,
2321 		  cs_dsp_ctl_all_param_desc);
2322 
2323 /*
2324  * All parameters populated, with all combinations of flags for a
2325  * non-volatile readable control
2326  */
2327 static const struct cs_dsp_ctl_rw_test_param all_pop_nonvol_readable_flags_cases[] = {
2328 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2329 	  .flags = 0
2330 	},
2331 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2332 	  .flags = WMFW_CTL_FLAG_READABLE,
2333 	},
2334 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2335 	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2336 	},
2337 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2338 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2339 	},
2340 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2341 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2342 	},
2343 };
2344 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags,
2345 		  all_pop_nonvol_readable_flags_cases,
2346 		  cs_dsp_ctl_all_param_desc);
2347 
2348 /*
2349  * All parameters populated, with all combinations of flags for a
2350  * writeable control
2351  */
2352 static const struct cs_dsp_ctl_rw_test_param all_pop_writeable_flags_cases[] = {
2353 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2354 	  .flags = 0
2355 	},
2356 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2357 	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2358 	},
2359 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2360 	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2361 	},
2362 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2363 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2364 	},
2365 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2366 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2367 	},
2368 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2369 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2370 	},
2371 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2372 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2373 	},
2374 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2375 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2376 	},
2377 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2378 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2379 		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2380 	},
2381 };
2382 KUNIT_ARRAY_PARAM(all_pop_writeable_flags,
2383 		  all_pop_writeable_flags_cases,
2384 		  cs_dsp_ctl_all_param_desc);
2385 
2386 /*
2387  * All parameters populated, with all combinations of flags for a
2388  * write-only control
2389  */
2390 static const struct cs_dsp_ctl_rw_test_param all_pop_writeonly_flags_cases[] = {
2391 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2392 	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2393 	},
2394 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2395 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2396 	},
2397 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2398 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2399 	},
2400 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2401 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2402 	},
2403 };
2404 KUNIT_ARRAY_PARAM(all_pop_writeonly_flags,
2405 		  all_pop_writeonly_flags_cases,
2406 		  cs_dsp_ctl_all_param_desc);
2407 
2408 /*
2409  * All parameters populated, with all combinations of flags for a
2410  * non-volatile writeable control
2411  */
2412 static const struct cs_dsp_ctl_rw_test_param all_pop_nonvol_writeable_flags_cases[] = {
2413 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2414 	  .flags = 0
2415 	},
2416 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2417 	  .flags = WMFW_CTL_FLAG_WRITEABLE,
2418 	},
2419 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2420 	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2421 	},
2422 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2423 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2424 	},
2425 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2426 	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2427 	},
2428 };
2429 KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags,
2430 		  all_pop_nonvol_writeable_flags_cases,
2431 		  cs_dsp_ctl_all_param_desc);
2432 
2433 /*
2434  * All parameters populated, with all combinations of flags for a
2435  * volatile readable control.
2436  */
2437 static const struct cs_dsp_ctl_rw_test_param all_pop_volatile_readable_flags_cases[] = {
2438 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2439 	  .flags = 0 /* flags == 0 is volatile while firmware is running */
2440 	},
2441 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2442 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE,
2443 	},
2444 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2445 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2446 	},
2447 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2448 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2449 	},
2450 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2451 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2452 		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2453 	},
2454 };
2455 KUNIT_ARRAY_PARAM(all_pop_volatile_readable_flags,
2456 		  all_pop_volatile_readable_flags_cases,
2457 		  cs_dsp_ctl_all_param_desc);
2458 
2459 /*
2460  * All parameters populated, with all combinations of flags for a
2461  * volatile readable control.
2462  */
2463 static const struct cs_dsp_ctl_rw_test_param all_pop_volatile_writeable_flags_cases[] = {
2464 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2465 	  .flags = 0 /* flags == 0 is volatile while firmware is running */
2466 	},
2467 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2468 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE,
2469 	},
2470 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2471 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2472 	},
2473 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2474 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2475 	},
2476 	{ .alg_id = 0xfafa,   .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2477 	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_SYS |
2478 		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2479 	},
2480 };
2481 KUNIT_ARRAY_PARAM(all_pop_volatile_writeable_flags,
2482 		  all_pop_volatile_writeable_flags_cases,
2483 		  cs_dsp_ctl_all_param_desc);
2484 
2485 static struct kunit_case cs_dsp_ctl_rw_test_cases_adsp[] = {
2486 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_len_gen_params),
2487 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_offset_gen_params),
2488 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_xy_gen_params),
2489 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_z_gen_params),
2490 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_alg_gen_params),
2491 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_writeable_flags_gen_params),
2492 
2493 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_len_gen_params),
2494 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_offset_gen_params),
2495 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_xy_gen_params),
2496 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_z_gen_params),
2497 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running,
2498 			 all_pop_volatile_readable_flags_gen_params),
2499 
2500 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_started,
2501 			 all_pop_volatile_readable_flags_gen_params),
2502 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped,
2503 			 all_pop_volatile_readable_flags_gen_params),
2504 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped_powered_down,
2505 			 all_pop_volatile_readable_flags_gen_params),
2506 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_loaded_fw,
2507 			 all_pop_volatile_readable_flags_gen_params),
2508 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_running_fw,
2509 			 all_pop_volatile_readable_flags_gen_params),
2510 
2511 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_started,
2512 			 all_pop_volatile_writeable_flags_gen_params),
2513 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped,
2514 			 all_pop_volatile_writeable_flags_gen_params),
2515 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped_powered_down,
2516 			 all_pop_volatile_writeable_flags_gen_params),
2517 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_loaded_fw,
2518 			 all_pop_volatile_writeable_flags_gen_params),
2519 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_running_fw,
2520 			 all_pop_volatile_writeable_flags_gen_params),
2521 
2522 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek,
2523 			 all_pop_readable_flags_gen_params),
2524 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_with_seek,
2525 			 all_pop_nonvol_readable_flags_gen_params),
2526 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_truncated,
2527 			 all_pop_readable_flags_gen_params),
2528 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_truncated,
2529 			 all_pop_nonvol_readable_flags_gen_params),
2530 
2531 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek,
2532 			 all_pop_writeable_flags_gen_params),
2533 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_with_seek,
2534 			 all_pop_nonvol_writeable_flags_gen_params),
2535 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_truncated,
2536 			 all_pop_writeable_flags_gen_params),
2537 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_truncated,
2538 			 all_pop_nonvol_writeable_flags_gen_params),
2539 
2540 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_oob,
2541 			 all_pop_varying_len_gen_params),
2542 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_length_overflow,
2543 			 all_pop_varying_len_gen_params),
2544 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_and_length_oob,
2545 			 all_pop_varying_len_gen_params),
2546 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_oob,
2547 			 all_pop_varying_len_gen_params),
2548 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_length_overflow,
2549 			 all_pop_varying_len_gen_params),
2550 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_and_length_oob,
2551 			 all_pop_varying_len_gen_params),
2552 
2553 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_from_writeonly,
2554 			 all_pop_writeonly_flags_gen_params),
2555 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_to_readonly,
2556 			 all_pop_readonly_flags_gen_params),
2557 
2558 	{ } /* terminator */
2559 };
2560 
2561 static struct kunit_case cs_dsp_ctl_rw_test_cases_halo[] = {
2562 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_len_gen_params),
2563 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_offset_gen_params),
2564 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_xy_gen_params),
2565 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_varying_alg_gen_params),
2566 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_running, all_pop_writeable_flags_gen_params),
2567 
2568 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_len_gen_params),
2569 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_offset_gen_params),
2570 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running, all_pop_varying_xy_gen_params),
2571 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_running,
2572 			 all_pop_volatile_readable_flags_gen_params),
2573 
2574 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_started,
2575 			 all_pop_volatile_readable_flags_gen_params),
2576 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped,
2577 			 all_pop_volatile_readable_flags_gen_params),
2578 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_stopped_powered_down,
2579 			 all_pop_volatile_readable_flags_gen_params),
2580 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_loaded_fw,
2581 			 all_pop_volatile_readable_flags_gen_params),
2582 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_volatile_not_current_running_fw,
2583 			 all_pop_volatile_readable_flags_gen_params),
2584 
2585 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_started,
2586 			 all_pop_volatile_writeable_flags_gen_params),
2587 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped,
2588 			 all_pop_volatile_writeable_flags_gen_params),
2589 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_stopped_powered_down,
2590 			 all_pop_volatile_writeable_flags_gen_params),
2591 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_loaded_fw,
2592 			 all_pop_volatile_writeable_flags_gen_params),
2593 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_volatile_not_current_running_fw,
2594 			 all_pop_volatile_writeable_flags_gen_params),
2595 
2596 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek,
2597 			 all_pop_readable_flags_gen_params),
2598 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_with_seek,
2599 			 all_pop_nonvol_readable_flags_gen_params),
2600 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_truncated,
2601 			 all_pop_readable_flags_gen_params),
2602 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_cache_truncated,
2603 			 all_pop_nonvol_readable_flags_gen_params),
2604 
2605 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek,
2606 			 all_pop_writeable_flags_gen_params),
2607 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_with_seek,
2608 			 all_pop_nonvol_writeable_flags_gen_params),
2609 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_truncated,
2610 			 all_pop_writeable_flags_gen_params),
2611 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_cache_truncated,
2612 			 all_pop_nonvol_writeable_flags_gen_params),
2613 
2614 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_oob,
2615 			 all_pop_varying_len_gen_params),
2616 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_length_overflow,
2617 			 all_pop_varying_len_gen_params),
2618 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_with_seek_and_length_oob,
2619 			 all_pop_varying_len_gen_params),
2620 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_oob,
2621 			 all_pop_varying_len_gen_params),
2622 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_length_overflow,
2623 			 all_pop_varying_len_gen_params),
2624 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_with_seek_and_length_oob,
2625 			 all_pop_varying_len_gen_params),
2626 
2627 	KUNIT_CASE_PARAM(cs_dsp_ctl_read_from_writeonly,
2628 			 all_pop_writeonly_flags_gen_params),
2629 	KUNIT_CASE_PARAM(cs_dsp_ctl_write_to_readonly,
2630 			 all_pop_readonly_flags_gen_params),
2631 
2632 	{ } /* terminator */
2633 };
2634 
2635 static struct kunit_suite cs_dsp_ctl_rw_test_halo = {
2636 	.name = "cs_dsp_ctl_rw_wmfwV3_halo",
2637 	.init = cs_dsp_ctl_rw_test_halo_init,
2638 	.test_cases = cs_dsp_ctl_rw_test_cases_halo,
2639 };
2640 
2641 static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1 = {
2642 	.name = "cs_dsp_ctl_rw_wmfwV1_adsp2_32bit",
2643 	.init = cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1_init,
2644 	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2645 };
2646 
2647 static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2 = {
2648 	.name = "cs_dsp_ctl_rw_wmfwV2_adsp2_32bit",
2649 	.init = cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2_init,
2650 	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2651 };
2652 
2653 static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1 = {
2654 	.name = "cs_dsp_ctl_rw_wmfwV1_adsp2_16bit",
2655 	.init = cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1_init,
2656 	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2657 };
2658 
2659 static struct kunit_suite cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2 = {
2660 	.name = "cs_dsp_ctl_rw_wmfwV2_adsp2_16bit",
2661 	.init = cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2_init,
2662 	.test_cases = cs_dsp_ctl_rw_test_cases_adsp,
2663 };
2664 
2665 kunit_test_suites(&cs_dsp_ctl_rw_test_halo,
2666 		  &cs_dsp_ctl_rw_test_adsp2_32bit_wmfw1,
2667 		  &cs_dsp_ctl_rw_test_adsp2_32bit_wmfw2,
2668 		  &cs_dsp_ctl_rw_test_adsp2_16bit_wmfw1,
2669 		  &cs_dsp_ctl_rw_test_adsp2_16bit_wmfw2);
2670