From: Tzung-Bi Shih <tzungbi@kernel.org>
To: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Johan Hovold <johan@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Bartosz Golaszewski <brgl@kernel.org>,
Linus Walleij <linusw@kernel.org>,
driver-core@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org
Subject: Re: [PATCH v14 4/5] reset: Add KUnit test cases
Date: Wed, 28 Oct 2026 12:10:57 +0000 [thread overview]
Message-ID: <auHmUVsSCbZI7V4e@google.com> (raw)
In-Reply-To: <986d1b636fc7a96b3c2e05e8725a693a496d2f62.camel@pengutronix.de>
On Mon, Oct 19, 2026 at 03:32:12PM +0200, Philipp Zabel wrote:
> On So, 2026-10-11 at 20:12 +0800, Tzung-Bi Shih wrote:
> > Since commit 9035073d0ef1 ("reset: convert reset core to using firmware
> > nodes"), reset suppliers and consumers can be wired up using software
> > nodes without requiring Device Tree or hardware devices. Leverage this
> > to add KUnit test cases for the reset controller framework.
> >
> > The test cases cover the following scenarios:
> >
> > - Basic: Verifies that a consumer can acquire a reset control via
> > fwnode and perform reset, assert, deassert, status, release, and
> > acquire operations.
> > - Use After Unregister: Verifies that after the supplier unregisters
> > the reset_controller_dev while a consumer still holds a reset_control
> > handle, subsequent consumer operations fail safely with -ENODEV.
> > - Concurrent Unregister: Verifies that unregistering the
> > reset_controller_dev concurrently with an in-flight reset operation
> > waits for the active operation to complete before returning.
> >
> > Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
>
> It looks like the Kunit tests are independent from the reset of the
> series and could be sent individually.
>
> Is there any dependency that I am missing?
No, but I was using it to verify if [PATCH v14 5/5] breaks anything. I'll
send it out independently.
> > +static int reset_test_init(struct kunit *test)
> > +{
...
> > + ctx->rcdev.ops = &reset_test_ops;
> > + ctx->rcdev.nr_resets = 1;
> > + ctx->rcdev.fwnode = ctx->supp_fwnode;
> > +
> > + ret = reset_controller_register(&ctx->rcdev);
> > + KUNIT_ASSERT_EQ(test, ret, 0);
> > +
> > + ctx->rstc = __fwnode_reset_control_get(ctx->cons_fwnode, NULL, 0,
> > + RESET_CONTROL_EXCLUSIVE);
> > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->rstc);
> > +
> > + test->priv = ctx;
>
> The rcdev and rstc could be cleaned up in .exit for the error cases.
Ack, will add a .exit() callback to clean up `rstc` and `rcdev`.
> > +static void reset_test_basic(struct kunit *test)
> > +{
...
> > + reset_control_release(rstc);
> > + KUNIT_EXPECT_EQ(test, reset_control_acquire(rstc), 0);
> > +
> > + reset_control_put(rstc);
> > + reset_controller_unregister(&ctx->rcdev);
>
> Could be cleaned up by .exit.
Ack, will let .exit() handle them.
> > +static void reset_test_use_after_unregister(struct kunit *test)
> > +{
> > + struct reset_test_context *ctx = test->priv;
> > + struct reset_control *rstc = ctx->rstc;
> > +
> > + KUNIT_EXPECT_EQ(test, ctx->reset_count, 0);
> > + KUNIT_EXPECT_EQ(test, reset_control_reset(rstc), 0);
> > + KUNIT_EXPECT_EQ(test, ctx->reset_count, 1);
> > +
> > + /* Unregister supplier while consumer still holds rstc. */
> > + reset_controller_unregister(&ctx->rcdev);
>
> If you allocate rcdev on its own instead of embedding it in the
> context, you could
>
> reset_controller_unregister(ctx->rcdev);
> ctx->rcdev = NULL;
>
> here and still have normal cleanup if not NULL in .exit.
The `reset_control_ops` callbacks use `container_of(...)` to obtain `ctx`,
so keeping `rcdev` embedded in `ctx` is convenient. Will add a bool flag
so .exit() only unregisters `rcdev` if it is still registered.
> > + KUNIT_EXPECT_EQ(test, ctx->reset_count, 1);
> > + KUNIT_EXPECT_EQ(test, reset_control_reset(rstc), -ENODEV);
> > + KUNIT_EXPECT_EQ(test, ctx->reset_count, 1);
> > +
> > + KUNIT_EXPECT_EQ(test, reset_control_assert(rstc), -ENODEV);
> > + KUNIT_EXPECT_EQ(test, reset_control_deassert(rstc), -ENODEV);
> > + KUNIT_EXPECT_EQ(test, reset_control_status(rstc), -ENODEV);
> > +
> > + reset_control_release(rstc);
> > + KUNIT_EXPECT_EQ(test, reset_control_acquire(rstc), -ENODEV);
> > +
> > + reset_control_put(rstc);
>
> This would not be required either.
Ack, will let .exit() handle it.
> > +static void reset_test_concurrent_unregister(struct kunit *test)
> > +{
> > + struct reset_test_context *rtc = test->priv;
> > + struct test_concurrent_unregister_context *ctx;
> > + int i, ret, val;
> > +
> > + rtc->rcdev.ops = &reset_test_concurrent_unregister_ops;
> > +
> > + ctx = kunit_kmalloc_array(test, 3, sizeof(*ctx), GFP_KERNEL);
> > + KUNIT_ASSERT_NOT_NULL(test, ctx);
> > +
> > + for (i = 0; i < 3; ++i) {
> > + ctx[i].test = test;
> > + init_completion(&ctx[i].started);
> > + init_completion(&ctx[i].enter);
> > +
> > + if (i == 0) {
> > + ctx[i].thread = kthread_run(
> > + test_concurrent_unregister_supplier, ctx + i,
> > + "supplier%d", i);
> > + } else {
> > + init_completion(&ctx[i].entered);
> > + init_completion(&ctx[i].exit);
> > +
> > + ctx[i].thread = kthread_run(
> > + test_concurrent_unregister_consumer, ctx + i,
> > + "consumer%d", i);
> > + }
> > + KUNIT_ASSERT_FALSE(test, IS_ERR(ctx[i].thread));
>
> Isn't this missing kthread cleanup in the error cases?
Correct, will fix it.
> > + /* Subsequent access must see -ENODEV. */
> > + KUNIT_EXPECT_EQ(test, reset_control_reset(rtc->rstc), -ENODEV);
> > + reset_control_put(rtc->rstc);
>
> reset_control_put() could be done by .exit.
Ack, will let .exit() handle it.
next prev parent reply other threads:[~2026-10-28 12:11 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-11 12:12 [PATCH v14 0/5] drivers/base: Introduce revocable Tzung-Bi Shih
2026-10-11 12:12 ` [PATCH v14 1/5] revocable: Revocable resource management Tzung-Bi Shih
2026-10-11 12:12 ` [PATCH v14 2/5] revocable: Add KUnit test cases Tzung-Bi Shih
2026-10-11 12:22 ` sashiko-bot
2026-10-11 12:12 ` [PATCH v14 3/5] gpio: Leverage revocable for accessing struct gpio_chip Tzung-Bi Shih
2026-10-11 12:30 ` sashiko-bot
2026-10-11 12:12 ` [PATCH v14 4/5] reset: Add KUnit test cases Tzung-Bi Shih
2026-10-11 12:25 ` sashiko-bot
2026-10-19 13:32 ` Philipp Zabel
2026-10-28 12:10 ` Tzung-Bi Shih [this message]
2026-10-11 12:12 ` [PATCH v14 5/5] reset: Leverage revocable for accessing struct reset_controller_dev Tzung-Bi Shih
2026-10-15 9:49 ` Bartosz Golaszewski
2026-10-19 11:53 ` Tzung-Bi Shih
2026-10-19 12:41 ` Philipp Zabel
2026-10-19 14:05 ` Bartosz Golaszewski
2026-10-28 12:11 ` Tzung-Bi Shih
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=auHmUVsSCbZI7V4e@google.com \
--to=tzungbi@kernel.org \
--cc=brgl@kernel.org \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=johan@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=p.zabel@pengutronix.de \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.