diff options
author | Elric Fu <elricfu1@gmail.com> | 2012-06-27 04:31:12 -0400 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-09-13 18:49:28 -0400 |
commit | b92cc66c047ff7cf587b318fe377061a353c120f (patch) | |
tree | c4c7e2f695ed5c796b2b7fcb88ddaaa5480f1d59 /drivers/usb/host/xhci.h | |
parent | c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 (diff) |
xHCI: add aborting command ring function
Software have to abort command ring and cancel command
when a command is failed or hang. Otherwise, the command
ring will hang up and can't handle the others. An example
of a command that may hang is the Address Device Command,
because waiting for a SET_ADDRESS request to be acknowledged
by a USB device is outside of the xHC's ability to control.
To cancel a command, software will initialize a command
descriptor for the cancel command, and add it into a
cancel_cmd_list of xhci.
Sarah: Fixed missing newline on "Have the command ring been stopped?"
debugging statement.
This patch should be backported to kernels as old as 3.0, that contain
the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an
assertion to check for virt_dev=0 bug." That commit papers over a NULL
pointer dereference, and this patch fixes the underlying issue that
caused the NULL pointer dereference.
Signed-off-by: Elric Fu <elricfu1@gmail.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb/host/xhci.h')
-rw-r--r-- | drivers/usb/host/xhci.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 33f24e9fa766..fdfcebf342e8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1256,6 +1256,13 @@ struct xhci_td { | |||
1256 | union xhci_trb *last_trb; | 1256 | union xhci_trb *last_trb; |
1257 | }; | 1257 | }; |
1258 | 1258 | ||
1259 | /* command descriptor */ | ||
1260 | struct xhci_cd { | ||
1261 | struct list_head cancel_cmd_list; | ||
1262 | struct xhci_command *command; | ||
1263 | union xhci_trb *cmd_trb; | ||
1264 | }; | ||
1265 | |||
1259 | struct xhci_dequeue_state { | 1266 | struct xhci_dequeue_state { |
1260 | struct xhci_segment *new_deq_seg; | 1267 | struct xhci_segment *new_deq_seg; |
1261 | union xhci_trb *new_deq_ptr; | 1268 | union xhci_trb *new_deq_ptr; |
@@ -1425,6 +1432,7 @@ struct xhci_hcd { | |||
1425 | #define CMD_RING_STATE_RUNNING (1 << 0) | 1432 | #define CMD_RING_STATE_RUNNING (1 << 0) |
1426 | #define CMD_RING_STATE_ABORTED (1 << 1) | 1433 | #define CMD_RING_STATE_ABORTED (1 << 1) |
1427 | #define CMD_RING_STATE_STOPPED (1 << 2) | 1434 | #define CMD_RING_STATE_STOPPED (1 << 2) |
1435 | struct list_head cancel_cmd_list; | ||
1428 | unsigned int cmd_ring_reserved_trbs; | 1436 | unsigned int cmd_ring_reserved_trbs; |
1429 | struct xhci_ring *event_ring; | 1437 | struct xhci_ring *event_ring; |
1430 | struct xhci_erst erst; | 1438 | struct xhci_erst erst; |
@@ -1702,6 +1710,8 @@ static inline void xhci_unregister_plat(void) | |||
1702 | 1710 | ||
1703 | /* xHCI host controller glue */ | 1711 | /* xHCI host controller glue */ |
1704 | typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); | 1712 | typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); |
1713 | int handshake(struct xhci_hcd *xhci, void __iomem *ptr, | ||
1714 | u32 mask, u32 done, int usec); | ||
1705 | void xhci_quiesce(struct xhci_hcd *xhci); | 1715 | void xhci_quiesce(struct xhci_hcd *xhci); |
1706 | int xhci_halt(struct xhci_hcd *xhci); | 1716 | int xhci_halt(struct xhci_hcd *xhci); |
1707 | int xhci_reset(struct xhci_hcd *xhci); | 1717 | int xhci_reset(struct xhci_hcd *xhci); |
@@ -1792,6 +1802,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, | |||
1792 | unsigned int slot_id, unsigned int ep_index, | 1802 | unsigned int slot_id, unsigned int ep_index, |
1793 | struct xhci_dequeue_state *deq_state); | 1803 | struct xhci_dequeue_state *deq_state); |
1794 | void xhci_stop_endpoint_command_watchdog(unsigned long arg); | 1804 | void xhci_stop_endpoint_command_watchdog(unsigned long arg); |
1805 | int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, | ||
1806 | union xhci_trb *cmd_trb); | ||
1795 | void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, | 1807 | void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, |
1796 | unsigned int ep_index, unsigned int stream_id); | 1808 | unsigned int ep_index, unsigned int stream_id); |
1797 | 1809 | ||