tpm, tpm: Implement usage counter for locality
Implement a usage counter for the (default) locality used by the TPM TIS driver: Request the locality from the TPM if it has not been claimed yet, otherwise only increment the counter. Also release the locality if the counter is 0 otherwise only decrement the counter. Since in case of SPI the register accesses are locked by means of the SPI bus mutex use a sleepable lock (i.e. also a mutex) to ensure thread-safety of the counter which may be accessed by both a userspace thread and the interrupt handler. By doing this refactor the names of the amended functions to use a more appropriate prefix. Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com> Tested-by: Michael Niewöhner <linux@mniewoehner.de> Tested-by: Jarkko Sakkinen <jarkko@kernel.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
This commit is contained in:
parent
35f621287e
commit
7a2f55d0be
|
@ -165,16 +165,27 @@ static bool check_locality(struct tpm_chip *chip, int l)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int release_locality(struct tpm_chip *chip, int l)
|
||||
static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
||||
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int request_locality(struct tpm_chip *chip, int l)
|
||||
static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
||||
mutex_lock(&priv->locality_count_mutex);
|
||||
priv->locality_count--;
|
||||
if (priv->locality_count == 0)
|
||||
__tpm_tis_relinquish_locality(priv, l);
|
||||
mutex_unlock(&priv->locality_count_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __tpm_tis_request_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
unsigned long stop, timeout;
|
||||
|
@ -215,6 +226,20 @@ again:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int tpm_tis_request_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->locality_count_mutex);
|
||||
if (priv->locality_count == 0)
|
||||
ret = __tpm_tis_request_locality(chip, l);
|
||||
if (!ret)
|
||||
priv->locality_count++;
|
||||
mutex_unlock(&priv->locality_count_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 tpm_tis_status(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
@ -682,7 +707,7 @@ static int probe_itpm(struct tpm_chip *chip)
|
|||
if (vendor != TPM_VID_INTEL)
|
||||
return 0;
|
||||
|
||||
if (request_locality(chip, 0) != 0)
|
||||
if (tpm_tis_request_locality(chip, 0) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
rc = tpm_tis_send_data(chip, cmd_getticks, len);
|
||||
|
@ -703,7 +728,7 @@ static int probe_itpm(struct tpm_chip *chip)
|
|||
|
||||
out:
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality);
|
||||
tpm_tis_relinquish_locality(chip, priv->locality);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -792,14 +817,14 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
|
|||
}
|
||||
priv->irq = irq;
|
||||
|
||||
rc = request_locality(chip, 0);
|
||||
rc = tpm_tis_request_locality(chip, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
|
||||
&original_int_vec);
|
||||
if (rc < 0) {
|
||||
release_locality(chip, priv->locality);
|
||||
tpm_tis_relinquish_locality(chip, priv->locality);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -838,7 +863,7 @@ restore_irqs:
|
|||
rc = -1;
|
||||
}
|
||||
|
||||
release_locality(chip, priv->locality);
|
||||
tpm_tis_relinquish_locality(chip, priv->locality);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -954,8 +979,8 @@ static const struct tpm_class_ops tpm_tis = {
|
|||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_canceled = tpm_tis_req_canceled,
|
||||
.request_locality = request_locality,
|
||||
.relinquish_locality = release_locality,
|
||||
.request_locality = tpm_tis_request_locality,
|
||||
.relinquish_locality = tpm_tis_relinquish_locality,
|
||||
.clk_enable = tpm_tis_clkrun_enable,
|
||||
};
|
||||
|
||||
|
@ -989,6 +1014,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
|
||||
priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
|
||||
priv->phy_ops = phy_ops;
|
||||
priv->locality_count = 0;
|
||||
mutex_init(&priv->locality_count_mutex);
|
||||
|
||||
dev_set_drvdata(&chip->dev, priv);
|
||||
|
||||
|
@ -1067,14 +1094,14 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
|
||||
intmask &= ~TPM_GLOBAL_INT_ENABLE;
|
||||
|
||||
rc = request_locality(chip, 0);
|
||||
rc = tpm_tis_request_locality(chip, 0);
|
||||
if (rc < 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
release_locality(chip, 0);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
|
||||
rc = tpm_chip_start(chip);
|
||||
if (rc)
|
||||
|
@ -1108,13 +1135,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
* proper timeouts for the driver.
|
||||
*/
|
||||
|
||||
rc = request_locality(chip, 0);
|
||||
rc = tpm_tis_request_locality(chip, 0);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
rc = tpm_get_timeouts(chip);
|
||||
|
||||
release_locality(chip, 0);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
|
||||
if (rc) {
|
||||
dev_err(dev, "Could not get TPM timeouts and durations\n");
|
||||
|
@ -1134,11 +1161,11 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
dev_err(&chip->dev, FW_BUG
|
||||
"TPM interrupt not working, polling instead\n");
|
||||
|
||||
rc = request_locality(chip, 0);
|
||||
rc = tpm_tis_request_locality(chip, 0);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
disable_interrupts(chip);
|
||||
release_locality(chip, 0);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1205,13 +1232,13 @@ int tpm_tis_resume(struct device *dev)
|
|||
* an error code but for unknown reason it isn't handled.
|
||||
*/
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
|
||||
ret = request_locality(chip, 0);
|
||||
ret = tpm_tis_request_locality(chip, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tpm1_do_selftest(chip);
|
||||
|
||||
release_locality(chip, 0);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -92,6 +92,8 @@ enum tpm_tis_flags {
|
|||
|
||||
struct tpm_tis_data {
|
||||
u16 manufacturer_id;
|
||||
struct mutex locality_count_mutex;
|
||||
unsigned int locality_count;
|
||||
int locality;
|
||||
int irq;
|
||||
unsigned int int_mask;
|
||||
|
|
Loading…
Reference in New Issue