[Spice-commits] 14 commits - block/iscsi.c docs/usb-storage.txt hw/lsi53c895a.c hw/qxl.c hw/scsi-bus.c hw/scsi-disk.c hw/usb trace-events

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed Jan 23 09:39:14 PST 2013


 block/iscsi.c        |  106 ++++++++++++++++++++++++++++++++++++++++++++++++---
 docs/usb-storage.txt |   11 ++++-
 hw/lsi53c895a.c      |    7 ---
 hw/qxl.c             |   24 ++++++++---
 hw/scsi-bus.c        |    2 
 hw/scsi-disk.c       |    4 -
 hw/usb/dev-storage.c |   96 ++++++++++++++++++++++++++++++++++++++--------
 hw/usb/hcd-ohci.c    |    1 
 trace-events         |    2 
 9 files changed, 216 insertions(+), 37 deletions(-)

New commits:
commit 177f7fc6884c47666f6c6eeca376a92432ccda38
Merge: 36ba580 0bf8264
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jan 23 09:08:54 2013 -0600

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    # By Peter Lieven (3) and others
    # Via Paolo Bonzini
    * bonzini/scsi-next:
      scsi: Drop useless null test in scsi_unit_attention()
      lsi: use qbus_reset_all to reset SCSI bus
      scsi: fix segfault with 0-byte disk
      iscsi: add support for iSCSI NOPs [v2]
      iscsi: partly avoid iovec linearization in iscsi_aio_writev
      iscsi: add iscsi_create support

commit 36ba58044e70a82b93e84b1f31076df847f23109
Merge: a29a6b7 3470733
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jan 23 09:08:33 2013 -0600

    Merge remote-tracking branch 'kraxel/usb.77' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/usb.77:
      usb: add usb-bot device (scsi bulk-only transport).
      ohci: add missing break
      Revert "usb-storage: Drop useless null test in usb_msd_handle_data()"

commit a29a6b73c4f17db6f82fd8d2094e824c04b29fee
Merge: 1356b98 038c187
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jan 23 09:07:29 2013 -0600

    Merge remote-tracking branch 'spice/spice.v68' into staging
    
    # By Alon Levy
    # Via Gerd Hoffmann
    * spice/spice.v68:
      qxl: change rom size to 8192
      qxl: stop using non revision 4 rom fields for revision < 4

commit 0bf8264e2d2bd19c1eecf9bde0e59284ef47eabb
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Jan 17 13:07:47 2013 +0100

    scsi: Drop useless null test in scsi_unit_attention()
    
    req was created by scsi_req_alloc(), which initializes req->dev to a
    value it dereferences.  req->dev isn't changed anywhere else.
    Therefore, req->dev can't be null.
    
    Drop the useless null test; it spooks Coverity.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 267a942..a97f1cd 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -282,7 +282,7 @@ static const struct SCSIReqOps reqops_invalid_opcode = {
 
 static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
 {
-    if (req->dev && req->dev->unit_attention.key == UNIT_ATTENTION) {
+    if (req->dev->unit_attention.key == UNIT_ATTENTION) {
         scsi_req_build_sense(req, req->dev->unit_attention);
     } else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
         scsi_req_build_sense(req, req->bus->unit_attention);
commit 032f0101aa6e009efda3a419379837ebceaeade1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Dec 17 11:23:25 2012 +0100

    lsi: use qbus_reset_all to reset SCSI bus
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 89c657f..860df32 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1670,12 +1670,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-                BusChild *kid;
-
-                QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
-                    DeviceState *dev = kid->child;
-                    device_reset(dev);
-                }
+                qbus_reset_all(&s->bus.qbus);
                 s->sstat0 |= LSI_SSTAT0_RST;
                 lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
             }
commit 0369f06f7464e7fb023f103aff889d28e99c43c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jan 10 15:08:05 2013 +0100

    scsi: fix segfault with 0-byte disk
    
    When a 0-sized disk is found, READ CAPACITY will return a
    LUN NOT READY error.  However, because it returns -1 instead
    of zero, the HBA will call scsi_req_continue.  This will
    typically cause a segmentation fault or an assertion failure.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index f8d7ef3..658e315 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1682,7 +1682,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
         if (!nb_sectors) {
             scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
-            return -1;
+            return 0;
         }
         if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
             goto illegal_request;
@@ -1751,7 +1751,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
             bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
             if (!nb_sectors) {
                 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
-                return -1;
+                return 0;
             }
             if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
                 goto illegal_request;
commit 5b5d34ec9882b29b757f6808693308e52a8e8ba7
Author: Peter Lieven <pl at kamp.de>
Date:   Thu Dec 6 10:46:47 2012 +0100

    iscsi: add support for iSCSI NOPs [v2]
    
    This patch will send NOP-Out PDUs every 5 seconds to the iSCSI target.
    If a consecutive number of NOP-In replies fail a reconnect is initiated.
    iSCSI NOPs help to ensure that the connection to the target is still operational.
    This should not, but in reality may be the case even if the TCP connection is still
    alive if there are bugs in either the target or the initiator implementation.
    
    v2:
     - track the NOPs inside libiscsi so libiscsi can reset the counter
       in case it initiates a reconnect.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 259192f..2497789 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -48,6 +48,7 @@ typedef struct IscsiLun {
     int block_size;
     uint64_t num_blocks;
     int events;
+    QEMUTimer *nop_timer;
 } IscsiLun;
 
 typedef struct IscsiAIOCB {
@@ -66,6 +67,9 @@ typedef struct IscsiAIOCB {
 #endif
 } IscsiAIOCB;
 
+#define NOP_INTERVAL 5000
+#define MAX_NOP_FAILURES 3
+
 static void
 iscsi_bh_cb(void *p)
 {
@@ -768,6 +772,26 @@ static char *parse_initiator_name(const char *target)
     }
 }
 
+#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
+static void iscsi_nop_timed_event(void *opaque)
+{
+    IscsiLun *iscsilun = opaque;
+
+    if (iscsi_get_nops_in_flight(iscsilun->iscsi) > MAX_NOP_FAILURES) {
+        error_report("iSCSI: NOP timeout. Reconnecting...");
+        iscsi_reconnect(iscsilun->iscsi);
+    }
+
+    if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) {
+        error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages.");
+        return;
+    }
+
+    qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
+    iscsi_set_events(iscsilun);
+}
+#endif
+
 /*
  * We support iscsi url's on the form
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
@@ -928,6 +952,12 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
 
     ret = 0;
 
+#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
+    /* Set up a timer for sending out iSCSI NOPs */
+    iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
+    qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
+#endif
+
 out:
     if (initiator_name != NULL) {
         g_free(initiator_name);
@@ -953,6 +983,10 @@ static void iscsi_close(BlockDriverState *bs)
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = iscsilun->iscsi;
 
+    if (iscsilun->nop_timer) {
+        qemu_del_timer(iscsilun->nop_timer);
+        qemu_free_timer(iscsilun->nop_timer);
+    }
     qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
     iscsi_destroy_context(iscsi);
     memset(iscsilun, 0, sizeof(IscsiLun));
@@ -987,6 +1021,10 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options)
     if (ret != 0) {
         goto out;
     }
+    if (iscsilun->nop_timer) {
+        qemu_del_timer(iscsilun->nop_timer);
+        qemu_free_timer(iscsilun->nop_timer);
+    }
     if (iscsilun->type != TYPE_DISK) {
         ret = -ENODEV;
         goto out;
commit 4cc841b57c1dc91d71bafc25b53ffab4eff7959b
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Nov 19 15:58:31 2012 +0100

    iscsi: partly avoid iovec linearization in iscsi_aio_writev
    
    libiscsi expects all write16 data in a linear buffer. If the
    iovec only contains one buffer we can skip the linearization
    step as well as the additional malloc/free and pass the
    buffer directly.
    
    Reported-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index d8382fd..259192f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -241,8 +241,17 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     /* XXX we should pass the iovec to write16 to avoid the extra copy */
     /* this will allow us to get rid of 'buf' completely */
     size = nb_sectors * BDRV_SECTOR_SIZE;
-    acb->buf = g_malloc(size);
-    qemu_iovec_to_buf(acb->qiov, 0, acb->buf, size);
+    data.size = MIN(size, acb->qiov->size);
+
+    /* if the iovec only contains one buffer we can pass it directly */
+    if (acb->qiov->niov == 1) {
+        acb->buf = NULL;
+        data.data = acb->qiov->iov[0].iov_base;
+    } else {
+        acb->buf = g_malloc(data.size);
+        qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size);
+        data.data = acb->buf;
+    }
 
     acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
@@ -263,9 +272,6 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
     acb->task->expxferlen = size;
 
-    data.data = acb->buf;
-    data.size = size;
-
     if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
                                  iscsi_aio_write16_cb,
                                  &data,
commit de8864e5ae645fc22aa4ecf1999705c2dd5cf93c
Author: Peter Lieven <pl at dlhnet.de>
Date:   Sat Nov 17 16:13:24 2012 +0100

    iscsi: add iscsi_create support
    
    This patch adds support for bdrv_create. This allows e.g.
    to use qemu-img to convert from any supported device to
    an iscsi backed storage as destination.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 041ee07..d8382fd 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -957,6 +957,56 @@ static int iscsi_has_zero_init(BlockDriverState *bs)
     return 0;
 }
 
+static int iscsi_create(const char *filename, QEMUOptionParameter *options)
+{
+    int ret = 0;
+    int64_t total_size = 0;
+    BlockDriverState bs;
+    IscsiLun *iscsilun = NULL;
+
+    memset(&bs, 0, sizeof(BlockDriverState));
+
+    /* Read out options */
+    while (options && options->name) {
+        if (!strcmp(options->name, "size")) {
+            total_size = options->value.n / BDRV_SECTOR_SIZE;
+        }
+        options++;
+    }
+
+    bs.opaque = g_malloc0(sizeof(struct IscsiLun));
+    iscsilun = bs.opaque;
+
+    ret = iscsi_open(&bs, filename, 0);
+    if (ret != 0) {
+        goto out;
+    }
+    if (iscsilun->type != TYPE_DISK) {
+        ret = -ENODEV;
+        goto out;
+    }
+    if (bs.total_sectors < total_size) {
+        ret = -ENOSPC;
+    }
+
+    ret = 0;
+out:
+    if (iscsilun->iscsi != NULL) {
+        iscsi_destroy_context(iscsilun->iscsi);
+    }
+    g_free(bs.opaque);
+    return ret;
+}
+
+static QEMUOptionParameter iscsi_create_options[] = {
+    {
+        .name = BLOCK_OPT_SIZE,
+        .type = OPT_SIZE,
+        .help = "Virtual disk size"
+    },
+    { NULL }
+};
+
 static BlockDriver bdrv_iscsi = {
     .format_name     = "iscsi",
     .protocol_name   = "iscsi",
@@ -964,6 +1014,8 @@ static BlockDriver bdrv_iscsi = {
     .instance_size   = sizeof(IscsiLun),
     .bdrv_file_open  = iscsi_open,
     .bdrv_close      = iscsi_close,
+    .bdrv_create     = iscsi_create,
+    .create_options  = iscsi_create_options,
 
     .bdrv_getlength  = iscsi_getlength,
 
commit 347073336d393a819928de0d4fd56563134c0e1a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 14 15:29:44 2013 +0100

    usb: add usb-bot device (scsi bulk-only transport).
    
    Basically the same as usb-storage, but without automatic scsi
    device setup.  Also features support for up to 16 LUNs.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/docs/usb-storage.txt b/docs/usb-storage.txt
index e58e849..fa93111 100644
--- a/docs/usb-storage.txt
+++ b/docs/usb-storage.txt
@@ -2,7 +2,7 @@
 qemu usb storage emulation
 --------------------------
 
-QEMU has two emulations for usb storage devices.
+QEMU has three devices for usb storage emulation.
 
 Number one emulates the classic bulk-only transport protocol which is
 used by 99% of the usb sticks on the marked today and is called
@@ -31,6 +31,15 @@ with tree logical units:
        -device scsi-cd,bus=uas.0,scsi-id=0,lun=5,drive=uas-cdrom
 
 
+Number three emulates the classic bulk-only transport protocol too.
+It's called "usb-bot".  It shares most code with "usb-storage", and
+the guest will not be able to see the difference.  The qemu command
+line interface is simliar to usb-uas though, i.e. no automatic scsi
+disk creation.  It also features support for up to 16 LUNs.  The LUN
+numbers must be continous, i.e. for three devices you must use 0+1+2.
+The 0+1+5 numbering from the "usb-uas" example isn't going to work
+with "usb-bot".
+
 enjoy,
   Gerd
 
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 1b87352..b89d00f 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -54,12 +54,12 @@ typedef struct {
     struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
+    /* For async completion.  */
+    USBPacket *packet;
+    /* usb-storage only */
     BlockConf conf;
     char *serial;
-    SCSIDevice *scsi_dev;
     uint32_t removable;
-    /* For async completion.  */
-    USBPacket *packet;
 } MSDState;
 
 struct usb_msd_cbw {
@@ -343,7 +343,8 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
     MSDState *s = (MSDState *)dev;
-    int ret;
+    SCSIDevice *scsi_dev;
+    int ret, maxlun;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
@@ -359,7 +360,19 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
         s->mode = USB_MSDM_CBW;
         break;
     case ClassInterfaceRequest | GetMaxLun:
-        data[0] = 0;
+        maxlun = 0;
+        for (;;) {
+            scsi_dev = scsi_device_find(&s->bus, 0, 0, maxlun+1);
+            if (scsi_dev == NULL) {
+                break;
+            }
+            if (scsi_dev->lun != maxlun+1) {
+                break;
+            }
+            maxlun++;
+        }
+        DPRINTF("MaxLun %d\n", maxlun);
+        data[0] = maxlun;
         p->actual_length = 1;
         break;
     default:
@@ -386,6 +399,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
     uint32_t tag;
     struct usb_msd_cbw cbw;
     uint8_t devep = p->ep->nr;
+    SCSIDevice *scsi_dev;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -405,7 +419,8 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 goto fail;
             }
             DPRINTF("Command on LUN %d\n", cbw.lun);
-            if (cbw.lun != 0) {
+            scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun);
+            if (scsi_dev == NULL) {
                 fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
                 goto fail;
             }
@@ -422,7 +437,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                     tag, cbw.flags, cbw.cmd_len, s->data_len);
             assert(le32_to_cpu(s->csw.residue) == 0);
             s->scsi_len = 0;
-            s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
+            s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL);
 #ifdef DEBUG_MSD
             scsi_req_print(s->req);
 #endif
@@ -553,7 +568,7 @@ static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
     return NULL;
 }
 
-static const struct SCSIBusInfo usb_msd_scsi_info = {
+static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
     .tcq = false,
     .max_target = 0,
     .max_lun = 0,
@@ -564,10 +579,22 @@ static const struct SCSIBusInfo usb_msd_scsi_info = {
     .load_request = usb_msd_load_request,
 };
 
-static int usb_msd_initfn(USBDevice *dev)
+static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
+    .tcq = false,
+    .max_target = 0,
+    .max_lun = 15,
+
+    .transfer_data = usb_msd_transfer_data,
+    .complete = usb_msd_command_complete,
+    .cancel = usb_msd_request_cancelled,
+    .load_request = usb_msd_load_request,
+};
+
+static int usb_msd_initfn_storage(USBDevice *dev)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
     BlockDriverState *bs = s->conf.bs;
+    SCSIDevice *scsi_dev;
 
     if (!bs) {
         error_report("drive property not set");
@@ -595,10 +622,10 @@ static int usb_msd_initfn(USBDevice *dev)
     }
 
     usb_desc_init(dev);
-    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage);
+    scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
                                             s->conf.bootindex);
-    if (!s->scsi_dev) {
+    if (!scsi_dev) {
         return -1;
     }
     s->bus.qbus.allow_hotplug = 0;
@@ -616,6 +643,19 @@ static int usb_msd_initfn(USBDevice *dev)
     return 0;
 }
 
+static int usb_msd_initfn_bot(USBDevice *dev)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+    usb_desc_create_serial(dev);
+    usb_desc_init(dev);
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot);
+    s->bus.qbus.allow_hotplug = 0;
+    usb_msd_handle_reset(dev);
+
+    return 0;
+}
+
 static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 {
     static int nr=0;
@@ -698,12 +738,11 @@ static Property msd_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void usb_msd_class_initfn(ObjectClass *klass, void *data)
+static void usb_msd_class_initfn_common(ObjectClass *klass)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    uc->init           = usb_msd_initfn;
     uc->product_desc   = "QEMU USB MSD";
     uc->usb_desc       = &desc;
     uc->cancel_packet  = usb_msd_cancel_io;
@@ -713,19 +752,44 @@ static void usb_msd_class_initfn(ObjectClass *klass, void *data)
     uc->handle_data    = usb_msd_handle_data;
     dc->fw_name = "storage";
     dc->vmsd = &vmstate_usb_msd;
+}
+
+static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init = usb_msd_initfn_storage;
     dc->props = msd_properties;
+    usb_msd_class_initfn_common(klass);
+}
+
+static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
+{
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init = usb_msd_initfn_bot;
+    usb_msd_class_initfn_common(klass);
 }
 
 static const TypeInfo msd_info = {
     .name          = "usb-storage",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(MSDState),
-    .class_init    = usb_msd_class_initfn,
+    .class_init    = usb_msd_class_initfn_storage,
+};
+
+static const TypeInfo bot_info = {
+    .name          = "usb-bot",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(MSDState),
+    .class_init    = usb_msd_class_initfn_bot,
 };
 
 static void usb_msd_register_types(void)
 {
     type_register_static(&msd_info);
+    type_register_static(&bot_info);
     usb_legacy_register("usb-storage", "disk", usb_msd_init);
 }
 
commit 7fa96d73893728752ec7b832a62a48c434748497
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 21 14:53:01 2013 +0100

    ohci: add missing break
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 6a2f5f8..dd9967b 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1736,6 +1736,7 @@ static void ohci_mem_write(void *opaque,
     /* PXA27x specific registers */
     case 24: /* HcStatus */
         ohci->hstatus &= ~(val & ohci->hmask);
+        break;
 
     case 25: /* HcHReset */
         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
commit 038c1879a00153b14bce113315b693e8c2944fa9
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Jan 21 14:48:07 2013 +0200

    qxl: change rom size to 8192
    
    This is a simpler solution to 869981, where migration breaks since qxl's
    rom bar size has changed. Instead of ignoring fields in QXLRom, which is what has
    actually changed, we remove some of the modes, a mechanism already
    accounted for by the guest. The modes left allow for portrait and
    landscape only modes, corresponding to orientations 0 and 1.
    Orientations 2 and 3 are dropped.
    
    Added assert so that rom size will fit the future QXLRom increases via
    spice-protocol changes.
    
    This patch has been tested with 6.1.0.10015. With the newer 6.1.0.10016
    there are problems with both "(flipped)" modes prior to the patch, and
    the patch loses the ability to set "Portrait" modes. But this is a
    separate bug to be fixed in the driver, and besides the patch doesn't
    affect the new arbitrary mode setting functionality.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 0d81816..a125e29 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -80,9 +80,7 @@
 
 #define QXL_MODE_EX(x_res, y_res)                 \
     QXL_MODE_16_32(x_res, y_res, 0),              \
-    QXL_MODE_16_32(y_res, x_res, 1),              \
-    QXL_MODE_16_32(x_res, y_res, 2),              \
-    QXL_MODE_16_32(y_res, x_res, 3)
+    QXL_MODE_16_32(x_res, y_res, 1)
 
 static QXLMode qxl_modes[] = {
     QXL_MODE_EX(640, 480),
@@ -306,10 +304,13 @@ static inline uint32_t msb_mask(uint32_t val)
 
 static ram_addr_t qxl_rom_size(void)
 {
-    uint32_t rom_size = sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes);
+    uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) +
+                                 sizeof(qxl_modes);
+    uint32_t rom_size = 8192; /* two pages */
 
-    rom_size = MAX(rom_size, TARGET_PAGE_SIZE);
-    rom_size = msb_mask(rom_size * 2 - 1);
+    required_rom_size = MAX(required_rom_size, TARGET_PAGE_SIZE);
+    required_rom_size = msb_mask(required_rom_size * 2 - 1);
+    assert(required_rom_size <= rom_size);
     return rom_size;
 }
 
commit f4c0e5011b96d67b87db407854ee948da708a0d9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 21 11:18:47 2013 +0100

    Revert "usb-storage: Drop useless null test in usb_msd_handle_data()"
    
    This reverts commit a1cbfd554e11bb8af38c2f3e1f1574bf4c563cd2.
    
    Test isn't useless.  scsi_req_enqueue() may finish the request (will
    actually happen for requests which don't trigger any I/O such as
    INQUIRY), then call usb_msd_command_complete() which in turn will
    set s->req to NULL after unref'ing it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index b839798..1b87352 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -427,7 +427,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             scsi_req_print(s->req);
 #endif
             scsi_req_enqueue(s->req);
-            if (s->req->cmd.xfer != SCSI_XFER_NONE) {
+            if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
                 scsi_req_continue(s->req);
             }
             break;
commit e0ac6097b6cc24694e83ae61e80040177bb5a584
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Jan 21 14:48:06 2013 +0200

    qxl: stop using non revision 4 rom fields for revision < 4
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 9dc44b9..0d81816 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -945,6 +945,12 @@ static void interface_set_client_capabilities(QXLInstance *sin,
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
 
+    if (qxl->revision < 4) {
+        trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id,
+                                                              qxl->revision);
+        return;
+    }
+
     if (runstate_check(RUN_STATE_INMIGRATE) ||
         runstate_check(RUN_STATE_POSTMIGRATE)) {
         return;
@@ -979,6 +985,11 @@ static int interface_client_monitors_config(QXLInstance *sin,
     QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
     int i;
 
+    if (qxl->revision < 4) {
+        trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
+                                                               qxl->revision);
+        return 0;
+    }
     /*
      * Older windows drivers set int_mask to 0 when their ISR is called,
      * then later set it to ~0. So it doesn't relate to the actual interrupts
diff --git a/trace-events b/trace-events
index 7de9106..09091e6 100644
--- a/trace-events
+++ b/trace-events
@@ -1029,8 +1029,10 @@ qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
 qxl_set_guest_bug(int qid) "%d"
 qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
 qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
+qxl_client_monitors_config_unsupported_by_device(int qid, int revision) "%d revision=%d"
 qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
 qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"
+qxl_set_client_capabilities_unsupported_by_revision(int qid, int revision) "%d revision=%d"
 
 # hw/qxl-render.c
 qxl_render_blit_guest_primary_initialized(void) ""


More information about the Spice-commits mailing list