diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/usb.h | 21 | ||||
-rw-r--r-- | include/linux/usb/ch11.h | 2 | ||||
-rw-r--r-- | include/linux/usb/ch9.h | 45 | ||||
-rw-r--r-- | include/linux/usb/hcd.h | 9 |
4 files changed, 75 insertions, 2 deletions
diff --git a/include/linux/usb.h b/include/linux/usb.h index 22e7b53123ef..40439dfd81a7 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -409,6 +409,12 @@ struct usb3_lpm_parameters { * 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; }; /** @@ -468,8 +474,12 @@ struct usb3_lpm_parameters { * 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 U1 (USB 3.0 LPM). - * @u2_params: exit latencies for U2 (USB 3.0 LPM). + * @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 @@ -544,6 +554,7 @@ struct usb_device { 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) @@ -579,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); 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..43bce9da7a4d 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -935,6 +935,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); |