[linux-yocto] [PATCH 14/17] drivers/usb/core: fix over-current race condition

Daniel Dragomir daniel.dragomir at windriver.com
Tue May 16 11:39:06 PDT 2017


From: Charlie Paul <cpaul.windriver at gmail.com>

There exists a race condition when an over-current fault is cleared,
between the event processing in the hub_event function and the setting
of the event bits in the hub_irq function. When the over-current is
cleared the hub_event call tries to read the event bits, which havent
been set by the hub_irq.  In this patch when the over-current is
cleared the hub_event will check the event bits and if they are not
set it will pause and check again. It will sync the event bits.

Signed-off-by: Charlie Paul <cpaul.windriver at gmail.com>
---
 drivers/usb/core/hub.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 35fb2bef..07da7ea 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5019,8 +5019,8 @@ static void port_event(struct usb_hub *hub, int port1)
 		dev_dbg(&port_dev->dev, "over-current change\n");
 		usb_clear_port_feature(hdev, port1,
 				USB_PORT_FEAT_C_OVER_CURRENT);
-		msleep(100);	/* Cool down */
 		hub_power_on(hub, true);
+		msleep(100);	/* Cool down */
 		hub_port_status(hub, port1, &status, &unused);
 		if (status & USB_PORT_STAT_OVERCURRENT)
 			dev_err(&port_dev->dev, "over-current condition\n");
@@ -5137,6 +5137,7 @@ static void hub_event(struct work_struct *work)
 		hub->error = 0;
 	}
 
+
 	/* deal with port status changes */
 	for (i = 1; i <= hdev->maxchild; i++) {
 		struct usb_port *port_dev = hub->ports[i - 1];
@@ -5159,7 +5160,9 @@ static void hub_event(struct work_struct *work)
 			port_event(hub, i);
 			usb_unlock_port(port_dev);
 			pm_runtime_put_sync(&port_dev->dev);
-		}
+		} else
+			/* Wait for the hub_irq to finish then update the port status */
+			msleep(100);
 	}
 
 	/* deal with hub status changes */
-- 
2.7.4



More information about the linux-yocto mailing list