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

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

Merge tag 'for-usb-next-2013-06-06' of...

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

Sarah writes:

xHCI: USB 2.0 Link PM and misc cleanup patches

Hi Greg,

Here's six patches to be queued for 3.11.

The first four add support for a new type of host hardware-managed USB
2.0 Link Power Management.  Hosts with BESL support, including Intel
Haswell ULT systems, will now be able to have USB 2.0 devices go into
the lower power link state (L1) in between packets.  These patches have
been tested on Haswell ULT platforms with USB 2.0 webcams that support
Link PM.

The other two patches are clean up.  One from Julius clarifies the xHCI
endpoint context debugging to make it consistent with standard endpoint
addresses, instead of xHCI endpoint context indexes.  The one from Alex
changes the xHCI driver to be consistent about passing a void pointer to
the xHCI IRQ handler.

Sarah Sharp
parents 3a57aa81 17f34867
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -236,3 +236,30 @@ Description:
		This attribute is to expose these information to user space.
		This attribute is to expose these information to user space.
		The file will read "hotplug", "wired" and "not used" if the
		The file will read "hotplug", "wired" and "not used" if the
		information is available, and "unknown" otherwise.
		information is available, and "unknown" otherwise.

What:		/sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
Date:		May 2013
Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
Description:
		USB 2.0 devices may support hardware link power management (LPM)
		L1 sleep state. The usb2_lpm_l1_timeout attribute allows
		tuning the timeout for L1 inactivity timer (LPM timer), e.g.
		needed inactivity time before host requests the device to go to L1 sleep.
		Useful for power management tuning.
		Supported values are 0 - 65535 microseconds.

What:		/sys/bus/usb/devices/.../power/usb2_lpm_besl
Date:		May 2013
Contact:	Mathias Nyman <mathias.nyman@linux.intel.com>
Description:
		USB 2.0 devices that support hardware link power management (LPM)
		L1 sleep state now use a best effort service latency value (BESL) to
		indicate the best effort to resumption of service to the device after the
		initiation of the resume event.
		If the device does not have a preferred besl value then the host can select
		one instead. This usb2_lpm_besl attribute allows to tune the host selected besl
		value in order to tune power saving and service latency.

		Supported values are 0 - 15.
		More information on how besl values map to microseconds can be found in
		USB 2.0 ECN Errata for Link Power Management, section 4.10)
+54 −0
Original line number Original line Diff line number Diff line
@@ -497,8 +497,62 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,
static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,
			set_usb2_hardware_lpm);
			set_usb2_hardware_lpm);


static ssize_t
show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
			 char *buf)
{
	struct usb_device *udev = to_usb_device(dev);
	return sprintf(buf, "%d\n", udev->l1_params.timeout);
}

static ssize_t
set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
			const char *buf, size_t count)
{
	struct usb_device *udev = to_usb_device(dev);
	u16 timeout;

	if (kstrtou16(buf, 0, &timeout))
		return -EINVAL;

	udev->l1_params.timeout = timeout;

	return count;
}

static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR,
		   show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout);

static ssize_t
show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
		   char *buf)
{
	struct usb_device *udev = to_usb_device(dev);
	return sprintf(buf, "%d\n", udev->l1_params.besl);
}

static ssize_t
set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct usb_device *udev = to_usb_device(dev);
	u8 besl;

	if (kstrtou8(buf, 0, &besl) || besl > 15)
		return -EINVAL;

	udev->l1_params.besl = besl;

	return count;
}

static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR,
		   show_usb2_lpm_besl, set_usb2_lpm_besl);

static struct attribute *usb2_hardware_lpm_attr[] = {
static struct attribute *usb2_hardware_lpm_attr[] = {
	&dev_attr_usb2_hardware_lpm.attr,
	&dev_attr_usb2_hardware_lpm.attr,
	&dev_attr_usb2_lpm_l1_timeout.attr,
	&dev_attr_usb2_lpm_besl.attr,
	NULL,
	NULL,
};
};
static struct attribute_group usb2_hardware_lpm_attr_group = {
static struct attribute_group usb2_hardware_lpm_attr_group = {
+4 −1
Original line number Original line Diff line number Diff line
@@ -503,11 +503,14 @@ static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
	if (last_ep < 31)
	if (last_ep < 31)
		last_ep_ctx = last_ep + 1;
		last_ep_ctx = last_ep + 1;
	for (i = 0; i < last_ep_ctx; ++i) {
	for (i = 0; i < last_ep_ctx; ++i) {
		unsigned int epaddr = xhci_get_endpoint_address(i);
		struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
		struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
		dma_addr_t dma = ctx->dma +
		dma_addr_t dma = ctx->dma +
			((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
			((unsigned long)ep_ctx - (unsigned long)ctx->bytes);


		xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
		xhci_dbg(xhci, "%s Endpoint %02d Context (ep_index %02d):\n",
				usb_endpoint_out(epaddr) ? "OUT" : "IN",
				epaddr & USB_ENDPOINT_NUMBER_MASK, i);
		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
				&ep_ctx->ep_info,
				&ep_ctx->ep_info,
				(unsigned long long)dma, ep_ctx->ep_info);
				(unsigned long long)dma, ep_ctx->ep_info);
+1 −0
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@


/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */
/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */
#define XHCI_HLC               (1 << 19)
#define XHCI_HLC               (1 << 19)
#define XHCI_BLC               (1 << 19)


/* command register values to disable interrupts and halt the HC */
/* command register values to disable interrupts and halt the HC */
/* start/stop HC execution - do not write unless HC is halted*/
/* start/stop HC execution - do not write unless HC is halted*/
+7 −9
Original line number Original line Diff line number Diff line
@@ -867,18 +867,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		case USB_PORT_FEAT_U1_TIMEOUT:
		case USB_PORT_FEAT_U1_TIMEOUT:
			if (hcd->speed != HCD_USB3)
			if (hcd->speed != HCD_USB3)
				goto error;
				goto error;
			temp = xhci_readl(xhci, port_array[wIndex] + 1);
			temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC);
			temp &= ~PORT_U1_TIMEOUT_MASK;
			temp &= ~PORT_U1_TIMEOUT_MASK;
			temp |= PORT_U1_TIMEOUT(timeout);
			temp |= PORT_U1_TIMEOUT(timeout);
			xhci_writel(xhci, temp, port_array[wIndex] + 1);
			xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC);
			break;
			break;
		case USB_PORT_FEAT_U2_TIMEOUT:
		case USB_PORT_FEAT_U2_TIMEOUT:
			if (hcd->speed != HCD_USB3)
			if (hcd->speed != HCD_USB3)
				goto error;
				goto error;
			temp = xhci_readl(xhci, port_array[wIndex] + 1);
			temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC);
			temp &= ~PORT_U2_TIMEOUT_MASK;
			temp &= ~PORT_U2_TIMEOUT_MASK;
			temp |= PORT_U2_TIMEOUT(timeout);
			temp |= PORT_U2_TIMEOUT(timeout);
			xhci_writel(xhci, temp, port_array[wIndex] + 1);
			xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC);
			break;
			break;
		default:
		default:
			goto error;
			goto error;
@@ -1098,10 +1098,8 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
			__le32 __iomem *addr;
			__le32 __iomem *addr;
			u32 tmp;
			u32 tmp;


			/* Add one to the port status register address to get
			/* Get the port power control register address. */
			 * the port power control register address.
			addr = port_array[port_index] + PORTPMSC;
			 */
			addr = port_array[port_index] + 1;
			tmp = xhci_readl(xhci, addr);
			tmp = xhci_readl(xhci, addr);
			tmp |= PORT_RWE;
			tmp |= PORT_RWE;
			xhci_writel(xhci, tmp, addr);
			xhci_writel(xhci, tmp, addr);
@@ -1193,7 +1191,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
			/* Add one to the port status register address to get
			/* Add one to the port status register address to get
			 * the port power control register address.
			 * the port power control register address.
			 */
			 */
			addr = port_array[port_index] + 1;
			addr = port_array[port_index] + PORTPMSC;
			tmp = xhci_readl(xhci, addr);
			tmp = xhci_readl(xhci, addr);
			tmp &= ~PORT_RWE;
			tmp &= ~PORT_RWE;
			xhci_writel(xhci, tmp, addr);
			xhci_writel(xhci, tmp, addr);
Loading