[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/17] xhci: Call usb_device_alloc/free_streams
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 12/17] xhci: Call usb_device_alloc/free_streams |
Date: |
Fri, 29 Nov 2013 09:06:16 +0100 |
From: Hans de Goede <address@hidden>
Note this code is not as KISS as I would like, the reason for this is that
the Linux kernel interface wants streams on eps belonging to one interface
to be allocated in one call. Things will also work if we do this one ep at a
time (as long as all eps support the same amount of streams), but lets stick
to the kernel API.
Signed-off-by: Hans de Goede <address@hidden>
Signed-off-by: Gerd Hoffmann <address@hidden>
---
hw/usb/hcd-xhci.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 220e99d..bafe085 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1150,6 +1150,111 @@ static void xhci_free_streams(XHCIEPContext *epctx)
epctx->nr_pstreams = 0;
}
+static int xhci_epmask_to_eps_with_streams(XHCIState *xhci,
+ unsigned int slotid,
+ uint32_t epmask,
+ XHCIEPContext **epctxs,
+ USBEndpoint **eps)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+ USBEndpoint *ep;
+ int i, j;
+
+ assert(slotid >= 1 && slotid <= xhci->numslots);
+
+ slot = &xhci->slots[slotid - 1];
+
+ for (i = 2, j = 0; i <= 31; i++) {
+ if (!(epmask & (1 << i))) {
+ continue;
+ }
+
+ epctx = slot->eps[i - 1];
+ ep = xhci_epid_to_usbep(xhci, slotid, i);
+ if (!epctx || !epctx->nr_pstreams || !ep) {
+ continue;
+ }
+
+ if (epctxs) {
+ epctxs[j] = epctx;
+ }
+ eps[j++] = ep;
+ }
+ return j;
+}
+
+static void xhci_free_device_streams(XHCIState *xhci, unsigned int slotid,
+ uint32_t epmask)
+{
+ USBEndpoint *eps[30];
+ int nr_eps;
+
+ nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, NULL, eps);
+ if (nr_eps) {
+ usb_device_free_streams(eps[0]->dev, eps, nr_eps);
+ }
+}
+
+static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid,
+ uint32_t epmask)
+{
+ XHCIEPContext *epctxs[30];
+ USBEndpoint *eps[30];
+ int i, r, nr_eps, req_nr_streams, dev_max_streams;
+
+ nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, epctxs,
+ eps);
+ if (nr_eps == 0) {
+ return CC_SUCCESS;
+ }
+
+ req_nr_streams = epctxs[0]->nr_pstreams;
+ dev_max_streams = eps[0]->max_streams;
+
+ for (i = 1; i < nr_eps; i++) {
+ /*
+ * HdG: I don't expect these to ever trigger, but if they do we need
+ * to come up with another solution, ie group identical endpoints
+ * together and make an usb_device_alloc_streams call per group.
+ */
+ if (epctxs[i]->nr_pstreams != req_nr_streams) {
+ FIXME("guest streams config not identical for all eps");
+ return CC_RESOURCE_ERROR;
+ }
+ if (eps[i]->max_streams != dev_max_streams) {
+ FIXME("device streams config not identical for all eps");
+ return CC_RESOURCE_ERROR;
+ }
+ }
+
+ /*
+ * max-streams in both the device descriptor and in the controller is a
+ * power of 2. But stream id 0 is reserved, so if a device can do up to 4
+ * streams the guest will ask for 5 rounded up to the next power of 2 which
+ * becomes 8. For emulated devices usb_device_alloc_streams is a nop.
+ *
+ * For redirected devices however this is an issue, as there we must ask
+ * the real xhci controller to alloc streams, and the host driver for the
+ * real xhci controller will likely disallow allocating more streams then
+ * the device can handle.
+ *
+ * So we limit the requested nr_streams to the maximum number the device
+ * can handle.
+ */
+ if (req_nr_streams > dev_max_streams) {
+ req_nr_streams = dev_max_streams;
+ }
+
+ r = usb_device_alloc_streams(eps[0]->dev, eps, nr_eps, req_nr_streams);
+ if (r != 0) {
+ fprintf(stderr, "xhci: alloc streams failed\n");
+ return CC_RESOURCE_ERROR;
+ }
+
+ return CC_SUCCESS;
+}
+
static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
unsigned int streamid,
uint32_t *cc_error)
@@ -2322,6 +2427,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci,
unsigned int slotid,
return CC_CONTEXT_STATE_ERROR;
}
+ xhci_free_device_streams(xhci, slotid, ictl_ctx[0] | ictl_ctx[1]);
+
for (i = 2; i <= 31; i++) {
if (ictl_ctx[0] & (1<<i)) {
xhci_disable_ep(xhci, slotid, i);
@@ -2343,6 +2450,16 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci,
unsigned int slotid,
}
}
+ res = xhci_alloc_device_streams(xhci, slotid, ictl_ctx[1]);
+ if (res != CC_SUCCESS) {
+ for (i = 2; i <= 31; i++) {
+ if (ictl_ctx[1] & (1 << i)) {
+ xhci_disable_ep(xhci, slotid, i);
+ }
+ }
+ return res;
+ }
+
slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
--
1.8.3.1
- [Qemu-devel] [PULL 00/17] usb patch queue, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 02/17] xhci: add support for suspend/resume, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 01/17] xhci: Add a few missing checks for disconnected devices, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 13/17] ehci: implement port wakeup, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 11/17] usb: Add usb_device_alloc/free_streams, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 12/17] xhci: Call usb_device_alloc/free_streams,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 17/17] usb: move usb_{hi, lo} helpers to header file., Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 07/17] uas: Bounds check tags when using streams, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 14/17] Revert "usb-tablet: Don't claim wakeup capability for USB-2 version", Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 06/17] uas: Streams are numbered 1-y, rather then 0-x, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 15/17] trace-events: Clean up after removal of old usb-host code, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 08/17] uas: Fix response iu struct definition, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 09/17] uas: s/ui/iu/, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 16/17] usb: add vendor request defines, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 04/17] uas: Only use report iu-s for task_mgmt status reporting, Gerd Hoffmann, 2013/11/29
- [Qemu-devel] [PATCH 10/17] usb: Add max_streams attribute to endpoint info, Gerd Hoffmann, 2013/11/29