]> Pileus Git - ~andy/linux/blobdiff - drivers/char/tpm/tpm.c
Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / drivers / char / tpm / tpm.c
index 02a495c2e068cabcb119c36a5757a45ed44fbca9..9c47dc48c9fd4526ac8e8972fb80c6b21ba2cae8 100644 (file)
@@ -525,19 +525,19 @@ void tpm_get_timeouts(struct tpm_chip *chip)
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
        if (timeout)
-               chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_a = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
        if (timeout)
-               chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_b = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
        if (timeout)
-               chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_c = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
        if (timeout)
-               chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_d = usecs_to_jiffies(timeout);
 
 duration:
        memcpy(data, tpm_cap, sizeof(tpm_cap));
@@ -554,15 +554,22 @@ duration:
                return;
 
        chip->vendor.duration[TPM_SHORT] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_1_IDX))));
+       /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
+        * value wrong and apparently reports msecs rather than usecs. So we
+        * fix up the resulting too-small TPM_SHORT value to make things work.
+        */
+       if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
+               chip->vendor.duration[TPM_SHORT] = HZ;
+
        chip->vendor.duration[TPM_MEDIUM] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_2_IDX))));
        chip->vendor.duration[TPM_LONG] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_3_IDX))));
 }
@@ -1004,9 +1011,9 @@ int tpm_release(struct inode *inode, struct file *file)
 {
        struct tpm_chip *chip = file->private_data;
 
+       del_singleshot_timer_sync(&chip->user_read_timer);
        flush_scheduled_work();
        file->private_data = NULL;
-       del_singleshot_timer_sync(&chip->user_read_timer);
        atomic_set(&chip->data_pending, 0);
        kfree(chip->data_buffer);
        clear_bit(0, &chip->is_open);
@@ -1150,7 +1157,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
  * Once all references to platform device are down to 0,
  * release all allocated structures.
  */
-static void tpm_dev_release(struct device *dev)
+void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
@@ -1180,11 +1187,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
 
-       if (chip == NULL || devname == NULL) {
-               kfree(chip);
-               kfree(devname);
-               return NULL;
-       }
+       if (chip == NULL || devname == NULL)
+               goto out_free;
 
        mutex_init(&chip->buffer_mutex);
        mutex_init(&chip->tpm_mutex);
@@ -1201,8 +1205,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
 
        if (chip->dev_num >= TPM_NUM_DEVICES) {
                dev_err(dev, "No available tpm device numbers\n");
-               kfree(chip);
-               return NULL;
+               goto out_free;
        } else if (chip->dev_num == 0)
                chip->vendor.miscdev.minor = TPM_MINOR;
        else
@@ -1243,6 +1246,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
        spin_unlock(&driver_lock);
 
        return chip;
+
+out_free:
+       kfree(chip);
+       kfree(devname);
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(tpm_register_hardware);