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

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

Merge branch 'for-usb-next' of...

Merge branch 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next

* 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci:
  xhci 1.0: Set transfer burst last packet count field.
  xhci 1.0: Set transfer burst count field.
  xhci 1.0: Update TD size field format.
  xhci 1.0: Only interrupt on short packet for IN EPs.
  xhci: Remove sparse warning about cmd_status.
  usbcore: warm reset USB3 port in SS.Inactive state
  usbcore: Refine USB3.0 device suspend and resume
  xHCI: report USB3.0 portstatus comply with USB3.0 specification
  xHCI: Set link state support
  xHCI: Clear link state change support
  xHCI: warm reset support
  usb/ch9: use proper endianess for wBytesPerInterval
  xhci: Remove recursive call to xhci_handle_event
  xhci: Add an assertion to check for virt_dev=0 bug.
  xhci: Add rmb() between reading event validity & event data access.
  xhci: Make xHCI driver endian-safe
parents 71a9f9d2 b61d378f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
		max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
	else
		max_tx = 999999;
	if (desc->wBytesPerInterval > max_tx) {
	if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
		dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
				"config %d interface %d altsetting %d ep %d: "
				"setting to %d\n",
+103 −28
Original line number Diff line number Diff line
@@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
		*status = le16_to_cpu(hub->status->port.wPortStatus);
		*change = le16_to_cpu(hub->status->port.wPortChange);

		if ((hub->hdev->parent != NULL) &&
				hub_is_superspeed(hub->hdev)) {
			/* Translate the USB 3 port status */
			u16 tmp = *status & USB_SS_PORT_STAT_MASK;
			if (*status & USB_SS_PORT_STAT_POWER)
				tmp |= USB_PORT_STAT_POWER;
			*status = tmp;
		}

		ret = 0;
	}
	mutex_unlock(&hub->status_mutex);
@@ -2160,11 +2151,76 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
	return status;
}

/* Warm reset a USB3 protocol port */
static int hub_port_warm_reset(struct usb_hub *hub, int port)
{
	int ret;
	u16 portstatus, portchange;

	if (!hub_is_superspeed(hub->hdev)) {
		dev_err(hub->intfdev, "only USB3 hub support warm reset\n");
		return -EINVAL;
	}

	/* Warm reset the port */
	ret = set_port_feature(hub->hdev,
				port, USB_PORT_FEAT_BH_PORT_RESET);
	if (ret) {
		dev_err(hub->intfdev, "cannot warm reset port %d\n", port);
		return ret;
	}

	msleep(20);
	ret = hub_port_status(hub, port, &portstatus, &portchange);

	if (portchange & USB_PORT_STAT_C_RESET)
		clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET);

	if (portchange & USB_PORT_STAT_C_BH_RESET)
		clear_port_feature(hub->hdev, port,
					USB_PORT_FEAT_C_BH_PORT_RESET);

	if (portchange & USB_PORT_STAT_C_LINK_STATE)
		clear_port_feature(hub->hdev, port,
					USB_PORT_FEAT_C_PORT_LINK_STATE);

	return ret;
}

/* Check if a port is power on */
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
{
	int ret = 0;

	if (hub_is_superspeed(hub->hdev)) {
		if (portstatus & USB_SS_PORT_STAT_POWER)
			ret = 1;
	} else {
		if (portstatus & USB_PORT_STAT_POWER)
			ret = 1;
	}

	return ret;
}

#ifdef	CONFIG_PM

#define MASK_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
				USB_PORT_STAT_SUSPEND)
#define WANT_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
{
	int ret = 0;

	if (hub_is_superspeed(hub->hdev)) {
		if ((portstatus & USB_PORT_STAT_LINK_STATE)
				== USB_SS_PORT_LS_U3)
			ret = 1;
	} else {
		if (portstatus & USB_PORT_STAT_SUSPEND)
			ret = 1;
	}

	return ret;
}

/* Determine whether the device on a port is ready for a normal resume,
 * is ready for a reset-resume, or should be disconnected.
@@ -2174,7 +2230,9 @@ static int check_port_resume_type(struct usb_device *udev,
		int status, unsigned portchange, unsigned portstatus)
{
	/* Is the device still present? */
	if (status || (portstatus & MASK_BITS) != WANT_BITS) {
	if (status || port_is_suspended(hub, portstatus) ||
			!port_is_power_on(hub, portstatus) ||
			!(portstatus & USB_PORT_STAT_CONNECTION)) {
		if (status >= 0)
			status = -ENODEV;
	}
@@ -2285,14 +2343,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
	}

	/* see 7.1.7.6 */
	/* Clear PORT_POWER if it's a USB3.0 device connected to USB 3.0
	 * external hub.
	 * FIXME: this is a temporary workaround to make the system able
	 * to suspend/resume.
	 */
	if ((hub->hdev->parent != NULL) && hub_is_superspeed(hub->hdev))
		status = clear_port_feature(hub->hdev, port1,
						USB_PORT_FEAT_POWER);
	if (hub_is_superspeed(hub->hdev))
		status = set_port_feature(hub->hdev,
				port1 | (USB_SS_PORT_LS_U3 << 3),
				USB_PORT_FEAT_LINK_STATE);
	else
		status = set_port_feature(hub->hdev, port1,
						USB_PORT_FEAT_SUSPEND);
@@ -2439,7 +2493,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)

	/* Skip the initial Clear-Suspend step for a remote wakeup */
	status = hub_port_status(hub, port1, &portstatus, &portchange);
	if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
	if (status == 0 && !port_is_suspended(hub, portstatus))
		goto SuspendCleared;

	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
@@ -2447,6 +2501,11 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
	set_bit(port1, hub->busy_bits);

	/* see 7.1.7.7; affects power usage, but not budgeting */
	if (hub_is_superspeed(hub->hdev))
		status = set_port_feature(hub->hdev,
				port1 | (USB_SS_PORT_LS_U0 << 3),
				USB_PORT_FEAT_LINK_STATE);
	else
		status = clear_port_feature(hub->hdev,
				port1, USB_PORT_FEAT_SUSPEND);
	if (status) {
@@ -2470,10 +2529,16 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)

 SuspendCleared:
	if (status == 0) {
		if (hub_is_superspeed(hub->hdev)) {
			if (portchange & USB_PORT_STAT_C_LINK_STATE)
				clear_port_feature(hub->hdev, port1,
					USB_PORT_FEAT_C_PORT_LINK_STATE);
		} else {
			if (portchange & USB_PORT_STAT_C_SUSPEND)
				clear_port_feature(hub->hdev, port1,
						USB_PORT_FEAT_C_SUSPEND);
		}
	}

	clear_bit(port1, hub->busy_bits);

@@ -3147,7 +3212,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,

		/* maybe switch power back on (e.g. root hub was reset) */
		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
				&& !(portstatus & USB_PORT_STAT_POWER))
				&& !port_is_power_on(hub, portstatus))
			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);

		if (portstatus & USB_PORT_STAT_ENABLE)
@@ -3490,6 +3555,16 @@ static void hub_events(void)
						USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
			}

			/* Warm reset a USB3 protocol port if it's in
			 * SS.Inactive state.
			 */
			if (hub_is_superspeed(hub->hdev) &&
				(portstatus & USB_PORT_STAT_LINK_STATE)
					== USB_SS_PORT_LS_SS_INACTIVE) {
				dev_dbg(hub_dev, "warm reset port %d\n", i);
				hub_port_warm_reset(hub, i);
			}

			if (connect_change)
				hub_port_connect_change(hub, i,
						portstatus, portchange);
+26 −25
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ static void xhci_print_op_regs(struct xhci_hcd *xhci)

static void xhci_print_ports(struct xhci_hcd *xhci)
{
	u32 __iomem *addr;
	__le32 __iomem *addr;
	int i, j;
	int ports;
	char *names[NUM_PORT_REGS] = {
@@ -253,27 +253,27 @@ void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
{
	u64	address;
	u32	type = xhci_readl(xhci, &trb->link.control) & TRB_TYPE_BITMASK;
	u32	type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK;

	switch (type) {
	case TRB_TYPE(TRB_LINK):
		xhci_dbg(xhci, "Link TRB:\n");
		xhci_print_trb_offsets(xhci, trb);

		address = trb->link.segment_ptr;
		address = le64_to_cpu(trb->link.segment_ptr);
		xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);

		xhci_dbg(xhci, "Interrupter target = 0x%x\n",
				GET_INTR_TARGET(trb->link.intr_target));
			 GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
		xhci_dbg(xhci, "Cycle bit = %u\n",
				(unsigned int) (trb->link.control & TRB_CYCLE));
			 (unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
		xhci_dbg(xhci, "Toggle cycle bit = %u\n",
				(unsigned int) (trb->link.control & LINK_TOGGLE));
			 (unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
		xhci_dbg(xhci, "No Snoop bit = %u\n",
				(unsigned int) (trb->link.control & TRB_NO_SNOOP));
			 (unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
		break;
	case TRB_TYPE(TRB_TRANSFER):
		address = trb->trans_event.buffer;
		address = le64_to_cpu(trb->trans_event.buffer);
		/*
		 * FIXME: look at flags to figure out if it's an address or if
		 * the data is directly in the buffer field.
@@ -281,11 +281,12 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
		xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
		break;
	case TRB_TYPE(TRB_COMPLETION):
		address = trb->event_cmd.cmd_trb;
		address = le64_to_cpu(trb->event_cmd.cmd_trb);
		xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
		xhci_dbg(xhci, "Completion status = %u\n",
				(unsigned int) GET_COMP_CODE(trb->event_cmd.status));
		xhci_dbg(xhci, "Flags = 0x%x\n", (unsigned int) trb->event_cmd.flags);
			 (unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
		xhci_dbg(xhci, "Flags = 0x%x\n",
			 (unsigned int) le32_to_cpu(trb->event_cmd.flags));
		break;
	default:
		xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
@@ -311,16 +312,16 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
{
	int i;
	u32 addr = (u32) seg->dma;
	u64 addr = seg->dma;
	union xhci_trb *trb = seg->trbs;

	for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
		trb = &seg->trbs[i];
		xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
				lower_32_bits(trb->link.segment_ptr),
				upper_32_bits(trb->link.segment_ptr),
				(unsigned int) trb->link.intr_target,
				(unsigned int) trb->link.control);
		xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
			 (u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
			 (u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
			 (unsigned int) le32_to_cpu(trb->link.intr_target),
			 (unsigned int) le32_to_cpu(trb->link.control));
		addr += sizeof(*trb);
	}
}
@@ -391,18 +392,18 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,

void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
{
	u32 addr = (u32) erst->erst_dma_addr;
	u64 addr = erst->erst_dma_addr;
	int i;
	struct xhci_erst_entry *entry;

	for (i = 0; i < erst->num_entries; ++i) {
		entry = &erst->entries[i];
		xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
				(unsigned int) addr,
				lower_32_bits(entry->seg_addr),
				upper_32_bits(entry->seg_addr),
				(unsigned int) entry->seg_size,
				(unsigned int) entry->rsvd);
		xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n",
			 addr,
			 lower_32_bits(le64_to_cpu(entry->seg_addr)),
			 upper_32_bits(le64_to_cpu(entry->seg_addr)),
			 (unsigned int) le32_to_cpu(entry->seg_size),
			 (unsigned int) le32_to_cpu(entry->rsvd));
		addr += sizeof(*entry);
	}
}
@@ -436,7 +437,7 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
{
	struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);

	switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
	switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
	case 0:
		return "enabled/disabled";
	case 1:
+116 −49
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
	temp |= 0x0008;
	/* Bits 6:5 - no TTs in root ports */
	/* Bit  7 - no port indicators */
	desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
	desc->wHubCharacteristics = cpu_to_le16(temp);
}

/* Fill in the USB 2.0 roothub descriptor */
@@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
}

static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
		u16 wIndex, u32 __iomem *addr, u32 port_status)
		u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
	/* Don't allow the USB core to disable SuperSpeed ports. */
	if (hcd->speed == HCD_USB3) {
@@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
}

static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
		u16 wIndex, u32 __iomem *addr, u32 port_status)
		u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
	char *port_change_bit;
	u32 status;
@@ -341,6 +341,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
		status = PORT_RC;
		port_change_bit = "reset";
		break;
	case USB_PORT_FEAT_C_BH_PORT_RESET:
		status = PORT_WRC;
		port_change_bit = "warm(BH) reset";
		break;
	case USB_PORT_FEAT_C_CONNECTION:
		status = PORT_CSC;
		port_change_bit = "connect";
@@ -357,6 +361,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
		status = PORT_PLC;
		port_change_bit = "suspend/resume";
		break;
	case USB_PORT_FEAT_C_PORT_LINK_STATE:
		status = PORT_PLC;
		port_change_bit = "link state";
		break;
	default:
		/* Should never happen */
		return;
@@ -376,9 +384,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
	unsigned long flags;
	u32 temp, temp1, status;
	int retval = 0;
	u32 __iomem **port_array;
	__le32 __iomem **port_array;
	int slot_id;
	struct xhci_bus_state *bus_state;
	u16 link_state = 0;

	if (hcd->speed == HCD_USB3) {
		ports = xhci->num_usb3_ports;
@@ -422,9 +431,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		}
		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", wIndex, temp);

		/* FIXME - should we return a port status value like the USB
		 * 3.0 external hubs do?
		 */
		/* wPortChange bits */
		if (temp & PORT_CSC)
			status |= USB_PORT_STAT_C_CONNECTION << 16;
@@ -432,13 +438,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			status |= USB_PORT_STAT_C_ENABLE << 16;
		if ((temp & PORT_OCC))
			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
		/*
		 * FIXME ignoring reset and USB 2.1/3.0 specific
		 * changes
		 */
		if ((temp & PORT_RC))
			status |= USB_PORT_STAT_C_RESET << 16;
		/* USB3.0 only */
		if (hcd->speed == HCD_USB3) {
			if ((temp & PORT_PLC))
				status |= USB_PORT_STAT_C_LINK_STATE << 16;
			if ((temp & PORT_WRC))
				status |= USB_PORT_STAT_C_BH_RESET << 16;
		}

		if (hcd->speed != HCD_USB3) {
			if ((temp & PORT_PLS_MASK) == XDEV_U3
					&& (temp & PORT_POWER))
			status |= 1 << USB_PORT_FEAT_SUSPEND;
				status |= USB_PORT_STAT_SUSPEND;
		}
		if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
			if ((temp & PORT_RESET) || !(temp & PORT_PE))
				goto error;
@@ -469,6 +483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			&& (temp & PORT_POWER)
			&& (bus_state->suspended_ports & (1 << wIndex))) {
			bus_state->suspended_ports &= ~(1 << wIndex);
			if (hcd->speed != HCD_USB3)
				bus_state->port_c_suspend |= 1 << wIndex;
		}
		if (temp & PORT_CONNECT) {
@@ -481,14 +496,28 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			status |= USB_PORT_STAT_OVERCURRENT;
		if (temp & PORT_RESET)
			status |= USB_PORT_STAT_RESET;
		if (temp & PORT_POWER)
		if (temp & PORT_POWER) {
			if (hcd->speed == HCD_USB3)
				status |= USB_SS_PORT_STAT_POWER;
			else
				status |= USB_PORT_STAT_POWER;
		}
		/* Port Link State */
		if (hcd->speed == HCD_USB3) {
			/* resume state is a xHCI internal state.
			 * Do not report it to usb core.
			 */
			if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
				status |= (temp & PORT_PLS_MASK);
		}
		if (bus_state->port_c_suspend & (1 << wIndex))
			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
		break;
	case SetPortFeature:
		if (wValue == USB_PORT_FEAT_LINK_STATE)
			link_state = (wIndex & 0xff00) >> 3;
		wIndex &= 0xff;
		if (!wIndex || wIndex > ports)
			goto error;
@@ -537,6 +566,44 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			temp = xhci_readl(xhci, port_array[wIndex]);
			bus_state->suspended_ports |= 1 << wIndex;
			break;
		case USB_PORT_FEAT_LINK_STATE:
			temp = xhci_readl(xhci, port_array[wIndex]);
			/* Software should not attempt to set
			 * port link state above '5' (Rx.Detect) and the port
			 * must be enabled.
			 */
			if ((temp & PORT_PE) == 0 ||
				(link_state > USB_SS_PORT_LS_RX_DETECT)) {
				xhci_warn(xhci, "Cannot set link state.\n");
				goto error;
			}

			if (link_state == USB_SS_PORT_LS_U3) {
				slot_id = xhci_find_slot_id_by_port(hcd, xhci,
						wIndex + 1);
				if (slot_id) {
					/* unlock to execute stop endpoint
					 * commands */
					spin_unlock_irqrestore(&xhci->lock,
								flags);
					xhci_stop_device(xhci, slot_id, 1);
					spin_lock_irqsave(&xhci->lock, flags);
				}
			}

			temp = xhci_port_state_to_neutral(temp);
			temp &= ~PORT_PLS_MASK;
			temp |= PORT_LINK_STROBE | link_state;
			xhci_writel(xhci, temp, port_array[wIndex]);

			spin_unlock_irqrestore(&xhci->lock, flags);
			msleep(20); /* wait device to enter */
			spin_lock_irqsave(&xhci->lock, flags);

			temp = xhci_readl(xhci, port_array[wIndex]);
			if (link_state == USB_SS_PORT_LS_U3)
				bus_state->suspended_ports |= 1 << wIndex;
			break;
		case USB_PORT_FEAT_POWER:
			/*
			 * Turn on ports, even if there isn't per-port switching.
@@ -557,6 +624,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			temp = xhci_readl(xhci, port_array[wIndex]);
			xhci_dbg(xhci, "set port reset, actual port %d status  = 0x%x\n", wIndex, temp);
			break;
		case USB_PORT_FEAT_BH_PORT_RESET:
			temp |= PORT_WR;
			xhci_writel(xhci, temp, port_array[wIndex]);

			temp = xhci_readl(xhci, port_array[wIndex]);
			break;
		default:
			goto error;
		}
@@ -584,14 +657,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			if (temp & XDEV_U3) {
				if ((temp & PORT_PE) == 0)
					goto error;
				if (DEV_SUPERSPEED(temp)) {
					temp = xhci_port_state_to_neutral(temp);
					temp &= ~PORT_PLS_MASK;
					temp |= PORT_LINK_STROBE | XDEV_U0;
					xhci_writel(xhci, temp,
							port_array[wIndex]);
					xhci_readl(xhci, port_array[wIndex]);
				} else {

				temp = xhci_port_state_to_neutral(temp);
				temp &= ~PORT_PLS_MASK;
				temp |= PORT_LINK_STROBE | XDEV_RESUME;
@@ -612,7 +678,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
						port_array[wIndex]);
			}
			bus_state->port_c_suspend |= 1 << wIndex;
			}

			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
					wIndex + 1);
@@ -625,9 +690,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		case USB_PORT_FEAT_C_SUSPEND:
			bus_state->port_c_suspend &= ~(1 << wIndex);
		case USB_PORT_FEAT_C_RESET:
		case USB_PORT_FEAT_C_BH_PORT_RESET:
		case USB_PORT_FEAT_C_CONNECTION:
		case USB_PORT_FEAT_C_OVER_CURRENT:
		case USB_PORT_FEAT_C_ENABLE:
		case USB_PORT_FEAT_C_PORT_LINK_STATE:
			xhci_clear_port_change_bit(xhci, wValue, wIndex,
					port_array[wIndex], temp);
			break;
@@ -664,7 +731,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
	int i, retval;
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int ports;
	u32 __iomem **port_array;
	__le32 __iomem **port_array;
	struct xhci_bus_state *bus_state;

	if (hcd->speed == HCD_USB3) {
@@ -681,7 +748,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
	memset(buf, 0, retval);
	status = 0;

	mask = PORT_CSC | PORT_PEC | PORT_OCC;
	mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC;

	spin_lock_irqsave(&xhci->lock, flags);
	/* For each port, did anything change?  If so, set that bit in buf. */
@@ -709,7 +776,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int max_ports, port_index;
	u32 __iomem **port_array;
	__le32 __iomem **port_array;
	struct xhci_bus_state *bus_state;
	unsigned long flags;

@@ -779,7 +846,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)

		if (DEV_HIGHSPEED(t1)) {
			/* enable remote wake up for USB 2.0 */
			u32 __iomem *addr;
			__le32 __iomem *addr;
			u32 tmp;

			/* Add one to the port status register address to get
@@ -801,7 +868,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int max_ports, port_index;
	u32 __iomem **port_array;
	__le32 __iomem **port_array;
	struct xhci_bus_state *bus_state;
	u32 temp;
	unsigned long flags;
@@ -875,7 +942,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)

		if (DEV_HIGHSPEED(temp)) {
			/* disable remote wake up for USB 2.0 */
			u32 __iomem *addr;
			__le32 __iomem *addr;
			u32 tmp;

			/* Add one to the port status register address to get
+62 −62

File changed.

Preview size limit exceeded, changes collapsed.

Loading