Skip to content

Commit bb44826

Browse files
ahunter6martinkpetersen
authored andcommitted
scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers
Intel platforms with UFS, can support Suspend-to-Idle (S0ix) and Suspend-to-RAM (S3). For S0ix the link state should be HIBERNATE. For S3, state is lost, so the link state must be OFF. Driver policy, expressed by spm_lvl, can be 3 (link HIBERNATE, device SLEEP) for S0ix but must be changed to 5 (link OFF, device POWEROFF) for S3. Fix support for S0ix/S3 by switching spm_lvl as needed. During suspend ->prepare(), if the suspend target state is not Suspend-to-Idle, ensure the spm_lvl is at least 5 to ensure that resume will be possible from deep sleep states. During suspend ->complete(), restore the spm_lvl to its original value that is suitable for S0ix. This fix is first needed in Intel Alder Lake based controllers. Fixes: 7dc9fb4 ("scsi: ufs: ufs-pci: Add support for Intel ADL") Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Link: https://patch.msgid.link/20251024085918.31825-2-adrian.hunter@intel.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent f838d62 commit bb44826

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

drivers/ufs/host/ufshcd-pci.c

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/pci.h>
1616
#include <linux/pm_runtime.h>
1717
#include <linux/pm_qos.h>
18+
#include <linux/suspend.h>
1819
#include <linux/debugfs.h>
1920
#include <linux/uuid.h>
2021
#include <linux/acpi.h>
@@ -31,6 +32,7 @@ struct intel_host {
3132
u32 dsm_fns;
3233
u32 active_ltr;
3334
u32 idle_ltr;
35+
int saved_spm_lvl;
3436
struct dentry *debugfs_root;
3537
struct gpio_desc *reset_gpio;
3638
};
@@ -347,6 +349,7 @@ static int ufs_intel_common_init(struct ufs_hba *hba)
347349
host = devm_kzalloc(hba->dev, sizeof(*host), GFP_KERNEL);
348350
if (!host)
349351
return -ENOMEM;
352+
host->saved_spm_lvl = -1;
350353
ufshcd_set_variant(hba, host);
351354
intel_dsm_init(host, hba->dev);
352355
if (INTEL_DSM_SUPPORTED(host, RESET)) {
@@ -538,6 +541,66 @@ static int ufshcd_pci_restore(struct device *dev)
538541

539542
return ufshcd_system_resume(dev);
540543
}
544+
545+
static int ufs_intel_suspend_prepare(struct device *dev)
546+
{
547+
struct ufs_hba *hba = dev_get_drvdata(dev);
548+
struct intel_host *host = ufshcd_get_variant(hba);
549+
int err;
550+
551+
/*
552+
* Only s2idle (S0ix) retains link state. Force power-off
553+
* (UFS_PM_LVL_5) for any other case.
554+
*/
555+
if (pm_suspend_target_state != PM_SUSPEND_TO_IDLE && hba->spm_lvl < UFS_PM_LVL_5) {
556+
host->saved_spm_lvl = hba->spm_lvl;
557+
hba->spm_lvl = UFS_PM_LVL_5;
558+
}
559+
560+
err = ufshcd_suspend_prepare(dev);
561+
562+
if (err < 0 && host->saved_spm_lvl != -1) {
563+
hba->spm_lvl = host->saved_spm_lvl;
564+
host->saved_spm_lvl = -1;
565+
}
566+
567+
return err;
568+
}
569+
570+
static void ufs_intel_resume_complete(struct device *dev)
571+
{
572+
struct ufs_hba *hba = dev_get_drvdata(dev);
573+
struct intel_host *host = ufshcd_get_variant(hba);
574+
575+
ufshcd_resume_complete(dev);
576+
577+
if (host->saved_spm_lvl != -1) {
578+
hba->spm_lvl = host->saved_spm_lvl;
579+
host->saved_spm_lvl = -1;
580+
}
581+
}
582+
583+
static int ufshcd_pci_suspend_prepare(struct device *dev)
584+
{
585+
struct ufs_hba *hba = dev_get_drvdata(dev);
586+
587+
if (!strcmp(hba->vops->name, "intel-pci"))
588+
return ufs_intel_suspend_prepare(dev);
589+
590+
return ufshcd_suspend_prepare(dev);
591+
}
592+
593+
static void ufshcd_pci_resume_complete(struct device *dev)
594+
{
595+
struct ufs_hba *hba = dev_get_drvdata(dev);
596+
597+
if (!strcmp(hba->vops->name, "intel-pci")) {
598+
ufs_intel_resume_complete(dev);
599+
return;
600+
}
601+
602+
ufshcd_resume_complete(dev);
603+
}
541604
#endif
542605

543606
/**
@@ -611,8 +674,8 @@ static const struct dev_pm_ops ufshcd_pci_pm_ops = {
611674
.thaw = ufshcd_system_resume,
612675
.poweroff = ufshcd_system_suspend,
613676
.restore = ufshcd_pci_restore,
614-
.prepare = ufshcd_suspend_prepare,
615-
.complete = ufshcd_resume_complete,
677+
.prepare = ufshcd_pci_suspend_prepare,
678+
.complete = ufshcd_pci_resume_complete,
616679
#endif
617680
};
618681

0 commit comments

Comments
 (0)