aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2008-10-12 18:35:14 -0400
committerJames Morris <jmorris@namei.org>2008-10-12 18:35:14 -0400
commit93db628658197aa46bd7f83d429908b6f187ec9c (patch)
treeb09496f42570a5864212eb8cfde4ba2ea9fa7a40 /drivers/char/tpm/tpm.c
parentf1b2a5ace996de339292d4035f9f5b294aecd11e (diff)
parent0da939b0058742ad2d8580b7db6b966d0fc72252 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r--drivers/char/tpm/tpm.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index ae766d868454..1fee7034a386 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -954,72 +954,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel);
954 954
955/* 955/*
956 * Device file system interface to the TPM 956 * Device file system interface to the TPM
957 *
958 * It's assured that the chip will be opened just once,
959 * by the check of is_open variable, which is protected
960 * by driver_lock.
957 */ 961 */
958int tpm_open(struct inode *inode, struct file *file) 962int tpm_open(struct inode *inode, struct file *file)
959{ 963{
960 int rc = 0, minor = iminor(inode); 964 int minor = iminor(inode);
961 struct tpm_chip *chip = NULL, *pos; 965 struct tpm_chip *chip = NULL, *pos;
962 966
963 lock_kernel(); 967 rcu_read_lock();
964 spin_lock(&driver_lock); 968 list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
965
966 list_for_each_entry(pos, &tpm_chip_list, list) {
967 if (pos->vendor.miscdev.minor == minor) { 969 if (pos->vendor.miscdev.minor == minor) {
968 chip = pos; 970 chip = pos;
971 get_device(chip->dev);
969 break; 972 break;
970 } 973 }
971 } 974 }
975 rcu_read_unlock();
972 976
973 if (chip == NULL) { 977 if (!chip)
974 rc = -ENODEV; 978 return -ENODEV;
975 goto err_out;
976 }
977 979
978 if (chip->num_opens) { 980 if (test_and_set_bit(0, &chip->is_open)) {
979 dev_dbg(chip->dev, "Another process owns this TPM\n"); 981 dev_dbg(chip->dev, "Another process owns this TPM\n");
980 rc = -EBUSY; 982 put_device(chip->dev);
981 goto err_out; 983 return -EBUSY;
982 } 984 }
983 985
984 chip->num_opens++;
985 get_device(chip->dev);
986
987 spin_unlock(&driver_lock);
988
989 chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); 986 chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
990 if (chip->data_buffer == NULL) { 987 if (chip->data_buffer == NULL) {
991 chip->num_opens--; 988 clear_bit(0, &chip->is_open);
992 put_device(chip->dev); 989 put_device(chip->dev);
993 unlock_kernel();
994 return -ENOMEM; 990 return -ENOMEM;
995 } 991 }
996 992
997 atomic_set(&chip->data_pending, 0); 993 atomic_set(&chip->data_pending, 0);
998 994
999 file->private_data = chip; 995 file->private_data = chip;
1000 unlock_kernel();
1001 return 0; 996 return 0;
1002
1003err_out:
1004 spin_unlock(&driver_lock);
1005 unlock_kernel();
1006 return rc;
1007} 997}
1008EXPORT_SYMBOL_GPL(tpm_open); 998EXPORT_SYMBOL_GPL(tpm_open);
1009 999
1000/*
1001 * Called on file close
1002 */
1010int tpm_release(struct inode *inode, struct file *file) 1003int tpm_release(struct inode *inode, struct file *file)
1011{ 1004{
1012 struct tpm_chip *chip = file->private_data; 1005 struct tpm_chip *chip = file->private_data;
1013 1006
1007 del_singleshot_timer_sync(&chip->user_read_timer);
1014 flush_scheduled_work(); 1008 flush_scheduled_work();
1015 spin_lock(&driver_lock);
1016 file->private_data = NULL; 1009 file->private_data = NULL;
1017 del_singleshot_timer_sync(&chip->user_read_timer);
1018 atomic_set(&chip->data_pending, 0); 1010 atomic_set(&chip->data_pending, 0);
1019 chip->num_opens--;
1020 put_device(chip->dev);
1021 kfree(chip->data_buffer); 1011 kfree(chip->data_buffer);
1022 spin_unlock(&driver_lock); 1012 clear_bit(0, &chip->is_open);
1013 put_device(chip->dev);
1023 return 0; 1014 return 0;
1024} 1015}
1025EXPORT_SYMBOL_GPL(tpm_release); 1016EXPORT_SYMBOL_GPL(tpm_release);
@@ -1093,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev)
1093 } 1084 }
1094 1085
1095 spin_lock(&driver_lock); 1086 spin_lock(&driver_lock);
1096 1087 list_del_rcu(&chip->list);
1097 list_del(&chip->list);
1098
1099 spin_unlock(&driver_lock); 1088 spin_unlock(&driver_lock);
1089 synchronize_rcu();
1100 1090
1101 misc_deregister(&chip->vendor.miscdev); 1091 misc_deregister(&chip->vendor.miscdev);
1102
1103 sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); 1092 sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
1104 tpm_bios_log_teardown(chip->bios_dir); 1093 tpm_bios_log_teardown(chip->bios_dir);
1105 1094
@@ -1144,25 +1133,33 @@ int tpm_pm_resume(struct device *dev)
1144} 1133}
1145EXPORT_SYMBOL_GPL(tpm_pm_resume); 1134EXPORT_SYMBOL_GPL(tpm_pm_resume);
1146 1135
1136/* In case vendor provided release function, call it too.*/
1137
1138void tpm_dev_vendor_release(struct tpm_chip *chip)
1139{
1140 if (chip->vendor.release)
1141 chip->vendor.release(chip->dev);
1142
1143 clear_bit(chip->dev_num, dev_mask);
1144 kfree(chip->vendor.miscdev.name);
1145}
1146EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
1147
1148
1147/* 1149/*
1148 * Once all references to platform device are down to 0, 1150 * Once all references to platform device are down to 0,
1149 * release all allocated structures. 1151 * release all allocated structures.
1150 * In case vendor provided release function,
1151 * call it too.
1152 */ 1152 */
1153static void tpm_dev_release(struct device *dev) 1153static void tpm_dev_release(struct device *dev)
1154{ 1154{
1155 struct tpm_chip *chip = dev_get_drvdata(dev); 1155 struct tpm_chip *chip = dev_get_drvdata(dev);
1156 1156
1157 if (chip->vendor.release) 1157 tpm_dev_vendor_release(chip);
1158 chip->vendor.release(dev);
1159 1158
1160 chip->release(dev); 1159 chip->release(dev);
1161
1162 clear_bit(chip->dev_num, dev_mask);
1163 kfree(chip->vendor.miscdev.name);
1164 kfree(chip); 1160 kfree(chip);
1165} 1161}
1162EXPORT_SYMBOL_GPL(tpm_dev_release);
1166 1163
1167/* 1164/*
1168 * Called from tpm_<specific>.c probe function only for devices 1165 * Called from tpm_<specific>.c probe function only for devices
@@ -1171,8 +1168,8 @@ static void tpm_dev_release(struct device *dev)
1171 * upon errant exit from this function specific probe function should call 1168 * upon errant exit from this function specific probe function should call
1172 * pci_disable_device 1169 * pci_disable_device
1173 */ 1170 */
1174struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific 1171struct tpm_chip *tpm_register_hardware(struct device *dev,
1175 *entry) 1172 const struct tpm_vendor_specific *entry)
1176{ 1173{
1177#define DEVNAME_SIZE 7 1174#define DEVNAME_SIZE 7
1178 1175
@@ -1231,21 +1228,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
1231 return NULL; 1228 return NULL;
1232 } 1229 }
1233 1230
1234 spin_lock(&driver_lock);
1235
1236 list_add(&chip->list, &tpm_chip_list);
1237
1238 spin_unlock(&driver_lock);
1239
1240 if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { 1231 if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
1241 list_del(&chip->list);
1242 misc_deregister(&chip->vendor.miscdev); 1232 misc_deregister(&chip->vendor.miscdev);
1243 put_device(chip->dev); 1233 put_device(chip->dev);
1234
1244 return NULL; 1235 return NULL;
1245 } 1236 }
1246 1237
1247 chip->bios_dir = tpm_bios_log_setup(devname); 1238 chip->bios_dir = tpm_bios_log_setup(devname);
1248 1239
1240 /* Make chip available */
1241 spin_lock(&driver_lock);
1242 list_add_rcu(&chip->list, &tpm_chip_list);
1243 spin_unlock(&driver_lock);
1244
1249 return chip; 1245 return chip;
1250} 1246}
1251EXPORT_SYMBOL_GPL(tpm_register_hardware); 1247EXPORT_SYMBOL_GPL(tpm_register_hardware);