aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.h
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-10-27 13:57:01 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:17 -0500
commit6f5165cf989387e84ef23122330b27cca1cbe831 (patch)
tree44ff1ea0590b00f2851f50ffa2cf9954eb70a767 /drivers/usb/host/xhci.h
parent4f0f0baef017dfd5d62b749716ab980a825e1071 (diff)
USB: xhci: Add watchdog timer for URB cancellation.
In order to giveback a canceled URB, we must ensure that the xHCI hardware will not access the buffer in an URB. We can't modify the buffer pointers on endpoint rings without issuing and waiting for a stop endpoint command. Since URBs can be canceled in interrupt context, we can't wait on that command. The old code trusted that the host controller would respond to the command, and would giveback the URBs in the event handler. If the hardware never responds to the stop endpoint command, the URBs will never be completed, and we might hang the USB subsystem. Implement a watchdog timer that is spawned whenever a stop endpoint command is queued. If a stop endpoint command event is found on the event ring during an interrupt, we need to stop the watchdog timer with del_timer(). Since del_timer() can fail if the timer is running and waiting on the xHCI lock, we need a way to signal to the timer that everything is fine and it should exit. If we simply clear EP_HALT_PENDING, a new stop endpoint command could sneak in and set it before the watchdog timer can grab the lock. Instead we use a combination of the EP_HALT_PENDING flag and a counter for the number of pending stop endpoint commands (xhci_virt_ep->stop_cmds_pending). If we need to cancel the watchdog timer and del_timer() succeeds, we decrement the number of pending stop endpoint commands. If del_timer() fails, we leave the number of pending stop endpoint commands alone. In either case, we clear the EP_HALT_PENDING flag. The timer will decrement the number of pending stop endpoint commands once it obtains the lock. If the timer is the tail end of the last stop endpoint command (xhci_virt_ep->stop_cmds_pending == 0), and the endpoint's command is still pending (EP_HALT_PENDING is set), we assume the host is dying. The watchdog timer will set XHCI_STATE_DYING, try to halt the xHCI host, and give back all pending URBs. Various other places in the driver need to check whether the xHCI host is dying. If the interrupt handler ever notices, it should immediately stop processing events. The URB enqueue function should also return -ESHUTDOWN. The URB dequeue function should simply return the value of usb_hcd_check_unlink_urb() and the watchdog timer will take care of giving the URB back. When a device is disconnected, the xHCI hardware structures should be freed without issuing a disable slot command (since the hardware probably won't respond to it anyway). The debugging polling loop should stop polling if the host is dying. When a device is disconnected, any pending watchdog timers are killed with del_timer_sync(). It must be synchronous so that the watchdog timer doesn't attempt to access the freed endpoint structures. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci.h')
-rw-r--r--drivers/usb/host/xhci.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index af3c5638526c..c92f84154fb5 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -659,6 +659,10 @@ struct xhci_virt_ep {
659 /* The TRB that was last reported in a stopped endpoint ring */ 659 /* The TRB that was last reported in a stopped endpoint ring */
660 union xhci_trb *stopped_trb; 660 union xhci_trb *stopped_trb;
661 struct xhci_td *stopped_td; 661 struct xhci_td *stopped_td;
662 /* Watchdog timer for stop endpoint command to cancel URBs */
663 struct timer_list stop_cmd_timer;
664 int stop_cmds_pending;
665 struct xhci_hcd *xhci;
662}; 666};
663 667
664struct xhci_virt_device { 668struct xhci_virt_device {
@@ -1022,6 +1026,8 @@ struct xhci_scratchpad {
1022#define ERST_ENTRIES 1 1026#define ERST_ENTRIES 1
1023/* Poll every 60 seconds */ 1027/* Poll every 60 seconds */
1024#define POLL_TIMEOUT 60 1028#define POLL_TIMEOUT 60
1029/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */
1030#define XHCI_STOP_EP_CMD_TIMEOUT 5
1025/* XXX: Make these module parameters */ 1031/* XXX: Make these module parameters */
1026 1032
1027 1033
@@ -1083,6 +1089,21 @@ struct xhci_hcd {
1083 struct timer_list event_ring_timer; 1089 struct timer_list event_ring_timer;
1084 int zombie; 1090 int zombie;
1085#endif 1091#endif
1092 /* Host controller watchdog timer structures */
1093 unsigned int xhc_state;
1094/* Host controller is dying - not responding to commands. "I'm not dead yet!"
1095 *
1096 * xHC interrupts have been disabled and a watchdog timer will (or has already)
1097 * halt the xHCI host, and complete all URBs with an -ESHUTDOWN code. Any code
1098 * that sees this status (other than the timer that set it) should stop touching
1099 * hardware immediately. Interrupt handlers should return immediately when
1100 * they see this status (any time they drop and re-acquire xhci->lock).
1101 * xhci_urb_dequeue() should call usb_hcd_check_unlink_urb() and return without
1102 * putting the TD on the canceled list, etc.
1103 *
1104 * There are no reports of xHCI host controllers that display this issue.
1105 */
1106#define XHCI_STATE_DYING (1 << 0)
1086 /* Statistics */ 1107 /* Statistics */
1087 int noops_submitted; 1108 int noops_submitted;
1088 int noops_handled; 1109 int noops_handled;
@@ -1279,6 +1300,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
1279void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, 1300void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
1280 unsigned int slot_id, unsigned int ep_index, 1301 unsigned int slot_id, unsigned int ep_index,
1281 struct xhci_dequeue_state *deq_state); 1302 struct xhci_dequeue_state *deq_state);
1303void xhci_stop_endpoint_command_watchdog(unsigned long arg);
1282 1304
1283/* xHCI roothub code */ 1305/* xHCI roothub code */
1284int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, 1306int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,