diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-18 19:32:52 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-18 19:32:52 -0400 |
commit | f06b9f3ced17dfb559af2c0c5db2d68e939f06e6 (patch) | |
tree | afd1cd52582f1c5088f891b08b13a3f63c597f45 /include | |
parent | 7cbb062ade87b987a24aa834bbde32ad8374a4cf (diff) | |
parent | e1f12eb6ba6f1e74007eb01ed26fad7c5239d62b (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')
-rw-r--r-- | include/linux/usb.h | 60 | ||||
-rw-r--r-- | include/linux/usb/ch11.h | 2 | ||||
-rw-r--r-- | include/linux/usb/ch9.h | 56 | ||||
-rw-r--r-- | include/linux/usb/hcd.h | 9 |
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 { | |||
378 | USB_DEVICE_FIXED, | 378 | USB_DEVICE_FIXED, |
379 | }; | 379 | }; |
380 | 380 | ||
381 | /* | ||
382 | * USB 3.0 Link Power Management (LPM) parameters. | ||
383 | * | ||
384 | * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit. | ||
385 | * MEL is the USB 3.0 Link PM latency for host-initiated LPM exit. | ||
386 | * All three are stored in nanoseconds. | ||
387 | */ | ||
388 | struct usb3_lpm_parameters { | ||
389 | /* | ||
390 | * Maximum exit latency (MEL) for the host to send a packet to the | ||
391 | * device (either a Ping for isoc endpoints, or a data packet for | ||
392 | * interrupt endpoints), the hubs to decode the packet, and for all hubs | ||
393 | * in the path to transition the links to U0. | ||
394 | */ | ||
395 | unsigned int mel; | ||
396 | /* | ||
397 | * Maximum exit latency for a device-initiated LPM transition to bring | ||
398 | * all links into U0. Abbreviated as "PEL" in section 9.4.12 of the USB | ||
399 | * 3.0 spec, with no explanation of what "P" stands for. "Path"? | ||
400 | */ | ||
401 | unsigned int pel; | ||
402 | |||
403 | /* | ||
404 | * The System Exit Latency (SEL) includes PEL, and three other | ||
405 | * latencies. After a device initiates a U0 transition, it will take | ||
406 | * some time from when the device sends the ERDY to when it will finally | ||
407 | * receive the data packet. Basically, SEL should be the worse-case | ||
408 | * latency from when a device starts initiating a U0 transition to when | ||
409 | * it will get data. | ||
410 | */ | ||
411 | unsigned int sel; | ||
412 | /* | ||
413 | * The idle timeout value that is currently programmed into the parent | ||
414 | * hub for this device. When the timer counts to zero, the parent hub | ||
415 | * will initiate an LPM transition to either U1 or U2. | ||
416 | */ | ||
417 | int timeout; | ||
418 | }; | ||
419 | |||
381 | /** | 420 | /** |
382 | * struct usb_device - kernel's representation of a USB device | 421 | * struct usb_device - kernel's representation of a USB device |
383 | * @devnum: device number; address on a USB bus | 422 | * @devnum: device number; address on a USB bus |
@@ -435,6 +474,12 @@ enum usb_device_removable { | |||
435 | * specific data for the device. | 474 | * specific data for the device. |
436 | * @slot_id: Slot ID assigned by xHCI | 475 | * @slot_id: Slot ID assigned by xHCI |
437 | * @removable: Device can be physically removed from this port | 476 | * @removable: Device can be physically removed from this port |
477 | * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout. | ||
478 | * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout. | ||
479 | * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm() | ||
480 | * to keep track of the number of functions that require USB 3.0 Link Power | ||
481 | * Management to be disabled for this usb_device. This count should only | ||
482 | * be manipulated by those functions, with the bandwidth_mutex is held. | ||
438 | * | 483 | * |
439 | * Notes: | 484 | * Notes: |
440 | * Usbcore drivers should not set usbdev->state directly. Instead use | 485 | * Usbcore drivers should not set usbdev->state directly. Instead use |
@@ -481,6 +526,7 @@ struct usb_device { | |||
481 | unsigned lpm_capable:1; | 526 | unsigned lpm_capable:1; |
482 | unsigned usb2_hw_lpm_capable:1; | 527 | unsigned usb2_hw_lpm_capable:1; |
483 | unsigned usb2_hw_lpm_enabled:1; | 528 | unsigned usb2_hw_lpm_enabled:1; |
529 | unsigned usb3_lpm_enabled:1; | ||
484 | int string_langid; | 530 | int string_langid; |
485 | 531 | ||
486 | /* static strings from the device */ | 532 | /* static strings from the device */ |
@@ -507,6 +553,10 @@ struct usb_device { | |||
507 | struct wusb_dev *wusb_dev; | 553 | struct wusb_dev *wusb_dev; |
508 | int slot_id; | 554 | int slot_id; |
509 | enum usb_device_removable removable; | 555 | enum usb_device_removable removable; |
556 | struct usb3_lpm_parameters u1_params; | ||
557 | struct usb3_lpm_parameters u2_params; | ||
558 | unsigned lpm_disable_count; | ||
559 | unsigned hub_initiated_lpm_disable_count; | ||
510 | }; | 560 | }; |
511 | #define to_usb_device(d) container_of(d, struct usb_device, dev) | 561 | #define to_usb_device(d) container_of(d, struct usb_device, dev) |
512 | 562 | ||
@@ -542,6 +592,12 @@ extern void usb_autopm_put_interface_async(struct usb_interface *intf); | |||
542 | extern void usb_autopm_get_interface_no_resume(struct usb_interface *intf); | 592 | extern void usb_autopm_get_interface_no_resume(struct usb_interface *intf); |
543 | extern void usb_autopm_put_interface_no_suspend(struct usb_interface *intf); | 593 | extern void usb_autopm_put_interface_no_suspend(struct usb_interface *intf); |
544 | 594 | ||
595 | extern int usb_disable_lpm(struct usb_device *udev); | ||
596 | extern void usb_enable_lpm(struct usb_device *udev); | ||
597 | /* Same as above, but these functions lock/unlock the bandwidth_mutex. */ | ||
598 | extern int usb_unlocked_disable_lpm(struct usb_device *udev); | ||
599 | extern void usb_unlocked_enable_lpm(struct usb_device *udev); | ||
600 | |||
545 | static inline void usb_mark_last_busy(struct usb_device *udev) | 601 | static inline void usb_mark_last_busy(struct usb_device *udev) |
546 | { | 602 | { |
547 | pm_runtime_mark_last_busy(&udev->dev); | 603 | pm_runtime_mark_last_busy(&udev->dev); |
@@ -842,6 +898,9 @@ struct usbdrv_wrap { | |||
842 | * for interfaces bound to this driver. | 898 | * for interfaces bound to this driver. |
843 | * @soft_unbind: if set to 1, the USB core will not kill URBs and disable | 899 | * @soft_unbind: if set to 1, the USB core will not kill URBs and disable |
844 | * endpoints before calling the driver's disconnect method. | 900 | * endpoints before calling the driver's disconnect method. |
901 | * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs | ||
902 | * to initiate lower power link state transitions when an idle timeout | ||
903 | * occurs. Device-initiated USB 3.0 link PM will still be allowed. | ||
845 | * | 904 | * |
846 | * USB interface drivers must provide a name, probe() and disconnect() | 905 | * USB interface drivers must provide a name, probe() and disconnect() |
847 | * methods, and an id_table. Other driver fields are optional. | 906 | * methods, and an id_table. Other driver fields are optional. |
@@ -882,6 +941,7 @@ struct usb_driver { | |||
882 | struct usbdrv_wrap drvwrap; | 941 | struct usbdrv_wrap drvwrap; |
883 | unsigned int no_dynamic_id:1; | 942 | unsigned int no_dynamic_id:1; |
884 | unsigned int supports_autosuspend:1; | 943 | unsigned int supports_autosuspend:1; |
944 | unsigned int disable_hub_initiated_lpm:1; | ||
885 | unsigned int soft_unbind:1; | 945 | unsigned int soft_unbind:1; |
886 | }; | 946 | }; |
887 | #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) | 947 | #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 @@ | |||
76 | #define USB_PORT_FEAT_C_BH_PORT_RESET 29 | 76 | #define USB_PORT_FEAT_C_BH_PORT_RESET 29 |
77 | #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 | 77 | #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 |
78 | 78 | ||
79 | #define USB_PORT_LPM_TIMEOUT(p) (((p) & 0xff) << 8) | ||
80 | |||
79 | /* USB 3.0 hub remote wake mask bits, see table 10-14 */ | 81 | /* USB 3.0 hub remote wake mask bits, see table 10-14 */ |
80 | #define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8) | 82 | #define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8) |
81 | #define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9) | 83 | #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 { | |||
392 | #define USB_ENDPOINT_XFER_INT 3 | 392 | #define USB_ENDPOINT_XFER_INT 3 |
393 | #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 | 393 | #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 |
394 | 394 | ||
395 | /* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ | ||
396 | #define USB_ENDPOINT_INTRTYPE 0x30 | ||
397 | #define USB_ENDPOINT_INTR_PERIODIC (0 << 4) | ||
398 | #define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4) | ||
399 | |||
395 | #define USB_ENDPOINT_SYNCTYPE 0x0c | 400 | #define USB_ENDPOINT_SYNCTYPE 0x0c |
396 | #define USB_ENDPOINT_SYNC_NONE (0 << 2) | 401 | #define USB_ENDPOINT_SYNC_NONE (0 << 2) |
397 | #define USB_ENDPOINT_SYNC_ASYNC (1 << 2) | 402 | #define USB_ENDPOINT_SYNC_ASYNC (1 << 2) |
@@ -594,6 +599,12 @@ static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) | |||
594 | return __le16_to_cpu(epd->wMaxPacketSize); | 599 | return __le16_to_cpu(epd->wMaxPacketSize); |
595 | } | 600 | } |
596 | 601 | ||
602 | static inline int usb_endpoint_interrupt_type( | ||
603 | const struct usb_endpoint_descriptor *epd) | ||
604 | { | ||
605 | return epd->bmAttributes & USB_ENDPOINT_INTRTYPE; | ||
606 | } | ||
607 | |||
597 | /*-------------------------------------------------------------------------*/ | 608 | /*-------------------------------------------------------------------------*/ |
598 | 609 | ||
599 | /* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ | 610 | /* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ |
@@ -935,6 +946,51 @@ enum usb_device_state { | |||
935 | */ | 946 | */ |
936 | }; | 947 | }; |
937 | 948 | ||
949 | enum usb3_link_state { | ||
950 | USB3_LPM_U0 = 0, | ||
951 | USB3_LPM_U1, | ||
952 | USB3_LPM_U2, | ||
953 | USB3_LPM_U3 | ||
954 | }; | ||
955 | |||
956 | /* | ||
957 | * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1. | ||
958 | * 0xff means the parent hub will accept transitions to U1, but will not | ||
959 | * initiate a transition. | ||
960 | * | ||
961 | * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to | ||
962 | * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved | ||
963 | * values. | ||
964 | * | ||
965 | * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2. | ||
966 | * 0xff means the parent hub will accept transitions to U2, but will not | ||
967 | * initiate a transition. | ||
968 | * | ||
969 | * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to | ||
970 | * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2 | ||
971 | * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means | ||
972 | * 65.024ms. | ||
973 | */ | ||
974 | #define USB3_LPM_DISABLED 0x0 | ||
975 | #define USB3_LPM_U1_MAX_TIMEOUT 0x7F | ||
976 | #define USB3_LPM_U2_MAX_TIMEOUT 0xFE | ||
977 | #define USB3_LPM_DEVICE_INITIATED 0xFF | ||
978 | |||
979 | struct usb_set_sel_req { | ||
980 | __u8 u1_sel; | ||
981 | __u8 u1_pel; | ||
982 | __le16 u2_sel; | ||
983 | __le16 u2_pel; | ||
984 | } __attribute__ ((packed)); | ||
985 | |||
986 | /* | ||
987 | * The Set System Exit Latency control transfer provides one byte each for | ||
988 | * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each | ||
989 | * are two bytes long. | ||
990 | */ | ||
991 | #define USB3_LPM_MAX_U1_SEL_PEL 0xFF | ||
992 | #define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF | ||
993 | |||
938 | /*-------------------------------------------------------------------------*/ | 994 | /*-------------------------------------------------------------------------*/ |
939 | 995 | ||
940 | /* | 996 | /* |
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 { | |||
344 | */ | 344 | */ |
345 | int (*update_device)(struct usb_hcd *, struct usb_device *); | 345 | int (*update_device)(struct usb_hcd *, struct usb_device *); |
346 | int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int); | 346 | int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int); |
347 | /* USB 3.0 Link Power Management */ | ||
348 | /* Returns the USB3 hub-encoded value for the U1/U2 timeout. */ | ||
349 | int (*enable_usb3_lpm_timeout)(struct usb_hcd *, | ||
350 | struct usb_device *, enum usb3_link_state state); | ||
351 | /* The xHCI host controller can still fail the command to | ||
352 | * disable the LPM timeouts, so this can return an error code. | ||
353 | */ | ||
354 | int (*disable_usb3_lpm_timeout)(struct usb_hcd *, | ||
355 | struct usb_device *, enum usb3_link_state state); | ||
347 | }; | 356 | }; |
348 | 357 | ||
349 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); | 358 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); |