aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-08-03 14:25:09 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-08-03 14:25:10 +0100
commit6eac5f7bad6cd8f56b3514ac485dd35d79abff66 (patch)
tree4b9a0226dbf8e12c999d10529bc66f8c76a02107 /hw
parent0cb34ff32e3123d79daac898496ed479aede7954 (diff)
parent0e39bb022b5fa8c11964968885f3263c02ce42b0 (diff)
Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160803-1' into staging
usb: bugfixes for xen-usb and ehci, mingw build fix. # gpg: Signature made Wed 03 Aug 2016 14:04:26 BST # gpg: using RSA key 0x4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/pull-usb-20160803-1: xen: use a common function for pv and hvm guest backend register calls xen: drain submit queue in xen-usb before removing device xen: when removing a backend don't remove many of them ehci: faster frame index calculation for skipped frames wxx: Fix compilation of host-libusb.c wxx: Fix compiler warning for host-libusb.c Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb/hcd-ehci.c31
-rw-r--r--hw/usb/host-libusb.c10
-rw-r--r--hw/usb/xen-usb.c96
-rw-r--r--hw/xen/xen_backend.c68
-rw-r--r--hw/xenpv/xen_machine_pv.c7
5 files changed, 114 insertions, 98 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 43a8f7abcc..b093db729c 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2206,29 +2206,28 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
static void ehci_update_frindex(EHCIState *ehci, int uframes)
{
- int i;
-
if (!ehci_enabled(ehci) && ehci->pstate == EST_INACTIVE) {
return;
}
- for (i = 0; i < uframes; i++) {
- ehci->frindex++;
-
- if (ehci->frindex == 0x00002000) {
- ehci_raise_irq(ehci, USBSTS_FLR);
- }
+ /* Generate FLR interrupt if frame index rolls over 0x2000 */
+ if ((ehci->frindex % 0x2000) + uframes >= 0x2000) {
+ ehci_raise_irq(ehci, USBSTS_FLR);
+ }
- if (ehci->frindex == 0x00004000) {
- ehci_raise_irq(ehci, USBSTS_FLR);
- ehci->frindex = 0;
- if (ehci->usbsts_frindex >= 0x00004000) {
- ehci->usbsts_frindex -= 0x00004000;
- } else {
- ehci->usbsts_frindex = 0;
- }
+ /* How many times will frindex roll over 0x4000 with this frame count?
+ * usbsts_frindex is decremented by 0x4000 on rollover until it reaches 0
+ */
+ int rollovers = (ehci->frindex + uframes) / 0x4000;
+ if (rollovers > 0) {
+ if (ehci->usbsts_frindex >= (rollovers * 0x4000)) {
+ ehci->usbsts_frindex -= 0x4000 * rollovers;
+ } else {
+ ehci->usbsts_frindex = 0;
}
}
+
+ ehci->frindex = (ehci->frindex + uframes) % 0x4000;
}
static void ehci_frame_timer(void *opaque)
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index da59c294bb..e94672c155 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -235,7 +235,7 @@ static int usb_host_init(void)
#ifndef CONFIG_WIN32
const struct libusb_pollfd **poll;
#endif
- int i, rc;
+ int rc;
if (ctx) {
return 0;
@@ -253,6 +253,7 @@ static int usb_host_init(void)
ctx);
poll = libusb_get_pollfds(ctx);
if (poll) {
+ int i;
for (i = 0; poll[i] != NULL; i++) {
usb_host_add_fd(poll[i]->fd, poll[i]->events, ctx);
}
@@ -358,7 +359,7 @@ static USBHostRequest *usb_host_req_find(USBHostDevice *s, USBPacket *p)
return NULL;
}
-static void usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
+static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
{
USBHostRequest *r = xfer->user_data;
USBHostDevice *s = r->host;
@@ -391,7 +392,7 @@ out:
}
}
-static void usb_host_req_complete_data(struct libusb_transfer *xfer)
+static void LIBUSB_CALL usb_host_req_complete_data(struct libusb_transfer *xfer)
{
USBHostRequest *r = xfer->user_data;
USBHostDevice *s = r->host;
@@ -447,7 +448,8 @@ static void usb_host_req_abort(USBHostRequest *r)
/* ------------------------------------------------------------------------ */
-static void usb_host_req_complete_iso(struct libusb_transfer *transfer)
+static void LIBUSB_CALL
+usb_host_req_complete_iso(struct libusb_transfer *transfer)
{
USBHostIsoXfer *xfer = transfer->user_data;
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index 799245654a..174d715e3e 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -90,6 +90,8 @@ struct usbback_req {
void *buffer;
void *isoc_buffer;
struct libusb_transfer *xfer;
+
+ bool cancelled;
};
struct usbback_hotplug {
@@ -301,20 +303,23 @@ static void usbback_do_response(struct usbback_req *usbback_req, int32_t status,
usbback_req->isoc_buffer = NULL;
}
- res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt);
- res->id = usbback_req->req.id;
- res->status = status;
- res->actual_length = actual_length;
- res->error_count = error_count;
- res->start_frame = 0;
- usbif->urb_ring.rsp_prod_pvt++;
- RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify);
-
- if (notify) {
- xen_be_send_notify(xendev);
+ if (usbif->urb_sring) {
+ res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt);
+ res->id = usbback_req->req.id;
+ res->status = status;
+ res->actual_length = actual_length;
+ res->error_count = error_count;
+ res->start_frame = 0;
+ usbif->urb_ring.rsp_prod_pvt++;
+ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify);
+
+ if (notify) {
+ xen_be_send_notify(xendev);
+ }
}
- usbback_put_req(usbback_req);
+ if (!usbback_req->cancelled)
+ usbback_put_req(usbback_req);
}
static void usbback_do_response_ret(struct usbback_req *usbback_req,
@@ -366,15 +371,14 @@ static void usbback_set_address(struct usbback_info *usbif,
}
}
-static bool usbback_cancel_req(struct usbback_req *usbback_req)
+static void usbback_cancel_req(struct usbback_req *usbback_req)
{
- bool ret = false;
-
if (usb_packet_is_inflight(&usbback_req->packet)) {
usb_cancel_packet(&usbback_req->packet);
- ret = true;
+ QTAILQ_REMOVE(&usbback_req->stub->submit_q, usbback_req, q);
+ usbback_req->cancelled = true;
+ usbback_do_response_ret(usbback_req, -EPROTO);
}
- return ret;
}
static void usbback_process_unlink_req(struct usbback_req *usbback_req)
@@ -391,7 +395,7 @@ static void usbback_process_unlink_req(struct usbback_req *usbback_req)
devnum = usbif_pipedevice(usbback_req->req.pipe);
if (unlikely(devnum == 0)) {
usbback_req->stub = usbif->ports +
- usbif_pipeportnum(usbback_req->req.pipe);
+ usbif_pipeportnum(usbback_req->req.pipe) - 1;
if (unlikely(!usbback_req->stub)) {
ret = -ENODEV;
goto fail_response;
@@ -406,9 +410,7 @@ static void usbback_process_unlink_req(struct usbback_req *usbback_req)
QTAILQ_FOREACH(unlink_req, &usbback_req->stub->submit_q, q) {
if (unlink_req->req.id == id) {
- if (usbback_cancel_req(unlink_req)) {
- usbback_do_response_ret(unlink_req, -EPROTO);
- }
+ usbback_cancel_req(unlink_req);
break;
}
}
@@ -681,6 +683,33 @@ static void usbback_hotplug_enq(struct usbback_info *usbif, unsigned port)
usbback_hotplug_notify(usbif);
}
+static void usbback_portid_drain(struct usbback_info *usbif, unsigned port)
+{
+ struct usbback_req *req, *tmp;
+ bool sched = false;
+
+ QTAILQ_FOREACH_SAFE(req, &usbif->ports[port - 1].submit_q, q, tmp) {
+ usbback_cancel_req(req);
+ sched = true;
+ }
+
+ if (sched) {
+ qemu_bh_schedule(usbif->bh);
+ }
+}
+
+static void usbback_portid_detach(struct usbback_info *usbif, unsigned port)
+{
+ if (!usbif->ports[port - 1].attached) {
+ return;
+ }
+
+ usbif->ports[port - 1].speed = USBIF_SPEED_NONE;
+ usbif->ports[port - 1].attached = false;
+ usbback_portid_drain(usbif, port);
+ usbback_hotplug_enq(usbif, port);
+}
+
static void usbback_portid_remove(struct usbback_info *usbif, unsigned port)
{
USBPort *p;
@@ -694,9 +723,7 @@ static void usbback_portid_remove(struct usbback_info *usbif, unsigned port)
object_unparent(OBJECT(usbif->ports[port - 1].dev));
usbif->ports[port - 1].dev = NULL;
- usbif->ports[port - 1].speed = USBIF_SPEED_NONE;
- usbif->ports[port - 1].attached = false;
- usbback_hotplug_enq(usbif, port);
+ usbback_portid_detach(usbif, port);
TR_BUS(&usbif->xendev, "port %d removed\n", port);
}
@@ -801,7 +828,6 @@ static void usbback_process_port(struct usbback_info *usbif, unsigned port)
static void usbback_disconnect(struct XenDevice *xendev)
{
struct usbback_info *usbif;
- struct usbback_req *req, *tmp;
unsigned int i;
TR_BUS(xendev, "start\n");
@@ -820,11 +846,8 @@ static void usbback_disconnect(struct XenDevice *xendev)
}
for (i = 0; i < usbif->num_ports; i++) {
- if (!usbif->ports[i].dev) {
- continue;
- }
- QTAILQ_FOREACH_SAFE(req, &usbif->ports[i].submit_q, q, tmp) {
- usbback_cancel_req(req);
+ if (usbif->ports[i].dev) {
+ usbback_portid_drain(usbif, i + 1);
}
}
@@ -944,8 +967,7 @@ static void xen_bus_detach(USBPort *port)
usbif = port->opaque;
TR_BUS(&usbif->xendev, "\n");
- usbif->ports[port->index].attached = false;
- usbback_hotplug_enq(usbif, port->index + 1);
+ usbback_portid_detach(usbif, port->index + 1);
}
static void xen_bus_child_detach(USBPort *port, USBDevice *child)
@@ -958,9 +980,16 @@ static void xen_bus_child_detach(USBPort *port, USBDevice *child)
static void xen_bus_complete(USBPort *port, USBPacket *packet)
{
+ struct usbback_req *usbback_req;
struct usbback_info *usbif;
- usbif = port->opaque;
+ usbback_req = container_of(packet, struct usbback_req, packet);
+ if (usbback_req->cancelled) {
+ g_free(usbback_req);
+ return;
+ }
+
+ usbif = usbback_req->usbif;
TR_REQ(&usbif->xendev, "\n");
usbback_packet_complete(packet);
}
@@ -1037,6 +1066,7 @@ static int usbback_free(struct XenDevice *xendev)
}
usb_bus_release(&usbif->bus);
+ object_unparent(OBJECT(&usbif->bus));
TR_BUS(xendev, "finished\n");
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index bab79b1912..69a238817e 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -321,48 +321,28 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
/*
* release xen backend device.
*/
-static struct XenDevice *xen_be_del_xendev(int dom, int dev)
+static void xen_be_del_xendev(struct XenDevice *xendev)
{
- struct XenDevice *xendev, *xnext;
-
- /*
- * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
- * we save the next pointer in xnext because we might free xendev.
- */
- xnext = xendevs.tqh_first;
- while (xnext) {
- xendev = xnext;
- xnext = xendev->next.tqe_next;
-
- if (xendev->dom != dom) {
- continue;
- }
- if (xendev->dev != dev && dev != -1) {
- continue;
- }
-
- if (xendev->ops->free) {
- xendev->ops->free(xendev);
- }
-
- if (xendev->fe) {
- char token[XEN_BUFSIZE];
- snprintf(token, sizeof(token), "fe:%p", xendev);
- xs_unwatch(xenstore, xendev->fe, token);
- g_free(xendev->fe);
- }
+ if (xendev->ops->free) {
+ xendev->ops->free(xendev);
+ }
- if (xendev->evtchndev != NULL) {
- xenevtchn_close(xendev->evtchndev);
- }
- if (xendev->gnttabdev != NULL) {
- xengnttab_close(xendev->gnttabdev);
- }
+ if (xendev->fe) {
+ char token[XEN_BUFSIZE];
+ snprintf(token, sizeof(token), "fe:%p", xendev);
+ xs_unwatch(xenstore, xendev->fe, token);
+ g_free(xendev->fe);
+ }
- QTAILQ_REMOVE(&xendevs, xendev, next);
- g_free(xendev);
+ if (xendev->evtchndev != NULL) {
+ xenevtchn_close(xendev->evtchndev);
}
- return NULL;
+ if (xendev->gnttabdev != NULL) {
+ xengnttab_close(xendev->gnttabdev);
+ }
+
+ QTAILQ_REMOVE(&xendevs, xendev, next);
+ g_free(xendev);
}
/*
@@ -682,7 +662,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
if (xendev != NULL) {
bepath = xs_read(xenstore, 0, xendev->be, &len);
if (bepath == NULL) {
- xen_be_del_xendev(dom, dev);
+ xen_be_del_xendev(xendev);
} else {
free(bepath);
xen_be_backend_changed(xendev, path);
@@ -800,6 +780,16 @@ int xen_be_register(const char *type, struct XenDevOps *ops)
return xenstore_scan(type, xen_domid, ops);
}
+void xen_be_register_common(void)
+{
+ xen_be_register("console", &xen_console_ops);
+ xen_be_register("vkbd", &xen_kbdmouse_ops);
+ xen_be_register("qdisk", &xen_blkdev_ops);
+#ifdef CONFIG_USB_LIBUSB
+ xen_be_register("qusb", &xen_usb_ops);
+#endif
+}
+
int xen_be_bind_evtchn(struct XenDevice *xendev)
{
if (xendev->local_port != -1) {
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 48f725c9cd..79aef4ecc3 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -67,14 +67,9 @@ static void xen_init_pv(MachineState *machine)
break;
}
- xen_be_register("console", &xen_console_ops);
- xen_be_register("vkbd", &xen_kbdmouse_ops);
+ xen_be_register_common();
xen_be_register("vfb", &xen_framebuffer_ops);
- xen_be_register("qdisk", &xen_blkdev_ops);
xen_be_register("qnic", &xen_netdev_ops);
-#ifdef CONFIG_USB_LIBUSB
- xen_be_register("qusb", &xen_usb_ops);
-#endif
/* configure framebuffer */
if (xenfb_enabled) {