linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Haris Okanovic <haris.okanovic@ni.com>
To: <linux-rt-users@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Cc: <tpmdd-devel@lists.sourceforge.net>, <haris.okanovic@ni.com>,
	<harisokn@gmail.com>, <julia.cartwright@ni.com>,
	<gratian.crisan@ni.com>, <scott.hartman@ni.com>,
	<chris.graf@ni.com>, <brad.mouring@ni.com>,
	<jonathan.david@ni.com>, <peterhuewe@gmx.de>,
	<tpmdd@selhorst.net>, <jarkko.sakkinen@linux.intel.com>,
	<jgunthorpe@obsidianresearch.com>, <eric.gardiner@ni.com>
Subject: [PATCH v2] tpm_tis: fix stall after iowrite*()s
Date: Tue, 15 Aug 2017 15:13:08 -0500	[thread overview]
Message-ID: <20170815201308.20024-1-haris.okanovic@ni.com> (raw)
In-Reply-To: <20170804215651.29247-1-haris.okanovic@ni.com>

ioread8() operations to TPM MMIO addresses can stall the cpu when
immediately following a sequence of iowrite*()'s to the same region.

For example, cyclitest measures ~400us latency spikes when a non-RT
usermode application communicates with an SPI-based TPM chip (Intel Atom
E3940 system, PREEMPT_RT_FULL kernel). The spikes are caused by a
stalling ioread8() operation following a sequence of 30+ iowrite8()s to
the same address. I believe this happens because the write sequence is
buffered (in cpu or somewhere along the bus), and gets flushed on the
first LOAD instruction (ioread*()) that follows.

The enclosed change appears to fix this issue: read the TPM chip's
access register (status code) after every iowrite*() operation to
amortize the cost of flushing data to chip across multiple instructions.

Signed-off-by: Haris Okanovic <haris.okanovic@ni.com>
---
[PATCH v2] Add tpm_tis_flush() function with comment explaining
the ioread8() after write, per Alexander.

https://patchwork.kernel.org/patch/9882119/
https://github.com/harisokanovic/linux/tree/dev/hokanovi/tpm-latency-spike-fix-v2
---
 drivers/char/tpm/tpm_tis.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index c7e1384f1b08..3fdec13eba8d 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -52,6 +52,31 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
 	return container_of(data, struct tpm_tis_tcg_phy, priv);
 }
 
+#ifdef CONFIG_PREEMPT_RT_FULL
+/*
+ * Flushes previous write operations to chip so that a subsequent
+ * ioread*()s won't stall a cpu.
+ */
+static inline void tpm_tis_flush(void __iomem *iobase)
+{
+	ioread8(iobase + TPM_ACCESS(0));
+}
+#else
+#define tpm_tis_flush(iobase) do { } while (0)
+#endif
+
+static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
+{
+	iowrite8(b, iobase + addr);
+	tpm_tis_flush(iobase);
+}
+
+static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
+{
+	iowrite32(b, iobase + addr);
+	tpm_tis_flush(iobase);
+}
+
 static bool interrupts = true;
 module_param(interrupts, bool, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -105,7 +130,7 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 	struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
 	while (len--)
-		iowrite8(*value++, phy->iobase + addr);
+		tpm_tis_iowrite8(*value++, phy->iobase, addr);
 	return 0;
 }
 
@@ -129,7 +154,7 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
 {
 	struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-	iowrite32(value, phy->iobase + addr);
+	tpm_tis_iowrite32(value, phy->iobase, addr);
 	return 0;
 }
 
-- 
2.13.2

  parent reply	other threads:[~2017-08-15 20:13 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-04 21:56 [PATCH] [RFC] tpm_tis: tpm_tcg_flush() after iowrite*()s Haris Okanovic
2017-08-07 14:59 ` Julia Cartwright
2017-08-08 21:58   ` Jarkko Sakkinen
2017-08-14 22:53     ` Haris Okanovic
2017-08-14 22:52   ` Haris Okanovic
2017-08-14 22:53 ` [PATCH] tpm_tis: fix stall " Haris Okanovic
2017-08-15  6:11   ` Alexander Stein
2017-08-15 20:10     ` Haris Okanovic
2017-08-15 20:13 ` Haris Okanovic [this message]
2017-08-16 21:15   ` [tpmdd-devel] [PATCH v2] " Ken Goldman
2017-08-17  5:57     ` Alexander Stein
2017-08-17 10:38     ` Sebastian Andrzej Siewior
2017-08-17 17:17       ` Jason Gunthorpe
2017-08-17 20:12         ` Haris Okanovic
2017-08-19 17:03         ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170815201308.20024-1-haris.okanovic@ni.com \
    --to=haris.okanovic@ni.com \
    --cc=brad.mouring@ni.com \
    --cc=chris.graf@ni.com \
    --cc=eric.gardiner@ni.com \
    --cc=gratian.crisan@ni.com \
    --cc=harisokn@gmail.com \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=jgunthorpe@obsidianresearch.com \
    --cc=jonathan.david@ni.com \
    --cc=julia.cartwright@ni.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=peterhuewe@gmx.de \
    --cc=scott.hartman@ni.com \
    --cc=tpmdd-devel@lists.sourceforge.net \
    --cc=tpmdd@selhorst.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).