From f4adf1bc3786c0bb9329c03577d15f6004f57a6b Mon Sep 17 00:00:00 2001 From: Feng Mingli Date: Wed, 9 Aug 2017 20:34:17 +0800 Subject: [PATCH] usb: dwc_otg_310: pcd: hold wake lock until phy suspended and clk disabled When begin connecting to PC in device mode, the driver will hold a wake lock to prevent system from entering deep sleep. If it fails to connect to PC or doesn't detect the vbus, the driver will suspend usb phy and disable usb clk, and release the wake lock. If unlock the wake lock first, system may enter deep sleep before suspend usb phy and disable usb clk. Then wake up system by pull out the usb cable, it may cause usb interrupt abnormal. TEST=rk3126c connect the usb charger into the charging interface, after the system entered deep sleep, pull out the usb cable with the following log: irq 42: nobody cared (try booting with the "irqpoll" option) CPU: 0 PID: 146 Comm: charger Not tainted 3.10.104 #133 [] unwind_backtrace+0x0/0xe0 [] show_stack+0x10/0x14 [] __report_bad_irq+0x28/0xb8 [] note_interrupt+0x138/0x1cc [] handle_irq_event_percpu+0x2c0/0x2f4 [] handle_irq_event+0x3c/0x5c [] handle_fasteoi_irq+0xbc/0x124 [] generic_handle_irq+0x20/0x30 [] handle_IRQ+0x64/0x8c [] gic_handle_irq+0x38/0x5c handlers: [] dwc_otg_common_irq [] dwc_otg_pcd_irq [] usb_hcd_irq Disabling IRQ #42 Change-Id: Id36717ae68e02226255c1207aeded0bd6fb356cd Signed-off-by: Feng Mingli Signed-off-by: William Wu --- drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 631579722ab0..a4595632a61c 100644 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c @@ -1664,11 +1664,6 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) printk("**************soft reconnect**************\n"); goto connect; } else if (_pcd->conn_status == 2) { - /* - * Release pcd->wake_lock if fail to connect, - * and allow system to enter deep sleep. - */ - dwc_otg_msc_unlock(_pcd); _pcd->conn_status++; if (pldata->bc_detect_cb && iddig) { @@ -1684,6 +1679,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work) udelay(3); pldata->clock_enable(pldata, 0); } + + /* + * Release pcd->wake_lock if fail to connect, + * and allow system to enter deep sleep. + */ + dwc_otg_msc_unlock(_pcd); } } else { if (pldata->bc_detect_cb && iddig) @@ -1697,15 +1698,15 @@ 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); - if (iddig || (usb_mode == USB_MODE_FORCE_DEVICE)) { /* No vbus detect here , suspend usb phy */ pldata->phy_suspend(pldata, USB_PHY_SUSPEND); udelay(3); pldata->clock_enable(pldata, 0); } + + /* Release wake lock */ + dwc_otg_msc_unlock(_pcd); } /* Bypass usb phy to uart mode */