lkml.org 
[lkml]   [2018]   [Mar]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.15 47/52] usb: dwc3: of-simple: fix oops by unbalanced clk disable call
    Date
    4.15-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Enric Balletbo i Serra <enric.balletbo@collabora.com>

    commit bff52352e0ccc2481f2b6b0d612ff8ff56c50f3a upstream.

    dwc3_of_simple_dev_pm_ops has never been used since commit a0d8c4cfdf31
    ("usb: dwc3: of-simple: set dev_pm_ops"), but this commit has brought
    and oops when unbind the device due this sequence:

    dwc3_of_simple_remove
    -> clk_disable ...
    -> pm_runtime_put_sync
    -> dwc3_of_simple_runtime_suspend
    -> clk_disable (again)

    This double call to clk_core_disable causes a kernel oops like this:

    WARNING: CPU: 1 PID: 4022 at drivers/clk/clk.c:656 clk_core_disable+0x78/0x80
    CPU: 1 PID: 4022 Comm: bash Not tainted 4.15.0-rc4+ #44
    Hardware name: Google Kevin (DT)
    pstate: 80000085 (Nzcv daIf -PAN -UAO)
    pc : clk_core_disable+0x78/0x80
    lr : clk_core_disable_lock+0x20/0x38
    sp : ffff00000bbf3a90
    ...
    Call trace:
    clk_core_disable+0x78/0x80
    clk_disable+0x1c/0x30
    dwc3_of_simple_runtime_suspend+0x30/0x50
    pm_generic_runtime_suspend+0x28/0x40

    This patch fixes the unbalanced clk disable call by setting the num_clocks
    variable to zero once the clocks were disabled.

    Fixes: a0d8c4cfdf31 ("usb: dwc3: of-simple: set dev_pm_ops")
    Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
    Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/usb/dwc3/dwc3-of-simple.c | 1 +
    1 file changed, 1 insertion(+)

    --- a/drivers/usb/dwc3/dwc3-of-simple.c
    +++ b/drivers/usb/dwc3/dwc3-of-simple.c
    @@ -143,6 +143,7 @@ static int dwc3_of_simple_remove(struct
    clk_disable_unprepare(simple->clks[i]);
    clk_put(simple->clks[i]);
    }
    + simple->num_clocks = 0;

    reset_control_assert(simple->resets);
    reset_control_put(simple->resets);

    \
     
     \ /
      Last update: 2018-03-19 19:41    [W:2.607 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site