aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2010-12-20 02:09:34 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-01-14 18:51:55 -0500
commit50f7b52a83a893929edf87a89ebc081ff26a7b91 (patch)
tree8cf753001566c0b925bee66c9458a30d96b94b49 /drivers/usb
parente1eab2e00015bfe48388920ff287efdbefb6af24 (diff)
xHCI: fix cycle bit set in giveback_first_trb()
giveback_first_trb() controls the cycle bit set of the start_trb, to ensure that the start_trb is written last and the host controller will receive a whole td at a time. However, if the ring is wrapped and cycle bit is toggled to zero, then giveback_first_trb() will be of no effect. In this case, set the cycle bit of start_trb to 1 at the beginning and clear it in giveback_first_trb(). Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-ring.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 59f81b560483..1ee6de92193a 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2421,7 +2421,10 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
2421 * isn't reordered. 2421 * isn't reordered.
2422 */ 2422 */
2423 wmb(); 2423 wmb();
2424 start_trb->field[3] |= start_cycle; 2424 if (start_cycle)
2425 start_trb->field[3] |= start_cycle;
2426 else
2427 start_trb->field[3] &= ~0x1;
2425 xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); 2428 xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
2426} 2429}
2427 2430
@@ -2551,9 +2554,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2551 u32 remainder = 0; 2554 u32 remainder = 0;
2552 2555
2553 /* Don't change the cycle bit of the first TRB until later */ 2556 /* Don't change the cycle bit of the first TRB until later */
2554 if (first_trb) 2557 if (first_trb) {
2555 first_trb = false; 2558 first_trb = false;
2556 else 2559 if (start_cycle == 0)
2560 field |= 0x1;
2561 } else
2557 field |= ep_ring->cycle_state; 2562 field |= ep_ring->cycle_state;
2558 2563
2559 /* Chain all the TRBs together; clear the chain bit in the last 2564 /* Chain all the TRBs together; clear the chain bit in the last
@@ -2711,9 +2716,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2711 field = 0; 2716 field = 0;
2712 2717
2713 /* Don't change the cycle bit of the first TRB until later */ 2718 /* Don't change the cycle bit of the first TRB until later */
2714 if (first_trb) 2719 if (first_trb) {
2715 first_trb = false; 2720 first_trb = false;
2716 else 2721 if (start_cycle == 0)
2722 field |= 0x1;
2723 } else
2717 field |= ep_ring->cycle_state; 2724 field |= ep_ring->cycle_state;
2718 2725
2719 /* Chain all the TRBs together; clear the chain bit in the last 2726 /* Chain all the TRBs together; clear the chain bit in the last
@@ -2818,13 +2825,17 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2818 /* Queue setup TRB - see section 6.4.1.2.1 */ 2825 /* Queue setup TRB - see section 6.4.1.2.1 */
2819 /* FIXME better way to translate setup_packet into two u32 fields? */ 2826 /* FIXME better way to translate setup_packet into two u32 fields? */
2820 setup = (struct usb_ctrlrequest *) urb->setup_packet; 2827 setup = (struct usb_ctrlrequest *) urb->setup_packet;
2828 field = 0;
2829 field |= TRB_IDT | TRB_TYPE(TRB_SETUP);
2830 if (start_cycle == 0)
2831 field |= 0x1;
2821 queue_trb(xhci, ep_ring, false, true, 2832 queue_trb(xhci, ep_ring, false, true,
2822 /* FIXME endianness is probably going to bite my ass here. */ 2833 /* FIXME endianness is probably going to bite my ass here. */
2823 setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16, 2834 setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
2824 setup->wIndex | setup->wLength << 16, 2835 setup->wIndex | setup->wLength << 16,
2825 TRB_LEN(8) | TRB_INTR_TARGET(0), 2836 TRB_LEN(8) | TRB_INTR_TARGET(0),
2826 /* Immediate data in pointer */ 2837 /* Immediate data in pointer */
2827 TRB_IDT | TRB_TYPE(TRB_SETUP)); 2838 field);
2828 2839
2829 /* If there's data, queue data TRBs */ 2840 /* If there's data, queue data TRBs */
2830 field = 0; 2841 field = 0;
@@ -2951,7 +2962,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2951 field |= TRB_TYPE(TRB_ISOC); 2962 field |= TRB_TYPE(TRB_ISOC);
2952 /* Assume URB_ISO_ASAP is set */ 2963 /* Assume URB_ISO_ASAP is set */
2953 field |= TRB_SIA; 2964 field |= TRB_SIA;
2954 if (i > 0) 2965 if (i == 0) {
2966 if (start_cycle == 0)
2967 field |= 0x1;
2968 } else
2955 field |= ep_ring->cycle_state; 2969 field |= ep_ring->cycle_state;
2956 first_trb = false; 2970 first_trb = false;
2957 } else { 2971 } else {