From: Feng Mingli Date: Mon, 17 Aug 2015 01:24:49 +0000 (+0800) Subject: USB: dwc_otg_310: modify usb mode change detect bug X-Git-Tag: firefly_0821_release~3842 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=954898839e4860bb69c1a3fc0bb9486c6a7249ab;p=firefly-linux-kernel-4.4.55.git USB: dwc_otg_310: modify usb mode change detect bug When dwc controller change mode form device to host, may check_vbus_work is running on other cpu, but we don't have a good synchronization id_status_change and check_vbus_work, as a result, phy and clk may in incorrect state. So modify it. Signed-off-by: Feng Mingli Signed-off-by: lyz Conflicts: drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c --- diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c index e5f1c6d201d4..e67384d73305 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c @@ -1561,7 +1561,7 @@ static void id_status_change(dwc_otg_core_if_t *p, bool current_id) core_if->op_state = A_HOST; dwc_otg_set_force_mode(core_if, USB_MODE_FORCE_HOST); - cancel_delayed_work(&pcd->check_vbus_work); + cancel_delayed_work_sync(&pcd->check_vbus_work); /* * Initialize the Core for Host mode. @@ -1590,11 +1590,8 @@ static void check_id(struct work_struct *work) pldata->phy_suspend(pldata, USB_PHY_ENABLED); } - if (!id) { /* Force Host */ - id_status_change(otg_dev->core_if, id); - } else { /* Force Device */ - id_status_change(otg_dev->core_if, id); - } + /* Force Device or Host by id */ + id_status_change(otg_dev->core_if, id); } last_id = id; schedule_delayed_work(&_pcd->check_id_work, (HZ)); @@ -1662,10 +1659,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) if (pldata->phy_status == USB_PHY_ENABLED) { /* release wake lock */ dwc_otg_msc_unlock(_pcd); - /* no vbus detect here , close usb phy */ - pldata->phy_suspend(pldata, USB_PHY_SUSPEND); - udelay(3); - pldata->clock_enable(pldata, 0); + if (pldata->get_status(USB_STATUS_ID)) { + /* no vbus detect here , close usb phy */ + pldata->phy_suspend(pldata, USB_PHY_SUSPEND); + udelay(3); + pldata->clock_enable(pldata, 0); + } } /* usb phy bypass to uart mode */ @@ -1673,7 +1672,8 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE); } - schedule_delayed_work(&_pcd->check_vbus_work, HZ); + if (pldata->get_status(USB_STATUS_ID)) + schedule_delayed_work(&_pcd->check_vbus_work, HZ); return; connect: