summaryrefslogtreecommitdiff
path: root/drivers/char/tpm/tpm_i2c_atmel.c
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2014-12-12 11:46:34 -0800
committerPeter Huewe <peterhuewe@gmx.de>2015-01-17 14:00:09 +0100
commitafb5abc262e962089ef2d7c2bbf71bb6f53a2a78 (patch)
tree5e59c2de94a0f083634e5ead5cf46c34df79eace /drivers/char/tpm/tpm_i2c_atmel.c
parent87155b7311bfec75b590b823b11f77adf2a16412 (diff)
tpm: two-phase chip management functions
tpm_register_hardware() and tpm_remove_hardware() are called often before initializing the device. The problem is that the device might not be fully initialized when it comes visible to the user space. This patch resolves the issue by diving initialization into two parts: - tpmm_chip_alloc() creates struct tpm_chip. - tpm_chip_register() sets up the character device and sysfs attributes. The framework takes care of freeing struct tpm_chip by using the devres API. The broken release callback has been wiped. ACPI drivers do not ever get this callback. Regards to Jason Gunthorpe for carefully reviewing this part of the code. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Jasob Gunthorpe <jason.gunthorpe@obsidianresearch.com> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Tested-by: Scot Doyle <lkml14@scotdoyle.com> Tested-by: Peter Huewe <peterhuewe@gmx.de> [phuewe: update to upstream changes] Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char/tpm/tpm_i2c_atmel.c')
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c39
1 files changed, 11 insertions, 28 deletions
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
index 5f448886417f..643a9402e911 100644
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -153,25 +153,20 @@ static const struct tpm_class_ops i2c_atmel = {
static int i2c_atmel_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int rc;
struct tpm_chip *chip;
struct device *dev = &client->dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
- chip = tpm_register_hardware(dev, &i2c_atmel);
- if (!chip) {
- dev_err(dev, "%s() error in tpm_register_hardware\n", __func__);
- return -ENODEV;
- }
+ chip = tpmm_chip_alloc(dev, &i2c_atmel);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
GFP_KERNEL);
- if (!chip->vendor.priv) {
- rc = -ENOMEM;
- goto out_err;
- }
+ if (!chip->vendor.priv)
+ return -ENOMEM;
/* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
@@ -183,32 +178,20 @@ static int i2c_atmel_probe(struct i2c_client *client,
/* There is no known way to probe for this device, and all version
* information seems to be read via TPM commands. Thus we rely on the
* TPM startup process in the common code to detect the device. */
- if (tpm_get_timeouts(chip)) {
- rc = -ENODEV;
- goto out_err;
- }
-
- if (tpm_do_selftest(chip)) {
- rc = -ENODEV;
- goto out_err;
- }
+ if (tpm_get_timeouts(chip))
+ return -ENODEV;
- return 0;
+ if (tpm_do_selftest(chip))
+ return -ENODEV;
-out_err:
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(chip->dev);
- return rc;
+ return tpm_chip_register(chip);
}
static int i2c_atmel_remove(struct i2c_client *client)
{
struct device *dev = &(client->dev);
struct tpm_chip *chip = dev_get_drvdata(dev);
-
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(dev);
- kfree(chip);
+ tpm_chip_unregister(chip);
return 0;
}