git: c0ec1e0e60ca - main - apple_bce: fix C_CONNECT_STATUS during port reset

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Sun, 06 Sep 2026 19:48:33 UTC
The branch main has been updated by seuros:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0ec1e0e60caf513e4cfa42b995631f19d376a26

commit c0ec1e0e60caf513e4cfa42b995631f19d376a26
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-09-06 19:16:33 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
CommitDate: 2026-09-06 19:47:44 +0000

    apple_bce: fix C_CONNECT_STATUS during port reset
    
    Only set the port change bit when the corresponding status bit
    actually transitioned, instead of unconditionally flagging
    C_CONNECT_STATUS on every port change event. Also clear any
    flaky C_CONNECT_STATUS that the port change taskqueue may have
    set while the bus lock was dropped during a successful port reset.
    
    Reviewed by:    adrian
    Differential Revision:  https://reviews.freebsd.org/D58875
---
 sys/dev/apple_bce/apple_bce_vhci.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/sys/dev/apple_bce/apple_bce_vhci.c b/sys/dev/apple_bce/apple_bce_vhci.c
index 7056f8e2fb97..56d519e715c1 100644
--- a/sys/dev/apple_bce/apple_bce_vhci.c
+++ b/sys/dev/apple_bce/apple_bce_vhci.c
@@ -1007,8 +1007,12 @@ bce_vhci_port_chg_task(void *arg, int pending __unused)
 
 		USB_BUS_LOCK(&vhci->sc_bus);
 		if (error == 0) {
+			uint16_t changed, old_status;
+
 			port_status = (uint32_t)reply.param2;
 
+			old_status = vhci->sc_port_status[port];
+
 			vhci->sc_port_status[port] = 0;
 			if (vhci->sc_port_power[port])
 				vhci->sc_port_status[port] |=
@@ -1025,8 +1029,24 @@ bce_vhci_port_chg_task(void *arg, int pending __unused)
 			if (port_status & BCE_VHCI_PORT_OVERCURRENT)
 				vhci->sc_port_status[port] |=
 				    UPS_OVERCURRENT_INDICATOR;
+
+			changed = old_status ^ vhci->sc_port_status[port];
+
+			if (changed & UPS_CURRENT_CONNECT_STATUS)
+				vhci->sc_port_change[port] |=
+				    UPS_C_CONNECT_STATUS;
+			if (changed & UPS_PORT_ENABLED)
+				vhci->sc_port_change[port] |=
+				    UPS_C_PORT_ENABLED;
+			if (changed & UPS_SUSPEND)
+				vhci->sc_port_change[port] |=
+				    UPS_C_SUSPEND;
+			if (changed & UPS_OVERCURRENT_INDICATOR)
+				vhci->sc_port_change[port] |=
+				    UPS_C_OVERCURRENT_INDICATOR;
+		} else {
+			vhci->sc_port_change[port] |= UPS_C_CONNECT_STATUS;
 		}
-		vhci->sc_port_change[port] |= UPS_C_CONNECT_STATUS;
 		USB_BUS_UNLOCK(&vhci->sc_bus);
 	}
 
@@ -4107,6 +4127,8 @@ bce_vhci_roothub_exec(struct usb_device *udev,
 					    UPS_HIGH_SPEED;
 					vhci->sc_port_change[index - 1] |=
 					    UPS_C_PORT_RESET;
+					vhci->sc_port_change[index - 1] &=
+					    ~UPS_C_CONNECT_STATUS;
 				} else {
 					device_printf(vhci->sc_dev,
 					    "port %d reset failed: %d\n",