Re: [PATCH 1/2] tpm: Factor out common startup code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Sun, Jun 19, 2016 at 11:20:00AM +0300, andrew zamansky wrote:
> From: Jason Gunthorpe <jgunthorpe@xxxxxxxxxxxxxxxxxxxx>
> 
> The TCG standard startup sequence (get timeouts, tpm startup, etc) for
> TPM and TPM2 chips is being open coded in many drivers, move it into
> the core code.
> 
> tpm_tis and tpm_crb are used as the basis for the core code
> implementation and the easy drivers are converted. In the process
> several small drivers bugs relating to error handling this flow
> are fixed.
> 
> For now the flag TPM_OPS_AUTO_STARTUP is optional to allow a staged
> driver roll out, but ultimately all drivers should use this flow and
> the flag removed. Some drivers still do not implement the startup
> sequence at all and will need to be tested with it enabled.
> 
> Signed-off-by: Jason Gunthorpe <jgunthorpe@xxxxxxxxxxxxxxxxxxxx>
> Tested-by: Andrew Zamansky <andrew.zamansky@xxxxxxxxxxx>

Couldn't tpm?_auto_startup() be static functions inside tpm-chip.c?

> ---
>  drivers/char/tpm/st33zp24/st33zp24.c |  4 +---
>  drivers/char/tpm/tpm-chip.c          | 15 ++++++++++++++
>  drivers/char/tpm/tpm-interface.c     | 27 ++++++++++++++++++++++++
>  drivers/char/tpm/tpm.h               |  2 ++
>  drivers/char/tpm/tpm2-cmd.c          | 40 ++++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_crb.c           | 10 +--------
>  drivers/char/tpm/tpm_i2c_atmel.c     |  6 +-----
>  drivers/char/tpm/tpm_i2c_infineon.c  |  4 +---
>  drivers/char/tpm/tpm_i2c_nuvoton.c   |  7 +------
>  drivers/char/tpm/tpm_tis.c           | 24 +---------------------
>  include/linux/tpm.h                  |  6 ++++++
>  11 files changed, 96 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
> index 8d62678..4556c95 100644
> --- a/drivers/char/tpm/st33zp24/st33zp24.c
> +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> @@ -532,6 +532,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops st33zp24_tpm = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.send = st33zp24_send,
>  	.recv = st33zp24_recv,
>  	.cancel = st33zp24_cancel,
> @@ -618,9 +619,6 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
>  		tpm_gen_interrupt(chip);
>  	}
>  
> -	tpm_get_timeouts(chip);
> -	tpm_do_selftest(chip);
> -
>  	return tpm_chip_register(chip);
>  _tpm_clean_answer:
>  	dev_info(&chip->dev, "TPM initialization fail\n");
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 274dd01..9a36ced 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -223,6 +223,21 @@ int tpm_chip_register(struct tpm_chip *chip)
>  {
>  	int rc;
>  
> +	if (chip->ops->flags & TPM_OPS_PROBE_TPM2) {
> +		rc = tpm2_probe(chip);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
> +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +			rc = tpm2_auto_startup(chip);
> +		else
> +			rc = tpm1_auto_startup(chip);
> +		if (rc)
> +			return rc;
> +	}
> +
>  	rc = tpm1_chip_register(chip);
>  	if (rc)
>  		return rc;
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index e2fa89c..4e6798a 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -842,6 +842,33 @@ int tpm_do_selftest(struct tpm_chip *chip)
>  }
>  EXPORT_SYMBOL_GPL(tpm_do_selftest);
>  
> +/**
> + * tpm1_auto_startup - Perform the standard automatic TPM initialization
> + *                     sequence
> + * @chip: TPM chip to use
> + *
> + * Returns 0 on success, < 0 in case of fatal error.
> + */
> +int tpm1_auto_startup(struct tpm_chip *chip)
> +{
> +	int rc;
> +
> +	rc = tpm_get_timeouts(chip);
> +	if (rc)
> +		goto out;
> +	rc = tpm_do_selftest(chip);
> +	if (rc) {
> +		dev_err(&chip->dev, "TPM self test failed\n");
> +		goto out;
> +	}
> +
> +	return rc;
> +out:
> +	if (rc > 0)
> +		rc = -ENODEV;
> +	return rc;
> +}
> +
>  int tpm_send(u32 chip_num, void *cmd, size_t buflen)
>  {
>  	struct tpm_chip *chip;
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 28b477e..a99105f 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -501,6 +501,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
>  			 const char *desc);
>  extern int tpm_get_timeouts(struct tpm_chip *);
>  extern void tpm_gen_interrupt(struct tpm_chip *);
> +int tpm1_auto_startup(struct tpm_chip *chip);
>  extern int tpm_do_selftest(struct tpm_chip *);
>  extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
>  extern int tpm_pm_suspend(struct device *);
> @@ -539,6 +540,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
>  ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
>  			u32 *value, const char *desc);
>  
> +int tpm2_auto_startup(struct tpm_chip *chip);
>  extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
>  extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
>  extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index b28e4da..984190e 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -943,3 +943,43 @@ int tpm2_probe(struct tpm_chip *chip)
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(tpm2_probe);
> +
> +/**
> + * tpm2_auto_startup - Perform the standard automatic TPM initialization
> + *                     sequence
> + * @chip: TPM chip to use
> + *
> + * Returns 0 on success, < 0 in case of fatal error.
> + */
> +int tpm2_auto_startup(struct tpm_chip *chip)
> +{
> +	int rc;
> +
> +	rc = tpm_get_timeouts(chip);
> +	if (rc)
> +		goto out;
> +
> +	rc = tpm2_do_selftest(chip);
> +	if (rc != TPM2_RC_INITIALIZE) {
> +		dev_err(&chip->dev, "TPM self test failed\n");
> +		goto out;
> +	}
> +
> +	if (rc == TPM2_RC_INITIALIZE) {
> +		rc = tpm2_startup(chip, TPM2_SU_CLEAR);
> +		if (rc)
> +			goto out;
> +
> +		rc = tpm2_do_selftest(chip);
> +		if (rc) {
> +			dev_err(&chip->dev, "TPM self test failed\n");
> +			goto out;
> +		}
> +	}
> +
> +	return rc;
> +out:
> +	if (rc > 0)
> +		rc = -ENODEV;
> +	return rc;
> +}
> diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> index a12b319..80c4af0 100644
> --- a/drivers/char/tpm/tpm_crb.c
> +++ b/drivers/char/tpm/tpm_crb.c
> @@ -189,6 +189,7 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops tpm_crb = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = crb_status,
>  	.recv = crb_recv,
>  	.send = crb_send,
> @@ -201,7 +202,6 @@ static const struct tpm_class_ops tpm_crb = {
>  static int crb_init(struct acpi_device *device, struct crb_priv *priv)
>  {
>  	struct tpm_chip *chip;
> -	int rc;
>  
>  	chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
>  	if (IS_ERR(chip))
> @@ -211,14 +211,6 @@ static int crb_init(struct acpi_device *device, struct crb_priv *priv)
>  	chip->acpi_dev_handle = device->handle;
>  	chip->flags = TPM_CHIP_FLAG_TPM2;
>  
> -	rc = tpm_get_timeouts(chip);
> -	if (rc)
> -		return rc;
> -
> -	rc = tpm2_do_selftest(chip);
> -	if (rc)
> -		return rc;
> -
>  	return tpm_chip_register(chip);
>  }
>  
> diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
> index 8dfb88b..6f7c73d 100644
> --- a/drivers/char/tpm/tpm_i2c_atmel.c
> +++ b/drivers/char/tpm/tpm_i2c_atmel.c
> @@ -141,6 +141,7 @@ static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops i2c_atmel = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = i2c_atmel_read_status,
>  	.recv = i2c_atmel_recv,
>  	.send = i2c_atmel_send,
> @@ -178,11 +179,6 @@ 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))
> -		return -ENODEV;
> -
> -	if (tpm_do_selftest(chip))
> -		return -ENODEV;
>  
>  	return tpm_chip_register(chip);
>  }
> diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
> index 63d5d22..e08633e 100644
> --- a/drivers/char/tpm/tpm_i2c_infineon.c
> +++ b/drivers/char/tpm/tpm_i2c_infineon.c
> @@ -566,6 +566,7 @@ static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops tpm_tis_i2c = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = tpm_tis_i2c_status,
>  	.recv = tpm_tis_i2c_recv,
>  	.send = tpm_tis_i2c_send,
> @@ -622,9 +623,6 @@ static int tpm_tis_i2c_init(struct device *dev)
>  	INIT_LIST_HEAD(&chip->vendor.list);
>  	tpm_dev.chip = chip;
>  
> -	tpm_get_timeouts(chip);
> -	tpm_do_selftest(chip);
> -
>  	return tpm_chip_register(chip);
>  out_release:
>  	release_locality(chip, chip->vendor.locality, 1);
> diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
> index 847f159..b64effc 100644
> --- a/drivers/char/tpm/tpm_i2c_nuvoton.c
> +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
> @@ -456,6 +456,7 @@ static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops tpm_i2c = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = i2c_nuvoton_read_status,
>  	.recv = i2c_nuvoton_recv,
>  	.send = i2c_nuvoton_send,
> @@ -601,12 +602,6 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
>  		}
>  	}
>  
> -	if (tpm_get_timeouts(chip))
> -		return -ENODEV;
> -
> -	if (tpm_do_selftest(chip))
> -		return -ENODEV;
> -
>  	return tpm_chip_register(chip);
>  }
>  
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index a507006..30aff5b 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -524,6 +524,7 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
>  }
>  
>  static const struct tpm_class_ops tpm_tis = {
> +	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = tpm_tis_status,
>  	.recv = tpm_tis_recv,
>  	.send = tpm_tis_send,
> @@ -785,29 +786,6 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
>  			tpm_tis_probe_irq(chip, intmask);
>  	}
>  
> -	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> -		rc = tpm2_do_selftest(chip);
> -		if (rc == TPM2_RC_INITIALIZE) {
> -			dev_warn(dev, "Firmware has not started TPM\n");
> -			rc  = tpm2_startup(chip, TPM2_SU_CLEAR);
> -			if (!rc)
> -				rc = tpm2_do_selftest(chip);
> -		}
> -
> -		if (rc) {
> -			dev_err(dev, "TPM self test failed\n");
> -			if (rc > 0)
> -				rc = -ENODEV;
> -			goto out_err;
> -		}
> -	} else {
> -		if (tpm_do_selftest(chip)) {
> -			dev_err(dev, "TPM self test failed\n");
> -			rc = -ENODEV;
> -			goto out_err;
> -		}
> -	}
> -
>  	return tpm_chip_register(chip);
>  out_err:
>  	tpm_tis_remove(chip);
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 706e63e..0115470 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -33,7 +33,13 @@ struct tpm_chip;
>  struct trusted_key_payload;
>  struct trusted_key_options;
>  
> +enum TPM_OPS_FLAGS {
> +	TPM_OPS_PROBE_TPM2 = BIT(0),

I see two alternatives here:

1. Make this work for tpm_tis.c if it is doable.
2. Remove this flag and call tpm2_probe() inside tpm_i2c_nuvoton.c.

If this flag works only for a single driver, it does not bring any value.

/Jarkko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux