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
This commit is contained in:
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user