diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2020-10-26 20:59:04 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2020-10-26 20:59:03 -0700 |
| commit | e982a3910e60c278cb343a906ebe259dabd221ba (patch) | |
| tree | 1212af0c29814bb65642b20cb96f6fdf356f3082 | |
| parent | 48beb346be2617a18064f111a4bc0dda1a9701c9 (diff) | |
| parent | 75f76b116032c79bd1bb077050f9690ff32fa16b (diff) | |
Merge "scsi: ufs: Flush exception event before suspend"
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9c77b89eb893..129b3a1b3d7f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3,7 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.c * Copyright (C) 2011-2013 Samsung India Software Operations - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> @@ -5405,8 +5405,15 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) * UFS device needs urgent BKOPs. */ if (!hba->pm_op_in_progress && - ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) - schedule_work(&hba->eeh_work); + ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) { + /* + * Prevent suspend once eeh_work is scheduled + * to avoid deadlock between ufshcd_suspend + * and exception event handler. + */ + if (schedule_work(&hba->eeh_work)) + pm_runtime_get_noresume(hba->dev); + } break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -5983,6 +5990,13 @@ static void ufshcd_exception_event_handler(struct work_struct *work) out: ufshcd_scsi_unblock_requests(hba); + /* + * pm_runtime_get_noresume is called while scheduling + * eeh_work to avoid suspend racing with exception work. + * Hence decrement usage counter using pm_runtime_put_noidle + * to allow suspend on completion of exception event handler. + */ + pm_runtime_put_noidle(hba->dev); pm_runtime_put(hba->dev); return; } @@ -8777,6 +8791,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto enable_gating; } + flush_work(&hba->eeh_work); ret = ufshcd_link_state_transition(hba, req_link_state, 1); if (ret) goto set_dev_active; |
