Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01815536 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 ||
+25 −5
Original line number Diff line number Diff line
@@ -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 -
@@ -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);
@@ -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];
@@ -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;
@@ -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;
@@ -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;
}