Instead, perform the check in the following way:
1. Read the current timestamp
2. Read the completion status. If completed, return the result
3. Sleep
4. Check if the timestamp read at step 1 exceeds the timeout. Return
an error if it does
5. Goto 1
Also, use ktime instead of jiffes as a more reliable and precise timing
source.
"also", i.e. a logically separate change which should be split up to
a separate patch.
+ curr_time = ktime_get();
u8 status = tpm_chip_status(chip);
if ((status & chip->ops->req_complete_mask) ==
chip->ops->req_complete_val)
@@ -140,7 +149,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
tpm_msleep(TPM_TIMEOUT_POLL);
rmb();
- } while (time_before(jiffies, stop));
+ } while (ktime_before(curr_time, timeout));
Wouldn't it be simpler fix to just check completion after dropping out
of the loop?
And declare this before tpm_try_transmit():
static bool tpm_transmit_completed(struct tpm_chip *chip)
{
u8 status = tpm_chip_status(chip);
return (status & chip->ops->req_complete_mask) == chip->ops->req_complete_val;
}