Print this page
MFV: illumos-gate@2aba3acda67326648fd60aaf2bfb4e18ee8c04ed
9816 Multi-TRB xhci transfers should use event data
9817 xhci needs to always set slot context
8550 increase xhci bulk transfer sgl count
9818 xhci_transfer_get_tdsize can return values that are too large
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Joshua M. Clulow <josh@sysmgr.org>
Author: Robert Mustacchi <rm@joyent.com>

@@ -8,11 +8,11 @@
  * source.  A copy of the CDDL is also available via the Internet at
  * http://www.illumos.org/license/CDDL.
  */
 
 /*
- * Copyright 2016 Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
  */
 
 /*
  * illumos USB framework endpoints and functions for xHCI.
  *

@@ -170,14 +170,17 @@
 
         mutex_enter(&xd->xd_imtx);
         mutex_exit(&xhcip->xhci_lock);
 
         /*
-         * Update the slot and input context for this endpoint.
+         * Update the slot and input context for this endpoint. We make sure to
+         * always set the slot as having changed in the context field as the
+         * specification suggests we should and some hardware requires it.
          */
         xd->xd_input->xic_drop_flags = LE_32(0);
-        xd->xd_input->xic_add_flags = LE_32(XHCI_INCTX_MASK_DCI(epid + 1));
+        xd->xd_input->xic_add_flags = LE_32(XHCI_INCTX_MASK_DCI(0) |
+            XHCI_INCTX_MASK_DCI(epid + 1));
 
         if (epid + 1 > XHCI_SCTX_GET_DCI(LE_32(xd->xd_slotin->xsc_info))) {
                 uint32_t info;
 
                 info = xd->xd_slotin->xsc_info;

@@ -469,15 +472,15 @@
          */
         mutex_enter(&xd->xd_imtx);
 
         /*
          * Potentially update the slot input context about the current max
-         * endpoint. While we don't update the slot context with this,
-         * surrounding code expects it to be updated to be consistent.
+         * endpoint. Make sure to set that the slot context is being updated
+         * here as it may be changing and some hardware requires it.
          */
         xd->xd_input->xic_drop_flags = LE_32(XHCI_INCTX_MASK_DCI(epid + 1));
-        xd->xd_input->xic_add_flags = LE_32(0);
+        xd->xd_input->xic_add_flags = LE_32(XHCI_INCTX_MASK_DCI(0));
         for (i = XHCI_NUM_ENDPOINTS - 1; i >= 0; i--) {
                 if (xd->xd_endpoints[i] != NULL &&
                     xd->xd_endpoints[i] != xep)
                         break;
         }

@@ -796,10 +799,11 @@
         xt->xt_trbs[xt->xt_ntrbs - 1].trb_addr = 0;
         xt->xt_trbs[xt->xt_ntrbs - 1].trb_status = LE_32(XHCI_TRB_INTR(0));
         xt->xt_trbs[xt->xt_ntrbs - 1].trb_flags = LE_32(XHCI_TRB_TYPE_STATUS |
             XHCI_TRB_IOC | statusdir);
 
+
         mutex_enter(&xhcip->xhci_lock);
 
         /*
          * Schedule the transfer, allocating resources in the process.
          */

@@ -928,21 +932,23 @@
                 xhci_trb_t *trb = &xt->xt_trbs[i];
 
                 trb->trb_addr = LE_64(buf);
 
                 /*
-                 * Beacuse we know that a single frame can have all of its data
-                 * in a single instance, we know that we don't neeed to do
+                 * Because we know that a single frame can have all of its data
+                 * in a single instance, we know that we don't need to do
                  * anything special here.
                  */
                 trb->trb_status = LE_32(XHCI_TRB_LEN(len) | XHCI_TRB_TDREM(0) |
                     XHCI_TRB_INTR(0));
 
                 /*
                  * Always enable SIA to start the frame ASAP. We also always
                  * enable an interrupt on a short packet. If this is the last
-                 * trb, then we will set IOC.
+                 * trb, then we will set IOC. Each TRB created here is really
+                 * its own TD. However, we only set an interrupt on the last
+                 * entry to better deal with scheduling.
                  */
                 flags = XHCI_TRB_SIA | XHCI_TRB_ISP | XHCI_TRB_SET_FRAME(0);
                 flags |= XHCI_TRB_TYPE_ISOCH;
 
                 if (i + 1 == usrp->isoc_pkts_count)