linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers
@ 2025-10-22 18:08 Adrian Hunter
  2025-10-22 18:08 ` [PATCH 1/4] scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers Adrian Hunter
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Adrian Hunter @ 2025-10-22 18:08 UTC (permalink / raw)
  To: Martin K Petersen
  Cc: James EJ Bottomley, Bart Van Assche, Avri Altman, linux-scsi

Hi

Here are fixes related to power management on Intel host controllers,
primarily ones based on Intel Alder Lake.

Patches are based on 6.18/scsi-fixes


Adrian Hunter (4):
      scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers
      scsi: ufs: core: Add a quirk to suppress link_startup_again
      scsi: ufs: ufs-pci: Set UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN for Intel ADL
      scsi: ufs: core: Fix invalid probe error return value

 drivers/ufs/core/ufshcd.c     |  7 +++--
 drivers/ufs/host/ufshcd-pci.c | 70 +++++++++++++++++++++++++++++++++++++++++--
 include/ufs/ufshcd.h          |  7 +++++
 3 files changed, 78 insertions(+), 6 deletions(-)

base-commit: d54c676d4fe0543d1642ab7a68ffdd31e8639a5d


Regards
Adrian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers
  2025-10-22 18:08 [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers Adrian Hunter
@ 2025-10-22 18:08 ` Adrian Hunter
  2025-10-22 18:08 ` [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again Adrian Hunter
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2025-10-22 18:08 UTC (permalink / raw)
  To: Martin K Petersen
  Cc: James EJ Bottomley, Bart Van Assche, Avri Altman, linux-scsi

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: 7dc9fb47bc9a ("scsi: ufs: ufs-pci: Add support for Intel ADL")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/ufs/host/ufshcd-pci.c | 67 +++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c
index b87e03777395..89f88b693850 100644
--- a/drivers/ufs/host/ufshcd-pci.c
+++ b/drivers/ufs/host/ufshcd-pci.c
@@ -15,6 +15,7 @@
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_qos.h>
+#include <linux/suspend.h>
 #include <linux/debugfs.h>
 #include <linux/uuid.h>
 #include <linux/acpi.h>
@@ -31,6 +32,7 @@ struct intel_host {
 	u32		dsm_fns;
 	u32		active_ltr;
 	u32		idle_ltr;
+	int		saved_spm_lvl;
 	struct dentry	*debugfs_root;
 	struct gpio_desc *reset_gpio;
 };
@@ -347,6 +349,7 @@ static int ufs_intel_common_init(struct ufs_hba *hba)
 	host = devm_kzalloc(hba->dev, sizeof(*host), GFP_KERNEL);
 	if (!host)
 		return -ENOMEM;
+	host->saved_spm_lvl = -1;
 	ufshcd_set_variant(hba, host);
 	intel_dsm_init(host, hba->dev);
 	if (INTEL_DSM_SUPPORTED(host, RESET)) {
@@ -538,6 +541,66 @@ static int ufshcd_pci_restore(struct device *dev)
 
 	return ufshcd_system_resume(dev);
 }
+
+static int ufs_intel_suspend_prepare(struct device *dev)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	struct intel_host *host = ufshcd_get_variant(hba);
+	int err;
+
+	/*
+	 * Only s2idle (S0ix) retains link state.  Force power-off
+	 * (UFS_PM_LVL_5) for any other case.
+	 */
+	if (pm_suspend_target_state != PM_SUSPEND_TO_IDLE && hba->spm_lvl < UFS_PM_LVL_5) {
+		host->saved_spm_lvl = hba->spm_lvl;
+		hba->spm_lvl = UFS_PM_LVL_5;
+	}
+
+	err = ufshcd_suspend_prepare(dev);
+
+	if (err < 0 && host->saved_spm_lvl != -1) {
+		hba->spm_lvl = host->saved_spm_lvl;
+		host->saved_spm_lvl = -1;
+	}
+
+	return err;
+}
+
+static void ufs_intel_resume_complete(struct device *dev)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	struct intel_host *host = ufshcd_get_variant(hba);
+
+	ufshcd_resume_complete(dev);
+
+	if (host->saved_spm_lvl != -1) {
+		hba->spm_lvl = host->saved_spm_lvl;
+		host->saved_spm_lvl = -1;
+	}
+}
+
+static int ufshcd_pci_suspend_prepare(struct device *dev)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	if (!strcmp(hba->vops->name, "intel-pci"))
+		return ufs_intel_suspend_prepare(dev);
+
+	return ufshcd_suspend_prepare(dev);
+}
+
+static void ufshcd_pci_resume_complete(struct device *dev)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+
+	if (!strcmp(hba->vops->name, "intel-pci")) {
+		ufs_intel_resume_complete(dev);
+		return;
+	}
+
+	ufshcd_resume_complete(dev);
+}
 #endif
 
 /**
@@ -611,8 +674,8 @@ static const struct dev_pm_ops ufshcd_pci_pm_ops = {
 	.thaw		= ufshcd_system_resume,
 	.poweroff	= ufshcd_system_suspend,
 	.restore	= ufshcd_pci_restore,
-	.prepare	= ufshcd_suspend_prepare,
-	.complete	= ufshcd_resume_complete,
+	.prepare	= ufshcd_pci_suspend_prepare,
+	.complete	= ufshcd_pci_resume_complete,
 #endif
 };
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again
  2025-10-22 18:08 [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers Adrian Hunter
  2025-10-22 18:08 ` [PATCH 1/4] scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers Adrian Hunter
@ 2025-10-22 18:08 ` Adrian Hunter
  2025-10-22 19:35   ` Bart Van Assche
  2025-10-22 18:08 ` [PATCH 3/4] scsi: ufs: ufs-pci: Set UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN for Intel ADL Adrian Hunter
  2025-10-22 18:08 ` [PATCH 4/4] scsi: ufs: core: Fix invalid probe error return value Adrian Hunter
  3 siblings, 1 reply; 6+ messages in thread
From: Adrian Hunter @ 2025-10-22 18:08 UTC (permalink / raw)
  To: Martin K Petersen
  Cc: James EJ Bottomley, Bart Van Assche, Avri Altman, linux-scsi

ufshcd_link_startup() has a facility (link_startup_again) to issue
DME_LINKSTARTUP a 2nd time even though the 1st time was successful.

Some older hardware benefits from that, however the behaviour is
non-standard, and has been found to cause link startup to be
unreliable for some Intel Alder Lake based host controllers.

Add UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN to suppress link_startup_again, in
preparation for setting the quirk for affected controllers.

Fixes: 7dc9fb47bc9a ("scsi: ufs: ufs-pci: Add support for Intel ADL")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/ufs/core/ufshcd.c | 3 ++-
 include/ufs/ufshcd.h      | 7 +++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 9ca27de4767a..632b508d0edb 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -5066,7 +5066,8 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
 	 * If UFS device isn't active then we will have to issue link startup
 	 * 2 times to make sure the device state move to active.
 	 */
-	if (!ufshcd_is_ufs_dev_active(hba))
+	if (!(hba->quirks & UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN) &&
+	    !ufshcd_is_ufs_dev_active(hba))
 		link_startup_again = true;
 
 link_startup:
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 9425cfd9d00e..4157fbaebff6 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -688,6 +688,13 @@ enum ufshcd_quirks {
 	 * single doorbell mode.
 	 */
 	UFSHCD_QUIRK_BROKEN_LSDBS_CAP			= 1 << 25,
+
+	/*
+	 * This quirk indicates that DME_LINKSTARTUP should not be issued a 2nd
+	 * time (refer link_startup_again) after the 1st time was successful,
+	 * because it causes link startup to become unreliable.
+	 */
+	UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN		= 1 << 26,
 };
 
 enum ufshcd_caps {
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] scsi: ufs: ufs-pci: Set UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN for Intel ADL
  2025-10-22 18:08 [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers Adrian Hunter
  2025-10-22 18:08 ` [PATCH 1/4] scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers Adrian Hunter
  2025-10-22 18:08 ` [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again Adrian Hunter
@ 2025-10-22 18:08 ` Adrian Hunter
  2025-10-22 18:08 ` [PATCH 4/4] scsi: ufs: core: Fix invalid probe error return value Adrian Hunter
  3 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2025-10-22 18:08 UTC (permalink / raw)
  To: Martin K Petersen
  Cc: James EJ Bottomley, Bart Van Assche, Avri Altman, linux-scsi

Link startup becomes unreliable for Intel Alder Lake based host controllers
when a 2nd DME_LINKSTARTUP is issued unnecessarily.  Employ
UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN to suppress that from happening.

Fixes: 7dc9fb47bc9a ("scsi: ufs: ufs-pci: Add support for Intel ADL")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/ufs/host/ufshcd-pci.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c
index 89f88b693850..171a3cc58512 100644
--- a/drivers/ufs/host/ufshcd-pci.c
+++ b/drivers/ufs/host/ufshcd-pci.c
@@ -428,7 +428,8 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba)
 static int ufs_intel_adl_init(struct ufs_hba *hba)
 {
 	hba->nop_out_timeout = 200;
-	hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8;
+	hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 |
+		       UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN;
 	hba->caps |= UFSHCD_CAP_WB_EN;
 	return ufs_intel_common_init(hba);
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] scsi: ufs: core: Fix invalid probe error return value
  2025-10-22 18:08 [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers Adrian Hunter
                   ` (2 preceding siblings ...)
  2025-10-22 18:08 ` [PATCH 3/4] scsi: ufs: ufs-pci: Set UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN for Intel ADL Adrian Hunter
@ 2025-10-22 18:08 ` Adrian Hunter
  3 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2025-10-22 18:08 UTC (permalink / raw)
  To: Martin K Petersen
  Cc: James EJ Bottomley, Bart Van Assche, Avri Altman, linux-scsi

After DME Link Startup, the error return value is set to the MIPI UniPro
GenericErrorCode which can be 0 (SUCCESS) or 1 (FAILURE).  Upon failure
during driver probe, the error code 1 is propagated back to the driver
probe function which must return a negative value to indicate an error,
but 1 is not negative, so the probe is considered to be successful even
though it failed.  Subsequently, removing the driver results in an oops
because it is not in a valid state.

This happens because none of the callers of ufshcd_init() expect a
non-negative error code.

Fix the return value and documentation to match actual usage.

Fixes: 69f5eb78d4b0 ("scsi: ufs: core: Move the ufshcd_device_init(hba, true) call")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/ufs/core/ufshcd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 632b508d0edb..eafff8cfb2b6 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -10662,7 +10662,7 @@ static int ufshcd_add_scsi_host(struct ufs_hba *hba)
  * @mmio_base: base register address
  * @irq: Interrupt line of device
  *
- * Return: 0 on success, non-zero value on failure.
+ * Return: 0 on success; < 0 on failure.
  */
 int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 {
@@ -10903,7 +10903,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 	hba->is_irq_enabled = false;
 	ufshcd_hba_exit(hba);
 out_error:
-	return err;
+	return err > 0 ? -EIO : err;
 }
 EXPORT_SYMBOL_GPL(ufshcd_init);
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again
  2025-10-22 18:08 ` [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again Adrian Hunter
@ 2025-10-22 19:35   ` Bart Van Assche
  0 siblings, 0 replies; 6+ messages in thread
From: Bart Van Assche @ 2025-10-22 19:35 UTC (permalink / raw)
  To: Adrian Hunter, Martin K Petersen
  Cc: James EJ Bottomley, Avri Altman, linux-scsi

On 10/22/25 11:08 AM, Adrian Hunter wrote:
> +	/*
> +	 * This quirk indicates that DME_LINKSTARTUP should not be issued a 2nd
> +	 * time (refer link_startup_again) after the 1st time was successful,
> +	 * because it causes link startup to become unreliable.
> +	 */
> +	UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN		= 1 << 26,

UFSHCD_QUIRK_PERFORM_LINK_STARTUP_ONCE might be a better name since it
doesn't include a negation.

Thanks,

Bart.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-10-22 19:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-22 18:08 [PATCH 0/4] scsi: ufs: PM fixes Intel host controllers Adrian Hunter
2025-10-22 18:08 ` [PATCH 1/4] scsi: ufs: ufs-pci: Fix S0ix/S3 for Intel controllers Adrian Hunter
2025-10-22 18:08 ` [PATCH 2/4] scsi: ufs: core: Add a quirk to suppress link_startup_again Adrian Hunter
2025-10-22 19:35   ` Bart Van Assche
2025-10-22 18:08 ` [PATCH 3/4] scsi: ufs: ufs-pci: Set UFSHCD_QUIRK_NO_LINK_STARTUP_AGAIN for Intel ADL Adrian Hunter
2025-10-22 18:08 ` [PATCH 4/4] scsi: ufs: core: Fix invalid probe error return value Adrian Hunter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).