[PATCH 4.9 064/206] xhci: Use delayed_work instead of timer for command timeout

From: Greg Kroah-Hartman
Date: Tue Jan 10 2017 - 08:46:32 EST


4.9-stable review patch. If anyone has any objections, please let me know.

------------------

From: OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx>

commit cb4d5ce588c5ff68e0fdd30370a0e6bc2c0a736b upstream.

This is preparation to fix abort operation race (See "xhci: Fix race
related to abort operation"). To make timeout sleepable, use
delayed_work instead of timer.

[change a newly added pending timer fix to pending work -Mathias]
Signed-off-by: OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/usb/host/xhci-mem.c | 7 +++----
drivers/usb/host/xhci-ring.c | 26 ++++++++++++++++----------
drivers/usb/host/xhci.h | 4 ++--
3 files changed, 21 insertions(+), 16 deletions(-)

--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1830,7 +1830,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
int size;
int i, j, num_ports;

- del_timer_sync(&xhci->cmd_timer);
+ cancel_delayed_work_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);
@@ -2377,9 +2377,8 @@ int xhci_mem_init(struct xhci_hcd *xhci,

INIT_LIST_HEAD(&xhci->cmd_list);

- /* init command timeout timer */
- setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
- (unsigned long)xhci);
+ /* init command timeout work */
+ INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);

page_size = readl(&xhci->op_regs->page_size);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -260,6 +260,11 @@ void xhci_ring_cmd_db(struct xhci_hcd *x
readl(&xhci->dba->doorbell[0]);
}

+static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, unsigned long delay)
+{
+ return mod_delayed_work(system_wq, &xhci->cmd_timer, delay);
+}
+
static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
{
u64 temp_64;
@@ -276,7 +281,7 @@ static int xhci_abort_cmd_ring(struct xh
* but the completion event in never sent. Use the cmd timeout timer to
* handle those cases. Use twice the time to cover the bit polling retry
*/
- mod_timer(&xhci->cmd_timer, jiffies + (2 * XHCI_CMD_DEFAULT_TIMEOUT));
+ xhci_mod_cmd_timer(xhci, 2 * XHCI_CMD_DEFAULT_TIMEOUT);
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);

@@ -301,7 +306,7 @@ static int xhci_abort_cmd_ring(struct xh

xhci_err(xhci, "Stopped the command ring failed, "
"maybe the host is dead\n");
- del_timer(&xhci->cmd_timer);
+ cancel_delayed_work(&xhci->cmd_timer);
xhci->xhc_state |= XHCI_STATE_DYING;
xhci_quiesce(xhci);
xhci_halt(xhci);
@@ -1255,21 +1260,22 @@ static void xhci_handle_stopped_cmd_ring
if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
!(xhci->xhc_state & XHCI_STATE_DYING)) {
xhci->current_cmd = cur_cmd;
- mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+ xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
xhci_ring_cmd_db(xhci);
}
return;
}


-void xhci_handle_command_timeout(unsigned long data)
+void xhci_handle_command_timeout(struct work_struct *work)
{
struct xhci_hcd *xhci;
int ret;
unsigned long flags;
u64 hw_ring_state;
bool second_timeout = false;
- xhci = (struct xhci_hcd *) data;
+
+ xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer);

spin_lock_irqsave(&xhci->lock, flags);

@@ -1277,7 +1283,7 @@ void xhci_handle_command_timeout(unsigne
* If timeout work is pending, or current_cmd is NULL, it means we
* raced with command completion. Command is handled so just return.
*/
- if (!xhci->current_cmd || timer_pending(&xhci->cmd_timer)) {
+ if (!xhci->current_cmd || delayed_work_pending(&xhci->cmd_timer)) {
spin_unlock_irqrestore(&xhci->lock, flags);
return;
}
@@ -1351,7 +1357,7 @@ static void handle_cmd_completion(struct

cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);

- del_timer(&xhci->cmd_timer);
+ cancel_delayed_work(&xhci->cmd_timer);

trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);

@@ -1442,7 +1448,7 @@ static void handle_cmd_completion(struct
if (cmd->cmd_list.next != &xhci->cmd_list) {
xhci->current_cmd = list_entry(cmd->cmd_list.next,
struct xhci_command, cmd_list);
- mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+ xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
} else if (xhci->current_cmd == cmd) {
xhci->current_cmd = NULL;
}
@@ -3938,9 +3944,9 @@ static int queue_command(struct xhci_hcd

/* if there are no other commands queued we start the timeout timer */
if (xhci->cmd_list.next == &cmd->cmd_list &&
- !timer_pending(&xhci->cmd_timer)) {
+ !delayed_work_pending(&xhci->cmd_timer)) {
xhci->current_cmd = cmd;
- mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+ xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
}

queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1571,7 +1571,7 @@ struct xhci_hcd {
#define CMD_RING_STATE_STOPPED (1 << 2)
struct list_head cmd_list;
unsigned int cmd_ring_reserved_trbs;
- struct timer_list cmd_timer;
+ struct delayed_work cmd_timer;
struct xhci_command *current_cmd;
struct xhci_ring *event_ring;
struct xhci_erst erst;
@@ -1941,7 +1941,7 @@ void xhci_queue_config_ep_quirk(struct x
unsigned int slot_id, unsigned int ep_index,
struct xhci_dequeue_state *deq_state);
void xhci_stop_endpoint_command_watchdog(unsigned long arg);
-void xhci_handle_command_timeout(unsigned long data);
+void xhci_handle_command_timeout(struct work_struct *work);

void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
unsigned int ep_index, unsigned int stream_id);