--- /dev/null
+From 031491d508cde1c3e316b7c42e27f2d3a76d6155 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Jun 2021 13:40:17 -0500
+Subject: ACPI: Check StorageD3Enable _DSD property in ACPI code
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 2744d7a0733503931b71c00d156119ced002f22c ]
+
+Although first implemented for NVME, this check may be usable by
+other drivers as well. Microsoft's specification explicitly mentions
+that is may be usable by SATA and AHCI devices. Google also indicates
+that they have used this with SDHCI in a downstream kernel tree that
+a user can plug a storage device into.
+
+Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
+Suggested-by: Keith Busch <kbusch@kernel.org>
+CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
+CC: Alexander Deucher <Alexander.Deucher@amd.com>
+CC: Rafael J. Wysocki <rjw@rjwysocki.net>
+CC: Prike Liang <prike.liang@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Stable-dep-of: dad651b2a44e ("nvme-pci: do not set the NUMA node of device if it has none")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/device_pm.c | 29 +++++++++++++++++++++++++++++
+ drivers/nvme/host/pci.c | 28 +---------------------------
+ include/linux/acpi.h | 5 +++++
+ 3 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
+index ecd2ddc2215f5..66e53df758655 100644
+--- a/drivers/acpi/device_pm.c
++++ b/drivers/acpi/device_pm.c
+@@ -1326,4 +1326,33 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
+ return 1;
+ }
+ EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
++
++/**
++ * acpi_storage_d3 - Check if D3 should be used in the suspend path
++ * @dev: Device to check
++ *
++ * Return %true if the platform firmware wants @dev to be programmed
++ * into D3hot or D3cold (if supported) in the suspend path, or %false
++ * when there is no specific preference. On some platforms, if this
++ * hint is ignored, @dev may remain unresponsive after suspending the
++ * platform as a whole.
++ *
++ * Although the property has storage in the name it actually is
++ * applied to the PCIe slot and plugging in a non-storage device the
++ * same platform restrictions will likely apply.
++ */
++bool acpi_storage_d3(struct device *dev)
++{
++ struct acpi_device *adev = ACPI_COMPANION(dev);
++ u8 val;
++
++ if (!adev)
++ return false;
++ if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
++ &val))
++ return false;
++ return val == 1;
++}
++EXPORT_SYMBOL_GPL(acpi_storage_d3);
++
+ #endif /* CONFIG_PM */
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 3aaead9b3a570..e384ade6c2cd2 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -2840,32 +2840,6 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_ACPI
+-static bool nvme_acpi_storage_d3(struct pci_dev *dev)
+-{
+- struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
+- u8 val;
+-
+- /*
+- * Look for _DSD property specifying that the storage device on the port
+- * must use D3 to support deep platform power savings during
+- * suspend-to-idle.
+- */
+-
+- if (!adev)
+- return false;
+- if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
+- &val))
+- return false;
+- return val == 1;
+-}
+-#else
+-static inline bool nvme_acpi_storage_d3(struct pci_dev *dev)
+-{
+- return false;
+-}
+-#endif /* CONFIG_ACPI */
+-
+ static void nvme_async_probe(void *data, async_cookie_t cookie)
+ {
+ struct nvme_dev *dev = data;
+@@ -2915,7 +2889,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ quirks |= check_vendor_combination_bug(pdev);
+
+- if (!noacpi && nvme_acpi_storage_d3(pdev)) {
++ if (!noacpi && acpi_storage_d3(&pdev->dev)) {
+ /*
+ * Some systems use a bios work around to ask for D3 on
+ * platforms that support kernel managed suspend.
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 96d69404a54ff..9c184dbceba47 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -1001,6 +1001,7 @@ int acpi_dev_resume(struct device *dev);
+ int acpi_subsys_runtime_suspend(struct device *dev);
+ int acpi_subsys_runtime_resume(struct device *dev);
+ int acpi_dev_pm_attach(struct device *dev, bool power_on);
++bool acpi_storage_d3(struct device *dev);
+ #else
+ static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
+ static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
+@@ -1008,6 +1009,10 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
+ {
+ return 0;
+ }
++static inline bool acpi_storage_d3(struct device *dev)
++{
++ return false;
++}
+ #endif
+
+ #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)
+--
+2.40.1
+
--- /dev/null
+From 99c73f188166d539d89151ee74a23acceeb28f05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:52:49 +0200
+Subject: nvme-pci: do not set the NUMA node of device if it has none
+
+From: Pratyush Yadav <ptyadav@amazon.de>
+
+[ Upstream commit dad651b2a44eb6b201738f810254279dca29d30d ]
+
+If a device has no NUMA node information associated with it, the driver
+puts the device in node first_memory_node (say node 0). Not having a
+NUMA node and being associated with node 0 are completely different
+things and it makes little sense to mix the two.
+
+Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index c329f73dbbf38..7bb42d0e087af 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -2866,9 +2866,6 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
+ struct nvme_dev *dev;
+ int ret = -ENOMEM;
+
+- if (node == NUMA_NO_NODE)
+- set_dev_node(&pdev->dev, first_memory_node);
+-
+ dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
+ if (!dev)
+ return NULL;
+--
+2.40.1
+
--- /dev/null
+From 485aa08f8855896607533682cb1a4b5b62c40671 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Nov 2022 09:44:00 +0100
+Subject: nvme-pci: factor out a nvme_pci_alloc_dev helper
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 2e87570be9d2746e7c4e7ab1cc18fd3ca7de2768 ]
+
+Add a helper that allocates the nvme_dev structure up to the point where
+we can call nvme_init_ctrl. This pairs with the free_ctrl method and can
+thus be used to cleanup the teardown path and make it more symmetric.
+
+Note that this now calls nvme_init_ctrl a lot earlier during probing,
+which also means the per-controller character device shows up earlier.
+Due to the controller state no commnds can be send on it, but it might
+make sense to delay the cdev registration until nvme_init_ctrl_finish.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Tested-by Gerd Bayer <gbayer@linxu.ibm.com>
+Stable-dep-of: dad651b2a44e ("nvme-pci: do not set the NUMA node of device if it has none")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 81 +++++++++++++++++++++++------------------
+ 1 file changed, 46 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 48886355ce90c..c329f73dbbf38 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -2572,6 +2572,7 @@ static void nvme_free_tagset(struct nvme_dev *dev)
+ dev->ctrl.tagset = NULL;
+ }
+
++/* pairs with nvme_pci_alloc_dev */
+ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
+ {
+ struct nvme_dev *dev = to_nvme_dev(ctrl);
+@@ -2857,19 +2858,23 @@ static void nvme_async_probe(void *data, async_cookie_t cookie)
+ nvme_put_ctrl(&dev->ctrl);
+ }
+
+-static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
++ const struct pci_device_id *id)
+ {
+- int node, result = -ENOMEM;
+- struct nvme_dev *dev;
+ unsigned long quirks = id->driver_data;
++ int node = dev_to_node(&pdev->dev);
++ struct nvme_dev *dev;
++ int ret = -ENOMEM;
+
+- node = dev_to_node(&pdev->dev);
+ if (node == NUMA_NO_NODE)
+ set_dev_node(&pdev->dev, first_memory_node);
+
+ dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
+ if (!dev)
+- return -ENOMEM;
++ return NULL;
++ INIT_WORK(&dev->ctrl.reset_work, nvme_reset_work);
++ INIT_WORK(&dev->remove_work, nvme_remove_dead_ctrl_work);
++ mutex_init(&dev->shutdown_lock);
+
+ dev->nr_write_queues = write_queues;
+ dev->nr_poll_queues = poll_queues;
+@@ -2877,25 +2882,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ dev->queues = kcalloc_node(dev->nr_allocated_queues,
+ sizeof(struct nvme_queue), GFP_KERNEL, node);
+ if (!dev->queues)
+- goto free;
++ goto out_free_dev;
+
+ dev->dev = get_device(&pdev->dev);
+- pci_set_drvdata(pdev, dev);
+-
+- result = nvme_dev_map(dev);
+- if (result)
+- goto put_pci;
+-
+- INIT_WORK(&dev->ctrl.reset_work, nvme_reset_work);
+- INIT_WORK(&dev->remove_work, nvme_remove_dead_ctrl_work);
+- mutex_init(&dev->shutdown_lock);
+-
+- result = nvme_setup_prp_pools(dev);
+- if (result)
+- goto unmap;
+
+ quirks |= check_vendor_combination_bug(pdev);
+-
+ if (!noacpi && acpi_storage_d3(&pdev->dev)) {
+ /*
+ * Some systems use a bios work around to ask for D3 on
+@@ -2905,34 +2896,54 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ "platform quirk: setting simple suspend\n");
+ quirks |= NVME_QUIRK_SIMPLE_SUSPEND;
+ }
++ ret = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_pci_ctrl_ops,
++ quirks);
++ if (ret)
++ goto out_put_device;
++ return dev;
+
+- result = nvme_pci_alloc_iod_mempool(dev);
++out_put_device:
++ put_device(dev->dev);
++ kfree(dev->queues);
++out_free_dev:
++ kfree(dev);
++ return ERR_PTR(ret);
++}
++
++static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++ struct nvme_dev *dev;
++ int result = -ENOMEM;
++
++ dev = nvme_pci_alloc_dev(pdev, id);
++ if (!dev)
++ return -ENOMEM;
++
++ result = nvme_dev_map(dev);
+ if (result)
+- goto release_pools;
++ goto out_uninit_ctrl;
+
+- result = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_pci_ctrl_ops,
+- quirks);
++ result = nvme_setup_prp_pools(dev);
++ if (result)
++ goto out_dev_unmap;
++
++ result = nvme_pci_alloc_iod_mempool(dev);
+ if (result)
+- goto release_mempool;
++ goto out_release_prp_pools;
+
+ dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
++ pci_set_drvdata(pdev, dev);
+
+ nvme_reset_ctrl(&dev->ctrl);
+ async_schedule(nvme_async_probe, dev);
+-
+ return 0;
+
+- release_mempool:
+- mempool_destroy(dev->iod_mempool);
+- release_pools:
++out_release_prp_pools:
+ nvme_release_prp_pools(dev);
+- unmap:
++out_dev_unmap:
+ nvme_dev_unmap(dev);
+- put_pci:
+- put_device(dev->dev);
+- free:
+- kfree(dev->queues);
+- kfree(dev);
++out_uninit_ctrl:
++ nvme_uninit_ctrl(&dev->ctrl);
+ return result;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 285848a82984b70d9400557e4f69d066cfd712f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Nov 2022 09:41:41 +0100
+Subject: nvme-pci: factor the iod mempool creation into a helper
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 081a7d958ce4b65f9aab6e70e65b0b2e0b92297c ]
+
+Add a helper to create the iod mempool.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Tested-by Gerd Bayer <gbayer@linxu.ibm.com>
+Stable-dep-of: dad651b2a44e ("nvme-pci: do not set the NUMA node of device if it has none")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 41 ++++++++++++++++++-----------------------
+ 1 file changed, 18 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index e384ade6c2cd2..48886355ce90c 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -387,14 +387,6 @@ static int nvme_pci_npages_sgl(void)
+ NVME_CTRL_PAGE_SIZE);
+ }
+
+-static size_t nvme_pci_iod_alloc_size(void)
+-{
+- size_t npages = max(nvme_pci_npages_prp(), nvme_pci_npages_sgl());
+-
+- return sizeof(__le64 *) * npages +
+- sizeof(struct scatterlist) * NVME_MAX_SEGS;
+-}
+-
+ static int nvme_admin_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
+ unsigned int hctx_idx)
+ {
+@@ -2557,6 +2549,22 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
+ dma_pool_destroy(dev->prp_small_pool);
+ }
+
++static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
++{
++ size_t npages = max(nvme_pci_npages_prp(), nvme_pci_npages_sgl());
++ size_t alloc_size = sizeof(__le64 *) * npages +
++ sizeof(struct scatterlist) * NVME_MAX_SEGS;
++
++ WARN_ON_ONCE(alloc_size > PAGE_SIZE);
++ dev->iod_mempool = mempool_create_node(1,
++ mempool_kmalloc, mempool_kfree,
++ (void *)alloc_size, GFP_KERNEL,
++ dev_to_node(dev->dev));
++ if (!dev->iod_mempool)
++ return -ENOMEM;
++ return 0;
++}
++
+ static void nvme_free_tagset(struct nvme_dev *dev)
+ {
+ if (dev->tagset.tags)
+@@ -2854,7 +2862,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ int node, result = -ENOMEM;
+ struct nvme_dev *dev;
+ unsigned long quirks = id->driver_data;
+- size_t alloc_size;
+
+ node = dev_to_node(&pdev->dev);
+ if (node == NUMA_NO_NODE)
+@@ -2899,21 +2906,9 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ quirks |= NVME_QUIRK_SIMPLE_SUSPEND;
+ }
+
+- /*
+- * Double check that our mempool alloc size will cover the biggest
+- * command we support.
+- */
+- alloc_size = nvme_pci_iod_alloc_size();
+- WARN_ON_ONCE(alloc_size > PAGE_SIZE);
+-
+- dev->iod_mempool = mempool_create_node(1, mempool_kmalloc,
+- mempool_kfree,
+- (void *) alloc_size,
+- GFP_KERNEL, node);
+- if (!dev->iod_mempool) {
+- result = -ENOMEM;
++ result = nvme_pci_alloc_iod_mempool(dev);
++ if (result)
+ goto release_pools;
+- }
+
+ result = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_pci_ctrl_ops,
+ quirks);
+--
+2.40.1
+
sched-cpuacct-fix-charge-percpu-cpuusage.patch
sched-cpuacct-optimize-away-rcu-read-lock.patch
cgroup-fix-suspicious-rcu_dereference_check-usage-wa.patch
+acpi-check-storaged3enable-_dsd-property-in-acpi-cod.patch
+nvme-pci-factor-the-iod-mempool-creation-into-a-help.patch
+nvme-pci-factor-out-a-nvme_pci_alloc_dev-helper.patch
+nvme-pci-do-not-set-the-numa-node-of-device-if-it-ha.patch