size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
- either via tpm_read or a user_read_timer timeout */
- while (atomic_read(&chip->data_pending) != 0)
- msleep(TPM_TIMEOUT);
-
- mutex_lock(&chip->buffer_mutex);
+ either via tpm_read or a user_read_timer timeout.
+ This also prevents splitted buffered writes from blocking here.
+ */
+ if (atomic_read(&chip->data_pending) != 0)
+ return -EBUSY;
/* atomic tpm command send and result receive */
out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
/* atomic tpm command send and result receive */
out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
atomic_set(&chip->data_pending, out_size);
mutex_unlock(&chip->buffer_mutex);
atomic_set(&chip->data_pending, out_size);
mutex_unlock(&chip->buffer_mutex);
ret_size = atomic_read(&chip->data_pending);
atomic_set(&chip->data_pending, 0);
if (ret_size > 0) { /* relay data */
ret_size = atomic_read(&chip->data_pending);
atomic_set(&chip->data_pending, 0);
if (ret_size > 0) { /* relay data */
if (size < ret_size)
ret_size = size;
mutex_lock(&chip->buffer_mutex);
rc = copy_to_user(buf, chip->data_buffer, ret_size);
if (size < ret_size)
ret_size = size;
mutex_lock(&chip->buffer_mutex);
rc = copy_to_user(buf, chip->data_buffer, ret_size);