Commit 01815536 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/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
parents dd5ae681 fd7cd061
...@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) { pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT; xhci->quirks |= XHCI_SPURIOUS_REBOOT;
xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
} }
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
......
...@@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -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? */ /* Fast path - was this the last TRB in the TD for this URB? */
} else if (event_trb == td->last_trb) { } 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) { if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length = td->urb->actual_length =
td->urb->transfer_buffer_length - td->urb->transfer_buffer_length -
...@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length += td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); 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); return finish_td(xhci, td, event_trb, event, ep, status, false);
...@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
u32 trb_comp_code; u32 trb_comp_code;
int ret = 0; int ret = 0;
int td_num = 0; int td_num = 0;
bool handling_skipped_tds = false;
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id]; xdev = xhci->devs[slot_id];
...@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep->skip = true; ep->skip = true;
xhci_dbg(xhci, "Miss service interval error, set skip flag\n"); xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
goto cleanup; goto cleanup;
case COMP_PING_ERR:
ep->skip = true;
xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
goto cleanup;
default: default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0; status = 0;
...@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep, &status); ep, &status);
cleanup: 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. * Do not update event ring dequeue pointer if we're in a loop
* Will roll back to continue process missed tds. * processing missed tds.
*/ */
if (trb_comp_code == COMP_MISSED_INT || !ep->skip) { if (!handling_skipped_tds)
inc_deq(xhci, xhci->event_ring); inc_deq(xhci, xhci->event_ring);
}
if (ret) { if (ret) {
urb = td->urb; urb = td->urb;
...@@ -2587,7 +2607,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2587,7 +2607,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* Process them as short transfer until reach the td pointed by * Process them as short transfer until reach the td pointed by
* the event. * the event.
*/ */
} while (ep->skip && trb_comp_code != COMP_MISSED_INT); } while (handling_skipped_tds);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment