USB: Add support to enable/disable USB3 link states.
[cascardo/linux.git] / include / linux / usb.h
index 69163a0..40439df 100644 (file)
@@ -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
@@ -424,6 +463,7 @@ enum usb_device_removable {
  *     access from userspace
  * @usbfs_dentry: usbfs dentry entry for the device
  * @maxchild: number of ports if hub
+ * @children: child devices - USB devices that are attached to this hub
  * @quirks: quirks of the whole device
  * @urbnum: number of URBs submitted for the whole device
  * @active_duration: total time device is not suspended
@@ -434,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
@@ -490,6 +536,7 @@ struct usb_device {
        struct list_head filelist;
 
        int maxchild;
+       struct usb_device **children;
 
        u32 quirks;
        atomic_t urbnum;
@@ -505,6 +552,9 @@ 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;
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -515,8 +565,6 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)
 
 extern struct usb_device *usb_get_dev(struct usb_device *dev);
 extern void usb_put_dev(struct usb_device *dev);
-extern struct usb_device *usb_get_hub_child_device(struct usb_device *hdev,
-       int port1);
 
 /* USB device locking */
 #define usb_lock_device(udev)          device_lock(&(udev)->dev)
@@ -542,6 +590,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);
@@ -790,6 +844,8 @@ extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
                                struct device_driver *driver,
                                const char *buf, size_t count);
 
+extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);
+
 /**
  * struct usbdrv_wrap - wrapper for driver-model structure
  * @driver: The driver-model core driver structure.
@@ -840,6 +896,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.
@@ -880,6 +939,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)