]> Pileus Git - ~andy/linux/blobdiff - drivers/char/tpm/tpm.c
Merge git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[~andy/linux] / drivers / char / tpm / tpm.c
index 4f18f84b498a4b774d76c93d8c39e58053ca7344..e70d13defde4bcc30724187ff6443f553730eeb7 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);
@@ -1133,23 +1140,33 @@ int tpm_pm_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
+/* In case vendor provided release function, call it too.*/
+
+void tpm_dev_vendor_release(struct tpm_chip *chip)
+{
+       if (chip->vendor.release)
+               chip->vendor.release(chip->dev);
+
+       clear_bit(chip->dev_num, dev_mask);
+       kfree(chip->vendor.miscdev.name);
+}
+EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
+
+
 /*
  * Once all references to platform device are down to 0,
  * release all allocated structures.
- * In case vendor provided release function, call it too.
  */
 static void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
-       if (chip->vendor.release)
-               chip->vendor.release(dev);
-       chip->release(dev);
+       tpm_dev_vendor_release(chip);
 
-       clear_bit(chip->dev_num, dev_mask);
-       kfree(chip->vendor.miscdev.name);
+       chip->release(dev);
        kfree(chip);
 }
+EXPORT_SYMBOL_GPL(tpm_dev_release);
 
 /*
  * Called from tpm_<specific>.c probe function only for devices 
@@ -1170,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);
@@ -1191,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
@@ -1233,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);