Loading drivers/usb/host/xhci-ring.c +33 −52 Original line number Diff line number Diff line Loading @@ -1367,47 +1367,11 @@ static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, return 0; } /* * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the * trb pointed by the command ring dequeue pointer is the trb we want to * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will * traverse the cancel_cmd_list to trun the all of the commands according * to command descriptor to NO-OP trb. */ static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, int cmd_trb_comp_code) { int cur_trb_is_good = 0; /* Searching the cmd trb pointed by the command ring dequeue * pointer in command descriptor list. If it is found, free it. */ cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, xhci->cmd_ring->dequeue); if (cmd_trb_comp_code == COMP_CMD_ABORT) xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; else if (cmd_trb_comp_code == COMP_CMD_STOP) { /* traversing the cancel_cmd_list and canceling * the command according to command descriptor */ xhci_cancel_cmd_in_cd_list(xhci); xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; /* * ring command ring doorbell again to restart the * command ring */ if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) xhci_ring_cmd_db(xhci); } return cur_trb_is_good; } static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); int comp_code = GET_COMP_CODE(le32_to_cpu(event->status)); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; struct xhci_input_control_ctx *ctrl_ctx; Loading @@ -1430,16 +1394,34 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, return; } if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { /* If the return value is 0, we think the trb pointed by * command ring dequeue pointer is a good trb. The good * trb means we don't want to cancel the trb, but it have * been stopped by host. So we should handle it normally. * Otherwise, driver should invoke inc_deq() and return. */ if (handle_stopped_cmd_ring(xhci, GET_COMP_CODE(le32_to_cpu(event->status)))) { /* * Command Ring Stopped events point at the xHC's *current* dequeue * pointer, i.e. the next command that will be executed. That TRB may * or may not have been issued yet. Just overwrite all canceled commands * with NOOPs and restart the ring, leaving our internal dequeue pointer * as it is (we will get another event for that position later, when * it has actually been executed). */ if (comp_code == COMP_CMD_STOP) { xhci_cancel_cmd_in_cd_list(xhci); xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) xhci_ring_cmd_db(xhci); return; } /* * If we aborted a command, we check if it is one of the commands we * meant to cancel. In that case, it will be freed and we just finish * up right here. If we aborted something else instead, we run it * through the normal handlers below. At any rate, the command ring is * stopped now, but the xHC will issue a Command Ring Stopped event * after this that will cause us to restart it. */ if (comp_code == COMP_CMD_ABORT) { xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; if (xhci_search_cmd_trb_in_cd_list(xhci, xhci->cmd_ring->dequeue)) { inc_deq(xhci, xhci->cmd_ring); return; } Loading @@ -1454,7 +1436,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): if (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_SUCCESS) if (comp_code == COMP_SUCCESS) xhci->slot_id = slot_id; else xhci->slot_id = 0; Loading Loading @@ -1510,19 +1492,18 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, } bandwidth_change: xhci_dbg(xhci, "Completed config ep cmd\n"); xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_EVAL_CONTEXT): virt_dev = xhci->devs[slot_id]; if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) break; xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_ADDR_DEV): xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->addr_dev); break; case TRB_TYPE(TRB_STOP_RING): Loading Loading
drivers/usb/host/xhci-ring.c +33 −52 Original line number Diff line number Diff line Loading @@ -1367,47 +1367,11 @@ static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, return 0; } /* * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the * trb pointed by the command ring dequeue pointer is the trb we want to * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will * traverse the cancel_cmd_list to trun the all of the commands according * to command descriptor to NO-OP trb. */ static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, int cmd_trb_comp_code) { int cur_trb_is_good = 0; /* Searching the cmd trb pointed by the command ring dequeue * pointer in command descriptor list. If it is found, free it. */ cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, xhci->cmd_ring->dequeue); if (cmd_trb_comp_code == COMP_CMD_ABORT) xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; else if (cmd_trb_comp_code == COMP_CMD_STOP) { /* traversing the cancel_cmd_list and canceling * the command according to command descriptor */ xhci_cancel_cmd_in_cd_list(xhci); xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; /* * ring command ring doorbell again to restart the * command ring */ if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) xhci_ring_cmd_db(xhci); } return cur_trb_is_good; } static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); int comp_code = GET_COMP_CODE(le32_to_cpu(event->status)); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; struct xhci_input_control_ctx *ctrl_ctx; Loading @@ -1430,16 +1394,34 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, return; } if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { /* If the return value is 0, we think the trb pointed by * command ring dequeue pointer is a good trb. The good * trb means we don't want to cancel the trb, but it have * been stopped by host. So we should handle it normally. * Otherwise, driver should invoke inc_deq() and return. */ if (handle_stopped_cmd_ring(xhci, GET_COMP_CODE(le32_to_cpu(event->status)))) { /* * Command Ring Stopped events point at the xHC's *current* dequeue * pointer, i.e. the next command that will be executed. That TRB may * or may not have been issued yet. Just overwrite all canceled commands * with NOOPs and restart the ring, leaving our internal dequeue pointer * as it is (we will get another event for that position later, when * it has actually been executed). */ if (comp_code == COMP_CMD_STOP) { xhci_cancel_cmd_in_cd_list(xhci); xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) xhci_ring_cmd_db(xhci); return; } /* * If we aborted a command, we check if it is one of the commands we * meant to cancel. In that case, it will be freed and we just finish * up right here. If we aborted something else instead, we run it * through the normal handlers below. At any rate, the command ring is * stopped now, but the xHC will issue a Command Ring Stopped event * after this that will cause us to restart it. */ if (comp_code == COMP_CMD_ABORT) { xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; if (xhci_search_cmd_trb_in_cd_list(xhci, xhci->cmd_ring->dequeue)) { inc_deq(xhci, xhci->cmd_ring); return; } Loading @@ -1454,7 +1436,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): if (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_SUCCESS) if (comp_code == COMP_SUCCESS) xhci->slot_id = slot_id; else xhci->slot_id = 0; Loading Loading @@ -1510,19 +1492,18 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, } bandwidth_change: xhci_dbg(xhci, "Completed config ep cmd\n"); xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_EVAL_CONTEXT): virt_dev = xhci->devs[slot_id]; if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) break; xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->devs[slot_id]->cmd_completion); break; case TRB_TYPE(TRB_ADDR_DEV): xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); xhci->devs[slot_id]->cmd_status = comp_code; complete(&xhci->addr_dev); break; case TRB_TYPE(TRB_STOP_RING): Loading