Re: [PATCH v3 1/3] scsi: ufs: Serialize eh_work with system PM events and async scan

2020-11-30 Thread Asutosh Das (asd)

On 11/16/2020 11:04 PM, Can Guo wrote:

Serialize eh_work with system PM events and async scan to make sure eh_work
does not run in parallel with them.

Signed-off-by: Can Guo 
---


Reviewed-by: Asutosh Das 


  drivers/scsi/ufs/ufshcd.c | 64 +--
  drivers/scsi/ufs/ufshcd.h |  1 +
  2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1d8134e..7e764e8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5597,7 +5597,9 @@ static inline void ufshcd_schedule_eh_work(struct ufs_hba 
*hba)
  static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
  {
pm_runtime_get_sync(hba->dev);
-   if (pm_runtime_suspended(hba->dev)) {
+   if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) {
+   enum ufs_pm_op pm_op;
+
/*
 * Don't assume anything of pm_runtime_get_sync(), if
 * resume fails, irq and clocks can be OFF, and powers
@@ -5612,7 +5614,8 @@ static void ufshcd_err_handling_prepare(struct ufs_hba 
*hba)
if (!ufshcd_is_clkgating_allowed(hba))
ufshcd_setup_clocks(hba, true);
ufshcd_release(hba);
-   ufshcd_vops_resume(hba, UFS_RUNTIME_PM);
+   pm_op = hba->is_sys_suspended ? UFS_RUNTIME_PM : UFS_SYSTEM_PM;
+   ufshcd_vops_resume(hba, pm_op);
} else {
ufshcd_hold(hba, false);
if (hba->clk_scaling.is_allowed) {
@@ -5633,7 +5636,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba 
*hba)
  
  static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)

  {
-   return (hba->ufshcd_state == UFSHCD_STATE_ERROR ||
+   return (!hba->is_powered || hba->ufshcd_state == UFSHCD_STATE_ERROR ||
(!(hba->saved_err || hba->saved_uic_err || hba->force_reset ||
ufshcd_is_link_broken(hba;
  }
@@ -5646,6 +5649,7 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba)
struct request_queue *q;
int ret;
  
+	hba->is_sys_suspended = false;

/*
 * Set RPM status of hba device to RPM_ACTIVE,
 * this also clears its runtime error.
@@ -5704,11 +5708,13 @@ static void ufshcd_err_handler(struct work_struct *work)
  
  	hba = container_of(work, struct ufs_hba, eh_work);
  
+	down(&hba->eh_sem);

spin_lock_irqsave(hba->host->host_lock, flags);
if (ufshcd_err_handling_should_stop(hba)) {
if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
+   up(&hba->eh_sem);
return;
}
ufshcd_set_eh_in_progress(hba);
@@ -5716,20 +5722,18 @@ static void ufshcd_err_handler(struct work_struct *work)
ufshcd_err_handling_prepare(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_scsi_block_requests(hba);
-   /*
-* A full reset and restore might have happened after preparation
-* is finished, double check whether we should stop.
-*/
-   if (ufshcd_err_handling_should_stop(hba)) {
-   if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
-   hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-   goto out;
-   }
hba->ufshcd_state = UFSHCD_STATE_RESET;
  
  	/* Complete requests that have door-bell cleared by h/w */

ufshcd_complete_requests(hba);
  
+	/*

+* A full reset and restore might have happened after preparation
+* is finished, double check whether we should stop.
+*/
+   if (ufshcd_err_handling_should_stop(hba))
+   goto skip_err_handling;
+
if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
bool ret;
  
@@ -5737,17 +5741,10 @@ static void ufshcd_err_handler(struct work_struct *work)

/* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */
ret = ufshcd_quirk_dl_nac_errors(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
-   if (!ret && !hba->force_reset && ufshcd_is_link_active(hba))
+   if (!ret && ufshcd_err_handling_should_stop(hba))
goto skip_err_handling;
}
  
-	if (hba->force_reset || ufshcd_is_link_broken(hba) ||

-   ufshcd_is_saved_err_fatal(hba) ||
-   ((hba->saved_err & UIC_ERROR) &&
-(hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
-   UFSHCD_UIC_DL_TCx_REPLAY_ERROR
-   needs_reset = true;
-
if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) ||
(hba->saved_uic_err &&
 (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
@@ -5767

Re: [PATCH v3 1/3] scsi: ufs: Serialize eh_work with system PM events and async scan

2020-11-24 Thread hongwus

On 2020-11-17 15:04, Can Guo wrote:
Serialize eh_work with system PM events and async scan to make sure 
eh_work

does not run in parallel with them.

Signed-off-by: Can Guo 
---
 drivers/scsi/ufs/ufshcd.c | 64 
+--

 drivers/scsi/ufs/ufshcd.h |  1 +
 2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1d8134e..7e764e8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5597,7 +5597,9 @@ static inline void
ufshcd_schedule_eh_work(struct ufs_hba *hba)
 static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
 {
pm_runtime_get_sync(hba->dev);
-   if (pm_runtime_suspended(hba->dev)) {
+   if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) {
+   enum ufs_pm_op pm_op;
+
/*
 * Don't assume anything of pm_runtime_get_sync(), if
 * resume fails, irq and clocks can be OFF, and powers
@@ -5612,7 +5614,8 @@ static void ufshcd_err_handling_prepare(struct
ufs_hba *hba)
if (!ufshcd_is_clkgating_allowed(hba))
ufshcd_setup_clocks(hba, true);
ufshcd_release(hba);
-   ufshcd_vops_resume(hba, UFS_RUNTIME_PM);
+   pm_op = hba->is_sys_suspended ? UFS_RUNTIME_PM : UFS_SYSTEM_PM;
+   ufshcd_vops_resume(hba, pm_op);
} else {
ufshcd_hold(hba, false);
if (hba->clk_scaling.is_allowed) {
@@ -5633,7 +5636,7 @@ static void ufshcd_err_handling_unprepare(struct
ufs_hba *hba)

 static inline bool ufshcd_err_handling_should_stop(struct ufs_hba 
*hba)

 {
-   return (hba->ufshcd_state == UFSHCD_STATE_ERROR ||
+	return (!hba->is_powered || hba->ufshcd_state == UFSHCD_STATE_ERROR 
||

(!(hba->saved_err || hba->saved_uic_err || hba->force_reset ||
ufshcd_is_link_broken(hba;
 }
@@ -5646,6 +5649,7 @@ static void ufshcd_recover_pm_error(struct 
ufs_hba *hba)

struct request_queue *q;
int ret;

+   hba->is_sys_suspended = false;
/*
 * Set RPM status of hba device to RPM_ACTIVE,
 * this also clears its runtime error.
@@ -5704,11 +5708,13 @@ static void ufshcd_err_handler(struct 
work_struct *work)


hba = container_of(work, struct ufs_hba, eh_work);

+   down(&hba->eh_sem);
spin_lock_irqsave(hba->host->host_lock, flags);
if (ufshcd_err_handling_should_stop(hba)) {
if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
+   up(&hba->eh_sem);
return;
}
ufshcd_set_eh_in_progress(hba);
@@ -5716,20 +5722,18 @@ static void ufshcd_err_handler(struct 
work_struct *work)

ufshcd_err_handling_prepare(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_scsi_block_requests(hba);
-   /*
-* A full reset and restore might have happened after preparation
-* is finished, double check whether we should stop.
-*/
-   if (ufshcd_err_handling_should_stop(hba)) {
-   if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
-   hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-   goto out;
-   }
hba->ufshcd_state = UFSHCD_STATE_RESET;

/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);

+   /*
+* A full reset and restore might have happened after preparation
+* is finished, double check whether we should stop.
+*/
+   if (ufshcd_err_handling_should_stop(hba))
+   goto skip_err_handling;
+
if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
bool ret;

@@ -5737,17 +5741,10 @@ static void ufshcd_err_handler(struct 
work_struct *work)

/* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */
ret = ufshcd_quirk_dl_nac_errors(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
-   if (!ret && !hba->force_reset && ufshcd_is_link_active(hba))
+   if (!ret && ufshcd_err_handling_should_stop(hba))
goto skip_err_handling;
}

-   if (hba->force_reset || ufshcd_is_link_broken(hba) ||
-   ufshcd_is_saved_err_fatal(hba) ||
-   ((hba->saved_err & UIC_ERROR) &&
-(hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
-   UFSHCD_UIC_DL_TCx_REPLAY_ERROR
-   needs_reset = true;
-
 	if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) 
||

(hba->saved_uic_err &&
 (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
@@ -5767,8 +5764,14 @@ static void u

[PATCH v3 1/3] scsi: ufs: Serialize eh_work with system PM events and async scan

2020-11-16 Thread Can Guo
Serialize eh_work with system PM events and async scan to make sure eh_work
does not run in parallel with them.

Signed-off-by: Can Guo 
---
 drivers/scsi/ufs/ufshcd.c | 64 +--
 drivers/scsi/ufs/ufshcd.h |  1 +
 2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1d8134e..7e764e8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5597,7 +5597,9 @@ static inline void ufshcd_schedule_eh_work(struct ufs_hba 
*hba)
 static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
 {
pm_runtime_get_sync(hba->dev);
-   if (pm_runtime_suspended(hba->dev)) {
+   if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) {
+   enum ufs_pm_op pm_op;
+
/*
 * Don't assume anything of pm_runtime_get_sync(), if
 * resume fails, irq and clocks can be OFF, and powers
@@ -5612,7 +5614,8 @@ static void ufshcd_err_handling_prepare(struct ufs_hba 
*hba)
if (!ufshcd_is_clkgating_allowed(hba))
ufshcd_setup_clocks(hba, true);
ufshcd_release(hba);
-   ufshcd_vops_resume(hba, UFS_RUNTIME_PM);
+   pm_op = hba->is_sys_suspended ? UFS_RUNTIME_PM : UFS_SYSTEM_PM;
+   ufshcd_vops_resume(hba, pm_op);
} else {
ufshcd_hold(hba, false);
if (hba->clk_scaling.is_allowed) {
@@ -5633,7 +5636,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba 
*hba)
 
 static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)
 {
-   return (hba->ufshcd_state == UFSHCD_STATE_ERROR ||
+   return (!hba->is_powered || hba->ufshcd_state == UFSHCD_STATE_ERROR ||
(!(hba->saved_err || hba->saved_uic_err || hba->force_reset ||
ufshcd_is_link_broken(hba;
 }
@@ -5646,6 +5649,7 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba)
struct request_queue *q;
int ret;
 
+   hba->is_sys_suspended = false;
/*
 * Set RPM status of hba device to RPM_ACTIVE,
 * this also clears its runtime error.
@@ -5704,11 +5708,13 @@ static void ufshcd_err_handler(struct work_struct *work)
 
hba = container_of(work, struct ufs_hba, eh_work);
 
+   down(&hba->eh_sem);
spin_lock_irqsave(hba->host->host_lock, flags);
if (ufshcd_err_handling_should_stop(hba)) {
if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
+   up(&hba->eh_sem);
return;
}
ufshcd_set_eh_in_progress(hba);
@@ -5716,20 +5722,18 @@ static void ufshcd_err_handler(struct work_struct *work)
ufshcd_err_handling_prepare(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_scsi_block_requests(hba);
-   /*
-* A full reset and restore might have happened after preparation
-* is finished, double check whether we should stop.
-*/
-   if (ufshcd_err_handling_should_stop(hba)) {
-   if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
-   hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-   goto out;
-   }
hba->ufshcd_state = UFSHCD_STATE_RESET;
 
/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);
 
+   /*
+* A full reset and restore might have happened after preparation
+* is finished, double check whether we should stop.
+*/
+   if (ufshcd_err_handling_should_stop(hba))
+   goto skip_err_handling;
+
if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
bool ret;
 
@@ -5737,17 +5741,10 @@ static void ufshcd_err_handler(struct work_struct *work)
/* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */
ret = ufshcd_quirk_dl_nac_errors(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
-   if (!ret && !hba->force_reset && ufshcd_is_link_active(hba))
+   if (!ret && ufshcd_err_handling_should_stop(hba))
goto skip_err_handling;
}
 
-   if (hba->force_reset || ufshcd_is_link_broken(hba) ||
-   ufshcd_is_saved_err_fatal(hba) ||
-   ((hba->saved_err & UIC_ERROR) &&
-(hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
-   UFSHCD_UIC_DL_TCx_REPLAY_ERROR
-   needs_reset = true;
-
if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) ||
(hba->saved_uic_err &&
 (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
@@ -5767,8 +5764,14 @@ static void ufshcd_err_handler(struct work_st