[PATCH net v3 2/2] nfc: trf7970a: quiesce timeout work before teardown
From: Fan Wu <hidden>
Date: 2026-08-01 05:11:58
Also in:
lkml, netdev, oe-linux-nfc, stable
Subsystem:
nfc subsystem, the rest, ti trf7970a nfc driver · Maintainers:
David Heidelberg, Linus Torvalds, Mark Greer
The timeout work can be running, blocked on trf->lock, while
trf7970a_remove() runs trf7970a_shutdown() under that lock. shutdown()
completes the active command through trf->cb(), but its non-blocking
cancel cannot stop a handler that is already running. Once remove drops
the lock, the handler may resume and complete the same command a second
time through trf->cb(). By then nfc_digital_unregister_device() may have
freed the struct digital_cmd referenced by trf->cb_arg.
Set ignore_timeout before shutdown completes the command, so the handler
short-circuits when it resumes. Then call cancel_delayed_work_sync()
after nfc_digital_unregister_device() and before nfc_digital_free_device().
Handle TRF7970A_ST_LISTENING_MD in shutdown so RF is switched off for
that state too; otherwise a threaded IRQ can re-arm the work after the
drain.
This patch depends on the preceding patch, which keeps trf->lock valid
until the threaded IRQ is drained.
This issue was found by an in-house static analysis tool.
Fixes: 165063f1dac4 ("NFC: trf7970a: Add driver with ISO/IEC 14443 Type 2 Tag Support")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <redacted>
---
drivers/nfc/trf7970a.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index 9c6f8db..42e7c05 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c@@ -2015,6 +2015,8 @@ static void trf7970a_shutdown(struct trf7970a *trf) case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: case TRF7970A_ST_WAIT_TO_ISSUE_EOF: case TRF7970A_ST_LISTENING: + case TRF7970A_ST_LISTENING_MD: + trf->ignore_timeout = true; trf7970a_send_err_upstream(trf, -ECANCELED); fallthrough; case TRF7970A_ST_IDLE:
@@ -2210,6 +2212,7 @@ static int trf7970a_probe(struct spi_device *spi) err_shutdown: trf7970a_shutdown(trf); err_free_ddev: + cancel_delayed_work_sync(&trf->timeout_work); nfc_digital_free_device(trf->ddev); err_disable_vddio_regulator: regulator_disable(trf->vddio_regulator);
@@ -2229,6 +2232,7 @@ static void trf7970a_remove(struct spi_device *spi) mutex_unlock(&trf->lock); nfc_digital_unregister_device(trf->ddev); + cancel_delayed_work_sync(&trf->timeout_work); nfc_digital_free_device(trf->ddev); regulator_disable(trf->vddio_regulator);
--
2.34.1