146 lines
4.6 KiB
Diff
146 lines
4.6 KiB
Diff
From 689cde2d569ede2c591c49faaf5917e709033fad Mon Sep 17 00:00:00 2001
|
|
From: Jake Day <jake@ninebysix.com>
|
|
Date: Tue, 30 Apr 2019 20:40:30 -0400
|
|
Subject: [PATCH 02/12] suspend
|
|
|
|
---
|
|
drivers/nvme/host/nvme.h | 5 +++++
|
|
drivers/nvme/host/pci.c | 10 +++++++++-
|
|
drivers/pci/quirks.c | 4 ++++
|
|
include/linux/pci_ids.h | 2 ++
|
|
kernel/power/suspend.c | 11 +++++++++++
|
|
kernel/sysctl.c | 9 +++++++++
|
|
6 files changed, 40 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
|
|
index c4a1bb41abf0..5537c35ab677 100644
|
|
--- a/drivers/nvme/host/nvme.h
|
|
+++ b/drivers/nvme/host/nvme.h
|
|
@@ -95,6 +95,11 @@ enum nvme_quirks {
|
|
* Ignore device provided subnqn.
|
|
*/
|
|
NVME_QUIRK_IGNORE_DEV_SUBNQN = (1 << 8),
|
|
+
|
|
+ /*
|
|
+ * Do not disable nvme when suspending (s2idle)
|
|
+ */
|
|
+ NVME_QUIRK_NO_DISABLE = (1 << 9),
|
|
};
|
|
|
|
/*
|
|
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
|
|
index 7fee665ec45e..ebf615570787 100644
|
|
--- a/drivers/nvme/host/pci.c
|
|
+++ b/drivers/nvme/host/pci.c
|
|
@@ -31,6 +31,7 @@
|
|
#include <linux/io-64-nonatomic-lo-hi.h>
|
|
#include <linux/sed-opal.h>
|
|
#include <linux/pci-p2pdma.h>
|
|
+#include <linux/suspend.h>
|
|
|
|
#include "trace.h"
|
|
#include "nvme.h"
|
|
@@ -2896,8 +2897,11 @@ static int nvme_suspend(struct device *dev)
|
|
{
|
|
struct pci_dev *pdev = to_pci_dev(dev);
|
|
struct nvme_dev *ndev = pci_get_drvdata(pdev);
|
|
+ struct nvme_ctrl *ctrl = &ndev->ctrl;
|
|
+
|
|
+ if (!(pm_suspend_via_s2idle() && (ctrl->quirks & NVME_QUIRK_NO_DISABLE)))
|
|
+ nvme_dev_disable(ndev, true);
|
|
|
|
- nvme_dev_disable(ndev, true);
|
|
return 0;
|
|
}
|
|
|
|
@@ -3002,6 +3006,10 @@ static const struct pci_device_id nvme_id_table[] = {
|
|
.driver_data = NVME_QUIRK_LIGHTNVM, },
|
|
{ PCI_DEVICE(0x1d1d, 0x2601), /* CNEX Granby */
|
|
.driver_data = NVME_QUIRK_LIGHTNVM, },
|
|
+ { PCI_VDEVICE(SK_HYNIX, 0x1527), /* Sk Hynix */
|
|
+ .driver_data = NVME_QUIRK_NO_DISABLE, },
|
|
+ { PCI_VDEVICE(TOSHIBA, 0x010f), /* TOSHIBA NVMe found on Surface Book with Performance Base */
|
|
+ .driver_data = NVME_QUIRK_NO_DISABLE, },
|
|
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index fba03a7d5c7f..84e9fed12b55 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -1357,6 +1357,10 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID,
|
|
occur when mode detecting */
|
|
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
|
|
PCI_CLASS_STORAGE_IDE, 8, quirk_no_ata_d3);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SK_HYNIX, 0x1527, quirk_no_ata_d3);
|
|
+/* TOSHIBA NVMe disk found on Surface Book with Performance Base
|
|
+ cannot wakeup from D3 state after s2idle */
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TOSHIBA, 0x010f, quirk_no_ata_d3);
|
|
|
|
/*
|
|
* This was originally an Alpha-specific thing, but it really fits here.
|
|
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
|
|
index 5eaf39dbc388..20f4e40cf04a 100644
|
|
--- a/include/linux/pci_ids.h
|
|
+++ b/include/linux/pci_ids.h
|
|
@@ -3098,4 +3098,6 @@
|
|
|
|
#define PCI_VENDOR_ID_NCUBE 0x10ff
|
|
|
|
+#define PCI_VENDOR_ID_SK_HYNIX 0x1c5c
|
|
+
|
|
#endif /* _LINUX_PCI_IDS_H */
|
|
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
|
|
index 0bd595a0b610..a8385e8894a5 100644
|
|
--- a/kernel/power/suspend.c
|
|
+++ b/kernel/power/suspend.c
|
|
@@ -526,6 +526,8 @@ int suspend_devices_and_enter(suspend_state_t state)
|
|
goto Resume_devices;
|
|
}
|
|
|
|
+unsigned int resume_delay = 3000;
|
|
+
|
|
/**
|
|
* suspend_finish - Clean up before finishing the suspend sequence.
|
|
*
|
|
@@ -534,6 +536,15 @@ int suspend_devices_and_enter(suspend_state_t state)
|
|
*/
|
|
static void suspend_finish(void)
|
|
{
|
|
+ if (resume_delay) {
|
|
+ /* Give kernel threads a head start, such that usb-storage
|
|
+ * can detect devices before syslog attempts to write log
|
|
+ * messages from the suspend code.
|
|
+ */
|
|
+ thaw_kernel_threads();
|
|
+ pr_debug("PM: Sleeping for %d milliseconds.\n", resume_delay);
|
|
+ msleep(resume_delay);
|
|
+ }
|
|
suspend_thaw_processes();
|
|
pm_notifier_call_chain(PM_POST_SUSPEND);
|
|
pm_restore_console();
|
|
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
|
index f50f1471c119..eabfe9059ff6 100644
|
|
--- a/kernel/sysctl.c
|
|
+++ b/kernel/sysctl.c
|
|
@@ -314,7 +314,16 @@ static int min_extfrag_threshold;
|
|
static int max_extfrag_threshold = 1000;
|
|
#endif
|
|
|
|
+extern unsigned int resume_delay;
|
|
+
|
|
static struct ctl_table kern_table[] = {
|
|
+ {
|
|
+ .procname = "resume_delay",
|
|
+ .data = &resume_delay,
|
|
+ .maxlen = sizeof(unsigned int),
|
|
+ .mode = 0644,
|
|
+ .proc_handler = proc_dointvec,
|
|
+ },
|
|
{
|
|
.procname = "sched_child_runs_first",
|
|
.data = &sysctl_sched_child_runs_first,
|
|
--
|
|
2.19.1
|
|
|