]> Git Repo - linux.git/blob - drivers/firmware/cirrus/test/cs_dsp_test_control_rw.c
Linux 6.14-rc3
[linux.git] / drivers / firmware / cirrus / test / cs_dsp_test_control_rw.c
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
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
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
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
875 static void cs_dsp_ctl_read_with_seek(struct kunit *test)
876 {
877         const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
878         struct cs_dsp_test *priv = test->priv;
879         struct cs_dsp_test_local *local = priv->local;
880         struct cs_dsp *dsp = priv->dsp;
881         struct cs_dsp_mock_coeff_def def = mock_coeff_template;
882         int alg_idx = _find_alg_entry(test, param->alg_id);
883         unsigned int reg, alg_base_words;
884         struct cs_dsp_coeff_ctl *ctl;
885         struct firmware *wmfw;
886         u32 *reg_vals, *readback;
887         unsigned int seek_words;
888
889         def.flags = param->flags;
890         def.mem_type = param->mem_type;
891         def.offset_dsp_words = param->offs_words;
892         def.length_bytes = 48;
893
894         reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
895         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
896
897         readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
898         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
899
900         /* Create some initial register content */
901         alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
902         reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
903         reg += (alg_base_words + param->offs_words) *
904                 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
905         get_random_bytes(reg_vals, def.length_bytes);
906         regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
907
908         /* Create control pointing to this data */
909         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
910                                               cs_dsp_ctl_rw_test_algs[alg_idx].id,
911                                               "dummyalg", NULL);
912         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
913         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
914
915         wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
916         KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
917
918         ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
919         KUNIT_ASSERT_NOT_NULL(test, ctl);
920
921         /* Start the firmware and add an action to stop it during cleanup */
922         KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
923         KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
924
925         for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
926                 unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
927
928                 KUNIT_EXPECT_EQ(test,
929                                 cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
930                                                                 readback, len_bytes),
931                                 0);
932                 KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
933         }
934 }
935
936 /*
937  * Read from an offset into the control cache. Should return only the
938  * portion of data from the offset position.
939  * Same as cs_dsp_ctl_read_with_seek() except the control is cached
940  * and the firmware is not running.
941  */
942 static void cs_dsp_ctl_read_cache_with_seek(struct kunit *test)
943 {
944         const struct cs_dsp_ctl_rw_test_param *param = test->param_value;
945         struct cs_dsp_test *priv = test->priv;
946         struct cs_dsp_test_local *local = priv->local;
947         struct cs_dsp *dsp = priv->dsp;
948         struct cs_dsp_mock_coeff_def def = mock_coeff_template;
949         int alg_idx = _find_alg_entry(test, param->alg_id);
950         unsigned int reg, alg_base_words;
951         struct cs_dsp_coeff_ctl *ctl;
952         struct firmware *wmfw;
953         u32 *reg_vals, *readback;
954         unsigned int seek_words;
955
956         def.flags = param->flags;
957         def.mem_type = param->mem_type;
958         def.offset_dsp_words = param->offs_words;
959         def.length_bytes = 48;
960
961         reg_vals = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
962         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
963
964         readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
965         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
966
967         /* Create some initial register content */
968         alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
969         reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
970         reg += (alg_base_words + param->offs_words) *
971                 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
972         get_random_bytes(reg_vals, def.length_bytes);
973         regmap_raw_write(dsp->regmap, reg, reg_vals, def.length_bytes);
974
975         /* Create control pointing to this data */
976         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
977                                               cs_dsp_ctl_rw_test_algs[alg_idx].id,
978                                               "dummyalg", NULL);
979         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
980         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
981
982         wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
983         KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
984
985         ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
986         KUNIT_ASSERT_NOT_NULL(test, ctl);
987
988         /* Start and stop the firmware so the read will come from the cache */
989         KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
990         cs_dsp_stop(dsp);
991
992         for (seek_words = 1; seek_words < (def.length_bytes / sizeof(u32)); seek_words++) {
993                 unsigned int len_bytes = def.length_bytes - (seek_words * sizeof(u32));
994
995                 KUNIT_EXPECT_EQ(test,
996                                 cs_dsp_coeff_lock_and_read_ctrl(ctl, seek_words,
997                                                                 readback, len_bytes),
998                                 0);
999                 KUNIT_EXPECT_MEMEQ(test, readback, &reg_vals[seek_words], len_bytes);
1000         }
1001 }
1002
1003 /*
1004  * Read less than the full length of data from a control. Should return
1005  * only the requested number of bytes.
1006  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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
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
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
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
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
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
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
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
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
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);
This page took 0.186656 seconds and 4 git commands to generate.