summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/audio/pcspk.c17
-rw-r--r--hw/i386/kvmvapic.c1
-rw-r--r--hw/i386/pc.c18
-rw-r--r--hw/intc/apic.c26
-rw-r--r--hw/misc/ivshmem.c1
-rw-r--r--hw/nvram/fw_cfg.c4
-rw-r--r--hw/ppc/ppc405.h6
-rw-r--r--hw/s390x/sclp.c2
-rw-r--r--hw/s390x/virtio-ccw.h1
-rw-r--r--hw/scsi/mptsas.c6
-rw-r--r--hw/scsi/scsi-disk.c22
-rw-r--r--hw/scsi/virtio-scsi.c15
-rw-r--r--hw/scsi/vmw_pvscsi.c5
-rw-r--r--hw/sh4/shix.c2
-rw-r--r--hw/tricore/tricore_testboard.c2
-rw-r--r--hw/usb/dev-mtp.c197
-rw-r--r--hw/usb/hcd-xhci.c9
-rw-r--r--hw/usb/host-libusb.c7
-rw-r--r--hw/vfio/pci.c4
19 files changed, 277 insertions, 68 deletions
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 42a6f4885a..984534b2d1 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -52,8 +52,8 @@ typedef struct {
     unsigned int pit_count;
     unsigned int samples;
     unsigned int play_pos;
-    int data_on;
-    int dummy_refresh_clock;
+    uint8_t data_on;
+    uint8_t dummy_refresh_clock;
 } PCSpkState;
 
 static const char *s_spk = "pcspk";
@@ -187,6 +187,18 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
     pcspk_state = s;
 }
 
+static const VMStateDescription vmstate_spk = {
+    .name = "pcspk",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(data_on, PCSpkState),
+        VMSTATE_UINT8(dummy_refresh_clock, PCSpkState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static Property pcspk_properties[] = {
     DEFINE_PROP_UINT32("iobase", PCSpkState, iobase,  -1),
     DEFINE_PROP_END_OF_LIST(),
@@ -198,6 +210,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
 
     dc->realize = pcspk_realizefn;
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
+    dc->vmsd = &vmstate_spk;
     dc->props = pcspk_properties;
     /* Reason: realize sets global pcspk_state */
     dc->cannot_instantiate_with_device_add_yet = true;
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 3bf1ddd976..a1cd9b5a29 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -768,6 +768,7 @@ static void kvmvapic_vm_state_change(void *opaque, int running,
     }
 
     qemu_del_vm_change_state_handler(s->vmsentry);
+    s->vmsentry = NULL;
 }
 
 static int vapic_post_load(void *opaque, int version_id)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e31f70f428..2d6d7920ff 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -161,13 +161,15 @@ int cpu_get_pic_interrupt(CPUX86State *env)
     X86CPU *cpu = x86_env_get_cpu(env);
     int intno;
 
-    intno = apic_get_interrupt(cpu->apic_state);
-    if (intno >= 0) {
-        return intno;
-    }
-    /* read the irq from the PIC */
-    if (!apic_accept_pic_intr(cpu->apic_state)) {
-        return -1;
+    if (!kvm_irqchip_in_kernel()) {
+        intno = apic_get_interrupt(cpu->apic_state);
+        if (intno >= 0) {
+            return intno;
+        }
+        /* read the irq from the PIC */
+        if (!apic_accept_pic_intr(cpu->apic_state)) {
+            return -1;
+        }
     }
 
     intno = pic_read_irq(isa_pic);
@@ -180,7 +182,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
     X86CPU *cpu = X86_CPU(cs);
 
     DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
-    if (cpu->apic_state) {
+    if (cpu->apic_state && !kvm_irqchip_in_kernel()) {
         CPU_FOREACH(cs) {
             cpu = X86_CPU(cs);
             if (apic_accept_pic_intr(cpu->apic_state)) {
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 45887d99c0..7bd1d279c4 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -39,6 +39,10 @@
 
 static APICCommonState *local_apics[MAX_APICS + 1];
 
+#define TYPE_APIC "apic"
+#define APIC(obj) \
+    OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC)
+
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
 static void apic_update_irq(APICCommonState *s);
 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
@@ -163,7 +167,7 @@ static void apic_local_deliver(APICCommonState *s, int vector)
 
 void apic_deliver_pic_intr(DeviceState *dev, int level)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
 
     if (level) {
         apic_local_deliver(s, APIC_LVT_LINT0);
@@ -373,7 +377,7 @@ static void apic_update_irq(APICCommonState *s)
 
 void apic_poll_irq(DeviceState *dev)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
 
     apic_sync_vapic(s, SYNC_FROM_VAPIC);
     apic_update_irq(s);
@@ -479,7 +483,7 @@ static void apic_startup(APICCommonState *s, int vector_num)
 
 void apic_sipi(DeviceState *dev)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
 
     cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 
@@ -493,7 +497,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
                          uint8_t delivery_mode, uint8_t vector_num,
                          uint8_t trigger_mode)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
     uint32_t deliver_bitmask[MAX_APIC_WORDS];
     int dest_shorthand = (s->icr[0] >> 18) & 3;
     APICCommonState *apic_iter;
@@ -550,7 +554,7 @@ static bool apic_check_pic(APICCommonState *s)
 
 int apic_get_interrupt(DeviceState *dev)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
     int intno;
 
     /* if the APIC is installed or enabled, we let the 8259 handle the
@@ -584,7 +588,7 @@ int apic_get_interrupt(DeviceState *dev)
 
 int apic_accept_pic_intr(DeviceState *dev)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
     uint32_t lvt0;
 
     if (!s)
@@ -663,7 +667,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
     if (!dev) {
         return 0;
     }
-    s = APIC_COMMON(dev);
+    s = APIC(dev);
 
     index = (addr >> 4) & 0xff;
     switch(index) {
@@ -766,7 +770,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
     if (!dev) {
         return;
     }
-    s = APIC_COMMON(dev);
+    s = APIC(dev);
 
     trace_apic_mem_writel(addr, val);
 
@@ -870,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = {
 
 static void apic_realize(DeviceState *dev, Error **errp)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
 
     if (s->id >= MAX_APICS) {
         error_setg(errp, "%s initialization failed. APIC ID %d is invalid",
@@ -889,7 +893,7 @@ static void apic_realize(DeviceState *dev, Error **errp)
 
 static void apic_unrealize(DeviceState *dev, Error **errp)
 {
-    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonState *s = APIC(dev);
 
     timer_del(s->timer);
     timer_free(s->timer);
@@ -912,7 +916,7 @@ static void apic_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo apic_info = {
-    .name          = "apic",
+    .name          = TYPE_APIC,
     .instance_size = sizeof(APICCommonState),
     .parent        = TYPE_APIC_COMMON,
     .class_init    = apic_class_init,
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 40a2ebca20..f803dfd5b3 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -628,7 +628,6 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
     s->msg_buffered_bytes = 0;
 
     fd = qemu_chr_fe_get_msgfd(s->server_chr);
-    IVSHMEM_DPRINTF("posn is %" PRId64 ", fd is %d\n", msg, fd);
 
     process_msg(s, msg, fd, &err);
     if (err) {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 6a68e594d5..1776b1b3c4 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -180,7 +180,7 @@ static void fw_cfg_bootsplash(FWCfgState *s)
         temp = qemu_opt_get(opts, "splash-time");
         if (temp != NULL) {
             p = (char *)temp;
-            boot_splash_time = strtol(p, (char **)&p, 10);
+            boot_splash_time = strtol(p, &p, 10);
         }
     }
 
@@ -240,7 +240,7 @@ static void fw_cfg_reboot(FWCfgState *s)
         temp = qemu_opt_get(opts, "reboot-timeout");
         if (temp != NULL) {
             p = (char *)temp;
-            reboot_timeout = strtol(p, (char **)&p, 10);
+            reboot_timeout = strtol(p, &p, 10);
         }
     }
     /* validate the input */
diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index c67febca2f..a9ffc87f19 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -71,11 +71,5 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
                         hwaddr ram_sizes[2],
                         uint32_t sysclk, qemu_irq **picp,
                         int do_init);
-/* IBM STBxxx microcontrollers */
-CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2],
-                           hwaddr ram_bases[2],
-                           hwaddr ram_sizes[2],
-                           uint32_t sysclk, qemu_irq **picp,
-                           ram_addr_t *offsetp);
 
 #endif /* PPC405_H */
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 48e38b2bbe..e741da1141 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -426,7 +426,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
         goto out;
     }
 
-    sclp_c->execute(sclp, (SCCB *)&work_sccb, code);
+    sclp_c->execute(sclp, &work_sccb, code);
 
     cpu_physical_memory_write(sccb, &work_sccb,
                               be16_to_cpu(work_sccb.h.length));
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 904e357581..b58ab21d4c 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -183,7 +183,6 @@ typedef struct VirtIORNGCcw {
     VirtIORNG vdev;
 } VirtIORNGCcw;
 
-void virtio_ccw_device_update_status(SubchDev *sch);
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
 
 #ifdef CONFIG_VIRTFS
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index 0e0a22f696..ad87e78fe2 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -304,7 +304,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s,
         goto bad;
     }
 
-    req = g_new(MPTSASRequest, 1);
+    req = g_new0(MPTSASRequest, 1);
     QTAILQ_INSERT_TAIL(&s->pending, req, next);
     req->scsi_io = *scsi_io;
     req->dev = s;
@@ -1269,7 +1269,7 @@ static const struct SCSIBusInfo mptsas_scsi_info = {
     .load_request = mptsas_load_request,
 };
 
-static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
+static void mptsas_scsi_realize(PCIDevice *dev, Error **errp)
 {
     DeviceState *d = DEVICE(dev);
     MPTSASState *s = MPT_SAS(dev);
@@ -1426,7 +1426,7 @@ static void mptsas1068_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
 
-    pc->realize = mptsas_scsi_init;
+    pc->realize = mptsas_scsi_realize;
     pc->exit = mptsas_scsi_uninit;
     pc->romfile = 0;
     pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 77cba31e30..88beaf4bb8 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -396,7 +396,7 @@ static void scsi_read_data(SCSIRequest *req)
         return;
     }
 
-    if (s->tray_open) {
+    if (!blk_is_available(req->dev->conf.blk)) {
         scsi_read_complete(r, -ENOMEDIUM);
         return;
     }
@@ -519,7 +519,7 @@ static void scsi_write_data(SCSIRequest *req)
         scsi_write_complete_noio(r, 0);
         return;
     }
-    if (s->tray_open) {
+    if (!blk_is_available(req->dev->conf.blk)) {
         scsi_write_complete_noio(r, -ENOMEDIUM);
         return;
     }
@@ -792,10 +792,7 @@ static inline bool media_is_dvd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!blk_is_inserted(s->qdev.conf.blk)) {
-        return false;
-    }
-    if (s->tray_open) {
+    if (!blk_is_available(s->qdev.conf.blk)) {
         return false;
     }
     blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
@@ -808,10 +805,7 @@ static inline bool media_is_cd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!blk_is_inserted(s->qdev.conf.blk)) {
-        return false;
-    }
-    if (s->tray_open) {
+    if (!blk_is_available(s->qdev.conf.blk)) {
         return false;
     }
     blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
@@ -875,7 +869,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
     }
 
     if (format != 0xff) {
-        if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
+        if (!blk_is_available(s->qdev.conf.blk)) {
             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
             return -1;
         }
@@ -1857,7 +1851,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         break;
 
     default:
-        if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
+        if (!blk_is_available(s->qdev.conf.blk)) {
             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
             return 0;
         }
@@ -1886,7 +1880,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
     memset(outbuf, 0, r->buflen);
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk));
+        assert(blk_is_available(s->qdev.conf.blk));
         break;
     case INQUIRY:
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -2126,7 +2120,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
 
     command = buf[0];
 
-    if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
+    if (!blk_is_available(s->qdev.conf.blk)) {
         scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
         return 0;
     }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index ce57ef6248..e596b64741 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -236,6 +236,13 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
     g_free(n);
 }
 
+static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
+{
+    if (s->dataplane_started && d && blk_is_available(d->conf.blk)) {
+        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
+    }
+}
+
 /* Return 0 if the request is ready to be completed and return to guest;
  * -EINPROGRESS if the request is submitted and will be completed later, in the
  *  case of async cancellation. */
@@ -247,9 +254,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
     int target;
     int ret = 0;
 
-    if (s->dataplane_started && d) {
-        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
-    }
+    virtio_scsi_ctx_check(s, d);
     /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
     req->resp.tmf.response = VIRTIO_SCSI_S_OK;
 
@@ -539,9 +544,7 @@ static bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req
         virtio_scsi_complete_cmd_req(req);
         return false;
     }
-    if (s->dataplane_started) {
-        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
-    }
+    virtio_scsi_ctx_check(s, d);
     req->sreq = scsi_req_new(d, req->req.cmd.tag,
                              virtio_scsi_get_lun(req->req.cmd.lun),
                              req->req.cmd.cdb, req);
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index babac5a68a..a5ce7dea8e 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -247,8 +247,11 @@ static hwaddr
 pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr)
 {
     uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx);
+    uint32_t ring_size = PVSCSI_MAX_NUM_PAGES_REQ_RING
+                            * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
 
-    if (ready_ptr != mgr->consumed_ptr) {
+    if (ready_ptr != mgr->consumed_ptr
+        && ready_ptr - mgr->consumed_ptr < ring_size) {
         uint32_t next_ready_ptr =
             mgr->consumed_ptr++ & mgr->txr_len_mask;
         uint32_t next_ready_page =
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
index ccc9e75894..14d4007c1c 100644
--- a/hw/sh4/shix.c
+++ b/hw/sh4/shix.c
@@ -23,7 +23,7 @@
  */
 /*
    Shix 2.0 board by Alexis Polti, described at
-   http://perso.enst.fr/~polti/realisations/shix20/
+   https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
 
    More information in target-sh4/README.sh4
 */
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
index 8d3520f5be..19dd587207 100644
--- a/hw/tricore/tricore_testboard.c
+++ b/hw/tricore/tricore_testboard.c
@@ -46,7 +46,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
     long kernel_size;
 
     kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
-                           NULL, (uint64_t *)&entry, NULL,
+                           NULL, &entry, NULL,
                            NULL, 0,
                            EM_TRICORE, 1, 0);
     if (kernel_size <= 0) {
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1be85ae75a..58d95fffb2 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -48,6 +48,9 @@ enum mtp_code {
     CMD_GET_OBJECT_INFO            = 0x1008,
     CMD_GET_OBJECT                 = 0x1009,
     CMD_GET_PARTIAL_OBJECT         = 0x101b,
+    CMD_GET_OBJECT_PROPS_SUPPORTED = 0x9801,
+    CMD_GET_OBJECT_PROP_DESC       = 0x9802,
+    CMD_GET_OBJECT_PROP_VALUE      = 0x9803,
 
     /* response codes */
     RES_OK                         = 0x2001,
@@ -59,10 +62,12 @@ enum mtp_code {
     RES_INCOMPLETE_TRANSFER        = 0x2007,
     RES_INVALID_STORAGE_ID         = 0x2008,
     RES_INVALID_OBJECT_HANDLE      = 0x2009,
+    RES_INVALID_OBJECT_FORMAT_CODE = 0x200b,
     RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
     RES_INVALID_PARENT_OBJECT      = 0x201a,
     RES_INVALID_PARAMETER          = 0x201d,
     RES_SESSION_ALREADY_OPEN       = 0x201e,
+    RES_INVALID_OBJECT_PROP_CODE   = 0xA801,
 
     /* format codes */
     FMT_UNDEFINED_OBJECT           = 0x3000,
@@ -72,6 +77,22 @@ enum mtp_code {
     EVT_OBJ_ADDED                  = 0x4002,
     EVT_OBJ_REMOVED                = 0x4003,
     EVT_OBJ_INFO_CHANGED           = 0x4007,
+
+    /* object properties */
+    PROP_STORAGE_ID                = 0xDC01,
+    PROP_OBJECT_FORMAT             = 0xDC02,
+    PROP_OBJECT_COMPRESSED_SIZE    = 0xDC04,
+    PROP_PARENT_OBJECT             = 0xDC0B,
+    PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41,
+    PROP_NAME                      = 0xDC44,
+};
+
+enum mtp_data_type {
+    DATA_TYPE_UINT16  = 0x0004,
+    DATA_TYPE_UINT32  = 0x0006,
+    DATA_TYPE_UINT64  = 0x0008,
+    DATA_TYPE_UINT128 = 0x000a,
+    DATA_TYPE_STRING  = 0xffff,
 };
 
 typedef struct {
@@ -115,8 +136,8 @@ struct MTPControl {
 struct MTPData {
     uint16_t     code;
     uint32_t     trans;
-    uint32_t     offset;
-    uint32_t     length;
+    uint64_t     offset;
+    uint64_t     length;
     uint32_t     alloc;
     uint8_t      *data;
     bool         first;
@@ -778,6 +799,9 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
         CMD_GET_OBJECT_INFO,
         CMD_GET_OBJECT,
         CMD_GET_PARTIAL_OBJECT,
+        CMD_GET_OBJECT_PROPS_SUPPORTED,
+        CMD_GET_OBJECT_PROP_DESC,
+        CMD_GET_OBJECT_PROP_VALUE,
     };
     static const uint16_t fmt[] = {
         FMT_UNDEFINED_OBJECT,
@@ -883,7 +907,12 @@ static MTPData *usb_mtp_get_object_info(MTPState *s, MTPControl *c,
     usb_mtp_add_u32(d, QEMU_STORAGE_ID);
     usb_mtp_add_u16(d, o->format);
     usb_mtp_add_u16(d, 0);
-    usb_mtp_add_u32(d, o->stat.st_size);
+
+    if (o->stat.st_size > 0xFFFFFFFF) {
+        usb_mtp_add_u32(d, 0xFFFFFFFF);
+    } else {
+        usb_mtp_add_u32(d, o->stat.st_size);
+    }
 
     usb_mtp_add_u16(d, 0);
     usb_mtp_add_u32(d, 0);
@@ -966,6 +995,122 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c,
     return d;
 }
 
+static MTPData *usb_mtp_get_object_props_supported(MTPState *s, MTPControl *c)
+{
+    static const uint16_t props[] = {
+        PROP_STORAGE_ID,
+        PROP_OBJECT_FORMAT,
+        PROP_OBJECT_COMPRESSED_SIZE,
+        PROP_PARENT_OBJECT,
+        PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER,
+        PROP_NAME,
+    };
+    MTPData *d = usb_mtp_data_alloc(c);
+    usb_mtp_add_u16_array(d, ARRAY_SIZE(props), props);
+
+    return d;
+}
+
+static MTPData *usb_mtp_get_object_prop_desc(MTPState *s, MTPControl *c)
+{
+    MTPData *d = usb_mtp_data_alloc(c);
+    switch (c->argv[0]) {
+    case PROP_STORAGE_ID:
+        usb_mtp_add_u16(d, PROP_STORAGE_ID);
+        usb_mtp_add_u16(d, DATA_TYPE_UINT32);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    case PROP_OBJECT_FORMAT:
+        usb_mtp_add_u16(d, PROP_OBJECT_FORMAT);
+        usb_mtp_add_u16(d, DATA_TYPE_UINT16);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u16(d, 0x0000);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    case PROP_OBJECT_COMPRESSED_SIZE:
+        usb_mtp_add_u16(d, PROP_OBJECT_COMPRESSED_SIZE);
+        usb_mtp_add_u16(d, DATA_TYPE_UINT64);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u64(d, 0x0000000000000000);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    case PROP_PARENT_OBJECT:
+        usb_mtp_add_u16(d, PROP_PARENT_OBJECT);
+        usb_mtp_add_u16(d, DATA_TYPE_UINT32);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
+        usb_mtp_add_u16(d, PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER);
+        usb_mtp_add_u16(d, DATA_TYPE_UINT128);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u64(d, 0x0000000000000000);
+        usb_mtp_add_u64(d, 0x0000000000000000);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    case PROP_NAME:
+        usb_mtp_add_u16(d, PROP_NAME);
+        usb_mtp_add_u16(d, DATA_TYPE_STRING);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u8(d, 0x00);
+        usb_mtp_add_u32(d, 0x00000000);
+        usb_mtp_add_u8(d, 0x00);
+        break;
+    default:
+        usb_mtp_data_free(d);
+        return NULL;
+    }
+
+    return d;
+}
+
+static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
+                                              MTPObject *o)
+{
+    MTPData *d = usb_mtp_data_alloc(c);
+    switch (c->argv[1]) {
+    case PROP_STORAGE_ID:
+        usb_mtp_add_u32(d, QEMU_STORAGE_ID);
+        break;
+    case PROP_OBJECT_FORMAT:
+        usb_mtp_add_u16(d, o->format);
+        break;
+    case PROP_OBJECT_COMPRESSED_SIZE:
+        usb_mtp_add_u64(d, o->stat.st_size);
+        break;
+    case PROP_PARENT_OBJECT:
+        if (o->parent == NULL) {
+            usb_mtp_add_u32(d, 0x00000000);
+        } else {
+            usb_mtp_add_u32(d, o->parent->handle);
+        }
+        break;
+    case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
+        /* Should be persistant between sessions,
+         * but using our objedt ID is "good enough"
+         * for now */
+        usb_mtp_add_u64(d, 0x0000000000000000);
+        usb_mtp_add_u64(d, o->handle);
+        break;
+    case PROP_NAME:
+        usb_mtp_add_str(d, o->name);
+        break;
+    default:
+        usb_mtp_data_free(d);
+        return NULL;
+    }
+
+    return d;
+}
+
 static void usb_mtp_command(MTPState *s, MTPControl *c)
 {
     MTPData *data_in = NULL;
@@ -1113,6 +1258,43 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
         nres = 1;
         res0 = data_in->length;
         break;
+    case CMD_GET_OBJECT_PROPS_SUPPORTED:
+        if (c->argv[0] != FMT_UNDEFINED_OBJECT &&
+            c->argv[0] != FMT_ASSOCIATION) {
+            usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
+                                 c->trans, 0, 0, 0);
+            return;
+        }
+        data_in = usb_mtp_get_object_props_supported(s, c);
+        break;
+    case CMD_GET_OBJECT_PROP_DESC:
+        if (c->argv[1] != FMT_UNDEFINED_OBJECT &&
+            c->argv[1] != FMT_ASSOCIATION) {
+            usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
+                                 c->trans, 0, 0, 0);
+            return;
+        }
+        data_in = usb_mtp_get_object_prop_desc(s, c);
+        if (data_in == NULL) {
+            usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
+                                 c->trans, 0, 0, 0);
+            return;
+        }
+        break;
+    case CMD_GET_OBJECT_PROP_VALUE:
+        o = usb_mtp_object_lookup(s, c->argv[0]);
+        if (o == NULL) {
+            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
+                                 c->trans, 0, 0, 0);
+            return;
+        }
+        data_in = usb_mtp_get_object_prop_value(s, c, o);
+        if (data_in == NULL) {
+            usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
+                                 c->trans, 0, 0, 0);
+            return;
+        }
+        break;
     default:
         trace_usb_mtp_op_unknown(s->dev.addr, c->code);
         usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED,
@@ -1193,10 +1375,15 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
         }
         if (s->data_in !=  NULL) {
             MTPData *d = s->data_in;
-            int dlen = d->length - d->offset;
+            uint64_t dlen = d->length - d->offset;
             if (d->first) {
                 trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length);
-                container.length = cpu_to_le32(d->length + sizeof(container));
+                if (d->length + sizeof(container) > 0xFFFFFFFF) {
+                    container.length = cpu_to_le32(0xFFFFFFFF);
+                } else {
+                    container.length =
+                        cpu_to_le32(d->length + sizeof(container));
+                }
                 container.type   = cpu_to_le16(TYPE_DATA);
                 container.code   = cpu_to_le16(d->code);
                 container.trans  = cpu_to_le32(d->trans);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 188f95416a..726435c462 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1753,6 +1753,12 @@ static void xhci_xfer_report(XHCITransfer *xfer)
         unsigned int chunk = 0;
 
         switch (TRB_TYPE(*trb)) {
+        case TR_SETUP:
+            chunk = trb->status & 0x1ffff;
+            if (chunk > 8) {
+                chunk = 8;
+            }
+            break;
         case TR_DATA:
         case TR_NORMAL:
         case TR_ISOCH:
@@ -3709,8 +3715,7 @@ static void usb_xhci_exit(PCIDevice *dev)
     /* destroy msix memory region */
     if (dev->msix_table && dev->msix_pba
         && dev->msix_entry_used) {
-        memory_region_del_subregion(&xhci->mem, &dev->msix_table_mmio);
-        memory_region_del_subregion(&xhci->mem, &dev->msix_pba_mmio);
+        msix_uninit(dev, &xhci->mem, &xhci->mem);
     }
 
     usb_bus_release(&xhci->bus);
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index e94672c155..bd81d71a98 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -743,10 +743,13 @@ static void usb_host_speed_compat(USBHostDevice *s)
                         rc = libusb_get_ss_endpoint_companion_descriptor
                             (ctx, endp, &endp_ss_comp);
                         if (rc == LIBUSB_SUCCESS) {
+                            int streams = endp_ss_comp->bmAttributes & 0x1f;
+                            if (streams) {
+                                compat_full = false;
+                                compat_high = false;
+                            }
                             libusb_free_ss_endpoint_companion_descriptor
                                 (endp_ss_comp);
-                            compat_full = false;
-                            compat_high = false;
                         }
 #endif
                         break;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 7bfa17ce38..a5a620a0c4 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -496,7 +496,9 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
             vfio_update_kvm_msi_virq(vector, *msg, pdev);
         }
     } else {
-        vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+        if (msg) {
+            vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+        }
     }
 
     /*