File Index
Files and directories
Sign in
FILE

cs_dsp_test_callbacks.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c 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
  9#include <kunit/device.h>
 10#include <kunit/resource.h>
 11#include <kunit/test.h>
 12#include <kunit/test-bug.h>
 13#include <linux/build_bug.h>
 14#include <linux/firmware/cirrus/cs_dsp.h>
 15#include <linux/firmware/cirrus/cs_dsp_test_utils.h>
 16#include <linux/firmware/cirrus/wmfw.h>
 17#include <linux/random.h>
 18#include <linux/regmap.h>
 19#include <linux/string.h>
 20#include <linux/vmalloc.h>
 21
 22#define ADSP2_LOCK_REGION_CTRL               0x7A
 23#define ADSP2_WDT_TIMEOUT_STS_MASK           0x2000
 24
 25KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)
 26KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)
 27
 28struct cs_dsp_test_local {
 29	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
 30
 31	int num_control_add;
 32	int num_control_remove;
 33	int num_pre_run;
 34	int num_post_run;
 35	int num_pre_stop;
 36	int num_post_stop;
 37	int num_watchdog_expired;
 38
 39	struct cs_dsp_coeff_ctl *passed_ctl[16];
 40	struct cs_dsp *passed_dsp;
 41};
 42
 43struct cs_dsp_callbacks_test_param {
 44	const struct cs_dsp_client_ops *ops;
 45	const char *case_name;
 46};
 47
 48static const struct cs_dsp_mock_alg_def cs_dsp_callbacks_test_mock_algs[] = {
 49	{
 50		.id = 0xfafa,
 51		.ver = 0x100000,
 52		.xm_size_words = 164,
 53		.ym_size_words = 164,
 54		.zm_size_words = 164,
 55	},
 56};
 57
 58static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
 59	.shortname = "Dummy Coeff",
 60	.type = WMFW_CTL_TYPE_BYTES,
 61	.mem_type = WMFW_ADSP2_YM,
 62	.flags = WMFW_CTL_FLAG_VOLATILE,
 63	.length_bytes = 4,
 64};
 65
 66static int cs_dsp_test_control_add_callback(struct cs_dsp_coeff_ctl *ctl)
 67{
 68	struct kunit *test = kunit_get_current_test();
 69	struct cs_dsp_test *priv = test->priv;
 70	struct cs_dsp_test_local *local = priv->local;
 71
 72	local->passed_ctl[local->num_control_add] = ctl;
 73	local->num_control_add++;
 74
 75	return 0;
 76}
 77
 78static void cs_dsp_test_control_remove_callback(struct cs_dsp_coeff_ctl *ctl)
 79{
 80	struct kunit *test = kunit_get_current_test();
 81	struct cs_dsp_test *priv = test->priv;
 82	struct cs_dsp_test_local *local = priv->local;
 83
 84	local->passed_ctl[local->num_control_remove] = ctl;
 85	local->num_control_remove++;
 86}
 87
 88static int cs_dsp_test_pre_run_callback(struct cs_dsp *dsp)
 89{
 90	struct kunit *test = kunit_get_current_test();
 91	struct cs_dsp_test *priv = test->priv;
 92	struct cs_dsp_test_local *local = priv->local;
 93
 94	local->passed_dsp = dsp;
 95	local->num_pre_run++;
 96
 97	return 0;
 98}
 99
100static int cs_dsp_test_post_run_callback(struct cs_dsp *dsp)
101{
102	struct kunit *test = kunit_get_current_test();
103	struct cs_dsp_test *priv = test->priv;
104	struct cs_dsp_test_local *local = priv->local;
105
106	local->passed_dsp = dsp;
107	local->num_post_run++;
108
109	return 0;
110}
111
112static void cs_dsp_test_pre_stop_callback(struct cs_dsp *dsp)
113{
114	struct kunit *test = kunit_get_current_test();
115	struct cs_dsp_test *priv = test->priv;
116	struct cs_dsp_test_local *local = priv->local;
117
118	local->passed_dsp = dsp;
119	local->num_pre_stop++;
120}
121
122static void cs_dsp_test_post_stop_callback(struct cs_dsp *dsp)
123{
124	struct kunit *test = kunit_get_current_test();
125	struct cs_dsp_test *priv = test->priv;
126	struct cs_dsp_test_local *local = priv->local;
127
128	local->passed_dsp = dsp;
129	local->num_post_stop++;
130}
131
132static void cs_dsp_test_watchdog_expired_callback(struct cs_dsp *dsp)
133{
134	struct kunit *test = kunit_get_current_test();
135	struct cs_dsp_test *priv = test->priv;
136	struct cs_dsp_test_local *local = priv->local;
137
138	local->passed_dsp = dsp;
139	local->num_watchdog_expired++;
140}
141
142static const struct cs_dsp_client_ops cs_dsp_callback_test_client_ops = {
143	.control_add = cs_dsp_test_control_add_callback,
144	.control_remove = cs_dsp_test_control_remove_callback,
145	.pre_run = cs_dsp_test_pre_run_callback,
146	.post_run = cs_dsp_test_post_run_callback,
147	.pre_stop = cs_dsp_test_pre_stop_callback,
148	.post_stop = cs_dsp_test_post_stop_callback,
149	.watchdog_expired = cs_dsp_test_watchdog_expired_callback,
150};
151
152static const struct cs_dsp_client_ops cs_dsp_callback_test_empty_client_ops = {
153	/* No entries */
154};
155
156static void cs_dsp_test_run_stop_callbacks(struct kunit *test)
157{
158	struct cs_dsp_test *priv = test->priv;
159	struct cs_dsp_test_local *local = priv->local;
160	struct firmware *wmfw;
161
162	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
163
164	KUNIT_EXPECT_EQ(test,
165			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
166			0);
167
168	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
169	KUNIT_EXPECT_EQ(test, local->num_pre_run, 1);
170	KUNIT_EXPECT_EQ(test, local->num_post_run, 1);
171	KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0);
172	KUNIT_EXPECT_EQ(test, local->num_post_stop, 0);
173	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
174	local->passed_dsp = NULL;
175
176	cs_dsp_stop(priv->dsp);
177	KUNIT_EXPECT_EQ(test, local->num_pre_run, 1);
178	KUNIT_EXPECT_EQ(test, local->num_post_run, 1);
179	KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1);
180	KUNIT_EXPECT_EQ(test, local->num_post_stop, 1);
181	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
182	local->passed_dsp = NULL;
183
184	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
185	KUNIT_EXPECT_EQ(test, local->num_pre_run, 2);
186	KUNIT_EXPECT_EQ(test, local->num_post_run, 2);
187	KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1);
188	KUNIT_EXPECT_EQ(test, local->num_post_stop, 1);
189	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
190	local->passed_dsp = NULL;
191
192	cs_dsp_stop(priv->dsp);
193	KUNIT_EXPECT_EQ(test, local->num_pre_run, 2);
194	KUNIT_EXPECT_EQ(test, local->num_post_run, 2);
195	KUNIT_EXPECT_EQ(test, local->num_pre_stop, 2);
196	KUNIT_EXPECT_EQ(test, local->num_post_stop, 2);
197	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
198	local->passed_dsp = NULL;
199}
200
201static void cs_dsp_test_ctl_v1_callbacks(struct kunit *test)
202{
203	struct cs_dsp_test *priv = test->priv;
204	struct cs_dsp_test_local *local = priv->local;
205	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
206	struct cs_dsp_coeff_ctl *ctl;
207	struct firmware *wmfw;
208	int i;
209
210	/* Add a control for each memory */
211	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
212					      cs_dsp_callbacks_test_mock_algs[0].id,
213					      "dummyalg", NULL);
214	def.shortname = "zm";
215	def.mem_type = WMFW_ADSP2_ZM;
216	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
217
218	def.shortname = "ym";
219	def.mem_type = WMFW_ADSP2_YM;
220	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
221
222	def.shortname = "xm";
223	def.mem_type = WMFW_ADSP2_XM;
224	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
225
226	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
227
228	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
229	KUNIT_EXPECT_EQ(test,
230			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
231			0);
232
233	/* There should have been an add callback for each control */
234	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 3);
235	KUNIT_EXPECT_EQ(test, local->num_control_add, 3);
236	KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
237
238	i = 0;
239	list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
240		KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
241
242	/*
243	 * Call cs_dsp_remove() and there should be a remove callback
244	 * for each control
245	 */
246	memset(local->passed_ctl, 0, sizeof(local->passed_ctl));
247	cs_dsp_remove(priv->dsp);
248
249	/* Prevent double cleanup */
250	kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
251
252	KUNIT_EXPECT_EQ(test, local->num_control_add, 3);
253	KUNIT_EXPECT_EQ(test, local->num_control_remove, 3);
254
255	i = 0;
256	list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
257		KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
258}
259
260static void cs_dsp_test_ctl_v2_callbacks(struct kunit *test)
261{
262	struct cs_dsp_test *priv = test->priv;
263	struct cs_dsp_test_local *local = priv->local;
264	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
265	struct cs_dsp_coeff_ctl *ctl;
266	struct firmware *wmfw;
267	char name[2] = { };
268	int i;
269
270	/* Add some controls */
271	def.shortname = name;
272	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
273					      cs_dsp_callbacks_test_mock_algs[0].id,
274					      "dummyalg", NULL);
275	for (i = 0; i < ARRAY_SIZE(local->passed_ctl); ++i) {
276		name[0] = 'A' + i;
277		def.offset_dsp_words = i;
278		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
279	}
280	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
281
282	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
283	KUNIT_EXPECT_EQ(test,
284			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
285			0);
286
287	/* There should have been an add callback for each control */
288	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
289			ARRAY_SIZE(local->passed_ctl));
290	KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl));
291	KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
292
293	i = 0;
294	list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
295		KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
296
297	/*
298	 * Call cs_dsp_remove() and there should be a remove callback
299	 * for each control
300	 */
301	memset(local->passed_ctl, 0, sizeof(local->passed_ctl));
302	cs_dsp_remove(priv->dsp);
303
304	/* Prevent double cleanup */
305	kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
306
307	KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl));
308	KUNIT_EXPECT_EQ(test, local->num_control_remove, ARRAY_SIZE(local->passed_ctl));
309
310	i = 0;
311	list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
312		KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
313}
314
315static void cs_dsp_test_no_callbacks(struct kunit *test)
316{
317	struct cs_dsp_test *priv = test->priv;
318	struct cs_dsp_test_local *local = priv->local;
319	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
320	struct firmware *wmfw;
321
322	/* Add a controls */
323	def.shortname = "A";
324	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
325					      cs_dsp_callbacks_test_mock_algs[0].id,
326					      "dummyalg", NULL);
327	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
328	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
329
330	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
331
332	/* Run a sequence of ops that would invoke callbacks */
333	KUNIT_EXPECT_EQ(test,
334			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
335			0);
336	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
337	cs_dsp_stop(priv->dsp);
338	cs_dsp_remove(priv->dsp);
339
340	/* Prevent double cleanup */
341	kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
342
343	/* Something went very wrong if any of our callbacks were called */
344	KUNIT_EXPECT_EQ(test, local->num_control_add, 0);
345	KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
346	KUNIT_EXPECT_EQ(test, local->num_pre_run, 0);
347	KUNIT_EXPECT_EQ(test, local->num_post_run, 0);
348	KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0);
349	KUNIT_EXPECT_EQ(test, local->num_post_stop, 0);
350}
351
352static void cs_dsp_test_adsp2v2_watchdog_callback(struct kunit *test)
353{
354	struct cs_dsp_test *priv = test->priv;
355	struct cs_dsp_test_local *local = priv->local;
356	struct firmware *wmfw;
357
358	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
359
360	KUNIT_EXPECT_EQ(test,
361			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
362			0);
363
364	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
365
366	/* Set the watchdog timeout bit */
367	regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL,
368		     ADSP2_WDT_TIMEOUT_STS_MASK);
369
370	/* Notify an interrupt and the watchdog callback should be called */
371	cs_dsp_adsp2_bus_error(priv->dsp);
372	KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1);
373	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
374}
375
376static void cs_dsp_test_adsp2v2_watchdog_no_callbacks(struct kunit *test)
377{
378	struct cs_dsp_test *priv = test->priv;
379	struct cs_dsp_test_local *local = priv->local;
380	struct firmware *wmfw;
381
382	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
383	KUNIT_EXPECT_EQ(test,
384			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
385			0);
386	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
387
388	/* Set the watchdog timeout bit */
389	regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL,
390		     ADSP2_WDT_TIMEOUT_STS_MASK);
391
392	/* Notify an interrupt, which will look for a watchdog callback */
393	cs_dsp_adsp2_bus_error(priv->dsp);
394	KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0);
395}
396
397static void cs_dsp_test_halo_watchdog_callback(struct kunit *test)
398{
399	struct cs_dsp_test *priv = test->priv;
400	struct cs_dsp_test_local *local = priv->local;
401	struct firmware *wmfw;
402
403	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
404
405	KUNIT_EXPECT_EQ(test,
406			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
407			0);
408
409	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
410
411	/* Notify an interrupt and the watchdog callback should be called */
412	cs_dsp_halo_wdt_expire(priv->dsp);
413	KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1);
414	KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
415}
416
417static void cs_dsp_test_halo_watchdog_no_callbacks(struct kunit *test)
418{
419	struct cs_dsp_test *priv = test->priv;
420	struct cs_dsp_test_local *local = priv->local;
421	struct firmware *wmfw;
422
423	wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
424	KUNIT_EXPECT_EQ(test,
425			cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
426			0);
427	KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
428
429	/* Notify an interrupt, which will look for a watchdog callback */
430	cs_dsp_halo_wdt_expire(priv->dsp);
431	KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0);
432}
433
434static int cs_dsp_callbacks_test_common_init(struct kunit *test, struct cs_dsp *dsp,
435					     int wmfw_version)
436{
437	const struct cs_dsp_callbacks_test_param *param = test->param_value;
438	struct cs_dsp_test *priv;
439	struct cs_dsp_test_local *local;
440	struct device *test_dev;
441	struct cs_dsp_mock_xm_header *xm_header;
442	int ret;
443
444	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
445	if (!priv)
446		return -ENOMEM;
447
448	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
449	if (!local)
450		return -ENOMEM;
451
452	priv->test = test;
453	priv->dsp = dsp;
454	test->priv = priv;
455	priv->local = local;
456
457	/* Create dummy struct device */
458	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
459	if (IS_ERR(test_dev))
460		return PTR_ERR(test_dev);
461
462	dsp->dev = get_device(test_dev);
463	if (!dsp->dev)
464		return -ENODEV;
465
466	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
467	if (ret)
468		return ret;
469
470	dev_set_drvdata(dsp->dev, priv);
471
472	/* Allocate regmap */
473	ret = cs_dsp_mock_regmap_init(priv);
474	if (ret)
475		return ret;
476
477	/*
478	 * There must always be a XM header with at least 1 algorithm,
479	 * so create a dummy one and pre-populate XM so the wmfw doesn't
480	 * have to contain an XM blob.
481	 */
482	xm_header = cs_dsp_create_mock_xm_header(priv,
483						 cs_dsp_callbacks_test_mock_algs,
484						 ARRAY_SIZE(cs_dsp_callbacks_test_mock_algs));
485	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_header);
486	cs_dsp_mock_xm_header_write_to_regmap(xm_header);
487
488	local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, wmfw_version);
489	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);
490
491	/* Add dummy XM header payload to wmfw */
492	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
493					WMFW_ADSP2_XM, 0,
494					xm_header->blob_data,
495					xm_header->blob_size_bytes);
496
497	/* Init cs_dsp */
498	dsp->client_ops = param->ops;
499
500	switch (dsp->type) {
501	case WMFW_ADSP2:
502		ret = cs_dsp_adsp2_init(dsp);
503		break;
504	case WMFW_HALO:
505		ret = cs_dsp_halo_init(dsp);
506		break;
507	default:
508		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
509		return -EINVAL;
510	}
511
512	if (ret)
513		return ret;
514
515	/* Automatically call cs_dsp_remove() when test case ends */
516	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
517}
518
519static int cs_dsp_callbacks_test_halo_init(struct kunit *test)
520{
521	struct cs_dsp *dsp;
522
523	/* Fill in cs_dsp and initialize */
524	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
525	if (!dsp)
526		return -ENOMEM;
527
528	dsp->num = 1;
529	dsp->type = WMFW_HALO;
530	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
531	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
532	dsp->base = cs_dsp_mock_halo_core_base;
533	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
534
535	return cs_dsp_callbacks_test_common_init(test, dsp, 3);
536}
537
538static int cs_dsp_callbacks_test_adsp2_32bit_init(struct kunit *test, int rev)
539{
540	struct cs_dsp *dsp;
541
542	/* Fill in cs_dsp and initialize */
543	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
544	if (!dsp)
545		return -ENOMEM;
546
547	dsp->num = 1;
548	dsp->type = WMFW_ADSP2;
549	dsp->rev = rev;
550	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
551	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
552	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
553
554	return cs_dsp_callbacks_test_common_init(test, dsp, 2);
555}
556
557static int cs_dsp_callbacks_test_adsp2v2_32bit_init(struct kunit *test)
558{
559	return cs_dsp_callbacks_test_adsp2_32bit_init(test, 2);
560}
561
562static int cs_dsp_callbacks_test_adsp2v1_32bit_init(struct kunit *test)
563{
564	return cs_dsp_callbacks_test_adsp2_32bit_init(test, 1);
565}
566
567static int cs_dsp_callbacks_test_adsp2_16bit_init(struct kunit *test)
568{
569	struct cs_dsp *dsp;
570
571	/* Fill in cs_dsp and initialize */
572	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
573	if (!dsp)
574		return -ENOMEM;
575
576	dsp->num = 1;
577	dsp->type = WMFW_ADSP2;
578	dsp->rev = 0;
579	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
580	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
581	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
582
583	return cs_dsp_callbacks_test_common_init(test, dsp, 1);
584}
585
586static void cs_dsp_callbacks_param_desc(const struct cs_dsp_callbacks_test_param *param,
587					char *desc)
588{
589	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", param->case_name);
590}
591
592/* Parameterize on different client callback ops tables */
593static const struct cs_dsp_callbacks_test_param cs_dsp_callbacks_ops_cases[] = {
594	{ .ops =  &cs_dsp_callback_test_client_ops, .case_name = "all ops" },
595};
596
597KUNIT_ARRAY_PARAM(cs_dsp_callbacks_ops,
598		  cs_dsp_callbacks_ops_cases,
599		  cs_dsp_callbacks_param_desc);
600
601static const struct cs_dsp_callbacks_test_param cs_dsp_no_callbacks_cases[] = {
602	{ .ops =  &cs_dsp_callback_test_empty_client_ops, .case_name = "empty ops" },
603	{ .ops =  NULL, .case_name = "NULL ops" },
604};
605
606KUNIT_ARRAY_PARAM(cs_dsp_no_callbacks,
607		  cs_dsp_no_callbacks_cases,
608		  cs_dsp_callbacks_param_desc);
609
610static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
611	KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
612	KUNIT_CASE_PARAM(cs_dsp_test_ctl_v1_callbacks, cs_dsp_callbacks_ops_gen_params),
613	KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
614
615	{ } /* terminator */
616};
617
618static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
619	KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
620	KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
621	KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
622
623	{ } /* terminator */
624};
625
626static struct kunit_case cs_dsp_callbacks_halo_test_cases[] = {
627	KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
628	KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
629	KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
630
631	{ } /* terminator */
632};
633
634static struct kunit_case cs_dsp_watchdog_adsp2v2_test_cases[] = {
635	KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_callback, cs_dsp_callbacks_ops_gen_params),
636	KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params),
637
638	{ } /* terminator */
639};
640
641static struct kunit_case cs_dsp_watchdog_halo_test_cases[] = {
642	KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_callback, cs_dsp_callbacks_ops_gen_params),
643	KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params),
644
645	{ } /* terminator */
646};
647
648static struct kunit_suite cs_dsp_callbacks_test_halo = {
649	.name = "cs_dsp_callbacks_halo",
650	.init = cs_dsp_callbacks_test_halo_init,
651	.test_cases = cs_dsp_callbacks_halo_test_cases,
652};
653
654static struct kunit_suite cs_dsp_callbacks_test_adsp2v2_32bit = {
655	.name = "cs_dsp_callbacks_adsp2v2_32bit_wmfwv2",
656	.init = cs_dsp_callbacks_test_adsp2v2_32bit_init,
657	.test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases,
658};
659
660static struct kunit_suite cs_dsp_callbacks_test_adsp2v1_32bit = {
661	.name = "cs_dsp_callbacks_adsp2v1_32bit_wmfwv2",
662	.init = cs_dsp_callbacks_test_adsp2v1_32bit_init,
663	.test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases,
664};
665
666static struct kunit_suite cs_dsp_callbacks_test_adsp2_16bit = {
667	.name = "cs_dsp_callbacks_adsp2_16bit_wmfwv1",
668	.init = cs_dsp_callbacks_test_adsp2_16bit_init,
669	.test_cases = cs_dsp_callbacks_adsp2_wmfwv1_test_cases,
670};
671
672static struct kunit_suite cs_dsp_watchdog_test_adsp2v2_32bit = {
673	.name = "cs_dsp_watchdog_adsp2v2_32bit",
674	.init = cs_dsp_callbacks_test_adsp2v2_32bit_init,
675	.test_cases = cs_dsp_watchdog_adsp2v2_test_cases,
676};
677
678static struct kunit_suite cs_dsp_watchdog_test_halo_32bit = {
679	.name = "cs_dsp_watchdog_halo",
680	.init = cs_dsp_callbacks_test_halo_init,
681	.test_cases = cs_dsp_watchdog_halo_test_cases,
682};
683
684kunit_test_suites(&cs_dsp_callbacks_test_halo,
685		  &cs_dsp_callbacks_test_adsp2v2_32bit,
686		  &cs_dsp_callbacks_test_adsp2v1_32bit,
687		  &cs_dsp_callbacks_test_adsp2_16bit,
688		  &cs_dsp_watchdog_test_adsp2v2_32bit,
689		  &cs_dsp_watchdog_test_halo_32bit);
~/ Read-only file preview.