libpayload: Rework connection state detection for OHCI

The connection state detection in the OHCI root hub driver was broken if
you used more than one device per root hub.

Change-Id: Ica5c735426beac45ef6f591ce68a72d8283a00f5
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: http://review.coreboot.org/1904
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
diff --git a/payloads/libpayload/drivers/usb/ohci_rh.c b/payloads/libpayload/drivers/usb/ohci_rh.c
index 9de2b98..aa44f33 100644
--- a/payloads/libpayload/drivers/usb/ohci_rh.c
+++ b/payloads/libpayload/drivers/usb/ohci_rh.c
@@ -128,15 +128,14 @@
 static int
 ohci_rh_report_port_changes (usbdev_t *dev)
 {
-	int i;
+	ohci_t *const ohcic = OHCI_INST (dev->controller);
 
-	if (!(OHCI_INST (dev->controller)->opreg->HcInterruptStatus & RootHubStatusChange)) return -1;
-	OHCI_INST (dev->controller)->opreg->HcInterruptStatus = RootHubStatusChange;
-	usb_debug("port change\n");
+	int i;
 
 	for (i = 0; i < RH_INST(dev)->numports; i++) {
 		// maybe detach+attach happened between two scans?
-		if (OHCI_INST (dev->controller)->opreg->HcRhPortStatus[i] & ConnectStatusChange) {
+		if (ohcic->opreg->HcRhPortStatus[i] & ConnectStatusChange) {
+			ohcic->opreg->HcRhPortStatus[i] = ConnectStatusChange;
 			usb_debug("attachment change on port %d\n", i);
 			return i;
 		}
@@ -158,7 +157,17 @@
 static void
 ohci_rh_poll (usbdev_t *dev)
 {
+	ohci_t *const ohcic = OHCI_INST (dev->controller);
+
 	int port;
+
+	/* Check if anything changed. */
+	if (!(ohcic->opreg->HcInterruptStatus & RootHubStatusChange))
+		return;
+	ohcic->opreg->HcInterruptStatus = RootHubStatusChange;
+	usb_debug("root hub status change\n");
+
+	/* Scan ports with changed connection status. */
 	while ((port = ohci_rh_report_port_changes (dev)) != -1)
 		ohci_rh_scanport (dev, port);
 }