All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v4 00/18] virtio-scsi driver
@ 2012-02-22 14:33 Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent Paolo Bonzini
                   ` (18 more replies)
  0 siblings, 19 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Anthony,

the following changes since commit 99c7f87826337fa81f2f0f9baa9ca0a44faf90e9:

  input: send kbd+mouse events only to running guests. (2012-02-17 11:02:55 -0600)

are available in the git repository at:
  git://github.com/bonzini/qemu.git virtio-scsi

Kevin agreed on getting virtio-scsi in via a pull request, now
that the code has been reviewed by Stefan Hajnoczi (virtio-scsi bits),
Laszlo Ersek and Orit Wassermann.  Laszlo and Orit found problems
in patches 2 and 14, which are fixed in this pull request.  In
fact they reviewed almost all SCSI changes that went in since 0.15
(!) and found two bugs in scsi-bus.c, fixed in patches 16/17.

Paolo Bonzini (16):
      dma-helpers: make QEMUSGList target independent
      dma-helpers: add dma_buf_read and dma_buf_write
      dma-helpers: add accounting wrappers
      ahci: use new DMA helpers
      scsi: pass residual amount to command_complete
      scsi: add scatter/gather functionality
      scsi-disk: enable scatter/gather functionality
      scsi: add SCSIDevice vmstate definitions
      scsi-generic: add migration support
      scsi-disk: add migration support
      virtio-scsi: add basic SCSI bus operation
      virtio-scsi: process control queue requests
      virtio-scsi: add migration support
      scsi: fix wrong return for target INQUIRY
      scsi: fix searching for an empty id
      scsi-block: always use scsi_generic_ops for cache != none

Stefan Hajnoczi (2):
      virtio-scsi: Add virtio-scsi stub device
      virtio-scsi: Add basic request processing infrastructure

 Makefile.target                   |    1 +
 default-configs/pci.mak           |    1 +
 default-configs/s390x-softmmu.mak |    1 +
 dma-helpers.c                     |   37 +++
 dma.h                             |   20 +-
 hw/esp.c                          |    3 +-
 hw/ide/ahci.c                     |   82 +----
 hw/lsi53c895a.c                   |    2 +-
 hw/pci.h                          |    1 +
 hw/s390-virtio-bus.c              |   33 ++
 hw/s390-virtio-bus.h              |    2 +
 hw/scsi-bus.c                     |  159 +++++++++-
 hw/scsi-disk.c                    |  138 +++++++--
 hw/scsi-generic.c                 |   25 ++
 hw/scsi.h                         |   22 ++-
 hw/spapr_vscsi.c                  |    2 +-
 hw/usb-msd.c                      |    2 +-
 hw/virtio-pci.c                   |   56 ++++
 hw/virtio-pci.h                   |    2 +
 hw/virtio-scsi.c                  |  617 +++++++++++++++++++++++++++++++++++++
 hw/virtio-scsi.h                  |   36 +++
 hw/virtio.h                       |    3 +
 22 files changed, 1132 insertions(+), 113 deletions(-)
 create mode 100644 hw/virtio-scsi.c
 create mode 100644 hw/virtio-scsi.h
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 02/18] dma-helpers: add dma_buf_read and dma_buf_write Paolo Bonzini
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

scsi-disk will manage scatter/gather list, but it does not create
single entries so it remains target-independent.  Make QEMUSGList
available to it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma.h |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/dma.h b/dma.h
index a13209d..d50019b 100644
--- a/dma.h
+++ b/dma.h
@@ -17,6 +17,13 @@
 
 typedef struct ScatterGatherEntry ScatterGatherEntry;
 
+struct QEMUSGList {
+    ScatterGatherEntry *sg;
+    int nsg;
+    int nalloc;
+    size_t size;
+};
+
 #if defined(TARGET_PHYS_ADDR_BITS)
 typedef target_phys_addr_t dma_addr_t;
 
@@ -32,13 +39,6 @@ struct ScatterGatherEntry {
     dma_addr_t len;
 };
 
-struct QEMUSGList {
-    ScatterGatherEntry *sg;
-    int nsg;
-    int nalloc;
-    dma_addr_t size;
-};
-
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 02/18] dma-helpers: add dma_buf_read and dma_buf_write
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 03/18] dma-helpers: add accounting wrappers Paolo Bonzini
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

These helpers do a full transfer from an in-memory buffer to target
memory, with support for scatter/gather lists.  It will be used to
store the reply of an emulated command into a QEMUSGList provided by
the adapter.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c |   31 +++++++++++++++++++++++++++++++
 dma.h         |    3 +++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index f08cdb5..df0a421 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -204,3 +204,34 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
 {
     return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, true);
 }
+
+
+static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg, bool to_dev)
+{
+    uint64_t resid;
+    int sg_cur_index;
+
+    resid = sg->size;
+    sg_cur_index = 0;
+    len = MIN(len, resid);
+    while (len > 0) {
+        ScatterGatherEntry entry = sg->sg[sg_cur_index++];
+        int32_t xfer = MIN(len, entry.len);
+        cpu_physical_memory_rw(entry.base, ptr, xfer, !to_dev);
+        ptr += xfer;
+        len -= xfer;
+        resid -= xfer;
+    }
+
+    return resid;
+}
+
+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg)
+{
+    return dma_buf_rw(ptr, len, sg, 0);
+}
+
+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg)
+{
+    return dma_buf_rw(ptr, len, sg, 1);
+}
diff --git a/dma.h b/dma.h
index d50019b..346ac4f 100644
--- a/dma.h
+++ b/dma.h
@@ -58,4 +58,7 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
 BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
                                  QEMUSGList *sg, uint64_t sector,
                                  BlockDriverCompletionFunc *cb, void *opaque);
+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
+
 #endif
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 03/18] dma-helpers: add accounting wrappers
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 02/18] dma-helpers: add dma_buf_read and dma_buf_write Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 04/18] ahci: use new DMA helpers Paolo Bonzini
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

The length of the transfer is already in the sglist, the wrapper simply
fetches it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c |    6 ++++++
 dma.h         |    3 +++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index df0a421..c29ea6d 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -235,3 +235,9 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg)
 {
     return dma_buf_rw(ptr, len, sg, 1);
 }
+
+void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
+                    QEMUSGList *sg, enum BlockAcctType type)
+{
+    bdrv_acct_start(bs, cookie, sg->size, type);
+}
diff --git a/dma.h b/dma.h
index 346ac4f..20e86d2 100644
--- a/dma.h
+++ b/dma.h
@@ -61,4 +61,7 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
 uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 
+void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
+                    QEMUSGList *sg, enum BlockAcctType type);
+
 #endif
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 04/18] ahci: use new DMA helpers
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (2 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 03/18] dma-helpers: add accounting wrappers Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 05/18] scsi: pass residual amount to command_complete Paolo Bonzini
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/ahci.c |   82 +++++++++------------------------------------------------
 1 files changed, 13 insertions(+), 69 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index b515f41..041ce1e 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -428,55 +428,6 @@ static void ahci_reg_init(AHCIState *s)
     }
 }
 
-static uint32_t read_from_sglist(uint8_t *buffer, uint32_t len,
-                                 QEMUSGList *sglist)
-{
-    uint32_t i = 0;
-    uint32_t total = 0, once;
-    ScatterGatherEntry *cur_prd;
-    uint32_t sgcount;
-
-    cur_prd = sglist->sg;
-    sgcount = sglist->nsg;
-    for (i = 0; len && sgcount; i++) {
-        once = MIN(cur_prd->len, len);
-        cpu_physical_memory_read(cur_prd->base, buffer, once);
-        cur_prd++;
-        sgcount--;
-        len -= once;
-        buffer += once;
-        total += once;
-    }
-
-    return total;
-}
-
-static uint32_t write_to_sglist(uint8_t *buffer, uint32_t len,
-                                QEMUSGList *sglist)
-{
-    uint32_t i = 0;
-    uint32_t total = 0, once;
-    ScatterGatherEntry *cur_prd;
-    uint32_t sgcount;
-
-    DPRINTF(-1, "total: 0x%x bytes\n", len);
-
-    cur_prd = sglist->sg;
-    sgcount = sglist->nsg;
-    for (i = 0; len && sgcount; i++) {
-        once = MIN(cur_prd->len, len);
-        DPRINTF(-1, "write 0x%x bytes to 0x%lx\n", once, (long)cur_prd->base);
-        cpu_physical_memory_write(cur_prd->base, buffer, once);
-        cur_prd++;
-        sgcount--;
-        len -= once;
-        buffer += once;
-        total += once;
-    }
-
-    return total;
-}
-
 static void check_cmd(AHCIState *s, int port)
 {
     AHCIPortRegs *pr = &s->dev[port].port_regs;
@@ -802,9 +753,8 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             DPRINTF(port, "tag %d aio read %"PRId64"\n",
                     ncq_tfs->tag, ncq_tfs->lba);
 
-            bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
-                            (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE,
-                            BDRV_ACCT_READ);
+            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
+                           &ncq_tfs->sglist, BDRV_ACCT_READ);
             ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs,
                                            &ncq_tfs->sglist, ncq_tfs->lba,
                                            ncq_cb, ncq_tfs);
@@ -816,9 +766,8 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             DPRINTF(port, "tag %d aio write %"PRId64"\n",
                     ncq_tfs->tag, ncq_tfs->lba);
 
-            bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
-                            (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE,
-                            BDRV_ACCT_WRITE);
+            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
+                           &ncq_tfs->sglist, BDRV_ACCT_WRITE);
             ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs,
                                             &ncq_tfs->sglist, ncq_tfs->lba,
                                             ncq_cb, ncq_tfs);
@@ -1023,12 +972,12 @@ static int ahci_start_transfer(IDEDMA *dma)
             is_write ? "writ" : "read", size, is_atapi ? "atapi" : "ata",
             has_sglist ? "" : "o");
 
-    if (is_write && has_sglist && (s->data_ptr < s->data_end)) {
-        read_from_sglist(s->data_ptr, size, &s->sg);
-    }
-
-    if (!is_write && has_sglist && (s->data_ptr < s->data_end)) {
-        write_to_sglist(s->data_ptr, size, &s->sg);
+    if (has_sglist && size) {
+        if (is_write) {
+            dma_buf_write(s->data_ptr, size, &s->sg);
+        } else {
+            dma_buf_read(s->data_ptr, size, &s->sg);
+        }
     }
 
     /* update number of transferred bytes */
@@ -1067,14 +1016,9 @@ static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
 {
     AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
     IDEState *s = &ad->port.ifs[0];
-    int i;
 
     ahci_populate_sglist(ad, &s->sg);
-
-    s->io_buffer_size = 0;
-    for (i = 0; i < s->sg.nsg; i++) {
-        s->io_buffer_size += s->sg.sg[i].len;
-    }
+    s->io_buffer_size = s->sg.size;
 
     DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
     return s->io_buffer_size != 0;
@@ -1092,9 +1036,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
     }
 
     if (is_write) {
-        write_to_sglist(p, l, &s->sg);
+        dma_buf_read(p, l, &s->sg);
     } else {
-        read_from_sglist(p, l, &s->sg);
+        dma_buf_write(p, l, &s->sg);
     }
 
     /* update number of transferred bytes */
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 05/18] scsi: pass residual amount to command_complete
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (3 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 04/18] ahci: use new DMA helpers Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 06/18] scsi: add scatter/gather functionality Paolo Bonzini
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

With the upcoming sglist support, HBAs will not see any transfer_data
call and will not have a way to detect short transfers.  So pass the
residual amount of data upon command completion.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/esp.c         |    3 ++-
 hw/lsi53c895a.c  |    2 +-
 hw/scsi-bus.c    |   12 ++++++++----
 hw/scsi.h        |    3 ++-
 hw/spapr_vscsi.c |    2 +-
 hw/usb-msd.c     |    2 +-
 6 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/hw/esp.c b/hw/esp.c
index 2dda8e3..8d73e56 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -390,7 +390,8 @@ static void esp_do_dma(ESPState *s)
     esp_dma_done(s);
 }
 
-static void esp_command_complete(SCSIRequest *req, uint32_t status)
+static void esp_command_complete(SCSIRequest *req, uint32_t status,
+                                 size_t resid)
 {
     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 0acd1d0..edc09b7 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -699,7 +699,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
 }
 
  /* Callback to indicate that the SCSI layer has completed a command.  */
-static void lsi_command_complete(SCSIRequest *req, uint32_t status)
+static void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
 {
     LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
     int out;
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index b3e97ce..eb97c87 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -533,6 +533,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
     }
 
     req->cmd = cmd;
+    req->resid = req->cmd.xfer;
+
     switch (buf[0]) {
     case INQUIRY:
         trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
@@ -1275,10 +1277,12 @@ void scsi_req_data(SCSIRequest *req, int len)
 {
     if (req->io_canceled) {
         trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
-    } else {
-        trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
-        req->bus->info->transfer_data(req, len);
+        return;
     }
+    trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
+    assert(req->cmd.mode != SCSI_XFER_NONE);
+    req->resid -= len;
+    req->bus->info->transfer_data(req, len);
 }
 
 void scsi_req_print(SCSIRequest *req)
@@ -1337,7 +1341,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
 
     scsi_req_ref(req);
     scsi_req_dequeue(req);
-    req->bus->info->complete(req, req->status);
+    req->bus->info->complete(req, req->status, req->resid);
     scsi_req_unref(req);
 }
 
diff --git a/hw/scsi.h b/hw/scsi.h
index dc72b6f..8722ef9 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -46,6 +46,7 @@ struct SCSIRequest {
     uint32_t          tag;
     uint32_t          lun;
     uint32_t          status;
+    size_t            resid;
     SCSICommand       cmd;
     BlockDriverAIOCB  *aiocb;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
@@ -112,7 +113,7 @@ struct SCSIBusInfo {
     int tcq;
     int max_channel, max_target, max_lun;
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
-    void (*complete)(SCSIRequest *req, uint32_t arg);
+    void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
     void (*cancel)(SCSIRequest *req);
 };
 
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index ffce261..2167017 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -494,7 +494,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 }
 
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
-static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
+static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid)
 {
     VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
     vscsi_req *req = sreq->hba_private;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index c933efe..5fbd2d0 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -223,7 +223,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     }
 }
 
-static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
+static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
 {
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
     USBPacket *p = s->packet;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 06/18] scsi: add scatter/gather functionality
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (4 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 05/18] scsi: pass residual amount to command_complete Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 07/18] scsi-disk: enable " Paolo Bonzini
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Scatter/gather functionality uses the newly added DMA helpers.  The
device can choose between doing DMA itself, or calling scsi_req_data
as usual, which will use the newly added DMA helpers to copy piecewise
to/from the destination area(s).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |   28 ++++++++++++++++++++++++++--
 hw/scsi.h     |    3 +++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index eb97c87..0c471e0 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -5,6 +5,7 @@
 #include "qdev.h"
 #include "blockdev.h"
 #include "trace.h"
+#include "dma.h"
 
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
@@ -651,6 +652,11 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
 
     assert(!req->enqueued);
     scsi_req_ref(req);
+    if (req->bus->info->get_sg_list) {
+        req->sg = req->bus->info->get_sg_list(req);
+    } else {
+        req->sg = NULL;
+    }
     req->enqueued = true;
     QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
 
@@ -1275,14 +1281,32 @@ void scsi_req_continue(SCSIRequest *req)
    Once it completes, calling scsi_req_continue will restart I/O.  */
 void scsi_req_data(SCSIRequest *req, int len)
 {
+    uint8_t *buf;
     if (req->io_canceled) {
         trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
         return;
     }
     trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
     assert(req->cmd.mode != SCSI_XFER_NONE);
-    req->resid -= len;
-    req->bus->info->transfer_data(req, len);
+    if (!req->sg) {
+        req->resid -= len;
+        req->bus->info->transfer_data(req, len);
+        return;
+    }
+
+    /* If the device calls scsi_req_data and the HBA specified a
+     * scatter/gather list, the transfer has to happen in a single
+     * step.  */
+    assert(!req->dma_started);
+    req->dma_started = true;
+
+    buf = scsi_req_get_buf(req);
+    if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
+        req->resid = dma_buf_read(buf, len, req->sg);
+    } else {
+        req->resid = dma_buf_write(buf, len, req->sg);
+    }
+    scsi_req_continue(req);
 }
 
 void scsi_req_print(SCSIRequest *req)
diff --git a/hw/scsi.h b/hw/scsi.h
index 8722ef9..34cdba8 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -49,6 +49,8 @@ struct SCSIRequest {
     size_t            resid;
     SCSICommand       cmd;
     BlockDriverAIOCB  *aiocb;
+    QEMUSGList        *sg;
+    bool              dma_started;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
     uint32_t sense_len;
     bool enqueued;
@@ -115,6 +117,7 @@ struct SCSIBusInfo {
     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
     void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
     void (*cancel)(SCSIRequest *req);
+    QEMUSGList *(*get_sg_list)(SCSIRequest *req);
 };
 
 struct SCSIBus {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 07/18] scsi-disk: enable scatter/gather functionality
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (5 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 06/18] scsi: add scatter/gather functionality Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 08/18] scsi: add SCSIDevice vmstate definitions Paolo Bonzini
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c  |    1 +
 hw/scsi-disk.c |   63 ++++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 0c471e0..dce6208 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -87,6 +87,7 @@ static void scsi_dma_restart_bh(void *opaque)
                 scsi_req_continue(req);
                 break;
             case SCSI_XFER_NONE:
+                assert(!req->sg);
                 scsi_req_dequeue(req);
                 scsi_req_enqueue(req);
                 break;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c12e3a6..2a24840 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -38,6 +38,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 #include "sysemu.h"
 #include "blockdev.h"
 #include "block_int.h"
+#include "dma.h"
 
 #ifdef __linux
 #include <scsi/sg.h>
@@ -123,6 +124,27 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r)
     return r->qiov.size / 512;
 }
 
+static void scsi_dma_complete(void *opaque, int ret)
+{
+    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+
+    if (ret) {
+        if (scsi_handle_rw_error(r, -ret)) {
+            goto done;
+        }
+    }
+
+    r->sector += r->sector_count;
+    r->sector_count = 0;
+    scsi_req_complete(&r->req, GOOD);
+
+done:
+    scsi_req_unref(&r->req);
+}
+
 static void scsi_read_complete(void * opaque, int ret)
 {
     SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -213,10 +235,17 @@ static void scsi_read_data(SCSIRequest *req)
         return;
     }
 
-    n = scsi_init_iovec(r);
-    bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-    r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
-                              scsi_read_complete, r);
+    if (r->req.sg) {
+        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
+        r->req.resid -= r->req.sg->size;
+        r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
+                                     scsi_dma_complete, r);
+    } else {
+        n = scsi_init_iovec(r);
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+        r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
+                                      scsi_read_complete, r);
+    }
 }
 
 /*
@@ -315,18 +344,26 @@ static void scsi_write_data(SCSIRequest *req)
         return;
     }
 
-    n = r->qiov.size / 512;
-    if (n) {
-        if (s->tray_open) {
-            scsi_write_complete(r, -ENOMEDIUM);
-            return;
-        }
+    if (!r->req.sg && !r->qiov.size) {
+        /* Called for the first time.  Ask the driver to send us more data.  */
+        scsi_write_complete(r, 0);
+        return;
+    }
+    if (s->tray_open) {
+        scsi_write_complete(r, -ENOMEDIUM);
+        return;
+    }
+
+    if (r->req.sg) {
+        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
+        r->req.resid -= r->req.sg->size;
+        r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
+                                      scsi_dma_complete, r);
+    } else {
+        n = r->qiov.size / 512;
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
         r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
                                        scsi_write_complete, r);
-    } else {
-        /* Called for the first time.  Ask the driver to send us more data.  */
-        scsi_write_complete(r, 0);
     }
 }
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 08/18] scsi: add SCSIDevice vmstate definitions
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (6 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 07/18] scsi-disk: enable " Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 09/18] scsi-generic: add migration support Paolo Bonzini
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |  107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 hw/scsi.h     |   16 ++++++++
 2 files changed, 120 insertions(+), 3 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index dce6208..f0babb1 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -647,10 +647,8 @@ void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
     req->sense_len = 18;
 }
 
-int32_t scsi_req_enqueue(SCSIRequest *req)
+static void scsi_req_enqueue_internal(SCSIRequest *req)
 {
-    int32_t rc;
-
     assert(!req->enqueued);
     scsi_req_ref(req);
     if (req->bus->info->get_sg_list) {
@@ -660,7 +658,14 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
     }
     req->enqueued = true;
     QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
+}
 
+int32_t scsi_req_enqueue(SCSIRequest *req)
+{
+    int32_t rc;
+
+    assert(!req->retry);
+    scsi_req_enqueue_internal(req);
     scsi_req_ref(req);
     rc = req->ops->send_command(req, req->cmd.buf);
     scsi_req_unref(req);
@@ -1442,6 +1447,102 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
     return target_dev;
 }
 
+/* SCSI request list.  For simplicity, pv points to the whole device */
+
+static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
+{
+    SCSIDevice *s = pv;
+    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+    SCSIRequest *req;
+
+    QTAILQ_FOREACH(req, &s->requests, next) {
+        assert(!req->io_canceled);
+        assert(req->status == -1);
+        assert(req->retry);
+        assert(req->enqueued);
+
+        qemu_put_sbyte(f, 1);
+        qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
+        qemu_put_be32s(f, &req->tag);
+        qemu_put_be32s(f, &req->lun);
+        if (bus->info->save_request) {
+            bus->info->save_request(f, req);
+        }
+        if (req->ops->save_request) {
+            req->ops->save_request(f, req);
+        }
+    }
+    qemu_put_sbyte(f, 0);
+}
+
+static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
+{
+    SCSIDevice *s = pv;
+    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+
+    while (qemu_get_sbyte(f)) {
+        uint8_t buf[SCSI_CMD_BUF_SIZE];
+        uint32_t tag;
+        uint32_t lun;
+        SCSIRequest *req;
+
+        qemu_get_buffer(f, buf, sizeof(buf));
+        qemu_get_be32s(f, &tag);
+        qemu_get_be32s(f, &lun);
+        req = scsi_req_new(s, tag, lun, buf, NULL);
+        if (bus->info->load_request) {
+            req->hba_private = bus->info->load_request(f, req);
+        }
+        if (req->ops->load_request) {
+            req->ops->load_request(f, req);
+        }
+
+        /* Just restart it later.  */
+        req->retry = true;
+        scsi_req_enqueue_internal(req);
+
+        /* At this point, the request will be kept alive by the reference
+         * added by scsi_req_enqueue_internal, so we can release our reference.
+         * The HBA of course will add its own reference in the load_request
+         * callback if it needs to hold on the SCSIRequest.
+         */
+        scsi_req_unref(req);
+    }
+
+    return 0;
+}
+
+const VMStateInfo vmstate_info_scsi_requests = {
+    .name = "scsi-requests",
+    .get  = get_scsi_requests,
+    .put  = put_scsi_requests,
+};
+
+const VMStateDescription vmstate_scsi_device = {
+    .name = "SCSIDevice",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(unit_attention.key, SCSIDevice),
+        VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
+        VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
+        VMSTATE_BOOL(sense_is_ua, SCSIDevice),
+        VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE),
+        VMSTATE_UINT32(sense_len, SCSIDevice),
+        {
+            .name         = "requests",
+            .version_id   = 0,
+            .field_exists = NULL,
+            .size         = 0,   /* ouch */
+            .info         = &vmstate_info_scsi_requests,
+            .flags        = VMS_SINGLE,
+            .offset       = 0,
+        },
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void scsi_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
diff --git a/hw/scsi.h b/hw/scsi.h
index 34cdba8..2eb66f7 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -96,6 +96,16 @@ struct SCSIDevice
     uint64_t max_lba;
 };
 
+extern const VMStateDescription vmstate_scsi_device;
+
+#define VMSTATE_SCSI_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(SCSIDevice),                                \
+    .vmsd       = &vmstate_scsi_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, SCSIDevice),  \
+}
+
 /* cdrom.c */
 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
 int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
@@ -109,6 +119,9 @@ struct SCSIReqOps {
     void (*write_data)(SCSIRequest *req);
     void (*cancel_io)(SCSIRequest *req);
     uint8_t *(*get_buf)(SCSIRequest *req);
+
+    void (*save_request)(QEMUFile *f, SCSIRequest *req);
+    void (*load_request)(QEMUFile *f, SCSIRequest *req);
 };
 
 struct SCSIBusInfo {
@@ -118,6 +131,9 @@ struct SCSIBusInfo {
     void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
     void (*cancel)(SCSIRequest *req);
     QEMUSGList *(*get_sg_list)(SCSIRequest *req);
+
+    void (*save_request)(QEMUFile *f, SCSIRequest *req);
+    void *(*load_request)(QEMUFile *f, SCSIRequest *req);
 };
 
 struct SCSIBus {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 09/18] scsi-generic: add migration support
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (7 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 08/18] scsi: add SCSIDevice vmstate definitions Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 10/18] scsi-disk: " Paolo Bonzini
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-generic.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 86014aa..d856d23 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -59,6 +59,28 @@ typedef struct SCSIGenericReq {
     sg_io_hdr_t io_header;
 } SCSIGenericReq;
 
+static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
+{
+    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
+
+    qemu_put_sbe32s(f, &r->buflen);
+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+        assert(!r->req.sg);
+        qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
+    }
+}
+
+static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
+{
+    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
+
+    qemu_get_sbe32s(f, &r->buflen);
+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+        assert(!r->req.sg);
+        qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
+    }
+}
+
 static void scsi_free_request(SCSIRequest *req)
 {
     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
@@ -446,6 +468,8 @@ const SCSIReqOps scsi_generic_req_ops = {
     .write_data   = scsi_write_data,
     .cancel_io    = scsi_cancel_io,
     .get_buf      = scsi_get_buf,
+    .load_request = scsi_generic_load_request,
+    .save_request = scsi_generic_save_request,
 };
 
 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
@@ -474,6 +498,7 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "pass through generic scsi device (/dev/sg*)";
     dc->reset = scsi_generic_reset;
     dc->props = scsi_generic_properties;
+    dc->vmsd  = &vmstate_scsi_device;
 }
 
 static TypeInfo scsi_generic_info = {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 10/18] scsi-disk: add migration support
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (8 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 09/18] scsi-generic: add migration support Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 11/18] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2a24840..ec8e7cb 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -111,12 +111,12 @@ static void scsi_cancel_io(SCSIRequest *req)
     r->req.aiocb = NULL;
 }
 
-static uint32_t scsi_init_iovec(SCSIDiskReq *r)
+static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
 
     if (!r->iov.iov_base) {
-        r->buflen = SCSI_DMA_BUF_SIZE;
+        r->buflen = size;
         r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
     }
     r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
@@ -124,6 +124,35 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r)
     return r->qiov.size / 512;
 }
 
+static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
+{
+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+
+    qemu_put_be64s(f, &r->sector);
+    qemu_put_be32s(f, &r->sector_count);
+    qemu_put_be32s(f, &r->buflen);
+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+    }
+}
+
+static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
+{
+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+
+    qemu_get_be64s(f, &r->sector);
+    qemu_get_be32s(f, &r->sector_count);
+    qemu_get_be32s(f, &r->buflen);
+    if (r->buflen) {
+        scsi_init_iovec(r, r->buflen);
+        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        }
+    }
+
+    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
+}
+
 static void scsi_dma_complete(void *opaque, int ret)
 {
     SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -241,7 +270,7 @@ static void scsi_read_data(SCSIRequest *req)
         r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
                                      scsi_dma_complete, r);
     } else {
-        n = scsi_init_iovec(r);
+        n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
         r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
                                       scsi_read_complete, r);
@@ -316,7 +345,7 @@ static void scsi_write_complete(void * opaque, int ret)
     if (r->sector_count == 0) {
         scsi_req_complete(&r->req, GOOD);
     } else {
-        scsi_init_iovec(r);
+        scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
         DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
         scsi_req_data(&r->req, r->qiov.size);
     }
@@ -1621,6 +1650,8 @@ static const SCSIReqOps scsi_disk_reqops = {
     .write_data   = scsi_write_data,
     .cancel_io    = scsi_cancel_io,
     .get_buf      = scsi_get_buf,
+    .load_request = scsi_disk_load_request,
+    .save_request = scsi_disk_save_request,
 };
 
 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
@@ -1755,6 +1786,22 @@ static Property scsi_hd_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static const VMStateDescription vmstate_scsi_disk_state = {
+    .name = "scsi-disk",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
+        VMSTATE_BOOL(media_changed, SCSIDiskState),
+        VMSTATE_BOOL(media_event, SCSIDiskState),
+        VMSTATE_BOOL(eject_request, SCSIDiskState),
+        VMSTATE_BOOL(tray_open, SCSIDiskState),
+        VMSTATE_BOOL(tray_locked, SCSIDiskState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1768,6 +1815,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "virtual SCSI disk";
     dc->reset = scsi_disk_reset;
     dc->props = scsi_hd_properties;
+    dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
 static TypeInfo scsi_hd_info = {
@@ -1795,6 +1843,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "virtual SCSI CD-ROM";
     dc->reset = scsi_disk_reset;
     dc->props = scsi_cd_properties;
+    dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
 static TypeInfo scsi_cd_info = {
@@ -1822,6 +1871,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "SCSI block device passthrough";
     dc->reset = scsi_disk_reset;
     dc->props = scsi_block_properties;
+    dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
 static TypeInfo scsi_block_info = {
@@ -1851,6 +1901,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
     dc->reset = scsi_disk_reset;
     dc->props = scsi_disk_properties;
+    dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
 static TypeInfo scsi_disk_info = {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 11/18] virtio-scsi: Add virtio-scsi stub device
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (9 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 10/18] scsi-disk: " Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Add a useless virtio SCSI HBA device:

  qemu -device virtio-scsi-pci

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.target                   |    1 +
 default-configs/pci.mak           |    1 +
 default-configs/s390x-softmmu.mak |    1 +
 hw/pci.h                          |    1 +
 hw/s390-virtio-bus.c              |   33 ++++++
 hw/s390-virtio-bus.h              |    2 +
 hw/virtio-pci.c                   |   56 +++++++++
 hw/virtio-pci.h                   |    2 +
 hw/virtio-scsi.c                  |  228 +++++++++++++++++++++++++++++++++++++
 hw/virtio-scsi.h                  |   36 ++++++
 hw/virtio.h                       |    3 +
 11 files changed, 364 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-scsi.c
 create mode 100644 hw/virtio-scsi.h

diff --git a/Makefile.target b/Makefile.target
index 651500e..eef4acc 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -200,6 +200,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
 obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
+obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 9d3e1db..21e4ccf 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -1,5 +1,6 @@
 CONFIG_PCI=y
 CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_SCSI=y
 CONFIG_VIRTIO=y
 CONFIG_USB_UHCI=y
 CONFIG_USB_OHCI=y
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 3005729..e588803 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1 +1,2 @@
 CONFIG_VIRTIO=y
+CONFIG_VIRTIO_SCSI=y
diff --git a/hw/pci.h b/hw/pci.h
index 33b0b18..ff4c12d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -75,6 +75,7 @@
 #define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
+#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
 
 #define FMT_PCIBUS                      PRIx64
 
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 9d48056..c450e4b 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -169,6 +169,18 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev)
     return r;
 }
 
+static int s390_virtio_scsi_init(VirtIOS390Device *dev)
+{
+    VirtIODevice *vdev;
+
+    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
+    if (!vdev) {
+        return -1;
+    }
+
+    return s390_virtio_device_init(dev, vdev);
+}
+
 static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
 {
     ram_addr_t token_off;
@@ -433,6 +445,26 @@ static TypeInfo virtio_s390_device_info = {
     .abstract = true,
 };
 
+static Property s390_virtio_scsi_properties[] = {
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+    k->init = s390_virtio_scsi_init;
+    dc->props = s390_virtio_scsi_properties;
+}
+
+static TypeInfo s390_virtio_scsi = {
+    .name          = "virtio-scsi-s390",
+    .parent        = TYPE_VIRTIO_S390_DEVICE,
+    .instance_size = sizeof(VirtIOS390Device),
+    .class_init    = s390_virtio_scsi_class_init,
+};
 
 /***************** S390 Virtio Bus Bridge Device *******************/
 /* Only required to have the virtio bus as child in the system bus */
@@ -465,6 +497,7 @@ static void s390_virtio_register_types(void)
     type_register_static(&s390_virtio_serial);
     type_register_static(&s390_virtio_blk);
     type_register_static(&s390_virtio_net);
+    type_register_static(&s390_virtio_scsi);
     type_register_static(&s390_virtio_bridge_info);
 }
 
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index b5e59b7..0e60bc0 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -19,6 +19,7 @@
 
 #include "virtio-net.h"
 #include "virtio-serial.h"
+#include "virtio-scsi.h"
 
 #define VIRTIO_DEV_OFFS_TYPE		0	/* 8 bits */
 #define VIRTIO_DEV_OFFS_NUM_VQ		1	/* 8 bits */
@@ -67,6 +68,7 @@ struct VirtIOS390Device {
     uint32_t host_features;
     virtio_serial_conf serial;
     virtio_net_conf net;
+    VirtIOSCSIConf scsi;
 };
 
 typedef struct VirtIOS390Bus {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 907b52a..a0fb7c1 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -21,6 +21,7 @@
 #include "virtio-blk.h"
 #include "virtio-net.h"
 #include "virtio-serial.h"
+#include "virtio-scsi.h"
 #include "pci.h"
 #include "qemu-error.h"
 #include "msix.h"
@@ -930,12 +931,67 @@ static TypeInfo virtio_balloon_info = {
     .class_init    = virtio_balloon_class_init,
 };
 
+static int virtio_scsi_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
+    if (!vdev) {
+        return -EINVAL;
+    }
+
+    vdev->nvectors = proxy->nvectors;
+    virtio_init_pci(proxy, vdev);
+
+    /* make the actual value visible */
+    proxy->nvectors = vdev->nvectors;
+    return 0;
+}
+
+static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_scsi_exit(proxy->vdev);
+    return virtio_exit_pci(pci_dev);
+}
+
+static Property virtio_scsi_properties[] = {
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_scsi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_scsi_init_pci;
+    k->exit = virtio_scsi_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
+    k->revision = 0x00;
+    k->class_id = PCI_CLASS_STORAGE_SCSI;
+    dc->reset = virtio_pci_reset;
+    dc->props = virtio_scsi_properties;
+}
+
+static TypeInfo virtio_scsi_info = {
+    .name          = "virtio-scsi-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .class_init    = virtio_scsi_class_init,
+};
+
 static void virtio_pci_register_types(void)
 {
     type_register_static(&virtio_blk_info);
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
     type_register_static(&virtio_balloon_info);
+    type_register_static(&virtio_scsi_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index 344c22b..e560428 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -17,6 +17,7 @@
 
 #include "virtio-net.h"
 #include "virtio-serial.h"
+#include "virtio-scsi.h"
 
 /* Performance improves when virtqueue kick processing is decoupled from the
  * vcpu thread using ioeventfd for some devices. */
@@ -40,6 +41,7 @@ typedef struct {
 #endif
     virtio_serial_conf serial;
     virtio_net_conf net;
+    VirtIOSCSIConf scsi;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
 } VirtIOPCIProxy;
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
new file mode 100644
index 0000000..a297fed
--- /dev/null
+++ b/hw/virtio-scsi.c
@@ -0,0 +1,228 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ * Copyright Red Hat, Inc. 2011
+ *
+ * Authors:
+ *   Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *   Paolo Bonzini      <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio-scsi.h"
+#include <hw/scsi.h>
+#include <hw/scsi-defs.h>
+
+#define VIRTIO_SCSI_VQ_SIZE     128
+#define VIRTIO_SCSI_CDB_SIZE    32
+#define VIRTIO_SCSI_SENSE_SIZE  96
+#define VIRTIO_SCSI_MAX_CHANNEL 0
+#define VIRTIO_SCSI_MAX_TARGET  255
+#define VIRTIO_SCSI_MAX_LUN     16383
+
+/* Response codes */
+#define VIRTIO_SCSI_S_OK                       0
+#define VIRTIO_SCSI_S_OVERRUN                  1
+#define VIRTIO_SCSI_S_ABORTED                  2
+#define VIRTIO_SCSI_S_BAD_TARGET               3
+#define VIRTIO_SCSI_S_RESET                    4
+#define VIRTIO_SCSI_S_BUSY                     5
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
+#define VIRTIO_SCSI_S_TARGET_FAILURE           7
+#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
+#define VIRTIO_SCSI_S_FAILURE                  9
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
+#define VIRTIO_SCSI_S_INCORRECT_LUN            12
+
+/* Controlq type codes.  */
+#define VIRTIO_SCSI_T_TMF                      0
+#define VIRTIO_SCSI_T_AN_QUERY                 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
+
+/* Valid TMF subtypes.  */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
+
+/* Events.  */
+#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT                 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
+
+/* SCSI command request, followed by data-out */
+typedef struct {
+    uint8_t lun[8];              /* Logical Unit Number */
+    uint64_t tag;                /* Command identifier */
+    uint8_t task_attr;           /* Task attribute */
+    uint8_t prio;
+    uint8_t crn;
+    uint8_t cdb[];
+} QEMU_PACKED VirtIOSCSICmdReq;
+
+/* Response, followed by sense data and data-in */
+typedef struct {
+    uint32_t sense_len;          /* Sense data length */
+    uint32_t resid;              /* Residual bytes in data buffer */
+    uint16_t status_qualifier;   /* Status qualifier */
+    uint8_t status;              /* Command completion status */
+    uint8_t response;            /* Response values */
+    uint8_t sense[];
+} QEMU_PACKED VirtIOSCSICmdResp;
+
+/* Task Management Request */
+typedef struct {
+    uint32_t type;
+    uint32_t subtype;
+    uint8_t lun[8];
+    uint64_t tag;
+} QEMU_PACKED VirtIOSCSICtrlTMFReq;
+
+typedef struct {
+    uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlTMFResp;
+
+/* Asynchronous notification query/subscription */
+typedef struct {
+    uint32_t type;
+    uint8_t lun[8];
+    uint32_t event_requested;
+} QEMU_PACKED VirtIOSCSICtrlANReq;
+
+typedef struct {
+    uint32_t event_actual;
+    uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlANResp;
+
+typedef struct {
+    uint32_t event;
+    uint8_t lun[8];
+    uint32_t reason;
+} QEMU_PACKED VirtIOSCSIEvent;
+
+typedef struct {
+    uint32_t num_queues;
+    uint32_t seg_max;
+    uint32_t max_sectors;
+    uint32_t cmd_per_lun;
+    uint32_t event_info_size;
+    uint32_t sense_size;
+    uint32_t cdb_size;
+    uint16_t max_channel;
+    uint16_t max_target;
+    uint32_t max_lun;
+} QEMU_PACKED VirtIOSCSIConfig;
+
+typedef struct {
+    VirtIODevice vdev;
+    DeviceState *qdev;
+    VirtIOSCSIConf *conf;
+
+    VirtQueue *ctrl_vq;
+    VirtQueue *event_vq;
+    VirtQueue *cmd_vq;
+    uint32_t sense_size;
+    uint32_t cdb_size;
+} VirtIOSCSI;
+
+static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /* TODO */
+}
+
+static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /* TODO */
+}
+
+static void virtio_scsi_get_config(VirtIODevice *vdev,
+                                   uint8_t *config)
+{
+    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+
+    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
+    stl_raw(&scsiconf->seg_max, 128 - 2);
+    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
+    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
+    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
+    stl_raw(&scsiconf->sense_size, s->sense_size);
+    stl_raw(&scsiconf->cdb_size, s->cdb_size);
+    stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
+    stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
+    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
+}
+
+static void virtio_scsi_set_config(VirtIODevice *vdev,
+                                   const uint8_t *config)
+{
+    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+
+    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
+        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
+        error_report("bad data written to virtio-scsi configuration space");
+        exit(1);
+    }
+
+    s->sense_size = ldl_raw(&scsiconf->sense_size);
+    s->cdb_size = ldl_raw(&scsiconf->cdb_size);
+}
+
+static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
+                                         uint32_t requested_features)
+{
+    return requested_features;
+}
+
+static void virtio_scsi_reset(VirtIODevice *vdev)
+{
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+
+    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
+    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
+}
+
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+{
+    VirtIOSCSI *s;
+
+    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
+                                         sizeof(VirtIOSCSIConfig),
+                                         sizeof(VirtIOSCSI));
+
+    s->qdev = dev;
+    s->conf = proxyconf;
+
+    /* TODO set up vdev function pointers */
+    s->vdev.get_config = virtio_scsi_get_config;
+    s->vdev.set_config = virtio_scsi_set_config;
+    s->vdev.get_features = virtio_scsi_get_features;
+    s->vdev.reset = virtio_scsi_reset;
+
+    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   virtio_scsi_handle_ctrl);
+    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   NULL);
+    s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   virtio_scsi_handle_cmd);
+
+    /* TODO savevm */
+
+    return &s->vdev;
+}
+
+void virtio_scsi_exit(VirtIODevice *vdev)
+{
+    virtio_cleanup(vdev);
+}
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
new file mode 100644
index 0000000..4bc889d
--- /dev/null
+++ b/hw/virtio-scsi.h
@@ -0,0 +1,36 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VIRTIO_SCSI_H
+#define _QEMU_VIRTIO_SCSI_H
+
+#include "virtio.h"
+#include "net.h"
+#include "pci.h"
+
+/* The ID for virtio_scsi */
+#define VIRTIO_ID_SCSI  8
+
+struct VirtIOSCSIConf {
+    uint32_t num_queues;
+    uint32_t max_sectors;
+    uint32_t cmd_per_lun;
+};
+
+#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
+    DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
+    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
+    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
+    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
+
+#endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/hw/virtio.h b/hw/virtio.h
index 25f5564..400c092 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -199,6 +199,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 typedef struct virtio_serial_conf virtio_serial_conf;
 VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+typedef struct VirtIOSCSIConf VirtIOSCSIConf;
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
 #ifdef CONFIG_LINUX
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
@@ -208,6 +210,7 @@ void virtio_net_exit(VirtIODevice *vdev);
 void virtio_blk_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
 void virtio_balloon_exit(VirtIODevice *vdev);
+void virtio_scsi_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (10 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 11/18] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 13/18] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |  142 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index a297fed..a9f883c 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -135,14 +135,152 @@ typedef struct {
     uint32_t cdb_size;
 } VirtIOSCSI;
 
+typedef struct VirtIOSCSIReq {
+    VirtIOSCSI *dev;
+    VirtQueue *vq;
+    VirtQueueElement elem;
+    QEMUSGList qsgl;
+    SCSIRequest *sreq;
+    union {
+        char                  *buf;
+        VirtIOSCSICmdReq      *cmd;
+        VirtIOSCSICtrlTMFReq  *tmf;
+        VirtIOSCSICtrlANReq   *an;
+    } req;
+    union {
+        char                  *buf;
+        VirtIOSCSICmdResp     *cmd;
+        VirtIOSCSICtrlTMFResp *tmf;
+        VirtIOSCSICtrlANResp  *an;
+        VirtIOSCSIEvent       *event;
+    } resp;
+} VirtIOSCSIReq;
+
+static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
+{
+    VirtIOSCSI *s = req->dev;
+    VirtQueue *vq = req->vq;
+    virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
+    qemu_sglist_destroy(&req->qsgl);
+    if (req->sreq) {
+        req->sreq->hba_private = NULL;
+        scsi_req_unref(req->sreq);
+    }
+    g_free(req);
+    virtio_notify(&s->vdev, vq);
+}
+
+static void virtio_scsi_bad_req(void)
+{
+    error_report("wrong size for virtio-scsi headers");
+    exit(1);
+}
+
+static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
+                                   target_phys_addr_t *addr, int num)
+{
+    memset(qsgl, 0, sizeof(*qsgl));
+    while (num--) {
+        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
+    }
+}
+
+static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
+                                  VirtIOSCSIReq *req)
+{
+    assert(req->elem.out_num && req->elem.in_num);
+    req->vq = vq;
+    req->dev = s;
+    req->sreq = NULL;
+    req->req.buf = req->elem.out_sg[0].iov_base;
+    req->resp.buf = req->elem.in_sg[0].iov_base;
+
+    if (req->elem.out_num > 1) {
+        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
+                               &req->elem.out_addr[1],
+                               req->elem.out_num - 1);
+    } else {
+        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
+                               &req->elem.in_addr[1],
+                               req->elem.in_num - 1);
+    }
+}
+
+static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
+{
+    VirtIOSCSIReq *req;
+    req = g_malloc(sizeof(*req));
+    if (!virtqueue_pop(vq, &req->elem)) {
+        g_free(req);
+        return NULL;
+    }
+
+    virtio_scsi_parse_req(s, vq, req);
+    return req;
+}
+
+static void virtio_scsi_fail_ctrl_req(VirtIOSCSIReq *req)
+{
+    if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
+        req->resp.tmf->response = VIRTIO_SCSI_S_FAILURE;
+    } else {
+        req->resp.an->response = VIRTIO_SCSI_S_FAILURE;
+    }
+
+    virtio_scsi_complete_req(req);
+}
+
 static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
 {
-    /* TODO */
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+    VirtIOSCSIReq *req;
+
+    while ((req = virtio_scsi_pop_req(s, vq))) {
+        virtio_scsi_fail_ctrl_req(req);
+    }
+}
+
+static void virtio_scsi_fail_cmd_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
+{
+    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
+    virtio_scsi_complete_req(req);
 }
 
 static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
 {
-    /* TODO */
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+    VirtIOSCSIReq *req;
+
+    while ((req = virtio_scsi_pop_req(s, vq))) {
+        int out_size, in_size;
+        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
+            virtio_scsi_bad_req();
+        }
+
+        out_size = req->elem.out_sg[0].iov_len;
+        in_size = req->elem.in_sg[0].iov_len;
+        if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
+            in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
+            virtio_scsi_bad_req();
+        }
+
+        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
+            virtio_scsi_fail_cmd_req(s, req);
+            continue;
+        }
+
+        req->resp.cmd->resid = 0;
+        req->resp.cmd->status_qualifier = 0;
+        req->resp.cmd->status = CHECK_CONDITION;
+        req->resp.cmd->sense_len = 4;
+        req->resp.cmd->sense[0] = 0xf0; /* Fixed format current sense */
+        req->resp.cmd->sense[1] = ILLEGAL_REQUEST;
+        req->resp.cmd->sense[2] = 0x20;
+        req->resp.cmd->sense[3] = 0x00;
+        req->resp.cmd->response = VIRTIO_SCSI_S_OK;
+
+        virtio_scsi_complete_req(req);
+    }
 }
 
 static void virtio_scsi_get_config(VirtIODevice *vdev,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 13/18] virtio-scsi: add basic SCSI bus operation
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (11 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests Paolo Bonzini
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 98 insertions(+), 13 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index a9f883c..f4eb8c7 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -128,6 +128,7 @@ typedef struct {
     DeviceState *qdev;
     VirtIOSCSIConf *conf;
 
+    SCSIBus bus;
     VirtQueue *ctrl_vq;
     VirtQueue *event_vq;
     VirtQueue *cmd_vq;
@@ -156,6 +157,22 @@ typedef struct VirtIOSCSIReq {
     } resp;
 } VirtIOSCSIReq;
 
+static inline int virtio_scsi_get_lun(uint8_t *lun)
+{
+    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
+}
+
+static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
+{
+    if (lun[0] != 1) {
+        return NULL;
+    }
+    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
+        return NULL;
+    }
+    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
+}
+
 static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
 {
     VirtIOSCSI *s = req->dev;
@@ -240,7 +257,42 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     }
 }
 
-static void virtio_scsi_fail_cmd_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
+static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
+                                         size_t resid)
+{
+    VirtIOSCSIReq *req = r->hba_private;
+
+    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
+    req->resp.cmd->status = status;
+    if (req->resp.cmd->status == GOOD) {
+        req->resp.cmd->resid = resid;
+    } else {
+        req->resp.cmd->resid = 0;
+        req->resp.cmd->sense_len =
+            scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
+    }
+    virtio_scsi_complete_req(req);
+}
+
+static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
+{
+    VirtIOSCSIReq *req = r->hba_private;
+
+    return &req->qsgl;
+}
+
+static void virtio_scsi_request_cancelled(SCSIRequest *r)
+{
+    VirtIOSCSIReq *req = r->hba_private;
+
+    if (!req) {
+        return;
+    }
+    req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
+    virtio_scsi_complete_req(req);
+}
+
+static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
 {
     req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
     virtio_scsi_complete_req(req);
@@ -250,8 +302,10 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
     VirtIOSCSIReq *req;
+    int n;
 
     while ((req = virtio_scsi_pop_req(s, vq))) {
+        SCSIDevice *d;
         int out_size, in_size;
         if (req->elem.out_num < 1 || req->elem.in_num < 1) {
             virtio_scsi_bad_req();
@@ -265,21 +319,36 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
         }
 
         if (req->elem.out_num > 1 && req->elem.in_num > 1) {
-            virtio_scsi_fail_cmd_req(s, req);
+            virtio_scsi_fail_cmd_req(req);
             continue;
         }
 
-        req->resp.cmd->resid = 0;
-        req->resp.cmd->status_qualifier = 0;
-        req->resp.cmd->status = CHECK_CONDITION;
-        req->resp.cmd->sense_len = 4;
-        req->resp.cmd->sense[0] = 0xf0; /* Fixed format current sense */
-        req->resp.cmd->sense[1] = ILLEGAL_REQUEST;
-        req->resp.cmd->sense[2] = 0x20;
-        req->resp.cmd->sense[3] = 0x00;
-        req->resp.cmd->response = VIRTIO_SCSI_S_OK;
-
-        virtio_scsi_complete_req(req);
+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
+        if (!d) {
+            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
+            virtio_scsi_complete_req(req);
+            continue;
+        }
+        req->sreq = scsi_req_new(d, req->req.cmd->tag,
+                                 virtio_scsi_get_lun(req->req.cmd->lun),
+                                 req->req.cmd->cdb, req);
+
+        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
+            int req_mode =
+                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
+
+            if (req->sreq->cmd.mode != req_mode ||
+                req->sreq->cmd.xfer > req->qsgl.size) {
+                req->resp.cmd->response = VIRTIO_SCSI_S_OVERRUN;
+                virtio_scsi_complete_req(req);
+                continue;
+            }
+        }
+
+        n = scsi_req_enqueue(req->sreq);
+        if (n) {
+            scsi_req_continue(req->sreq);
+        }
     }
 }
 
@@ -331,6 +400,17 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
     s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
 }
 
+static struct SCSIBusInfo virtio_scsi_scsi_info = {
+    .tcq = true,
+    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
+    .max_target = VIRTIO_SCSI_MAX_TARGET,
+    .max_lun = VIRTIO_SCSI_MAX_LUN,
+
+    .complete = virtio_scsi_command_complete,
+    .cancel = virtio_scsi_request_cancelled,
+    .get_sg_list = virtio_scsi_get_sg_list,
+};
+
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
@@ -355,6 +435,11 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
     s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_cmd);
 
+    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
+    if (!dev->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus);
+    }
+
     /* TODO savevm */
 
     return &s->vdev;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (12 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 13/18] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-24  7:54   ` Hu Tao
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 15/18] virtio-scsi: add migration support Paolo Bonzini
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 126 insertions(+), 8 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index f4eb8c7..380073a 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -134,6 +134,7 @@ typedef struct {
     VirtQueue *cmd_vq;
     uint32_t sense_size;
     uint32_t cdb_size;
+    int resetting;
 } VirtIOSCSI;
 
 typedef struct VirtIOSCSIReq {
@@ -236,15 +237,104 @@ static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
     return req;
 }
 
-static void virtio_scsi_fail_ctrl_req(VirtIOSCSIReq *req)
+static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
-    if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
-        req->resp.tmf->response = VIRTIO_SCSI_S_FAILURE;
-    } else {
-        req->resp.an->response = VIRTIO_SCSI_S_FAILURE;
+    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
+    SCSIRequest *r, *next;
+    DeviceState *qdev;
+    int target;
+
+    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
+    req->resp.tmf->response = VIRTIO_SCSI_S_OK;
+
+    switch (req->req.tmf->subtype) {
+    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
+    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
+        if (!d) {
+            goto fail;
+        }
+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+            goto incorrect_lun;
+        }
+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
+            if (r->tag == req->req.cmd->tag) {
+                break;
+            }
+        }
+        if (r && r->hba_private) {
+            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
+                /* "If the specified command is present in the task set, then
+                 * return a service response set to FUNCTION SUCCEEDED".
+                 */
+                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
+            } else {
+                scsi_req_cancel(r);
+            }
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
+        if (!d) {
+            goto fail;
+        }
+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+            goto incorrect_lun;
+        }
+        s->resetting++;
+        qdev_reset_all(&d->qdev);
+        s->resetting--;
+        break;
+
+    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
+    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
+    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
+        if (!d) {
+            goto fail;
+        }
+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+            goto incorrect_lun;
+        }
+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
+            if (r->hba_private) {
+                if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
+                    /* "If there is any command present in the task set, then
+                     * return a service response set to FUNCTION SUCCEEDED".
+                     */
+                    req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
+                    break;
+                } else {
+                    scsi_req_cancel(r);
+                }
+            }
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
+        target = req->req.cmd->lun[1];
+        s->resetting++;
+        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
+             d = DO_UPCAST(SCSIDevice, qdev, qdev);
+             if (d->channel == 0 && d->id == target) {
+                qdev_reset_all(&d->qdev);
+             }
+        }
+        s->resetting--;
+        break;
+
+    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
+    default:
+        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+        break;
     }
 
-    virtio_scsi_complete_req(req);
+    return;
+
+incorrect_lun:
+    req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
+    return;
+
+fail:
+    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
 }
 
 static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
@@ -253,7 +343,31 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     VirtIOSCSIReq *req;
 
     while ((req = virtio_scsi_pop_req(s, vq))) {
-        virtio_scsi_fail_ctrl_req(req);
+        int out_size, in_size;
+        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
+            virtio_scsi_bad_req();
+            continue;
+        }
+
+        out_size = req->elem.out_sg[0].iov_len;
+        in_size = req->elem.in_sg[0].iov_len;
+        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
+            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
+                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
+                virtio_scsi_bad_req();
+            }
+            virtio_scsi_do_tmf(s, req);
+
+        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
+                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
+            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
+                in_size < sizeof(VirtIOSCSICtrlANResp)) {
+                virtio_scsi_bad_req();
+            }
+            req->resp.an->event_actual = 0;
+            req->resp.an->response = VIRTIO_SCSI_S_OK;
+        }
+        virtio_scsi_complete_req(req);
     }
 }
 
@@ -288,7 +402,11 @@ static void virtio_scsi_request_cancelled(SCSIRequest *r)
     if (!req) {
         return;
     }
-    req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
+    if (req->dev->resetting) {
+        req->resp.cmd->response = VIRTIO_SCSI_S_RESET;
+    } else {
+        req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
+    }
     virtio_scsi_complete_req(req);
 }
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 15/18] virtio-scsi: add migration support
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (13 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 16/18] scsi: fix wrong return for target INQUIRY Paolo Bonzini
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 380073a..7f850d1 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -237,6 +237,34 @@ static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
     return req;
 }
 
+static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
+{
+    VirtIOSCSIReq *req = sreq->hba_private;
+
+    qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
+}
+
+static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
+{
+    SCSIBus *bus = sreq->bus;
+    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIOSCSIReq *req;
+
+    req = g_malloc(sizeof(*req));
+    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
+    virtio_scsi_parse_req(s, s->cmd_vq, req);
+
+    scsi_req_ref(sreq);
+    req->sreq = sreq;
+    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
+        int req_mode =
+            (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
+
+        assert(req->sreq->cmd.mode == req_mode);
+    }
+    return req;
+}
+
 static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
     SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
@@ -518,6 +546,22 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
     s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
 }
 
+/* The device does not have anything to save beyond the virtio data.
+ * Request data is saved with callbacks from SCSI devices.
+ */
+static void virtio_scsi_save(QEMUFile *f, void *opaque)
+{
+    VirtIOSCSI *s = opaque;
+    virtio_save(&s->vdev, f);
+}
+
+static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VirtIOSCSI *s = opaque;
+    virtio_load(&s->vdev, f);
+    return 0;
+}
+
 static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .tcq = true,
     .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
@@ -527,11 +571,14 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .complete = virtio_scsi_command_complete,
     .cancel = virtio_scsi_request_cancelled,
     .get_sg_list = virtio_scsi_get_sg_list,
+    .save_request = virtio_scsi_save_request,
+    .load_request = virtio_scsi_load_request,
 };
 
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
+    static int virtio_scsi_id;
 
     s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
                                          sizeof(VirtIOSCSIConfig),
@@ -558,7 +605,8 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
 
-    /* TODO savevm */
+    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
+                    virtio_scsi_save, virtio_scsi_load, s);
 
     return &s->vdev;
 }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 16/18] scsi: fix wrong return for target INQUIRY
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (14 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 15/18] virtio-scsi: add migration support Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 17/18] scsi: fix searching for an empty id Paolo Bonzini
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index f0babb1..2cf2f0d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -380,7 +380,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
 
     /* PAGE CODE == 0 */
     if (r->req.cmd.xfer < 5) {
-        return -1;
+        return false;
     }
 
     r->len = MIN(r->req.cmd.xfer, 36);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 17/18] scsi: fix searching for an empty id
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (15 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 16/18] scsi: fix wrong return for target INQUIRY Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 18/18] scsi-block: always use scsi_generic_ops for cache != none Paolo Bonzini
  2012-02-24 16:34 ` [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Anthony Liguori
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

The conditions for detecting no free target or LUN were wrong.

The LUN loop was followed by an "if" condition that is never true, because
the loop is exited as soon as lun becomes equal to bus->info->max_lun,
and never becomes greater than it.

The target loop had a wrong condition (<= instead of <).  Once this is
fixed, the loop would fail in the same way as the LUN loop.

The fix is to see whether scsi_device_find returned the device with the
last (channel, target, LUN) pair, and fail if so.

In addition, scsi_bus_legacy_handle_cmdline also had an off-by-one error.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2cf2f0d..2cb5a18 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -132,6 +132,10 @@ static int scsi_qdev_init(DeviceState *qdev)
         error_report("bad scsi device id: %d", dev->id);
         goto err;
     }
+    if (dev->lun != -1 && dev->lun > bus->info->max_lun) {
+        error_report("bad scsi device lun: %d", dev->lun);
+        goto err;
+    }
 
     if (dev->id == -1) {
         int id = -1;
@@ -140,8 +144,8 @@ static int scsi_qdev_init(DeviceState *qdev)
         }
         do {
             d = scsi_device_find(bus, dev->channel, ++id, dev->lun);
-        } while (d && d->lun == dev->lun && id <= bus->info->max_target);
-        if (id > bus->info->max_target) {
+        } while (d && d->lun == dev->lun && id < bus->info->max_target);
+        if (d && d->lun == dev->lun) {
             error_report("no free target");
             goto err;
         }
@@ -151,14 +155,15 @@ static int scsi_qdev_init(DeviceState *qdev)
         do {
             d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
         } while (d && d->lun == lun && lun < bus->info->max_lun);
-        if (lun > bus->info->max_lun) {
+        if (d && d->lun == lun) {
             error_report("no free lun");
             goto err;
         }
         dev->lun = lun;
     } else {
         d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
-        if (dev->lun == d->lun && dev != d) {
+        assert(d);
+        if (d->lun == dev->lun && dev != d) {
             qdev_free(&d->qdev);
         }
     }
@@ -217,7 +222,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     int res = 0, unit;
 
     loc_push_none(&loc);
-    for (unit = 0; unit < bus->info->max_target; unit++) {
+    for (unit = 0; unit <= bus->info->max_target; unit++) {
         dinfo = drive_get(IF_SCSI, bus->busnr, unit);
         if (dinfo == NULL) {
             continue;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v4 18/18] scsi-block: always use scsi_generic_ops for cache != none
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (16 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 17/18] scsi: fix searching for an empty id Paolo Bonzini
@ 2012-02-22 14:33 ` Paolo Bonzini
  2012-02-24 16:34 ` [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Anthony Liguori
  18 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-22 14:33 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index ec8e7cb..4101a59 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1754,6 +1754,15 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
     case WRITE_VERIFY_10:
     case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
+        /* If we are not using O_DIRECT, we might read stale data from the
+         * host cache if writes were made using other commands than these
+         * ones (such as WRITE SAME or EXTENDED COPY, etc.).  So, without
+         * O_DIRECT everything must go through SG_IO.
+         */
+        if (!(s->qdev.conf.bs->open_flags & BDRV_O_NOCACHE)) {
+            break;
+        }
+
         /* MMC writing cannot be done via pread/pwrite, because it sometimes
          * involves writing beyond the maximum LBA or to negative LBA (lead-in).
          * And once you do these writes, reading from the block device is
@@ -1764,10 +1773,11 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
          * seen, but performance usually isn't paramount on optical media.  So,
          * just make scsi-block operate the same as scsi-generic for them.
          */
-        if (s->qdev.type != TYPE_ROM) {
-            return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
-                                  hba_private);
-        }
+        if (s->qdev.type == TYPE_ROM) {
+            break;
+        }
+        return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
+                              hba_private);
     }
 
     return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests Paolo Bonzini
@ 2012-02-24  7:54   ` Hu Tao
  2012-02-24  8:56     ` Paolo Bonzini
  2012-02-24 13:58     ` Paolo Bonzini
  0 siblings, 2 replies; 23+ messages in thread
From: Hu Tao @ 2012-02-24  7:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Wed, Feb 22, 2012 at 03:33:52PM +0100, Paolo Bonzini wrote:
> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/virtio-scsi.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 126 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
> index f4eb8c7..380073a 100644
> --- a/hw/virtio-scsi.c
> +++ b/hw/virtio-scsi.c
> @@ -134,6 +134,7 @@ typedef struct {
>      VirtQueue *cmd_vq;
>      uint32_t sense_size;
>      uint32_t cdb_size;
> +    int resetting;
>  } VirtIOSCSI;
>  
>  typedef struct VirtIOSCSIReq {
> @@ -236,15 +237,104 @@ static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
>      return req;
>  }
>  
> -static void virtio_scsi_fail_ctrl_req(VirtIOSCSIReq *req)
> +static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>  {
> -    if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
> -        req->resp.tmf->response = VIRTIO_SCSI_S_FAILURE;
> -    } else {
> -        req->resp.an->response = VIRTIO_SCSI_S_FAILURE;
> +    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);

should be req->req.tmf->lun here and elsewhere in this function?

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 380073a..1f3b851 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -239,7 +239,7 @@ static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
 
 static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
-    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
+    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
     SCSIRequest *r, *next;
     DeviceState *qdev;
     int target;
@@ -253,11 +253,11 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
         if (!d) {
             goto fail;
         }
-        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
             goto incorrect_lun;
         }
         QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
-            if (r->tag == req->req.cmd->tag) {
+            if (r->tag == req->req.tmf->tag) {
                 break;
             }
         }
@@ -277,7 +277,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
         if (!d) {
             goto fail;
         }
-        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
             goto incorrect_lun;
         }
         s->resetting++;
@@ -291,7 +291,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
         if (!d) {
             goto fail;
         }
-        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
             goto incorrect_lun;
         }
         QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
@@ -310,7 +310,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
         break;
 
     case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
-        target = req->req.cmd->lun[1];
+        target = req->req.tmf->lun[1];
         s->resetting++;
         QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
              d = DO_UPCAST(SCSIDevice, qdev, qdev);

-- 
Thanks,
Hu Tao

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests
  2012-02-24  7:54   ` Hu Tao
@ 2012-02-24  8:56     ` Paolo Bonzini
  2012-02-24 13:58     ` Paolo Bonzini
  1 sibling, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-24  8:56 UTC (permalink / raw)
  To: qemu-devel

On 02/24/2012 08:54 AM, Hu Tao wrote:
> should be req->req.tmf->lun here and elsewhere in this function?

Yes, good catch!

Paolo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests
  2012-02-24  7:54   ` Hu Tao
  2012-02-24  8:56     ` Paolo Bonzini
@ 2012-02-24 13:58     ` Paolo Bonzini
  1 sibling, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2012-02-24 13:58 UTC (permalink / raw)
  To: Hu Tao; +Cc: qemu-devel

On 02/24/2012 08:54 AM, Hu Tao wrote:
> diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
> index 380073a..1f3b851 100644
> --- a/hw/virtio-scsi.c
> +++ b/hw/virtio-scsi.c
> @@ -239,7 +239,7 @@ static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
>  
>  static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>  {
> -    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
> +    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
>      SCSIRequest *r, *next;
>      DeviceState *qdev;
>      int target;
> @@ -253,11 +253,11 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>          if (!d) {
>              goto fail;
>          }
> -        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
> +        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
>              goto incorrect_lun;
>          }
>          QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
> -            if (r->tag == req->req.cmd->tag) {
> +            if (r->tag == req->req.tmf->tag) {
>                  break;
>              }
>          }
> @@ -277,7 +277,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>          if (!d) {
>              goto fail;
>          }
> -        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
> +        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
>              goto incorrect_lun;
>          }
>          s->resetting++;
> @@ -291,7 +291,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>          if (!d) {
>              goto fail;
>          }
> -        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
> +        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
>              goto incorrect_lun;
>          }
>          QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
> @@ -310,7 +310,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
>          break;
>  
>      case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
> -        target = req->req.cmd->lun[1];
> +        target = req->req.tmf->lun[1];
>          s->resetting++;
>          QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
>               d = DO_UPCAST(SCSIDevice, qdev, qdev);

This is now fixed on github.

Paolo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PULL v4 00/18] virtio-scsi driver
  2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
                   ` (17 preceding siblings ...)
  2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 18/18] scsi-block: always use scsi_generic_ops for cache != none Paolo Bonzini
@ 2012-02-24 16:34 ` Anthony Liguori
  18 siblings, 0 replies; 23+ messages in thread
From: Anthony Liguori @ 2012-02-24 16:34 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On 02/22/2012 08:33 AM, Paolo Bonzini wrote:
> Anthony,
>
> the following changes since commit 99c7f87826337fa81f2f0f9baa9ca0a44faf90e9:
>
>    input: send kbd+mouse events only to running guests. (2012-02-17 11:02:55 -0600)
>
> are available in the git repository at:
>    git://github.com/bonzini/qemu.git virtio-scsi
>
> Kevin agreed on getting virtio-scsi in via a pull request, now
> that the code has been reviewed by Stefan Hajnoczi (virtio-scsi bits),
> Laszlo Ersek and Orit Wassermann.  Laszlo and Orit found problems
> in patches 2 and 14, which are fixed in this pull request.  In
> fact they reviewed almost all SCSI changes that went in since 0.15
> (!) and found two bugs in scsi-bus.c, fixed in patches 16/17.

Pulled.  Thanks.

Regards,

Anthony Liguori

>
> Paolo Bonzini (16):
>        dma-helpers: make QEMUSGList target independent
>        dma-helpers: add dma_buf_read and dma_buf_write
>        dma-helpers: add accounting wrappers
>        ahci: use new DMA helpers
>        scsi: pass residual amount to command_complete
>        scsi: add scatter/gather functionality
>        scsi-disk: enable scatter/gather functionality
>        scsi: add SCSIDevice vmstate definitions
>        scsi-generic: add migration support
>        scsi-disk: add migration support
>        virtio-scsi: add basic SCSI bus operation
>        virtio-scsi: process control queue requests
>        virtio-scsi: add migration support
>        scsi: fix wrong return for target INQUIRY
>        scsi: fix searching for an empty id
>        scsi-block: always use scsi_generic_ops for cache != none
>
> Stefan Hajnoczi (2):
>        virtio-scsi: Add virtio-scsi stub device
>        virtio-scsi: Add basic request processing infrastructure
>
>   Makefile.target                   |    1 +
>   default-configs/pci.mak           |    1 +
>   default-configs/s390x-softmmu.mak |    1 +
>   dma-helpers.c                     |   37 +++
>   dma.h                             |   20 +-
>   hw/esp.c                          |    3 +-
>   hw/ide/ahci.c                     |   82 +----
>   hw/lsi53c895a.c                   |    2 +-
>   hw/pci.h                          |    1 +
>   hw/s390-virtio-bus.c              |   33 ++
>   hw/s390-virtio-bus.h              |    2 +
>   hw/scsi-bus.c                     |  159 +++++++++-
>   hw/scsi-disk.c                    |  138 +++++++--
>   hw/scsi-generic.c                 |   25 ++
>   hw/scsi.h                         |   22 ++-
>   hw/spapr_vscsi.c                  |    2 +-
>   hw/usb-msd.c                      |    2 +-
>   hw/virtio-pci.c                   |   56 ++++
>   hw/virtio-pci.h                   |    2 +
>   hw/virtio-scsi.c                  |  617 +++++++++++++++++++++++++++++++++++++
>   hw/virtio-scsi.h                  |   36 +++
>   hw/virtio.h                       |    3 +
>   22 files changed, 1132 insertions(+), 113 deletions(-)
>   create mode 100644 hw/virtio-scsi.c
>   create mode 100644 hw/virtio-scsi.h

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2012-02-24 16:34 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-22 14:33 [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 02/18] dma-helpers: add dma_buf_read and dma_buf_write Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 03/18] dma-helpers: add accounting wrappers Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 04/18] ahci: use new DMA helpers Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 05/18] scsi: pass residual amount to command_complete Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 06/18] scsi: add scatter/gather functionality Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 07/18] scsi-disk: enable " Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 08/18] scsi: add SCSIDevice vmstate definitions Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 09/18] scsi-generic: add migration support Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 10/18] scsi-disk: " Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 11/18] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 13/18] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests Paolo Bonzini
2012-02-24  7:54   ` Hu Tao
2012-02-24  8:56     ` Paolo Bonzini
2012-02-24 13:58     ` Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 15/18] virtio-scsi: add migration support Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 16/18] scsi: fix wrong return for target INQUIRY Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 17/18] scsi: fix searching for an empty id Paolo Bonzini
2012-02-22 14:33 ` [Qemu-devel] [PATCH v4 18/18] scsi-block: always use scsi_generic_ops for cache != none Paolo Bonzini
2012-02-24 16:34 ` [Qemu-devel] [PULL v4 00/18] virtio-scsi driver Anthony Liguori

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.