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

Commit d78658d4 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'for-usb-linus-2013-03-26' of...

Merge tag 'for-usb-linus-2013-03-26' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus

Misc xHCI fixes for 3.9

Hi Greg,

Here's a couple of fixes for the xHCI driver.  Three patches are nothing
major: build warning fix, macro field width fix, and removing some
unnecessary log spam.

The only interesting thing here is Tianyu's two patches to fix the USB
port connection type discovery, for the USB port power off mechanism.
This adds new USB host API, but as discussed, it's necessary to avoid
powering off the wrong USB port.  It's not marked for backport to stable
kernels, since the sysfs mechanism to manually power off a port didn't
go in until 3.9.

I've smoke tested these, including system suspend, USB device suspend,
and rocking out in my cube with a pair of USB headphones.  They look
fine to me.

Hibernate is currently broken on my system, due to some nouveau MMIO
read faults.  I'll report that separately.

Sarah Sharp
parents eba0e3c3 a83d6755
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);

int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1)
{
	if (!hcd->driver->find_raw_port_number)
		return port1;

	return hcd->driver->find_raw_port_number(hcd, port1);
}

static int usb_hcd_request_irqs(struct usb_hcd *hcd,
		unsigned int irqnum, unsigned long irqflags)
{
+7 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/usb/hcd.h>
#include <acpi/acpi_bus.h>

#include "usb.h"
@@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
		 * connected to.
		 */
		if (!udev->parent) {
			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
			struct usb_hcd *hcd = bus_to_hcd(udev->bus);
			int raw_port_num;

			raw_port_num = usb_hcd_find_raw_port_number(hcd,
				port_num);
			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
				raw_port_num);
			if (!*handle)
				return -ENODEV;
		} else {
+8 −28
Original line number Diff line number Diff line
@@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
 * is attached to (or the roothub port its ancestor hub is attached to).  All we
 * know is the index of that port under either the USB 2.0 or the USB 3.0
 * roothub, but that doesn't give us the real index into the HW port status
 * registers.  Scan through the xHCI roothub port array, looking for the Nth
 * entry of the correct port speed.  Return the port number of that entry.
 * registers. Call xhci_find_raw_port_number() to get real index.
 */
static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
		struct usb_device *udev)
{
	struct usb_device *top_dev;
	unsigned int num_similar_speed_ports;
	unsigned int faked_port_num;
	int i;
	struct usb_hcd *hcd;

	if (udev->speed == USB_SPEED_SUPER)
		hcd = xhci->shared_hcd;
	else
		hcd = xhci->main_hcd;

	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
			top_dev = top_dev->parent)
		/* Found device below root hub */;
	faked_port_num = top_dev->portnum;
	for (i = 0, num_similar_speed_ports = 0;
			i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
		u8 port_speed = xhci->port_array[i];

		/*
		 * Skip ports that don't have known speeds, or have duplicate
		 * Extended Capabilities port speed entries.
		 */
		if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
			continue;

		/*
		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
		 * 1.1 ports are under the USB 2.0 hub.  If the port speed
		 * matches the device speed, it's a similar speed port.
		 */
		if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
			num_similar_speed_ports++;
		if (num_similar_speed_ports == faked_port_num)
			/* Roothub ports are numbered from 1 to N */
			return i+1;
	}
	return 0;
	return	xhci_find_raw_port_number(hcd, top_dev->portnum);
}

/* Setup an xHCI virtual device for a Set Address command */
+1 −0
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
	.set_usb2_hw_lpm =	xhci_set_usb2_hardware_lpm,
	.enable_usb3_lpm_timeout =	xhci_enable_usb3_lpm_timeout,
	.disable_usb3_lpm_timeout =	xhci_disable_usb3_lpm_timeout,
	.find_raw_port_number =	xhci_find_raw_port_number,
};

/*-------------------------------------------------------------------------*/
+35 −26
Original line number Diff line number Diff line
@@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,
	max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
	if ((port_id <= 0) || (port_id > max_ports)) {
		xhci_warn(xhci, "Invalid port id %d\n", port_id);
		bogus_port_status = true;
		goto cleanup;
		inc_deq(xhci, xhci->event_ring);
		return;
	}

	/* Figure out which usb_hcd this port is attached to:
	 * is it a USB 3.0 port or a USB 2.0/1.1 port?
	 */
	major_revision = xhci->port_array[port_id - 1];

	/* Find the right roothub. */
	hcd = xhci_to_hcd(xhci);
	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
		hcd = xhci->shared_hcd;

	if (major_revision == 0) {
		xhci_warn(xhci, "Event for port %u not in "
				"Extended Capabilities, ignoring.\n",
@@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
	 * into the index into the ports on the correct split roothub, and the
	 * correct bus_state structure.
	 */
	/* Find the right roothub. */
	hcd = xhci_to_hcd(xhci);
	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
		hcd = xhci->shared_hcd;
	bus_state = &xhci->bus_state[hcd_index(hcd)];
	if (hcd->speed == HCD_USB3)
		port_array = xhci->usb3_ports;
@@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
		if (event_trb != ep_ring->dequeue &&
				event_trb != td->last_trb)
			td->urb->actual_length =
				td->urb->transfer_buffer_length
				- TRB_LEN(le32_to_cpu(event->transfer_len));
				td->urb->transfer_buffer_length -
				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
		else
			td->urb->actual_length = 0;

@@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
		/* Maybe the event was for the data stage? */
			td->urb->actual_length =
				td->urb->transfer_buffer_length -
				TRB_LEN(le32_to_cpu(event->transfer_len));
				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
			xhci_dbg(xhci, "Waiting for status "
					"stage event\n");
			return 0;
@@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
	/* handle completion code */
	switch (trb_comp_code) {
	case COMP_SUCCESS:
		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
			frame->status = 0;
			break;
		}
@@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
		}
		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
			TRB_LEN(le32_to_cpu(event->transfer_len));
			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));

		if (trb_comp_code != COMP_STOP_INVAL) {
			frame->actual_length = len;
@@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
	case COMP_SUCCESS:
		/* Double check that the HW transferred everything. */
		if (event_trb != td->last_trb ||
				TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
		    EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
			xhci_warn(xhci, "WARN Successful completion "
					"on short TX\n");
			if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
				"%d bytes untransferred\n",
				td->urb->ep->desc.bEndpointAddress,
				td->urb->transfer_buffer_length,
				TRB_LEN(le32_to_cpu(event->transfer_len)));
				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
	/* Fast path - was this the last TRB in the TD for this URB? */
	if (event_trb == td->last_trb) {
		if (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->transfer_buffer_length -
				TRB_LEN(le32_to_cpu(event->transfer_len));
				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
			if (td->urb->transfer_buffer_length <
					td->urb->actual_length) {
				xhci_warn(xhci, "HC gave bad length "
						"of %d bytes left\n",
					  TRB_LEN(le32_to_cpu(event->transfer_len)));
					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
				td->urb->actual_length = 0;
				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
					*status = -EREMOTEIO;
@@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
		if (trb_comp_code != COMP_STOP_INVAL)
			td->urb->actual_length +=
				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
				TRB_LEN(le32_to_cpu(event->transfer_len));
				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
	}

	return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
	 * transfer type
	 */
	case COMP_SUCCESS:
		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
			break;
		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
			trb_comp_code = COMP_SHORT_TX;
@@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
		 * TD list.
		 */
		if (list_empty(&ep_ring->td_list)) {
			xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
					"with no TDs queued?\n",
			/*
			 * A stopped endpoint may generate an extra completion
			 * event if the device was suspended.  Don't print
			 * warnings.
			 */
			if (!(trb_comp_code == COMP_STOP ||
						trb_comp_code == COMP_STOP_INVAL)) {
				xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
						TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
						ep_index);
				xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
						(le32_to_cpu(event->flags) &
						 TRB_TYPE_BITMASK)>>10);
				xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
			}
			if (ep->skip) {
				ep->skip = false;
				xhci_dbg(xhci, "td_list is empty while skip "
Loading