aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.h
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-29 22:02:31 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:49 -0400
commitae636747146ea97efa18e04576acd3416e2514f5 (patch)
tree22e392df7126974c0ac4dc2fe516dc9e16a49873 /drivers/usb/host/xhci.h
parent8a96c052283e68fe91a6c657c175b39bfed80bed (diff)
USB: xhci: URB cancellation support.
Add URB cancellation support to the xHCI host controller driver. This currently supports cancellation for endpoints that do not have streams enabled. An URB is represented by a number of Transaction Request Buffers (TRBs), that are chained together to make one (or more) Transaction Descriptors (TDs) on an endpoint ring. The ring is comprised of contiguous segments, linked together with Link TRBs (which may or may not be chained into a TD). To cancel an URB, we must stop the endpoint ring, make the hardware skip over the TDs in the URB (either by turning them into No-op TDs, or by moving the hardware's ring dequeue pointer past the last TRB in the last TD), and then restart the ring. There are times when we must drop the xHCI lock during this process, like when we need to complete cancelled URBs. We must ensure that additional URBs can be marked as cancelled, and that new URBs can be enqueued (since the URB completion handlers can do either). The new endpoint ring variables cancels_pending and state (which can only be modified while holding the xHCI lock) ensure that future cancellation and enqueueing do not interrupt any pending cancellation code. To facilitate cancellation, we must keep track of the starting ring segment, first TRB, and last TRB for each URB. We also need to keep track of the list of TDs that have been marked as cancelled, separate from the list of TDs that are queued for this endpoint. The new variables and cancellation list are stored in the xhci_td structure. 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.h31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 06e07616631f..7b7103405c69 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -514,6 +514,7 @@ struct xhci_slot_ctx {
514/* bits 8:26 reserved */ 514/* bits 8:26 reserved */
515/* Slot state */ 515/* Slot state */
516#define SLOT_STATE (0x1f << 27) 516#define SLOT_STATE (0x1f << 27)
517#define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27)
517 518
518 519
519/** 520/**
@@ -765,6 +766,11 @@ struct xhci_event_cmd {
765#define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24) 766#define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24)
766#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) 767#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24)
767 768
769/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB */
770#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1)
771#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16)
772
773
768/* Port Status Change Event TRB fields */ 774/* Port Status Change Event TRB fields */
769/* Port ID - bits 31:24 */ 775/* Port ID - bits 31:24 */
770#define GET_PORT_ID(p) (((p) & (0xff << 24)) >> 24) 776#define GET_PORT_ID(p) (((p) & (0xff << 24)) >> 24)
@@ -893,12 +899,6 @@ union xhci_trb {
893#define TRB_MAX_BUFF_SHIFT 16 899#define TRB_MAX_BUFF_SHIFT 16
894#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) 900#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT)
895 901
896struct xhci_td {
897 struct list_head td_list;
898 struct urb *urb;
899 union xhci_trb *last_trb;
900};
901
902struct xhci_segment { 902struct xhci_segment {
903 union xhci_trb *trbs; 903 union xhci_trb *trbs;
904 /* private to HCD */ 904 /* private to HCD */
@@ -906,6 +906,15 @@ struct xhci_segment {
906 dma_addr_t dma; 906 dma_addr_t dma;
907} __attribute__ ((packed)); 907} __attribute__ ((packed));
908 908
909struct xhci_td {
910 struct list_head td_list;
911 struct list_head cancelled_td_list;
912 struct urb *urb;
913 struct xhci_segment *start_seg;
914 union xhci_trb *first_trb;
915 union xhci_trb *last_trb;
916};
917
909struct xhci_ring { 918struct xhci_ring {
910 struct xhci_segment *first_seg; 919 struct xhci_segment *first_seg;
911 union xhci_trb *enqueue; 920 union xhci_trb *enqueue;
@@ -915,6 +924,14 @@ struct xhci_ring {
915 struct xhci_segment *deq_seg; 924 struct xhci_segment *deq_seg;
916 unsigned int deq_updates; 925 unsigned int deq_updates;
917 struct list_head td_list; 926 struct list_head td_list;
927 /* ---- Related to URB cancellation ---- */
928 struct list_head cancelled_td_list;
929 unsigned int cancels_pending;
930 unsigned int state;
931#define SET_DEQ_PENDING (1 << 0)
932 /* The TRB that was last reported in a stopped endpoint ring */
933 union xhci_trb *stopped_trb;
934 struct xhci_td *stopped_td;
918 /* 935 /*
919 * Write the cycle state into the TRB cycle field to give ownership of 936 * Write the cycle state into the TRB cycle field to give ownership of
920 * the TRB to the host controller (if we are the producer), or to check 937 * the TRB to the host controller (if we are the producer), or to check
@@ -1119,6 +1136,8 @@ void handle_event(struct xhci_hcd *xhci);
1119void set_hc_event_deq(struct xhci_hcd *xhci); 1136void set_hc_event_deq(struct xhci_hcd *xhci);
1120int queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); 1137int queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
1121int queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); 1138int queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id);
1139int queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
1140 unsigned int ep_index);
1122int queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); 1141int queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index);
1123int queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); 1142int queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index);
1124int queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); 1143int queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id);