summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2014-05-08 19:26:03 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-20 10:03:25 +0900
commitc311e391a7efd101250c0e123286709b7e736249 (patch)
tree5d26094a50efde190578e3f16cef2827992706ae /drivers/usb/host/xhci-mem.c
parent9ea1833e4c210ac5580f63495be15502f275c578 (diff)
xhci: rework command timeout and cancellation,
Use one timer to control command timeout. start/kick the timer every time a command is completed and a new command is waiting, or a new command is added to a empty list. If the timer runs out, then tag the current command as "aborted", and start the xhci command abortion process. Previously each function that submitted a command had its own timer. If that command timed out, a new command structure for the command was created and it was put on a cancel_cmd_list list, then a pci write to abort the command ring was issued. when the ring was aborted, it checked if the current command was the one to be canceled, later when the ring was stopped the driver got ownership of the TRBs in the command ring, compared then to the TRBs in the cancel_cmd_list, and turned them into No-ops. Now, instead, at timeout we tag the status of the command in the command queue to be aborted, and start the ring abortion. Ring abortion stops the command ring and gives control of the commands to us. All the aborted commands are now turned into No-ops. If the ring is already stopped when the command times outs its not possible to start the ring abortion, in this case the command is turnd to No-op right away. All these changes allows us to remove the entire cancel_cmd_list code. The functions waiting for a command to finish no longer have their own timeouts. They will wait either until the command completes normally, or until the whole command abortion is done. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 38dc721bc8bb..6a57e81c2a76 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1793,10 +1793,11 @@ void xhci_free_command(struct xhci_hcd *xhci,
void xhci_mem_cleanup(struct xhci_hcd *xhci)
{
struct device *dev = xhci_to_hcd(xhci)->self.controller;
- struct xhci_cd *cur_cd, *next_cd;
int size;
int i, j, num_ports;
+ del_timer_sync(&xhci->cmd_timer);
+
/* Free the Event Ring Segment Table and the actual Event Ring */
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries)
@@ -1815,11 +1816,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
- list_for_each_entry_safe(cur_cd, next_cd,
- &xhci->cancel_cmd_list, cancel_cmd_list) {
- list_del(&cur_cd->cancel_cmd_list);
- kfree(cur_cd);
- }
xhci_cleanup_command_queue(xhci);
for (i = 1; i < MAX_HC_SLOTS; ++i)
@@ -2323,7 +2319,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
u32 page_size, temp;
int i;
- INIT_LIST_HEAD(&xhci->cancel_cmd_list);
INIT_LIST_HEAD(&xhci->cmd_list);
page_size = readl(&xhci->op_regs->page_size);
@@ -2510,6 +2505,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
"Wrote ERST address to ir_set 0.");
xhci_print_ir_set(xhci, 0);
+ /* init command timeout timer */
+ init_timer(&xhci->cmd_timer);
+ xhci->cmd_timer.data = (unsigned long) xhci;
+ xhci->cmd_timer.function = xhci_handle_command_timeout;
+
/*
* XXX: Might need to set the Interrupter Moderation Register to
* something other than the default (~1ms minimum between interrupts).