diff options
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r-- | drivers/char/tpm/tpm.c | 44 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 2 |
2 files changed, 29 insertions, 17 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index c88424a0c89b..a5d8bcb40000 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1031,18 +1031,13 @@ void tpm_remove_hardware(struct device *dev) | |||
1031 | 1031 | ||
1032 | spin_unlock(&driver_lock); | 1032 | spin_unlock(&driver_lock); |
1033 | 1033 | ||
1034 | dev_set_drvdata(dev, NULL); | ||
1035 | misc_deregister(&chip->vendor.miscdev); | 1034 | misc_deregister(&chip->vendor.miscdev); |
1036 | kfree(chip->vendor.miscdev.name); | ||
1037 | 1035 | ||
1038 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); | 1036 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
1039 | tpm_bios_log_teardown(chip->bios_dir); | 1037 | tpm_bios_log_teardown(chip->bios_dir); |
1040 | 1038 | ||
1041 | clear_bit(chip->dev_num, dev_mask); | 1039 | /* write it this way to be explicit (chip->dev == dev) */ |
1042 | 1040 | put_device(chip->dev); | |
1043 | kfree(chip); | ||
1044 | |||
1045 | put_device(dev); | ||
1046 | } | 1041 | } |
1047 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1042 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1048 | 1043 | ||
@@ -1083,6 +1078,26 @@ int tpm_pm_resume(struct device *dev) | |||
1083 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1078 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
1084 | 1079 | ||
1085 | /* | 1080 | /* |
1081 | * Once all references to platform device are down to 0, | ||
1082 | * release all allocated structures. | ||
1083 | * In case vendor provided release function, | ||
1084 | * call it too. | ||
1085 | */ | ||
1086 | static void tpm_dev_release(struct device *dev) | ||
1087 | { | ||
1088 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
1089 | |||
1090 | if (chip->vendor.release) | ||
1091 | chip->vendor.release(dev); | ||
1092 | |||
1093 | chip->release(dev); | ||
1094 | |||
1095 | clear_bit(chip->dev_num, dev_mask); | ||
1096 | kfree(chip->vendor.miscdev.name); | ||
1097 | kfree(chip); | ||
1098 | } | ||
1099 | |||
1100 | /* | ||
1086 | * Called from tpm_<specific>.c probe function only for devices | 1101 | * Called from tpm_<specific>.c probe function only for devices |
1087 | * the driver has determined it should claim. Prior to calling | 1102 | * the driver has determined it should claim. Prior to calling |
1088 | * this function the specific probe function has called pci_enable_device | 1103 | * this function the specific probe function has called pci_enable_device |
@@ -1136,23 +1151,21 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1136 | 1151 | ||
1137 | chip->vendor.miscdev.parent = dev; | 1152 | chip->vendor.miscdev.parent = dev; |
1138 | chip->dev = get_device(dev); | 1153 | chip->dev = get_device(dev); |
1154 | chip->release = dev->release; | ||
1155 | dev->release = tpm_dev_release; | ||
1156 | dev_set_drvdata(dev, chip); | ||
1139 | 1157 | ||
1140 | if (misc_register(&chip->vendor.miscdev)) { | 1158 | if (misc_register(&chip->vendor.miscdev)) { |
1141 | dev_err(chip->dev, | 1159 | dev_err(chip->dev, |
1142 | "unable to misc_register %s, minor %d\n", | 1160 | "unable to misc_register %s, minor %d\n", |
1143 | chip->vendor.miscdev.name, | 1161 | chip->vendor.miscdev.name, |
1144 | chip->vendor.miscdev.minor); | 1162 | chip->vendor.miscdev.minor); |
1145 | put_device(dev); | 1163 | put_device(chip->dev); |
1146 | clear_bit(chip->dev_num, dev_mask); | ||
1147 | kfree(chip); | ||
1148 | kfree(devname); | ||
1149 | return NULL; | 1164 | return NULL; |
1150 | } | 1165 | } |
1151 | 1166 | ||
1152 | spin_lock(&driver_lock); | 1167 | spin_lock(&driver_lock); |
1153 | 1168 | ||
1154 | dev_set_drvdata(dev, chip); | ||
1155 | |||
1156 | list_add(&chip->list, &tpm_chip_list); | 1169 | list_add(&chip->list, &tpm_chip_list); |
1157 | 1170 | ||
1158 | spin_unlock(&driver_lock); | 1171 | spin_unlock(&driver_lock); |
@@ -1160,10 +1173,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1160 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | 1173 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
1161 | list_del(&chip->list); | 1174 | list_del(&chip->list); |
1162 | misc_deregister(&chip->vendor.miscdev); | 1175 | misc_deregister(&chip->vendor.miscdev); |
1163 | put_device(dev); | 1176 | put_device(chip->dev); |
1164 | clear_bit(chip->dev_num, dev_mask); | ||
1165 | kfree(chip); | ||
1166 | kfree(devname); | ||
1167 | return NULL; | 1177 | return NULL; |
1168 | } | 1178 | } |
1169 | 1179 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index d15ccddc92eb..e885148b4cfb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -74,6 +74,7 @@ struct tpm_vendor_specific { | |||
74 | int (*send) (struct tpm_chip *, u8 *, size_t); | 74 | int (*send) (struct tpm_chip *, u8 *, size_t); |
75 | void (*cancel) (struct tpm_chip *); | 75 | void (*cancel) (struct tpm_chip *); |
76 | u8 (*status) (struct tpm_chip *); | 76 | u8 (*status) (struct tpm_chip *); |
77 | void (*release) (struct device *); | ||
77 | struct miscdevice miscdev; | 78 | struct miscdevice miscdev; |
78 | struct attribute_group *attr_group; | 79 | struct attribute_group *attr_group; |
79 | struct list_head list; | 80 | struct list_head list; |
@@ -106,6 +107,7 @@ struct tpm_chip { | |||
106 | struct dentry **bios_dir; | 107 | struct dentry **bios_dir; |
107 | 108 | ||
108 | struct list_head list; | 109 | struct list_head list; |
110 | void (*release) (struct device *); | ||
109 | }; | 111 | }; |
110 | 112 | ||
111 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | 113 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) |