From patchwork Fri Dec 8 18:46:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Steffen X-Patchwork-Id: 10103145 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 697B5602A0 for ; Fri, 8 Dec 2017 18:48:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A7CB28E21 for ; Fri, 8 Dec 2017 18:48:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F4DC28E3D; Fri, 8 Dec 2017 18:48:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 747EE28E21 for ; Fri, 8 Dec 2017 18:48:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752680AbdLHSsQ (ORCPT ); Fri, 8 Dec 2017 13:48:16 -0500 Received: from smtp11.infineon.com ([217.10.52.105]:27459 "EHLO smtp11.infineon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751275AbdLHSsP (ORCPT ); Fri, 8 Dec 2017 13:48:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=infineon.com; i=@infineon.com; q=dns/txt; s=IFXMAIL; t=1512758896; x=1544294896; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=gFmL/WtadTlzQs13Hm3i0Ugssik3QaJ+9yDyGnVRJMQ=; b=Mb5Ko3pO17olrZlRu8kJRkygwurafsx2oqlymDIuFAfKE3bYkPYhZ+bl 3MkyXZCwxb3h+t1xaFoiaMP4B4pu35uVTXv9caRikXOmUpL1zARysIdN8 6C5ZLqJuR2DdL9hOeniE6LpwrTAQ4hcRp+nvLXEZ/1a7TCbcKQfHln/kY g=; X-SBRS: None Received: from unknown (HELO mucxv002.muc.infineon.com) ([172.23.11.17]) by smtp11.infineon.com with ESMTP/TLS/AES256-GCM-SHA384; 08 Dec 2017 19:48:15 +0100 Received: from MUCSE708.infineon.com (mucse708.infineon.com [172.23.7.82]) by mucxv002.muc.infineon.com (Postfix) with ESMTPS; Fri, 8 Dec 2017 19:48:14 +0100 (CET) Received: from ABGN5CG4522MQD.eu.infineon.com (172.23.8.247) by MUCSE708.infineon.com (172.23.7.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.1.669.32; Fri, 8 Dec 2017 19:48:13 +0100 From: Alexander Steffen To: , , , CC: Alexander Steffen Subject: [RFC][PATCH 3/9] tpm_tis_core: correctly wait for flags to become zero Date: Fri, 8 Dec 2017 19:46:52 +0100 Message-ID: <20171208184658.9588-4-Alexander.Steffen@infineon.com> X-Mailer: git-send-email 2.11.1.windows.1 In-Reply-To: <20171208184658.9588-1-Alexander.Steffen@infineon.com> References: <20171208184658.9588-1-Alexander.Steffen@infineon.com> MIME-Version: 1.0 X-Originating-IP: [172.23.8.247] X-ClientProxiedBy: MUCSE706.infineon.com (172.23.7.80) To MUCSE708.infineon.com (172.23.7.82) Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP According to TIS/PTP the dataAvail flag and the Expect flag in the STS register contain valid values if and only if the stsValid flag in the same register is set. Currently, the code first waits for the stsValid flag to be set and then looks at the other flags. This causes the STS register to be read twice, so that the stsValid flag might not be set anymore when the other flags are evaluated. Other parts of the code already check both flags in a single operation within wait_for_tpm_stat. But the current implementation can only check for flags being set to 1, not 0. Therefore, add a parameter to wait_for_tpm_stat that allows to specify the expected value in addition to the selected flags and adapt all callers accordingly. In addition, this now checks the dataAvail and Expect flags multiple times within the specified timeout, so those flags no longer need to have the expected value right away. This is important for example when sending large amounts of data to the TPM, when the TPM might not process its I/O buffer fast enough for the flags to be set correctly when they are checked for the first time. Signed-off-by: Alexander Steffen Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis_core.c | 51 +++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index d367016..0df05b4 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -37,13 +37,13 @@ */ #define TPM_POLL_SLEEP 1 /* msec */ -static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, +static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, u8 value, bool check_cancel, bool *canceled) { u8 status = chip->ops->status(chip); *canceled = false; - if ((status & mask) == mask) + if ((status & mask) == value) return true; if (check_cancel && chip->ops->req_canceled(chip, status)) { *canceled = true; @@ -52,7 +52,7 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, return false; } -static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, +static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, u8 value, unsigned long timeout, wait_queue_head_t *queue, bool check_cancel) { @@ -63,7 +63,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, /* check current status */ status = chip->ops->status(chip); - if ((status & mask) == mask) + if ((status & mask) == value) return 0; stop = jiffies + timeout; @@ -74,7 +74,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, 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, mask, value, check_cancel, &canceled), timeout); if (rc > 0) { @@ -90,7 +90,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, do { tpm_msleep(TPM_POLL_SLEEP); status = chip->ops->status(chip); - if ((status & mask) == mask) + if ((status & mask) == value) return 0; } while (time_before(jiffies, stop)); } @@ -243,6 +243,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) while (size < count) { rc = wait_for_tpm_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->timeout_c, &priv->read_queue, true); if (rc < 0) @@ -268,7 +269,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int size = 0; - int expected, status; + int expected; if (count < TPM_HEADER_SIZE) { size = -EIO; @@ -296,13 +297,9 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, + if (wait_for_tpm_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, + TPM_STS_VALID, chip->timeout_c, &priv->int_queue, false) < 0) { - size = -ETIME; - goto out; - } - status = tpm_tis_status(chip); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ dev_err(&chip->dev, "Error left over data\n"); size = -EIO; goto out; @@ -329,8 +326,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_ready(chip); if (wait_for_tpm_stat - (chip, TPM_STS_COMMAND_READY, chip->timeout_b, - &priv->int_queue, false) < 0) { + (chip, TPM_STS_COMMAND_READY, TPM_STS_COMMAND_READY, + chip->timeout_b, &priv->int_queue, false) < 0) { rc = -ETIME; goto out_err; } @@ -351,13 +348,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) count += burstcnt; - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { - rc = -ETIME; - goto out_err; - } - status = tpm_tis_status(chip); - if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { + if (!itpm && wait_for_tpm_stat + (chip, TPM_STS_DATA_EXPECT | TPM_STS_VALID, + TPM_STS_DATA_EXPECT | TPM_STS_VALID, + chip->timeout_c, &priv->int_queue, false) < 0) { rc = -EIO; goto out_err; } @@ -368,13 +362,9 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if (rc < 0) goto out_err; - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { - rc = -ETIME; - goto out_err; - } - status = tpm_tis_status(chip); - if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { + if (!itpm && wait_for_tpm_stat + (chip, TPM_STS_DATA_EXPECT | TPM_STS_VALID, TPM_STS_VALID, + chip->timeout_c, &priv->int_queue, false) < 0) { rc = -EIO; goto out_err; } @@ -434,7 +424,8 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) dur = tpm_calc_ordinal_duration(chip, ordinal); if (wait_for_tpm_stat - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, &priv->read_queue, false) < 0) { rc = -ETIME; goto out_err;