Re: [PATCH v11 1/2] scsi: ufs: Enable power management for wlun

2021-03-18 Thread Asutosh Das (asd)

On 3/15/2021 7:29 AM, Adrian Hunter wrote:

On 12/03/21 12:19 am, Asutosh Das wrote:

During runtime-suspend of ufs host, the scsi devices are
already suspended and so are the queues associated with them.
But the ufs host sends SSU to wlun during its runtime-suspend.
During the process blk_queue_enter checks if the queue is not in
suspended state. If so, it waits for the queue to resume, and never
comes out of it.
The commit
(d55d15a33: scsi: block: Do not accept any requests while suspended)
adds the check if the queue is in suspended state in blk_queue_enter().

Call trace:
  __switch_to+0x174/0x2c4
  __schedule+0x478/0x764
  schedule+0x9c/0xe0
  blk_queue_enter+0x158/0x228
  blk_mq_alloc_request+0x40/0xa4
  blk_get_request+0x2c/0x70
  __scsi_execute+0x60/0x1c4
  ufshcd_set_dev_pwr_mode+0x124/0x1e4
  ufshcd_suspend+0x208/0x83c
  ufshcd_runtime_suspend+0x40/0x154
  ufshcd_pltfrm_runtime_suspend+0x14/0x20
  pm_generic_runtime_suspend+0x28/0x3c
  __rpm_callback+0x80/0x2a4
  rpm_suspend+0x308/0x614
  rpm_idle+0x158/0x228
  pm_runtime_work+0x84/0xac
  process_one_work+0x1f0/0x470
  worker_thread+0x26c/0x4c8
  kthread+0x13c/0x320
  ret_from_fork+0x10/0x18

Fix this by registering ufs device wlun as a scsi driver and
registering it for block runtime-pm. Also make this as a
supplier for all other luns. That way, this device wlun
suspends after all the consumers and resumes after
hba resumes.


I haven't had time to try to reproduce the device-links issue, but
there are a couple of comments below, in addition to the suggestions
here:

https://lore.kernel.org/linux-scsi/b13086f3-eea1-51a7-2117-579d520f2...@intel.com/


Thanks.
I think even if the race in pm framework is fixed, the 
scsi_sysfs_add_sdev() can race with sd_probe().
IIUC that's because scsi_sysfs_add_sdev() schedules an async probe for 
the sd device and then invokes scsi_autopm_put_device().



Also, there are still ufshcd_err_handling_prepare()/unprepare()
and ufshcd_recover_pm_error(), that look like they need attention
e.g. to use scsi_autopm_get/put_device(hba->sdev_ufs_device)


Sure will address this.





Co-developed-by: Can Guo 
Signed-off-by: Can Guo 
Signed-off-by: Asutosh Das 
---
  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
  drivers/scsi/ufs/ufs-debugfs.c |   5 +
  drivers/scsi/ufs/ufs-debugfs.h |   2 +
  drivers/scsi/ufs/ufs-exynos.c  |   2 +
  drivers/scsi/ufs/ufs-hisi.c|   2 +
  drivers/scsi/ufs/ufs-mediatek.c|   2 +
  drivers/scsi/ufs/ufs-qcom.c|   2 +
  drivers/scsi/ufs/ufs_bsg.c |   6 +-
  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
  drivers/scsi/ufs/ufshcd.c  | 616 ++---
  drivers/scsi/ufs/ufshcd.h  |   7 +
  include/trace/events/ufs.h |  20 ++
  13 files changed, 498 insertions(+), 206 deletions(-)

diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
index 149391f..3e70c23 100644
--- a/drivers/scsi/ufs/cdns-pltfrm.c
+++ b/drivers/scsi/ufs/cdns-pltfrm.c
@@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
.runtime_suspend = ufshcd_pltfrm_runtime_suspend,
.runtime_resume  = ufshcd_pltfrm_runtime_resume,
.runtime_idle= ufshcd_pltfrm_runtime_idle,
+   .prepare = ufshcd_suspend_prepare,
+   .complete   = ufshcd_resume_complete,
  };
  
  static struct platform_driver cdns_ufs_pltfrm_driver = {

diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index 67a6a61..b01db12 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
.runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
.runtime_resume  = tc_dwc_g210_pci_runtime_resume,
.runtime_idle= tc_dwc_g210_pci_runtime_idle,
+   .prepare = ufshcd_suspend_prepare,
+   .complete   = ufshcd_resume_complete,
  };
  
  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index dee98dc..f8ce2eb 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -54,3 +54,8 @@ void ufs_debugfs_hba_exit(struct ufs_hba *hba)
  {
debugfs_remove_recursive(hba->debugfs_root);
  }
+
+void ufs_debugfs_eh_exit(void)
+{
+   debugfs_remove_recursive(ufs_debugfs_root);
+}


This is the same as ufs_debugfs_exit() without __exit so why not
remove __exit from ufs_debugfs_exit() and use that instead?


Will change it.


diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index f35b39c..3fce5a0 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
  void __exit ufs_debugfs_exit(void);
  void ufs_debugfs_hba_init(struct ufs_hba *hba);
  void ufs_debugfs_hba_exit(struct ufs_

Re: [PATCH v11 1/2] scsi: ufs: Enable power management for wlun

2021-03-15 Thread Asutosh Das (asd)

On 3/15/2021 7:29 AM, Adrian Hunter wrote:

On 12/03/21 12:19 am, Asutosh Das wrote:

During runtime-suspend of ufs host, the scsi devices are
already suspended and so are the queues associated with them.
But the ufs host sends SSU to wlun during its runtime-suspend.
During the process blk_queue_enter checks if the queue is not in
suspended state. If so, it waits for the queue to resume, and never
comes out of it.
The commit
(d55d15a33: scsi: block: Do not accept any requests while suspended)
adds the check if the queue is in suspended state in blk_queue_enter().

Call trace:
  __switch_to+0x174/0x2c4
  __schedule+0x478/0x764
  schedule+0x9c/0xe0
  blk_queue_enter+0x158/0x228
  blk_mq_alloc_request+0x40/0xa4
  blk_get_request+0x2c/0x70
  __scsi_execute+0x60/0x1c4
  ufshcd_set_dev_pwr_mode+0x124/0x1e4
  ufshcd_suspend+0x208/0x83c
  ufshcd_runtime_suspend+0x40/0x154
  ufshcd_pltfrm_runtime_suspend+0x14/0x20
  pm_generic_runtime_suspend+0x28/0x3c
  __rpm_callback+0x80/0x2a4
  rpm_suspend+0x308/0x614
  rpm_idle+0x158/0x228
  pm_runtime_work+0x84/0xac
  process_one_work+0x1f0/0x470
  worker_thread+0x26c/0x4c8
  kthread+0x13c/0x320
  ret_from_fork+0x10/0x18

Fix this by registering ufs device wlun as a scsi driver and
registering it for block runtime-pm. Also make this as a
supplier for all other luns. That way, this device wlun
suspends after all the consumers and resumes after
hba resumes.


I haven't had time to try to reproduce the device-links issue, but
there are a couple of comments below, in addition to the suggestions
here:

https://lore.kernel.org/linux-scsi/b13086f3-eea1-51a7-2117-579d520f2...@intel.com/

Also, there are still ufshcd_err_handling_prepare()/unprepare()
and ufshcd_recover_pm_error(), that look like they need attention
e.g. to use scsi_autopm_get/put_device(hba->sdev_ufs_device)



Hi Adrian,
Thanks for the suggestions and review.

Sorry I'd missed this mail.

Let me go through it and I'll get back.



Co-developed-by: Can Guo 
Signed-off-by: Can Guo 
Signed-off-by: Asutosh Das 
---
  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
  drivers/scsi/ufs/ufs-debugfs.c |   5 +
  drivers/scsi/ufs/ufs-debugfs.h |   2 +
  drivers/scsi/ufs/ufs-exynos.c  |   2 +
  drivers/scsi/ufs/ufs-hisi.c|   2 +
  drivers/scsi/ufs/ufs-mediatek.c|   2 +
  drivers/scsi/ufs/ufs-qcom.c|   2 +
  drivers/scsi/ufs/ufs_bsg.c |   6 +-
  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
  drivers/scsi/ufs/ufshcd.c  | 616 ++---
  drivers/scsi/ufs/ufshcd.h  |   7 +
  include/trace/events/ufs.h |  20 ++
  13 files changed, 498 insertions(+), 206 deletions(-)

diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
index 149391f..3e70c23 100644
--- a/drivers/scsi/ufs/cdns-pltfrm.c
+++ b/drivers/scsi/ufs/cdns-pltfrm.c
@@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
.runtime_suspend = ufshcd_pltfrm_runtime_suspend,
.runtime_resume  = ufshcd_pltfrm_runtime_resume,
.runtime_idle= ufshcd_pltfrm_runtime_idle,
+   .prepare = ufshcd_suspend_prepare,
+   .complete   = ufshcd_resume_complete,
  };
  
  static struct platform_driver cdns_ufs_pltfrm_driver = {

diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index 67a6a61..b01db12 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
.runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
.runtime_resume  = tc_dwc_g210_pci_runtime_resume,
.runtime_idle= tc_dwc_g210_pci_runtime_idle,
+   .prepare = ufshcd_suspend_prepare,
+   .complete   = ufshcd_resume_complete,
  };
  
  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index dee98dc..f8ce2eb 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -54,3 +54,8 @@ void ufs_debugfs_hba_exit(struct ufs_hba *hba)
  {
debugfs_remove_recursive(hba->debugfs_root);
  }
+
+void ufs_debugfs_eh_exit(void)
+{
+   debugfs_remove_recursive(ufs_debugfs_root);
+}


This is the same as ufs_debugfs_exit() without __exit so why not
remove __exit from ufs_debugfs_exit() and use that instead?


diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index f35b39c..3fce5a0 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
  void __exit ufs_debugfs_exit(void);
  void ufs_debugfs_hba_init(struct ufs_hba *hba);
  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
+void ufs_debugfs_eh_exit(void);
  #else
  static inline void ufs_debugfs_init(void) {}
  static inline void ufs_debugfs_exit(void) {}
  static inline void u

Re: [PATCH v11 1/2] scsi: ufs: Enable power management for wlun

2021-03-15 Thread Adrian Hunter
On 12/03/21 12:19 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.

I haven't had time to try to reproduce the device-links issue, but
there are a couple of comments below, in addition to the suggestions
here:

https://lore.kernel.org/linux-scsi/b13086f3-eea1-51a7-2117-579d520f2...@intel.com/

Also, there are still ufshcd_err_handling_prepare()/unprepare()
and ufshcd_recover_pm_error(), that look like they need attention
e.g. to use scsi_autopm_get/put_device(hba->sdev_ufs_device)


> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-debugfs.c |   5 +
>  drivers/scsi/ufs/ufs-debugfs.h |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>  drivers/scsi/ufs/ufshcd.c  | 616 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  13 files changed, 498 insertions(+), 206 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
> index dee98dc..f8ce2eb 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.c
> +++ b/drivers/scsi/ufs/ufs-debugfs.c
> @@ -54,3 +54,8 @@ void ufs_debugfs_hba_exit(struct ufs_hba *hba)
>  {
>   debugfs_remove_recursive(hba->debugfs_root);
>  }
> +
> +void ufs_debugfs_eh_exit(void)
> +{
> + debugfs_remove_recursive(ufs_debugfs_root);
> +}

This is the same as ufs_debugfs_exit() without __exit so why not
remove __exit from ufs_debugfs_exit() and use that instead?

> diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
> index f35b39c..3fce5a0 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.h
> +++ b/drivers/scsi/ufs/ufs-debugfs.h
> @@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
>  void __exit ufs_debugfs_exit(void);
>  void ufs_debugfs_hba_init(struct ufs_hba *hba);
>  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
> +void ufs_debugfs_eh_exit(void);
>  #else
>  static inline void ufs_debugfs_init(void) {}
>  static inline void ufs_debugfs_exit(void) {}
>  static inline void ufs_debugfs_hba_init(stru

Re: [PATCH v11 1/2] scsi: ufs: Enable power management for wlun

2021-03-12 Thread Jaegeuk Kim
On 03/11, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-debugfs.c |   5 +
>  drivers/scsi/ufs/ufs-debugfs.h |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>  drivers/scsi/ufs/ufshcd.c  | 616 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  13 files changed, 498 insertions(+), 206 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
> index dee98dc..f8ce2eb 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.c
> +++ b/drivers/scsi/ufs/ufs-debugfs.c
> @@ -54,3 +54,8 @@ void ufs_debugfs_hba_exit(struct ufs_hba *hba)
>  {
>   debugfs_remove_recursive(hba->debugfs_root);
>  }
> +
> +void ufs_debugfs_eh_exit(void)
> +{
> + debugfs_remove_recursive(ufs_debugfs_root);
> +}
> diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
> index f35b39c..3fce5a0 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.h
> +++ b/drivers/scsi/ufs/ufs-debugfs.h
> @@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
>  void __exit ufs_debugfs_exit(void);
>  void ufs_debugfs_hba_init(struct ufs_hba *hba);
>  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
> +void ufs_debugfs_eh_exit(void);
>  #else
>  static inline void ufs_debugfs_init(void) {}
>  static inline void ufs_debugfs_exit(void) {}
>  static inline void ufs_debugfs_hba_init(struct ufs_hba *hba) {}
>  static inline void ufs_debugfs_hba_exit(struct ufs_hba *hba) {}
> +static inline void ufs_debugfs_eh_exit(void) {}
>  #endif
>  
>  #endif
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idl