From 105e2d39dcf15844113a04711a6d240dbae00517 Mon Sep 17 00:00:00 2001 From: hgchu Date: Fri, 12 Jan 2018 15:35:04 +0900 Subject: [PATCH] [COMMON] scsi: ufs: asynchronous link establishment on UFS resume Change-Id: I62f0259277959fa90590f5823adbe3bc7fbc2ccd Signed-off-by: hgchu --- drivers/scsi/ufs/Kconfig | 12 ++++++++++++ drivers/scsi/ufs/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 42afe905acff..5b174f8feb91 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -87,6 +87,18 @@ config SCSI_UFS_DWC_TC_PLATFORM If unsure, say N. +config SCSI_UFS_ASYNC_RELINK + tristate "Asynchronous link establishment on UFS device resume" + depends on SCSI_UFSHCD && SCSI_UFSHCD_PLATFORM + ---help--- + This feature is to support concurrency of UFS resume and the others. + In UFS re-link, system wake-up may task a long time when UFS resume + time is increased for device latency or etc. + + If you want to enable this feature, say Y or M here. + + If unsure, say N. + config SCSI_UFS_QCOM tristate "QCOM specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 317eae63c98c..5a6d7f76e405 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6003,7 +6003,7 @@ out: */ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) { - int err; + int err = 0; unsigned long flags; /* Reset the host controller */ @@ -6017,12 +6017,20 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) ufshcd_scale_clks(hba, true); /* Establish the link again and restore the device */ - err = ufshcd_probe_hba(hba); +#ifdef CONFIG_SCSI_UFS_ASYNC_RELINK + if (hba->pm_op_in_progress) + async_schedule(ufshcd_async_scan, hba); + else +#endif + { + err = ufshcd_probe_hba(hba); if (!err && (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)) { dev_err(hba->dev, "%s: failed\n", __func__); err = -EIO; } + } + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_clear_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -6685,7 +6693,8 @@ retry: * If we are in error handling context or in power management callbacks * context, no need to scan the host */ - if (!ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) { + if (!ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress + && !hba->async_resume) { bool flag; /* clear any previous UFS device information */ @@ -6777,8 +6786,30 @@ out: static void ufshcd_async_scan(void *data, async_cookie_t cookie) { struct ufs_hba *hba = (struct ufs_hba *)data; + int err = 0; - ufshcd_probe_hba(hba); + if (hba->async_resume) { + scsi_block_requests(hba->host); + err = ufshcd_probe_hba(hba); + if (err) + goto err; + + if (!ufshcd_is_ufs_dev_active(hba)) { + scsi_unblock_requests(hba->host); + ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE); + scsi_block_requests(hba->host); + } + + /* + * If BKOPs operations are urgently needed at this moment then + * keep auto-bkops enabled or else disable it. + */ + ufshcd_urgent_bkops(hba); +err: + scsi_unblock_requests(hba->host); + } else { + ufshcd_probe_hba(hba); + } } static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) -- 2.20.1