* [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue
@ 2013-05-07 9:50 Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 1/4] usb-host: live migration support for the libusb version Gerd Hoffmann
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-05-07 9:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hi,
A few small usb fixes for 1.5. Two host controller bugfixes, and two
small enhancements for the libusb based usb-host implementation. They
bring the libusb on par with the old linux usbfs implementation and are
needed to make sure usb passthrough doesn't lose features in 1.5.
please pull,
Gerd
The following changes since commit b5803aa3583e82e5133f7621121bc15ee694f4a1:
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging (2013-05-06 15:45:08 -0500)
are available in the git repository at:
git://git.kraxel.org/qemu usb.82
for you to fetch changes up to 4e906d567a97ee45b4922001bf521dad0bde5268:
xhci: handle USB_RET_BABBLE (2013-05-07 11:34:03 +0200)
----------------------------------------------------------------
Gerd Hoffmann (3):
usb-host: live migration support for the libusb version
usb-host: add usb_host_full_speed_compat
xhci: handle USB_RET_BABBLE
Hans de Goede (1):
uhci: Use an intermediate buffer for usb packet data
hw/usb/hcd-uhci.c | 21 ++++++-----
hw/usb/hcd-xhci.c | 5 +++
hw/usb/host-libusb.c | 94 +++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 104 insertions(+), 16 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 1/4] usb-host: live migration support for the libusb version
2013-05-07 9:50 [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue Gerd Hoffmann
@ 2013-05-07 9:50 ` Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 2/4] usb-host: add usb_host_full_speed_compat Gerd Hoffmann
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-05-07 9:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/host-libusb.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index d1186b8..ee67c4c 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -94,7 +94,8 @@ struct USBHostDevice {
} ifs[USB_MAX_INTERFACES];
/* callbacks & friends */
- QEMUBH *bh;
+ QEMUBH *bh_nodev;
+ QEMUBH *bh_postld;
Notifier exit;
/* request queues */
@@ -835,10 +836,10 @@ static void usb_host_nodev_bh(void *opaque)
static void usb_host_nodev(USBHostDevice *s)
{
- if (!s->bh) {
- s->bh = qemu_bh_new(usb_host_nodev_bh, s);
+ if (!s->bh_nodev) {
+ s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s);
}
- qemu_bh_schedule(s->bh);
+ qemu_bh_schedule(s->bh_nodev);
}
static void usb_host_exit_notifier(struct Notifier *n, void *data)
@@ -1228,9 +1229,52 @@ static void usb_host_handle_reset(USBDevice *udev)
usb_host_ep_update(s);
}
+/*
+ * This is *NOT* about restoring state. We have absolutely no idea
+ * what state the host device is in at the moment and whenever it is
+ * still present in the first place. Attemping to contine where we
+ * left off is impossible.
+ *
+ * What we are going to to to here is emulate a surprise removal of
+ * the usb device passed through, then kick host scan so the device
+ * will get re-attached (and re-initialized by the guest) in case it
+ * is still present.
+ *
+ * As the device removal will change the state of other devices (usb
+ * host controller, most likely interrupt controller too) we have to
+ * wait with it until *all* vmstate is loaded. Thus post_load just
+ * kicks a bottom half which then does the actual work.
+ */
+static void usb_host_post_load_bh(void *opaque)
+{
+ USBHostDevice *dev = opaque;
+ USBDevice *udev = USB_DEVICE(dev);
+
+ if (dev->dh != NULL) {
+ usb_host_close(dev);
+ }
+ if (udev->attached) {
+ usb_device_detach(udev);
+ }
+ usb_host_auto_check(NULL);
+}
+
+static int usb_host_post_load(void *opaque, int version_id)
+{
+ USBHostDevice *dev = opaque;
+
+ if (!dev->bh_postld) {
+ dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev);
+ }
+ qemu_bh_schedule(dev->bh_postld);
+ return 0;
+}
+
static const VMStateDescription vmstate_usb_host = {
.name = "usb-host",
- .unmigratable = 1,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = usb_host_post_load,
.fields = (VMStateField[]) {
VMSTATE_USB_DEVICE(parent_obj, USBHostDevice),
VMSTATE_END_OF_LIST()
--
1.7.9.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/4] usb-host: add usb_host_full_speed_compat
2013-05-07 9:50 [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 1/4] usb-host: live migration support for the libusb version Gerd Hoffmann
@ 2013-05-07 9:50 ` Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 3/4] uhci: Use an intermediate buffer for usb packet data Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 4/4] xhci: handle USB_RET_BABBLE Gerd Hoffmann
3 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-05-07 9:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Alloes to pass through usb2 devices on usb1 host controllers if possible.
Brings the libusb implementation to feature-parity with the linux usbfs
code, so the usb-host implementation in 1.5 (libusb) doesn't regress
compared to 1.4 (usbfs).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/host-libusb.c | 40 +++++++++++++++++++++++++++++++++++++---
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index ee67c4c..f3de459 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -667,6 +667,42 @@ static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p)
/* ------------------------------------------------------------------------ */
+static bool usb_host_full_speed_compat(USBHostDevice *s)
+{
+ struct libusb_config_descriptor *conf;
+ const struct libusb_interface_descriptor *intf;
+ const struct libusb_endpoint_descriptor *endp;
+ uint8_t type;
+ int rc, c, i, a, e;
+
+ for (c = 0;; c++) {
+ rc = libusb_get_config_descriptor(s->dev, c, &conf);
+ if (rc != 0) {
+ break;
+ }
+ for (i = 0; i < conf->bNumInterfaces; i++) {
+ for (a = 0; a < conf->interface[i].num_altsetting; a++) {
+ intf = &conf->interface[i].altsetting[a];
+ for (e = 0; e < intf->bNumEndpoints; e++) {
+ endp = &intf->endpoint[e];
+ type = endp->bmAttributes & 0x3;
+ switch (type) {
+ case 0x01: /* ISO */
+ return false;
+ case 0x03: /* INTERRUPT */
+ if (endp->wMaxPacketSize > 64) {
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ }
+ libusb_free_config_descriptor(conf);
+ }
+ return true;
+}
+
static void usb_host_ep_update(USBHostDevice *s)
{
static const char *tname[] = {
@@ -758,11 +794,9 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev)
udev->speed = speed_map[libusb_get_device_speed(dev)];
udev->speedmask = (1 << udev->speed);
-#if 0
- if (udev->speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
+ if (udev->speed == USB_SPEED_HIGH && usb_host_full_speed_compat(s)) {
udev->speedmask |= USB_SPEED_MASK_FULL;
}
-#endif
if (s->ddesc.iProduct) {
libusb_get_string_descriptor_ascii(s->dh, s->ddesc.iProduct,
--
1.7.9.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 3/4] uhci: Use an intermediate buffer for usb packet data
2013-05-07 9:50 [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 1/4] usb-host: live migration support for the libusb version Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 2/4] usb-host: add usb_host_full_speed_compat Gerd Hoffmann
@ 2013-05-07 9:50 ` Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 4/4] xhci: handle USB_RET_BABBLE Gerd Hoffmann
3 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-05-07 9:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann
From: Hans de Goede <hdegoede@redhat.com>
Due to various unfortunate reasons we cannot reliable detect a guest
cancelling a packet as soon as it happens, instead we detect cancels
with some delay.
When packets are handled async, and we directly pass the guest memory for
the packet to the usb-device as iovec, this means that the usb-device can
write to guest-memory which the guest has already re-used for other purposes
-> not good!
This patch fixes this by adding an intermediate buffer and writing back not
only the result, but also the data, of async completed packets when scanning
the schedule.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-uhci.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index f8c4286..c85b203 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -119,7 +119,8 @@ struct UHCIPCIDeviceClass {
struct UHCIAsync {
USBPacket packet;
- QEMUSGList sgl;
+ uint8_t static_buf[64]; /* 64 bytes is enough, except for isoc packets */
+ uint8_t *buf;
UHCIQueue *queue;
QTAILQ_ENTRY(UHCIAsync) next;
uint32_t td_addr;
@@ -264,7 +265,6 @@ static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr)
async->queue = queue;
async->td_addr = td_addr;
usb_packet_init(&async->packet);
- pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
trace_usb_uhci_packet_add(async->queue->token, async->td_addr);
return async;
@@ -274,7 +274,9 @@ static void uhci_async_free(UHCIAsync *async)
{
trace_usb_uhci_packet_del(async->queue->token, async->td_addr);
usb_packet_cleanup(&async->packet);
- qemu_sglist_destroy(&async->sgl);
+ if (async->buf != async->static_buf) {
+ g_free(async->buf);
+ }
g_free(async);
}
@@ -299,7 +301,6 @@ static void uhci_async_cancel(UHCIAsync *async)
async->done);
if (!async->done)
usb_cancel_packet(&async->packet);
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
}
@@ -774,6 +775,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
*int_mask |= 0x01;
if (pid == USB_TOKEN_IN) {
+ pci_dma_write(&s->dev, td->buffer, async->buf, len);
if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
*int_mask |= 0x02;
/* short packet: do not update QH */
@@ -881,12 +883,17 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0);
usb_packet_setup(&async->packet, pid, q->ep, 0, td_addr, spd,
(td->ctrl & TD_CTRL_IOC) != 0);
- qemu_sglist_add(&async->sgl, td->buffer, max_len);
- usb_packet_map(&async->packet, &async->sgl);
+ if (max_len <= sizeof(async->static_buf)) {
+ async->buf = async->static_buf;
+ } else {
+ async->buf = g_malloc(max_len);
+ }
+ usb_packet_addbuf(&async->packet, async->buf, max_len);
switch(pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
+ pci_dma_read(&s->dev, td->buffer, async->buf, max_len);
usb_handle_packet(q->ep->dev, &async->packet);
if (async->packet.status == USB_RET_SUCCESS) {
async->packet.actual_length = max_len;
@@ -899,7 +906,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
default:
/* invalid pid : frame interrupted */
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
s->status |= UHCI_STS_HCPERR;
uhci_update_irq(s);
@@ -916,7 +922,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
done:
ret = uhci_complete_td(s, td, async, int_mask);
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
return ret;
}
--
1.7.9.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 4/4] xhci: handle USB_RET_BABBLE
2013-05-07 9:50 [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue Gerd Hoffmann
` (2 preceding siblings ...)
2013-05-07 9:50 ` [Qemu-devel] [PATCH 3/4] uhci: Use an intermediate buffer for usb packet data Gerd Hoffmann
@ 2013-05-07 9:50 ` Gerd Hoffmann
3 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-05-07 9:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-xhci.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 2c90e56..8813bdf 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1716,6 +1716,11 @@ static int xhci_complete_packet(XHCITransfer *xfer)
xhci_xfer_report(xfer);
xhci_stall_ep(xfer);
break;
+ case USB_RET_BABBLE:
+ xfer->status = CC_BABBLE_DETECTED;
+ xhci_xfer_report(xfer);
+ xhci_stall_ep(xfer);
+ break;
default:
fprintf(stderr, "%s: FIXME: status = %d\n", __func__,
xfer->packet.status);
--
1.7.9.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-05-07 10:24 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-07 9:50 [Qemu-devel] [PULL for-1.5 0/4] usb patch qeue Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 1/4] usb-host: live migration support for the libusb version Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 2/4] usb-host: add usb_host_full_speed_compat Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 3/4] uhci: Use an intermediate buffer for usb packet data Gerd Hoffmann
2013-05-07 9:50 ` [Qemu-devel] [PATCH 4/4] xhci: handle USB_RET_BABBLE Gerd Hoffmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).