@@ -103,6 +103,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
103
103
104
104
static void hub_release (struct kref * kref );
105
105
static int usb_reset_and_verify_device (struct usb_device * udev );
106
+ static void hub_usb3_port_prepare_disable (struct usb_hub * hub ,
107
+ struct usb_port * port_dev );
106
108
107
109
static inline char * portspeed (struct usb_hub * hub , int portstatus )
108
110
{
@@ -901,82 +903,28 @@ static int hub_set_port_link_state(struct usb_hub *hub, int port1,
901
903
}
902
904
903
905
/*
904
- * If USB 3.0 ports are placed into the Disabled state, they will no longer
905
- * detect any device connects or disconnects. This is generally not what the
906
- * USB core wants, since it expects a disabled port to produce a port status
907
- * change event when a new device connects.
908
- *
909
- * Instead, set the link state to Disabled, wait for the link to settle into
910
- * that state, clear any change bits, and then put the port into the RxDetect
911
- * state.
906
+ * USB-3 does not have a similar link state as USB-2 that will avoid negotiating
907
+ * a connection with a plugged-in cable but will signal the host when the cable
908
+ * is unplugged. Disable remote wake and set link state to U3 for USB-3 devices
912
909
*/
913
- static int hub_usb3_port_disable (struct usb_hub * hub , int port1 )
914
- {
915
- int ret ;
916
- int total_time ;
917
- u16 portchange , portstatus ;
918
-
919
- if (!hub_is_superspeed (hub -> hdev ))
920
- return - EINVAL ;
921
-
922
- ret = hub_port_status (hub , port1 , & portstatus , & portchange );
923
- if (ret < 0 )
924
- return ret ;
925
-
926
- /*
927
- * USB controller Advanced Micro Devices, Inc. [AMD] FCH USB XHCI
928
- * Controller [1022:7814] will have spurious result making the following
929
- * usb 3.0 device hotplugging route to the 2.0 root hub and recognized
930
- * as high-speed device if we set the usb 3.0 port link state to
931
- * Disabled. Since it's already in USB_SS_PORT_LS_RX_DETECT state, we
932
- * check the state here to avoid the bug.
933
- */
934
- if ((portstatus & USB_PORT_STAT_LINK_STATE ) ==
935
- USB_SS_PORT_LS_RX_DETECT ) {
936
- dev_dbg (& hub -> ports [port1 - 1 ]-> dev ,
937
- "Not disabling port; link state is RxDetect\n" );
938
- return ret ;
939
- }
940
-
941
- ret = hub_set_port_link_state (hub , port1 , USB_SS_PORT_LS_SS_DISABLED );
942
- if (ret )
943
- return ret ;
944
-
945
- /* Wait for the link to enter the disabled state. */
946
- for (total_time = 0 ; ; total_time += HUB_DEBOUNCE_STEP ) {
947
- ret = hub_port_status (hub , port1 , & portstatus , & portchange );
948
- if (ret < 0 )
949
- return ret ;
950
-
951
- if ((portstatus & USB_PORT_STAT_LINK_STATE ) ==
952
- USB_SS_PORT_LS_SS_DISABLED )
953
- break ;
954
- if (total_time >= HUB_DEBOUNCE_TIMEOUT )
955
- break ;
956
- msleep (HUB_DEBOUNCE_STEP );
957
- }
958
- if (total_time >= HUB_DEBOUNCE_TIMEOUT )
959
- dev_warn (& hub -> ports [port1 - 1 ]-> dev ,
960
- "Could not disable after %d ms\n" , total_time );
961
-
962
- return hub_set_port_link_state (hub , port1 , USB_SS_PORT_LS_RX_DETECT );
963
- }
964
-
965
910
static int hub_port_disable (struct usb_hub * hub , int port1 , int set_state )
966
911
{
967
912
struct usb_port * port_dev = hub -> ports [port1 - 1 ];
968
913
struct usb_device * hdev = hub -> hdev ;
969
914
int ret = 0 ;
970
915
971
- if (port_dev -> child && set_state )
972
- usb_set_device_state (port_dev -> child , USB_STATE_NOTATTACHED );
973
916
if (!hub -> error ) {
974
- if (hub_is_superspeed (hub -> hdev ))
975
- ret = hub_usb3_port_disable (hub , port1 );
976
- else
917
+ if (hub_is_superspeed (hub -> hdev )) {
918
+ hub_usb3_port_prepare_disable (hub , port_dev );
919
+ ret = hub_set_port_link_state (hub , port_dev -> portnum ,
920
+ USB_SS_PORT_LS_U3 );
921
+ } else {
977
922
ret = usb_clear_port_feature (hdev , port1 ,
978
923
USB_PORT_FEAT_ENABLE );
924
+ }
979
925
}
926
+ if (port_dev -> child && set_state )
927
+ usb_set_device_state (port_dev -> child , USB_STATE_NOTATTACHED );
980
928
if (ret && ret != - ENODEV )
981
929
dev_err (& port_dev -> dev , "cannot disable (err = %d)\n" , ret );
982
930
return ret ;
@@ -4142,13 +4090,36 @@ void usb_unlocked_enable_lpm(struct usb_device *udev)
4142
4090
}
4143
4091
EXPORT_SYMBOL_GPL (usb_unlocked_enable_lpm );
4144
4092
4093
+ /* usb3 devices use U3 for disabled, make sure remote wakeup is disabled */
4094
+ static void hub_usb3_port_prepare_disable (struct usb_hub * hub ,
4095
+ struct usb_port * port_dev )
4096
+ {
4097
+ struct usb_device * udev = port_dev -> child ;
4098
+ int ret ;
4099
+
4100
+ if (udev && udev -> port_is_suspended && udev -> do_remote_wakeup ) {
4101
+ ret = hub_set_port_link_state (hub , port_dev -> portnum ,
4102
+ USB_SS_PORT_LS_U0 );
4103
+ if (!ret ) {
4104
+ msleep (USB_RESUME_TIMEOUT );
4105
+ ret = usb_disable_remote_wakeup (udev );
4106
+ }
4107
+ if (ret )
4108
+ dev_warn (& udev -> dev ,
4109
+ "Port disable: can't disable remote wake\n" );
4110
+ udev -> do_remote_wakeup = 0 ;
4111
+ }
4112
+ }
4145
4113
4146
4114
#else /* CONFIG_PM */
4147
4115
4148
4116
#define hub_suspend NULL
4149
4117
#define hub_resume NULL
4150
4118
#define hub_reset_resume NULL
4151
4119
4120
+ static inline void hub_usb3_port_prepare_disable (struct usb_hub * hub ,
4121
+ struct usb_port * port_dev ) { }
4122
+
4152
4123
int usb_disable_lpm (struct usb_device * udev )
4153
4124
{
4154
4125
return 0 ;
0 commit comments