From dcf51f2d382ae009f9ef6ffd75164513edbe7515 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Fri, 8 May 2015 12:46:17 +0300 Subject: usb: phy: msm: Unregister driver interest for VBUS and ID events Right now even if driver failed to probe extcon framework will still deliver VBUS and ID events, which will lead to random exception codes, like: # kworker/2:1[621]: undefined instruction: pc=ffffffc036a40148 Code: 00000000 00000000 30303031 2e303030 (636e6970) Internal error: Oops - undefined instruction: 0 [#1] PREEMPT SMP Modules linked in: CPU: 2 PID: 621 Comm: kworker/2:1 Not tainted 4.1.0-rc2+ #1 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) Workqueue: events_power_efficient usb_extcon_detect_cable task: ffffffc002756300 ti: ffffffc002724000 task.ti: ffffffc002724000 PC is at 0xffffffc036a40148 LR is at notifier_call_chain+0x4c/0x88 Fix this by removing driver interest for VBUS and ID events when probe fail or driver remove. Signed-off-by: Ivan T. Ivanov --- drivers/usb/phy/phy-msm-usb.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index ab9c393dbe52..04f378052f8e 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1629,15 +1629,6 @@ static int msm_otg_probe(struct platform_device *pdev) if (!motg) return -ENOMEM; - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - if (!np) - return -ENXIO; - ret = msm_otg_read_dt(pdev, motg); - if (ret) - return ret; - } - motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), GFP_KERNEL); if (!motg->phy.otg) @@ -1708,6 +1699,15 @@ static int msm_otg_probe(struct platform_device *pdev) if (ret) return ret; + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + if (!np) + return -ENXIO; + ret = msm_otg_read_dt(pdev, motg); + if (ret) + return ret; + } + motg->vddcx = regs[0].consumer; motg->v3p3 = regs[1].consumer; motg->v1p8 = regs[2].consumer; @@ -1789,6 +1789,12 @@ disable_vddcx: clk_disable_unprepare(motg->clk); if (!IS_ERR(motg->core_clk)) clk_disable_unprepare(motg->core_clk); + + if (motg->id_cable.edev) + extcon_unregister_interest(&motg->id_cable); + if (motg->vbus_cable.edev) + extcon_unregister_interest(&motg->vbus_cable); + return ret; } @@ -1801,6 +1807,11 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; + if (motg->id_cable.edev) + extcon_unregister_interest(&motg->id_cable); + if (motg->vbus_cable.edev) + extcon_unregister_interest(&motg->vbus_cable); + msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_work_sync(&motg->sm_work); -- cgit v1.2.3