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, ®_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, ®_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