diff options
author | James Morris <james.l.morris@oracle.com> | 2012-10-11 18:41:29 +0800 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-10-11 18:41:29 +0800 |
commit | 59b69ac2bad602d02904d310ee156e47e74d8109 (patch) | |
tree | 0111734ea6331072d4991f9b6fb53c996a96bf79 /drivers/char | |
parent | bb95a0d73bb69d73c16d32c10a0c31a32abddb03 (diff) | |
parent | abce9ac292e13da367bbd22c1f7669f988d931ac (diff) | |
download | linux-3.10-59b69ac2bad602d02904d310ee156e47e74d8109.tar.gz linux-3.10-59b69ac2bad602d02904d310ee156e47e74d8109.tar.bz2 linux-3.10-59b69ac2bad602d02904d310ee156e47e74d8109.zip |
Merge branch 'tpmdd-next-v3.6' of git://github.com/shpedoikal/linux into for-linus
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index b429f1ea1b9..93211df52aa 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1182,17 +1182,20 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - size_t in_size = size, out_size; + size_t in_size = size; + ssize_t out_size; /* cannot perform a write until the read has cleared - 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; if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; + return -E2BIG; + + mutex_lock(&chip->buffer_mutex); if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -1202,6 +1205,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, /* atomic tpm command send and result receive */ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); + if (out_size < 0) { + mutex_unlock(&chip->buffer_mutex); + return out_size; + } atomic_set(&chip->data_pending, out_size); mutex_unlock(&chip->buffer_mutex); |