[PATCH v5 07/10] tmp, tmp_tis: Implement usage counter for locality

From: LinoSanfilippo
Date: Fri Jun 10 2022 - 07:09:54 EST


From: Lino Sanfilippo <l.sanfilippo@xxxxxxxxxx>

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. Ensure thread-safety by protecting
the counter with a mutex.

This allows to request and release the locality from a thread and the
interrupt handler at the same time without the danger to interfere with
each other.

Signed-off-by: Lino Sanfilippo <l.sanfilippo@xxxxxxxxxx>
---
drivers/char/tpm/tpm_tis_core.c | 30 ++++++++++++++++++++++++++++--
drivers/char/tpm/tpm_tis_core.h | 2 ++
2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 028bec44362d..0ef74979bc2c 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -158,16 +158,26 @@ static bool check_locality(struct tpm_chip *chip, int l)
return false;
}

+static int release_locality_locked(struct tpm_tis_data *priv, int l)
+{
+ tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+ return 0;
+}
+
static int release_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)
+ release_locality_locked(priv, l);
+ mutex_unlock(&priv->locality_count_mutex);

return 0;
}

-static int request_locality(struct tpm_chip *chip, int l)
+static int request_locality_locked(struct tpm_chip *chip, int l)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
unsigned long stop, timeout;
@@ -208,6 +218,20 @@ static int request_locality(struct tpm_chip *chip, int l)
return -1;
}

+static int 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 = request_locality_locked(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);
@@ -987,6 +1011,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);

diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index 8e02faa4079d..e1871c482da2 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -94,6 +94,8 @@ enum tpm_tis_irqtest_flags {

struct tpm_tis_data {
u16 manufacturer_id;
+ struct mutex locality_count_mutex;
+ unsigned int locality_count;
int locality;
int irq;
unsigned int irqs_in_use;
--
2.36.1