diff options
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 303f1588046..a9be0e8eaea 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -43,6 +43,13 @@ static void user_reader_timeout(unsigned long ptr) { struct tpm_chip *chip = (struct tpm_chip *) ptr; + schedule_work(&chip->work); +} + +static void timeout_work(void * ptr) +{ + struct tpm_chip *chip = ptr; + down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); memset(chip->data_buffer, 0, TPM_BUFSIZE); @@ -370,6 +377,7 @@ int tpm_release(struct inode *inode, struct file *file) file->private_data = NULL; chip->num_opens--; del_singleshot_timer_sync(&chip->user_read_timer); + flush_scheduled_work(); atomic_set(&chip->data_pending, 0); put_device(chip->dev); kfree(chip->data_buffer); @@ -421,6 +429,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, int ret_size; del_singleshot_timer_sync(&chip->user_read_timer); + flush_scheduled_work(); ret_size = atomic_read(&chip->data_pending); atomic_set(&chip->data_pending, 0); if (ret_size > 0) { /* relay data */ @@ -428,8 +437,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, ret_size = size; down(&chip->buffer_mutex); - if (copy_to_user - ((void __user *) buf, chip->data_buffer, ret_size)) + if (copy_to_user(buf, chip->data_buffer, ret_size)) ret_size = -EFAULT; up(&chip->buffer_mutex); } @@ -460,7 +468,7 @@ void tpm_remove_hardware(struct device *dev) sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= - !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); + ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); kfree(chip); @@ -528,6 +536,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) init_MUTEX(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); + INIT_WORK(&chip->work, timeout_work, chip); + init_timer(&chip->user_read_timer); chip->user_read_timer.function = user_reader_timeout; chip->user_read_timer.data = (unsigned long) chip; |