return cur_seg;
 }
 
-struct dequeue_state {
-       struct xhci_segment *new_deq_seg;
-       union xhci_trb *new_deq_ptr;
-       int new_cycle_state;
-};
-
 /*
  * Move the xHC's endpoint ring dequeue pointer past cur_td.
  * Record the new state of the xHC's endpoint ring dequeue segment,
  *  - Finally we move the dequeue state one TRB further, toggling the cycle bit
  *    if we've moved it past a link TRB with the toggle cycle bit set.
  */
-static void find_new_dequeue_state(struct xhci_hcd *xhci,
+void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
                unsigned int slot_id, unsigned int ep_index,
-               struct xhci_td *cur_td, struct dequeue_state *state)
+               struct xhci_td *cur_td, struct xhci_dequeue_state *state)
 {
        struct xhci_virt_device *dev = xhci->devs[slot_id];
        struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
        struct xhci_generic_trb *trb;
        struct xhci_ep_ctx *ep_ctx;
+       dma_addr_t addr;
 
        state->new_cycle_state = 0;
+       xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
        state->new_deq_seg = find_trb_seg(cur_td->start_seg,
                        ep_ring->stopped_trb,
                        &state->new_cycle_state);
        if (!state->new_deq_seg)
                BUG();
        /* Dig out the cycle state saved by the xHC during the stop ep cmd */
+       xhci_dbg(xhci, "Finding endpoint context\n");
        ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
        state->new_cycle_state = 0x1 & ep_ctx->deq;
 
        state->new_deq_ptr = cur_td->last_trb;
+       xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n");
        state->new_deq_seg = find_trb_seg(state->new_deq_seg,
                        state->new_deq_ptr,
                        &state->new_cycle_state);
        next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
        /* Don't update the ring cycle state for the producer (us). */
+       xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
+                       state->new_deq_seg);
+       addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
+       xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
+                       (unsigned long long) addr);
+       xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
        ep_ring->dequeue = state->new_deq_ptr;
        ep_ring->deq_seg = state->new_deq_seg;
 }
                unsigned int ep_index, struct xhci_segment *deq_seg,
                union xhci_trb *deq_ptr, u32 cycle_state);
 
+void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+               struct xhci_ring *ep_ring, unsigned int slot_id,
+               unsigned int ep_index, struct xhci_dequeue_state *deq_state)
+{
+       xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
+                       "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
+                       deq_state->new_deq_seg,
+                       (unsigned long long)deq_state->new_deq_seg->dma,
+                       deq_state->new_deq_ptr,
+                       (unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
+                       deq_state->new_cycle_state);
+       queue_set_tr_deq(xhci, slot_id, ep_index,
+                       deq_state->new_deq_seg,
+                       deq_state->new_deq_ptr,
+                       (u32) deq_state->new_cycle_state);
+       /* Stop the TD queueing code from ringing the doorbell until
+        * this command completes.  The HC won't set the dequeue pointer
+        * if the ring is running, and ringing the doorbell starts the
+        * ring running.
+        */
+       ep_ring->state |= SET_DEQ_PENDING;
+       xhci_ring_cmd_db(xhci);
+}
+
 /*
  * When we get a command completion for a Stop Endpoint Command, we need to
  * unlink any cancelled TDs from the ring.  There are two ways to do that:
        struct xhci_td *cur_td = 0;
        struct xhci_td *last_unlinked_td;
 
-       struct dequeue_state deq_state;
+       struct xhci_dequeue_state deq_state;
 #ifdef CONFIG_USB_HCD_STAT
        ktime_t stop_time = ktime_get();
 #endif
                 * move the xHC endpoint ring dequeue pointer past this TD.
                 */
                if (cur_td == ep_ring->stopped_td)
-                       find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
+                       xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
                                        &deq_state);
                else
                        td_to_noop(xhci, ep_ring, cur_td);
 
        /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
        if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
-               xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
-                               "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
-                               deq_state.new_deq_seg,
-                               (unsigned long long)deq_state.new_deq_seg->dma,
-                               deq_state.new_deq_ptr,
-                               (unsigned long long)xhci_trb_virt_to_dma(deq_state.new_deq_seg, deq_state.new_deq_ptr),
-                               deq_state.new_cycle_state);
-               queue_set_tr_deq(xhci, slot_id, ep_index,
-                               deq_state.new_deq_seg,
-                               deq_state.new_deq_ptr,
-                               (u32) deq_state.new_cycle_state);
-               /* Stop the TD queueing code from ringing the doorbell until
-                * this command completes.  The HC won't set the dequeue pointer
-                * if the ring is running, and ringing the doorbell starts the
-                * ring running.
-                */
-               ep_ring->state |= SET_DEQ_PENDING;
-               xhci_ring_cmd_db(xhci);
+               xhci_queue_new_dequeue_state(xhci, ep_ring,
+                               slot_id, ep_index, &deq_state);
        } else {
                /* Otherwise just ring the doorbell to restart the ring */
                ring_ep_doorbell(xhci, slot_id, ep_index);
                if (event_trb != ep_ring->dequeue) {
                        /* The event was for the status stage */
                        if (event_trb == td->last_trb) {
-                               /* Did we already see a short data stage? */
-                               if (td->urb->actual_length != 0)
-                                       status = -EREMOTEIO;
-                               else
+                               if (td->urb->actual_length != 0) {
+                                       /* Don't overwrite a previously set error code */
+                                       if (status == -EINPROGRESS || status == 0)
+                                               /* Did we already see a short data stage? */
+                                               status = -EREMOTEIO;
+                               } else {
                                        td->urb->actual_length =
                                                td->urb->transfer_buffer_length;
+                               }
                        } else {
                        /* Maybe the event was for the data stage? */
                                if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
                                                        TRB_LEN(event->transfer_len));
                                        td->urb->actual_length = 0;
                                }
-                               if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-                                       status = -EREMOTEIO;
-                               else
-                                       status = 0;
+                               /* Don't overwrite a previously set error code */
+                               if (status == -EINPROGRESS) {
+                                       if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+                                               status = -EREMOTEIO;
+                                       else
+                                               status = 0;
+                               }
                        } else {
                                td->urb->actual_length = td->urb->transfer_buffer_length;
                                /* Ignore a short packet completion if the
                                 * untransferred length was zero.
                                 */
-                               status = 0;
+                               if (status == -EREMOTEIO)
+                                       status = 0;
                        }
                } else {
                        /* Slow path - walk the list, starting from the dequeue
                                        TRB_LEN(event->transfer_len);
                }
        }
-       /* The Endpoint Stop Command completion will take care of
-        * any stopped TDs.  A stopped TD may be restarted, so don't update the
-        * ring dequeue pointer or take this TD off any lists yet.
-        */
        if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
                        GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
+               /* The Endpoint Stop Command completion will take care of any
+                * stopped TDs.  A stopped TD may be restarted, so don't update
+                * the ring dequeue pointer or take this TD off any lists yet.
+                */
                ep_ring->stopped_td = td;
                ep_ring->stopped_trb = event_trb;
        } else {
-               /* Update ring dequeue pointer */
-               while (ep_ring->dequeue != td->last_trb)
+               if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
+                       /* The transfer is completed from the driver's
+                        * perspective, but we need to issue a set dequeue
+                        * command for this stalled endpoint to move the dequeue
+                        * pointer past the TD.  We can't do that here because
+                        * the halt condition must be cleared first.
+                        */
+                       ep_ring->stopped_td = td;
+                       ep_ring->stopped_trb = event_trb;
+               } else {
+                       /* Update ring dequeue pointer */
+                       while (ep_ring->dequeue != td->last_trb)
+                               inc_deq(xhci, ep_ring, false);
                        inc_deq(xhci, ep_ring, false);
-               inc_deq(xhci, ep_ring, false);
+               }
 
                /* Clean up the endpoint's TD list */
                urb = td->urb;
                        list_del(&td->cancelled_td_list);
                        ep_ring->cancels_pending--;
                }
-               kfree(td);
+               /* Leave the TD around for the reset endpoint function to use */
+               if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+                       kfree(td);
+               }
                urb->hcpriv = NULL;
        }
 cleanup:
                 */
                xhci_warn(xhci, "WARN urb submitted to disabled ep\n");
                return -ENOENT;
-       case EP_STATE_HALTED:
        case EP_STATE_ERROR:
-               xhci_warn(xhci, "WARN waiting for halt or error on ep "
-                               "to be cleared\n");
+               xhci_warn(xhci, "WARN waiting for error on ep to be cleared\n");
                /* FIXME event handling code for error needs to clear it */
                /* XXX not sure if this should be -ENOENT or not */
                return -EINVAL;
+       case EP_STATE_HALTED:
+               xhci_dbg(xhci, "WARN halted endpoint, queueing URB anyway.\n");
        case EP_STATE_STOPPED:
        case EP_STATE_RUNNING:
                break;
        u32 type = TRB_TYPE(TRB_SET_DEQ);
 
        addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
-       if (addr == 0)
+       if (addr == 0) {
                xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
                xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
                                deq_seg, deq_ptr);
+               return 0;
+       }
        return queue_command(xhci, lower_32_bits(addr) | cycle_state,
                        upper_32_bits(addr), 0,
                        trb_slot_id | trb_ep_index | type);