diff options
author | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2014-12-12 11:46:34 -0800 |
---|---|---|
committer | Peter Huewe <peterhuewe@gmx.de> | 2015-01-17 14:00:09 +0100 |
commit | afb5abc262e962089ef2d7c2bbf71bb6f53a2a78 (patch) | |
tree | 5e59c2de94a0f083634e5ead5cf46c34df79eace /drivers/char/tpm/tpm_i2c_infineon.c | |
parent | 87155b7311bfec75b590b823b11f77adf2a16412 (diff) | |
download | op-kernel-dev-afb5abc262e962089ef2d7c2bbf71bb6f53a2a78.zip op-kernel-dev-afb5abc262e962089ef2d7c2bbf71bb6f53a2a78.tar.gz |
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_infineon.c')
-rw-r--r-- | drivers/char/tpm/tpm_i2c_infineon.c | 37 |
1 files changed, 7 insertions, 30 deletions
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 472af4b..03708e6 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -581,12 +581,9 @@ static int tpm_tis_i2c_init(struct device *dev) int rc = 0; struct tpm_chip *chip; - chip = tpm_register_hardware(dev, &tpm_tis_i2c); - if (!chip) { - dev_err(dev, "could not register hardware\n"); - rc = -ENODEV; - goto out_err; - } + chip = tpmm_chip_alloc(dev, &tpm_tis_i2c); + if (IS_ERR(chip)) + return PTR_ERR(chip); /* Disable interrupts */ chip->vendor.irq = 0; @@ -600,7 +597,7 @@ static int tpm_tis_i2c_init(struct device *dev) if (request_locality(chip, 0) != 0) { dev_err(dev, "could not request locality\n"); rc = -ENODEV; - goto out_vendor; + goto out_err; } /* read four bytes from DID_VID register */ @@ -628,21 +625,9 @@ static int tpm_tis_i2c_init(struct device *dev) tpm_get_timeouts(chip); tpm_do_selftest(chip); - return 0; - + return tpm_chip_register(chip); out_release: release_locality(chip, chip->vendor.locality, 1); - -out_vendor: - /* close file handles */ - tpm_dev_vendor_release(chip); - - /* remove hardware */ - tpm_remove_hardware(chip->dev); - - /* reset these pointers, otherwise we oops */ - chip->dev->release = NULL; - chip->release = NULL; tpm_dev.client = NULL; out_err: return rc; @@ -712,17 +697,9 @@ static int tpm_tis_i2c_probe(struct i2c_client *client, static int tpm_tis_i2c_remove(struct i2c_client *client) { struct tpm_chip *chip = tpm_dev.chip; - release_locality(chip, chip->vendor.locality, 1); - /* close file handles */ - tpm_dev_vendor_release(chip); - - /* remove hardware */ - tpm_remove_hardware(chip->dev); - - /* reset these pointers, otherwise we oops */ - chip->dev->release = NULL; - chip->release = NULL; + tpm_chip_unregister(chip); + release_locality(chip, chip->vendor.locality, 1); tpm_dev.client = NULL; return 0; |