diff mbox series

[1/1] scsi: ufs-pci: Force a full restore after suspend-to-disk

Message ID 20211012125914.21977-2-adrian.hunter@intel.com (mailing list archive)
State Superseded
Headers show
Series scsi: ufs-pci: Force a full restore after suspend-to-disk | expand

Commit Message

Adrian Hunter Oct. 12, 2021, 12:59 p.m. UTC
Implement the ->restore() PM operation and set the link to off, which
will force a full reset and restore.  This ensures that Host Performance
Booster is reset after suspend-to-disk.

The Host Performance Booster feature caches logical-to-physical mapping
information in the host memory.  After suspend-to-disk, such information
is not valid, so a full reset and restore is needed.

A full reset and restore is done if the SPM level is 5 or 6, but not for
other SPM levels, so this change fixes those cases.

A full reset and restore also restores base address registers, so that
code is removed.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/scsi/ufs/ufshcd-pci.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

Comments

Avri Altman Oct. 14, 2021, 6:15 a.m. UTC | #1
> Implement the ->restore() PM operation and set the link to off, which
> will force a full reset and restore.  This ensures that Host Performance
> Booster is reset after suspend-to-disk.
> 
> The Host Performance Booster feature caches logical-to-physical mapping
> information in the host memory.  After suspend-to-disk, such information
> is not valid, so a full reset and restore is needed.
> 
> A full reset and restore is done if the SPM level is 5 or 6, but not for
> other SPM levels, so this change fixes those cases.
It is perfectly fine for you to do that on your platform, if you choose so - 
Hence my reviewed-by.
But the reasoning is a bit odd, because you already set SSU4 for your spm-lvl,
And on SSU3 the device does not dump its internal tables.

Thanks,
Avri

> A full reset and restore also restores base address registers, so that
> code is removed.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Adrian Hunter Oct. 14, 2021, 6:37 a.m. UTC | #2
On 14/10/2021 09:15, Avri Altman wrote:
>  
>> Implement the ->restore() PM operation and set the link to off, which
>> will force a full reset and restore.  This ensures that Host Performance
>> Booster is reset after suspend-to-disk.
>>
>> The Host Performance Booster feature caches logical-to-physical mapping
>> information in the host memory.  After suspend-to-disk, such information
>> is not valid, so a full reset and restore is needed.
>>
>> A full reset and restore is done if the SPM level is 5 or 6, but not for
>> other SPM levels, so this change fixes those cases.
> It is perfectly fine for you to do that on your platform, if you choose so - 
> Hence my reviewed-by.
> But the reasoning is a bit odd, because you already set SSU4 for your spm-lvl,
> And on SSU3 the device does not dump its internal tables.

Hibernation flow is:

	->freeze()
	create memory image
	->thaw()
	write image
	->poweroff()

	time passes
	someone presses the power button or something else activates the machine

	kernel boots
	detects restore image
	read image
	->freeze()
	restore memory image
	->restore()

It is up to ->restore() to ensure the device state matches the
memory state as it was when the hibernation image was made.

> 
> Thanks,
> Avri
> 
>> A full reset and restore also restores base address registers, so that
>> code is removed.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> Reviewed-by: Avri Altman <avri.altman@wdc.com>
>
Avri Altman Oct. 14, 2021, 7:14 a.m. UTC | #3
> On 14/10/2021 09:15, Avri Altman wrote:
> >
> >> Implement the ->restore() PM operation and set the link to off, which
> >> will force a full reset and restore.  This ensures that Host
> >> Performance Booster is reset after suspend-to-disk.
> >>
> >> The Host Performance Booster feature caches logical-to-physical
> >> mapping information in the host memory.  After suspend-to-disk, such
> >> information is not valid, so a full reset and restore is needed.
> >>
> >> A full reset and restore is done if the SPM level is 5 or 6, but not
> >> for other SPM levels, so this change fixes those cases.
> > It is perfectly fine for you to do that on your platform, if you
> > choose so - Hence my reviewed-by.
> > But the reasoning is a bit odd, because you already set SSU4 for your
> > spm-lvl, And on SSU3 the device does not dump its internal tables.
> 
> Hibernation flow is:
> 
>         ->freeze()
>         create memory image
>         ->thaw()
>         write image
>         ->poweroff()
> 
>         time passes
>         someone presses the power button or something else activates the
> machine
> 
>         kernel boots
>         detects restore image
>         read image
>         ->freeze()
>         restore memory image
>         ->restore()
> 
> It is up to ->restore() to ensure the device state matches the memory state as it
> was when the hibernation image was made.
Oh, ok.  I missed the poweroff part before.

Thanks,
Avri

> 
> >
> > Thanks,
> > Avri
> >
> >> A full reset and restore also restores base address registers, so
> >> that code is removed.
> >>
> >> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> > Reviewed-by: Avri Altman <avri.altman@wdc.com>
> >
Martin K. Petersen Oct. 17, 2021, 2:05 a.m. UTC | #4
Adrian,

> Implement the ->restore() PM operation and set the link to off, which
> will force a full reset and restore.  This ensures that Host
> Performance Booster is reset after suspend-to-disk.

Applied to 5.16/scsi-staging, thanks!
diff mbox series

Patch

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 149c1aa09103..d65e6cd7a28d 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -370,20 +370,6 @@  static void ufs_intel_common_exit(struct ufs_hba *hba)
 
 static int ufs_intel_resume(struct ufs_hba *hba, enum ufs_pm_op op)
 {
-	/*
-	 * To support S4 (suspend-to-disk) with spm_lvl other than 5, the base
-	 * address registers must be restored because the restore kernel can
-	 * have used different addresses.
-	 */
-	ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
-		      REG_UTP_TRANSFER_REQ_LIST_BASE_L);
-	ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
-		      REG_UTP_TRANSFER_REQ_LIST_BASE_H);
-	ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
-		      REG_UTP_TASK_REQ_LIST_BASE_L);
-	ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
-		      REG_UTP_TASK_REQ_LIST_BASE_H);
-
 	if (ufshcd_is_link_hibern8(hba)) {
 		int ret = ufshcd_uic_hibern8_exit(hba);
 
@@ -463,6 +449,16 @@  static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = {
 	.device_reset		= ufs_intel_device_reset,
 };
 
+static int ufshcd_pci_restore(struct device *dev)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	/* Force a full reset and restore */
+	ufshcd_set_link_off(hba);
+
+	return ufshcd_system_resume(dev);
+}
+
 /**
  * ufshcd_pci_shutdown - main function to put the controller in reset state
  * @pdev: pointer to PCI device handle
@@ -546,9 +542,14 @@  ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 }
 
 static const struct dev_pm_ops ufshcd_pci_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
 	SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
 #ifdef CONFIG_PM_SLEEP
+	.suspend	= ufshcd_system_suspend,
+	.resume		= ufshcd_system_resume,
+	.freeze		= ufshcd_system_suspend,
+	.thaw		= ufshcd_system_resume,
+	.poweroff	= ufshcd_system_suspend,
+	.restore	= ufshcd_pci_restore,
 	.prepare	= ufshcd_suspend_prepare,
 	.complete	= ufshcd_resume_complete,
 #endif