From patchwork Mon Oct 17 23:57:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lino Sanfilippo X-Patchwork-Id: 13009719 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66401C4167B for ; Mon, 17 Oct 2022 23:58:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230390AbiJQX6Q (ORCPT ); Mon, 17 Oct 2022 19:58:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230254AbiJQX6O (ORCPT ); Mon, 17 Oct 2022 19:58:14 -0400 Received: from mout.gmx.net (mout.gmx.net [212.227.17.21]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4C7617E320; Mon, 17 Oct 2022 16:58:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1666051072; bh=aGoHsAcDuhhqSpkLQAxXzsC5Nh/HzN5f5Q02AEnI5+I=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=CQnw5FNrGJNnfwbeZ1tCNB1MFkNeGujM/NnltvNvJFZ+3HE68JAsYfdnHlrbJFaYt ITQouyu0X5vBCOMrTTjL7yYz1FAT4lQk5gn4PxAS9CK21sZkSiYqyReuI7WPue98TO jUBoYujT8tC6ibZMa0tpPKVZNq07e+oJd9XPXQ0U= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from Venus.speedport.ip ([84.162.5.241]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MF3HU-1ovYKl4Awa-00FQ7i; Tue, 18 Oct 2022 01:57:52 +0200 From: Lino Sanfilippo To: peterhuewe@gmx.de, jarkko@kernel.org, jgg@ziepe.ca Cc: stefanb@linux.vnet.ibm.com, linux@mniewoehner.de, linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org, jandryuk@gmail.com, pmenzel@molgen.mpg.de, l.sanfilippo@kunbus.com, LinoSanfilippo@gmx.de, lukas@wunner.de, p.rosenberger@kunbus.com Subject: [PATCH v8 05/11] tpm, tpm_tis: Only handle supported interrupts Date: Tue, 18 Oct 2022 01:57:26 +0200 Message-Id: <20221017235732.10145-6-LinoSanfilippo@gmx.de> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221017235732.10145-1-LinoSanfilippo@gmx.de> References: <20221017235732.10145-1-LinoSanfilippo@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:nUbU4NRPZD5rhgOWoMvN+mlSIdLkSir1mw9uGxYDN1Ie3MUq4bE b9JdPFI1/+DemG7CeEmSXQXUrvg6FGea8VUVDHIWTSheUhkUuTjydUf1DgwkBig3Il+8Gq2 snTZ6Bbv/sP4Bgk3lvGcl3hZJ9j2Qoa8g9g+qTY9L36LI/JqK98AjWxm6WBkIzYqW3U/hW5 0Whp5kZD342S6FwgL/uIg== X-UI-Out-Filterresults: notjunk:1;V03:K0:EkqpYWXdsdo=:3kQz8APDD0Ord+K1eyK1j1 fgUdmtsx0UJNG2isqOZnZmQB/DvZx3IQSm8pRoewuJ9Ay4uj86XACRw+yN/C1k3w0Aek9TSpp rUjVM/vHinU51WDQdrCvLR427oAh5wawwcJ3ifRpDapopc6JFqrD1gGAuVdBaCWEUArD959VY f5GxxyFlHw8VymMlOS/ggpuOfmXk/VxV5RQ+3kCkzs7tOzGp3G8YVMDS40R4qFPKB/HTPLLnC nF21JKEG2rdMMOfZrDm7aAbvO/O3x4Pm/fg0gaByF2BOm3r+E1kj0KrOZCo3SlredNYChs3Mt WDyKs7sXETYFQT2pMKxkSRSbfaGoe0NA+BzoFrlk/eaWohBj3+iiL7XhzxJtRXUE82atk3hE6 Wj2hvZFaAdwFZ0Td6S7nBAAJWEk6kdaKIICy31H8DsFu1Zmg94/+lBEbAuCwCAB6OgIpvJ+gM dM3qwhKuIGqI0fp+ZXRcD6uRoUHaafjNr+PvHaVdhcJ/pQ/Y3zMSs8HiFVo29yKG21CVaNaL2 O8bncCvQ1IdfBBhGmm2Y//8BDSMI6DDgEgqci/YDocXghvh8J8duixvfdlqFkNacgHAs9yLZO Hhr23lN1/sSbP9JhcwBBB2iHXHbzRJV9GflcEKyw/4KiJ9Er6h3VLKwSXg+XMpuy2Vz8Wa3r1 kF1ZW0jRpzdvrvc6MuePFFQkN0bO28BwsxqRdJJ77qlKv+/YysHN5wQ06LUXCPu01GjU8OVA2 JUR1MH9d3/89k+MCUvu3D/pBBa4BeXMixvuyq8ZnAjpvEN1ydZoOfstMpYDqhcGM8fsZLSy6V eJB6pEpXWWQaVkcY1iWWM5hfqrxtMs++MrA7m3VMpvYw5LBSHtGXD8p9GrUVtQeiL1BjC89fl Xxh6Jv/uSvKO5l16apTiFiFtunEiTUkSaA9Wm2bKoapMap0eTmLhOgRTEVsBY9VVET1FdTzbW 6GtpQKb8qR0sQfY5YTLd/zqLyvemAQzJk15uk2uG01wurqaglLqAGb//PImT+QU51nC/5T712 rBLxu4AyVT2zv/xTfdpGdJ/CkJNmEU7w8HFm/bvHkBxR4nAJ7IzKmGD6o0BuZWC34N48Tf9R6 0qKgrt/S6zCe6ZLD/D/xPPJqE7cgjbPLJetfqRFo4ArArBR9ySypL9ynkn3GAjrMMCiu6Fa/q kHYSxFYAvmh6MCz2tQw5MLGzgJwkemjaOwlXydgARqbILtPqgxOuSgMbWUIKcwW0BFcMhKBRg Y9Sj44bR0I6f0j8Q5vqn4drbGHdPK2xFvI+X51IRx7vY3M0a3ORjAdz3pU4y9wS2/lpl0eVjA 4Nt47s23yteUS3FEqS7lBCq77oREHTCwPEMWUu0Ip/p3ZezxcjJar6Uq/lCqLRbFbVwQSywT6 MnaPmeYx9J1sA6Ts6vlGq3LREvxC9vmOdCSt4qqlKfs0xlIQD1SqP0LL5Z0UkYuPjMNDANweK +zVSnSyhh4VFvm8pcIcCN/m22FyUCWZ2Z22GZ5roGPe8CefVRtz0TvU8nurFEv2YHVY0lIKVl Tn1avMzuHtlCtOmzugKA4KFxlsa4XZrDPpOAAPchMjtwP Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Lino Sanfilippo According to the TPM Interface Specification (TIS) support for "stsValid" and "commandReady" interrupts is only optional. This has to be taken into account when handling the interrupts in functions like wait_for_tpm_stat(). To determine the supported interrupts use the capability query. Also adjust wait_for_tpm_stat() to only wait for interrupt reported status changes. After that process all the remaining status changes by polling the status register. Signed-off-by: Lino Sanfilippo Tested-by: Michael Niewöhner Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis_core.c | 120 +++++++++++++++++++------------- drivers/char/tpm/tpm_tis_core.h | 1 + 2 files changed, 73 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 52205a1fee9e..d07debc3182c 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -53,41 +53,63 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, long rc; u8 status; bool canceled = false; + u8 sts_mask = 0; + int ret = 0; /* check current status */ status = chip->ops->status(chip); if ((status & mask) == mask) return 0; - stop = jiffies + timeout; + /* check what status changes can be handled by irqs */ + if (priv->int_mask & TPM_INTF_STS_VALID_INT) + sts_mask |= TPM_STS_VALID; - if (chip->flags & TPM_CHIP_FLAG_IRQ) { + if (priv->int_mask & TPM_INTF_DATA_AVAIL_INT) + sts_mask |= TPM_STS_DATA_AVAIL; + + if (priv->int_mask & TPM_INTF_CMD_READY_INT) + sts_mask |= TPM_STS_COMMAND_READY; + + sts_mask &= mask; + + stop = jiffies + timeout; + /* process status changes with irq support */ + if (sts_mask) { + ret = -ETIME; again: timeout = stop - jiffies; if ((long)timeout <= 0) return -ETIME; rc = wait_event_interruptible_timeout(*queue, - wait_for_tpm_stat_cond(chip, mask, check_cancel, + wait_for_tpm_stat_cond(chip, sts_mask, check_cancel, &canceled), timeout); if (rc > 0) { if (canceled) return -ECANCELED; - return 0; + ret = 0; } if (rc == -ERESTARTSYS && freezing(current)) { clear_thread_flag(TIF_SIGPENDING); goto again; } - } else { - do { - usleep_range(priv->timeout_min, - priv->timeout_max); - status = chip->ops->status(chip); - if ((status & mask) == mask) - return 0; - } while (time_before(jiffies, stop)); } + + if (ret) + return ret; + + mask &= ~sts_mask; + if (!mask) /* all done */ + return 0; + /* process status changes without irq support */ + do { + status = chip->ops->status(chip); + if ((status & mask) == mask) + return 0; + usleep_range(priv->timeout_min, + priv->timeout_max); + } while (time_before(jiffies, stop)); return -ETIME; } @@ -1021,8 +1043,40 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, 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; + /* 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) { + intmask |= 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) { + intmask |= TPM_INTF_LOCALITY_CHANGE_INT; + dev_dbg(dev, "\tLocality Change Int Support\n"); + } + if (intfcaps & TPM_INTF_STS_VALID_INT) { + intmask |= TPM_INTF_STS_VALID_INT; + dev_dbg(dev, "\tSts Valid Int Support\n"); + } + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) { + intmask |= TPM_INTF_DATA_AVAIL_INT; + dev_dbg(dev, "\tData Avail Int Support\n"); + } + intmask &= ~TPM_GLOBAL_INT_ENABLE; rc = request_locality(chip, 0); @@ -1056,32 +1110,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); @@ -1112,7 +1140,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, else tpm_tis_probe_irq(chip, intmask); - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { + if (chip->flags & TPM_CHIP_FLAG_IRQ) { + priv->int_mask = intmask; + } else { dev_err(&chip->dev, FW_BUG "TPM interrupt not working, polling instead\n"); @@ -1159,13 +1189,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) if (rc < 0) goto out; - rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); - 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->int_mask | 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 695a2516dce0..2deef11c88db 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -93,6 +93,7 @@ struct tpm_tis_data { u16 manufacturer_id; int locality; int irq; + unsigned int int_mask; unsigned long flags; void __iomem *ilb_base_addr; u16 clkrun_enabled;