From: Peter Xu <peterx@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: linux-kernel@vger.kernel.org, bhe@redhat.com, slp@redhat.com,
mst@redhat.com, somlo@cmu.edu, xiaolong.ye@intel.com,
qemu-devel@nongnu.org
Subject: Re: [PATCH v10 2/4] fw_cfg: do DMA read operation
Date: Wed, 24 Jan 2018 11:25:05 +0800 [thread overview]
Message-ID: <20180124032505.GD8001@xz-mi> (raw)
In-Reply-To: <20180123164041.30339-3-marcandre.lureau@redhat.com>
On Tue, Jan 23, 2018 at 05:40:39PM +0100, Marc-André Lureau wrote:
> Modify fw_cfg_read_blob() to use DMA if the device supports it.
> Return errors, because the operation may fail.
>
> The DMA operation is expected to run synchronously with today qemu,
> but the specification states that it may become async, so we run
> "control" field check in a loop for eventual changes.
>
> We may want to switch all the *buf addresses to use only kmalloc'ed
> buffers (instead of using stack/image addresses with dma=false).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> drivers/firmware/qemu_fw_cfg.c | 131 ++++++++++++++++++++++++++++++++++-------
> 1 file changed, 111 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> index 740df0df2260..686f0e839858 100644
> --- a/drivers/firmware/qemu_fw_cfg.c
> +++ b/drivers/firmware/qemu_fw_cfg.c
> @@ -33,6 +33,7 @@
> #include <linux/slab.h>
> #include <linux/io.h>
> #include <linux/ioport.h>
> +#include <linux/delay.h>
>
> MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");
> MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
> @@ -43,12 +44,22 @@ MODULE_LICENSE("GPL");
> #define FW_CFG_ID 0x01
> #define FW_CFG_FILE_DIR 0x19
>
> +#define FW_CFG_VERSION_DMA 0x02
> +#define FW_CFG_DMA_CTL_ERROR 0x01
> +#define FW_CFG_DMA_CTL_READ 0x02
> +#define FW_CFG_DMA_CTL_SKIP 0x04
> +#define FW_CFG_DMA_CTL_SELECT 0x08
> +#define FW_CFG_DMA_CTL_WRITE 0x10
> +
> /* size in bytes of fw_cfg signature */
> #define FW_CFG_SIG_SIZE 4
>
> /* fw_cfg "file name" is up to 56 characters (including terminating nul) */
> #define FW_CFG_MAX_FILE_PATH 56
>
> +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
> +static u32 fw_cfg_rev;
> +
> /* fw_cfg file directory entry type */
> struct fw_cfg_file {
> u32 size;
> @@ -57,6 +68,12 @@ struct fw_cfg_file {
> char name[FW_CFG_MAX_FILE_PATH];
> };
>
> +struct fw_cfg_dma {
> + u32 control;
> + u32 length;
> + u64 address;
> +} __packed;
> +
> /* fw_cfg device i/o register addresses */
> static bool fw_cfg_is_mmio;
> static phys_addr_t fw_cfg_p_base;
> @@ -75,12 +92,68 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
> return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key);
> }
>
> +static inline bool fw_cfg_dma_enabled(void)
> +{
> + return fw_cfg_rev & FW_CFG_VERSION_DMA && fw_cfg_reg_dma;
> +}
> +
> +/* qemu fw_cfg device is sync today, but spec says it may become async */
> +static void fw_cfg_wait_for_control(struct fw_cfg_dma *d)
> +{
> + do {
> + u32 ctrl = be32_to_cpu(READ_ONCE(d->control));
> +
> + if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0)
> + return;
> +
> + usleep_range(50, 100);
> + } while (true);
> +}
> +
> +static ssize_t fw_cfg_dma_transfer(struct device *dev,
> + void *address, u32 length, u32 control)
> +{
> + phys_addr_t dma;
> + struct fw_cfg_dma *d = NULL;
> + ssize_t ret = length;
> +
> + d = kmalloc(sizeof(*d), GFP_KERNEL);
> + if (!d) {
> + ret = -ENOMEM;
> + goto end;
> + }
> +
> + *d = (struct fw_cfg_dma) {
> + .address = cpu_to_be64(virt_to_phys(address)),
> + .length = cpu_to_be32(length),
> + .control = cpu_to_be32(control)
> + };
> +
> + dma = virt_to_phys(d);
> +
> + iowrite32be((u64)dma >> 32, fw_cfg_reg_dma);
> + iowrite32be(dma, fw_cfg_reg_dma + 4);
We can do it with iowrite64be(virt_to_phys(d)) too? In all cases I
think it's good enough and no worth for a repost.
For the DMA transfer part:
Acked-by: Peter Xu <peterx@redhat.com>
Thanks,
--
Peter Xu
WARNING: multiple messages have this Message-ID (diff)
From: Peter Xu <peterx@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: linux-kernel@vger.kernel.org, bhe@redhat.com, slp@redhat.com,
mst@redhat.com, somlo@cmu.edu, xiaolong.ye@intel.com,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v10 2/4] fw_cfg: do DMA read operation
Date: Wed, 24 Jan 2018 11:25:05 +0800 [thread overview]
Message-ID: <20180124032505.GD8001@xz-mi> (raw)
In-Reply-To: <20180123164041.30339-3-marcandre.lureau@redhat.com>
On Tue, Jan 23, 2018 at 05:40:39PM +0100, Marc-André Lureau wrote:
> Modify fw_cfg_read_blob() to use DMA if the device supports it.
> Return errors, because the operation may fail.
>
> The DMA operation is expected to run synchronously with today qemu,
> but the specification states that it may become async, so we run
> "control" field check in a loop for eventual changes.
>
> We may want to switch all the *buf addresses to use only kmalloc'ed
> buffers (instead of using stack/image addresses with dma=false).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> drivers/firmware/qemu_fw_cfg.c | 131 ++++++++++++++++++++++++++++++++++-------
> 1 file changed, 111 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> index 740df0df2260..686f0e839858 100644
> --- a/drivers/firmware/qemu_fw_cfg.c
> +++ b/drivers/firmware/qemu_fw_cfg.c
> @@ -33,6 +33,7 @@
> #include <linux/slab.h>
> #include <linux/io.h>
> #include <linux/ioport.h>
> +#include <linux/delay.h>
>
> MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");
> MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
> @@ -43,12 +44,22 @@ MODULE_LICENSE("GPL");
> #define FW_CFG_ID 0x01
> #define FW_CFG_FILE_DIR 0x19
>
> +#define FW_CFG_VERSION_DMA 0x02
> +#define FW_CFG_DMA_CTL_ERROR 0x01
> +#define FW_CFG_DMA_CTL_READ 0x02
> +#define FW_CFG_DMA_CTL_SKIP 0x04
> +#define FW_CFG_DMA_CTL_SELECT 0x08
> +#define FW_CFG_DMA_CTL_WRITE 0x10
> +
> /* size in bytes of fw_cfg signature */
> #define FW_CFG_SIG_SIZE 4
>
> /* fw_cfg "file name" is up to 56 characters (including terminating nul) */
> #define FW_CFG_MAX_FILE_PATH 56
>
> +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
> +static u32 fw_cfg_rev;
> +
> /* fw_cfg file directory entry type */
> struct fw_cfg_file {
> u32 size;
> @@ -57,6 +68,12 @@ struct fw_cfg_file {
> char name[FW_CFG_MAX_FILE_PATH];
> };
>
> +struct fw_cfg_dma {
> + u32 control;
> + u32 length;
> + u64 address;
> +} __packed;
> +
> /* fw_cfg device i/o register addresses */
> static bool fw_cfg_is_mmio;
> static phys_addr_t fw_cfg_p_base;
> @@ -75,12 +92,68 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
> return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key);
> }
>
> +static inline bool fw_cfg_dma_enabled(void)
> +{
> + return fw_cfg_rev & FW_CFG_VERSION_DMA && fw_cfg_reg_dma;
> +}
> +
> +/* qemu fw_cfg device is sync today, but spec says it may become async */
> +static void fw_cfg_wait_for_control(struct fw_cfg_dma *d)
> +{
> + do {
> + u32 ctrl = be32_to_cpu(READ_ONCE(d->control));
> +
> + if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0)
> + return;
> +
> + usleep_range(50, 100);
> + } while (true);
> +}
> +
> +static ssize_t fw_cfg_dma_transfer(struct device *dev,
> + void *address, u32 length, u32 control)
> +{
> + phys_addr_t dma;
> + struct fw_cfg_dma *d = NULL;
> + ssize_t ret = length;
> +
> + d = kmalloc(sizeof(*d), GFP_KERNEL);
> + if (!d) {
> + ret = -ENOMEM;
> + goto end;
> + }
> +
> + *d = (struct fw_cfg_dma) {
> + .address = cpu_to_be64(virt_to_phys(address)),
> + .length = cpu_to_be32(length),
> + .control = cpu_to_be32(control)
> + };
> +
> + dma = virt_to_phys(d);
> +
> + iowrite32be((u64)dma >> 32, fw_cfg_reg_dma);
> + iowrite32be(dma, fw_cfg_reg_dma + 4);
We can do it with iowrite64be(virt_to_phys(d)) too? In all cases I
think it's good enough and no worth for a repost.
For the DMA transfer part:
Acked-by: Peter Xu <peterx@redhat.com>
Thanks,
--
Peter Xu
next prev parent reply other threads:[~2018-01-24 3:25 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-23 16:40 [PATCH v10 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support Marc-André Lureau
2018-01-23 16:40 ` [Qemu-devel] " Marc-André Lureau
2018-01-23 16:40 ` [PATCH v10 1/4] fw_cfg: add DMA register Marc-André Lureau
2018-01-23 16:40 ` [Qemu-devel] " Marc-André Lureau
2018-01-23 16:40 ` [PATCH v10 2/4] fw_cfg: do DMA read operation Marc-André Lureau
2018-01-23 16:40 ` [Qemu-devel] " Marc-André Lureau
2018-01-24 3:25 ` Peter Xu [this message]
2018-01-24 3:25 ` Peter Xu
2018-01-24 10:29 ` Marc-Andre Lureau
2018-01-24 10:29 ` [Qemu-devel] " Marc-Andre Lureau
2018-01-23 16:40 ` [PATCH v10 3/4] crash: export paddr_vmcoreinfo_note() Marc-André Lureau
2018-01-23 16:40 ` [Qemu-devel] " Marc-André Lureau
2018-01-23 16:40 ` [PATCH v10 4/4] fw_cfg: write vmcoreinfo details Marc-André Lureau
2018-01-23 16:40 ` [Qemu-devel] " Marc-André Lureau
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=20180124032505.GD8001@xz-mi \
--to=peterx@redhat.com \
--cc=bhe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=marcandre.lureau@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--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.