From patchwork Tue Jun 21 13:24:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lino Sanfilippo X-Patchwork-Id: 12889300 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 E7037C43334 for ; Tue, 21 Jun 2022 13:34:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351462AbiFUNeY (ORCPT ); Tue, 21 Jun 2022 09:34:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351722AbiFUNbC (ORCPT ); Tue, 21 Jun 2022 09:31:02 -0400 Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 678DD2AE19; Tue, 21 Jun 2022 06:25:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1655817938; bh=ZtEf9z9KJysNGGV3ChvOjRTJrFhCrpznXAsR54JnfUE=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=OzUTeAj6/Yec0YXXCrxnrihQym7oUcnXm/+bI/eRw6Y7kMIeJWjjXuioR9y/61yGE 6bKj/Sl6FFaOMHU+LKQjncFk/44e5UXXkGEyufJ1YA5KWbJzrWrIgb+QgIrePHoeuS 8JFGuMNWDyYfYxMg8je4Nk1HcIXE3ptOGzhbkOac= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from Venus.fritz.box ([46.223.2.162]) by mail.gmx.net (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MhD6W-1nQTJL3ozS-00ePJO; Tue, 21 Jun 2022 15:25:38 +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, l.sanfilippo@kunbus.com, LinoSanfilippo@gmx.de, lukas@wunner.de, p.rosenberger@kunbus.com Subject: [PATCH v6 5/9] tpm, tpm_tis: Only handle supported interrupts Date: Tue, 21 Jun 2022 15:24:43 +0200 Message-Id: <20220621132447.16281-6-LinoSanfilippo@gmx.de> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220621132447.16281-1-LinoSanfilippo@gmx.de> References: <20220621132447.16281-1-LinoSanfilippo@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:PfAWhCJFoEHpwbXMfPUh7kYO31Tnx8Cf5/J7Gpg8nzHJD17NSJS A9z46GMWp0J+eAaQ/oOnB1XTWj3eoo1HiZXwmrgOdZ+505PBRKp+AMgA/oaBYWn2nUjZv2A AB0C8s+5xX4SeMrZYOmtI/x8+schZerxyGuUwVFnsY0amSIKqUHdtAbEix+OC7vuRt9i9Ym e4ik1o7L9itY5PHe34MEA== X-UI-Out-Filterresults: notjunk:1;V03:K0:G+++L7UgAio=:vHehAF1AaVLEPwfa7S05gL aoahPZHLW22hMlDcBURPbL6TFlOnrbymKuWLXxj8ThnBIDm9YVa4ETKQE+cjQJx1ud68nZMGI I4MzOS/E1yzDsrpsqb6KiN7ekXtR/cQm03ttdrtdim9JAMiBA8xv0LjYPxVifxzjMBNT9+kf0 tdHfgOrSaX5lCyYls2rMSY6ogsSECukhCUdXo+6p6sPu+QZzTTjT4mWNzwNrtIJym4MTUWLAS W5C5fHL9GZCQMkyBy4IpFBy6mWE1j6aPg7RjGFv2RBzA4FjmVnytvNy+5h7FCZUZdMukBCaUc YXZYa32BfeUm8jqPNTgLEuvSyJqchw0VLrskzo4EzXmzZ8i/rem/mchhaCq3KbJ33nmszhGO1 O2PZ4lqk2/dyDYd4hMOuw4/sb81PfTykqJ6/ZKbst/qtAPCtdRCTV7F6qwOtxc1vuwePPjnoZ ePhfxjJ/kAoUsp6Op8ZmjGIuxaj8C34ilmqLfzSt034JyWb2lXtNWxVJSSwB0Ws6MQZywsHeM pEqo0Dl6vf/ldYo440034wxkkxt2DS+bu17939iarzYvLV9UJRSqWcllFFMkd7CuxPJ13JBBi 7S2UVq+r4H/6O/+F6KS3eWNCTU+fu3zAIUr23PpEi5ubdgRhHuitebCEHyUhXJTa3NAUgF/cJ 6f6e+UKfgZQXkH6NoVHGNXBjwlPYe3RnHygTj5rffnWnBh8rqmpftzTAoUKMOa3jiN+Z6mjjs UY8QcTsZ0XKvhNiTCT+AXmy9FFR49gyZ0VsGV1V28E+7EN+QZjN9Wsr9g1oEbhtSnF7fq2PSp DnwfNjuID7eeI9Z6yK8rHs7KF0/rNyZBKKV08vqKBwFfiCMo+PNtFKwgYuEk4C8ivPTVKLrhY hJfBuKhQmGxVy0iLkDy2i6PyG6PvqKdiQU8AuZ/h/1e+QYX7qCxo9mcX4GgLJBLszII/0Fc1c 1g4oWySyfsdTxMe9vY6TZpVyaT/dSR/QKnl4Eh3p8bLPv83IlDXXImw5afZABDCFjdCCAxASQ oleW3CA5y3uUoJr/OFiMd4TsX92l43DZt9/UeDla2N/IMR/rRhhswrV0xk0DA6WXVxSralNFE ydZLGlB76O/gzc7i3kv/arWOa/xEF9smfsMDgvwJDsmHXHUWfKxhn4SdA== 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 --- drivers/char/tpm/tpm_tis_core.c | 119 +++++++++++++++++++------------- drivers/char/tpm/tpm_tis_core.h | 1 + 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 09d8f04cbc81..cb469591373a 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; } @@ -1007,8 +1029,39 @@ 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); @@ -1042,32 +1095,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); @@ -1098,7 +1125,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"); @@ -1145,13 +1174,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 bf07379dea42..e005eb99480e 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;