Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xhci: move usb2 get port status link resume handling to its own function

Refactoring, no functional changes.

But worth mentioning that checking for port link resume state is now behind
a additional port power check.

This is fine as ports can't be in resume state if port power bit is not
set.

xhci spec section 4.19.1.1.6 figure 34 shows that port power bit must be
set for all 'Enable' substates, including U0,U1,U2,U3 (suspended), Resume,
and RExit states.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
e67ebf1b a231ec41

+104 -84
+104 -84
drivers/usb/host/xhci-hub.c
··· 795 795 } 796 796 } 797 797 798 + static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, 799 + u32 *status, u32 portsc, 800 + unsigned long flags) 801 + { 802 + struct xhci_bus_state *bus_state; 803 + struct xhci_hcd *xhci; 804 + struct usb_hcd *hcd; 805 + int slot_id; 806 + u32 wIndex; 807 + 808 + hcd = port->rhub->hcd; 809 + bus_state = &port->rhub->bus_state; 810 + xhci = hcd_to_xhci(hcd); 811 + wIndex = port->hcd_portnum; 812 + 813 + if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) { 814 + *status = 0xffffffff; 815 + return -EINVAL; 816 + } 817 + /* did port event handler already start resume timing? */ 818 + if (!bus_state->resume_done[wIndex]) { 819 + /* If not, maybe we are in a host initated resume? */ 820 + if (test_bit(wIndex, &bus_state->resuming_ports)) { 821 + /* Host initated resume doesn't time the resume 822 + * signalling using resume_done[]. 823 + * It manually sets RESUME state, sleeps 20ms 824 + * and sets U0 state. This should probably be 825 + * changed, but not right now. 826 + */ 827 + } else { 828 + /* port resume was discovered now and here, 829 + * start resume timing 830 + */ 831 + unsigned long timeout = jiffies + 832 + msecs_to_jiffies(USB_RESUME_TIMEOUT); 833 + 834 + set_bit(wIndex, &bus_state->resuming_ports); 835 + bus_state->resume_done[wIndex] = timeout; 836 + mod_timer(&hcd->rh_timer, timeout); 837 + usb_hcd_start_port_resume(&hcd->self, wIndex); 838 + } 839 + /* Has resume been signalled for USB_RESUME_TIME yet? */ 840 + } else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) { 841 + int time_left; 842 + 843 + xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); 844 + bus_state->resume_done[wIndex] = 0; 845 + clear_bit(wIndex, &bus_state->resuming_ports); 846 + 847 + set_bit(wIndex, &bus_state->rexit_ports); 848 + 849 + xhci_test_and_clear_bit(xhci, port, PORT_PLC); 850 + xhci_set_link_state(xhci, port, XDEV_U0); 851 + 852 + spin_unlock_irqrestore(&xhci->lock, flags); 853 + time_left = wait_for_completion_timeout( 854 + &bus_state->rexit_done[wIndex], 855 + msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS)); 856 + spin_lock_irqsave(&xhci->lock, flags); 857 + 858 + if (time_left) { 859 + slot_id = xhci_find_slot_id_by_port(hcd, xhci, 860 + wIndex + 1); 861 + if (!slot_id) { 862 + xhci_dbg(xhci, "slot_id is zero\n"); 863 + *status = 0xffffffff; 864 + return -ENODEV; 865 + } 866 + xhci_ring_device(xhci, slot_id); 867 + } else { 868 + int port_status = readl(port->addr); 869 + 870 + xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n", 871 + XHCI_MAX_REXIT_TIMEOUT_MS, 872 + port_status); 873 + *status |= USB_PORT_STAT_SUSPEND; 874 + clear_bit(wIndex, &bus_state->rexit_ports); 875 + } 876 + 877 + usb_hcd_end_port_resume(&hcd->self, wIndex); 878 + bus_state->port_c_suspend |= 1 << wIndex; 879 + bus_state->suspended_ports &= ~(1 << wIndex); 880 + } else { 881 + /* 882 + * The resume has been signaling for less than 883 + * USB_RESUME_TIME. Report the port status as SUSPEND, 884 + * let the usbcore check port status again and clear 885 + * resume signaling later. 886 + */ 887 + *status |= USB_PORT_STAT_SUSPEND; 888 + } 889 + return 0; 890 + } 891 + 798 892 static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) 799 893 { 800 894 u32 ext_stat = 0; ··· 947 853 } 948 854 949 855 static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, 950 - u32 portsc) 856 + u32 portsc, unsigned long flags) 951 857 { 952 858 struct xhci_bus_state *bus_state; 953 859 u32 link_state; 954 860 u32 portnum; 861 + int ret; 955 862 956 863 bus_state = &port->rhub->bus_state; 957 864 link_state = portsc & PORT_PLS_MASK; ··· 975 880 bus_state->port_c_suspend |= 1 << portnum; 976 881 } 977 882 } 883 + if (link_state == XDEV_RESUME) { 884 + ret = xhci_handle_usb2_port_link_resume(port, status, 885 + portsc, flags); 886 + if (ret) 887 + return; 888 + } 978 889 } 979 890 } 980 891 ··· 1001 900 __releases(&xhci->lock) 1002 901 __acquires(&xhci->lock) 1003 902 { 1004 - struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1005 903 u32 status = 0; 1006 - int slot_id; 1007 904 struct xhci_hub *rhub; 1008 905 struct xhci_port *port; 1009 906 ··· 1034 935 if (hcd->speed >= HCD_USB3) 1035 936 xhci_get_usb3_port_status(port, &status, raw_port_status); 1036 937 else 1037 - xhci_get_usb2_port_status(port, &status, raw_port_status); 1038 - 1039 - if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && 1040 - !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) { 1041 - if ((raw_port_status & PORT_RESET) || 1042 - !(raw_port_status & PORT_PE)) 1043 - return 0xffffffff; 1044 - /* did port event handler already start resume timing? */ 1045 - if (!bus_state->resume_done[wIndex]) { 1046 - /* If not, maybe we are in a host initated resume? */ 1047 - if (test_bit(wIndex, &bus_state->resuming_ports)) { 1048 - /* Host initated resume doesn't time the resume 1049 - * signalling using resume_done[]. 1050 - * It manually sets RESUME state, sleeps 20ms 1051 - * and sets U0 state. This should probably be 1052 - * changed, but not right now. 1053 - */ 1054 - } else { 1055 - /* port resume was discovered now and here, 1056 - * start resume timing 1057 - */ 1058 - unsigned long timeout = jiffies + 1059 - msecs_to_jiffies(USB_RESUME_TIMEOUT); 1060 - 1061 - set_bit(wIndex, &bus_state->resuming_ports); 1062 - bus_state->resume_done[wIndex] = timeout; 1063 - mod_timer(&hcd->rh_timer, timeout); 1064 - usb_hcd_start_port_resume(&hcd->self, wIndex); 1065 - } 1066 - /* Has resume been signalled for USB_RESUME_TIME yet? */ 1067 - } else if (time_after_eq(jiffies, 1068 - bus_state->resume_done[wIndex])) { 1069 - int time_left; 1070 - 1071 - xhci_dbg(xhci, "Resume USB2 port %d\n", 1072 - wIndex + 1); 1073 - bus_state->resume_done[wIndex] = 0; 1074 - clear_bit(wIndex, &bus_state->resuming_ports); 1075 - 1076 - set_bit(wIndex, &bus_state->rexit_ports); 1077 - 1078 - xhci_test_and_clear_bit(xhci, port, PORT_PLC); 1079 - xhci_set_link_state(xhci, port, XDEV_U0); 1080 - 1081 - spin_unlock_irqrestore(&xhci->lock, flags); 1082 - time_left = wait_for_completion_timeout( 1083 - &bus_state->rexit_done[wIndex], 1084 - msecs_to_jiffies( 1085 - XHCI_MAX_REXIT_TIMEOUT_MS)); 1086 - spin_lock_irqsave(&xhci->lock, flags); 1087 - 1088 - if (time_left) { 1089 - slot_id = xhci_find_slot_id_by_port(hcd, 1090 - xhci, wIndex + 1); 1091 - if (!slot_id) { 1092 - xhci_dbg(xhci, "slot_id is zero\n"); 1093 - return 0xffffffff; 1094 - } 1095 - xhci_ring_device(xhci, slot_id); 1096 - } else { 1097 - int port_status = readl(port->addr); 1098 - xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", 1099 - XHCI_MAX_REXIT_TIMEOUT_MS, 1100 - port_status); 1101 - status |= USB_PORT_STAT_SUSPEND; 1102 - clear_bit(wIndex, &bus_state->rexit_ports); 1103 - } 1104 - 1105 - usb_hcd_end_port_resume(&hcd->self, wIndex); 1106 - bus_state->port_c_suspend |= 1 << wIndex; 1107 - bus_state->suspended_ports &= ~(1 << wIndex); 1108 - } else { 1109 - /* 1110 - * The resume has been signaling for less than 1111 - * USB_RESUME_TIME. Report the port status as SUSPEND, 1112 - * let the usbcore check port status again and clear 1113 - * resume signaling later. 1114 - */ 1115 - status |= USB_PORT_STAT_SUSPEND; 1116 - } 1117 - } 938 + xhci_get_usb2_port_status(port, &status, raw_port_status, 939 + flags); 1118 940 /* 1119 941 * Clear stale usb2 resume signalling variables in case port changed 1120 942 * state during resume signalling. For example on error