lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260121132243.1256019-6-rf@opensource.cirrus.com>
Date: Wed, 21 Jan 2026 13:22:43 +0000
From: Richard Fitzgerald <rf@...nsource.cirrus.com>
To: broonie@...nel.org
Cc: linux-sound@...r.kernel.org, linux-kernel@...r.kernel.org,
        patches@...nsource.cirrus.com
Subject: [PATCH 5/5] ASoC: cs35l56: Add KUnit testing of cs35l56_set_fw_suffix()

Add a new KUnit test for testing the creation of firmware name
qualifiers in the cs35l56 driver. The initial set of test cases
are for cs35l56_set_fw_suffix().

Signed-off-by: Richard Fitzgerald <rf@...nsource.cirrus.com>
---
 sound/soc/codecs/Kconfig        |  13 ++
 sound/soc/codecs/Makefile       |   2 +
 sound/soc/codecs/cs-amp-lib.c   |   3 +
 sound/soc/codecs/cs35l56-test.c | 365 ++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l56.c      |   5 +-
 sound/soc/codecs/cs35l56.h      |   4 +
 6 files changed, 391 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/codecs/cs35l56-test.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 21d5b79f079d..d09de0ff5f22 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -933,6 +933,19 @@ config SND_SOC_CS35L56_CAL_SET_CTRL
 	  On most platforms this is not needed.
 
 	  If unsure select "N".
+
+config SND_SOC_CS35L56_TEST
+	tristate "KUnit test for Cirrus Logic cs35l56 driver" if !KUNIT_ALL_TESTS
+	depends on SND_SOC_CS35L56 && KUNIT
+	default KUNIT_ALL_TESTS
+	select SND_SOC_CS_AMP_LIB_TEST_HOOKS
+	help
+	  This builds KUnit tests for the Cirrus Logic cs35l56
+	  codec driver.
+	  For more information on KUnit and unit tests in general,
+	  please refer to the KUnit documentation in
+	  Documentation/dev-tools/kunit/.
+	  If in doubt, say "N".
 endmenu
 
 config SND_SOC_CS40L50
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a6406bc907a9..c3568de5e0c9 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -81,6 +81,7 @@ snd-soc-cs35l56-shared-y := cs35l56-shared.o
 snd-soc-cs35l56-i2c-y := cs35l56-i2c.o
 snd-soc-cs35l56-spi-y := cs35l56-spi.o
 snd-soc-cs35l56-sdw-y := cs35l56-sdw.o
+snd-soc-cs35l56-test-y := cs35l56-test.o
 snd-soc-cs40l50-y := cs40l50-codec.o
 snd-soc-cs42l42-y := cs42l42.o
 snd-soc-cs42l42-i2c-y := cs42l42-i2c.o
@@ -516,6 +517,7 @@ obj-$(CONFIG_SND_SOC_CS35L56_SHARED)	+= snd-soc-cs35l56-shared.o
 obj-$(CONFIG_SND_SOC_CS35L56_I2C)	+= snd-soc-cs35l56-i2c.o
 obj-$(CONFIG_SND_SOC_CS35L56_SPI)	+= snd-soc-cs35l56-spi.o
 obj-$(CONFIG_SND_SOC_CS35L56_SDW)	+= snd-soc-cs35l56-sdw.o
+obj-$(CONFIG_SND_SOC_CS35L56_TEST)	+= snd-soc-cs35l56-test.o
 obj-$(CONFIG_SND_SOC_CS40L50)		+= snd-soc-cs40l50.o
 obj-$(CONFIG_SND_SOC_CS42L42_CORE)	+= snd-soc-cs42l42.o
 obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42-i2c.o
diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c
index f8c7f594d54a..8b131975143d 100644
--- a/sound/soc/codecs/cs-amp-lib.c
+++ b/sound/soc/codecs/cs-amp-lib.c
@@ -806,6 +806,9 @@ const char *cs_amp_devm_get_vendor_specific_variant_id(struct device *dev,
 						       int ssid_vendor,
 						       int ssid_device)
 {
+	KUNIT_STATIC_STUB_REDIRECT(cs_amp_devm_get_vendor_specific_variant_id,
+				   dev, ssid_vendor, ssid_device);
+
 	if ((ssid_vendor == PCI_VENDOR_ID_DELL) || (ssid_vendor < 0))
 		return cs_amp_devm_get_dell_ssidex(dev, ssid_vendor, ssid_device);
 
diff --git a/sound/soc/codecs/cs35l56-test.c b/sound/soc/codecs/cs35l56-test.c
new file mode 100644
index 000000000000..66d772d7b982
--- /dev/null
+++ b/sound/soc/codecs/cs35l56-test.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// KUnit test for the Cirrus Logic cs35l56 driver.
+//
+// Copyright (C) 2026 Cirrus Logic, Inc. and
+//                    Cirrus Logic International Semiconductor Ltd.
+
+#include <kunit/resource.h>
+#include <kunit/test.h>
+#include <kunit/static_stub.h>
+#include <linux/efi.h>
+#include <linux/device/faux.h>
+#include <linux/firmware/cirrus/cs_dsp.h>
+#include <linux/firmware/cirrus/wmfw.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/pci_ids.h>
+#include <linux/soundwire/sdw.h>
+#include <sound/cs35l56.h>
+#include <sound/cs-amp-lib.h>
+#include "cs35l56.h"
+
+KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
+			    struct faux_device *)
+
+struct cs35l56_test_priv {
+	struct faux_device *amp_dev;
+	struct cs35l56_private *cs35l56_priv;
+
+	const char *ssidexv2;
+};
+
+struct cs35l56_test_param {
+	u8 type;
+	u8 rev;
+};
+
+static const char *cs35l56_test_devm_get_vendor_specific_variant_id_none(struct device *dev,
+									 int ssid_vendor,
+									 int ssid_device)
+{
+	return ERR_PTR(-ENOENT);
+}
+
+static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set device type info */
+	cs35l56->base.type = 0x56;
+	cs35l56->base.rev = 0xb0;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	/* Set SoundWire link and UID number */
+	cs35l56->sdw_link_num = 1;
+	cs35l56->sdw_unique_id = 5;
+
+	kunit_activate_static_stub(test,
+				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
+				   cs_amp_devm_get_vendor_specific_variant_id);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Priority suffix should be the legacy ALSA prefix */
+	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
+
+	/* Fallback suffix should be the new SoundWire ID */
+	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
+}
+
+static void cs35l56_test_suffix_sdw(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	/* Set SoundWire link and UID number */
+	cs35l56->sdw_link_num = 1;
+	cs35l56->sdw_unique_id = 5;
+
+	kunit_activate_static_stub(test,
+				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
+				   cs_amp_devm_get_vendor_specific_variant_id);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Suffix should be the SoundWire ID without a fallback */
+	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "l1u5");
+	KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
+}
+
+static void cs35l56_test_suffix_i2cspi(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	kunit_activate_static_stub(test,
+				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
+				   cs_amp_devm_get_vendor_specific_variant_id);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Suffix strings should not be set: use default wm_adsp suffixing */
+	KUNIT_EXPECT_NULL(test, cs35l56->dsp.fwf_suffix);
+	KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
+}
+
+static efi_status_t cs35l56_test_get_efi_ssidexv2(efi_char16_t *name,
+						  efi_guid_t *guid,
+						  u32 *returned_attr,
+						  unsigned long *size,
+						  void *buf)
+{
+	struct kunit *test = kunit_get_current_test();
+	struct cs35l56_test_priv *priv = test->priv;
+	unsigned int len;
+
+	KUNIT_ASSERT_NOT_NULL(test, priv->ssidexv2);
+	len = strlen(priv->ssidexv2);
+
+	if (*size < len) {
+		*size = len;
+		return EFI_BUFFER_TOO_SMALL;
+	}
+
+	KUNIT_ASSERT_NOT_NULL(test, buf);
+	memcpy(buf, priv->ssidexv2, len);
+
+	return EFI_SUCCESS;
+}
+
+static void cs35l56_test_ssidexv2_suffix_sdw(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	/* Set SoundWire link and UID number */
+	cs35l56->sdw_link_num = 1;
+	cs35l56->sdw_unique_id = 5;
+
+	/* Set a SSID to enable lookup of SSIDExV2 */
+	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
+
+	priv->ssidexv2 = "10281234_01_BB_CC";
+
+	kunit_activate_static_stub(test,
+				   cs_amp_test_hooks->get_efi_variable,
+				   cs35l56_test_get_efi_ssidexv2);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Priority suffix should be the SSIDExV2 string with SoundWire ID */
+	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-l1u5");
+
+	/* Fallback suffix should be the SoundWireID */
+	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
+}
+
+static void cs35l56_test_ssidexv2_suffix_i2cspi(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	/* Set a SSID to enable lookup of SSIDExV2 */
+	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
+
+	priv->ssidexv2 = "10281234_01_BB_CC";
+
+	kunit_activate_static_stub(test,
+				   cs_amp_test_hooks->get_efi_variable,
+				   cs35l56_test_get_efi_ssidexv2);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Priority suffix should be the SSIDExV2 string with ALSA name prefix */
+	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-AMP1");
+
+	/* Fallback suffix should be the ALSA name prefix */
+	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "AMP1");
+}
+
+/*
+ * CS35L56 B0 SoundWire should ignore any SSIDExV2 suffix. It isn't needed
+ * on any products with B0 silicon and would interfere with the fallback
+ * to legacy naming convention for early B0-based laptops.
+ */
+static void cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv = test->priv;
+	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
+
+	/* Set device type info */
+	cs35l56->base.type = 0x56;
+	cs35l56->base.rev = 0xb0;
+
+	/* Set the ALSA name prefix */
+	cs35l56->component->name_prefix = "AMP1";
+
+	/* Set SoundWire link and UID number */
+	cs35l56->sdw_link_num = 1;
+	cs35l56->sdw_unique_id = 5;
+
+	/* Set a SSID to enable lookup of SSIDExV2 */
+	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
+
+	priv->ssidexv2 = "10281234_01_BB_CC";
+
+	kunit_activate_static_stub(test,
+				   cs_amp_test_hooks->get_efi_variable,
+				   cs35l56_test_get_efi_ssidexv2);
+
+	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
+
+	/* Priority suffix should be the legacy ALSA prefix */
+	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
+
+	/* Fallback suffix should be the new SoundWire ID */
+	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
+}
+
+static int cs35l56_test_case_init_common(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv;
+	const struct cs35l56_test_param *param = test->param_value;
+	struct cs35l56_private *cs35l56;
+
+	KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks);
+
+	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	test->priv = priv;
+
+	/* Create dummy amp driver dev */
+	priv->amp_dev = faux_device_create("cs35l56_test_drv", NULL, NULL);
+	KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
+	KUNIT_ASSERT_EQ(test, 0,
+			kunit_add_action_or_reset(test,
+						  faux_device_destroy_wrapper,
+						  priv->amp_dev));
+
+	/* Construct minimal set of driver structs */
+	priv->cs35l56_priv = kunit_kzalloc(test, sizeof(*priv->cs35l56_priv), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_priv);
+	cs35l56 = priv->cs35l56_priv;
+	cs35l56->base.dev = &priv->amp_dev->dev;
+
+	cs35l56->component = kunit_kzalloc(test, sizeof(*cs35l56->component), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, cs35l56->component);
+	cs35l56->component->dev = cs35l56->base.dev;
+
+	cs35l56->component->card = kunit_kzalloc(test, sizeof(*cs35l56->component->card),
+						 GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, cs35l56->component->card);
+
+	if (param) {
+		cs35l56->base.type = param->type;
+		cs35l56->base.rev = param->rev;
+	}
+
+	return 0;
+}
+
+static int cs35l56_test_case_init_soundwire(struct kunit *test)
+{
+	struct cs35l56_test_priv *priv;
+	struct cs35l56_private *cs35l56;
+	int ret;
+
+	ret = cs35l56_test_case_init_common(test);
+	if (ret)
+		return ret;
+
+	priv = test->priv;
+	cs35l56 = priv->cs35l56_priv;
+
+	/* Dummy to indicate this is Soundwire */
+	cs35l56->sdw_peripheral = kunit_kzalloc(test, sizeof(*cs35l56->sdw_peripheral),
+						GFP_KERNEL);
+	if (!cs35l56->sdw_peripheral)
+		return -ENOMEM;
+
+
+	return 0;
+}
+
+static void cs35l56_test_type_rev_param_desc(const struct cs35l56_test_param *param,
+					     char *desc)
+{
+	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "type: %02x rev: %02x",
+		 param->type, param->rev);
+}
+
+static const struct cs35l56_test_param cs35l56_test_type_rev_ex_b0_param_cases[] = {
+	{ .type = 0x56, .rev = 0xb2 },
+	{ .type = 0x57, .rev = 0xb2 },
+	{ .type = 0x63, .rev = 0xa1 },
+};
+KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_ex_b0, cs35l56_test_type_rev_ex_b0_param_cases,
+		  cs35l56_test_type_rev_param_desc);
+
+
+static const struct cs35l56_test_param cs35l56_test_type_rev_all_param_cases[] = {
+	{ .type = 0x56, .rev = 0xb0 },
+	{ .type = 0x56, .rev = 0xb2 },
+	{ .type = 0x57, .rev = 0xb2 },
+	{ .type = 0x63, .rev = 0xa1 },
+};
+KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_all, cs35l56_test_type_rev_all_param_cases,
+		  cs35l56_test_type_rev_param_desc);
+
+static struct kunit_case cs35l56_test_cases_soundwire[] = {
+	KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw),
+	KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params),
+	KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw,
+			 cs35l56_test_type_rev_ex_b0_gen_params),
+	KUNIT_CASE(cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw),
+
+	{ } /* terminator */
+};
+
+static struct kunit_case cs35l56_test_cases_not_soundwire[] = {
+	KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params),
+	KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi,
+			 cs35l56_test_type_rev_all_gen_params),
+
+	{ } /* terminator */
+};
+
+static struct kunit_suite cs35l56_test_suite_soundwire = {
+	.name = "snd-soc-cs35l56-test-soundwire",
+	.init = cs35l56_test_case_init_soundwire,
+	.test_cases = cs35l56_test_cases_soundwire,
+};
+
+static struct kunit_suite cs35l56_test_suite_not_soundwire = {
+	.name = "snd-soc-cs35l56-test-not-soundwire",
+	.init = cs35l56_test_case_init_common,
+	.test_cases = cs35l56_test_cases_not_soundwire,
+};
+
+kunit_test_suites(
+	&cs35l56_test_suite_soundwire,
+	&cs35l56_test_suite_not_soundwire,
+);
+
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
+MODULE_DESCRIPTION("KUnit test for Cirrus Logic cs35l56 codec driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@...nsource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index abea782bcd3f..31dd2f7b2858 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -5,6 +5,8 @@
 // Copyright (C) 2023 Cirrus Logic, Inc. and
 //                    Cirrus Logic International Semiconductor Ltd.
 
+#include <kunit/static_stub.h>
+#include <kunit/visibility.h>
 #include <linux/acpi.h>
 #include <linux/array_size.h>
 #include <linux/completion.h>
@@ -1107,7 +1109,7 @@ static const struct snd_kcontrol_new cs35l56_cal_data_restore_controls[] = {
 			SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE),
 };
 
-static int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56)
+VISIBLE_IF_KUNIT int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56)
 {
 	unsigned short vendor, device;
 	const char *vendor_id;
@@ -1175,6 +1177,7 @@ static int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56)
 
 	return 0;
 }
+EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_suffix);
 
 static int cs35l56_component_probe(struct snd_soc_component *component)
 {
diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h
index 4c59f92f3206..7187885a13c1 100644
--- a/sound/soc/codecs/cs35l56.h
+++ b/sound/soc/codecs/cs35l56.h
@@ -74,4 +74,8 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56);
 int cs35l56_init(struct cs35l56_private *cs35l56);
 void cs35l56_remove(struct cs35l56_private *cs35l56);
 
+#if IS_ENABLED(CONFIG_KUNIT)
+int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56);
+#endif
+
 #endif /* ifndef CS35L56_H */
-- 
2.47.3


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ