Commit 7a2f55d0 authored by Lino Sanfilippo's avatar Lino Sanfilippo Committed by Jarkko Sakkinen

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: default avatarLino Sanfilippo <l.sanfilippo@kunbus.com>
Tested-by: default avatarMichael Niewöhner <linux@mniewoehner.de>
Tested-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
Reviewed-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
parent 35f62128
......@@ -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)
{
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
return 0;
}
static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
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 request_locality(struct tpm_chip *chip, int l)
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 @@ static int request_locality(struct tpm_chip *chip, int l)
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 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment