mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Nathan Lynch via B4 Relay <devnull+nathan.lynch.amd.com@kernel.org>
To: Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>
Cc: Tycho Andersen <tycho@kernel.org>, Wei Huang <wei.huang2@amd.com>,
	 dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Nathan Lynch <nathan.lynch@amd.com>
Subject: [PATCH 4/4] dmaengine: dmatest: Optionally make test errors fatal
Date: Wed, 22 Jul 2026 10:47:49 -0500	[thread overview]
Message-ID: <20260722-dmatest-fixes-and-fatal-errors-v1-4-8287709987ea@amd.com> (raw)
In-Reply-To: <20260722-dmatest-fixes-and-fatal-errors-v1-0-8287709987ea@amd.com>

From: Nathan Lynch <nathan.lynch@amd.com>

For automated testing it is useful to have dmatest halt the machine when
errors occur rather than logging them and continuing, so that the system
state at the point of failure can be captured instead of allowing the run
to carry on.

Add a 'fatal_errors' module parameter, defaulting to 0. When set to a
non-zero value N, panic the kernel once N test errors have accumulated in
a run; the count is reset at the start of each run. The panic is triggered
after the existing result() line is logged, so the specific error (data
mismatch, mapping/prep/submit error, timeout, or bad completion status) is
recorded before the crash.

Assisted-by: Claude:claude-opus-4-8 [Claude-Code]
Signed-off-by: Nathan Lynch <nathan.lynch@amd.com>
---
 drivers/dma/dmatest.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 0d7752c2451a..a070ce6f2fa9 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -7,6 +7,7 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/atomic.h>
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -92,6 +93,11 @@ static bool polled;
 module_param(polled, bool, 0644);
 MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
 
+static unsigned int fatal_errors;
+module_param(fatal_errors, uint, 0644);
+MODULE_PARM_DESC(fatal_errors,
+		"Panic after this many test errors in a run; 0 = never (default: 0)");
+
 /**
  * struct dmatest_params - test parameters.
  * @nobounce:		prevent using swiotlb buffer
@@ -109,6 +115,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
  * @alignment:		custom data address alignment taken as 2^alignment
  * @transfer_size:	custom transfer size in bytes
  * @polled:		use polling for completion instead of interrupts
+ * @fatal_errors:	panic after this many test errors in a run (0 = never)
  */
 struct dmatest_params {
 	bool		nobounce;
@@ -126,6 +133,7 @@ struct dmatest_params {
 	int		alignment;
 	unsigned int	transfer_size;
 	bool		polled;
+	unsigned int	fatal_errors;
 };
 
 /**
@@ -133,6 +141,7 @@ struct dmatest_params {
  * @params:		test parameters
  * @channels:		channels under test
  * @nr_channels:	number of channels under test
+ * @error_count:	test errors in the current run (for fatal_errors)
  * @lock:		access protection to the fields of this structure
  * @did_init:		module has been initialized completely
  * @last_error:		test has faced configuration issues
@@ -144,6 +153,7 @@ struct dmatest_info {
 	/* Internal state */
 	struct list_head	channels;
 	unsigned int		nr_channels;
+	atomic_t		error_count;
 	int			last_error;
 	struct mutex		lock;
 	bool			did_init;
@@ -487,6 +497,24 @@ static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
 		dbg_result(err, n, src_off, dst_off, len, data);\
 })
 
+/*
+ * Record a test error whose details were just logged via result(). When
+ * fatal_errors is set, panic once that many errors have accumulated in the
+ * current run.
+ */
+static void dmatest_note_error(struct dmatest_info *info)
+{
+	unsigned int errors;
+
+	if (!info->params.fatal_errors)
+		return;
+
+	errors = atomic_inc_return(&info->error_count);
+	if (errors >= info->params.fatal_errors)
+		panic("dmatest: fatal_errors=%u and %u error(s) encountered\n",
+		      info->params.fatal_errors, errors);
+}
+
 static unsigned long long dmatest_persec(s64 runtime, unsigned int val)
 {
 	unsigned long long per_sec = 1000000;
@@ -583,7 +611,7 @@ static int dmatest_func(void *data)
 	struct dma_device	*dev;
 	struct device		*dma_dev;
 	unsigned int		error_count;
-	unsigned int		failed_tests = 0;
+	unsigned int		failed_tests = 0;	/* for this thread */
 	unsigned int		total_tests = 0;
 	dma_cookie_t		cookie;
 	enum dma_status		status;
@@ -755,6 +783,7 @@ static int dmatest_func(void *data)
 			failed_tests++;
 			result("unmap data NULL", total_tests,
 			       src->off, dst->off, len, ret);
+			dmatest_note_error(info);
 			continue;
 		}
 
@@ -910,6 +939,7 @@ static int dmatest_func(void *data)
 			result("data error", total_tests, src->off, dst->off,
 			       len, error_count);
 			failed_tests++;
+			dmatest_note_error(info);
 		} else {
 			verbose_result("test passed", total_tests, src->off,
 				       dst->off, len, 0);
@@ -920,6 +950,7 @@ static int dmatest_func(void *data)
 error_unmap_continue:
 		dmaengine_unmap_put(um);
 		failed_tests++;
+		dmatest_note_error(info);
 	}
 	ktime = ktime_sub(ktime_get(), ktime);
 	ktime = ktime_sub(ktime, comparetime);
@@ -1135,6 +1166,7 @@ static void add_threaded_test(struct dmatest_info *info)
 	params->alignment = alignment;
 	params->transfer_size = transfer_size;
 	params->polled = polled;
+	params->fatal_errors = fatal_errors;
 
 	request_channels(info, DMA_MEMCPY);
 	request_channels(info, DMA_MEMSET);
@@ -1147,6 +1179,8 @@ static void run_pending_tests(struct dmatest_info *info)
 	struct dmatest_chan *dtc;
 	unsigned int thread_count = 0;
 
+	atomic_set(&info->error_count, 0);
+
 	list_for_each_entry(dtc, &info->channels, node) {
 		struct dmatest_thread *thread;
 

-- 
2.54.0



  parent reply	other threads:[~2026-07-22 15:48 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-22 15:47 [PATCH 0/4] dmatest: shared channel fixes and fatal errors option Nathan Lynch via B4 Relay
2026-07-22 15:47 ` [PATCH 1/4] dmaengine: dmatest: Don't forcibly terminate channel in polled mode Nathan Lynch via B4 Relay
2026-07-22 15:47 ` [PATCH 2/4] dmaengine: dmatest: Suppress bogus failures when stopping a run Nathan Lynch via B4 Relay
2026-07-22 15:47 ` [PATCH 3/4] dmaengine: dmatest: Terminate channel before freeing threads Nathan Lynch via B4 Relay
2026-07-22 15:47 ` Nathan Lynch via B4 Relay [this message]
2026-07-22 19:58   ` [PATCH 4/4] dmaengine: dmatest: Optionally make test errors fatal Tycho Andersen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260722-dmatest-fixes-and-fatal-errors-v1-4-8287709987ea@amd.com \
    --to=devnull+nathan.lynch.amd.com@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nathan.lynch@amd.com \
    --cc=tycho@kernel.org \
    --cc=vkoul@kernel.org \
    --cc=wei.huang2@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®