lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 0753/1039] scsi: ufs: Fix a kernel crash during shutdown
    Date
    From: Bart Van Assche <bvanassche@acm.org>

    [ Upstream commit 3489c34bd02b73a72646037d673a122a53cee174 ]

    Fix the following kernel crash:

    Unable to handle kernel paging request at virtual address ffffffc91e735000
    Call trace:
    __queue_work+0x26c/0x624
    queue_work_on+0x6c/0xf0
    ufshcd_hold+0x12c/0x210
    __ufshcd_wl_suspend+0xc0/0x400
    ufshcd_wl_shutdown+0xb8/0xcc
    device_shutdown+0x184/0x224
    kernel_restart+0x4c/0x124
    __arm64_sys_reboot+0x194/0x264
    el0_svc_common+0xc8/0x1d4
    do_el0_svc+0x30/0x8c
    el0_svc+0x20/0x30
    el0_sync_handler+0x84/0xe4
    el0_sync+0x1bc/0x1c0

    Fix this crash by ungating the clock before destroying the work queue on
    which clock gating work is queued.

    Link: https://lore.kernel.org/r/20211203231950.193369-15-bvanassche@acm.org
    Tested-by: Bean Huo <beanhuo@micron.com>
    Reviewed-by: Bean Huo <beanhuo@micron.com>
    Signed-off-by: Bart Van Assche <bvanassche@acm.org>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/ufs/ufshcd.c | 15 ++++++++++-----
    1 file changed, 10 insertions(+), 5 deletions(-)

    diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
    index 4394081806978..c94377aa82739 100644
    --- a/drivers/scsi/ufs/ufshcd.c
    +++ b/drivers/scsi/ufs/ufshcd.c
    @@ -1666,7 +1666,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
    bool flush_result;
    unsigned long flags;

    - if (!ufshcd_is_clkgating_allowed(hba))
    + if (!ufshcd_is_clkgating_allowed(hba) ||
    + !hba->clk_gating.is_initialized)
    goto out;
    spin_lock_irqsave(hba->host->host_lock, flags);
    hba->clk_gating.active_reqs++;
    @@ -1826,7 +1827,7 @@ static void __ufshcd_release(struct ufs_hba *hba)

    if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended ||
    hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL ||
    - hba->outstanding_tasks ||
    + hba->outstanding_tasks || !hba->clk_gating.is_initialized ||
    hba->active_uic_cmd || hba->uic_async_done ||
    hba->clk_gating.state == CLKS_OFF)
    return;
    @@ -1961,11 +1962,15 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
    {
    if (!hba->clk_gating.is_initialized)
    return;
    +
    ufshcd_remove_clk_gating_sysfs(hba);
    - cancel_work_sync(&hba->clk_gating.ungate_work);
    - cancel_delayed_work_sync(&hba->clk_gating.gate_work);
    - destroy_workqueue(hba->clk_gating.clk_gating_workq);
    +
    + /* Ungate the clock if necessary. */
    + ufshcd_hold(hba, false);
    hba->clk_gating.is_initialized = false;
    + ufshcd_release(hba);
    +
    + destroy_workqueue(hba->clk_gating.clk_gating_workq);
    }

    /* Must be called with host lock acquired */
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-01-25 00:11    [W:2.917 / U:0.424 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site