diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-18 00:24:26 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-18 00:24:26 +0300 |
commit | 48d10bda1f2c69980601a61194015bb0790fb7ab (patch) | |
tree | e4ea2021560b1f18b335f6e8e20761fb9514cd1b /drivers/usb/host/xhci-ring.c | |
parent | 96b9b1c95660d4bc5510c5d798d3817ae9f0b391 (diff) | |
parent | ce53bfc4374cada8b645765e2b4ad5831e760932 (diff) | |
download | linux-48d10bda1f2c69980601a61194015bb0790fb7ab.tar.xz |
Merge tag 'usb-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
"Here is the big USB patchset for 4.6-rc1.
The normal mess is here, gadget and xhci fixes and updates, and lots
of other driver updates and cleanups as well. Full details are in the
shortlog.
All have been in linux-next for a while with no reported issues"
* tag 'usb-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (266 commits)
USB: core: let USB device know device node
usb: devio: Add ioctl to disallow detaching kernel USB drivers.
usb: gadget: f_acm: Fix configfs attr name
usb: udc: lpc32xx: remove USB PLL and USB OTG clock management
usb: udc: lpc32xx: remove direct access to clock controller registers
usb: udc: lpc32xx: switch to clock prepare/unprepare model
usb: renesas_usbhs: gadget: fix giveback status code in usbhsg_pipe_disable()
usb: gadget: renesas_usb3: Use ARCH_RENESAS
usb: dwc2: Fix issues in dwc2_complete_non_isoc_xfer_ddma()
usb: dwc2: Add support for Lantiq ARX and XRX SoCs
usb: phy: generic: Handle late registration of gadget
usb: gadget: bdc_udc: fix race condition in bdc_udc_exit()
usb: musb: core: added missing const qualifier to musb_hdrc_platform_data::config
usb: dwc2: Move host-specific core functions into hcd.c
usb: dwc2: Move register save and restore functions
usb: dwc2: Use kmem_cache_free()
usb: dwc2: host: If using uframe scheduler, end splits better
usb: dwc2: host: Totally redo the microframe scheduler
usb: dwc2: host: Properly set even/odd frame
usb: dwc2: host: Add dwc2_hcd_get_future_frame_number() call
...
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 134 |
1 files changed, 62 insertions, 72 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3915657e6078..7cf66212ceae 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3558,12 +3558,11 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci, * zero. Only xHCI 1.0 host controllers support this field. */ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, - struct usb_device *udev, struct urb *urb, unsigned int total_packet_count) { unsigned int max_burst; - if (xhci->hci_version < 0x100 || udev->speed != USB_SPEED_SUPER) + if (xhci->hci_version < 0x100 || urb->dev->speed < USB_SPEED_SUPER) return 0; max_burst = urb->ep->ss_ep_comp.bMaxBurst; @@ -3579,7 +3578,6 @@ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, * contain 1 to (bMaxBurst + 1) packets. */ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, - struct usb_device *udev, struct urb *urb, unsigned int total_packet_count) { unsigned int max_burst; @@ -3588,8 +3586,7 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, if (xhci->hci_version < 0x100) return 0; - switch (udev->speed) { - case USB_SPEED_SUPER: + if (urb->dev->speed >= USB_SPEED_SUPER) { /* bMaxBurst is zero based: 0 means 1 packet per burst */ max_burst = urb->ep->ss_ep_comp.bMaxBurst; residue = total_packet_count % (max_burst + 1); @@ -3599,11 +3596,10 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, if (residue == 0) return max_burst; return residue - 1; - default: - if (total_packet_count == 0) - return 0; - return total_packet_count - 1; } + if (total_packet_count == 0) + return 0; + return total_packet_count - 1; } /* @@ -3714,6 +3710,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int i, j; bool more_trbs_coming; struct xhci_virt_ep *xep; + int frame_id; xep = &xhci->devs[slot_id]->eps[ep_index]; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; @@ -3723,33 +3720,31 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, xhci_dbg(xhci, "Isoc URB with zero packets?\n"); return -EINVAL; } - start_addr = (u64) urb->transfer_dma; start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; urb_priv = urb->hcpriv; - /* Queue the first TRB, even if it's zero-length */ + /* Queue the TRBs for each TD, even if they are zero-length */ for (i = 0; i < num_tds; i++) { - unsigned int total_packet_count; - unsigned int burst_count; - unsigned int residue; + unsigned int total_pkt_count, max_pkt; + unsigned int burst_count, last_burst_pkt_count; + u32 sia_frame_id; first_trb = true; running_total = 0; addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - total_packet_count = DIV_ROUND_UP(td_len, - GET_MAX_PACKET( - usb_endpoint_maxp(&urb->ep->desc))); + max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + total_pkt_count = DIV_ROUND_UP(td_len, max_pkt); + /* A zero-length transfer still involves at least one packet. */ - if (total_packet_count == 0) - total_packet_count++; - burst_count = xhci_get_burst_count(xhci, urb->dev, urb, - total_packet_count); - residue = xhci_get_last_burst_packet_count(xhci, - urb->dev, urb, total_packet_count); + if (total_pkt_count == 0) + total_pkt_count++; + burst_count = xhci_get_burst_count(xhci, urb, total_pkt_count); + last_burst_pkt_count = xhci_get_last_burst_packet_count(xhci, + urb, total_pkt_count); trbs_per_td = count_isoc_trbs_needed(xhci, urb, i); @@ -3760,68 +3755,57 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return ret; goto cleanup; } - td = urb_priv->td[i]; + + /* use SIA as default, if frame id is used overwrite it */ + sia_frame_id = TRB_SIA; + if (!(urb->transfer_flags & URB_ISO_ASAP) && + HCC_CFC(xhci->hcc_params)) { + frame_id = xhci_get_isoc_frame_id(xhci, urb, i); + if (frame_id >= 0) + sia_frame_id = TRB_FRAME_ID(frame_id); + } + /* + * Set isoc specific data for the first TRB in a TD. + * Prevent HW from getting the TRBs by keeping the cycle state + * inverted in the first TDs isoc TRB. + */ + field = TRB_TYPE(TRB_ISOC) | + TRB_TLBPC(last_burst_pkt_count) | + sia_frame_id | + (i ? ep_ring->cycle_state : !start_cycle); + + /* xhci 1.1 with ETE uses TD_Size field for TBC, old is Rsvdz */ + if (!xep->use_extended_tbc) + field |= TRB_TBC(burst_count); + + /* fill the rest of the TRB fields, and remaining normal TRBs */ for (j = 0; j < trbs_per_td; j++) { - int frame_id = 0; u32 remainder = 0; - field = 0; - - if (first_trb) { - field = TRB_TBC(burst_count) | - TRB_TLBPC(residue); - /* Queue the isoc TRB */ - field |= TRB_TYPE(TRB_ISOC); - - /* Calculate Frame ID and SIA fields */ - if (!(urb->transfer_flags & URB_ISO_ASAP) && - HCC_CFC(xhci->hcc_params)) { - frame_id = xhci_get_isoc_frame_id(xhci, - urb, - i); - if (frame_id >= 0) - field |= TRB_FRAME_ID(frame_id); - else - field |= TRB_SIA; - } else - field |= TRB_SIA; - - if (i == 0) { - if (start_cycle == 0) - field |= 0x1; - } else - field |= ep_ring->cycle_state; - first_trb = false; - } else { - /* Queue other normal TRBs */ - field |= TRB_TYPE(TRB_NORMAL); - field |= ep_ring->cycle_state; - } + + /* only first TRB is isoc, overwrite otherwise */ + if (!first_trb) + field = TRB_TYPE(TRB_NORMAL) | + ep_ring->cycle_state; /* Only set interrupt on short packet for IN EPs */ if (usb_urb_dir_in(urb)) field |= TRB_ISP; - /* Chain all the TRBs together; clear the chain bit in - * the last TRB to indicate it's the last TRB in the - * chain. - */ + /* Set the chain bit for all except the last TRB */ if (j < trbs_per_td - 1) { - field |= TRB_CHAIN; more_trbs_coming = true; + field |= TRB_CHAIN; } else { + more_trbs_coming = false; td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100 && - !(xhci->quirks & - XHCI_AVOID_BEI)) { - /* Set BEI bit except for the last td */ - if (i < num_tds - 1) - field |= TRB_BEI; - } - more_trbs_coming = false; + /* set BEI, except for the last TD */ + if (xhci->hci_version >= 0x100 && + !(xhci->quirks & XHCI_AVOID_BEI) && + i < num_tds - 1) + field |= TRB_BEI; } - /* Calculate TRB length */ trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); @@ -3834,9 +3818,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb, trbs_per_td - j - 1); length_field = TRB_LEN(trb_buff_len) | - TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); + /* xhci 1.1 with ETE uses TD Size field for TBC */ + if (first_trb && xep->use_extended_tbc) + length_field |= TRB_TD_SIZE_TBC(burst_count); + else + length_field |= TRB_TD_SIZE(remainder); + first_trb = false; + queue_trb(xhci, ep_ring, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), |