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 303f15880466..a9be0e8eaea5 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) | |||
43 | { | 43 | { |
44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; | 44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; |
45 | 45 | ||
46 | schedule_work(&chip->work); | ||
47 | } | ||
48 | |||
49 | static void timeout_work(void * ptr) | ||
50 | { | ||
51 | struct tpm_chip *chip = ptr; | ||
52 | |||
46 | down(&chip->buffer_mutex); | 53 | down(&chip->buffer_mutex); |
47 | atomic_set(&chip->data_pending, 0); | 54 | atomic_set(&chip->data_pending, 0); |
48 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 55 | memset(chip->data_buffer, 0, TPM_BUFSIZE); |
@@ -370,6 +377,7 @@ int tpm_release(struct inode *inode, struct file *file) | |||
370 | file->private_data = NULL; | 377 | file->private_data = NULL; |
371 | chip->num_opens--; | 378 | chip->num_opens--; |
372 | del_singleshot_timer_sync(&chip->user_read_timer); | 379 | del_singleshot_timer_sync(&chip->user_read_timer); |
380 | flush_scheduled_work(); | ||
373 | atomic_set(&chip->data_pending, 0); | 381 | atomic_set(&chip->data_pending, 0); |
374 | put_device(chip->dev); | 382 | put_device(chip->dev); |
375 | kfree(chip->data_buffer); | 383 | kfree(chip->data_buffer); |
@@ -421,6 +429,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
421 | int ret_size; | 429 | int ret_size; |
422 | 430 | ||
423 | del_singleshot_timer_sync(&chip->user_read_timer); | 431 | del_singleshot_timer_sync(&chip->user_read_timer); |
432 | flush_scheduled_work(); | ||
424 | ret_size = atomic_read(&chip->data_pending); | 433 | ret_size = atomic_read(&chip->data_pending); |
425 | atomic_set(&chip->data_pending, 0); | 434 | atomic_set(&chip->data_pending, 0); |
426 | if (ret_size > 0) { /* relay data */ | 435 | if (ret_size > 0) { /* relay data */ |
@@ -428,8 +437,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
428 | ret_size = size; | 437 | ret_size = size; |
429 | 438 | ||
430 | down(&chip->buffer_mutex); | 439 | down(&chip->buffer_mutex); |
431 | if (copy_to_user | 440 | if (copy_to_user(buf, chip->data_buffer, ret_size)) |
432 | ((void __user *) buf, chip->data_buffer, ret_size)) | ||
433 | ret_size = -EFAULT; | 441 | ret_size = -EFAULT; |
434 | up(&chip->buffer_mutex); | 442 | up(&chip->buffer_mutex); |
435 | } | 443 | } |
@@ -460,7 +468,7 @@ void tpm_remove_hardware(struct device *dev) | |||
460 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); |
461 | 469 | ||
462 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 470 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= |
463 | !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | 471 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
464 | 472 | ||
465 | kfree(chip); | 473 | kfree(chip); |
466 | 474 | ||
@@ -528,6 +536,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
528 | init_MUTEX(&chip->tpm_mutex); | 536 | init_MUTEX(&chip->tpm_mutex); |
529 | INIT_LIST_HEAD(&chip->list); | 537 | INIT_LIST_HEAD(&chip->list); |
530 | 538 | ||
539 | INIT_WORK(&chip->work, timeout_work, chip); | ||
540 | |||
531 | init_timer(&chip->user_read_timer); | 541 | init_timer(&chip->user_read_timer); |
532 | chip->user_read_timer.function = user_reader_timeout; | 542 | chip->user_read_timer.function = user_reader_timeout; |
533 | chip->user_read_timer.data = (unsigned long) chip; | 543 | chip->user_read_timer.data = (unsigned long) chip; |