All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Marc-André Lureau" <marcandre.lureau@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: slp@redhat.com, bhe@redhat.com, mst@redhat.com, somlo@cmu.edu,
	xiaolong.ye@intel.com,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PATCH v15 11/11] RFC: fw_cfg: do DMA read operation
Date: Thu, 15 Feb 2018 22:33:12 +0100	[thread overview]
Message-ID: <20180215213312.29234-12-marcandre.lureau@redhat.com> (raw)
In-Reply-To: <20180215213312.29234-1-marcandre.lureau@redhat.com>

Modify fw_cfg_read_blob() to use DMA if the device supports it.
Return errors, because the operation may fail.

So far, only one call in fw_cfg_register_dir_entries() is using
kmalloc'ed buf and is thus clearly eligible to DMA read.

Initially, I didn't implement DMA read to speed up boot time, but as a
first step before introducing DMA write (since read operations were
already presents). Even more, I didn't realize fw-cfg entries were
being read by the kernel during boot by default. But actally fw-cfg
entries are being populated during module probe. I knew DMA improved a
lot bios boot time (the main reason the DMA interface was added
afaik). Let see the time it would take to read the whole ACPI
tables (128kb allocated)

 # time cat /sys/firmware/qemu_fw_cfg/by_name/etc/acpi/tables/raw
  - with DMA: sys 0m0.003s
  - without DMA (-global fw_cfg.dma_enabled=off): sys 0m7.674s

FW_CFG_FILE_DIR (0x19) is the only "file" that is read during kernel
boot to populate sysfs qemu_fw_cfg directory, and it is quite
small (1-2kb). Since it does not expose itself, in order to measure
the time it takes to read such small file, I took a comparable sized
file of 2048 bytes and exposed it (-fw_cfg test,file=file with a
modified read_raw enabling DMA)

 # perf stat -r 100 cat /sys/firmware/qemu_fw_cfg/by_name/test/raw >/dev/null
  - with DMA:
          0.636037      task-clock (msec)         #    0.141 CPUs utilized            ( +-  1.19% )
  - without DMA:
          6.430128      task-clock (msec)         #    0.622 CPUs utilized            ( +-  0.22% )

That's a few msec saved during boot by enabling DMA read (the gain
would be more substantial if other & bigger fw-cfg entries are read by
others from sysfs, unfortunately, it's not clear if we can always
enable DMA there)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 drivers/firmware/qemu_fw_cfg.c | 61 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 3015e77aebca..94df57e9be66 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -124,12 +124,47 @@ static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
 	return ret;
 }
 
+/* with acpi & dev locks taken */
+static ssize_t fw_cfg_read_blob_dma(u16 key,
+				void *buf, loff_t pos, size_t count)
+{
+	ssize_t ret;
+
+	if (pos == 0) {
+		ret = fw_cfg_dma_transfer(buf, count, key << 16
+					| FW_CFG_DMA_CTL_SELECT
+					| FW_CFG_DMA_CTL_READ);
+	} else {
+		fw_cfg_sel_endianness(key);
+		ret = fw_cfg_dma_transfer(NULL, pos, FW_CFG_DMA_CTL_SKIP);
+		if (ret < 0)
+			return ret;
+		ret = fw_cfg_dma_transfer(buf, count,
+					FW_CFG_DMA_CTL_READ);
+	}
+
+	return ret;
+}
+
+/* with acpi & dev locks taken */
+static ssize_t fw_cfg_read_blob_io(u16 key,
+				void *buf, loff_t pos, size_t count)
+{
+	fw_cfg_sel_endianness(key);
+	while (pos-- > 0)
+		ioread8(fw_cfg_reg_data);
+	ioread8_rep(fw_cfg_reg_data, buf, count);
+	return count;
+}
+
 /* read chunk of given fw_cfg blob (caller responsible for sanity-check) */
 static ssize_t fw_cfg_read_blob(u16 key,
-				void *buf, loff_t pos, size_t count)
+				void *buf, loff_t pos, size_t count,
+				bool dma)
 {
 	u32 glk = -1U;
 	acpi_status status;
+	ssize_t ret;
 
 	/* If we have ACPI, ensure mutual exclusion against any potential
 	 * device access by the firmware, e.g. via AML methods:
@@ -143,14 +178,17 @@ static ssize_t fw_cfg_read_blob(u16 key,
 	}
 
 	mutex_lock(&fw_cfg_dev_lock);
-	fw_cfg_sel_endianness(key);
-	while (pos-- > 0)
-		ioread8(fw_cfg_reg_data);
-	ioread8_rep(fw_cfg_reg_data, buf, count);
+	if (dma && fw_cfg_dma_enabled()) {
+		ret = fw_cfg_read_blob_dma(key, buf, pos, count);
+	} else {
+		ret = fw_cfg_read_blob_io(key, buf, pos, count);
+	}
+
 	mutex_unlock(&fw_cfg_dev_lock);
 
 	acpi_release_global_lock(glk);
-	return count;
+
+	return ret;
 }
 
 #ifdef CONFIG_CRASH_CORE
@@ -284,7 +322,7 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 
 	/* verify fw_cfg device signature */
 	if (fw_cfg_read_blob(FW_CFG_SIGNATURE, sig,
-				0, FW_CFG_SIG_SIZE) < 0 ||
+				0, FW_CFG_SIG_SIZE, false) < 0 ||
 		memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
 		fw_cfg_io_cleanup();
 		return -ENODEV;
@@ -468,7 +506,8 @@ static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,
 	if (count > entry->size - pos)
 		count = entry->size - pos;
 
-	return fw_cfg_read_blob(entry->select, buf, pos, count);
+	/* do not use DMA, virt_to_phys(buf) might not be ok */
+	return fw_cfg_read_blob(entry->select, buf, pos, count, false);
 }
 
 static struct bin_attribute fw_cfg_sysfs_attr_raw = {
@@ -634,7 +673,7 @@ static int fw_cfg_register_dir_entries(void)
 	size_t dir_size;
 
 	ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, &files_count,
-			0, sizeof(files_count));
+			0, sizeof(files_count), false);
 	if (ret < 0)
 		return ret;
 
@@ -646,7 +685,7 @@ static int fw_cfg_register_dir_entries(void)
 		return -ENOMEM;
 
 	ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, dir,
-			sizeof(files_count), dir_size);
+			sizeof(files_count), dir_size, false);
 	if (ret < 0)
 		goto end;
 
@@ -697,7 +736,7 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
 		goto err_probe;
 
 	/* get revision number, add matching top-level attribute */
-	err = fw_cfg_read_blob(FW_CFG_ID, &rev, 0, sizeof(rev));
+	err = fw_cfg_read_blob(FW_CFG_ID, &rev, 0, sizeof(rev), false);
 	if (err < 0)
 		goto err_probe;
 
-- 
2.16.1.73.g5832b7e9f2

  parent reply	other threads:[~2018-02-15 21:33 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-15 21:33 [PATCH v15 00/11] fw_cfg: add DMA operations & etc/vmcoreinfo support Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 01/11] crash: export paddr_vmcoreinfo_note() Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 02/11] fw_cfg: add a public uapi header Marc-André Lureau
2018-02-27  0:06   ` Michael S. Tsirkin
2018-02-28 11:50     ` Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 03/11] fw_cfg: fix sparse warnings in fw_cfg_sel_endianness() Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 04/11] fw_cfg: fix sparse warnings with fw_cfg_file Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 05/11] fw_cfg: fix sparse warning reading FW_CFG_ID Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 06/11] fw_cfg: fix sparse warnings around FW_CFG_FILE_DIR read Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 07/11] fw_cfg: remove inline from fw_cfg_read_blob() Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 08/11] fw_cfg: handle fw_cfg_read_blob() error Marc-André Lureau
2018-02-27  0:20   ` Michael S. Tsirkin
2018-02-28 11:49     ` Marc-André Lureau
2018-02-28 13:01       ` Gabriel Somlo
2018-02-28 15:32       ` Michael S. Tsirkin
2018-02-28 23:25         ` Gabriel Somlo
2018-02-28 23:58           ` Michael S. Tsirkin
2018-02-28 23:58             ` Michael S. Tsirkin
2018-03-01  0:49               ` Gabriel Somlo
2018-03-01  0:35             ` Gabriel Somlo
2018-02-15 21:33 ` [PATCH v15 09/11] fw_cfg: add DMA register Marc-André Lureau
2018-02-15 21:33 ` [PATCH v15 10/11] fw_cfg: write vmcoreinfo details Marc-André Lureau
2018-02-27  0:28   ` Michael S. Tsirkin
2018-02-28 12:22     ` Marc-André Lureau
2018-02-28 15:34       ` Michael S. Tsirkin
2018-02-15 21:33 ` Marc-André Lureau [this message]
2018-02-27  0:04   ` [PATCH v15 11/11] RFC: fw_cfg: do DMA read operation Michael S. Tsirkin
2018-02-28 12:27     ` Marc-André Lureau
2018-02-28 15:35       ` Michael S. Tsirkin
2018-02-28 15:41         ` Marc-André Lureau
2018-02-28 15:48           ` Michael S. Tsirkin
2018-02-28 16:00             ` Marc-André Lureau
2018-02-28 17:16               ` Michael S. Tsirkin
2018-02-28 17:17           ` Michael S. Tsirkin
2018-02-28 17:22             ` Marc-André Lureau
2018-02-27  0:29 ` [PATCH v15 00/11] fw_cfg: add DMA operations & etc/vmcoreinfo support Michael S. Tsirkin

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=20180215213312.29234-12-marcandre.lureau@redhat.com \
    --to=marcandre.lureau@redhat.com \
    --cc=bhe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=slp@redhat.com \
    --cc=somlo@cmu.edu \
    --cc=xiaolong.ye@intel.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.