]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: cs_dsp: rate-limit log messages in KUnit builds
authorRichard Fitzgerald <rf@opensource.cirrus.com>
Fri, 30 Jan 2026 17:12:56 +0000 (17:12 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 2 Feb 2026 12:09:28 +0000 (12:09 +0000)
Use the dev_*_ratelimit() macros if the cs_dsp KUnit tests are enabled
in the build, and allow the KUnit tests to disable message output.

Some of the KUnit tests cause a very large number of log messages from
cs_dsp, because the tests perform many different test cases. This could
cause some lines to be dropped from the kernel log. Dropped lines can
prevent the KUnit wrappers from parsing the ktap output in the dmesg log.

The KUnit builds of cs_dsp export three bools that the KUnit tests can
use to entirely disable log output of err, warn and info messages. Some
tests have been updated to use this, replacing the previous fudge of a
usleep() in the exit handler of each test. We don't necessarily want to
disable all log messages if they aren't expected to be excessive,
so the rate-limiting allows leaving some logging enabled.

The rate-limited macros are not used in normal builds because it is not
appropriate to rate-limit every message. That could cause important
messages to be dropped, and there wouldn't be such a high rate of
messages in normal operation.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Reported-by: Mark Brown <broonie@kernel.org>
Closes: https://lore.kernel.org/linux-sound/af393f08-facb-4c44-a054-1f61254803ec@opensource.cirrus.com/T/#t
Fixes: cd8c058499b6 ("firmware: cs_dsp: Add KUnit testing of bin error cases")
Link: https://patch.msgid.link/20260130171256.863152-1-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/firmware/cirrus/cs_dsp.c
drivers/firmware/cirrus/cs_dsp.h [new file with mode: 0644]
drivers/firmware/cirrus/test/cs_dsp_test_bin.c
drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c
drivers/firmware/cirrus/test/cs_dsp_test_wmfw.c
drivers/firmware/cirrus/test/cs_dsp_test_wmfw_error.c
drivers/firmware/cirrus/test/cs_dsp_tests.c

index 525ac0f0a75d8f4e15f35a829e504df38f19fed1..73d201e7d9927a958e0b864592c6a984329b8e39 100644 (file)
@@ -9,6 +9,7 @@
  *                         Cirrus Logic International Semiconductor Ltd.
  */
 
+#include <kunit/visibility.h>
 #include <linux/cleanup.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
 #include <linux/firmware/cirrus/cs_dsp.h>
 #include <linux/firmware/cirrus/wmfw.h>
 
+#include "cs_dsp.h"
+
+/*
+ * When the KUnit test is running the error-case tests will cause a lot
+ * of messages. Rate-limit to prevent overflowing the kernel log buffer
+ * during KUnit test runs.
+ */
+#if IS_ENABLED(CONFIG_FW_CS_DSP_KUNIT_TEST)
+bool cs_dsp_suppress_err_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_err_messages);
+
+bool cs_dsp_suppress_warn_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_warn_messages);
+
+bool cs_dsp_suppress_info_messages;
+EXPORT_SYMBOL_IF_KUNIT(cs_dsp_suppress_info_messages);
+
+#define cs_dsp_err(_dsp, fmt, ...) \
+       do { \
+               if (!cs_dsp_suppress_err_messages) \
+                       dev_err_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+       } while (false)
+#define cs_dsp_warn(_dsp, fmt, ...) \
+       do { \
+               if (!cs_dsp_suppress_warn_messages) \
+                       dev_warn_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+       } while (false)
+#define cs_dsp_info(_dsp, fmt, ...) \
+       do { \
+               if (!cs_dsp_suppress_info_messages) \
+                       dev_info_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__); \
+       } while (false)
+#define cs_dsp_dbg(_dsp, fmt, ...) \
+       dev_dbg_ratelimited(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
+#else
 #define cs_dsp_err(_dsp, fmt, ...) \
        dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
 #define cs_dsp_warn(_dsp, fmt, ...) \
@@ -32,6 +68,7 @@
        dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
 #define cs_dsp_dbg(_dsp, fmt, ...) \
        dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
+#endif
 
 #define ADSP1_CONTROL_1                   0x00
 #define ADSP1_CONTROL_2                   0x02
diff --git a/drivers/firmware/cirrus/cs_dsp.h b/drivers/firmware/cirrus/cs_dsp.h
new file mode 100644 (file)
index 0000000..adf5430
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * cs_dsp.h  --  Private header for cs_dsp driver.
+ *
+ * Copyright (C) 2026 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef FW_CS_DSP_H
+#define FW_CS_DSP_H
+
+#if IS_ENABLED(CONFIG_KUNIT)
+extern bool cs_dsp_suppress_err_messages;
+extern bool cs_dsp_suppress_warn_messages;
+extern bool cs_dsp_suppress_info_messages;
+#endif
+
+#endif /* ifndef FW_CS_DSP_H */
index 163b7faecff4662dd444a69ba6cfe10d1d91d55b..2c6486fa95758df69ffd3122ae94cace3aa4af5f 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/random.h>
 #include <linux/regmap.h>
 
+#include "../cs_dsp.h"
+
 /*
  * Test method is:
  *
@@ -2224,7 +2226,22 @@ static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp)
                return ret;
 
        /* Automatically call cs_dsp_remove() when test case ends */
-       return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       if (ret)
+               return ret;
+
+       /*
+        * The large number of test cases will cause an unusually large amount
+        * of dev_info() messages from cs_dsp, so suppress these.
+        */
+       cs_dsp_suppress_info_messages = true;
+
+       return 0;
+}
+
+static void cs_dsp_bin_test_exit(struct kunit *test)
+{
+       cs_dsp_suppress_info_messages = false;
 }
 
 static int cs_dsp_bin_test_halo_init(struct kunit *test)
@@ -2536,18 +2553,21 @@ static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {
 static struct kunit_suite cs_dsp_bin_test_halo = {
        .name = "cs_dsp_bin_halo",
        .init = cs_dsp_bin_test_halo_init,
+       .exit = cs_dsp_bin_test_exit,
        .test_cases = cs_dsp_bin_test_cases_halo,
 };
 
 static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {
        .name = "cs_dsp_bin_adsp2_32bit",
        .init = cs_dsp_bin_test_adsp2_32bit_init,
+       .exit = cs_dsp_bin_test_exit,
        .test_cases = cs_dsp_bin_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {
        .name = "cs_dsp_bin_adsp2_16bit",
        .init = cs_dsp_bin_test_adsp2_16bit_init,
+       .exit = cs_dsp_bin_test_exit,
        .test_cases = cs_dsp_bin_test_cases_adsp2,
 };
 
index a7ec956d27249ec4abca50757f079d158aa5199a..631b9cb9eb2508146498918e57ca65139034b415 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 
+#include "../cs_dsp.h"
+
 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
 
@@ -380,11 +382,9 @@ static void bin_block_payload_len_garbage(struct kunit *test)
 
 static void cs_dsp_bin_err_test_exit(struct kunit *test)
 {
-       /*
-        * Testing error conditions can produce a lot of log output
-        * from cs_dsp error messages, so rate limit the test cases.
-        */
-       usleep_range(200, 500);
+       cs_dsp_suppress_err_messages = false;
+       cs_dsp_suppress_warn_messages = false;
+       cs_dsp_suppress_info_messages = false;
 }
 
 static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@@ -474,7 +474,19 @@ static int cs_dsp_bin_err_test_common_init(struct kunit *test, struct cs_dsp *ds
                return ret;
 
        /* Automatically call cs_dsp_remove() when test case ends */
-       return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       if (ret)
+               return ret;
+
+       /*
+        * Testing error conditions can produce a lot of log output
+        * from cs_dsp error messages, so suppress messages.
+        */
+       cs_dsp_suppress_err_messages = true;
+       cs_dsp_suppress_warn_messages = true;
+       cs_dsp_suppress_info_messages = true;
+
+       return 0;
 }
 
 static int cs_dsp_bin_err_test_halo_init(struct kunit *test)
index 9e997c4ee2d67ce3e8b3955de09b86a503c942ce..f02cb6cf763868ed3283cb23de7da4d33d20f9af 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 
+#include "../cs_dsp.h"
+
 /*
  * Test method is:
  *
@@ -1853,7 +1855,22 @@ static int cs_dsp_wmfw_test_common_init(struct kunit *test, struct cs_dsp *dsp,
                return ret;
 
        /* Automatically call cs_dsp_remove() when test case ends */
-       return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       if (ret)
+               return ret;
+
+       /*
+        * The large number of test cases will cause an unusually large amount
+        * of dev_info() messages from cs_dsp, so suppress these.
+        */
+       cs_dsp_suppress_info_messages = true;
+
+       return 0;
+}
+
+static void cs_dsp_wmfw_test_exit(struct kunit *test)
+{
+       cs_dsp_suppress_info_messages = false;
 }
 
 static int cs_dsp_wmfw_test_halo_init(struct kunit *test)
@@ -2163,42 +2180,49 @@ static struct kunit_case cs_dsp_wmfw_test_cases_adsp2[] = {
 static struct kunit_suite cs_dsp_wmfw_test_halo = {
        .name = "cs_dsp_wmfwV3_halo",
        .init = cs_dsp_wmfw_test_halo_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_halo,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw0 = {
        .name = "cs_dsp_wmfwV0_adsp2_32bit",
        .init = cs_dsp_wmfw_test_adsp2_32bit_wmfw0_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw1 = {
        .name = "cs_dsp_wmfwV1_adsp2_32bit",
        .init = cs_dsp_wmfw_test_adsp2_32bit_wmfw1_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_32bit_wmfw2 = {
        .name = "cs_dsp_wmfwV2_adsp2_32bit",
        .init = cs_dsp_wmfw_test_adsp2_32bit_wmfw2_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw0 = {
        .name = "cs_dsp_wmfwV0_adsp2_16bit",
        .init = cs_dsp_wmfw_test_adsp2_16bit_wmfw0_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw1 = {
        .name = "cs_dsp_wmfwV1_adsp2_16bit",
        .init = cs_dsp_wmfw_test_adsp2_16bit_wmfw1_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
 static struct kunit_suite cs_dsp_wmfw_test_adsp2_16bit_wmfw2 = {
        .name = "cs_dsp_wmfwV2_adsp2_16bit",
        .init = cs_dsp_wmfw_test_adsp2_16bit_wmfw2_init,
+       .exit = cs_dsp_wmfw_test_exit,
        .test_cases = cs_dsp_wmfw_test_cases_adsp2,
 };
 
index c309843261d724daa0d33070a39d8bceede7f48c..37162d12e2fa7873e79d939642ae9b6fc58c2938 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 
+#include "../cs_dsp.h"
+
 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
 
@@ -989,11 +991,9 @@ static void wmfw_v2_coeff_description_exceeds_block(struct kunit *test)
 
 static void cs_dsp_wmfw_err_test_exit(struct kunit *test)
 {
-       /*
-        * Testing error conditions can produce a lot of log output
-        * from cs_dsp error messages, so rate limit the test cases.
-        */
-       usleep_range(200, 500);
+       cs_dsp_suppress_err_messages = false;
+       cs_dsp_suppress_warn_messages = false;
+       cs_dsp_suppress_info_messages = false;
 }
 
 static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *dsp,
@@ -1072,7 +1072,19 @@ static int cs_dsp_wmfw_err_test_common_init(struct kunit *test, struct cs_dsp *d
                return ret;
 
        /* Automatically call cs_dsp_remove() when test case ends */
-       return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
+       if (ret)
+               return ret;
+
+       /*
+        * Testing error conditions can produce a lot of log output
+        * from cs_dsp error messages, so suppress messages.
+        */
+       cs_dsp_suppress_err_messages = true;
+       cs_dsp_suppress_warn_messages = true;
+       cs_dsp_suppress_info_messages = true;
+
+       return 0;
 }
 
 static int cs_dsp_wmfw_err_test_halo_init(struct kunit *test)
index 7b829a03ca5291246394ec665de1a28fb13d2eb7..288675fdbdc534d856451c2c685a281e233e2b2e 100644 (file)
@@ -12,3 +12,4 @@ MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
 MODULE_LICENSE("GPL");
 MODULE_IMPORT_NS("FW_CS_DSP");
 MODULE_IMPORT_NS("FW_CS_DSP_KUNIT_TEST_UTILS");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");