Skip to content

Commit c311e39

Browse files
matnymangregkh
authored andcommitted
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>
1 parent 9ea1833 commit c311e39

File tree

5 files changed

+169
-320
lines changed

5 files changed

+169
-320
lines changed

drivers/usb/host/xhci-hub.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
271271
struct xhci_virt_device *virt_dev;
272272
struct xhci_command *cmd;
273273
unsigned long flags;
274-
int timeleft;
275274
int ret;
276275
int i;
277276

@@ -304,12 +303,10 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
304303
spin_unlock_irqrestore(&xhci->lock, flags);
305304

306305
/* Wait for last stop endpoint command to finish */
307-
timeleft = wait_for_completion_interruptible_timeout(
308-
cmd->completion,
309-
XHCI_CMD_DEFAULT_TIMEOUT);
310-
if (timeleft <= 0) {
311-
xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
312-
timeleft == 0 ? "Timeout" : "Signal");
306+
wait_for_completion(cmd->completion);
307+
308+
if (cmd->status == COMP_CMD_ABORT || cmd->status == COMP_CMD_STOP) {
309+
xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
313310
ret = -ETIME;
314311
}
315312
xhci_free_command(xhci, cmd);

drivers/usb/host/xhci-mem.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,10 +1793,11 @@ void xhci_free_command(struct xhci_hcd *xhci,
17931793
void xhci_mem_cleanup(struct xhci_hcd *xhci)
17941794
{
17951795
struct device *dev = xhci_to_hcd(xhci)->self.controller;
1796-
struct xhci_cd *cur_cd, *next_cd;
17971796
int size;
17981797
int i, j, num_ports;
17991798

1799+
del_timer_sync(&xhci->cmd_timer);
1800+
18001801
/* Free the Event Ring Segment Table and the actual Event Ring */
18011802
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
18021803
if (xhci->erst.entries)
@@ -1815,11 +1816,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
18151816
xhci_ring_free(xhci, xhci->cmd_ring);
18161817
xhci->cmd_ring = NULL;
18171818
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
1818-
list_for_each_entry_safe(cur_cd, next_cd,
1819-
&xhci->cancel_cmd_list, cancel_cmd_list) {
1820-
list_del(&cur_cd->cancel_cmd_list);
1821-
kfree(cur_cd);
1822-
}
18231819
xhci_cleanup_command_queue(xhci);
18241820

18251821
for (i = 1; i < MAX_HC_SLOTS; ++i)
@@ -2323,7 +2319,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
23232319
u32 page_size, temp;
23242320
int i;
23252321

2326-
INIT_LIST_HEAD(&xhci->cancel_cmd_list);
23272322
INIT_LIST_HEAD(&xhci->cmd_list);
23282323

23292324
page_size = readl(&xhci->op_regs->page_size);
@@ -2510,6 +2505,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
25102505
"Wrote ERST address to ir_set 0.");
25112506
xhci_print_ir_set(xhci, 0);
25122507

2508+
/* init command timeout timer */
2509+
init_timer(&xhci->cmd_timer);
2510+
xhci->cmd_timer.data = (unsigned long) xhci;
2511+
xhci->cmd_timer.function = xhci_handle_command_timeout;
2512+
25132513
/*
25142514
* XXX: Might need to set the Interrupter Moderation Register to
25152515
* something other than the default (~1ms minimum between interrupts).

0 commit comments

Comments
 (0)