Messages in this thread Patch in this message | | | From | Stefan Berger <> | Subject | Enabling interrupts in QEMU TPM TIS | Date | Thu, 25 Jun 2020 10:56:43 -0400 |
| |
Hello!
I want to enable IRQs now in QEMU's TPM TIS device model and I need to work with the following patch to Linux TIS. I am wondering whether the changes there look reasonable to you? Windows works with the QEMU modifications as-is, so maybe it's a bug in the TIS code (which I had not run into before).
The point of the loop I need to introduce in the interrupt handler is that while the interrupt handler is running another interrupt may occur/be posted that then does NOT cause the interrupt handler to be invoked again but causes a stall, unless the loop is there.
The 'o' in the dmesg log indicates the original IRQ for which the handler was invoked. The interrupt values have the following meaning.
0x2: STS valid
0x4: locality changed
0x80: command ready
So the first 'looping entry' [in log below] indicates that a locality change interrupt occurred while the interrupt handler was running due to STS_valid + command ready. This sounds reasonable considering that we are frequently acquiring and releasing the locality. The loop then deals with the locality change interrupt and the interrupts then settle.
[ 210.365129] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x1, rev-id 1) [ 210.367124] looping: 0x4 (o: 0x82) [ 212.375045] looping: 0x80 (o: 0x2) [ 212.389218] looping: 0x4 (o: 0x82) [ 212.404161] looping: 0x80 (o: 0x2) [ 212.526427] looping: 0x4 (o: 0x82) [ 212.595488] looping: 0x4 (o: 0x82) [ 212.614357] looping: 0x80 (o: 0x2)
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 65ab1b027949..f77544563fb1 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -704,7 +704,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) { struct tpm_chip *chip = dev_id; struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - u32 interrupt; + u32 interrupt, o; int i, rc;
rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); @@ -715,6 +715,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) return IRQ_NONE;
priv->irq_tested = true; +again: if (interrupt & TPM_INTF_DATA_AVAIL_INT) wake_up_interruptible(&priv->read_queue); if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) @@ -731,7 +732,12 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) if (rc < 0) return IRQ_NONE;
+ o = interrupt; tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); + if (interrupt != 0) { + printk("looping: 0x%x (o: 0x%x)\n", interrupt, o); + goto again; + } return IRQ_HANDLED; }
@@ -1062,6 +1068,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, goto out_err; }
+ tpm_chip_start(chip); + chip->flags |= TPM_CHIP_FLAG_IRQ; if (irq) { tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, irq); @@ -1074,6 +1082,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, } else { tpm_tis_probe_irq(chip, intmask); } + tpm_chip_stop(chip); }
rc = tpm_chip_register(chip); -- 2.26.2 Stefan
| |