Skip to content

Commit e3837e7

Browse files
jgunthorpeJarkko Sakkinen
authored andcommitted
tpm_tis: Refactor the interrupt setup
Now that the probe and run cases are merged together we can use a much simpler setup flow where probe and normal setup are done with exactly the same code. Since the new flow always calls tpm_gen_interrupt to confirm the IRQ there is also no longer any need to call tpm_get_timeouts twice. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Martin Wilck <Martin.Wilck@ts.fujitsu.com> Tested-by: Scot Doyle <lkml14@scotdoyle.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Acked-by: Peter Huewe <peterhuewe@gmx.de>
1 parent 7ab4032 commit e3837e7

File tree

1 file changed

+84
-100
lines changed

1 file changed

+84
-100
lines changed

drivers/char/tpm/tpm_tis.c

Lines changed: 84 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ static struct tpm_info tis_default_info = {
9999
#define TPM_RID(l) (0x0F04 | ((l) << 12))
100100

101101
struct priv_data {
102-
bool irq_probing;
103102
bool irq_tested;
104103
};
105104

@@ -462,12 +461,8 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
462461
chip->vendor.irq = irq;
463462
if (!priv->irq_tested)
464463
msleep(1);
465-
if (!priv->irq_tested) {
464+
if (!priv->irq_tested)
466465
disable_interrupts(chip);
467-
if (!priv->irq_probing)
468-
dev_err(chip->pdev, FW_BUG
469-
"TPM interrupt not working, polling instead\n");
470-
}
471466
priv->irq_tested = true;
472467
return rc;
473468
}
@@ -604,6 +599,80 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
604599
return IRQ_HANDLED;
605600
}
606601

602+
/* Register the IRQ and issue a command that will cause an interrupt. If an
603+
* irq is seen then leave the chip setup for IRQ operation, otherwise reverse
604+
* everything and leave in polling mode. Returns 0 on success.
605+
*/
606+
static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, int irq)
607+
{
608+
struct priv_data *priv = chip->vendor.priv;
609+
u8 original_int_vec;
610+
611+
if (devm_request_irq(chip->pdev, irq, tis_int_handler, IRQF_SHARED,
612+
chip->devname, chip) != 0) {
613+
dev_info(chip->pdev, "Unable to request irq: %d for probe\n",
614+
irq);
615+
return -1;
616+
}
617+
chip->vendor.irq = irq;
618+
619+
original_int_vec = ioread8(chip->vendor.iobase +
620+
TPM_INT_VECTOR(chip->vendor.locality));
621+
iowrite8(irq,
622+
chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality));
623+
624+
/* Clear all existing */
625+
iowrite32(ioread32(chip->vendor.iobase +
626+
TPM_INT_STATUS(chip->vendor.locality)),
627+
chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality));
628+
629+
/* Turn on */
630+
iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
631+
chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
632+
633+
priv->irq_tested = false;
634+
635+
/* Generate an interrupt by having the core call through to
636+
* tpm_tis_send
637+
*/
638+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
639+
tpm2_gen_interrupt(chip);
640+
else
641+
tpm_gen_interrupt(chip);
642+
643+
/* tpm_tis_send will either confirm the interrupt is working or it
644+
* will call disable_irq which undoes all of the above.
645+
*/
646+
if (!chip->vendor.irq) {
647+
iowrite8(original_int_vec,
648+
chip->vendor.iobase +
649+
TPM_INT_VECTOR(chip->vendor.locality));
650+
return 1;
651+
}
652+
653+
return 0;
654+
}
655+
656+
/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
657+
* do not have ACPI/etc. We typically expect the interrupt to be declared if
658+
* present.
659+
*/
660+
static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
661+
{
662+
u8 original_int_vec;
663+
int i;
664+
665+
original_int_vec = ioread8(chip->vendor.iobase +
666+
TPM_INT_VECTOR(chip->vendor.locality));
667+
668+
if (!original_int_vec) {
669+
for (i = 3; i <= 15; i++)
670+
if (!tpm_tis_probe_irq_single(chip, intmask, i))
671+
return;
672+
} else if (!tpm_tis_probe_irq_single(chip, intmask, original_int_vec))
673+
return;
674+
}
675+
607676
static bool interrupts = true;
608677
module_param(interrupts, bool, 0444);
609678
MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -626,8 +695,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
626695
acpi_handle acpi_dev_handle)
627696
{
628697
u32 vendor, intfcaps, intmask;
629-
int rc, i, irq_s, irq_e, probe;
630-
int irq_r = -1;
698+
int rc, probe;
631699
struct tpm_chip *chip;
632700
struct priv_data *priv;
633701

@@ -735,98 +803,14 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
735803
/* INTERRUPT Setup */
736804
init_waitqueue_head(&chip->vendor.read_queue);
737805
init_waitqueue_head(&chip->vendor.int_queue);
738-
739-
if (interrupts)
740-
chip->vendor.irq = tpm_info->irq;
741-
if (interrupts && !chip->vendor.irq) {
742-
irq_s =
743-
ioread8(chip->vendor.iobase +
744-
TPM_INT_VECTOR(chip->vendor.locality));
745-
irq_r = irq_s;
746-
if (irq_s) {
747-
irq_e = irq_s;
748-
} else {
749-
irq_s = 3;
750-
irq_e = 15;
751-
}
752-
753-
for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
754-
iowrite8(i, chip->vendor.iobase +
755-
TPM_INT_VECTOR(chip->vendor.locality));
756-
if (devm_request_irq
757-
(dev, i, tis_int_handler, IRQF_SHARED,
758-
chip->devname, chip) != 0) {
759-
dev_info(chip->pdev,
760-
"Unable to request irq: %d for probe\n",
761-
i);
762-
continue;
763-
}
764-
chip->vendor.irq = i;
765-
766-
/* Clear all existing */
767-
iowrite32(ioread32
768-
(chip->vendor.iobase +
769-
TPM_INT_STATUS(chip->vendor.locality)),
770-
chip->vendor.iobase +
771-
TPM_INT_STATUS(chip->vendor.locality));
772-
773-
/* Turn on */
774-
iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
775-
chip->vendor.iobase +
776-
TPM_INT_ENABLE(chip->vendor.locality));
777-
778-
priv->irq_tested = false;
779-
priv->irq_probing = true;
780-
781-
/* Generate Interrupts */
782-
if (chip->flags & TPM_CHIP_FLAG_TPM2)
783-
tpm2_gen_interrupt(chip);
784-
else
785-
tpm_gen_interrupt(chip);
786-
787-
priv->irq_probing = false;
788-
789-
/* tpm_tis_send will either confirm the interrupt is
790-
* working or it will call disable_irq which undoes
791-
* all of the above.
792-
*/
793-
if (chip->vendor.irq)
794-
break;
795-
}
796-
if (!chip->vendor.irq)
797-
iowrite8(irq_r, chip->vendor.iobase +
798-
TPM_INT_VECTOR(chip->vendor.locality));
799-
}
800-
if (chip->vendor.irq && !priv->irq_tested) {
801-
iowrite8(chip->vendor.irq,
802-
chip->vendor.iobase +
803-
TPM_INT_VECTOR(chip->vendor.locality));
804-
if (devm_request_irq
805-
(dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED,
806-
chip->devname, chip) != 0) {
807-
dev_info(chip->pdev,
808-
"Unable to request irq: %d for use\n",
809-
chip->vendor.irq);
810-
chip->vendor.irq = 0;
811-
} else {
812-
/* Clear all existing */
813-
iowrite32(ioread32
814-
(chip->vendor.iobase +
815-
TPM_INT_STATUS(chip->vendor.locality)),
816-
chip->vendor.iobase +
817-
TPM_INT_STATUS(chip->vendor.locality));
818-
819-
/* Turn on */
820-
iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
821-
chip->vendor.iobase +
822-
TPM_INT_ENABLE(chip->vendor.locality));
823-
}
824-
}
825-
826-
if (tpm_get_timeouts(chip)) {
827-
dev_err(dev, "Could not get TPM timeouts and durations\n");
828-
rc = -ENODEV;
829-
goto out_err;
806+
if (interrupts) {
807+
if (tpm_info->irq) {
808+
tpm_tis_probe_irq_single(chip, intmask, tpm_info->irq);
809+
if (!chip->vendor.irq)
810+
dev_err(chip->pdev, FW_BUG
811+
"TPM interrupt not working, polling instead\n");
812+
} else
813+
tpm_tis_probe_irq(chip, intmask);
830814
}
831815

832816
if (chip->flags & TPM_CHIP_FLAG_TPM2) {

0 commit comments

Comments
 (0)