2424#include <linux/wait.h>
2525#include <linux/acpi.h>
2626#include <linux/freezer.h>
27+ #include <linux/dmi.h>
2728#include "tpm.h"
2829#include "tpm_tis_core.h"
2930
31+ #define TPM_TIS_MAX_UNHANDLED_IRQS 1000
32+
3033static void tpm_tis_clkrun_enable (struct tpm_chip * chip , bool value );
3134
3235static bool wait_for_tpm_stat_cond (struct tpm_chip * chip , u8 mask ,
@@ -468,25 +471,29 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
468471 return rc ;
469472}
470473
471- static void disable_interrupts (struct tpm_chip * chip )
474+ static void __tpm_tis_disable_interrupts (struct tpm_chip * chip )
475+ {
476+ struct tpm_tis_data * priv = dev_get_drvdata (& chip -> dev );
477+ u32 int_mask = 0 ;
478+
479+ tpm_tis_read32 (priv , TPM_INT_ENABLE (priv -> locality ), & int_mask );
480+ int_mask &= ~TPM_GLOBAL_INT_ENABLE ;
481+ tpm_tis_write32 (priv , TPM_INT_ENABLE (priv -> locality ), int_mask );
482+
483+ chip -> flags &= ~TPM_CHIP_FLAG_IRQ ;
484+ }
485+
486+ static void tpm_tis_disable_interrupts (struct tpm_chip * chip )
472487{
473488 struct tpm_tis_data * priv = dev_get_drvdata (& chip -> dev );
474- u32 intmask ;
475- int rc ;
476489
477490 if (priv -> irq == 0 )
478491 return ;
479492
480- rc = tpm_tis_read32 (priv , TPM_INT_ENABLE (priv -> locality ), & intmask );
481- if (rc < 0 )
482- intmask = 0 ;
483-
484- intmask &= ~TPM_GLOBAL_INT_ENABLE ;
485- rc = tpm_tis_write32 (priv , TPM_INT_ENABLE (priv -> locality ), intmask );
493+ __tpm_tis_disable_interrupts (chip );
486494
487495 devm_free_irq (chip -> dev .parent , priv -> irq , chip );
488496 priv -> irq = 0 ;
489- chip -> flags &= ~TPM_CHIP_FLAG_IRQ ;
490497}
491498
492499/*
@@ -552,7 +559,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
552559 if (!test_bit (TPM_TIS_IRQ_TESTED , & priv -> flags ))
553560 tpm_msleep (1 );
554561 if (!test_bit (TPM_TIS_IRQ_TESTED , & priv -> flags ))
555- disable_interrupts (chip );
562+ tpm_tis_disable_interrupts (chip );
556563 set_bit (TPM_TIS_IRQ_TESTED , & priv -> flags );
557564 return rc ;
558565}
@@ -752,6 +759,57 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
752759 return status == TPM_STS_COMMAND_READY ;
753760}
754761
762+ static irqreturn_t tpm_tis_revert_interrupts (struct tpm_chip * chip )
763+ {
764+ struct tpm_tis_data * priv = dev_get_drvdata (& chip -> dev );
765+ const char * product ;
766+ const char * vendor ;
767+
768+ dev_warn (& chip -> dev , FW_BUG
769+ "TPM interrupt storm detected, polling instead\n" );
770+
771+ vendor = dmi_get_system_info (DMI_SYS_VENDOR );
772+ product = dmi_get_system_info (DMI_PRODUCT_VERSION );
773+
774+ if (vendor && product ) {
775+ dev_info (& chip -> dev ,
776+ "Consider adding the following entry to tpm_tis_dmi_table:\n" );
777+ dev_info (& chip -> dev , "\tDMI_SYS_VENDOR: %s\n" , vendor );
778+ dev_info (& chip -> dev , "\tDMI_PRODUCT_VERSION: %s\n" , product );
779+ }
780+
781+ if (tpm_tis_request_locality (chip , 0 ) != 0 )
782+ return IRQ_NONE ;
783+
784+ __tpm_tis_disable_interrupts (chip );
785+ tpm_tis_relinquish_locality (chip , 0 );
786+
787+ schedule_work (& priv -> free_irq_work );
788+
789+ return IRQ_HANDLED ;
790+ }
791+
792+ static irqreturn_t tpm_tis_update_unhandled_irqs (struct tpm_chip * chip )
793+ {
794+ struct tpm_tis_data * priv = dev_get_drvdata (& chip -> dev );
795+ irqreturn_t irqret = IRQ_HANDLED ;
796+
797+ if (!(chip -> flags & TPM_CHIP_FLAG_IRQ ))
798+ return IRQ_HANDLED ;
799+
800+ if (time_after (jiffies , priv -> last_unhandled_irq + HZ /10 ))
801+ priv -> unhandled_irqs = 1 ;
802+ else
803+ priv -> unhandled_irqs ++ ;
804+
805+ priv -> last_unhandled_irq = jiffies ;
806+
807+ if (priv -> unhandled_irqs > TPM_TIS_MAX_UNHANDLED_IRQS )
808+ irqret = tpm_tis_revert_interrupts (chip );
809+
810+ return irqret ;
811+ }
812+
755813static irqreturn_t tis_int_handler (int dummy , void * dev_id )
756814{
757815 struct tpm_chip * chip = dev_id ;
@@ -761,10 +819,10 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
761819
762820 rc = tpm_tis_read32 (priv , TPM_INT_STATUS (priv -> locality ), & interrupt );
763821 if (rc < 0 )
764- return IRQ_NONE ;
822+ goto err ;
765823
766824 if (interrupt == 0 )
767- return IRQ_NONE ;
825+ goto err ;
768826
769827 set_bit (TPM_TIS_IRQ_TESTED , & priv -> flags );
770828 if (interrupt & TPM_INTF_DATA_AVAIL_INT )
@@ -780,10 +838,13 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
780838 rc = tpm_tis_write32 (priv , TPM_INT_STATUS (priv -> locality ), interrupt );
781839 tpm_tis_relinquish_locality (chip , 0 );
782840 if (rc < 0 )
783- return IRQ_NONE ;
841+ goto err ;
784842
785843 tpm_tis_read32 (priv , TPM_INT_STATUS (priv -> locality ), & interrupt );
786844 return IRQ_HANDLED ;
845+
846+ err :
847+ return tpm_tis_update_unhandled_irqs (chip );
787848}
788849
789850static void tpm_tis_gen_interrupt (struct tpm_chip * chip )
@@ -804,6 +865,15 @@ static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
804865 chip -> flags &= ~TPM_CHIP_FLAG_IRQ ;
805866}
806867
868+ static void tpm_tis_free_irq_func (struct work_struct * work )
869+ {
870+ struct tpm_tis_data * priv = container_of (work , typeof (* priv ), free_irq_work );
871+ struct tpm_chip * chip = priv -> chip ;
872+
873+ devm_free_irq (chip -> dev .parent , priv -> irq , chip );
874+ priv -> irq = 0 ;
875+ }
876+
807877/* Register the IRQ and issue a command that will cause an interrupt. If an
808878 * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
809879 * everything and leave in polling mode. Returns 0 on success.
@@ -816,6 +886,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
816886 int rc ;
817887 u32 int_status ;
818888
889+ INIT_WORK (& priv -> free_irq_work , tpm_tis_free_irq_func );
819890
820891 rc = devm_request_threaded_irq (chip -> dev .parent , irq , NULL ,
821892 tis_int_handler , IRQF_ONESHOT | flags ,
@@ -918,6 +989,7 @@ void tpm_tis_remove(struct tpm_chip *chip)
918989 interrupt = 0 ;
919990
920991 tpm_tis_write32 (priv , reg , ~TPM_GLOBAL_INT_ENABLE & interrupt );
992+ flush_work (& priv -> free_irq_work );
921993
922994 tpm_tis_clkrun_enable (chip , false);
923995
@@ -1021,6 +1093,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
10211093 chip -> timeout_b = msecs_to_jiffies (TIS_TIMEOUT_B_MAX );
10221094 chip -> timeout_c = msecs_to_jiffies (TIS_TIMEOUT_C_MAX );
10231095 chip -> timeout_d = msecs_to_jiffies (TIS_TIMEOUT_D_MAX );
1096+ priv -> chip = chip ;
10241097 priv -> timeout_min = TPM_TIMEOUT_USECS_MIN ;
10251098 priv -> timeout_max = TPM_TIMEOUT_USECS_MAX ;
10261099 priv -> phy_ops = phy_ops ;
@@ -1179,7 +1252,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
11791252 rc = tpm_tis_request_locality (chip , 0 );
11801253 if (rc < 0 )
11811254 goto out_err ;
1182- disable_interrupts (chip );
1255+ tpm_tis_disable_interrupts (chip );
11831256 tpm_tis_relinquish_locality (chip , 0 );
11841257 }
11851258 }
0 commit comments