Changeset View
Standalone View
/usr/src/sys/dev/usb/usb_hub.c
Context not available. | |||||
udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); | udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); | ||||
if (err != USB_ERR_NORMAL_COMPLETION) | if (err != USB_ERR_NORMAL_COMPLETION) | ||||
retval = err; | retval = err; | ||||
/* Turn on hub port power if current get normalized. */ | |||||
DPRINTF("Turn on power on port %d.\n", portno); | |||||
err = usbd_req_set_port_feature( | |||||
hselasky: FreeBSD Style: 4-space indent when you wrap long lines
The pause should be after… | |||||
Done Inline ActionsNoted on the 4-space indent, thanks! Re-organizing the code on putting the pause after UHF_PORT_POWER will not turn-on my PL2303 device unless I unplug it and then execute the "usbconfig reset" command then plug it back again. This is the experience. archimedes.gaviola_gmail.com: Noted on the 4-space indent, thanks!
Re-organizing the code on putting the pause after… | |||||
Done Inline Actions
Okay, so to understand better the behavior with pause code placed after UHF_PORT_POWER I added temporary checkpoints to track the flow of the wPortChange value. It turns out that wPortChange missed or didn't transition from UPS_C_OVERCURRENT_INDICATOR (0x0008) to UPS_C_CONNECT_STATUS (0x0001) when hitting the pause code to 300ms (lines 1060-1064) which leads to fallback to overcurrent condition and then shut-off its ports power. Sharing the temporarily revise code for reference. 1038 err = uhub_read_port_status(sc, portno); 1039 if (err != USB_ERR_NORMAL_COMPLETION) 1040 retval = err; 1041 1042 DPRINTF("Checkpoint-#1 wPortChange value is %u.\n", sc->sc_st.port_change); 1043 if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) { 1044 DPRINTF("Checkpoint-#2 wPortChange value is %u.\n", sc->sc_st.port_change); 1045 DPRINTF("Overcurrent on port %u.\n", portno); 1046 err = usbd_req_clear_port_feature( 1047 udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); 1048 if (err != USB_ERR_NORMAL_COMPLETION) 1049 retval = err; 1050 1051 /* Turn on hub port power if current get normalized. */ 1052 DPRINTF("Checkpoint-#3 wPortChange value is %u.\n", sc->sc_st.port_change); 1053 DPRINTF("Turn on power on port %d.\n", portno); 1054 err = usbd_req_set_port_feature( 1055 udev, NULL, portno, UHF_PORT_POWER); 1056 if (err != USB_ERR_NORMAL_COMPLETION) 1057 retval = err; 1058 1059 /* Wait for power to come back on. */ 1060 DPRINTF("Checkpoint-#4 wPortChange value is %u.\n", sc->sc_st.port_change); 1061 DPRINTF("USB_MS_TO_TICKS(usb_port_powerup_delay) for 300 ms."); 1062 usb_pause_mtx(NULL, 1063 USB_MS_TO_TICKS(usb_port_powerup_delay)); 1064 DPRINTF("Checkpoint-#5 wPortChange value is %u.\n", sc->sc_st.port_change); 1065 1066 /* Re-validate if overcurrent still exists. */ 1067 DPRINTF("Checkpoint-#6 wPortChange value is %u.\n", sc->sc_st.port_change); 1068 err = uhub_read_port_status(sc, portno); 1069 if (err != USB_ERR_NORMAL_COMPLETION) 1070 retval = err; 1071 DPRINTF("Checkpoint-#7 wPortChange value is %u.\n", sc->sc_st.port_change); 1072 if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) { 1073 DPRINTF("Checkpoint-#8 wPortChnage value is %u.\n", sc->sc_st.port_change); 1074 DPRINTF("Overcurrent condition on port %u.\n", portno); 1075 err = usbd_req_clear_port_feature( 1076 udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); 1077 if (err != USB_ERR_NORMAL_COMPLETION) 1078 retval = err; 1079 DPRINTF("Checkpoint-#9 wPortChange value is %u.\n", sc->sc_st.port_change); 1080 } 1081 DPRINTF("Checkpoint-#10 wPortChange value is %u.\n", sc->sc_st.port_change); 1082 } And here's the logs. uhub_intr_callback: archimedes.gaviola_gmail.com: > Noted on the 4-space indent, thanks!
>
> Re-organizing the code on putting the pause after… | |||||
Done Inline ActionsHere's also the behavior when my PL2303 device is unplug and then perform "usbconfig reset" and then plug back PL2303 device again. In the captured logs, checkpoint #7 is already showing the transitioned value of wPortChange to 1 from 8. This also traverses the pause code 300ms. uhub_intr_callback: archimedes.gaviola_gmail.com: Here's also the behavior when my PL2303 device is unplug and then perform "usbconfig reset" and… | |||||
udev, NULL, portno, UHF_PORT_POWER); | |||||
if (err != USB_ERR_NORMAL_COMPLETION) | |||||
retval = err; | |||||
/* Re-validate if overcurrent still exists. */ | |||||
Not Done Inline ActionsIs there some kind of fail-safe mechanism here? How many times can we re-turn on power again? Forever? hselasky: Is there some kind of fail-safe mechanism here?
How many times can we re-turn on power again? | |||||
Done Inline ActionsYes, the fail-safe mechanism are the lines covering from 1060-1070 on re-validating overcurrent if it still exists. The uhub_read_port_status(sc, portno) will always notify if the existence of the UPS_C_OVERCURRENT_INDICATOR with 0x0008 value. If UPS_C_OVERCURRENT_INDICATOR still exists then it will execute usbd_req_clear_port_feature() function to shut-off the ports again but once it's non-existing as per validation in the if-statement (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) then it will exit. As per re-testing observation with verbose generated logs (hw.usb.uhub.debug=17) re-turn on power happened only once in port-by-port basis. It's not forever as you can see in the logs below for RPi 3B and 4B. With RPi 3B (power is ganged on port 2 so all the ports are activated once up), With RPi 4B, archimedes.gaviola_gmail.com: Yes, the fail-safe mechanism are the lines covering from 1060-1070 on re-validating overcurrent… | |||||
err = uhub_read_port_status(sc, portno); | |||||
if (err != USB_ERR_NORMAL_COMPLETION) | |||||
retval = err; | |||||
if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) { | |||||
DPRINTF("Overcurrent condition on port %u.\n", portno); | |||||
err = usbd_req_clear_port_feature( | |||||
udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); | |||||
if (err != USB_ERR_NORMAL_COMPLETION) | |||||
retval = err; | |||||
} | |||||
} | } | ||||
if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) { | if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) { | ||||
/* | /* | ||||
Context not available. |
FreeBSD Style: 4-space indent when you wrap long lines
The pause should be after UHF_PORT_POWER .