From patchwork Thu Nov 24 13:55:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lino Sanfilippo X-Patchwork-Id: 13055010 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 8F57FC433FE for ; Thu, 24 Nov 2022 13:56:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230152AbiKXN4k (ORCPT ); Thu, 24 Nov 2022 08:56:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230003AbiKXN4d (ORCPT ); Thu, 24 Nov 2022 08:56:33 -0500 Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 934CBF5A1B; Thu, 24 Nov 2022 05:56:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.de; s=s31663417; t=1669298172; bh=/LIepLLbPWcHWTum88qdQFhReQDSW470FeNeEDgXBaE=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=BGJc5p5j+7qHYahYlcBr4a6uozSb9nhA9r/+Los+6iUOxthJE0sW4fFWw6Le/SO47 Z7tq0OWILZrA+TxuS+w+rMlOp+OX31oG6JY4U26sI0e3KnA72zwT7P0eXEcvRs75pe pljZnhRSTCTpsxpcYHJ5eNT4VDbUmBLuKqAQipaJJi0kr38ije+zO0RSHqpxPomkC+ GD9KnnnZ77r1HqOwhPJT84nDcnQr5s1sApqObSG53AtoAJXZP1/t9ZKcnD9dwx8oh5 jPWF43EzAK2gliXbdPQf8EGj7um+QdLDdVDnZm5pcse7dFZFI3wNO0MPoYUYdypkk/ ka5LDy70uVbBw== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Received: from Venus.speedport.ip ([84.162.7.17]) by mail.gmx.net (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MNKm0-1oZNME08sc-00Orb8; Thu, 24 Nov 2022 14:56:12 +0100 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 v11 06/14] tpm, tpm_tis: Only handle supported interrupts Date: Thu, 24 Nov 2022 14:55:30 +0100 Message-Id: <20221124135538.31020-7-LinoSanfilippo@gmx.de> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221124135538.31020-1-LinoSanfilippo@gmx.de> References: <20221124135538.31020-1-LinoSanfilippo@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:67o+5BRMDYtidqREBdNHB+oywrFTm9p0D+fHxBUOOEXWbXOiKO3 P2ExBY73eaQFFm5PkSstT+ezw8gxHLZbmrkgiOfbOVMXS7WFlsNOQufRUjx29141gVbAvwf Nw0FZGM3AXYkIwysp2UrwSoFTBrtsOVPDY0maiVwx5EyhcKBy7q8+w7CSN84LcD36XJCqG7 HlehynnNh7p5NDYU87laQ== UI-OutboundReport: notjunk:1;M01:P0:vpdU4kdjoPI=;8Ksw9yPGaSp+fNnK40CiYbdyZIc biz+cVRG3NvqFlGWCrVg6blB0bu+ocByBpc4jlpRDTBDb5lChp5SmpQc58o+npk1N7i4hlcf9 +T48J734dIW2ed6mY0c2DNjoROvY1IS0USnba5ohw6/Dhnx0FDzECgugkG13j9s1FIUPy8+hg 6c0/gnZO1lFwtQZAyhcetH6rzSIJmwQoRs5EJUcrPkBMFH5F7rO7tQPjxpE7FCgIhxK41r/Cn WeSDVdE+lfki1zd1e+SP2DXQQuxckd1GIoBaygp2PhFq5ymYNVJC+SyMwu73KPWI4zZm3bOO1 vIJDyrvAkXXDoO7H1+bgTmjargfn/zwAatGu7S9yStSoJCkcngjSnu4ajeoZs7ezq6yhbHL9X jdH6KHhxZ7wv135dGdzntQAimz3eBTyETnAElLCy8bewRjFBE7e3I8fdPeIl5PuK3LUGEjEsA JJmUJVNNAzlAyx76j8zDFQN23bnQ5PMuQz8xrKHFOxQieGW0SWgkE8PYhxu4rA09q3x2UAW+m 4rWGEsgWL78J+uCzjl5ETBklNj6LaKbNoZvjF5FANNjnQTQh+uWr8W6iJajBhk67U/7+RQE+v tCEPfAxSLjyQF2TtzakvtEXkOATz1zBY2T8BFN7QtHMhdVbidZhjYj0YlRf69npguFBLaQDhN xmvXkmhzMisDNgxD9HnlQSQfxhFAqbtLpw4bmERPeuu4o+kgl2HPVOXzYCAPqlLwEJfbBMlu/ SeplPkVNuVqT1SCTlurWmMEebqiK6wLuELNE0h5igs5k6vO2o5E7iTJIkBIRsqzgShn3vUGnA uSrVyAr8vg1vvvUOHuQuE0hLe4VRGX25sx7agTajfLWKfJjg1+gffpk+aZGO8iLe0ae/oY7vA FFGmdLDSlKDI1U50WE6usnapllcl8ctp3FVoSHfPIvrJReGWz2RofC1NicC0JCTOph/VIk0x5 NC2AVGCujEpWc/l3K4XxOVgp4ZA= 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 49848268f547..2694b1bb77de 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; } @@ -1001,8 +1023,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); @@ -1036,32 +1090,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); @@ -1092,7 +1120,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"); @@ -1139,13 +1169,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;