2022-05-09 10:39:39

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v4 0/6] TPM irq fixes

This series fixes issues around the interrupt handling in the TPM TIS core.

Patch 1:
Request threaded interrupt handler for SPI. This is needed since SPI uses a
mutex for data transmission and since we exchange data via SPI int the irq
handler we need a sleepable context.

Patch 2:
Make locality handling simpler by only claiming it at driver startup and
releasing it at driver shutdown.

Patch 3:
Enable the irq test which is always skipped in the current code.

Patch 4:
Fix the irq test by ensuring CPU cache coherency when setting the irq test
condition on one and checking it on another CPU.

Patch 5:
Move the irq test and the check for irq test from tpm_tis_send() to
tpm_tis_probe_irq_single() so the check has not to be done for each data
transmission.

Patch 6:
Instead of blindly trying to enable all possible interrupts, use the result
from the capability query and request only the interrupts that are actually
supported.


Changes in v4:
- only request threaded irq in case of SPI as requested by Jarko.
- reimplement patch 2 to limit locality handling changes to the TIS core.
- separate fixes from cleanups as requested by Jarko.
- rephrase commit messages

Changes in v3:
- fixed compiler error reported by kernel test robot
- rephrased commit message as suggested by Jarko Sakkinen
- added Reviewed-by tag

Changes in v2:
- rebase against 5.12
- free irq on error path


Lino Sanfilippo (6):
tpm, tpm_tis_spi: Request threaded irq
tpm, tpm_tis: Claim and release locality only once
tpm, tpm_tis: enable irq test
tpm, tpm_tis: avoid CPU cache incoherency in irq test
tpm, tpm_tis: Move irq test from tpm_tis_send() to
tpm_tis_probe_irq_single()
tpm, tpm_tis: Only enable supported IRQs

drivers/char/tpm/tpm_tis_core.c | 202 ++++++++++++----------------
drivers/char/tpm/tpm_tis_core.h | 8 +-
drivers/char/tpm/tpm_tis_spi_main.c | 5 +-
3 files changed, 96 insertions(+), 119 deletions(-)


base-commit: fe27d189e3f42e31d3c8223d5daed7285e334c5e
--
2.36.0


2022-05-09 10:39:46

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

From: Lino Sanfilippo <[email protected]>

There is no need to check for the irq test completion at each data
transmission during the driver livetime. Instead do the check only once at
driver startup.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++----------------------
1 file changed, 22 insertions(+), 46 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index bdfde1cd71fe..4c65718feb7d 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip *chip)
* tpm.c can skip polling for the data to be available as the interrupt is
* waited for here
*/
-static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
int rc;
@@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
return rc;
}

-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
-{
- int rc, irq;
- struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
-
- if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
- test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
- return tpm_tis_send_main(chip, buf, len);
-
- /* Verify receipt of the expected IRQ */
- irq = priv->irq;
- priv->irq = 0;
- chip->flags &= ~TPM_CHIP_FLAG_IRQ;
- rc = tpm_tis_send_main(chip, buf, len);
- priv->irq = irq;
- chip->flags |= TPM_CHIP_FLAG_IRQ;
- if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
- tpm_msleep(1);
- if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
- disable_interrupts(chip);
- set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
- return rc;
-}
-
struct tis_vendor_durations_override {
u32 did_vid;
struct tpm1_version version;
@@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,

rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
&original_int_vec);
- if (rc < 0)
+ if (rc < 0) {
+ disable_interrupts(chip);
return rc;
+ }

rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
if (rc < 0)
- return rc;
+ goto out_err;

rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
if (rc < 0)
- return rc;
+ goto out_err;

/* Clear all existing */
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
if (rc < 0)
- return rc;
+ goto out_err;

/* Turn on */
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
intmask | TPM_GLOBAL_INT_ENABLE);
if (rc < 0)
- return rc;
+ goto out_err;

clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
- chip->flags |= TPM_CHIP_FLAG_IRQ;

/* Generate an interrupt by having the core call through to
* tpm_tis_send
*/
rc = tpm_tis_gen_interrupt(chip);
if (rc < 0)
- return rc;
+ goto out_err;

- /* tpm_tis_send will either confirm the interrupt is working or it
- * will call disable_irq which undoes all of the above.
- */
- if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
- rc = tpm_tis_write8(priv, original_int_vec,
- TPM_INT_VECTOR(priv->locality));
- if (rc < 0)
- return rc;
+ tpm_msleep(1);

- return 1;
- }
+ /* Verify receipt of the expected IRQ */
+ if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
+ goto out_err;
+
+ chip->flags |= TPM_CHIP_FLAG_IRQ;

return 0;
+
+out_err:
+ disable_interrupts(chip);
+ tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv->locality));
+
+ return rc;
}

/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
@@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
if (irq) {
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
irq);
- if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
+ if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
dev_err(&chip->dev, FW_BUG
"TPM interrupt not working, polling instead\n");
-
- disable_interrupts(chip);
- }
} else {
tpm_tis_probe_irq(chip, intmask);
}
--
2.36.0

2022-05-09 10:39:58

by Lino Sanfilippo

[permalink] [raw]
Subject: [PATCH v4 6/6] tpm, tpm_tis: Only enable supported IRQs

From: Lino Sanfilippo <[email protected]>

Instead of blindly trying to enable all possible interrupts, use the result
from the capability query and request only the interrupts that are actually
supported.

Signed-off-by: Lino Sanfilippo <[email protected]>
---
drivers/char/tpm/tpm_tis_core.c | 67 ++++++++++++++++++---------------
drivers/char/tpm/tpm_tis_core.h | 1 +
2 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 4c65718feb7d..784e153e2895 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -976,13 +976,46 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
goto out_err;
}

+ /* Figure out the capabilities */
+ rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
+ if (rc < 0)
+ goto out_err;
+
+ dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
+ intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ dev_dbg(dev, "\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT) {
+ priv->supported_irqs |= TPM_INTF_CMD_READY_INT;
+ dev_dbg(dev, "\tCommand Ready Int Support\n");
+ }
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ dev_dbg(dev, "\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ dev_dbg(dev, "\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ dev_dbg(dev, "\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ dev_dbg(dev, "\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
+ priv->supported_irqs |= TPM_INTF_LOCALITY_CHANGE_INT;
+ dev_dbg(dev, "\tLocality Change Int Support\n");
+ }
+ if (intfcaps & TPM_INTF_STS_VALID_INT) {
+ priv->supported_irqs |= TPM_INTF_STS_VALID_INT;
+ dev_dbg(dev, "\tSts Valid Int Support\n");
+ }
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
+ priv->supported_irqs |= TPM_INTF_DATA_AVAIL_INT;
+ dev_dbg(dev, "\tData Avail Int Support\n");
+ }
+
/* Take control of the TPM's interrupt hardware and shut it off */
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
if (rc < 0)
goto out_err;

- intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
- TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
+ intmask |= priv->supported_irqs;
intmask &= ~TPM_GLOBAL_INT_ENABLE;

tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
@@ -1009,32 +1042,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
goto out_err;
}

- /* Figure out the capabilities */
- rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
- if (rc < 0)
- goto out_err;
-
- dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
- intfcaps);
- if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
- dev_dbg(dev, "\tBurst Count Static\n");
- if (intfcaps & TPM_INTF_CMD_READY_INT)
- dev_dbg(dev, "\tCommand Ready Int Support\n");
- if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
- dev_dbg(dev, "\tInterrupt Edge Falling\n");
- if (intfcaps & TPM_INTF_INT_EDGE_RISING)
- dev_dbg(dev, "\tInterrupt Edge Rising\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
- dev_dbg(dev, "\tInterrupt Level Low\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
- dev_dbg(dev, "\tInterrupt Level High\n");
- if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
- dev_dbg(dev, "\tLocality Change Int Support\n");
- if (intfcaps & TPM_INTF_STS_VALID_INT)
- dev_dbg(dev, "\tSts Valid Int Support\n");
- if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
- dev_dbg(dev, "\tData Avail Int Support\n");
-
/* INTERRUPT Setup */
init_waitqueue_head(&priv->read_queue);
init_waitqueue_head(&priv->int_queue);
@@ -1101,9 +1108,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
if (rc < 0)
goto out;

- intmask |= TPM_INTF_CMD_READY_INT
- | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
- | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
+ intmask |= priv->supported_irqs | TPM_GLOBAL_INT_ENABLE;

tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);

diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index c8972ea8e13e..3d6b05c6fdba 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -97,6 +97,7 @@ struct tpm_tis_data {
u16 manufacturer_id;
int locality;
int irq;
+ unsigned int supported_irqs;
unsigned long irqtest_flags;
unsigned long flags;
void __iomem *ilb_base_addr;
--
2.36.0

2022-05-11 20:19:17

by Lino Sanfilippo

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
> On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
>> From: Lino Sanfilippo <[email protected]>
>>
>> There is no need to check for the irq test completion at each data
>> transmission during the driver livetime. Instead do the check only once at
>> driver startup.
>>
>> Signed-off-by: Lino Sanfilippo <[email protected]>
>> ---
>> drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++----------------------
>> 1 file changed, 22 insertions(+), 46 deletions(-)
>>
>> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
>> index bdfde1cd71fe..4c65718feb7d 100644
>> --- a/drivers/char/tpm/tpm_tis_core.c
>> +++ b/drivers/char/tpm/tpm_tis_core.c
>> @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip *chip)
>> * tpm.c can skip polling for the data to be available as the interrupt is
>> * waited for here
>> */
>> -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>> +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
>> {
>> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>> int rc;
>> @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>> return rc;
>> }
>>
>> -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
>> -{
>> - int rc, irq;
>> - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>> -
>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
>> - test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>> - return tpm_tis_send_main(chip, buf, len);
>> -
>> - /* Verify receipt of the expected IRQ */
>> - irq = priv->irq;
>> - priv->irq = 0;
>> - chip->flags &= ~TPM_CHIP_FLAG_IRQ;
>> - rc = tpm_tis_send_main(chip, buf, len);
>> - priv->irq = irq;
>> - chip->flags |= TPM_CHIP_FLAG_IRQ;
>> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>> - tpm_msleep(1);
>> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>> - disable_interrupts(chip);
>> - set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
>> - return rc;
>> -}
>> -
>> struct tis_vendor_durations_override {
>> u32 did_vid;
>> struct tpm1_version version;
>> @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
>>
>> rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
>> &original_int_vec);
>> - if (rc < 0)
>> + if (rc < 0) {
>> + disable_interrupts(chip);
>> return rc;
>> + }
>>
>> rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
>> if (rc < 0)
>> - return rc;
>> + goto out_err;
>>
>> rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
>> if (rc < 0)
>> - return rc;
>> + goto out_err;
>>
>> /* Clear all existing */
>> rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
>> if (rc < 0)
>> - return rc;
>> + goto out_err;
>>
>> /* Turn on */
>> rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
>> intmask | TPM_GLOBAL_INT_ENABLE);
>> if (rc < 0)
>> - return rc;
>> + goto out_err;
>>
>> clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
>> - chip->flags |= TPM_CHIP_FLAG_IRQ;
>>
>> /* Generate an interrupt by having the core call through to
>> * tpm_tis_send
>> */
>> rc = tpm_tis_gen_interrupt(chip);
>> if (rc < 0)
>> - return rc;
>> + goto out_err;
>>
>> - /* tpm_tis_send will either confirm the interrupt is working or it
>> - * will call disable_irq which undoes all of the above.
>> - */
>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
>> - rc = tpm_tis_write8(priv, original_int_vec,
>> - TPM_INT_VECTOR(priv->locality));
>> - if (rc < 0)
>> - return rc;
>> + tpm_msleep(1);
>>
>> - return 1;
>> - }
>> + /* Verify receipt of the expected IRQ */
>> + if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>> + goto out_err;
>> +
>> + chip->flags |= TPM_CHIP_FLAG_IRQ;
>>
>> return 0;
>> +
>> +out_err:
>> + disable_interrupts(chip);
>> + tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv->locality));
>> +
>> + return rc;
>> }
>>
>> /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
>> @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
>> if (irq) {
>> tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
>> irq);
>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
>> + if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
>> dev_err(&chip->dev, FW_BUG
>> "TPM interrupt not working, polling instead\n");
>> -
>> - disable_interrupts(chip);
>> - }
>> } else {
>> tpm_tis_probe_irq(chip, intmask);
>> }
>> --
>> 2.36.0
>>
>
> For me this looks just code shuffling.
>
> I don't disagree but changing working code without actual semantical
> reasons neither makes sense.
>
> BR, Jarkko
>

Well the semantical reason for this change is that the check for irq test completion
only has to be done once for the driver livetime. There is no point in doing it
over and over again for each transmission.
So the code is not simply shuffled around, it is shifted to a place where it is only
executed once.

This is not a bugfix but it is clearly an improvement/cleanup. As far as I understood
from your comments on the earlier versions of this patch set cleanups are also ok as
long as they are not intermixed with bugfixes.

Regards,
Lino

2022-05-11 21:49:45

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
> From: Lino Sanfilippo <[email protected]>
>
> There is no need to check for the irq test completion at each data
> transmission during the driver livetime. Instead do the check only once at
> driver startup.
>
> Signed-off-by: Lino Sanfilippo <[email protected]>
> ---
> drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++----------------------
> 1 file changed, 22 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index bdfde1cd71fe..4c65718feb7d 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip *chip)
> * tpm.c can skip polling for the data to be available as the interrupt is
> * waited for here
> */
> -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
> +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> {
> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> int rc;
> @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
> return rc;
> }
>
> -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> -{
> - int rc, irq;
> - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> -
> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
> - test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> - return tpm_tis_send_main(chip, buf, len);
> -
> - /* Verify receipt of the expected IRQ */
> - irq = priv->irq;
> - priv->irq = 0;
> - chip->flags &= ~TPM_CHIP_FLAG_IRQ;
> - rc = tpm_tis_send_main(chip, buf, len);
> - priv->irq = irq;
> - chip->flags |= TPM_CHIP_FLAG_IRQ;
> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> - tpm_msleep(1);
> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> - disable_interrupts(chip);
> - set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> - return rc;
> -}
> -
> struct tis_vendor_durations_override {
> u32 did_vid;
> struct tpm1_version version;
> @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
>
> rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
> &original_int_vec);
> - if (rc < 0)
> + if (rc < 0) {
> + disable_interrupts(chip);
> return rc;
> + }
>
> rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
> if (rc < 0)
> - return rc;
> + goto out_err;
>
> rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
> if (rc < 0)
> - return rc;
> + goto out_err;
>
> /* Clear all existing */
> rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
> if (rc < 0)
> - return rc;
> + goto out_err;
>
> /* Turn on */
> rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
> intmask | TPM_GLOBAL_INT_ENABLE);
> if (rc < 0)
> - return rc;
> + goto out_err;
>
> clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> - chip->flags |= TPM_CHIP_FLAG_IRQ;
>
> /* Generate an interrupt by having the core call through to
> * tpm_tis_send
> */
> rc = tpm_tis_gen_interrupt(chip);
> if (rc < 0)
> - return rc;
> + goto out_err;
>
> - /* tpm_tis_send will either confirm the interrupt is working or it
> - * will call disable_irq which undoes all of the above.
> - */
> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> - rc = tpm_tis_write8(priv, original_int_vec,
> - TPM_INT_VECTOR(priv->locality));
> - if (rc < 0)
> - return rc;
> + tpm_msleep(1);
>
> - return 1;
> - }
> + /* Verify receipt of the expected IRQ */
> + if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> + goto out_err;
> +
> + chip->flags |= TPM_CHIP_FLAG_IRQ;
>
> return 0;
> +
> +out_err:
> + disable_interrupts(chip);
> + tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv->locality));
> +
> + return rc;
> }
>
> /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
> @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
> if (irq) {
> tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
> irq);
> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> + if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
> dev_err(&chip->dev, FW_BUG
> "TPM interrupt not working, polling instead\n");
> -
> - disable_interrupts(chip);
> - }
> } else {
> tpm_tis_probe_irq(chip, intmask);
> }
> --
> 2.36.0
>

For me this looks just code shuffling.

I don't disagree but changing working code without actual semantical
reasons neither makes sense.

BR, Jarkko

2022-05-11 22:07:42

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 6/6] tpm, tpm_tis: Only enable supported IRQs

On Mon, May 09, 2022 at 10:05:59AM +0200, Lino Sanfilippo wrote:
> From: Lino Sanfilippo <[email protected]>
>
> Instead of blindly trying to enable all possible interrupts, use the result
> from the capability query and request only the interrupts that are actually
> supported.
>
> Signed-off-by: Lino Sanfilippo <[email protected]>
> ---
> drivers/char/tpm/tpm_tis_core.c | 67 ++++++++++++++++++---------------
> drivers/char/tpm/tpm_tis_core.h | 1 +
> 2 files changed, 37 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index 4c65718feb7d..784e153e2895 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -976,13 +976,46 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
> goto out_err;
> }
>
> + /* Figure out the capabilities */
> + rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
> + if (rc < 0)
> + goto out_err;
> +
> + dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
> + intfcaps);
> + if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
> + dev_dbg(dev, "\tBurst Count Static\n");
> + if (intfcaps & TPM_INTF_CMD_READY_INT) {
> + priv->supported_irqs |= TPM_INTF_CMD_READY_INT;
> + dev_dbg(dev, "\tCommand Ready Int Support\n");
> + }
> + if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
> + dev_dbg(dev, "\tInterrupt Edge Falling\n");
> + if (intfcaps & TPM_INTF_INT_EDGE_RISING)
> + dev_dbg(dev, "\tInterrupt Edge Rising\n");
> + if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
> + dev_dbg(dev, "\tInterrupt Level Low\n");
> + if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
> + dev_dbg(dev, "\tInterrupt Level High\n");
> + if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
> + priv->supported_irqs |= TPM_INTF_LOCALITY_CHANGE_INT;
> + dev_dbg(dev, "\tLocality Change Int Support\n");
> + }
> + if (intfcaps & TPM_INTF_STS_VALID_INT) {
> + priv->supported_irqs |= TPM_INTF_STS_VALID_INT;
> + dev_dbg(dev, "\tSts Valid Int Support\n");
> + }
> + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
> + priv->supported_irqs |= TPM_INTF_DATA_AVAIL_INT;
> + dev_dbg(dev, "\tData Avail Int Support\n");
> + }
> +
> /* Take control of the TPM's interrupt hardware and shut it off */
> rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
> if (rc < 0)
> goto out_err;
>
> - intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
> - TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
> + intmask |= priv->supported_irqs;
> intmask &= ~TPM_GLOBAL_INT_ENABLE;
>
> tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
> @@ -1009,32 +1042,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
> goto out_err;
> }
>
> - /* Figure out the capabilities */
> - rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
> - if (rc < 0)
> - goto out_err;
> -
> - dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
> - intfcaps);
> - if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
> - dev_dbg(dev, "\tBurst Count Static\n");
> - if (intfcaps & TPM_INTF_CMD_READY_INT)
> - dev_dbg(dev, "\tCommand Ready Int Support\n");
> - if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
> - dev_dbg(dev, "\tInterrupt Edge Falling\n");
> - if (intfcaps & TPM_INTF_INT_EDGE_RISING)
> - dev_dbg(dev, "\tInterrupt Edge Rising\n");
> - if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
> - dev_dbg(dev, "\tInterrupt Level Low\n");
> - if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
> - dev_dbg(dev, "\tInterrupt Level High\n");
> - if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
> - dev_dbg(dev, "\tLocality Change Int Support\n");
> - if (intfcaps & TPM_INTF_STS_VALID_INT)
> - dev_dbg(dev, "\tSts Valid Int Support\n");
> - if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
> - dev_dbg(dev, "\tData Avail Int Support\n");
> -
> /* INTERRUPT Setup */
> init_waitqueue_head(&priv->read_queue);
> init_waitqueue_head(&priv->int_queue);
> @@ -1101,9 +1108,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
> if (rc < 0)
> goto out;
>
> - intmask |= TPM_INTF_CMD_READY_INT
> - | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
> - | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
> + intmask |= priv->supported_irqs | TPM_GLOBAL_INT_ENABLE;
>
> tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
>
> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
> index c8972ea8e13e..3d6b05c6fdba 100644
> --- a/drivers/char/tpm/tpm_tis_core.h
> +++ b/drivers/char/tpm/tpm_tis_core.h
> @@ -97,6 +97,7 @@ struct tpm_tis_data {
> u16 manufacturer_id;
> int locality;
> int irq;
> + unsigned int supported_irqs;
> unsigned long irqtest_flags;
> unsigned long flags;
> void __iomem *ilb_base_addr;
> --
> 2.36.0
>

Does the existing code cause issues in a some specific environment?

BR, Jarkko

2022-05-12 13:22:56

by Lino Sanfilippo

[permalink] [raw]
Subject: Re: [PATCH v4 6/6] tpm, tpm_tis: Only enable supported IRQs

On 11.05.22 at 17:08, Jarkko Sakkinen wrote:
> On Mon, May 09, 2022 at 10:05:59AM +0200, Lino Sanfilippo wrote:
>> From: Lino Sanfilippo <[email protected]>
>>
>> Instead of blindly trying to enable all possible interrupts, use the result
>> from the capability query and request only the interrupts that are actually
>> supported.
>>
>> Signed-off-by: Lino Sanfilippo <[email protected]>
>> ---
>> drivers/char/tpm/tpm_tis_core.c | 67 ++++++++++++++++++---------------
>> drivers/char/tpm/tpm_tis_core.h | 1 +
>> 2 files changed, 37 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
>> index 4c65718feb7d..784e153e2895 100644
>> --- a/drivers/char/tpm/tpm_tis_core.c
>> +++ b/drivers/char/tpm/tpm_tis_core.c
>> @@ -976,13 +976,46 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
>> goto out_err;
>> }
>>
>> + /* Figure out the capabilities */
>> + rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
>> + if (rc < 0)
>> + goto out_err;
>> +
>> + dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
>> + intfcaps);
>> + if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
>> + dev_dbg(dev, "\tBurst Count Static\n");
>> + if (intfcaps & TPM_INTF_CMD_READY_INT) {
>> + priv->supported_irqs |= TPM_INTF_CMD_READY_INT;
>> + dev_dbg(dev, "\tCommand Ready Int Support\n");
>> + }
>> + if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
>> + dev_dbg(dev, "\tInterrupt Edge Falling\n");
>> + if (intfcaps & TPM_INTF_INT_EDGE_RISING)
>> + dev_dbg(dev, "\tInterrupt Edge Rising\n");
>> + if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
>> + dev_dbg(dev, "\tInterrupt Level Low\n");
>> + if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
>> + dev_dbg(dev, "\tInterrupt Level High\n");
>> + if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
>> + priv->supported_irqs |= TPM_INTF_LOCALITY_CHANGE_INT;
>> + dev_dbg(dev, "\tLocality Change Int Support\n");
>> + }
>> + if (intfcaps & TPM_INTF_STS_VALID_INT) {
>> + priv->supported_irqs |= TPM_INTF_STS_VALID_INT;
>> + dev_dbg(dev, "\tSts Valid Int Support\n");
>> + }
>> + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
>> + priv->supported_irqs |= TPM_INTF_DATA_AVAIL_INT;
>> + dev_dbg(dev, "\tData Avail Int Support\n");
>> + }
>> +
>> /* Take control of the TPM's interrupt hardware and shut it off */
>> rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
>> if (rc < 0)
>> goto out_err;
>>
>> - intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
>> - TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
>> + intmask |= priv->supported_irqs;
>> intmask &= ~TPM_GLOBAL_INT_ENABLE;
>>
>> tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
>> @@ -1009,32 +1042,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
>> goto out_err;
>> }
>>
>> - /* Figure out the capabilities */
>> - rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
>> - if (rc < 0)
>> - goto out_err;
>> -
>> - dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
>> - intfcaps);
>> - if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
>> - dev_dbg(dev, "\tBurst Count Static\n");
>> - if (intfcaps & TPM_INTF_CMD_READY_INT)
>> - dev_dbg(dev, "\tCommand Ready Int Support\n");
>> - if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
>> - dev_dbg(dev, "\tInterrupt Edge Falling\n");
>> - if (intfcaps & TPM_INTF_INT_EDGE_RISING)
>> - dev_dbg(dev, "\tInterrupt Edge Rising\n");
>> - if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
>> - dev_dbg(dev, "\tInterrupt Level Low\n");
>> - if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
>> - dev_dbg(dev, "\tInterrupt Level High\n");
>> - if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
>> - dev_dbg(dev, "\tLocality Change Int Support\n");
>> - if (intfcaps & TPM_INTF_STS_VALID_INT)
>> - dev_dbg(dev, "\tSts Valid Int Support\n");
>> - if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
>> - dev_dbg(dev, "\tData Avail Int Support\n");
>> -
>> /* INTERRUPT Setup */
>> init_waitqueue_head(&priv->read_queue);
>> init_waitqueue_head(&priv->int_queue);
>> @@ -1101,9 +1108,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
>> if (rc < 0)
>> goto out;
>>
>> - intmask |= TPM_INTF_CMD_READY_INT
>> - | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
>> - | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
>> + intmask |= priv->supported_irqs | TPM_GLOBAL_INT_ENABLE;
>>
>> tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
>>
>> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
>> index c8972ea8e13e..3d6b05c6fdba 100644
>> --- a/drivers/char/tpm/tpm_tis_core.h
>> +++ b/drivers/char/tpm/tpm_tis_core.h
>> @@ -97,6 +97,7 @@ struct tpm_tis_data {
>> u16 manufacturer_id;
>> int locality;
>> int irq;
>> + unsigned int supported_irqs;
>> unsigned long irqtest_flags;
>> unsigned long flags;
>> void __iomem *ilb_base_addr;
>> --
>> 2.36.0
>>
>
> Does the existing code cause issues in a some specific environment?
>
> BR, Jarkko
>

Not that I know of. This patch is not supposed to be a bugfix but an improvement of
the existing code by using the information about supported interrupts which is collected during
the capability query. After the query we know exactly which irqs are supported, so why not use
this knowledge when setting the irq mask?

Regards,
Lino


2022-05-17 06:11:49

by Lino Sanfilippo

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On 16.05.22 at 19:51, Jarkko Sakkinen wrote:
> On Wed, May 11, 2022 at 09:56:59PM +0200, Lino Sanfilippo wrote:
>> On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
>>> On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
>>>> From: Lino Sanfilippo <[email protected]>
>>>>
>>>> There is no need to check for the irq test completion at each data
>>>> transmission during the driver livetime. Instead do the check only once at
>>>> driver startup.
>>>>
>>>> Signed-off-by: Lino Sanfilippo <[email protected]>
>>>> ---
>>>> drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++----------------------
>>>> 1 file changed, 22 insertions(+), 46 deletions(-)
>>>>
>>>> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
>>>> index bdfde1cd71fe..4c65718feb7d 100644
>>>> --- a/drivers/char/tpm/tpm_tis_core.c
>>>> +++ b/drivers/char/tpm/tpm_tis_core.c
>>>> @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip *chip)
>>>> * tpm.c can skip polling for the data to be available as the interrupt is
>>>> * waited for here
>>>> */
>>>> -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>>>> +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
>>>> {
>>>> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>>>> int rc;
>>>> @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>>>> return rc;
>>>> }
>>>>
>>>> -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
>>>> -{
>>>> - int rc, irq;
>>>> - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>>>> -
>>>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
>>>> - test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>>>> - return tpm_tis_send_main(chip, buf, len);
>>>> -
>>>> - /* Verify receipt of the expected IRQ */
>>>> - irq = priv->irq;
>>>> - priv->irq = 0;
>>>> - chip->flags &= ~TPM_CHIP_FLAG_IRQ;
>>>> - rc = tpm_tis_send_main(chip, buf, len);
>>>> - priv->irq = irq;
>>>> - chip->flags |= TPM_CHIP_FLAG_IRQ;
>>>> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>>>> - tpm_msleep(1);
>>>> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>>>> - disable_interrupts(chip);
>>>> - set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
>>>> - return rc;
>>>> -}
>>>> -
>>>> struct tis_vendor_durations_override {
>>>> u32 did_vid;
>>>> struct tpm1_version version;
>>>> @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
>>>>
>>>> rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
>>>> &original_int_vec);
>>>> - if (rc < 0)
>>>> + if (rc < 0) {
>>>> + disable_interrupts(chip);
>>>> return rc;
>>>> + }
>>>>
>>>> rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
>>>> if (rc < 0)
>>>> - return rc;
>>>> + goto out_err;
>>>>
>>>> rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
>>>> if (rc < 0)
>>>> - return rc;
>>>> + goto out_err;
>>>>
>>>> /* Clear all existing */
>>>> rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
>>>> if (rc < 0)
>>>> - return rc;
>>>> + goto out_err;
>>>>
>>>> /* Turn on */
>>>> rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
>>>> intmask | TPM_GLOBAL_INT_ENABLE);
>>>> if (rc < 0)
>>>> - return rc;
>>>> + goto out_err;
>>>>
>>>> clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
>>>> - chip->flags |= TPM_CHIP_FLAG_IRQ;
>>>>
>>>> /* Generate an interrupt by having the core call through to
>>>> * tpm_tis_send
>>>> */
>>>> rc = tpm_tis_gen_interrupt(chip);
>>>> if (rc < 0)
>>>> - return rc;
>>>> + goto out_err;
>>>>
>>>> - /* tpm_tis_send will either confirm the interrupt is working or it
>>>> - * will call disable_irq which undoes all of the above.
>>>> - */
>>>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
>>>> - rc = tpm_tis_write8(priv, original_int_vec,
>>>> - TPM_INT_VECTOR(priv->locality));
>>>> - if (rc < 0)
>>>> - return rc;
>>>> + tpm_msleep(1);
>>>>
>>>> - return 1;
>>>> - }
>>>> + /* Verify receipt of the expected IRQ */
>>>> + if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
>>>> + goto out_err;
>>>> +
>>>> + chip->flags |= TPM_CHIP_FLAG_IRQ;
>>>>
>>>> return 0;
>>>> +
>>>> +out_err:
>
> Rename this as just 'err'.
>
>>>> + disable_interrupts(chip);
>>>> + tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv->locality));
>>>> +
>>>> + return rc;
>>>> }
>>>>
>>>> /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
>>>> @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
>>>> if (irq) {
>>>> tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
>>>> irq);
>>>> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
>>>> + if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
>>>> dev_err(&chip->dev, FW_BUG
>>>> "TPM interrupt not working, polling instead\n");
>>>> -
>>>> - disable_interrupts(chip);
>>>> - }
>>>> } else {
>>>> tpm_tis_probe_irq(chip, intmask);
>>>> }
>>>> --
>>>> 2.36.0
>>>>
>>>
>>> For me this looks just code shuffling.
>>>
>>> I don't disagree but changing working code without actual semantical
>>> reasons neither makes sense.
>>>
>>> BR, Jarkko
>>>
>>
>> Well the semantical reason for this change is that the check for irq test completion
>> only has to be done once for the driver livetime. There is no point in doing it
>> over and over again for each transmission.
>> So the code is not simply shuffled around, it is shifted to a place where it is only
>> executed once.
>>
>> This is not a bugfix but it is clearly an improvement/cleanup. As far as I understood
>> from your comments on the earlier versions of this patch set cleanups are also ok as
>> long as they are not intermixed with bugfixes.
>
> The patch does not do anything particulary useful IMHO. There's no
> stimulus to do this change.
>

Ok, I will drop this patch in the next version of this series then.

Regards,
Lino


2022-05-17 07:17:41

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On Wed, May 11, 2022 at 09:56:59PM +0200, Lino Sanfilippo wrote:
> On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
> > On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
> >> From: Lino Sanfilippo <[email protected]>
> >>
> >> There is no need to check for the irq test completion at each data
> >> transmission during the driver livetime. Instead do the check only once at
> >> driver startup.
> >>
> >> Signed-off-by: Lino Sanfilippo <[email protected]>
> >> ---
> >> drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++----------------------
> >> 1 file changed, 22 insertions(+), 46 deletions(-)
> >>
> >> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> >> index bdfde1cd71fe..4c65718feb7d 100644
> >> --- a/drivers/char/tpm/tpm_tis_core.c
> >> +++ b/drivers/char/tpm/tpm_tis_core.c
> >> @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip *chip)
> >> * tpm.c can skip polling for the data to be available as the interrupt is
> >> * waited for here
> >> */
> >> -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
> >> +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> >> {
> >> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> >> int rc;
> >> @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
> >> return rc;
> >> }
> >>
> >> -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> >> -{
> >> - int rc, irq;
> >> - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> >> -
> >> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
> >> - test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> >> - return tpm_tis_send_main(chip, buf, len);
> >> -
> >> - /* Verify receipt of the expected IRQ */
> >> - irq = priv->irq;
> >> - priv->irq = 0;
> >> - chip->flags &= ~TPM_CHIP_FLAG_IRQ;
> >> - rc = tpm_tis_send_main(chip, buf, len);
> >> - priv->irq = irq;
> >> - chip->flags |= TPM_CHIP_FLAG_IRQ;
> >> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> >> - tpm_msleep(1);
> >> - if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> >> - disable_interrupts(chip);
> >> - set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> >> - return rc;
> >> -}
> >> -
> >> struct tis_vendor_durations_override {
> >> u32 did_vid;
> >> struct tpm1_version version;
> >> @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
> >>
> >> rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
> >> &original_int_vec);
> >> - if (rc < 0)
> >> + if (rc < 0) {
> >> + disable_interrupts(chip);
> >> return rc;
> >> + }
> >>
> >> rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
> >> if (rc < 0)
> >> - return rc;
> >> + goto out_err;
> >>
> >> rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
> >> if (rc < 0)
> >> - return rc;
> >> + goto out_err;
> >>
> >> /* Clear all existing */
> >> rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
> >> if (rc < 0)
> >> - return rc;
> >> + goto out_err;
> >>
> >> /* Turn on */
> >> rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
> >> intmask | TPM_GLOBAL_INT_ENABLE);
> >> if (rc < 0)
> >> - return rc;
> >> + goto out_err;
> >>
> >> clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> >> - chip->flags |= TPM_CHIP_FLAG_IRQ;
> >>
> >> /* Generate an interrupt by having the core call through to
> >> * tpm_tis_send
> >> */
> >> rc = tpm_tis_gen_interrupt(chip);
> >> if (rc < 0)
> >> - return rc;
> >> + goto out_err;
> >>
> >> - /* tpm_tis_send will either confirm the interrupt is working or it
> >> - * will call disable_irq which undoes all of the above.
> >> - */
> >> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> >> - rc = tpm_tis_write8(priv, original_int_vec,
> >> - TPM_INT_VECTOR(priv->locality));
> >> - if (rc < 0)
> >> - return rc;
> >> + tpm_msleep(1);
> >>
> >> - return 1;
> >> - }
> >> + /* Verify receipt of the expected IRQ */
> >> + if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> >> + goto out_err;
> >> +
> >> + chip->flags |= TPM_CHIP_FLAG_IRQ;
> >>
> >> return 0;
> >> +
> >> +out_err:

Rename this as just 'err'.

> >> + disable_interrupts(chip);
> >> + tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv->locality));
> >> +
> >> + return rc;
> >> }
> >>
> >> /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
> >> @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
> >> if (irq) {
> >> tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
> >> irq);
> >> - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> >> + if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
> >> dev_err(&chip->dev, FW_BUG
> >> "TPM interrupt not working, polling instead\n");
> >> -
> >> - disable_interrupts(chip);
> >> - }
> >> } else {
> >> tpm_tis_probe_irq(chip, intmask);
> >> }
> >> --
> >> 2.36.0
> >>
> >
> > For me this looks just code shuffling.
> >
> > I don't disagree but changing working code without actual semantical
> > reasons neither makes sense.
> >
> > BR, Jarkko
> >
>
> Well the semantical reason for this change is that the check for irq test completion
> only has to be done once for the driver livetime. There is no point in doing it
> over and over again for each transmission.
> So the code is not simply shuffled around, it is shifted to a place where it is only
> executed once.
>
> This is not a bugfix but it is clearly an improvement/cleanup. As far as I understood
> from your comments on the earlier versions of this patch set cleanups are also ok as
> long as they are not intermixed with bugfixes.

The patch does not do anything particulary useful IMHO. There's no
stimulus to do this change.

> Regards,
> Lino

BR, Jarkko

2022-05-18 04:03:25

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On Tue, 2022-05-17 at 20:19 +0200, Michael Niewöhner wrote:
> Hi guys,
>
>
> On Mon, 2022-05-16 at 22:25 +0200, Lino Sanfilippo wrote:
> > On 16.05.22 at 19:51, Jarkko Sakkinen wrote:
> > > On Wed, May 11, 2022 at 09:56:59PM +0200, Lino Sanfilippo wrote:
> > > > On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
> > > > > On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
> > > > > > From: Lino Sanfilippo <[email protected]>
> > > > > >
> > > > > > There is no need to check for the irq test completion at each data
> > > > > > transmission during the driver livetime. Instead do the check only
> > > > > > once at
> > > > > > driver startup.
> > > > > >
> > > > > > Signed-off-by: Lino Sanfilippo <[email protected]>
> > > > > > ---
> > > > > >  drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++---------------------
> > > > > > -
> > > > > >  1 file changed, 22 insertions(+), 46 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/char/tpm/tpm_tis_core.c
> > > > > > b/drivers/char/tpm/tpm_tis_core.c
> > > > > > index bdfde1cd71fe..4c65718feb7d 100644
> > > > > > --- a/drivers/char/tpm/tpm_tis_core.c
> > > > > > +++ b/drivers/char/tpm/tpm_tis_core.c
> > > > > > @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip
> > > > > > *chip)
> > > > > >   * tpm.c can skip polling for the data to be available as the
> > > > > > interrupt is
> > > > > >   * waited for here
> > > > > >   */
> > > > > > -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf,
> > > > > > size_t len)
> > > > > > +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> > > > > >  {
> > > > > >         struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > > >         int rc;
> > > > > > @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip
> > > > > > *chip, const u8 *buf, size_t len)
> > > > > >         return rc;
> > > > > >  }
> > > > > >
> > > > > > -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> > > > > > -{
> > > > > > -       int rc, irq;
> > > > > > -       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > > > -
> > > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
> > > > > > -            test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > -               return tpm_tis_send_main(chip, buf, len);
> > > > > > -
> > > > > > -       /* Verify receipt of the expected IRQ */
> > > > > > -       irq = priv->irq;
> > > > > > -       priv->irq = 0;
> > > > > > -       chip->flags &= ~TPM_CHIP_FLAG_IRQ;
> > > > > > -       rc = tpm_tis_send_main(chip, buf, len);
> > > > > > -       priv->irq = irq;
> > > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > -               tpm_msleep(1);
> > > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > -               disable_interrupts(chip);
> > > > > > -       set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > > -       return rc;
> > > > > > -}
> > > > > > -
> > > > > >  struct tis_vendor_durations_override {
> > > > > >         u32 did_vid;
> > > > > >         struct tpm1_version version;
> > > > > > @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct
> > > > > > tpm_chip *chip, u32 intmask,
> > > > > >
> > > > > >         rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
> > > > > >                            &original_int_vec);
> > > > > > -       if (rc < 0)
> > > > > > +       if (rc < 0) {
> > > > > > +               disable_interrupts(chip);
> > > > > >                 return rc;
> > > > > > +       }
> > > > > >
> > > > > >         rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality),
> > > > > > irq);
> > > > > >         if (rc < 0)
> > > > > > -               return rc;
> > > > > > +               goto out_err;
> > > > > >
> > > > > >         rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality),
> > > > > > &int_status);
> > > > > >         if (rc < 0)
> > > > > > -               return rc;
> > > > > > +               goto out_err;
> > > > > >
> > > > > >         /* Clear all existing */
> > > > > >         rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality),
> > > > > > int_status);
> > > > > >         if (rc < 0)
> > > > > > -               return rc;
> > > > > > +               goto out_err;
> > > > > >
> > > > > >         /* Turn on */
> > > > > >         rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
> > > > > >                              intmask | TPM_GLOBAL_INT_ENABLE);
> > > > > >         if (rc < 0)
> > > > > > -               return rc;
> > > > > > +               goto out_err;
> > > > > >
> > > > > >         clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > >
> > > > > >         /* Generate an interrupt by having the core call through to
> > > > > >          * tpm_tis_send
> > > > > >          */
> > > > > >         rc = tpm_tis_gen_interrupt(chip);
> > > > > >         if (rc < 0)
> > > > > > -               return rc;
> > > > > > +               goto out_err;
> > > > > >
> > > > > > -       /* tpm_tis_send will either confirm the interrupt is working
> > > > > > or it
> > > > > > -        * will call disable_irq which undoes all of the above.
> > > > > > -        */
> > > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > > -               rc = tpm_tis_write8(priv, original_int_vec,
> > > > > > -                               TPM_INT_VECTOR(priv->locality));
> > > > > > -               if (rc < 0)
> > > > > > -                       return rc;
> > > > > > +       tpm_msleep(1);
> > > > > >
> > > > > > -               return 1;
> > > > > > -       }
> > > > > > +       /* Verify receipt of the expected IRQ */
> > > > > > +       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > +               goto out_err;
> > > > > > +
> > > > > > +       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > >
> > > > > >         return 0;
> > > > > > +
> > > > > > +out_err:
> > >
> > > Rename this as just 'err'.
> > >
> > > > > > +       disable_interrupts(chip);
> > > > > > +       tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv-
> > > > > > > locality));
> > > > > > +
> > > > > > +       return rc;
> > > > > >  }
> > > > > >
> > > > > >  /* Try to find the IRQ the TPM is using. This is for legacy x86
> > > > > > systems that
> > > > > > @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev,
> > > > > > struct tpm_tis_data *priv, int irq,
> > > > > >                 if (irq) {
> > > > > >                         tpm_tis_probe_irq_single(chip, intmask,
> > > > > > IRQF_SHARED,
> > > > > >                                                  irq);
> > > > > > -                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > > +                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
> > > > > >                                 dev_err(&chip->dev, FW_BUG
> > > > > >                                         "TPM interrupt not working,
> > > > > > polling instead\n");
> > > > > > -
> > > > > > -                               disable_interrupts(chip);
> > > > > > -                       }
> > > > > >                 } else {
> > > > > >                         tpm_tis_probe_irq(chip, intmask);
> > > > > >                 }
> > > > > > --
> > > > > > 2.36.0
> > > > > >
> > > > >
> > > > > For me this looks just code shuffling.
> > > > >
> > > > > I don't disagree but changing working code without actual semantical
> > > > > reasons neither makes sense.
> > > > >
> > > > > BR, Jarkko
> > > > >
> > > >
> > > > Well the semantical reason for this change is that the check for irq test
> > > > completion
> > > > only has to be done once for the driver livetime. There is no point in
> > > > doing it
> > > > over and over again for each transmission.
> > > > So the code is not simply shuffled around, it is shifted to a place where
> > > > it is only
> > > > executed once.
> > > >
> > > > This is not a bugfix but it is clearly an improvement/cleanup. As far as I
> > > > understood
> > > > from your comments on the earlier versions of this patch set cleanups are
> > > > also ok as
> > > > long as they are not intermixed with bugfixes.
> > >
> > > The patch does not do anything particulary useful IMHO. There's no
> > > stimulus to do this change.
> > >
>
> I don't agree. IMHO preventing useless actions (like checking the interrupt
> again and again) *is* useful and I think it's reason enough.

Show me the test data to back this up.

BR, Jarkko

2022-05-18 04:06:21

by Michael Niewöhner

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

Hi guys,


On Mon, 2022-05-16 at 22:25 +0200, Lino Sanfilippo wrote:
> On 16.05.22 at 19:51, Jarkko Sakkinen wrote:
> > On Wed, May 11, 2022 at 09:56:59PM +0200, Lino Sanfilippo wrote:
> > > On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
> > > > On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
> > > > > From: Lino Sanfilippo <[email protected]>
> > > > >
> > > > > There is no need to check for the irq test completion at each data
> > > > > transmission during the driver livetime. Instead do the check only
> > > > > once at
> > > > > driver startup.
> > > > >
> > > > > Signed-off-by: Lino Sanfilippo <[email protected]>
> > > > > ---
> > > > >  drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++---------------------
> > > > > -
> > > > >  1 file changed, 22 insertions(+), 46 deletions(-)
> > > > >
> > > > > diff --git a/drivers/char/tpm/tpm_tis_core.c
> > > > > b/drivers/char/tpm/tpm_tis_core.c
> > > > > index bdfde1cd71fe..4c65718feb7d 100644
> > > > > --- a/drivers/char/tpm/tpm_tis_core.c
> > > > > +++ b/drivers/char/tpm/tpm_tis_core.c
> > > > > @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip
> > > > > *chip)
> > > > >   * tpm.c can skip polling for the data to be available as the
> > > > > interrupt is
> > > > >   * waited for here
> > > > >   */
> > > > > -static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf,
> > > > > size_t len)
> > > > > +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> > > > >  {
> > > > >         struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > >         int rc;
> > > > > @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip
> > > > > *chip, const u8 *buf, size_t len)
> > > > >         return rc;
> > > > >  }
> > > > >
> > > > > -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> > > > > -{
> > > > > -       int rc, irq;
> > > > > -       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > > -
> > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
> > > > > -            test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > -               return tpm_tis_send_main(chip, buf, len);
> > > > > -
> > > > > -       /* Verify receipt of the expected IRQ */
> > > > > -       irq = priv->irq;
> > > > > -       priv->irq = 0;
> > > > > -       chip->flags &= ~TPM_CHIP_FLAG_IRQ;
> > > > > -       rc = tpm_tis_send_main(chip, buf, len);
> > > > > -       priv->irq = irq;
> > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > -               tpm_msleep(1);
> > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > -               disable_interrupts(chip);
> > > > > -       set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > -       return rc;
> > > > > -}
> > > > > -
> > > > >  struct tis_vendor_durations_override {
> > > > >         u32 did_vid;
> > > > >         struct tpm1_version version;
> > > > > @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct
> > > > > tpm_chip *chip, u32 intmask,
> > > > >
> > > > >         rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
> > > > >                            &original_int_vec);
> > > > > -       if (rc < 0)
> > > > > +       if (rc < 0) {
> > > > > +               disable_interrupts(chip);
> > > > >                 return rc;
> > > > > +       }
> > > > >
> > > > >         rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality),
> > > > > irq);
> > > > >         if (rc < 0)
> > > > > -               return rc;
> > > > > +               goto out_err;
> > > > >
> > > > >         rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality),
> > > > > &int_status);
> > > > >         if (rc < 0)
> > > > > -               return rc;
> > > > > +               goto out_err;
> > > > >
> > > > >         /* Clear all existing */
> > > > >         rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality),
> > > > > int_status);
> > > > >         if (rc < 0)
> > > > > -               return rc;
> > > > > +               goto out_err;
> > > > >
> > > > >         /* Turn on */
> > > > >         rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
> > > > >                              intmask | TPM_GLOBAL_INT_ENABLE);
> > > > >         if (rc < 0)
> > > > > -               return rc;
> > > > > +               goto out_err;
> > > > >
> > > > >         clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > >
> > > > >         /* Generate an interrupt by having the core call through to
> > > > >          * tpm_tis_send
> > > > >          */
> > > > >         rc = tpm_tis_gen_interrupt(chip);
> > > > >         if (rc < 0)
> > > > > -               return rc;
> > > > > +               goto out_err;
> > > > >
> > > > > -       /* tpm_tis_send will either confirm the interrupt is working
> > > > > or it
> > > > > -        * will call disable_irq which undoes all of the above.
> > > > > -        */
> > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > -               rc = tpm_tis_write8(priv, original_int_vec,
> > > > > -                               TPM_INT_VECTOR(priv->locality));
> > > > > -               if (rc < 0)
> > > > > -                       return rc;
> > > > > +       tpm_msleep(1);
> > > > >
> > > > > -               return 1;
> > > > > -       }
> > > > > +       /* Verify receipt of the expected IRQ */
> > > > > +       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > +               goto out_err;
> > > > > +
> > > > > +       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > >
> > > > >         return 0;
> > > > > +
> > > > > +out_err:
> >
> > Rename this as just 'err'.
> >
> > > > > +       disable_interrupts(chip);
> > > > > +       tpm_tis_write8(priv, original_int_vec, TPM_INT_VECTOR(priv-
> > > > > >locality));
> > > > > +
> > > > > +       return rc;
> > > > >  }
> > > > >
> > > > >  /* Try to find the IRQ the TPM is using. This is for legacy x86
> > > > > systems that
> > > > > @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev,
> > > > > struct tpm_tis_data *priv, int irq,
> > > > >                 if (irq) {
> > > > >                         tpm_tis_probe_irq_single(chip, intmask,
> > > > > IRQF_SHARED,
> > > > >                                                  irq);
> > > > > -                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > +                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
> > > > >                                 dev_err(&chip->dev, FW_BUG
> > > > >                                         "TPM interrupt not working,
> > > > > polling instead\n");
> > > > > -
> > > > > -                               disable_interrupts(chip);
> > > > > -                       }
> > > > >                 } else {
> > > > >                         tpm_tis_probe_irq(chip, intmask);
> > > > >                 }
> > > > > --
> > > > > 2.36.0
> > > > >
> > > >
> > > > For me this looks just code shuffling.
> > > >
> > > > I don't disagree but changing working code without actual semantical
> > > > reasons neither makes sense.
> > > >
> > > > BR, Jarkko
> > > >
> > >
> > > Well the semantical reason for this change is that the check for irq test
> > > completion
> > > only has to be done once for the driver livetime. There is no point in
> > > doing it
> > > over and over again for each transmission.
> > > So the code is not simply shuffled around, it is shifted to a place where
> > > it is only
> > > executed once.
> > >
> > > This is not a bugfix but it is clearly an improvement/cleanup. As far as I
> > > understood
> > > from your comments on the earlier versions of this patch set cleanups are
> > > also ok as
> > > long as they are not intermixed with bugfixes.
> >
> > The patch does not do anything particulary useful IMHO. There's no
> > stimulus to do this change.
> >

I don't agree. IMHO preventing useless actions (like checking the interrupt
again and again) *is* useful and I think it's reason enough.

>
> Ok, I will drop this patch in the next version of this series then.
>
> Regards,
> Lino
>

Michael

2022-05-18 16:13:01

by Michael Niewöhner

[permalink] [raw]
Subject: Re: [PATCH v4 5/6] tpm, tpm_tis: Move irq test from tpm_tis_send() to tpm_tis_probe_irq_single()

On Wed, 2022-05-18 at 04:26 +0300, Jarkko Sakkinen wrote:
> On Tue, 2022-05-17 at 20:19 +0200, Michael Niewöhner wrote:
> > Hi guys,
> >
> >
> > On Mon, 2022-05-16 at 22:25 +0200, Lino Sanfilippo wrote:
> > > On 16.05.22 at 19:51, Jarkko Sakkinen wrote:
> > > > On Wed, May 11, 2022 at 09:56:59PM +0200, Lino Sanfilippo wrote:
> > > > > On 11.05.22 at 17:09, Jarkko Sakkinen wrote:
> > > > > > On Mon, May 09, 2022 at 10:05:58AM +0200, Lino Sanfilippo wrote:
> > > > > > > From: Lino Sanfilippo <[email protected]>
> > > > > > >
> > > > > > > There is no need to check for the irq test completion at each data
> > > > > > > transmission during the driver livetime. Instead do the check only
> > > > > > > once at
> > > > > > > driver startup.
> > > > > > >
> > > > > > > Signed-off-by: Lino Sanfilippo <[email protected]>
> > > > > > > ---
> > > > > > >  drivers/char/tpm/tpm_tis_core.c | 68 +++++++++++-----------------
> > > > > > > ----
> > > > > > > -
> > > > > > >  1 file changed, 22 insertions(+), 46 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/char/tpm/tpm_tis_core.c
> > > > > > > b/drivers/char/tpm/tpm_tis_core.c
> > > > > > > index bdfde1cd71fe..4c65718feb7d 100644
> > > > > > > --- a/drivers/char/tpm/tpm_tis_core.c
> > > > > > > +++ b/drivers/char/tpm/tpm_tis_core.c
> > > > > > > @@ -432,7 +432,7 @@ static void disable_interrupts(struct tpm_chip
> > > > > > > *chip)
> > > > > > >   * tpm.c can skip polling for the data to be available as the
> > > > > > > interrupt is
> > > > > > >   * waited for here
> > > > > > >   */
> > > > > > > -static int tpm_tis_send_main(struct tpm_chip *chip, const u8
> > > > > > > *buf,
> > > > > > > size_t len)
> > > > > > > +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t
> > > > > > > len)
> > > > > > >  {
> > > > > > >         struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > > > >         int rc;
> > > > > > > @@ -465,30 +465,6 @@ static int tpm_tis_send_main(struct tpm_chip
> > > > > > > *chip, const u8 *buf, size_t len)
> > > > > > >         return rc;
> > > > > > >  }
> > > > > > >
> > > > > > > -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t
> > > > > > > len)
> > > > > > > -{
> > > > > > > -       int rc, irq;
> > > > > > > -       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> > > > > > > -
> > > > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
> > > > > > > -            test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > > -               return tpm_tis_send_main(chip, buf, len);
> > > > > > > -
> > > > > > > -       /* Verify receipt of the expected IRQ */
> > > > > > > -       irq = priv->irq;
> > > > > > > -       priv->irq = 0;
> > > > > > > -       chip->flags &= ~TPM_CHIP_FLAG_IRQ;
> > > > > > > -       rc = tpm_tis_send_main(chip, buf, len);
> > > > > > > -       priv->irq = irq;
> > > > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > > -               tpm_msleep(1);
> > > > > > > -       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > > -               disable_interrupts(chip);
> > > > > > > -       set_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > > > -       return rc;
> > > > > > > -}
> > > > > > > -
> > > > > > >  struct tis_vendor_durations_override {
> > > > > > >         u32 did_vid;
> > > > > > >         struct tpm1_version version;
> > > > > > > @@ -759,51 +735,54 @@ static int tpm_tis_probe_irq_single(struct
> > > > > > > tpm_chip *chip, u32 intmask,
> > > > > > >
> > > > > > >         rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
> > > > > > >                            &original_int_vec);
> > > > > > > -       if (rc < 0)
> > > > > > > +       if (rc < 0) {
> > > > > > > +               disable_interrupts(chip);
> > > > > > >                 return rc;
> > > > > > > +       }
> > > > > > >
> > > > > > >         rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality),
> > > > > > > irq);
> > > > > > >         if (rc < 0)
> > > > > > > -               return rc;
> > > > > > > +               goto out_err;
> > > > > > >
> > > > > > >         rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality),
> > > > > > > &int_status);
> > > > > > >         if (rc < 0)
> > > > > > > -               return rc;
> > > > > > > +               goto out_err;
> > > > > > >
> > > > > > >         /* Clear all existing */
> > > > > > >         rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality),
> > > > > > > int_status);
> > > > > > >         if (rc < 0)
> > > > > > > -               return rc;
> > > > > > > +               goto out_err;
> > > > > > >
> > > > > > >         /* Turn on */
> > > > > > >         rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
> > > > > > >                              intmask | TPM_GLOBAL_INT_ENABLE);
> > > > > > >         if (rc < 0)
> > > > > > > -               return rc;
> > > > > > > +               goto out_err;
> > > > > > >
> > > > > > >         clear_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags);
> > > > > > > -       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > > >
> > > > > > >         /* Generate an interrupt by having the core call through
> > > > > > > to
> > > > > > >          * tpm_tis_send
> > > > > > >          */
> > > > > > >         rc = tpm_tis_gen_interrupt(chip);
> > > > > > >         if (rc < 0)
> > > > > > > -               return rc;
> > > > > > > +               goto out_err;
> > > > > > >
> > > > > > > -       /* tpm_tis_send will either confirm the interrupt is
> > > > > > > working
> > > > > > > or it
> > > > > > > -        * will call disable_irq which undoes all of the above.
> > > > > > > -        */
> > > > > > > -       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > > > -               rc = tpm_tis_write8(priv, original_int_vec,
> > > > > > > -                               TPM_INT_VECTOR(priv->locality));
> > > > > > > -               if (rc < 0)
> > > > > > > -                       return rc;
> > > > > > > +       tpm_msleep(1);
> > > > > > >
> > > > > > > -               return 1;
> > > > > > > -       }
> > > > > > > +       /* Verify receipt of the expected IRQ */
> > > > > > > +       if (!test_bit(TPM_TIS_IRQTEST_OK, &priv->irqtest_flags))
> > > > > > > +               goto out_err;
> > > > > > > +
> > > > > > > +       chip->flags |= TPM_CHIP_FLAG_IRQ;
> > > > > > >
> > > > > > >         return 0;
> > > > > > > +
> > > > > > > +out_err:
> > > >
> > > > Rename this as just 'err'.
> > > >
> > > > > > > +       disable_interrupts(chip);
> > > > > > > +       tpm_tis_write8(priv, original_int_vec,
> > > > > > > TPM_INT_VECTOR(priv-
> > > > > > > > locality));
> > > > > > > +
> > > > > > > +       return rc;
> > > > > > >  }
> > > > > > >
> > > > > > >  /* Try to find the IRQ the TPM is using. This is for legacy x86
> > > > > > > systems that
> > > > > > > @@ -1075,12 +1054,9 @@ int tpm_tis_core_init(struct device *dev,
> > > > > > > struct tpm_tis_data *priv, int irq,
> > > > > > >                 if (irq) {
> > > > > > >                         tpm_tis_probe_irq_single(chip, intmask,
> > > > > > > IRQF_SHARED,
> > > > > > >                                                  irq);
> > > > > > > -                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
> > > > > > > +                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
> > > > > > >                                 dev_err(&chip->dev, FW_BUG
> > > > > > >                                         "TPM interrupt not
> > > > > > > working,
> > > > > > > polling instead\n");
> > > > > > > -
> > > > > > > -                               disable_interrupts(chip);
> > > > > > > -                       }
> > > > > > >                 } else {
> > > > > > >                         tpm_tis_probe_irq(chip, intmask);
> > > > > > >                 }
> > > > > > > --
> > > > > > > 2.36.0
> > > > > > >
> > > > > >
> > > > > > For me this looks just code shuffling.
> > > > > >
> > > > > > I don't disagree but changing working code without actual semantical
> > > > > > reasons neither makes sense.
> > > > > >
> > > > > > BR, Jarkko
> > > > > >
> > > > >
> > > > > Well the semantical reason for this change is that the check for irq
> > > > > test
> > > > > completion
> > > > > only has to be done once for the driver livetime. There is no point in
> > > > > doing it
> > > > > over and over again for each transmission.
> > > > > So the code is not simply shuffled around, it is shifted to a place
> > > > > where
> > > > > it is only
> > > > > executed once.
> > > > >
> > > > > This is not a bugfix but it is clearly an improvement/cleanup. As far
> > > > > as I
> > > > > understood
> > > > > from your comments on the earlier versions of this patch set cleanups
> > > > > are
> > > > > also ok as
> > > > > long as they are not intermixed with bugfixes.
> > > >
> > > > The patch does not do anything particulary useful IMHO. There's no
> > > > stimulus to do this change.
> > > >
> >
> > I don't agree. IMHO preventing useless actions (like checking the interrupt
> > again and again) *is* useful and I think it's reason enough.
>
> Show me the test data to back this up.

Why do you need test data as an argument for not doing useless actions? o.O

>
> BR, Jarkko