/** * Is this TRB a link TRB or was the last TRB the last TRB in this event ring * segment? I.e. would the updated event TRB pointer step off the end of the * event seg ? * * @param ctrl Host controller data structure * @param ring pointer to the ring * @param seg poniter to the segment to which TRB belongs * @param trb poniter to the ring trb * @return 1 if this TRB a link TRB else 0 */ static int last_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring, struct xhci_segment *seg, union xhci_trb *trb) { if (ring == ctrl->event_ring) return trb == &seg->trbs[TRBS_PER_SEGMENT]; else return TRB_TYPE_LINK_LE32(trb->link.control); }
/* * Stop device * It issues stop endpoint command for EP 0 to 30. And wait the last command * to complete. * suspend will set to 1, if suspend bit need to set in command. */ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) { struct xhci_virt_device *virt_dev; struct xhci_command *cmd; unsigned long flags; int timeleft; int ret; int i; ret = 0; virt_dev = xhci->devs[slot_id]; cmd = etxhci_alloc_command(xhci, false, true, GFP_NOIO); if (!cmd) { xhci_dbg(xhci, "Couldn't allocate command structure.\n"); return -ENOMEM; } spin_lock_irqsave(&xhci->lock, flags); for (i = LAST_EP_INDEX; i > 0; i--) { if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) etxhci_queue_stop_endpoint(xhci, slot_id, i, suspend); } cmd->command_trb = xhci->cmd_ring->enqueue; /* Enqueue pointer can be left pointing to the link TRB, * we must handle that */ if (TRB_TYPE_LINK_LE32(cmd->command_trb->link.control)) cmd->command_trb = xhci->cmd_ring->enq_seg->next->trbs; list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list); etxhci_queue_stop_endpoint(xhci, slot_id, 0, suspend); etxhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); /* Wait for last stop endpoint command to finish */ timeleft = wait_for_completion_interruptible_timeout( cmd->completion, USB_CTRL_SET_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for stop endpoint command\n", timeleft == 0 ? "Timeout" : "Signal"); spin_lock_irqsave(&xhci->lock, flags); /* The timeout might have raced with the event ring handler, so * only delete from the list if the item isn't poisoned. */ if (cmd->cmd_list.next != LIST_POISON1) list_del(&cmd->cmd_list); spin_unlock_irqrestore(&xhci->lock, flags); ret = -ETIME; goto command_cleanup; } command_cleanup: etxhci_free_command(xhci, cmd); return ret; }