diff options
author | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2015-03-01 16:55:47 -0500 |
---|---|---|
committer | Peter Huewe <peterhuewe@gmx.de> | 2015-03-06 16:35:49 -0500 |
commit | 19913b6db3aa417d855318c9cf5b40fbc1f28e52 (patch) | |
tree | edc596fc2c6577237680788ace8d2736c9270d3d | |
parent | 62dfd912ab3b5405b6fe72d0135c37e9648071f1 (diff) |
tpm: fix call order in tpm-chip.c
- tpm_dev_add_device(): cdev_add() must be done before uevent is
propagated in order to avoid races.
- tpm_chip_register(): tpm_dev_add_device() must be done as the
last step before exposing device to the user space in order to
avoid races.
In addition clarified description in tpm_chip_register().
Fixes: 313d21eeab92 ("tpm: device class for tpm")
Fixes: afb5abc262e9 ("tpm: two-phase chip management functions")
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Peter Huewe <peterhuewe@gmx.de>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 1d278ccd751f..e096e9cddb40 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -140,24 +140,24 @@ static int tpm_dev_add_device(struct tpm_chip *chip) | |||
140 | { | 140 | { |
141 | int rc; | 141 | int rc; |
142 | 142 | ||
143 | rc = device_add(&chip->dev); | 143 | rc = cdev_add(&chip->cdev, chip->dev.devt, 1); |
144 | if (rc) { | 144 | if (rc) { |
145 | dev_err(&chip->dev, | 145 | dev_err(&chip->dev, |
146 | "unable to device_register() %s, major %d, minor %d, err=%d\n", | 146 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", |
147 | chip->devname, MAJOR(chip->dev.devt), | 147 | chip->devname, MAJOR(chip->dev.devt), |
148 | MINOR(chip->dev.devt), rc); | 148 | MINOR(chip->dev.devt), rc); |
149 | 149 | ||
150 | device_unregister(&chip->dev); | ||
150 | return rc; | 151 | return rc; |
151 | } | 152 | } |
152 | 153 | ||
153 | rc = cdev_add(&chip->cdev, chip->dev.devt, 1); | 154 | rc = device_add(&chip->dev); |
154 | if (rc) { | 155 | if (rc) { |
155 | dev_err(&chip->dev, | 156 | dev_err(&chip->dev, |
156 | "unable to cdev_add() %s, major %d, minor %d, err=%d\n", | 157 | "unable to device_register() %s, major %d, minor %d, err=%d\n", |
157 | chip->devname, MAJOR(chip->dev.devt), | 158 | chip->devname, MAJOR(chip->dev.devt), |
158 | MINOR(chip->dev.devt), rc); | 159 | MINOR(chip->dev.devt), rc); |
159 | 160 | ||
160 | device_unregister(&chip->dev); | ||
161 | return rc; | 161 | return rc; |
162 | } | 162 | } |
163 | 163 | ||
@@ -174,27 +174,17 @@ static void tpm_dev_del_device(struct tpm_chip *chip) | |||
174 | * tpm_chip_register() - create a character device for the TPM chip | 174 | * tpm_chip_register() - create a character device for the TPM chip |
175 | * @chip: TPM chip to use. | 175 | * @chip: TPM chip to use. |
176 | * | 176 | * |
177 | * Creates a character device for the TPM chip and adds sysfs interfaces for | 177 | * Creates a character device for the TPM chip and adds sysfs attributes for |
178 | * the device, PPI and TCPA. As the last step this function adds the | 178 | * the device. As the last step this function adds the chip to the list of TPM |
179 | * chip to the list of TPM chips available for use. | 179 | * chips available for in-kernel use. |
180 | * | 180 | * |
181 | * NOTE: This function should be only called after the chip initialization | 181 | * This function should be only called after the chip initialization is |
182 | * is complete. | 182 | * complete. |
183 | * | ||
184 | * Called from tpm_<specific>.c probe function only for devices | ||
185 | * the driver has determined it should claim. Prior to calling | ||
186 | * this function the specific probe function has called pci_enable_device | ||
187 | * upon errant exit from this function specific probe function should call | ||
188 | * pci_disable_device | ||
189 | */ | 183 | */ |
190 | int tpm_chip_register(struct tpm_chip *chip) | 184 | int tpm_chip_register(struct tpm_chip *chip) |
191 | { | 185 | { |
192 | int rc; | 186 | int rc; |
193 | 187 | ||
194 | rc = tpm_dev_add_device(chip); | ||
195 | if (rc) | ||
196 | return rc; | ||
197 | |||
198 | /* Populate sysfs for TPM1 devices. */ | 188 | /* Populate sysfs for TPM1 devices. */ |
199 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { | 189 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { |
200 | rc = tpm_sysfs_add_device(chip); | 190 | rc = tpm_sysfs_add_device(chip); |
@@ -208,6 +198,10 @@ int tpm_chip_register(struct tpm_chip *chip) | |||
208 | chip->bios_dir = tpm_bios_log_setup(chip->devname); | 198 | chip->bios_dir = tpm_bios_log_setup(chip->devname); |
209 | } | 199 | } |
210 | 200 | ||
201 | rc = tpm_dev_add_device(chip); | ||
202 | if (rc) | ||
203 | return rc; | ||
204 | |||
211 | /* Make the chip available. */ | 205 | /* Make the chip available. */ |
212 | spin_lock(&driver_lock); | 206 | spin_lock(&driver_lock); |
213 | list_add_rcu(&chip->list, &tpm_chip_list); | 207 | list_add_rcu(&chip->list, &tpm_chip_list); |