Skip to content

Commit

Permalink
Merge tag 'usb-4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are three xhci driver fixes for reported issues for 4.3-rc7

  All have been in linux-next for a while with no problems"

* tag 'usb-4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  xhci: Add spurious wakeup quirk for LynxPoint-LP controllers
  xhci: handle no ping response error properly
  xhci: don't finish a TD if we get a short transfer event mid TD
  • Loading branch information
torvalds committed Oct 23, 2015
2 parents dd5ae68 + fd7cd06 commit 0181553
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
1 change: 1 addition & 0 deletions drivers/usb/host/xhci-pci.c
Expand Up @@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
Expand Down
30 changes: 25 additions & 5 deletions drivers/usb/host/xhci-ring.c
Expand Up @@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
}
/* Fast path - was this the last TRB in the TD for this URB? */
} else if (event_trb == td->last_trb) {
if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
return finish_td(xhci, td, event_trb, event, ep,
status, false);

if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
Expand Down Expand Up @@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));

if (trb_comp_code == COMP_SHORT_TX) {
xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
td->urb_length_set = true;
return 0;
}
}

return finish_td(xhci, td, event_trb, event, ep, status, false);
Expand Down Expand Up @@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
u32 trb_comp_code;
int ret = 0;
int td_num = 0;
bool handling_skipped_tds = false;

slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
Expand Down Expand Up @@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep->skip = true;
xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
goto cleanup;
case COMP_PING_ERR:
ep->skip = true;
xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
goto cleanup;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
Expand Down Expand Up @@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep, &status);

cleanup:


handling_skipped_tds = ep->skip &&
trb_comp_code != COMP_MISSED_INT &&
trb_comp_code != COMP_PING_ERR;

/*
* Do not update event ring dequeue pointer if ep->skip is set.
* Will roll back to continue process missed tds.
* Do not update event ring dequeue pointer if we're in a loop
* processing missed tds.
*/
if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
if (!handling_skipped_tds)
inc_deq(xhci, xhci->event_ring);
}

if (ret) {
urb = td->urb;
Expand Down Expand Up @@ -2587,7 +2607,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* Process them as short transfer until reach the td pointed by
* the event.
*/
} while (ep->skip && trb_comp_code != COMP_MISSED_INT);
} while (handling_skipped_tds);

return 0;
}
Expand Down

0 comments on commit 0181553

Please sign in to comment.