Re: [PATCH] staging: nvec: fix power-off path to not depend on workqueue

Marc Dietrich <[email protected]> Tue, 28 Jul 2026 10:49:09 +0200 (CEST)
Newsgroups org.kernel.vger.linux-tegra,dev.linux.lists.linux-staging,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hello Aayush,

On Tue, 21 Jul 2026, Aayush7352 wrote:

> From: Aayush Dixit <[email protected]>
>
> nvec_power_off() uses nvec_write_async() which queues work via
> schedule_work().  During system shutdown or reboot, workqueues may be
> frozen, so the AP_PWR_DOWN message never reaches the embedded
> controller and the system hangs instead of powering off.

right, but not only for PWR_DOWN but also for disabling events. Best would=
=20
be to move the toggle events to the shutdown preparation phase.

> Fix by calling nvec_request_master() directly after queuing the
> power-off messages, processing the TX queue synchronously in the
> power-off context.  Also add a NULL guard for nvec_power_handle.

This still won't work and cannot be tested as long as the driver does not=
=20
support atomic i2c tranfers, which should be implemented first.

> This addresses the TODO item "add atomic ops in order to fix
> shutoff/reboot problems" in drivers/staging/nvec/TODO.

No, atomic ops means to implement irq less i2c transfers (polling).

Marc

> Signed-off-by: Aayush Dixit <[email protected]>
> ---
> This patch has not been tested.  Compile-tested and checkpatch-clean onl=
y.
>
> drivers/staging/nvec/nvec.c | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
> index 88c416ee0..938ea8f34 100644
> --- a/drivers/staging/nvec/nvec.c
> +++ b/drivers/staging/nvec/nvec.c
> @@ -774,10 +774,23 @@ static void nvec_disable_i2c_slave(struct nvec_chi=
p *nvec)
>
> static void nvec_power_off(void)
> {
> +	struct nvec_chip *nvec =3D nvec_power_handle;
> 	char ap_pwr_down[] =3D { NVEC_SLEEP, AP_PWR_DOWN };
>
> -	nvec_toggle_global_events(nvec_power_handle, false);
> -	nvec_write_async(nvec_power_handle, ap_pwr_down, 2);
> +	if (!nvec)
> +		return;
> +
> +	nvec_toggle_global_events(nvec, false);
> +	nvec_write_async(nvec, ap_pwr_down, 2);
> +
> +	/*
> +	 * Process the TX queue directly instead of relying on the
> +	 * workqueue.  Workqueues may be frozen during the power-off
> +	 * sequence, so schedule_work() from nvec_write_async() may
> +	 * not execute, leaving the AP_PWR_DOWN message unsent and
> +	 * the system unable to power off.
> +	 */
> +	nvec_request_master(&nvec->tx_work);
> }
>
> static int tegra_nvec_probe(struct platform_device *pdev)
> --=20
> 2.55.0
>
>