diff mbox series

[v2,1/3] scsi: ufs: Minor adjustments to error handling

Message ID 1614145010-36079-2-git-send-email-cang@codeaurora.org
State New
Headers show
Series Three minor changes related with error handling | expand

Commit Message

Can Guo Feb. 24, 2021, 5:36 a.m. UTC
In error handling prepare stage, after SCSI requests are blocked, do a
down/up_write(clk_scaling_lock) to clean up the queuecommand() path.
Meanwhile, stop eeh_work in case it disturbs error recovery. Moreover,
reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it may be
called multiple times during error recovery.

Signed-off-by: Can Guo <cang@codeaurora.org>
---
 drivers/scsi/ufs/ufshcd.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

Comments

Avri Altman March 3, 2021, 7:22 a.m. UTC | #1
> 

> 

> In error handling prepare stage, after SCSI requests are blocked, do a

> down/up_write(clk_scaling_lock) to clean up the queuecommand() path.

> Meanwhile, stop eeh_work in case it disturbs error recovery. Moreover,

> reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it may be

> called multiple times during error recovery.

> 

> Signed-off-by: Can Guo <cang@codeaurora.org>

I noticed that you tagged Adrian's patch -
https://lore.kernel.org/lkml/20210301191940.15247-1-adrian.hunter@intel.com/
So this patch needs to be adjusted accordingly?

Thanks,
Avri

> ---

>  drivers/scsi/ufs/ufshcd.c | 18 ++++++++++++------

>  1 file changed, 12 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c

> index 80620c8..013eb73 100644

> --- a/drivers/scsi/ufs/ufshcd.c

> +++ b/drivers/scsi/ufs/ufshcd.c

> @@ -4987,6 +4987,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,

> struct ufshcd_lrb *lrbp)

>                          * UFS device needs urgent BKOPs.

>                          */

>                         if (!hba->pm_op_in_progress &&

> +                           !ufshcd_eh_in_progress(hba) &&

>                             ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&

>                             schedule_work(&hba->eeh_work)) {

>                                 /*

> @@ -5784,13 +5785,20 @@ static void ufshcd_err_handling_prepare(struct

> ufs_hba *hba)

>                         ufshcd_suspend_clkscaling(hba);

>                 ufshcd_clk_scaling_allow(hba, false);

>         }

> +       ufshcd_scsi_block_requests(hba);

> +       /* Drain ufshcd_queuecommand() */

> +       down_write(&hba->clk_scaling_lock);

> +       up_write(&hba->clk_scaling_lock);

> +       cancel_work_sync(&hba->eeh_work);

>  }

> 

>  static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)

>  {

> +       ufshcd_scsi_unblock_requests(hba);

>         ufshcd_release(hba);

>         if (ufshcd_is_clkscaling_supported(hba))

>                 ufshcd_clk_scaling_suspend(hba, false);

> +       ufshcd_clear_ua_wluns(hba);

>         pm_runtime_put(hba->dev);

>  }

> 

> @@ -5882,8 +5890,8 @@ static void ufshcd_err_handler(struct work_struct

> *work)

>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>         ufshcd_err_handling_prepare(hba);

>         spin_lock_irqsave(hba->host->host_lock, flags);

> -       ufshcd_scsi_block_requests(hba);

> -       hba->ufshcd_state = UFSHCD_STATE_RESET;

> +       if (hba->ufshcd_state != UFSHCD_STATE_ERROR)

> +               hba->ufshcd_state = UFSHCD_STATE_RESET;

> 

>         /* Complete requests that have door-bell cleared by h/w */

>         ufshcd_complete_requests(hba);

> @@ -6042,12 +6050,8 @@ static void ufshcd_err_handler(struct work_struct

> *work)

>         }

>         ufshcd_clear_eh_in_progress(hba);

>         spin_unlock_irqrestore(hba->host->host_lock, flags);

> -       ufshcd_scsi_unblock_requests(hba);

>         ufshcd_err_handling_unprepare(hba);

>         up(&hba->host_sem);

> -

> -       if (!err && needs_reset)

> -               ufshcd_clear_ua_wluns(hba);

>  }

> 

>  /**

> @@ -7858,6 +7862,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba,

> bool async)

>         unsigned long flags;

>         ktime_t start = ktime_get();

> 

> +       hba->ufshcd_state = UFSHCD_STATE_RESET;

> +

>         ret = ufshcd_link_startup(hba);

>         if (ret)

>                 goto out;

> --

> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux

> Foundation Collaborative Project.
Can Guo March 3, 2021, 10:03 a.m. UTC | #2
Hi Avri,

On 2021-03-03 15:22, Avri Altman wrote:
>> 

>> 

>> In error handling prepare stage, after SCSI requests are blocked, do a

>> down/up_write(clk_scaling_lock) to clean up the queuecommand() path.

>> Meanwhile, stop eeh_work in case it disturbs error recovery. Moreover,

>> reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it may 

>> be

>> called multiple times during error recovery.

>> 

>> Signed-off-by: Can Guo <cang@codeaurora.org>

> I noticed that you tagged Adrian's patch -

> https://lore.kernel.org/lkml/20210301191940.15247-1-adrian.hunter@intel.com/

> So this patch needs to be adjusted accordingly?


Thanks for pointing me to that one, I will rebase mine.

Regards,
Can Guo.

> 

> Thanks,

> Avri

> 

>> ---

>>  drivers/scsi/ufs/ufshcd.c | 18 ++++++++++++------

>>  1 file changed, 12 insertions(+), 6 deletions(-)

>> 

>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c

>> index 80620c8..013eb73 100644

>> --- a/drivers/scsi/ufs/ufshcd.c

>> +++ b/drivers/scsi/ufs/ufshcd.c

>> @@ -4987,6 +4987,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,

>> struct ufshcd_lrb *lrbp)

>>                          * UFS device needs urgent BKOPs.

>>                          */

>>                         if (!hba->pm_op_in_progress &&

>> +                           !ufshcd_eh_in_progress(hba) &&

>>                             

>> ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&

>>                             schedule_work(&hba->eeh_work)) {

>>                                 /*

>> @@ -5784,13 +5785,20 @@ static void ufshcd_err_handling_prepare(struct

>> ufs_hba *hba)

>>                         ufshcd_suspend_clkscaling(hba);

>>                 ufshcd_clk_scaling_allow(hba, false);

>>         }

>> +       ufshcd_scsi_block_requests(hba);

>> +       /* Drain ufshcd_queuecommand() */

>> +       down_write(&hba->clk_scaling_lock);

>> +       up_write(&hba->clk_scaling_lock);

>> +       cancel_work_sync(&hba->eeh_work);

>>  }

>> 

>>  static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)

>>  {

>> +       ufshcd_scsi_unblock_requests(hba);

>>         ufshcd_release(hba);

>>         if (ufshcd_is_clkscaling_supported(hba))

>>                 ufshcd_clk_scaling_suspend(hba, false);

>> +       ufshcd_clear_ua_wluns(hba);

>>         pm_runtime_put(hba->dev);

>>  }

>> 

>> @@ -5882,8 +5890,8 @@ static void ufshcd_err_handler(struct 

>> work_struct

>> *work)

>>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>>         ufshcd_err_handling_prepare(hba);

>>         spin_lock_irqsave(hba->host->host_lock, flags);

>> -       ufshcd_scsi_block_requests(hba);

>> -       hba->ufshcd_state = UFSHCD_STATE_RESET;

>> +       if (hba->ufshcd_state != UFSHCD_STATE_ERROR)

>> +               hba->ufshcd_state = UFSHCD_STATE_RESET;

>> 

>>         /* Complete requests that have door-bell cleared by h/w */

>>         ufshcd_complete_requests(hba);

>> @@ -6042,12 +6050,8 @@ static void ufshcd_err_handler(struct 

>> work_struct

>> *work)

>>         }

>>         ufshcd_clear_eh_in_progress(hba);

>>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>> -       ufshcd_scsi_unblock_requests(hba);

>>         ufshcd_err_handling_unprepare(hba);

>>         up(&hba->host_sem);

>> -

>> -       if (!err && needs_reset)

>> -               ufshcd_clear_ua_wluns(hba);

>>  }

>> 

>>  /**

>> @@ -7858,6 +7862,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba,

>> bool async)

>>         unsigned long flags;

>>         ktime_t start = ktime_get();

>> 

>> +       hba->ufshcd_state = UFSHCD_STATE_RESET;

>> +

>>         ret = ufshcd_link_startup(hba);

>>         if (ret)

>>                 goto out;

>> --

>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a 

>> Linux

>> Foundation Collaborative Project.
Can Guo March 3, 2021, 10:06 a.m. UTC | #3
On 2021-03-03 18:03, Can Guo wrote:
> Hi Avri,

> 

> On 2021-03-03 15:22, Avri Altman wrote:

>>> 

>>> 

>>> In error handling prepare stage, after SCSI requests are blocked, do 

>>> a

>>> down/up_write(clk_scaling_lock) to clean up the queuecommand() path.

>>> Meanwhile, stop eeh_work in case it disturbs error recovery. 

>>> Moreover,

>>> reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it 

>>> may be

>>> called multiple times during error recovery.

>>> 

>>> Signed-off-by: Can Guo <cang@codeaurora.org>

>> I noticed that you tagged Adrian's patch -

>> https://lore.kernel.org/lkml/20210301191940.15247-1-adrian.hunter@intel.com/

>> So this patch needs to be adjusted accordingly?

> 

> Thanks for pointing me to that one, I will rebase mine.

> 

> Regards,

> Can Guo.

> 


Just noticed that Adrian's change comes later than mine, so I may not 
need to
adjust mine.

Thanks,
Can Guo.

>> 

>> Thanks,

>> Avri

>> 

>>> ---

>>>  drivers/scsi/ufs/ufshcd.c | 18 ++++++++++++------

>>>  1 file changed, 12 insertions(+), 6 deletions(-)

>>> 

>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c

>>> index 80620c8..013eb73 100644

>>> --- a/drivers/scsi/ufs/ufshcd.c

>>> +++ b/drivers/scsi/ufs/ufshcd.c

>>> @@ -4987,6 +4987,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,

>>> struct ufshcd_lrb *lrbp)

>>>                          * UFS device needs urgent BKOPs.

>>>                          */

>>>                         if (!hba->pm_op_in_progress &&

>>> +                           !ufshcd_eh_in_progress(hba) &&

>>>                             

>>> ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&

>>>                             schedule_work(&hba->eeh_work)) {

>>>                                 /*

>>> @@ -5784,13 +5785,20 @@ static void 

>>> ufshcd_err_handling_prepare(struct

>>> ufs_hba *hba)

>>>                         ufshcd_suspend_clkscaling(hba);

>>>                 ufshcd_clk_scaling_allow(hba, false);

>>>         }

>>> +       ufshcd_scsi_block_requests(hba);

>>> +       /* Drain ufshcd_queuecommand() */

>>> +       down_write(&hba->clk_scaling_lock);

>>> +       up_write(&hba->clk_scaling_lock);

>>> +       cancel_work_sync(&hba->eeh_work);

>>>  }

>>> 

>>>  static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)

>>>  {

>>> +       ufshcd_scsi_unblock_requests(hba);

>>>         ufshcd_release(hba);

>>>         if (ufshcd_is_clkscaling_supported(hba))

>>>                 ufshcd_clk_scaling_suspend(hba, false);

>>> +       ufshcd_clear_ua_wluns(hba);

>>>         pm_runtime_put(hba->dev);

>>>  }

>>> 

>>> @@ -5882,8 +5890,8 @@ static void ufshcd_err_handler(struct 

>>> work_struct

>>> *work)

>>>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>>>         ufshcd_err_handling_prepare(hba);

>>>         spin_lock_irqsave(hba->host->host_lock, flags);

>>> -       ufshcd_scsi_block_requests(hba);

>>> -       hba->ufshcd_state = UFSHCD_STATE_RESET;

>>> +       if (hba->ufshcd_state != UFSHCD_STATE_ERROR)

>>> +               hba->ufshcd_state = UFSHCD_STATE_RESET;

>>> 

>>>         /* Complete requests that have door-bell cleared by h/w */

>>>         ufshcd_complete_requests(hba);

>>> @@ -6042,12 +6050,8 @@ static void ufshcd_err_handler(struct 

>>> work_struct

>>> *work)

>>>         }

>>>         ufshcd_clear_eh_in_progress(hba);

>>>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>>> -       ufshcd_scsi_unblock_requests(hba);

>>>         ufshcd_err_handling_unprepare(hba);

>>>         up(&hba->host_sem);

>>> -

>>> -       if (!err && needs_reset)

>>> -               ufshcd_clear_ua_wluns(hba);

>>>  }

>>> 

>>>  /**

>>> @@ -7858,6 +7862,8 @@ static int ufshcd_probe_hba(struct ufs_hba 

>>> *hba,

>>> bool async)

>>>         unsigned long flags;

>>>         ktime_t start = ktime_get();

>>> 

>>> +       hba->ufshcd_state = UFSHCD_STATE_RESET;

>>> +

>>>         ret = ufshcd_link_startup(hba);

>>>         if (ret)

>>>                 goto out;

>>> --

>>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a 

>>> Linux

>>> Foundation Collaborative Project.
Avri Altman March 3, 2021, 11:43 a.m. UTC | #4
> 

> In error handling prepare stage, after SCSI requests are blocked, do a

> down/up_write(clk_scaling_lock) to clean up the queuecommand() path.

> Meanwhile, stop eeh_work in case it disturbs error recovery. Moreover,

> reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it may be

> called multiple times during error recovery.

> 

> Signed-off-by: Can Guo <cang@codeaurora.org>

Reviewed-by: Avri Altman <avri.altman@wdc.com>



> ---

>  drivers/scsi/ufs/ufshcd.c | 18 ++++++++++++------

>  1 file changed, 12 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c

> index 80620c8..013eb73 100644

> --- a/drivers/scsi/ufs/ufshcd.c

> +++ b/drivers/scsi/ufs/ufshcd.c

> @@ -4987,6 +4987,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,

> struct ufshcd_lrb *lrbp)

>                          * UFS device needs urgent BKOPs.

>                          */

>                         if (!hba->pm_op_in_progress &&

> +                           !ufshcd_eh_in_progress(hba) &&

>                             ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&

>                             schedule_work(&hba->eeh_work)) {

>                                 /*

> @@ -5784,13 +5785,20 @@ static void ufshcd_err_handling_prepare(struct

> ufs_hba *hba)

>                         ufshcd_suspend_clkscaling(hba);

>                 ufshcd_clk_scaling_allow(hba, false);

>         }

> +       ufshcd_scsi_block_requests(hba);

> +       /* Drain ufshcd_queuecommand() */

> +       down_write(&hba->clk_scaling_lock);

> +       up_write(&hba->clk_scaling_lock);

> +       cancel_work_sync(&hba->eeh_work);

>  }

> 

>  static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)

>  {

> +       ufshcd_scsi_unblock_requests(hba);

>         ufshcd_release(hba);

>         if (ufshcd_is_clkscaling_supported(hba))

>                 ufshcd_clk_scaling_suspend(hba, false);

> +       ufshcd_clear_ua_wluns(hba);

>         pm_runtime_put(hba->dev);

>  }

> 

> @@ -5882,8 +5890,8 @@ static void ufshcd_err_handler(struct work_struct

> *work)

>         spin_unlock_irqrestore(hba->host->host_lock, flags);

>         ufshcd_err_handling_prepare(hba);

>         spin_lock_irqsave(hba->host->host_lock, flags);

> -       ufshcd_scsi_block_requests(hba);

> -       hba->ufshcd_state = UFSHCD_STATE_RESET;

> +       if (hba->ufshcd_state != UFSHCD_STATE_ERROR)

> +               hba->ufshcd_state = UFSHCD_STATE_RESET;

> 

>         /* Complete requests that have door-bell cleared by h/w */

>         ufshcd_complete_requests(hba);

> @@ -6042,12 +6050,8 @@ static void ufshcd_err_handler(struct work_struct

> *work)

>         }

>         ufshcd_clear_eh_in_progress(hba);

>         spin_unlock_irqrestore(hba->host->host_lock, flags);

> -       ufshcd_scsi_unblock_requests(hba);

>         ufshcd_err_handling_unprepare(hba);

>         up(&hba->host_sem);

> -

> -       if (!err && needs_reset)

> -               ufshcd_clear_ua_wluns(hba);

>  }

> 

>  /**

> @@ -7858,6 +7862,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba,

> bool async)

>         unsigned long flags;

>         ktime_t start = ktime_get();

> 

> +       hba->ufshcd_state = UFSHCD_STATE_RESET;

> +

>         ret = ufshcd_link_startup(hba);

>         if (ret)

>                 goto out;

> --

> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux

> Foundation Collaborative Project.
diff mbox series

Patch

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 80620c8..013eb73 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4987,6 +4987,7 @@  ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 			 * UFS device needs urgent BKOPs.
 			 */
 			if (!hba->pm_op_in_progress &&
+			    !ufshcd_eh_in_progress(hba) &&
 			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&
 			    schedule_work(&hba->eeh_work)) {
 				/*
@@ -5784,13 +5785,20 @@  static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
 			ufshcd_suspend_clkscaling(hba);
 		ufshcd_clk_scaling_allow(hba, false);
 	}
+	ufshcd_scsi_block_requests(hba);
+	/* Drain ufshcd_queuecommand() */
+	down_write(&hba->clk_scaling_lock);
+	up_write(&hba->clk_scaling_lock);
+	cancel_work_sync(&hba->eeh_work);
 }
 
 static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
 {
+	ufshcd_scsi_unblock_requests(hba);
 	ufshcd_release(hba);
 	if (ufshcd_is_clkscaling_supported(hba))
 		ufshcd_clk_scaling_suspend(hba, false);
+	ufshcd_clear_ua_wluns(hba);
 	pm_runtime_put(hba->dev);
 }
 
@@ -5882,8 +5890,8 @@  static void ufshcd_err_handler(struct work_struct *work)
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 	ufshcd_err_handling_prepare(hba);
 	spin_lock_irqsave(hba->host->host_lock, flags);
-	ufshcd_scsi_block_requests(hba);
-	hba->ufshcd_state = UFSHCD_STATE_RESET;
+	if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
+		hba->ufshcd_state = UFSHCD_STATE_RESET;
 
 	/* Complete requests that have door-bell cleared by h/w */
 	ufshcd_complete_requests(hba);
@@ -6042,12 +6050,8 @@  static void ufshcd_err_handler(struct work_struct *work)
 	}
 	ufshcd_clear_eh_in_progress(hba);
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	ufshcd_scsi_unblock_requests(hba);
 	ufshcd_err_handling_unprepare(hba);
 	up(&hba->host_sem);
-
-	if (!err && needs_reset)
-		ufshcd_clear_ua_wluns(hba);
 }
 
 /**
@@ -7858,6 +7862,8 @@  static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
 	unsigned long flags;
 	ktime_t start = ktime_get();
 
+	hba->ufshcd_state = UFSHCD_STATE_RESET;
+
 	ret = ufshcd_link_startup(hba);
 	if (ret)
 		goto out;