[PATCH v2] usb: port: add delay after usb_hub_set_port_power()

Xu Yang posted 1 patch 1 month, 1 week ago
There is a newer version of this series
drivers/usb/core/port.c | 1 +
1 file changed, 1 insertion(+)
[PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Xu Yang 1 month, 1 week ago
When a port is disabled, an attached device will be disconnected.  This
causes a port-status-change event, which will race with hub autosuspend
(if the disabled port was the only connected port on its hub), causing
an immediate resume and a second autosuspend.  Both of these can be
avoided by adding a short delay after the call to
usb_hub_set_port_power().

Below log shows what is happening:

$ echo 1 > usb1-port1/disable
[   37.958239] usb 1-1: USB disconnect, device number 2
[   37.964101] usb 1-1: unregistering device
[   37.970070] hub 1-0:1.0: hub_suspend
[   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
[   37.974412] usb usb1: bus auto-suspend, wakeup 1
[   37.988175] usb usb1: suspend raced with wakeup event         <---
[   37.993947] usb usb1: usb auto-resume
[   37.998401] hub 1-0:1.0: hub_resume
[   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
[   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
[   38.118645] hub 1-0:1.0: hub_suspend
[   38.122963] usb usb1: bus auto-suspend, wakeup 1
[   38.200368] usb usb1: usb wakeup-resume
[   38.204982] usb usb1: usb auto-resume
[   38.209376] hub 1-0:1.0: hub_resume
[   38.213676] usb usb1-port1: status 0101 change 0001
[   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
[   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
[   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc

Then, port change bit will be fixed to the final state and
usb_clear_port_feature() can correctly clear it after this period. This
will also avoid usb runtime suspend routine to run because
usb_autopm_put_interface() not run yet.

Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
Cc: stable@kernel.org
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

---
Changes in v2:
 - improve commit message
---
 drivers/usb/core/port.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 44e38f922bc5..027a5f21c5f7 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -141,6 +141,7 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
 		usb_disconnect(&port_dev->child);
 
 	rc = usb_hub_set_port_power(hdev, hub, port1, !disabled);
+	msleep(2 * hub_power_on_good_delay(hub));
 
 	if (disabled) {
 		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
-- 
2.34.1
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Fabio Estevam 1 month, 1 week ago
Hi Xu Yang,

On Tue, Feb 24, 2026 at 12:17 AM Xu Yang <xu.yang_2@nxp.com> wrote:
>
> When a port is disabled, an attached device will be disconnected.  This
> causes a port-status-change event, which will race with hub autosuspend
> (if the disabled port was the only connected port on its hub), causing
> an immediate resume and a second autosuspend.  Both of these can be
> avoided by adding a short delay after the call to
> usb_hub_set_port_power().
>
> Below log shows what is happening:
>
> $ echo 1 > usb1-port1/disable
> [   37.958239] usb 1-1: USB disconnect, device number 2
> [   37.964101] usb 1-1: unregistering device
> [   37.970070] hub 1-0:1.0: hub_suspend
> [   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
> [   37.974412] usb usb1: bus auto-suspend, wakeup 1
> [   37.988175] usb usb1: suspend raced with wakeup event         <---
> [   37.993947] usb usb1: usb auto-resume
> [   37.998401] hub 1-0:1.0: hub_resume
> [   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
> [   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
> [   38.118645] hub 1-0:1.0: hub_suspend
> [   38.122963] usb usb1: bus auto-suspend, wakeup 1
> [   38.200368] usb usb1: usb wakeup-resume
> [   38.204982] usb usb1: usb auto-resume
> [   38.209376] hub 1-0:1.0: hub_resume
> [   38.213676] usb usb1-port1: status 0101 change 0001
> [   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
> [   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
> [   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc
>
> Then, port change bit will be fixed to the final state and
> usb_clear_port_feature() can correctly clear it after this period. This
> will also avoid usb runtime suspend routine to run because
> usb_autopm_put_interface() not run yet.
>
> Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
> Cc: stable@kernel.org
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

On an imx6x-sdb board, I still get the inconsistency below even after
applying your patch:

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
[   20.656414] usb 1-1: USB disconnect, device number 2

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
[   28.263516] usb 1-1: new high-speed USB device number 3 using ci_hdrc
[   28.466813] usb 1-1: New USB device found, idVendor=0457,
idProduct=0151, bcdDevice= 1.00
[   28.466949] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   28.467039] usb 1-1: Product: USB Mass Storage Device
[   28.467086] usb 1-1: Manufacturer: USBest Technology
[   28.467126] usb 1-1: SerialNumber: 000000000003FF
[   28.501826] usb-storage 1-1:1.0: USB Mass Storage device detected
[   28.510452] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
[   28.517597] scsi host0: usb-storage 1-1:1.0
[   28.524066] usb 1-1: USB disconnect, device number 3

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# [   35.323593] usb 1-1: new high-speed USB device number 4 using ci_hdrc
[   35.526916] usb 1-1: New USB device found, idVendor=0457,
idProduct=0151, bcdDevice= 1.00
[   35.527054] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   35.527150] usb 1-1: Product: USB Mass Storage Device
[   35.527198] usb 1-1: Manufacturer: USBest Technology
[   35.527239] usb 1-1: SerialNumber: 000000000003FF
[   35.562024] usb-storage 1-1:1.0: USB Mass Storage device detected
[   35.570430] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
[   35.577562] scsi host0: usb-storage 1-1:1.0
[   36.645798] scsi 0:0:0:0: Direct-Access     Ut163
USB2FlashStorage 0.00 PQ: 0 ANSI: 2

# [   36.682705] sd 0:0:0:0: [sda] 248000 512-byte logical blocks:
(127 MB/121 MiB)
[   36.691645] sd 0:0:0:0: [sda] Write Protect is off
[   36.697915] sd 0:0:0:0: [sda] Asking for cache data failed
[   36.697981] sd 0:0:0:0: [sda] Assuming drive cache: write through
[   36.735520]  sda: sda1
[   36.739376] sd 0:0:0:0: [sda] Attached SCSI removable disk

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
[   39.423511] usb 1-1: USB disconnect, device number 4

Please try disabling the port several times in a row.
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Xu Yang 1 month, 1 week ago
Hi Fabio,

On Tue, Feb 24, 2026 at 09:19:51AM -0300, Fabio Estevam wrote:
> Hi Xu Yang,
> 
> On Tue, Feb 24, 2026 at 12:17 AM Xu Yang <xu.yang_2@nxp.com> wrote:
> >
> > When a port is disabled, an attached device will be disconnected.  This
> > causes a port-status-change event, which will race with hub autosuspend
> > (if the disabled port was the only connected port on its hub), causing
> > an immediate resume and a second autosuspend.  Both of these can be
> > avoided by adding a short delay after the call to
> > usb_hub_set_port_power().
> >
> > Below log shows what is happening:
> >
> > $ echo 1 > usb1-port1/disable
> > [   37.958239] usb 1-1: USB disconnect, device number 2
> > [   37.964101] usb 1-1: unregistering device
> > [   37.970070] hub 1-0:1.0: hub_suspend
> > [   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
> > [   37.974412] usb usb1: bus auto-suspend, wakeup 1
> > [   37.988175] usb usb1: suspend raced with wakeup event         <---
> > [   37.993947] usb usb1: usb auto-resume
> > [   37.998401] hub 1-0:1.0: hub_resume
> > [   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
> > [   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
> > [   38.118645] hub 1-0:1.0: hub_suspend
> > [   38.122963] usb usb1: bus auto-suspend, wakeup 1
> > [   38.200368] usb usb1: usb wakeup-resume
> > [   38.204982] usb usb1: usb auto-resume
> > [   38.209376] hub 1-0:1.0: hub_resume
> > [   38.213676] usb usb1-port1: status 0101 change 0001
> > [   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
> > [   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
> > [   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> >
> > Then, port change bit will be fixed to the final state and
> > usb_clear_port_feature() can correctly clear it after this period. This
> > will also avoid usb runtime suspend routine to run because
> > usb_autopm_put_interface() not run yet.
> >
> > Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
> > Cc: stable@kernel.org
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> 
> On an imx6x-sdb board, I still get the inconsistency below even after
> applying your patch:
> 
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> [   20.656414] usb 1-1: USB disconnect, device number 2
> 
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> [   28.263516] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> [   28.466813] usb 1-1: New USB device found, idVendor=0457,
> idProduct=0151, bcdDevice= 1.00
> [   28.466949] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> [   28.467039] usb 1-1: Product: USB Mass Storage Device
> [   28.467086] usb 1-1: Manufacturer: USBest Technology
> [   28.467126] usb 1-1: SerialNumber: 000000000003FF
> [   28.501826] usb-storage 1-1:1.0: USB Mass Storage device detected
> [   28.510452] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
> [   28.517597] scsi host0: usb-storage 1-1:1.0
> [   28.524066] usb 1-1: USB disconnect, device number 3

It's another different problem.

For ports which VBUS are not controlled by PORTSC.PP (always on VBUS
regulator or Type-C controlled VBUS), they are still powered on after
you disable the ports. This will cause PORTSC.CCS still be set after it.

When usb_autopm_get_interface() gets called, hub_resume will check CCS
bit and check new connection again. So you see new device is reported.

Below patch will be a workaround for the issue when you disable the port
many times:
https://lore.kernel.org/linux-usb/20260223-v6-16-topic-usb-onboard-dev-v5-1-28d3018a8026@pengutronix.de/

However, it will still report new device when you "cat usb1-port1/disable".
To fix the issue completely, I guess the usb core needs some sync with the
port disabled state. 

Thanks,
Xu Yang
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Fabio Estevam 1 month, 1 week ago
Hi Xu Yang,

On Wed, Feb 25, 2026 at 4:47 AM Xu Yang <xu.yang_2@nxp.com> wrote:
>
> Hi Fabio,
>
> On Tue, Feb 24, 2026 at 09:19:51AM -0300, Fabio Estevam wrote:
> > Hi Xu Yang,
> >
> > On Tue, Feb 24, 2026 at 12:17 AM Xu Yang <xu.yang_2@nxp.com> wrote:
> > >
> > > When a port is disabled, an attached device will be disconnected.  This
> > > causes a port-status-change event, which will race with hub autosuspend
> > > (if the disabled port was the only connected port on its hub), causing
> > > an immediate resume and a second autosuspend.  Both of these can be
> > > avoided by adding a short delay after the call to
> > > usb_hub_set_port_power().
> > >
> > > Below log shows what is happening:
> > >
> > > $ echo 1 > usb1-port1/disable
> > > [   37.958239] usb 1-1: USB disconnect, device number 2
> > > [   37.964101] usb 1-1: unregistering device
> > > [   37.970070] hub 1-0:1.0: hub_suspend
> > > [   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
> > > [   37.974412] usb usb1: bus auto-suspend, wakeup 1
> > > [   37.988175] usb usb1: suspend raced with wakeup event         <---
> > > [   37.993947] usb usb1: usb auto-resume
> > > [   37.998401] hub 1-0:1.0: hub_resume
> > > [   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
> > > [   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
> > > [   38.118645] hub 1-0:1.0: hub_suspend
> > > [   38.122963] usb usb1: bus auto-suspend, wakeup 1
> > > [   38.200368] usb usb1: usb wakeup-resume
> > > [   38.204982] usb usb1: usb auto-resume
> > > [   38.209376] hub 1-0:1.0: hub_resume
> > > [   38.213676] usb usb1-port1: status 0101 change 0001
> > > [   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
> > > [   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
> > > [   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > >
> > > Then, port change bit will be fixed to the final state and
> > > usb_clear_port_feature() can correctly clear it after this period. This
> > > will also avoid usb runtime suspend routine to run because
> > > usb_autopm_put_interface() not run yet.
> > >
> > > Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
> > > Cc: stable@kernel.org
> > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >
> > On an imx6x-sdb board, I still get the inconsistency below even after
> > applying your patch:
> >
> > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > [   20.656414] usb 1-1: USB disconnect, device number 2
> >
> > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > [   28.263516] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > [   28.466813] usb 1-1: New USB device found, idVendor=0457,
> > idProduct=0151, bcdDevice= 1.00
> > [   28.466949] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> > [   28.467039] usb 1-1: Product: USB Mass Storage Device
> > [   28.467086] usb 1-1: Manufacturer: USBest Technology
> > [   28.467126] usb 1-1: SerialNumber: 000000000003FF
> > [   28.501826] usb-storage 1-1:1.0: USB Mass Storage device detected
> > [   28.510452] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
> > [   28.517597] scsi host0: usb-storage 1-1:1.0
> > [   28.524066] usb 1-1: USB disconnect, device number 3
>
> It's another different problem.
>
> For ports which VBUS are not controlled by PORTSC.PP (always on VBUS
> regulator or Type-C controlled VBUS), they are still powered on after
> you disable the ports. This will cause PORTSC.CCS still be set after it.
>
> When usb_autopm_get_interface() gets called, hub_resume will check CCS
> bit and check new connection again. So you see new device is reported.
>
> Below patch will be a workaround for the issue when you disable the port
> many times:
> https://lore.kernel.org/linux-usb/20260223-v6-16-topic-usb-onboard-dev-v5-1-28d3018a8026@pengutronix.de/

I applied Marco's patch, and it fixes the inconsistent state that I
reported before on the imx6sx-sdb:

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
[  110.494838] usb 1-1: USB disconnect, device number 3
# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable

Now I want the USB OTG2 VBUS to be turned off.

I understand that the chipidea driver does not turn off VBUS when
vbus-supply is passed, so I tried using the pin as
MX6SX_PAD_GPIO1_IO12__USB_OTG2_PWR:

--- a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
@@ -70,17 +70,6 @@ reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
                enable-active-high;
        };

-       reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
-               compatible = "regulator-fixed";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_usb_otg2>;
-               regulator-name = "usb_otg2_vbus";
-               regulator-min-microvolt = <5000000>;
-               regulator-max-microvolt = <5000000>;
-               gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-       };
-
        reg_psu_5v: regulator-psu-5v {
                compatible = "regulator-fixed";
                regulator-name = "PSU-5V0";
@@ -347,7 +336,8 @@ &usbotg1 {
 };

 &usbotg2 {
-       vbus-supply = <&reg_usb_otg2_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usb_otg2>;
        dr_mode = "host";
        status = "okay";
 };
@@ -636,7 +626,7 @@ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID        0x17059

        pinctrl_usb_otg2: usbot2ggrp {
                fsl,pins = <
-                       MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12       0x10b0
+                       MX6SX_PAD_GPIO1_IO12__USB_OTG2_PWR      0x10b0
                >;
        };

This works in the opposite way:

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# [   48.509650] mxs_phy 20c9000.usbphy: vbus is not valid
[   48.940605] usb 1-1: new high-speed USB device number 3 using ci_hdrc
[   49.144001] usb 1-1: New USB device found, idVendor=0457,
idProduct=0151, bcdDevice= 1.00
[   49.144133] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   49.144225] usb 1-1: Product: USB Mass Storage Device
[   49.144273] usb 1-1: Manufacturer: USBest Technology
[   49.144314] usb 1-1: SerialNumber: 000000000003FF
[   49.179136] usb-storage 1-1:1.0: USB Mass Storage device detected
[   49.188023] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
[   49.195308] scsi host0: usb-storage 1-1:1.0
[   50.252746] scsi 0:0:0:0: Direct-Access     Ut163
USB2FlashStorage 0.00 PQ: 0 ANSI: 2
[   50.291866] sd 0:0:0:0: [sda] 248000 512-byte logical blocks: (127
MB/121 MiB)
[   50.301593] sd 0:0:0:0: [sda] Write Protect is off
[   50.308917] sd 0:0:0:0: [sda] Asking for cache data failed
[   50.309042] sd 0:0:0:0: [sda] Assuming drive cache: write through
[   50.342155]  sda: sda1
[   50.345288] sd 0:0:0:0: [sda] Attached SCSI removable disk

#
#
# echo 0 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
# [   57.161272] usb 1-1: USB disconnect, device number 3

Then I passed the 'power-active-high' property, but it failed:

# echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
[   16.892793] usb 1-1: USB disconnect, device number 2
# [   18.330848] usb usb1-port1: Cannot enable. Maybe the USB cable is bad?
[   19.240797] usb usb1-port1: Cannot enable. Maybe the USB cable is bad?
[   19.248159] usb usb1-port1: attempt power cycle
[   20.520852] usb usb1-port1: Cannot enable. Maybe the USB cable is bad?
[   21.430861] usb usb1-port1: Cannot enable. Maybe the USB cable is bad?
[   21.437883] usb usb1-port1: unable to enumerate USB device

Any ideas on how to properly turn off the OTG2 VBUS?

Thanks
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Xu Yang 1 month, 1 week ago
On Wed, Feb 25, 2026 at 05:13:17PM -0300, Fabio Estevam wrote:
> Hi Xu Yang,
> 
> On Wed, Feb 25, 2026 at 4:47 AM Xu Yang <xu.yang_2@nxp.com> wrote:
> >
> > Hi Fabio,
> >
> > On Tue, Feb 24, 2026 at 09:19:51AM -0300, Fabio Estevam wrote:
> > > Hi Xu Yang,
> > >
> > > On Tue, Feb 24, 2026 at 12:17 AM Xu Yang <xu.yang_2@nxp.com> wrote:
> > > >
> > > > When a port is disabled, an attached device will be disconnected.  This
> > > > causes a port-status-change event, which will race with hub autosuspend
> > > > (if the disabled port was the only connected port on its hub), causing
> > > > an immediate resume and a second autosuspend.  Both of these can be
> > > > avoided by adding a short delay after the call to
> > > > usb_hub_set_port_power().
> > > >
> > > > Below log shows what is happening:
> > > >
> > > > $ echo 1 > usb1-port1/disable
> > > > [   37.958239] usb 1-1: USB disconnect, device number 2
> > > > [   37.964101] usb 1-1: unregistering device
> > > > [   37.970070] hub 1-0:1.0: hub_suspend
> > > > [   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
> > > > [   37.974412] usb usb1: bus auto-suspend, wakeup 1
> > > > [   37.988175] usb usb1: suspend raced with wakeup event         <---
> > > > [   37.993947] usb usb1: usb auto-resume
> > > > [   37.998401] hub 1-0:1.0: hub_resume
> > > > [   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
> > > > [   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
> > > > [   38.118645] hub 1-0:1.0: hub_suspend
> > > > [   38.122963] usb usb1: bus auto-suspend, wakeup 1
> > > > [   38.200368] usb usb1: usb wakeup-resume
> > > > [   38.204982] usb usb1: usb auto-resume
> > > > [   38.209376] hub 1-0:1.0: hub_resume
> > > > [   38.213676] usb usb1-port1: status 0101 change 0001
> > > > [   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
> > > > [   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
> > > > [   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > > >
> > > > Then, port change bit will be fixed to the final state and
> > > > usb_clear_port_feature() can correctly clear it after this period. This
> > > > will also avoid usb runtime suspend routine to run because
> > > > usb_autopm_put_interface() not run yet.
> > > >
> > > > Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
> > > > Cc: stable@kernel.org
> > > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > >
> > > On an imx6x-sdb board, I still get the inconsistency below even after
> > > applying your patch:
> > >
> > > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > > [   20.656414] usb 1-1: USB disconnect, device number 2
> > >
> > > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > > [   28.263516] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > > [   28.466813] usb 1-1: New USB device found, idVendor=0457,
> > > idProduct=0151, bcdDevice= 1.00
> > > [   28.466949] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> > > [   28.467039] usb 1-1: Product: USB Mass Storage Device
> > > [   28.467086] usb 1-1: Manufacturer: USBest Technology
> > > [   28.467126] usb 1-1: SerialNumber: 000000000003FF
> > > [   28.501826] usb-storage 1-1:1.0: USB Mass Storage device detected
> > > [   28.510452] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
> > > [   28.517597] scsi host0: usb-storage 1-1:1.0
> > > [   28.524066] usb 1-1: USB disconnect, device number 3
> >
> > It's another different problem.
> >
> > For ports which VBUS are not controlled by PORTSC.PP (always on VBUS
> > regulator or Type-C controlled VBUS), they are still powered on after
> > you disable the ports. This will cause PORTSC.CCS still be set after it.
> >
> > When usb_autopm_get_interface() gets called, hub_resume will check CCS
> > bit and check new connection again. So you see new device is reported.
> >
> > Below patch will be a workaround for the issue when you disable the port
> > many times:
> > https://lore.kernel.org/linux-usb/20260223-v6-16-topic-usb-onboard-dev-v5-1-28d3018a8026@pengutronix.de/
> 
> I applied Marco's patch, and it fixes the inconsistent state that I
> reported before on the imx6sx-sdb:
> 
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> [  110.494838] usb 1-1: USB disconnect, device number 3
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> 
> Now I want the USB OTG2 VBUS to be turned off.
> 
> I understand that the chipidea driver does not turn off VBUS when
> vbus-supply is passed, so I tried using the pin as
> MX6SX_PAD_GPIO1_IO12__USB_OTG2_PWR:

No. You can't do this because CI_HDRC_TURN_VBUS_EARLY_ON won't take effect
as we talked in previous thread. Then, USB phy will work abnormally.

I recommend to unbind/bind the device for switching VBUS off/on. 

Thanks,
Xu Yang
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Alan Stern 1 month, 1 week ago
On Wed, Feb 25, 2026 at 03:40:15PM +0800, Xu Yang wrote:
> Hi Fabio,
> 
> On Tue, Feb 24, 2026 at 09:19:51AM -0300, Fabio Estevam wrote:
> > Hi Xu Yang,
> > 
> > On Tue, Feb 24, 2026 at 12:17 AM Xu Yang <xu.yang_2@nxp.com> wrote:
> > >
> > > When a port is disabled, an attached device will be disconnected.  This
> > > causes a port-status-change event, which will race with hub autosuspend
> > > (if the disabled port was the only connected port on its hub), causing
> > > an immediate resume and a second autosuspend.  Both of these can be
> > > avoided by adding a short delay after the call to
> > > usb_hub_set_port_power().
> > >
> > > Below log shows what is happening:
> > >
> > > $ echo 1 > usb1-port1/disable
> > > [   37.958239] usb 1-1: USB disconnect, device number 2
> > > [   37.964101] usb 1-1: unregistering device
> > > [   37.970070] hub 1-0:1.0: hub_suspend
> > > [   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
> > > [   37.974412] usb usb1: bus auto-suspend, wakeup 1
> > > [   37.988175] usb usb1: suspend raced with wakeup event         <---
> > > [   37.993947] usb usb1: usb auto-resume
> > > [   37.998401] hub 1-0:1.0: hub_resume
> > > [   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
> > > [   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
> > > [   38.118645] hub 1-0:1.0: hub_suspend
> > > [   38.122963] usb usb1: bus auto-suspend, wakeup 1
> > > [   38.200368] usb usb1: usb wakeup-resume
> > > [   38.204982] usb usb1: usb auto-resume
> > > [   38.209376] hub 1-0:1.0: hub_resume
> > > [   38.213676] usb usb1-port1: status 0101 change 0001
> > > [   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
> > > [   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
> > > [   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > >
> > > Then, port change bit will be fixed to the final state and
> > > usb_clear_port_feature() can correctly clear it after this period. This
> > > will also avoid usb runtime suspend routine to run because
> > > usb_autopm_put_interface() not run yet.
> > >
> > > Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
> > > Cc: stable@kernel.org
> > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > 
> > On an imx6x-sdb board, I still get the inconsistency below even after
> > applying your patch:
> > 
> > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > [   20.656414] usb 1-1: USB disconnect, device number 2
> > 
> > # echo 1 >  /sys/bus/usb/devices/1-0\:1.0/usb1-port1/disable
> > [   28.263516] usb 1-1: new high-speed USB device number 3 using ci_hdrc
> > [   28.466813] usb 1-1: New USB device found, idVendor=0457,
> > idProduct=0151, bcdDevice= 1.00
> > [   28.466949] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> > [   28.467039] usb 1-1: Product: USB Mass Storage Device
> > [   28.467086] usb 1-1: Manufacturer: USBest Technology
> > [   28.467126] usb 1-1: SerialNumber: 000000000003FF
> > [   28.501826] usb-storage 1-1:1.0: USB Mass Storage device detected
> > [   28.510452] usb-storage 1-1:1.0: Quirks match for vid 0457 pid 0151: 80
> > [   28.517597] scsi host0: usb-storage 1-1:1.0
> > [   28.524066] usb 1-1: USB disconnect, device number 3
> 
> It's another different problem.
> 
> For ports which VBUS are not controlled by PORTSC.PP (always on VBUS
> regulator or Type-C controlled VBUS), they are still powered on after
> you disable the ports. This will cause PORTSC.CCS still be set after it.

That is arguably a hardware bug.  According to section 11.5.1.2 of the 
USB-2 spec, when a port is in the powered-off state its transmitters and 
receivers are disabled.  This implies that it is unable to tell whether 
a device is connected, so PORTSC.CCS should be clear.

> When usb_autopm_get_interface() gets called, hub_resume will check CCS
> bit and check new connection again. So you see new device is reported.
> 
> Below patch will be a workaround for the issue when you disable the port
> many times:
> https://lore.kernel.org/linux-usb/20260223-v6-16-topic-usb-onboard-dev-v5-1-28d3018a8026@pengutronix.de/
> 
> However, it will still report new device when you "cat usb1-port1/disable".
> To fix the issue completely, I guess the usb core needs some sync with the
> port disabled state. 

Another patch on top of the one you mentioned should be straigtforward.  
Feel like writing one?  All it has to do is make the hub driver skip 
handling connect-status changes for disabled ports.

Alan Stern
Re: [PATCH v2] usb: port: add delay after usb_hub_set_port_power()
Posted by Xu Yang 1 month, 1 week ago
On Wed, Feb 25, 2026 at 10:17:43AM -0500, Alan Stern wrote:
> > 
> > For ports which VBUS are not controlled by PORTSC.PP (always on VBUS
> > regulator or Type-C controlled VBUS), they are still powered on after
> > you disable the ports. This will cause PORTSC.CCS still be set after it.
> 
> That is arguably a hardware bug.  According to section 11.5.1.2 of the 
> USB-2 spec, when a port is in the powered-off state its transmitters and 
> receivers are disabled.  This implies that it is unable to tell whether 
> a device is connected, so PORTSC.CCS should be clear.

Thanks for the information! I'll check the HW behavior with designer.

> 
> > When usb_autopm_get_interface() gets called, hub_resume will check CCS
> > bit and check new connection again. So you see new device is reported.
> > 
> > Below patch will be a workaround for the issue when you disable the port
> > many times:
> > https://lore.kernel.org/linux-usb/20260223-v6-16-topic-usb-onboard-dev-v5-1-28d3018a8026@pengutronix.de/
> > 
> > However, it will still report new device when you "cat usb1-port1/disable".
> > To fix the issue completely, I guess the usb core needs some sync with the
> > port disabled state. 
> 
> Another patch on top of the one you mentioned should be straigtforward.  
> Feel like writing one?  All it has to do is make the hub driver skip 
> handling connect-status changes for disabled ports.o

That patchset haven't been merged. I might be able to do this sometime in
the future.

I just have a simple test, to skip handling connect-status changes is easy,
but to make it work again (echo 0 > disable) is problematic because
when usb_autopm_get_interface() is executed the disabled flag is still true
(so the hub will still skip handling connect-status changes) and the port
won't generate connect change event given the HW is buggy.

Thanks,
Xu Yang