Linux Trace Kernel
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jingyuan Liang" <jingyliang@chromium.org>
Cc: linux-input@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
	dmitry.torokhov@gmail.com
Subject: Re: [PATCH v7 11/11] HID: spi-hid: add panel follower support
Date: Sat, 24 Oct 2026 01:10:47 +0000	[thread overview]
Message-ID: <sashiko-outbox-183484@kernel.org> (raw)
In-Reply-To: <20261024-send-upstream-v7-11-abad13174b43@chromium.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] HID: spi-hid: unrecovered deassert_reset() failure in spi_hid_resume()
- [Medium] HID: spi-hid: improper wakeup teardown for panel followers in probe
--

commit 35d9a38c1b6ffa8dbb3ab740ec9ce120c5b2e7a1
Author: Jingyuan Liang <jingyliang@chromium.org>

HID: spi-hid: add panel follower support

This commit adds DRM panel follower support to spi-hid so that a follower
device powers up and suspends in coordination with its panel rather than
during initial probe and standard system PM callbacks.

> diff --git a/drivers/hid/spi-hid/spi-hid-core.c b/drivers/hid/spi-hid/spi-hid-core.c
> index 3b8874ca0e1cc..496b33cdf3d46 100644
> --- a/drivers/hid/spi-hid/spi-hid-core.c
> +++ b/drivers/hid/spi-hid/spi-hid-core.c

[ ... ]

> @@ -325,28 +328,30 @@ static int spi_hid_resume(struct spi_hid *shid)
>  		return 0;
>  	}
>  
> -	if (!device_may_wakeup(dev)) {
> -		if (shid->power_state == HIDSPI_OFF) {
> -			shid->ops->assert_reset(shid->ops);
> +	/*
> +	 * Check power_state, not device_may_wakeup(): power/wakeup can change
> +	 * while the device is off.
> +	 */
> +	if (shid->power_state == HIDSPI_OFF) {
> +		shid->ops->assert_reset(shid->ops);
>  
> -			shid->ops->sleep_minimal_reset_delay(shid->ops);
> +		shid->ops->sleep_minimal_reset_delay(shid->ops);
>  
> -			error = shid->ops->power_up(shid->ops);
> -			if (error) {
> -				dev_err(dev, "%s: could not power up: %d\n", __func__, error);
> -				/* Suspend runs next even if resume fails. */
> -				enable_irq(shid->spi->irq);
> -				return error;
> -			}
> -			shid->power_state = HIDSPI_ON;
> -			reinit_completion(&shid->reset_done);
> -			error = shid->ops->deassert_reset(shid->ops);
> -			if (error)
> -				dev_err(dev, "%s: failed to deassert reset: %d\n",
> -					__func__, error);
> -			else
> -				was_reset = true;
> +		error = shid->ops->power_up(shid->ops);
> +		if (error) {
> +			dev_err(dev, "%s: could not power up: %d\n", __func__, error);
> +			/* Suspend runs next even if resume fails. */
> +			enable_irq(shid->spi->irq);
> +			return error;
>  		}
> +		shid->power_state = HIDSPI_ON;
> +		reinit_completion(&shid->reset_done);
> +		error = shid->ops->deassert_reset(shid->ops);
> +		if (error)
> +			dev_err(dev, "%s: failed to deassert reset: %d\n",
> +				__func__, error);
> +		else
> +			was_reset = true;
>  	}

[Severity: Medium]
What happens if shid->ops->deassert_reset(shid->ops) fails in
spi_hid_resume()?

For non-followers, initial power-up goes through spi_hid_dev_init(), which
powers down the device and returns the error when deassert_reset() fails.
For panel followers, spi_hid_core_probe() leaves shid->power_state as
HIDSPI_OFF and shid->hid as NULL, and spi_hid_panel_follower_work() relies
on spi_hid_resume() for the initial power-up as well as subsequent resumes.

When deassert_reset() fails in spi_hid_resume(), was_reset remains false
while shid->power_state is set to HIDSPI_ON and the IRQ is enabled with the
device still held in reset:

drivers/hid/spi-hid/spi-hid-core.c:spi_hid_resume() {
    ...
	if (shid->hid) {
		if (was_reset && spi_hid_wait_for_reset(shid)) {
			/* No reset response: let recovery retry. */
			set_bit(SPI_HID_ERROR, &shid->flags);
			schedule_work(&shid->reset_work);
			return -ETIMEDOUT;
		}
		/* HID requests would fail while the device is not ready. */
		if (!test_bit(SPI_HID_READY, &shid->flags))
			return 0;
    ...
}

On the first power-up of a panel follower, shid->hid is NULL, so
spi_hid_resume() returns 0 without scheduling shid->reset_work. On subsequent
resumes where shid->hid is non-NULL, was_reset is false and SPI_HID_READY was
cleared during spi_hid_suspend(), so spi_hid_resume() again returns 0 without
setting SPI_HID_ERROR or scheduling shid->reset_work.

Should a deassert_reset() failure in spi_hid_resume() trigger recovery (or
clean up and return the error) so the device is not left powered on in reset
and permanently uninitialized?

> @@ -1447,6 +1452,108 @@ static struct hid_ll_driver spi_hid_ll_driver = {

[ ... ]

> +static int spi_hid_register_panel_follower(struct spi_hid *shid)
> +{
> +	struct device *dev = &shid->spi->dev;
> +
> +	shid->panel_follower.funcs = &spi_hid_panel_follower_prepare_funcs;
> +
> +	/*
> +	 * If we're not in control of our own power up/power down then we can't
> +	 * do the logic to manage wakeups. Give a warning if a user thought
> +	 * that was possible then force the capability off.
> +	 */
> +	if (device_can_wakeup(dev)) {
> +		dev_warn(dev, "Can't wakeup if following panel\n");
> +		device_set_wakeup_capable(dev, false);
> +	}
> +
> +	return drm_panel_add_follower(dev, &shid->panel_follower);
> +}

[ ... ]

> @@ -1523,21 +1618,19 @@ int spi_hid_core_probe(struct spi_device *spi, struct spihid_ops *ops,
>  		}
>  	}
>  
> -	error = shid->ops->power_up(shid->ops);
> -	if (error) {
> -		dev_err(dev, "%s: could not power up: %d\n", __func__, error);
> -		return error;
> -	}
> -
> -	error = shid->ops->deassert_reset(shid->ops);
> -	if (error) {
> -		dev_err(dev, "%s: failed to deassert reset: %d\n", __func__, error);
> -		shid->ops->power_down(shid->ops);
> -		return error;
> +	if (shid->is_panel_follower) {
> +		/* Like the IRQ: the first panel_prepared resume enables it. */
> +		disable_work(&shid->reset_work);
> +		error = spi_hid_register_panel_follower(shid);

[Severity: Medium]
Does calling device_set_wakeup_capable(dev, false) in
spi_hid_register_panel_follower() after devm_pm_set_wake_irq() in
spi_hid_core_probe() leave the wake IRQ configured and leak
dev->power.wakeup if wakeup was enabled on the device before probe?

In spi_hid_core_probe(), if the firmware node marked the device as wakeup
capable (for example via acpi_bind_one()), device_can_wakeup(dev) is true and
devm_pm_set_wake_irq(dev, spi->irq) attaches a wake IRQ before
shid->is_panel_follower is checked:

drivers/hid/spi-hid/spi-hid-core.c:spi_hid_core_probe() {
    ...
	if (device_can_wakeup(dev)) {
		error = devm_pm_set_wake_irq(dev, spi->irq);
		if (error) {
			dev_err(dev, "%s: failed to set wake IRQ\n", __func__);
			return error;
		}
	}

	if (shid->is_panel_follower) {
		/* Like the IRQ: the first panel_prepared resume enables it. */
		disable_work(&shid->reset_work);
		error = spi_hid_register_panel_follower(shid);
    ...
}

Furthermore, if a wakeup_source was attached to dev->power.wakeup (for
example via sysfs power/wakeup before async or deferred probe completes),
calling device_set_wakeup_capable(dev, false) directly sets
dev->power.can_wakeup = false without detaching the wakeup source first.
Subsequent calls to device_wakeup_disable(dev), including from
device_pm_remove() on unbind, check dev->power.can_wakeup and return early:

drivers/base/power/wakeup.c:device_wakeup_disable() {
	struct wakeup_source *ws;

	if (!dev || !dev->power.can_wakeup)
		return;

	ws = device_wakeup_detach(dev);
	wakeup_source_unregister(ws);
}

Should spi_hid_register_panel_follower() use device_init_wakeup(dev, false)
(which calls device_wakeup_disable(dev) before clearing wakeup capability),
and should spi_hid_core_probe() skip devm_pm_set_wake_irq() when
shid->is_panel_follower is true?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261024-send-upstream-v7-0-abad13174b43@chromium.org?part=11

      reply	other threads:[~2026-10-24  1:10 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-24  0:51 [PATCH v7 00/11] Add spi-hid transport driver Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 01/11] Documentation: Correction in HID output_report callback description Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 02/11] HID: Add BUS_SPI support and define HID_SPI_DEVICE macro Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 03/11] HID: spi-hid: add transport driver skeleton for HID over SPI bus Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 04/11] HID: spi-hid: add spi-hid driver HID layer Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 05/11] HID: spi-hid: add HID SPI protocol implementation Jingyuan Liang
2026-10-24  1:13   ` sashiko-bot
2026-10-24  0:51 ` [PATCH v7 06/11] HID: spi-hid: add spi_hid traces Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 07/11] HID: spi-hid: add ACPI support for HID over SPI Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 08/11] dt-bindings: input: Document hid-over-spi DT schema Jingyuan Liang
2026-10-27 18:17   ` Conor Dooley
2026-10-27 19:10   ` Rob Herring (Arm)
2026-10-24  0:51 ` [PATCH v7 09/11] HID: spi-hid: add device tree support for HID over SPI Jingyuan Liang
2026-10-24  0:51 ` [PATCH v7 10/11] HID: spi-hid: add power management implementation Jingyuan Liang
2026-10-24  1:19   ` sashiko-bot
2026-10-24  0:51 ` [PATCH v7 11/11] HID: spi-hid: add panel follower support Jingyuan Liang
2026-10-24  1:10   ` sashiko-bot [this message]

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=sashiko-outbox-183484@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=jingyliang@chromium.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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