aboutsummaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorGreg Kroah-Hartman2012-05-18 16:32:52 -0700
committerGreg Kroah-Hartman2012-05-18 16:32:52 -0700
commitf06b9f3ced17dfb559af2c0c5db2d68e939f06e6 (patch)
treeafd1cd52582f1c5088f891b08b13a3f63c597f45 /include/linux
parent7cbb062ade87b987a24aa834bbde32ad8374a4cf (diff)
parente1f12eb6ba6f1e74007eb01ed26fad7c5239d62b (diff)
Merge tag 'for-usb-next-2012-05-18' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next
xhci: Link PM and bug fixes for 3.5. Hi Greg, Here's the final Link Power Management patches, along with a couple of bug fixes that have been sitting in my queue. I've fixed all the comments that Alan and Andiry had on the Link PM patches, so I think they're ready to go. Sarah Sharp
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/usb.h60
-rw-r--r--include/linux/usb/ch11.h2
-rw-r--r--include/linux/usb/ch9.h56
-rw-r--r--include/linux/usb/hcd.h9
4 files changed, 127 insertions, 0 deletions
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 14933451d21d..c19297a8779c 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -378,6 +378,45 @@ enum usb_device_removable {
USB_DEVICE_FIXED,
};
+/*
+ * USB 3.0 Link Power Management (LPM) parameters.
+ *
+ * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit.
+ * MEL is the USB 3.0 Link PM latency for host-initiated LPM exit.
+ * All three are stored in nanoseconds.
+ */
+struct usb3_lpm_parameters {
+ /*
+ * Maximum exit latency (MEL) for the host to send a packet to the
+ * device (either a Ping for isoc endpoints, or a data packet for
+ * interrupt endpoints), the hubs to decode the packet, and for all hubs
+ * in the path to transition the links to U0.
+ */
+ unsigned int mel;
+ /*
+ * Maximum exit latency for a device-initiated LPM transition to bring
+ * all links into U0. Abbreviated as "PEL" in section 9.4.12 of the USB
+ * 3.0 spec, with no explanation of what "P" stands for. "Path"?
+ */
+ unsigned int pel;
+
+ /*
+ * The System Exit Latency (SEL) includes PEL, and three other
+ * latencies. After a device initiates a U0 transition, it will take
+ * some time from when the device sends the ERDY to when it will finally
+ * receive the data packet. Basically, SEL should be the worse-case
+ * latency from when a device starts initiating a U0 transition to when
+ * it will get data.
+ */
+ unsigned int sel;
+ /*
+ * The idle timeout value that is currently programmed into the parent
+ * hub for this device. When the timer counts to zero, the parent hub
+ * will initiate an LPM transition to either U1 or U2.
+ */
+ int timeout;
+};
+
/**
* struct usb_device - kernel's representation of a USB device
* @devnum: device number; address on a USB bus
@@ -435,6 +474,12 @@ enum usb_device_removable {
* specific data for the device.
* @slot_id: Slot ID assigned by xHCI
* @removable: Device can be physically removed from this port
+ * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout.
+ * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout.
+ * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm()
+ * to keep track of the number of functions that require USB 3.0 Link Power
+ * Management to be disabled for this usb_device. This count should only
+ * be manipulated by those functions, with the bandwidth_mutex is held.
*
* Notes:
* Usbcore drivers should not set usbdev->state directly. Instead use
@@ -481,6 +526,7 @@ struct usb_device {
unsigned lpm_capable:1;
unsigned usb2_hw_lpm_capable:1;
unsigned usb2_hw_lpm_enabled:1;
+ unsigned usb3_lpm_enabled:1;
int string_langid;
/* static strings from the device */
@@ -507,6 +553,10 @@ struct usb_device {
struct wusb_dev *wusb_dev;
int slot_id;
enum usb_device_removable removable;
+ struct usb3_lpm_parameters u1_params;
+ struct usb3_lpm_parameters u2_params;
+ unsigned lpm_disable_count;
+ unsigned hub_initiated_lpm_disable_count;
};
#define to_usb_device(d) container_of(d, struct usb_device, dev)
@@ -542,6 +592,12 @@ extern void usb_autopm_put_interface_async(struct usb_interface *intf);
extern void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
extern void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
+extern int usb_disable_lpm(struct usb_device *udev);
+extern void usb_enable_lpm(struct usb_device *udev);
+/* Same as above, but these functions lock/unlock the bandwidth_mutex. */
+extern int usb_unlocked_disable_lpm(struct usb_device *udev);
+extern void usb_unlocked_enable_lpm(struct usb_device *udev);
+
static inline void usb_mark_last_busy(struct usb_device *udev)
{
pm_runtime_mark_last_busy(&udev->dev);
@@ -842,6 +898,9 @@ struct usbdrv_wrap {
* for interfaces bound to this driver.
* @soft_unbind: if set to 1, the USB core will not kill URBs and disable
* endpoints before calling the driver's disconnect method.
+ * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs
+ * to initiate lower power link state transitions when an idle timeout
+ * occurs. Device-initiated USB 3.0 link PM will still be allowed.
*
* USB interface drivers must provide a name, probe() and disconnect()
* methods, and an id_table. Other driver fields are optional.
@@ -882,6 +941,7 @@ struct usb_driver {
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
+ unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
#define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index f1d26b6067f1..b6c2863b2c94 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -76,6 +76,8 @@
#define USB_PORT_FEAT_C_BH_PORT_RESET 29
#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
+#define USB_PORT_LPM_TIMEOUT(p) (((p) & 0xff) << 8)
+
/* USB 3.0 hub remote wake mask bits, see table 10-14 */
#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8)
#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9)
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index e785d85b617f..d1d732c2838d 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -392,6 +392,11 @@ struct usb_endpoint_descriptor {
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
+#define USB_ENDPOINT_INTRTYPE 0x30
+#define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
+#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
+
#define USB_ENDPOINT_SYNCTYPE 0x0c
#define USB_ENDPOINT_SYNC_NONE (0 << 2)
#define USB_ENDPOINT_SYNC_ASYNC (1 << 2)
@@ -594,6 +599,12 @@ static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
return __le16_to_cpu(epd->wMaxPacketSize);
}
+static inline int usb_endpoint_interrupt_type(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
+}
+
/*-------------------------------------------------------------------------*/
/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
@@ -935,6 +946,51 @@ enum usb_device_state {
*/
};
+enum usb3_link_state {
+ USB3_LPM_U0 = 0,
+ USB3_LPM_U1,
+ USB3_LPM_U2,
+ USB3_LPM_U3
+};
+
+/*
+ * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
+ * 0xff means the parent hub will accept transitions to U1, but will not
+ * initiate a transition.
+ *
+ * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
+ * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved
+ * values.
+ *
+ * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
+ * 0xff means the parent hub will accept transitions to U2, but will not
+ * initiate a transition.
+ *
+ * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
+ * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2
+ * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
+ * 65.024ms.
+ */
+#define USB3_LPM_DISABLED 0x0
+#define USB3_LPM_U1_MAX_TIMEOUT 0x7F
+#define USB3_LPM_U2_MAX_TIMEOUT 0xFE
+#define USB3_LPM_DEVICE_INITIATED 0xFF
+
+struct usb_set_sel_req {
+ __u8 u1_sel;
+ __u8 u1_pel;
+ __le16 u2_sel;
+ __le16 u2_pel;
+} __attribute__ ((packed));
+
+/*
+ * The Set System Exit Latency control transfer provides one byte each for
+ * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each
+ * are two bytes long.
+ */
+#define USB3_LPM_MAX_U1_SEL_PEL 0xFF
+#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF
+
/*-------------------------------------------------------------------------*/
/*
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index bbb946437070..7f855d50cdf5 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -344,6 +344,15 @@ struct hc_driver {
*/
int (*update_device)(struct usb_hcd *, struct usb_device *);
int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int);
+ /* USB 3.0 Link Power Management */
+ /* Returns the USB3 hub-encoded value for the U1/U2 timeout. */
+ int (*enable_usb3_lpm_timeout)(struct usb_hcd *,
+ struct usb_device *, enum usb3_link_state state);
+ /* The xHCI host controller can still fail the command to
+ * disable the LPM timeouts, so this can return an error code.
+ */
+ int (*disable_usb3_lpm_timeout)(struct usb_hcd *,
+ struct usb_device *, enum usb3_link_state state);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);