From: Mathias Nyman Date: Thu, 8 May 2014 16:26:02 +0000 (+0300) Subject: xhci: Use completion and status in global command queue X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=9ea1833e4c210ac5580f63495be15502f275c578;p=openwrt%2Fstaging%2Fblogic.git xhci: Use completion and status in global command queue Remove the per-device command list and handle_cmd_in_cmd_wait_list() and use the completion and status variables found in the command structure in the global command list. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 3ce9c0ac2614..12871b5d4a2e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -299,7 +299,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) suspend); } } - list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list); xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); @@ -311,18 +310,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) 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: xhci_free_command(xhci, cmd); return ret; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b070a17bf53f..38dc721bc8bb 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1020,7 +1020,6 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, dev->num_rings_cached = 0; init_completion(&dev->cmd_completion); - INIT_LIST_HEAD(&dev->cmd_list); dev->udev = udev; /* Point to output device context in dcbaa. */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 89b874567548..3d60865a3d8f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -69,10 +69,6 @@ #include "xhci.h" #include "xhci-trace.h" -static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, - struct xhci_virt_device *virt_dev, - struct xhci_event_cmd *event); - /* * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA * address of the TRB. @@ -765,7 +761,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, union xhci_trb *trb, struct xhci_event_cmd *event) { unsigned int ep_index; - struct xhci_virt_device *virt_dev; struct xhci_ring *ep_ring; struct xhci_virt_ep *ep; struct list_head *entry; @@ -775,11 +770,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, struct xhci_dequeue_state deq_state; if (unlikely(TRB_TO_SUSPEND_PORT(le32_to_cpu(trb->generic.field[3])))) { - virt_dev = xhci->devs[slot_id]; - if (virt_dev) - handle_cmd_in_cmd_wait_list(xhci, virt_dev, - event); - else + if (!xhci->devs[slot_id]) xhci_warn(xhci, "Stop endpoint command " "completion for disabled slot %u\n", slot_id); @@ -1229,29 +1220,6 @@ static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, } -/* Check to see if a command in the device's command queue matches this one. - * Signal the completion or free the command, and return 1. Return 0 if the - * completed command isn't at the head of the command list. - */ -static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, - struct xhci_virt_device *virt_dev, - struct xhci_event_cmd *event) -{ - struct xhci_command *command; - - if (list_empty(&virt_dev->cmd_list)) - return 0; - - command = list_entry(virt_dev->cmd_list.next, - struct xhci_command, cmd_list); - if (xhci->cmd_ring->dequeue != command->command_trb) - return 0; - - xhci_complete_cmd_in_cmd_wait_list(xhci, command, - GET_COMP_CODE(le32_to_cpu(event->status))); - return 1; -} - /* * Finding the command trb need to be cancelled and modifying it to * NO OP command. And if the command is in device's command wait @@ -1403,7 +1371,6 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id, xhci->slot_id = slot_id; else xhci->slot_id = 0; - complete(&xhci->addr_dev); } static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) @@ -1428,9 +1395,6 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, unsigned int ep_state; u32 add_flags, drop_flags; - virt_dev = xhci->devs[slot_id]; - if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) - return; /* * Configure endpoint commands can come from the USB core * configuration or alt setting changes, or because the HW @@ -1439,6 +1403,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, * If the command was for a halted endpoint, the xHCI driver * is not waiting on the configure endpoint command. */ + virt_dev = xhci->devs[slot_id]; ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); if (!ctrl_ctx) { xhci_warn(xhci, "Could not get input context, bad type.\n"); @@ -1474,35 +1439,11 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, return; } -static void xhci_handle_cmd_eval_ctx(struct xhci_hcd *xhci, int slot_id, - struct xhci_event_cmd *event, u32 cmd_comp_code) -{ - struct xhci_virt_device *virt_dev; - - virt_dev = xhci->devs[slot_id]; - if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) - return; - virt_dev->cmd_status = cmd_comp_code; - complete(&virt_dev->cmd_completion); -} - -static void xhci_handle_cmd_addr_dev(struct xhci_hcd *xhci, int slot_id, - u32 cmd_comp_code) -{ - xhci->devs[slot_id]->cmd_status = cmd_comp_code; - complete(&xhci->addr_dev); -} - static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id, struct xhci_event_cmd *event) { - struct xhci_virt_device *virt_dev; - xhci_dbg(xhci, "Completed reset device command.\n"); - virt_dev = xhci->devs[slot_id]; - if (virt_dev) - handle_cmd_in_cmd_wait_list(xhci, virt_dev, event); - else + if (!xhci->devs[slot_id]) xhci_warn(xhci, "Reset device command completion " "for disabled slot %u\n", slot_id); } @@ -1520,18 +1461,23 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci, NEC_FW_MINOR(le32_to_cpu(event->status))); } -static void xhci_del_and_free_cmd(struct xhci_command *cmd) +static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 status) { list_del(&cmd->cmd_list); - if (!cmd->completion) + + if (cmd->completion) { + cmd->status = status; + complete(cmd->completion); + } else { kfree(cmd); + } } void xhci_cleanup_command_queue(struct xhci_hcd *xhci) { struct xhci_command *cur_cmd, *tmp_cmd; list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list, cmd_list) - xhci_del_and_free_cmd(cur_cmd); + xhci_complete_del_and_free_cmd(cur_cmd, COMP_CMD_ABORT); } static void handle_cmd_completion(struct xhci_hcd *xhci, @@ -1598,13 +1544,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci_handle_cmd_disable_slot(xhci, slot_id); break; case TRB_CONFIG_EP: - xhci_handle_cmd_config_ep(xhci, slot_id, event, cmd_comp_code); + if (!cmd->completion) + xhci_handle_cmd_config_ep(xhci, slot_id, event, + cmd_comp_code); break; case TRB_EVAL_CONTEXT: - xhci_handle_cmd_eval_ctx(xhci, slot_id, event, cmd_comp_code); break; case TRB_ADDR_DEV: - xhci_handle_cmd_addr_dev(xhci, slot_id, cmd_comp_code); break; case TRB_STOP_RING: WARN_ON(slot_id != TRB_TO_SLOT_ID( @@ -1637,7 +1583,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, break; } - xhci_del_and_free_cmd(cmd); + xhci_complete_del_and_free_cmd(cmd, cmd_comp_code); inc_deq(xhci, xhci->cmd_ring); } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8dbc41032177..64c1ba353856 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2626,8 +2626,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, return -ENOMEM; } - list_add_tail(&command->cmd_list, &virt_dev->cmd_list); - if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, command, command->in_ctx->dma, @@ -2637,7 +2635,6 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, command->in_ctx->dma, udev->slot_id, must_succeed); if (ret < 0) { - list_del(&command->cmd_list); if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) xhci_free_host_resources(xhci, ctrl_ctx); spin_unlock_irqrestore(&xhci->lock, flags); @@ -3499,11 +3496,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Attempt to submit the Reset Device command to the command ring */ spin_lock_irqsave(&xhci->lock, flags); - list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); ret = xhci_queue_reset_device(xhci, reset_device_cmd, slot_id); if (ret) { xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); - list_del(&reset_device_cmd->cmd_list); spin_unlock_irqrestore(&xhci->lock, flags); goto command_cleanup; } @@ -3517,13 +3512,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for reset device 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 (reset_device_cmd->cmd_list.next != LIST_POISON1) - list_del(&reset_device_cmd->cmd_list); - spin_unlock_irqrestore(&xhci->lock, flags); ret = -ETIME; goto command_cleanup; } @@ -3895,7 +3883,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, return -ETIME; } - switch (virt_dev->cmd_status) { + switch (command->status) { case COMP_CTX_STATE: case COMP_EBADSLT: xhci_err(xhci, "Setup ERROR: setup %s command for slot %d.\n", @@ -3918,7 +3906,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, default: xhci_err(xhci, "ERROR: unexpected setup %s command completion code 0x%x.\n", - act, virt_dev->cmd_status); + act, command->status); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d33cd3750a15..fde57b09a9bd 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -937,9 +937,6 @@ struct xhci_virt_device { #define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; struct completion cmd_completion; - /* Status of the last command issued for this device */ - u32 cmd_status; - struct list_head cmd_list; u8 fake_port; u8 real_port; struct xhci_interval_bw_table *bw_table;