Skip to contentSkip to conversation

tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat()

PATCH In review Jarkko Sakkinen 3 participants 5 messages May 9 – May 15

Subsystems (3)
lore
Share & tools
lore

Jarkko Sakkinen

author maintainer
#0 lore raw

PATCH 1/1 tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat()

wait_event_interruptible_timeout() evaluates its condition after setting the current task state to TASK_INTERRUPTIBLE.

With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait path is used:

    tpm_tis_status()
      tpm_tis_spi_read_bytes()
        tpm_tis_spi_transfer_full()
          spi_bus_lock()
            mutex_lock()

Address this with the following measures:

1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.

Cc [email protected] # v4.19+
Cc Linus Walleij <[email protected]>
Fixes 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")

---
Linus' change only unmasked a pre-existing bug but it is the change realizes it in tpm_tis_spi.

 drivers/char/tpm/tpm_tis_core.c | 35 ++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 14 deletions(-)
drivers/char/tpm/tpm_tis_core.c +21 -14
index 21d79ad3b164..153a57c79240 100644
@@ -66,8 +66,8 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
 		bool check_cancel)
 {
 	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	unsigned long stop;
-	long rc;
 	u8 status;
 	bool canceled = false;
 	u8 sts_mask;
@@ -87,23 +87,30 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
 	/* process status changes with irq support */
 	if (sts_mask) {
 		ret = -ETIME;
+		add_wait_queue(queue, &wait);
 again:
+		if (wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
+					   &canceled)) {
+			ret = canceled ? -ECANCELED : 0;
+			goto out;
+		}
+
 		timeout = stop - jiffies;
 		if ((long)timeout <= 0)
-			return -ETIME;
-		rc = wait_event_interruptible_timeout(*queue,
-			wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
-					       &canceled),
-			timeout);
-		if (rc > 0) {
-			if (canceled)
-				return -ECANCELED;
-			ret = 0;
-		}
-		if (rc == -ERESTARTSYS && freezing(current)) {
-			clear_thread_flag(TIF_SIGPENDING);
-			goto again;
+			goto out;
+
+		if (signal_pending(current)) {
+			if (freezing(current)) {
+				clear_thread_flag(TIF_SIGPENDING);
+				goto again;
+			}
+			goto out;
 		}
+
+		wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
+		goto again;
+out:
+		remove_wait_queue(queue, &wait);
 	}
 
 	if (ret)

--
2.47.3

Tested-by on v1 1/1
#1 lore raw

Am 09.05.26 um 20:51 schrieb Jarkko Sakkinen:

Quoted 17 lines

wait_event_interruptible_timeout() evaluates its condition after setting the current task state to TASK_INTERRUPTIBLE.

With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait path is used:

     tpm_tis_status()
       tpm_tis_spi_read_bytes()
         tpm_tis_spi_transfer_full()
           spi_bus_lock()
             mutex_lock()

Address this with the following measures:

1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.

Quoted 7 lines
Cc [email protected] # v4.19+
Cc Linus Walleij <[email protected]>
Fixes 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")

The issue isn't reproducible anymore. Thanks

author maintainer
#2 lore raw
Quoted 25 lines · Stefan Wahren

Am 09.05.26 um 20:51 schrieb Jarkko Sakkinen:

Quoted 17 lines

wait_event_interruptible_timeout() evaluates its condition after setting the current task state to TASK_INTERRUPTIBLE.

With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait path is used:

     tpm_tis_status()
       tpm_tis_spi_read_bytes()
         tpm_tis_spi_transfer_full()
           spi_bus_lock()
             mutex_lock()

Address this with the following measures:

1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.

Quoted 7 lines
Cc [email protected] # v4.19+
Cc Linus Walleij <[email protected]>
Fixes 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")
Quoted 3 lines

The issue isn't reproducible anymore. Thanks

Thank you.

BR, Jarkko

Reviewed-by on v1 1/1
#3 lore raw
In reply to Jarkko Sakkinen
Quoted 23 lines · Jarkko Sakkinen

wait_event_interruptible_timeout() evaluates its condition after setting the current task state to TASK_INTERRUPTIBLE.

With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait path is used:

    tpm_tis_status()
      tpm_tis_spi_read_bytes()
        tpm_tis_spi_transfer_full()
          spi_bus_lock()
            mutex_lock()

Address this with the following measures:

1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.

Cc [email protected] # v4.19+
Cc Linus Walleij <[email protected]>
Fixes 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")
Quoted 3 lines

---
Linus' change only unmasked a pre-existing bug but it is the change realizes it in tpm_tis_spi.

Took me a while to understand this but looks right to me!

Yours,
Linus Walleij

author maintainer
#4 lore raw
Quoted 29 lines · Linus Walleij
Quoted 23 lines · Jarkko Sakkinen

wait_event_interruptible_timeout() evaluates its condition after setting the current task state to TASK_INTERRUPTIBLE.

With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait path is used:

    tpm_tis_status()
      tpm_tis_spi_read_bytes()
        tpm_tis_spi_transfer_full()
          spi_bus_lock()
            mutex_lock()

Address this with the following measures:

1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.

Cc [email protected] # v4.19+
Cc Linus Walleij <[email protected]>
Fixes 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")
Quoted 3 lines

---
Linus' change only unmasked a pre-existing bug but it is the change realizes it in tpm_tis_spi.

Quoted 2 lines

Took me a while to understand this but looks right to me!

Thank you.

Quoted 3 lines

Yours,
Linus Walleij

BR, Jarkko