Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp2054124pxu; Tue, 24 Nov 2020 16:01:44 -0800 (PST) X-Google-Smtp-Source: ABdhPJywekuf4UaaUNIlDMHpq7eJPZVMl7biwli5qXxYRSQoWknZt85pisT/qREw6Erf1hf6bfMd X-Received: by 2002:a17:906:1fc9:: with SMTP id e9mr826487ejt.319.1606262503784; Tue, 24 Nov 2020 16:01:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606262503; cv=none; d=google.com; s=arc-20160816; b=mJ7XcTaD8p55LogxBODskoj14U1bO1TMm3hDsu8mt/qhPpMUp9pYGyEfewlH24bI5f mythupEPCMPiZui6Rj776glBvHMoZ6A7ClKaXFgDs0kSzY4a/zyc48kM/76QcbB4H1Si Q00bFKQAmtb0uhlRTTFMnC91JYe/rX6PvRkZ8i2kWUpwFKgLEVmhEY7NseeaBpBzW9y8 AvGlbj4kEvxtDfhxLMt8n/Ro4UwHfy3raIj880ij8J962ARtwFGEo3qDzo/0s3zdk4ln QPkPO/nw38pJ84q0TWoQkh7Tks/Yu3NSxvipPmKtOgFI/hHwZJnNfNv7I+INKtpjTOEn mpyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:content-language :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject:dkim-signature; bh=/01D88jyTMdO8ru48uxIMGQv6yUqBjrpOvNUgxnu8cM=; b=IKBgFm8843UTYGpf9cWJm4zlNoB2dNmUD+7ohN7Ybzl59IsEup2KBKl2lP4ENKNKMP gLU6rIsucHN4aBcf3ghl9gFLQfyxAF4DqMzsJIayz1RXaJpCIU3JpiMt7n6sn9MA1hMw BJvosbk9PRg65iuAEBwrgTM8zDB5gVA9UO2bY/il2qgYSHKfqnaca1ALutYoPl49DVXb URCZOYWd5XNSRUwMtY/zguCh533FTL5v6/FXK0NygrcOh0qQ50mYy0LLYU7aPQjRs//n yaoya8uSECB0DO2CaNrteG2osoFLZewown1ZXuFFG6omlgaMs2J3dmswyzfHBF7YOtXW EcIQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=g0OTq0ul; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ho13si293416ejc.11.2020.11.24.16.01.20; Tue, 24 Nov 2020 16:01:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=g0OTq0ul; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732980AbgKXVpK (ORCPT + 99 others); Tue, 24 Nov 2020 16:45:10 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:36551 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729173AbgKXVpK (ORCPT ); Tue, 24 Nov 2020 16:45:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1606254307; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/01D88jyTMdO8ru48uxIMGQv6yUqBjrpOvNUgxnu8cM=; b=g0OTq0uli4XZqS82Ml07DxjQ1Iz5GHI8t284/FvKAXJnVoWKPWww0UU5nNY7oQd4IHuxJy Rr+GONgBH4DIUOID2pckEiHMTh3Cay/sRuZDXuTSC2MADVl8aydVPHLoK7L3Nnezx596BS 3PSZK0i5ZNsoZwVPKxGtBHEBLJ5XYWI= Received: from mail-ed1-f70.google.com (mail-ed1-f70.google.com [209.85.208.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-113-C4SejxuCNW6EmUEgWg7mxg-1; Tue, 24 Nov 2020 16:45:03 -0500 X-MC-Unique: C4SejxuCNW6EmUEgWg7mxg-1 Received: by mail-ed1-f70.google.com with SMTP id x15so170632edr.10 for ; Tue, 24 Nov 2020 13:45:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=/01D88jyTMdO8ru48uxIMGQv6yUqBjrpOvNUgxnu8cM=; b=ac82gW/r6DEGS1nH+eEqcOz2ygpvOL5Esf4y/qF3oX6ZgecGTe/AAmQztkgtjjzkrn iIzbIc81mHD5DzJXG3W/uYJKgBfm7+sJjbgVcU+S304VFKSGqUvV7U3zRnk+fupFe6RS 0vH/WTXZOHYgfwSfdCDNjpcAWaSO+VCFZ4TR7tKgr57AQigCyzZIBcQElfbJzB1QOFuE yQy4cWPKMDFypb9vmfqsE9DI0D5eVTborLsbjy55VWlHPRPEMfNsqPT9ElYIJRSpgnsU R+ZAkmVhDxKzgAo1MeTjagCklIhJm+pJgKTejNP25UJj+dv/SSbES5IBFSRtOZl04UY6 oBQA== X-Gm-Message-State: AOAM533jVE116fkysjqxNTKiDVCx4TXZ36jJ7HafG85AF1gfQGbEZWLX H5jgvIpxuEj3xWiYAcr2Udetx6XR7zAfbfa6KaEf41LUVQ5eToVEzdvKzRtdHB2fBa3hyQA7DTR 1HHIy2pV3v96bhcSP3WFDl3He X-Received: by 2002:a17:906:86ca:: with SMTP id j10mr385030ejy.507.1606254302670; Tue, 24 Nov 2020 13:45:02 -0800 (PST) X-Received: by 2002:a17:906:86ca:: with SMTP id j10mr385018ejy.507.1606254302453; Tue, 24 Nov 2020 13:45:02 -0800 (PST) Received: from x1.localdomain (2001-1c00-0c0c-fe00-6c10-fbf3-14c4-884c.cable.dynamic.v6.ziggo.nl. [2001:1c00:c0c:fe00:6c10:fbf3:14c4:884c]) by smtp.gmail.com with ESMTPSA id y24sm88296edt.15.2020.11.24.13.45.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 24 Nov 2020 13:45:01 -0800 (PST) Subject: Re: [PATCH] tpm_tis: Disable interrupts on ThinkPad T490s To: Jerry Snitselaar , Jarkko Sakkinen Cc: Matthew Garrett , linux-integrity , Linux Kernel Mailing List , Peter Huewe , Jason Gunthorpe , James Bottomley References: <20201015214430.17937-1-jsnitsel@redhat.com> <87d009c0pn.fsf@redhat.com> <20201124032623.GA40007@kernel.org> <871rgiod53.fsf@redhat.com> From: Hans de Goede Message-ID: <7779bfbc-f96b-dd81-313f-36f451ce9c32@redhat.com> Date: Tue, 24 Nov 2020 22:45:01 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: <871rgiod53.fsf@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On 11/24/20 6:52 PM, Jerry Snitselaar wrote: > > Jarkko Sakkinen @ 2020-11-23 20:26 MST: > >> On Wed, Nov 18, 2020 at 11:36:20PM -0700, Jerry Snitselaar wrote: >>> >>> Matthew Garrett @ 2020-10-15 15:39 MST: >>> >>>> On Thu, Oct 15, 2020 at 2:44 PM Jerry Snitselaar wrote: >>>>> >>>>> There is a misconfiguration in the bios of the gpio pin used for the >>>>> interrupt in the T490s. When interrupts are enabled in the tpm_tis >>>>> driver code this results in an interrupt storm. This was initially >>>>> reported when we attempted to enable the interrupt code in the tpm_tis >>>>> driver, which previously wasn't setting a flag to enable it. Due to >>>>> the reports of the interrupt storm that code was reverted and we went back >>>>> to polling instead of using interrupts. Now that we know the T490s problem >>>>> is a firmware issue, add code to check if the system is a T490s and >>>>> disable interrupts if that is the case. This will allow us to enable >>>>> interrupts for everyone else. If the user has a fixed bios they can >>>>> force the enabling of interrupts with tpm_tis.interrupts=1 on the >>>>> kernel command line. >>>> >>>> I think an implication of this is that systems haven't been >>>> well-tested with interrupts enabled. In general when we've found a >>>> firmware issue in one place it ends up happening elsewhere as well, so >>>> it wouldn't surprise me if there are other machines that will also be >>>> unhappy with interrupts enabled. Would it be possible to automatically >>>> detect this case (eg, if we get more than a certain number of >>>> interrupts in a certain timeframe immediately after enabling the >>>> interrupt) and automatically fall back to polling in that case? It >>>> would also mean that users with fixed firmware wouldn't need to pass a >>>> parameter. >>> >>> I believe Matthew is correct here. I found another system today >>> with completely different vendor for both the system and the tpm chip. >>> In addition another Lenovo model, the L490, has the issue. >>> >>> This initial attempt at a solution like Matthew suggested works on >>> the system I found today, but I imagine it is all sorts of wrong. >>> In the 2 systems where I've seen it, there are about 100000 interrupts >>> in around 1.5 seconds, and then the irq code shuts down the interrupt >>> because they aren't being handled. >>> >>> >>> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c >>> index 49ae09ac604f..478e9d02a3fa 100644 >>> --- a/drivers/char/tpm/tpm_tis_core.c >>> +++ b/drivers/char/tpm/tpm_tis_core.c >>> @@ -27,6 +27,11 @@ >>> #include "tpm.h" >>> #include "tpm_tis_core.h" >>> >>> +static unsigned int time_start = 0; >>> +static bool storm_check = true; >>> +static bool storm_killed = false; >>> +static u32 irqs_fired = 0; >> >> Maybe kstat_irqs() would be a better idea than ad hoc stats. >> > > Thanks, yes that would be better. > >>> + >>> static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value); >>> >>> static void tpm_tis_enable_interrupt(struct tpm_chip *chip, u8 mask) >>> @@ -464,25 +469,31 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) >>> return rc; >>> } >>> >>> -static void disable_interrupts(struct tpm_chip *chip) >>> +static void __disable_interrupts(struct tpm_chip *chip) >>> { >>> struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >>> u32 intmask; >>> int rc; >>> >>> - if (priv->irq == 0) >>> - return; >>> - >>> rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); >>> if (rc < 0) >>> intmask = 0; >>> >>> intmask &= ~TPM_GLOBAL_INT_ENABLE; >>> rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); >>> + chip->flags &= ~TPM_CHIP_FLAG_IRQ; >>> +} >>> + >>> +static void disable_interrupts(struct tpm_chip *chip) >>> +{ >>> + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); >>> >>> + if (priv->irq == 0) >>> + return; >>> + >>> + __disable_interrupts(chip); >>> devm_free_irq(chip->dev.parent, priv->irq, chip); >>> priv->irq = 0; >>> - chip->flags &= ~TPM_CHIP_FLAG_IRQ; >>> } >>> >>> /* >>> @@ -528,6 +539,12 @@ 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 (unlikely(storm_killed)) { >>> + devm_free_irq(chip->dev.parent, priv->irq, chip); >>> + priv->irq = 0; >>> + storm_killed = false; >>> + } >> >> OK this kind of bad solution because if tpm_tis_send() is not called, >> then IRQ is never freed. AFAIK, devres_* do not sleep but use spin >> lock, i.e. you could render out both storm_check and storm_killed. >> > > Is there a way to flag it for freeing later while in an interrupt > context? I'm not sure where to clean it up since devm_free_irq can't be > called in tis_int_handler. You could add a workqueue work-struct just for this and queue that up to do the free when you detect the storm. That will then run pretty much immediately, avoiding the storm going on for (much) longer. > Before diving further into that though, does anyone else have an opinion > on ripping out the irq code, and just using polling? We've been only > polling since 2015 anyways. Given James Bottomley's reply I guess it would be worthwhile to get the storm detection to work. Regards, Hans > >>> + >>> if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested) >>> return tpm_tis_send_main(chip, buf, len); >>> >>> @@ -748,6 +765,21 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) >>> u32 interrupt; >>> int i, rc; >>> >>> + if (storm_check) { >>> + irqs_fired++; >>> + >>> + if (!time_start) { >>> + time_start = jiffies_to_msecs(jiffies); >>> + } else if ((irqs_fired > 1000) && (jiffies_to_msecs(jiffies) - jiffies < 500)) { >>> + __disable_interrupts(chip); >>> + storm_check = false; >>> + storm_killed = true; >>> + return IRQ_HANDLED; >>> + } else if ((jiffies_to_msecs(jiffies) - time_start > 500) && (irqs_fired < 1000)) { >>> + storm_check = false; >>> + } >>> + } >>> + >>> rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); >>> if (rc < 0) >>> return IRQ_NONE; >>> >>> >> >> /Jarkko >