diff options
| -rw-r--r-- | drivers/char/tpm/tpm.c | 61 |
1 files changed, 24 insertions, 37 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index dfd4e7fc350b..4f18f84b498a 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
| @@ -961,33 +961,28 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel); | |||
| 961 | */ | 961 | */ |
| 962 | int tpm_open(struct inode *inode, struct file *file) | 962 | int tpm_open(struct inode *inode, struct file *file) |
| 963 | { | 963 | { |
| 964 | int rc = 0, minor = iminor(inode); | 964 | int minor = iminor(inode); |
| 965 | struct tpm_chip *chip = NULL, *pos; | 965 | struct tpm_chip *chip = NULL, *pos; |
| 966 | 966 | ||
| 967 | spin_lock(&driver_lock); | 967 | rcu_read_lock(); |
| 968 | 968 | list_for_each_entry_rcu(pos, &tpm_chip_list, list) { | |
| 969 | list_for_each_entry(pos, &tpm_chip_list, list) { | ||
| 970 | if (pos->vendor.miscdev.minor == minor) { | 969 | if (pos->vendor.miscdev.minor == minor) { |
| 971 | chip = pos; | 970 | chip = pos; |
| 971 | get_device(chip->dev); | ||
| 972 | break; | 972 | break; |
| 973 | } | 973 | } |
| 974 | } | 974 | } |
| 975 | rcu_read_unlock(); | ||
| 975 | 976 | ||
| 976 | if (chip == NULL) { | 977 | if (!chip) |
| 977 | rc = -ENODEV; | 978 | return -ENODEV; |
| 978 | goto err_out; | ||
| 979 | } | ||
| 980 | 979 | ||
| 981 | if (test_and_set_bit(0, &chip->is_open)) { | 980 | if (test_and_set_bit(0, &chip->is_open)) { |
| 982 | dev_dbg(chip->dev, "Another process owns this TPM\n"); | 981 | dev_dbg(chip->dev, "Another process owns this TPM\n"); |
| 983 | rc = -EBUSY; | 982 | put_device(chip->dev); |
| 984 | goto err_out; | 983 | return -EBUSY; |
| 985 | } | 984 | } |
| 986 | 985 | ||
| 987 | get_device(chip->dev); | ||
| 988 | |||
| 989 | spin_unlock(&driver_lock); | ||
| 990 | |||
| 991 | chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); | 986 | chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); |
| 992 | if (chip->data_buffer == NULL) { | 987 | if (chip->data_buffer == NULL) { |
| 993 | clear_bit(0, &chip->is_open); | 988 | clear_bit(0, &chip->is_open); |
| @@ -999,26 +994,23 @@ int tpm_open(struct inode *inode, struct file *file) | |||
| 999 | 994 | ||
| 1000 | file->private_data = chip; | 995 | file->private_data = chip; |
| 1001 | return 0; | 996 | return 0; |
| 1002 | |||
| 1003 | err_out: | ||
| 1004 | spin_unlock(&driver_lock); | ||
| 1005 | return rc; | ||
| 1006 | } | 997 | } |
| 1007 | EXPORT_SYMBOL_GPL(tpm_open); | 998 | EXPORT_SYMBOL_GPL(tpm_open); |
| 1008 | 999 | ||
| 1000 | /* | ||
| 1001 | * Called on file close | ||
| 1002 | */ | ||
| 1009 | int tpm_release(struct inode *inode, struct file *file) | 1003 | int tpm_release(struct inode *inode, struct file *file) |
| 1010 | { | 1004 | { |
| 1011 | struct tpm_chip *chip = file->private_data; | 1005 | struct tpm_chip *chip = file->private_data; |
| 1012 | 1006 | ||
| 1013 | flush_scheduled_work(); | 1007 | flush_scheduled_work(); |
| 1014 | spin_lock(&driver_lock); | ||
| 1015 | file->private_data = NULL; | 1008 | file->private_data = NULL; |
| 1016 | del_singleshot_timer_sync(&chip->user_read_timer); | 1009 | del_singleshot_timer_sync(&chip->user_read_timer); |
| 1017 | atomic_set(&chip->data_pending, 0); | 1010 | atomic_set(&chip->data_pending, 0); |
| 1011 | kfree(chip->data_buffer); | ||
| 1018 | clear_bit(0, &chip->is_open); | 1012 | clear_bit(0, &chip->is_open); |
| 1019 | put_device(chip->dev); | 1013 | put_device(chip->dev); |
| 1020 | kfree(chip->data_buffer); | ||
| 1021 | spin_unlock(&driver_lock); | ||
| 1022 | return 0; | 1014 | return 0; |
| 1023 | } | 1015 | } |
| 1024 | EXPORT_SYMBOL_GPL(tpm_release); | 1016 | EXPORT_SYMBOL_GPL(tpm_release); |
| @@ -1092,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev) | |||
| 1092 | } | 1084 | } |
| 1093 | 1085 | ||
| 1094 | spin_lock(&driver_lock); | 1086 | spin_lock(&driver_lock); |
| 1095 | 1087 | list_del_rcu(&chip->list); | |
| 1096 | list_del(&chip->list); | ||
| 1097 | |||
| 1098 | spin_unlock(&driver_lock); | 1088 | spin_unlock(&driver_lock); |
| 1089 | synchronize_rcu(); | ||
| 1099 | 1090 | ||
| 1100 | misc_deregister(&chip->vendor.miscdev); | 1091 | misc_deregister(&chip->vendor.miscdev); |
| 1101 | |||
| 1102 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); | 1092 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
| 1103 | tpm_bios_log_teardown(chip->bios_dir); | 1093 | tpm_bios_log_teardown(chip->bios_dir); |
| 1104 | 1094 | ||
| @@ -1146,8 +1136,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); | |||
| 1146 | /* | 1136 | /* |
| 1147 | * Once all references to platform device are down to 0, | 1137 | * Once all references to platform device are down to 0, |
| 1148 | * release all allocated structures. | 1138 | * release all allocated structures. |
| 1149 | * In case vendor provided release function, | 1139 | * In case vendor provided release function, call it too. |
| 1150 | * call it too. | ||
| 1151 | */ | 1140 | */ |
| 1152 | static void tpm_dev_release(struct device *dev) | 1141 | static void tpm_dev_release(struct device *dev) |
| 1153 | { | 1142 | { |
| @@ -1155,7 +1144,6 @@ static void tpm_dev_release(struct device *dev) | |||
| 1155 | 1144 | ||
| 1156 | if (chip->vendor.release) | 1145 | if (chip->vendor.release) |
| 1157 | chip->vendor.release(dev); | 1146 | chip->vendor.release(dev); |
| 1158 | |||
| 1159 | chip->release(dev); | 1147 | chip->release(dev); |
| 1160 | 1148 | ||
| 1161 | clear_bit(chip->dev_num, dev_mask); | 1149 | clear_bit(chip->dev_num, dev_mask); |
| @@ -1170,8 +1158,8 @@ static void tpm_dev_release(struct device *dev) | |||
| 1170 | * upon errant exit from this function specific probe function should call | 1158 | * upon errant exit from this function specific probe function should call |
| 1171 | * pci_disable_device | 1159 | * pci_disable_device |
| 1172 | */ | 1160 | */ |
| 1173 | struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific | 1161 | struct tpm_chip *tpm_register_hardware(struct device *dev, |
| 1174 | *entry) | 1162 | const struct tpm_vendor_specific *entry) |
| 1175 | { | 1163 | { |
| 1176 | #define DEVNAME_SIZE 7 | 1164 | #define DEVNAME_SIZE 7 |
| 1177 | 1165 | ||
| @@ -1230,21 +1218,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
| 1230 | return NULL; | 1218 | return NULL; |
| 1231 | } | 1219 | } |
| 1232 | 1220 | ||
| 1233 | spin_lock(&driver_lock); | ||
| 1234 | |||
| 1235 | list_add(&chip->list, &tpm_chip_list); | ||
| 1236 | |||
| 1237 | spin_unlock(&driver_lock); | ||
| 1238 | |||
| 1239 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | 1221 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
| 1240 | list_del(&chip->list); | ||
| 1241 | misc_deregister(&chip->vendor.miscdev); | 1222 | misc_deregister(&chip->vendor.miscdev); |
| 1242 | put_device(chip->dev); | 1223 | put_device(chip->dev); |
| 1224 | |||
| 1243 | return NULL; | 1225 | return NULL; |
| 1244 | } | 1226 | } |
| 1245 | 1227 | ||
| 1246 | chip->bios_dir = tpm_bios_log_setup(devname); | 1228 | chip->bios_dir = tpm_bios_log_setup(devname); |
| 1247 | 1229 | ||
| 1230 | /* Make chip available */ | ||
| 1231 | spin_lock(&driver_lock); | ||
| 1232 | list_add_rcu(&chip->list, &tpm_chip_list); | ||
| 1233 | spin_unlock(&driver_lock); | ||
| 1234 | |||
| 1248 | return chip; | 1235 | return chip; |
| 1249 | } | 1236 | } |
| 1250 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 1237 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
