All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: qemu-devel Developers <qemu-devel@nongnu.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Joerg Roedel <Joerg.Roedel@amd.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Sebastian Herbszt <herbszt@gmx.de>
Subject: [Qemu-devel] [PATCH 4/8] ahci: use qiov instead of dma helpers
Date: Mon, 20 Dec 2010 22:13:20 +0100	[thread overview]
Message-ID: <1292879604-22268-5-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1292879604-22268-1-git-send-email-agraf@suse.de>

The DMA helpers incur additional overhead on data transfers. I'm not
sure we need the additional complexity provided by them. So let's just
use qiovs directly when running in the fast path (ncq).

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/ide/ahci.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 hw/ide/ahci.h |    3 ++
 2 files changed, 95 insertions(+), 8 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index fa97f9b..7a29925 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -642,6 +642,87 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
     }
 }
 
+static int ahci_iov_destroy(AHCIDevice *ad, QEMUIOVector *qiov, int is_write)
+{
+    int i;
+    struct iovec *iov = qiov->iov;
+
+    for (i = 0; i < qiov->niov; i++) {
+        /* flags_size is zero-based */
+        cpu_physical_memory_unmap(iov[i].iov_base, !is_write,
+                                  iov[i].iov_len, iov[i].iov_len);
+    }
+
+    return 0;
+}
+
+static int ahci_populate_iov(AHCIDevice *ad, NCQTransferState *ncq_tfs,
+                             int is_write)
+{
+    QEMUIOVector *qiov = &ncq_tfs->qiov;
+    struct iovec *iov;
+    AHCICmdHdr *cmd = ad->cur_cmd;
+    uint32_t opts = le32_to_cpu(cmd->opts);
+    uint64_t prdt_addr = le64_to_cpu(cmd->tbl_addr) + 0x80;
+    int sglist_alloc_hint = opts >> AHCI_CMD_HDR_PRDT_LEN;
+    target_phys_addr_t prdt_len = (sglist_alloc_hint * sizeof(AHCI_SG));
+    target_phys_addr_t real_prdt_len = prdt_len;
+    uint8_t *prdt;
+    int i;
+    int r = 0;
+
+    if (!sglist_alloc_hint) {
+        DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
+        return -1;
+    }
+
+    /* map PRDT */
+    if (!(prdt = cpu_physical_memory_map(prdt_addr, &prdt_len, 0))){
+        DPRINTF(ad->port_no, "map failed\n");
+        return -1;
+    }
+
+    if (prdt_len < real_prdt_len) {
+        DPRINTF(ad->port_no, "mapped less than expected\n");
+        r = -1;
+        goto out;
+    }
+
+    /* Ensure we have enough space to store the iovecs */
+    if (ncq_tfs->iov_max < sglist_alloc_hint) {
+        ncq_tfs->iov = qemu_realloc(ncq_tfs->iov,
+                                    sglist_alloc_hint * sizeof(struct iovec));
+        ncq_tfs->iov_max = sglist_alloc_hint;
+    }
+    iov = ncq_tfs->iov;
+
+    if (!iov) {
+        DPRINTF(ad->port_no, "out of memory\n");
+        ncq_tfs->iov_max = 0;
+        goto out;
+    }
+
+    /* Get entries in the PRDT, init a qemu sglist accordingly */
+    if (sglist_alloc_hint > 0) {
+        AHCI_SG *tbl = (AHCI_SG *)prdt;
+        void *p;
+
+        for (i = 0; i < sglist_alloc_hint; i++) {
+            target_phys_addr_t len;
+            /* flags_size is zero-based */
+            len = iov[i].iov_len = le32_to_cpu(tbl[i].flags_size) + 1;
+            p = cpu_physical_memory_map(le64_to_cpu(tbl[i].addr),
+                                        &len, !is_write);
+            iov[i].iov_base = p;
+        }
+        qemu_iovec_init_external(qiov, iov, sglist_alloc_hint);
+    }
+
+out:
+    cpu_physical_memory_unmap(prdt, 0, prdt_len, prdt_len);
+    return r;
+}
+
 static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
 {
     AHCICmdHdr *cmd = ad->cur_cmd;
@@ -711,7 +792,7 @@ static void ncq_cb(void *opaque, int ret)
     DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n",
             ncq_tfs->tag);
 
-    qemu_sglist_destroy(&ncq_tfs->sglist);
+    ahci_iov_destroy(ncq_tfs->drive, &ncq_tfs->qiov, !ncq_tfs->is_read);
     ncq_tfs->used = 0;
 }
 
@@ -747,7 +828,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             ncq_tfs->lba, ncq_tfs->lba + ncq_tfs->sector_count - 2,
             s->dev[port].port.ifs[0].nb_sectors - 1);
 
-    ahci_populate_sglist(&s->dev[port], &ncq_tfs->sglist);
     ncq_tfs->tag = tag;
 
     switch(ncq_fis->command) {
@@ -757,9 +837,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             ncq_tfs->is_read = 1;
 
             DPRINTF(port, "tag %d aio read %ld\n", ncq_tfs->tag, ncq_tfs->lba);
-            ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs,
-                                           &ncq_tfs->sglist, ncq_tfs->lba,
-                                           ncq_cb, ncq_tfs);
+            ahci_populate_iov(&s->dev[port], ncq_tfs, 0);
+            ncq_tfs->aiocb = bdrv_aio_readv(ncq_tfs->drive->port.ifs[0].bs,
+                                            ncq_tfs->lba, &ncq_tfs->qiov,
+                                            ncq_tfs->sector_count, ncq_cb,
+                                            ncq_tfs);
             break;
         case WRITE_FPDMA_QUEUED:
             DPRINTF(port, "NCQ writing %d sectors to LBA %ld, tag %d\n",
@@ -767,9 +849,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             ncq_tfs->is_read = 0;
 
             DPRINTF(port, "tag %d aio write %ld\n", ncq_tfs->tag, ncq_tfs->lba);
-            ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs,
-                                            &ncq_tfs->sglist, ncq_tfs->lba,
-                                            ncq_cb, ncq_tfs);
+            ahci_populate_iov(&s->dev[port], ncq_tfs, 1);
+            ncq_tfs->aiocb = bdrv_aio_writev(ncq_tfs->drive->port.ifs[0].bs,
+                                             ncq_tfs->lba, &ncq_tfs->qiov,
+                                             ncq_tfs->sector_count, ncq_cb,
+                                             ncq_tfs);
             break;
         default:
             DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n");
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 5f8126a..0824064 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -243,6 +243,9 @@ typedef struct NCQTransferState {
     uint8_t tag;
     int slot;
     int used;
+    QEMUIOVector qiov;
+    struct iovec *iov;
+    int iov_max;
 } NCQTransferState;
 
 struct AHCIDevice {
-- 
1.6.0.2

  parent reply	other threads:[~2010-12-20 21:13 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-20 21:13 [Qemu-devel] [PATCH 0/8] Some more AHCI work Alexander Graf
2010-12-20 21:13 ` [Qemu-devel] [PATCH 1/8] ahci: split ICH9 from core Alexander Graf
2010-12-23  8:23   ` Stefan Hajnoczi
2010-12-23 10:32     ` Alexander Graf
2010-12-27 11:51       ` Sebastian Herbszt
2010-12-20 21:13 ` [Qemu-devel] [PATCH 2/8] ahci: split ICH and AHCI even more Alexander Graf
2011-01-18 12:19   ` [Qemu-devel] " Kevin Wolf
2011-02-01 14:12     ` Alexander Graf
2010-12-20 21:13 ` [Qemu-devel] [PATCH 3/8] ahci: send init d2h fis on fis enable Alexander Graf
2011-01-18 12:25   ` [Qemu-devel] " Kevin Wolf
2011-01-18 12:42     ` Alexander Graf
2010-12-20 21:13 ` Alexander Graf [this message]
2011-01-18 12:35   ` [Qemu-devel] Re: [PATCH 4/8] ahci: use qiov instead of dma helpers Kevin Wolf
2011-01-18 12:45     ` Alexander Graf
2011-01-18 13:14       ` Stefan Hajnoczi
2011-01-18 13:30         ` Kevin Wolf
2010-12-20 21:13 ` [Qemu-devel] [PATCH 5/8] ahci: Implement HBA reset Alexander Graf
2010-12-20 21:13 ` [Qemu-devel] [PATCH 6/8] ahci: make number of ports runtime determined Alexander Graf
2011-01-18 12:40   ` [Qemu-devel] " Kevin Wolf
2011-01-18 12:46     ` Alexander Graf
2011-01-18 13:33       ` Kevin Wolf
2011-01-18 13:09     ` Gerd Hoffmann
2010-12-20 21:13 ` [Qemu-devel] [PATCH 7/8] ahci: free dynamically allocated iovs Alexander Graf
2011-01-18 12:41   ` [Qemu-devel] " Kevin Wolf
2010-12-20 21:13 ` [Qemu-devel] [PATCH 8/8] ahci: fix !msi interrupts Alexander Graf
2011-01-17 14:37   ` [Qemu-devel] " Jan Kiszka
2011-01-17 16:00     ` Alexander Graf
2011-01-17 16:03       ` Jan Kiszka
2011-01-17 16:04         ` Alexander Graf
2011-01-17 16:20           ` Jan Kiszka
2011-01-17 16:33             ` Alexander Graf
2011-01-17 16:48               ` Jan Kiszka
2011-01-17 16:50                 ` Alexander Graf
2011-01-18  9:08               ` Gerd Hoffmann
2011-01-18 12:05                 ` Alexander Graf
2011-01-18 12:58                   ` Jan Kiszka
2011-01-22 13:13                     ` Aurelien Jarno
2011-01-22 14:14                       ` Edgar E. Iglesias
2011-01-22 14:32                         ` Alexander Graf
2011-01-22 14:40                           ` Aurelien Jarno
2011-01-23  3:34                             ` Edgar E. Iglesias
2011-01-22 14:28                       ` Alexander Graf
2011-01-22 14:34                         ` Aurelien Jarno
2011-01-18 13:02                   ` Gerd Hoffmann
2011-01-17 13:25 ` [Qemu-devel] [PATCH 0/8] Some more AHCI work Gerd Hoffmann

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=1292879604-22268-5-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=Joerg.Roedel@amd.com \
    --cc=herbszt@gmx.de \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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.