* [PATCH v5 00/12] VRAM Self Refresh
@ 2025-10-15 8:06 Badal Nilawar
2025-10-15 8:06 ` [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method Badal Nilawar
` (11 more replies)
0 siblings, 12 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:06 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
Changes in v5:
- Added Co-developed by, whereever necessary
- Addressed review comments
- Added new patch to handle vrsr in s2idle
drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state
Changes in v4:
- Resolved build warnings
Changes in v3:
PCIe ACPI Patches:
- dropped the notifier block code and added patch to allow only one Aux
power limit request per root port (Rafael J. Wysocki)
- Addressed Review comments (Rafael J. Wysocki, Bjorn Helgaas)
Xe Pacthes:
- Addressed Review comments (Bjorn Helgaas)
Anshuman Gupta (6):
PCI/ACPI: Add D3cold Aux Power Limit_DSM method
PCI/ACPI: Add PERST# Assertion Delay _DSM method
drm/xe/vrsr: Detect VRSR Capability
drm/xe/vrsr: Refactor d3cold.allowed to a enum
drm/xe/pm: D3cold target state
drm/xe/vrsr: Enable VRSR
Badal Nilawar (6):
PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit
request
drm/xe/vrsr: Introduce flag has_vrsr
drm/xe/vrsr: Initialize VRSR feature
drm/xe/vrsr: Enable VRSR on default VGA boot device
drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state
drm/xe/vrsr: Introduce a debugfs node named vrsr_capable
drivers/acpi/scan.c | 3 +
drivers/gpu/drm/i915/display/intel_display.c | 22 ++
drivers/gpu/drm/i915/display/intel_display.h | 1 +
drivers/gpu/drm/xe/display/xe_display.c | 11 +-
drivers/gpu/drm/xe/display/xe_display.h | 2 +
drivers/gpu/drm/xe/regs/xe_regs.h | 3 +
drivers/gpu/drm/xe/xe_debugfs.c | 3 +
drivers/gpu/drm/xe/xe_device_types.h | 12 +-
drivers/gpu/drm/xe/xe_pci.c | 12 +-
drivers/gpu/drm/xe/xe_pci_types.h | 1 +
drivers/gpu/drm/xe/xe_pcode_api.h | 7 +
drivers/gpu/drm/xe/xe_pm.c | 231 +++++++++++++++++--
drivers/gpu/drm/xe/xe_pm.h | 10 +-
drivers/pci/pci-acpi.c | 189 +++++++++++++++
include/acpi/acpi_bus.h | 3 +
include/linux/pci-acpi.h | 18 +-
16 files changed, 494 insertions(+), 34 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
@ 2025-10-15 8:06 ` Badal Nilawar
2025-10-27 19:03 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request Badal Nilawar
` (10 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:06 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Implement _DSM method 0Ah, as per PCI Firmware r3.3, sec 4.6.10,
to request auxiliary power required by the device when in D3cold state.
Note that this implementation assumes only a single device below the
Downstream Port will request for Aux Power Limit under a given
Root Port/Downstream Port because it does not track and aggregate
requests from all child devices below the Downstream Port as required
by PCI Firmware r3.3, sec 4.6.10.
Co-developed-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
V2(Bjorn/Rafael):
- Call acpi_dsm_check() to find method 0Ah supported
- Return retry interval to caller
V3(Kuppuswamy)
- Add NULL check for retry interval
V4
- Define enums for aux power request status (Rafael)
- Add Co-developed-by and clean up Signed-off-by (Kappuswamy)
(Bjorn)
- Instead of root pci device pass the pci device of driver, traverse
up the tree and discover _DSM
- Allow only function 0 of device to request aux power
- Allow retry_interval to be NULL
- Refine commit message and function description
---
drivers/pci/pci-acpi.c | 114 +++++++++++++++++++++++++++++++++++++++
include/linux/pci-acpi.h | 9 ++++
2 files changed, 123 insertions(+)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 9369377725fa..c7eab1e75dd5 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1418,6 +1418,120 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
ACPI_FREE(obj);
}
+static struct pci_dev *pci_acpi_check_dsm(struct pci_dev *dev, u64 rev, u64 funcs)
+{
+ struct pci_dev *bdev;
+ acpi_handle handle;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ bdev = dev;
+ while (bdev) {
+ handle = ACPI_HANDLE(&bdev->dev);
+ if (handle && acpi_check_dsm(handle, &pci_acpi_dsm_guid, rev, 1 << funcs))
+ return bdev;
+
+ bdev = pci_upstream_bridge(bdev);
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+enum aux_pwr_req_status {
+ AUX_PWR_REQ_DENIED = 0x0,
+ AUX_PWR_REQ_GRANTED = 0x1,
+ AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL = 0x2,
+ AUX_PWR_REQ_RETRY_INTERVAL_MIN = 0x11,
+ AUX_PWR_REQ_RETRY_INTERVAL_MAX = 0x1F
+};
+
+/**
+ * pci_acpi_request_d3cold_aux_power - Request aux power while device is in D3cold
+ * @dev: PCI device instance
+ * @requested_mw: Requested auxiliary power in milliwatts
+ * @retry_interval: Retry interval returned by platform to retry auxiliary
+ * power request
+ *
+ * Request auxilary power to platform firmware, via Root Port/Switch Downstream
+ * Port ACPI _DSM Function 0Ah, needed for the PCI device when it is in D3cold.
+ * Evaluate the _DSM and handle the response accordingly.
+ *
+ * For Multi-Function Devices, driver for Function 0 is required to report an
+ * aggregate power requirement covering all functions contained within the
+ * device.
+ *
+ * Note: Aggregation across multiple child devices beneath the Root/Switch Downstream
+ * Port is not supported.
+ *
+ * Return: Returns 0 on success and errno on failure.
+ */
+int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
+ u32 *retry_interval)
+{
+ union acpi_object in_obj = {
+ .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = requested_mw,
+ };
+
+ union acpi_object *out_obj;
+ int result, ret = -EINVAL;
+ struct pci_dev *bdev;
+
+ if (!dev || PCI_FUNC(dev->devfn) != 0)
+ return -EINVAL;
+
+ bdev = pci_acpi_check_dsm(dev, 4, 1 << DSM_PCI_D3COLD_AUX_POWER_LIMIT);
+
+ if (IS_ERR(bdev))
+ return PTR_ERR(bdev);
+
+ out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
+ &pci_acpi_dsm_guid, 4,
+ DSM_PCI_D3COLD_AUX_POWER_LIMIT,
+ &in_obj, ACPI_TYPE_INTEGER);
+ if (!out_obj)
+ return -EINVAL;
+
+ result = out_obj->integer.value;
+ if (retry_interval)
+ *retry_interval = 0;
+
+ switch (result) {
+ case AUX_PWR_REQ_DENIED:
+ pci_dbg(bdev, "D3cold Aux Power %u mW request denied\n",
+ requested_mw);
+ break;
+ case AUX_PWR_REQ_GRANTED:
+ pci_info(bdev, "D3cold Aux Power request granted: %u mW\n",
+ requested_mw);
+ ret = 0;
+ break;
+ case AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL:
+ pci_info(bdev, "D3cold Aux Power: Main power won't be removed\n");
+ ret = -EBUSY;
+ break;
+ default:
+ if (result >= AUX_PWR_REQ_RETRY_INTERVAL_MIN &&
+ result <= AUX_PWR_REQ_RETRY_INTERVAL_MAX) {
+ pci_info(bdev, "D3cold Aux Power request needs retry interval: %u seconds\n",
+ result & 0xF);
+ if (retry_interval) {
+ *retry_interval = result & 0xF;
+ ret = -EAGAIN;
+ }
+ } else {
+ pci_err(bdev, "D3cold Aux Power: Reserved or unsupported response: 0x%x\n",
+ result);
+ }
+ break;
+ }
+
+ ACPI_FREE(out_obj);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pci_acpi_request_d3cold_aux_power);
+
static void pci_acpi_set_external_facing(struct pci_dev *dev)
{
u8 val;
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 078225b514d4..ba48e7ddb360 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -121,6 +121,7 @@ extern const guid_t pci_acpi_dsm_guid;
#define DSM_PCI_DEVICE_NAME 0x07
#define DSM_PCI_POWER_ON_RESET_DELAY 0x08
#define DSM_PCI_DEVICE_READINESS_DURATIONS 0x09
+#define DSM_PCI_D3COLD_AUX_POWER_LIMIT 0x0A
#ifdef CONFIG_PCIE_EDR
void pci_acpi_add_edr_notifier(struct pci_dev *pdev);
@@ -132,10 +133,18 @@ static inline void pci_acpi_remove_edr_notifier(struct pci_dev *pdev) { }
int pci_acpi_set_companion_lookup_hook(struct acpi_device *(*func)(struct pci_dev *));
void pci_acpi_clear_companion_lookup_hook(void);
+int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
+ u32 *retry_interval);
#else /* CONFIG_ACPI */
static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
+static inline int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev,
+ u32 requested_mw,
+ u32 *retry_interval)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_ACPI */
#endif /* _PCI_ACPI_H_ */
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
2025-10-15 8:06 ` [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-27 19:11 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method Badal Nilawar
` (9 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
Since aggregation of auxiliary power across multiple devices under a
Root or Switch Downstream Port is not supported, allow only one device
is to request auxiliary power
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
V1:
- Use guard(mutex) for new mutex (Rafael)
- Add mutex_detroy (Ilpo Järvinen)
- %s/pci_warn/pci_info/ for -EAGAIN
- Allow the same device to re-request auxiliary power if it has already been granted
---
drivers/acpi/scan.c | 3 +++
drivers/pci/pci-acpi.c | 22 ++++++++++++++++++++++
include/acpi/acpi_bus.h | 3 +++
3 files changed, 28 insertions(+)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index ef16d58b2949..4573fb0f4f3e 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -518,6 +518,7 @@ static void acpi_device_release(struct device *dev)
acpi_free_properties(acpi_dev);
acpi_free_pnp_ids(&acpi_dev->pnp);
acpi_free_power_resources_lists(acpi_dev);
+ mutex_destroy(&acpi_dev->power.aux_pwr_lock);
kfree(acpi_dev);
}
@@ -746,6 +747,8 @@ int acpi_device_add(struct acpi_device *device)
INIT_LIST_HEAD(&device->physical_node_list);
INIT_LIST_HEAD(&device->del_list);
mutex_init(&device->physical_node_lock);
+ mutex_init(&device->power.aux_pwr_lock);
+ device->power.dev = NULL;
mutex_lock(&acpi_device_lock);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c7eab1e75dd5..74f118016b1d 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1477,6 +1477,7 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
union acpi_object *out_obj;
int result, ret = -EINVAL;
struct pci_dev *bdev;
+ struct acpi_device *adev;
if (!dev || PCI_FUNC(dev->devfn) != 0)
return -EINVAL;
@@ -1486,6 +1487,19 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
if (IS_ERR(bdev))
return PTR_ERR(bdev);
+ adev = ACPI_COMPANION(&bdev->dev);
+ if (!adev)
+ return -EINVAL;
+
+ guard(mutex)(&adev->power.aux_pwr_lock);
+
+ /* Check if aux power already granted to different device */
+ if (adev->power.dev && adev->power.dev != &dev->dev) {
+ pci_info(to_pci_dev(adev->power.dev), "D3cold Aux Power request already granted: %u mW\n",
+ adev->power.aux_power_limit);
+ return -EPERM;
+ }
+
out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
&pci_acpi_dsm_guid, 4,
DSM_PCI_D3COLD_AUX_POWER_LIMIT,
@@ -1501,14 +1515,20 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
case AUX_PWR_REQ_DENIED:
pci_dbg(bdev, "D3cold Aux Power %u mW request denied\n",
requested_mw);
+ adev->power.aux_power_limit = 0;
+ adev->power.dev = NULL;
break;
case AUX_PWR_REQ_GRANTED:
pci_info(bdev, "D3cold Aux Power request granted: %u mW\n",
requested_mw);
+ adev->power.aux_power_limit = requested_mw;
+ adev->power.dev = &dev->dev;
ret = 0;
break;
case AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL:
pci_info(bdev, "D3cold Aux Power: Main power won't be removed\n");
+ adev->power.aux_power_limit = 0;
+ adev->power.dev = NULL;
ret = -EBUSY;
break;
default:
@@ -1524,6 +1544,8 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
pci_err(bdev, "D3cold Aux Power: Reserved or unsupported response: 0x%x\n",
result);
}
+ adev->power.aux_power_limit = 0;
+ adev->power.dev = NULL;
break;
}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index aad1a95e6863..cfa0c7233f13 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -294,6 +294,9 @@ struct acpi_device_power {
struct acpi_device_power_flags flags;
struct acpi_device_power_state states[ACPI_D_STATE_COUNT]; /* Power states (D0-D3Cold) */
u8 state_for_enumeration; /* Deepest power state for enumeration */
+ u32 aux_power_limit; /* aux power limit granted by platform firmware */
+ struct device *dev; /* device to which aux power is granted */
+ struct mutex aux_pwr_lock; /* prevent concurrent aux power limit requests */
};
struct acpi_dep_data {
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
2025-10-15 8:06 ` [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-27 19:18 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 04/12] drm/xe/vrsr: Introduce flag has_vrsr Badal Nilawar
` (8 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Implement _DSM Method 0Bh as per PCI Firmware r3.3, sec 4.6.10.
Co-developed-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
V2:
- Call acpi_check_dsm() to find method 0Bh supported
V3(Kappuswamy/Rafael):
- %s/pci_warn/pci_info/ when PERST# Assertion Delay request fails
---
drivers/pci/pci-acpi.c | 53 ++++++++++++++++++++++++++++++++++++++++
include/linux/pci-acpi.h | 9 ++++++-
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 74f118016b1d..230077200ce8 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1554,6 +1554,59 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
}
EXPORT_SYMBOL_GPL(pci_acpi_request_d3cold_aux_power);
+/**
+ * pci_acpi_add_perst_assertion_delay - Request PERST# Delay via ACPI DSM
+ * @dev: PCI device instance
+ * @delay_us: Requested delay_us
+ *
+ * Request PERST# Assertion Delay to platform firmware, via Root Port/
+ * Switch Downstream Port ACPI _DSM Function 0Bh, for the specified
+ * PCI device.
+ * Evaluate the _DSM and handle the response accordingly.
+ *
+ * Return: returns 0 on success and errno on failure.
+ */
+int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev, u32 delay_us)
+{
+ union acpi_object in_obj = {
+ .integer.type = ACPI_TYPE_INTEGER,
+ .integer.value = delay_us,
+ };
+
+ union acpi_object *out_obj;
+ int result, ret = -EINVAL;
+ struct pci_dev *bdev;
+
+ if (!dev)
+ return -EINVAL;
+
+ bdev = pci_acpi_check_dsm(dev, 4, 1 << DSM_PCI_PERST_ASSERTION_DELAY);
+
+ if (IS_ERR(bdev))
+ return PTR_ERR(bdev);
+
+ out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
+ &pci_acpi_dsm_guid, 4,
+ DSM_PCI_PERST_ASSERTION_DELAY,
+ &in_obj, ACPI_TYPE_INTEGER);
+ if (!out_obj)
+ return -EINVAL;
+
+ result = out_obj->integer.value;
+
+ if (result == delay_us) {
+ pci_info(dev, "PERST# Assertion Delay set to %u microseconds\n", delay_us);
+ ret = 0;
+ } else {
+ pci_info(dev, "PERST# Assertion Delay request failed, using %u microseconds\n",
+ result);
+ }
+
+ ACPI_FREE(out_obj);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pci_acpi_add_perst_assertion_delay);
+
static void pci_acpi_set_external_facing(struct pci_dev *dev)
{
u8 val;
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index ba48e7ddb360..4d8b8cea019e 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -122,6 +122,7 @@ extern const guid_t pci_acpi_dsm_guid;
#define DSM_PCI_POWER_ON_RESET_DELAY 0x08
#define DSM_PCI_DEVICE_READINESS_DURATIONS 0x09
#define DSM_PCI_D3COLD_AUX_POWER_LIMIT 0x0A
+#define DSM_PCI_PERST_ASSERTION_DELAY 0x0B
#ifdef CONFIG_PCIE_EDR
void pci_acpi_add_edr_notifier(struct pci_dev *pdev);
@@ -135,7 +136,7 @@ int pci_acpi_set_companion_lookup_hook(struct acpi_device *(*func)(struct pci_de
void pci_acpi_clear_companion_lookup_hook(void);
int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
u32 *retry_interval);
-
+int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev, u32 delay_us);
#else /* CONFIG_ACPI */
static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
@@ -145,6 +146,12 @@ static inline int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev,
{
return -EOPNOTSUPP;
}
+
+static inline int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev,
+ u32 delay_us)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_ACPI */
#endif /* _PCI_ACPI_H_ */
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 04/12] drm/xe/vrsr: Introduce flag has_vrsr
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (2 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 05/12] drm/xe/vrsr: Detect VRSR Capability Badal Nilawar
` (7 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
Introduce flag has_vrsr to determine if platform supports VRSR feature
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
---
drivers/gpu/drm/xe/xe_device_types.h | 2 ++
drivers/gpu/drm/xe/xe_pci.c | 2 ++
drivers/gpu/drm/xe/xe_pci_types.h | 1 +
3 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 02c04ad7296e..7fbdb5545946 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -313,6 +313,8 @@ struct xe_device {
u8 has_sriov:1;
/** @info.has_usm: Device has unified shared memory support */
u8 has_usm:1;
+ /** @info.has_vrsr: Has capability to enter into VRAM self refresh */
+ u8 has_vrsr:1;
/** @info.has_64bit_timestamp: Device supports 64-bit timestamps */
u8 has_64bit_timestamp:1;
/** @info.is_dgfx: is discrete device */
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 24a38904bb50..0cc14ddd92de 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -350,6 +350,7 @@ static const struct xe_device_desc bmg_desc = {
.has_heci_cscfi = 1,
.has_late_bind = true,
.has_sriov = true,
+ .has_vrsr = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.subplatforms = (const struct xe_subplatform_desc[]) {
@@ -633,6 +634,7 @@ static int xe_info_init_early(struct xe_device *xe,
xe->info.has_pxp = desc->has_pxp;
xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) &&
desc->has_sriov;
+ xe->info.has_vrsr = desc->has_vrsr;
xe->info.skip_guc_pc = desc->skip_guc_pc;
xe->info.skip_mtcfg = desc->skip_mtcfg;
xe->info.skip_pcode = desc->skip_pcode;
diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
index a4451bdc79fb..ad5b024ede1e 100644
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@ -48,6 +48,7 @@ struct xe_device_desc {
u8 has_mbx_power_limits:1;
u8 has_pxp:1;
u8 has_sriov:1;
+ u8 has_vrsr:1;
u8 needs_scratch:1;
u8 skip_guc_pc:1;
u8 skip_mtcfg:1;
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 05/12] drm/xe/vrsr: Detect VRSR Capability
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (3 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 04/12] drm/xe/vrsr: Introduce flag has_vrsr Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 06/12] drm/xe/vrsr: Initialize VRSR feature Badal Nilawar
` (6 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Detect VRAM Self Refresh(vrsr) Capability.
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
drivers/gpu/drm/xe/regs/xe_regs.h | 3 +++
drivers/gpu/drm/xe/xe_device_types.h | 4 ++++
drivers/gpu/drm/xe/xe_pm.c | 26 ++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h b/drivers/gpu/drm/xe/regs/xe_regs.h
index 1926b4044314..5fe114e6bd51 100644
--- a/drivers/gpu/drm/xe/regs/xe_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_regs.h
@@ -55,6 +55,9 @@
#define MTL_MPE_FREQUENCY XE_REG(0x13802c)
#define MTL_RPE_MASK REG_GENMASK(8, 0)
+#define VRAM_SR_CAPABILITY XE_REG(0x138144)
+#define VRAM_SR_SUPPORTED REG_BIT(0)
+
#define VF_CAP_REG XE_REG(0x1901f8, XE_REG_OPTION_VF)
#define VF_CAP REG_BIT(0)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 7fbdb5545946..d94fee10d041 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -512,6 +512,9 @@ struct xe_device {
/** @d3cold.allowed: Indicates if d3cold is a valid device state */
bool allowed;
+ /** @d3cold.vrsr_capable: Indicates if d3cold VRAM Self Refresh is supported */
+ bool vrsr_capable;
+
/**
* @d3cold.vram_threshold:
*
@@ -522,6 +525,7 @@ struct xe_device {
* Default threshold value is 300mb.
*/
u32 vram_threshold;
+
/** @d3cold.lock: protect vram_threshold */
struct mutex lock;
} d3cold;
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index 210298c4bcb1..b9cd48359e6f 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -13,15 +13,18 @@
#include <drm/ttm/ttm_placement.h>
#include "display/xe_display.h"
+#include "regs/xe_regs.h"
#include "xe_bo.h"
#include "xe_bo_evict.h"
#include "xe_device.h"
+#include "xe_force_wake.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
#include "xe_gt_idle.h"
#include "xe_i2c.h"
#include "xe_irq.h"
#include "xe_late_bind_fw.h"
+#include "xe_mmio.h"
#include "xe_pcode.h"
#include "xe_pxp.h"
#include "xe_sriov_vf_ccs.h"
@@ -309,6 +312,28 @@ static bool xe_pm_pci_d3cold_capable(struct xe_device *xe)
return true;
}
+static bool xe_pm_vrsr_capable(struct xe_device *xe)
+{
+ struct xe_mmio *mmio = xe_root_tile_mmio(xe);
+ unsigned int fw_ref;
+ struct xe_gt *gt;
+ u32 val;
+
+ gt = xe_root_mmio_gt(xe);
+
+ if (!xe->info.probe_display)
+ return false;
+
+ fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
+ if (!fw_ref)
+ return false;
+
+ val = xe_mmio_read32(mmio, VRAM_SR_CAPABILITY);
+ xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
+
+ return val & VRAM_SR_SUPPORTED;
+}
+
static void xe_pm_runtime_init(struct xe_device *xe)
{
struct device *dev = xe->drm.dev;
@@ -453,6 +478,7 @@ int xe_pm_init(struct xe_device *xe)
err = xe_pm_set_vram_threshold(xe, vram_threshold);
if (err)
goto err_unregister;
+ xe->d3cold.vrsr_capable = xe_pm_vrsr_capable(xe);
}
xe_pm_runtime_init(xe);
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 06/12] drm/xe/vrsr: Initialize VRSR feature
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (4 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 05/12] drm/xe/vrsr: Detect VRSR Capability Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 07/12] drm/xe/vrsr: Enable VRSR on default VGA boot device Badal Nilawar
` (5 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
Add the API xe_pm_vrsr_enable to initialize the VRSR feature,
requesting AUX power limit and PERST# assertion delay.
V2: Add retry mechanism while requesting AUX power limit
V3: Split xe_pm_vrsr_enable() into separate enable and
disable functions
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
V3:
- Drop unnecessary comments
---
drivers/gpu/drm/xe/xe_device_types.h | 1 +
drivers/gpu/drm/xe/xe_pcode_api.h | 7 ++
drivers/gpu/drm/xe/xe_pm.c | 110 ++++++++++++++++++++++++++-
drivers/gpu/drm/xe/xe_pm.h | 2 +
4 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index d94fee10d041..da81e1937918 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -7,6 +7,7 @@
#define _XE_DEVICE_TYPES_H_
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <drm/drm_device.h>
#include <drm/drm_file.h>
diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h
index 92bfcba51e19..c9922cf43c07 100644
--- a/drivers/gpu/drm/xe/xe_pcode_api.h
+++ b/drivers/gpu/drm/xe/xe_pcode_api.h
@@ -65,6 +65,13 @@
#define FAN_TABLE 1
#define VR_CONFIG 2
+#define PCODE_D3_VRAM_SELF_REFRESH 0x71
+#define PCODE_D3_VRSR_SC_DISABLE 0x0
+#define PCODE_D3_VRSR_SC_ENABLE 0x1
+#define PCODE_D3_VRSR_SC_AUX_PL_AND_PERST_DELAY 0x2
+#define POWER_D3_VRSR_PERST_MASK REG_GENMASK(31, 16)
+#define POWER_D3_VRSR_AUX_PL_MASK REG_GENMASK(15, 0)
+
#define PCODE_FREQUENCY_CONFIG 0x6e
/* Frequency Config Sub Commands (param1) */
#define PCODE_MBOX_FC_SC_READ_FUSED_P0 0x0
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index b9cd48359e6f..d95de9015ef5 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -5,6 +5,7 @@
#include "xe_pm.h"
+#include <linux/delay.h>
#include <linux/fault-inject.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
@@ -25,6 +26,7 @@
#include "xe_irq.h"
#include "xe_late_bind_fw.h"
#include "xe_mmio.h"
+#include "xe_pcode_api.h"
#include "xe_pcode.h"
#include "xe_pxp.h"
#include "xe_sriov_vf_ccs.h"
@@ -334,6 +336,112 @@ static bool xe_pm_vrsr_capable(struct xe_device *xe)
return val & VRAM_SR_SUPPORTED;
}
+static int pci_acpi_aux_power_setup(struct xe_device *xe)
+{
+ struct xe_tile *root_tile = xe_device_get_root_tile(xe);
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+ int ret;
+ u32 uval;
+ u32 aux_pwr_limit;
+ u32 retry_interval;
+ u32 perst_delay;
+
+ ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_D3_VRAM_SELF_REFRESH,
+ PCODE_D3_VRSR_SC_AUX_PL_AND_PERST_DELAY, 0),
+ &uval, NULL);
+ if (ret)
+ return ret;
+
+ aux_pwr_limit = REG_FIELD_GET(POWER_D3_VRSR_AUX_PL_MASK, uval);
+ perst_delay = REG_FIELD_GET(POWER_D3_VRSR_PERST_MASK, uval);
+
+ drm_dbg(&xe->drm, "Aux Power limit = %d mW\n", aux_pwr_limit);
+ drm_dbg(&xe->drm, "PERST# Assertion delay = %d microseconds\n", perst_delay);
+
+retry:
+ ret = pci_acpi_request_d3cold_aux_power(pdev, aux_pwr_limit, &retry_interval);
+
+ if (ret == -EAGAIN) {
+ drm_warn(&xe->drm, "D3cold Aux Power request needs retry interval: %d seconds\n",
+ retry_interval);
+ msleep(retry_interval * 1000);
+ goto retry;
+ }
+
+ if (ret)
+ return ret;
+
+ ret = pci_acpi_add_perst_assertion_delay(pdev, perst_delay);
+
+ return ret;
+}
+
+static void xe_pm_vrsr_init(struct xe_device *xe)
+{
+ int ret;
+
+ if (!xe->info.has_vrsr)
+ return;
+
+ if (!xe_pm_vrsr_capable(xe))
+ return;
+
+ /*
+ * If the VRSR initialization fails, the device will proceed with the regular
+ * D3cold flow
+ */
+ ret = pci_acpi_aux_power_setup(xe);
+ if (ret) {
+ drm_info(&xe->drm, "VRSR capable: No\n");
+ return;
+ }
+
+ xe->d3cold.vrsr_capable = true;
+ drm_info(&xe->drm, "VRSR capable: Yes\n");
+}
+
+/**
+ * xe_pm_vrsr_enable - Enable VRAM self refresh
+ * @xe: The xe device.
+ *
+ * Enable VRSR feature in D3cold path.
+ *
+ * Return: It returns 0 on success and errno on failure.
+ */
+int xe_pm_vrsr_enable(struct xe_device *xe)
+{
+ struct xe_tile *root_tile = xe_device_get_root_tile(xe);
+ int ret;
+
+ if (!xe->d3cold.vrsr_capable)
+ return -ENXIO;
+
+ drm_dbg(&xe->drm, "Enabling VRSR\n");
+
+ ret = xe_pcode_write(root_tile, PCODE_MBOX(PCODE_D3_VRAM_SELF_REFRESH,
+ PCODE_D3_VRSR_SC_ENABLE, 0), 0);
+ return ret;
+}
+
+/**
+ * xe_pm_vrsr_disable - Disable VRAM self refresh
+ * @xe: The xe device.
+ *
+ * Disable VRSR feature in D3cold path.
+ */
+void xe_pm_vrsr_disable(struct xe_device *xe)
+{
+ struct xe_tile *root_tile = xe_device_get_root_tile(xe);
+
+ if (!xe->d3cold.vrsr_capable)
+ return;
+
+ drm_dbg(&xe->drm, "Disabling VRSR\n");
+
+ xe_pcode_write(root_tile, PCODE_MBOX(PCODE_D3_VRAM_SELF_REFRESH,
+ PCODE_D3_VRSR_SC_DISABLE, 0), 0);
+}
+
static void xe_pm_runtime_init(struct xe_device *xe)
{
struct device *dev = xe->drm.dev;
@@ -478,7 +586,7 @@ int xe_pm_init(struct xe_device *xe)
err = xe_pm_set_vram_threshold(xe, vram_threshold);
if (err)
goto err_unregister;
- xe->d3cold.vrsr_capable = xe_pm_vrsr_capable(xe);
+ xe_pm_vrsr_init(xe);
}
xe_pm_runtime_init(xe);
diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h
index f7f89a18b6fc..3d5a8c4a4971 100644
--- a/drivers/gpu/drm/xe/xe_pm.h
+++ b/drivers/gpu/drm/xe/xe_pm.h
@@ -37,4 +37,6 @@ int xe_pm_block_on_suspend(struct xe_device *xe);
void xe_pm_might_block_on_suspend(void);
int xe_pm_module_init(void);
+int xe_pm_vrsr_enable(struct xe_device *xe);
+void xe_pm_vrsr_disable(struct xe_device *xe);
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 07/12] drm/xe/vrsr: Enable VRSR on default VGA boot device
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (5 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 06/12] drm/xe/vrsr: Initialize VRSR feature Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum Badal Nilawar
` (4 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
The VRSR feature is to enhance the display screen refresh experience
when the device exits from the D3cold state. Therefore, apply the VRSR
feature to the default VGA boot device and when a display is connected.
v2: Move generic display logic to i915/display (Jani)
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 22 ++++++++++++++++++++
drivers/gpu/drm/i915/display/intel_display.h | 1 +
drivers/gpu/drm/xe/display/xe_display.c | 5 +++++
drivers/gpu/drm/xe/display/xe_display.h | 2 ++
drivers/gpu/drm/xe/xe_pm.c | 5 +++++
5 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index d5b2612d4ec2..b974e7dc978d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8300,3 +8300,25 @@ bool intel_scanout_needs_vtd_wa(struct intel_display *display)
return IS_DISPLAY_VER(display, 6, 11) && i915_vtd_active(i915);
}
+
+bool intel_display_connected(struct intel_display *display)
+{
+ struct drm_connector *list_connector;
+ struct drm_connector_list_iter iter;
+ bool ret = false;
+
+ mutex_lock(&display->drm->mode_config.mutex);
+ drm_connector_list_iter_begin(display->drm, &iter);
+
+ drm_for_each_connector_iter(list_connector, &iter) {
+ if (list_connector->status == connector_status_connected) {
+ ret = true;
+ break;
+ }
+ }
+
+ drm_connector_list_iter_end(&iter);
+ mutex_unlock(&display->drm->mode_config.mutex);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index fc2ef92ccf68..78a479241c67 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -555,5 +555,6 @@ bool assert_port_valid(struct intel_display *display, enum port port);
bool intel_scanout_needs_vtd_wa(struct intel_display *display);
int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
+bool intel_display_connected(struct intel_display *display);
#endif
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index 47619bb8dc10..205040f43ddd 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -58,6 +58,11 @@ bool xe_display_driver_probe_defer(struct pci_dev *pdev)
return intel_display_driver_probe_defer(pdev);
}
+bool xe_display_connected(struct xe_device *xe)
+{
+ return intel_display_connected(xe->display);
+}
+
/**
* xe_display_driver_set_hooks - Add driver flags and hooks for display
* @driver: DRM device driver
diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h
index 76db95c25f7e..11d4b09808e5 100644
--- a/drivers/gpu/drm/xe/display/xe_display.h
+++ b/drivers/gpu/drm/xe/display/xe_display.h
@@ -37,6 +37,7 @@ void xe_display_pm_resume(struct xe_device *xe);
void xe_display_pm_runtime_suspend(struct xe_device *xe);
void xe_display_pm_runtime_suspend_late(struct xe_device *xe);
void xe_display_pm_runtime_resume(struct xe_device *xe);
+bool xe_display_connected(struct xe_device *xe);
#else
@@ -67,5 +68,6 @@ static inline void xe_display_pm_runtime_suspend(struct xe_device *xe) {}
static inline void xe_display_pm_runtime_suspend_late(struct xe_device *xe) {}
static inline void xe_display_pm_runtime_resume(struct xe_device *xe) {}
+static inline bool xe_display_connected(struct xe_device *xe) { return false; }
#endif /* CONFIG_DRM_XE_DISPLAY */
#endif /* _XE_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index d95de9015ef5..61466bf0bba6 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -9,6 +9,7 @@
#include <linux/fault-inject.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
+#include <linux/vgaarb.h>
#include <drm/drm_managed.h>
#include <drm/ttm/ttm_placement.h>
@@ -378,6 +379,7 @@ static int pci_acpi_aux_power_setup(struct xe_device *xe)
static void xe_pm_vrsr_init(struct xe_device *xe)
{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
int ret;
if (!xe->info.has_vrsr)
@@ -386,6 +388,9 @@ static void xe_pm_vrsr_init(struct xe_device *xe)
if (!xe_pm_vrsr_capable(xe))
return;
+ if (pdev != vga_default_device() || !xe_display_connected(xe))
+ return;
+
/*
* If the VRSR initialization fails, the device will proceed with the regular
* D3cold flow
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (6 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 07/12] drm/xe/vrsr: Enable VRSR on default VGA boot device Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:39 ` Raag Jadav
2025-10-15 8:07 ` [PATCH v5 09/12] drm/xe/pm: D3cold target state Badal Nilawar
` (3 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Add xe_d3_state enum to add support for VRAM Self Refresh
d3cold state.
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
---
V2: Rebased
---
drivers/gpu/drm/xe/display/xe_display.c | 6 +++---
drivers/gpu/drm/xe/xe_device_types.h | 5 +++--
drivers/gpu/drm/xe/xe_pci.c | 6 +++---
drivers/gpu/drm/xe/xe_pm.c | 21 +++++++++++----------
drivers/gpu/drm/xe/xe_pm.h | 8 +++++++-
5 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index 205040f43ddd..35d09109462e 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -395,7 +395,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe)
if (!xe->info.probe_display)
return;
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
xe_display_enable_d3cold(xe);
return;
}
@@ -421,7 +421,7 @@ void xe_display_pm_runtime_suspend_late(struct xe_device *xe)
if (!xe->info.probe_display)
return;
- if (xe->d3cold.allowed)
+ if (xe->d3cold.target_state)
xe_display_pm_suspend_late(xe);
/*
@@ -501,7 +501,7 @@ void xe_display_pm_runtime_resume(struct xe_device *xe)
if (!xe->info.probe_display)
return;
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
xe_display_disable_d3cold(xe);
return;
}
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index da81e1937918..a139f8aec33b 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -20,6 +20,7 @@
#include "xe_memirq_types.h"
#include "xe_oa_types.h"
#include "xe_platform_types.h"
+#include "xe_pm.h"
#include "xe_pmu_types.h"
#include "xe_pt_types.h"
#include "xe_sriov_pf_types.h"
@@ -510,8 +511,8 @@ struct xe_device {
/** @d3cold.capable: Indicates if root port is d3cold capable */
bool capable;
- /** @d3cold.allowed: Indicates if d3cold is a valid device state */
- bool allowed;
+ /** @d3cold.target_state: Indicates d3cold target state */
+ enum xe_d3_state target_state;
/** @d3cold.vrsr_capable: Indicates if d3cold VRAM Self Refresh is supported */
bool vrsr_capable;
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 0cc14ddd92de..eb60cf44c1d7 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1118,7 +1118,7 @@ static int xe_pci_runtime_suspend(struct device *dev)
pci_save_state(pdev);
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
d3cold_toggle(pdev, D3COLD_ENABLE);
pci_disable_device(pdev);
pci_ignore_hotplug(pdev);
@@ -1143,7 +1143,7 @@ static int xe_pci_runtime_resume(struct device *dev)
pci_restore_state(pdev);
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
err = pci_enable_device(pdev);
if (err)
return err;
@@ -1159,7 +1159,7 @@ static int xe_pci_runtime_idle(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
- xe_pm_d3cold_allowed_toggle(xe);
+ xe_pm_d3cold_target_state_toggle(xe);
return 0;
}
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index 61466bf0bba6..aa38dbe1e368 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -719,7 +719,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
xe_display_pm_runtime_suspend(xe);
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
err = xe_bo_evict_all(xe);
if (err)
goto out_resume;
@@ -771,7 +771,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
for_each_gt(gt, xe, id)
xe_gt_idle_disable_c6(gt);
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
err = xe_pcode_ready(xe, true);
if (err)
goto out;
@@ -787,7 +787,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
goto out;
}
- xe_i2c_pm_resume(xe, xe->d3cold.allowed);
+ if (xe->d3cold.target_state != XE_D3HOT)
+ xe_i2c_pm_resume(xe, true);
xe_irq_resume(xe);
@@ -796,7 +797,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
xe_display_pm_runtime_resume(xe);
- if (xe->d3cold.allowed) {
+ if (xe->d3cold.target_state) {
err = xe_bo_restore_late(xe);
if (err)
goto out;
@@ -807,7 +808,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
if (IS_VF_CCS_READY(xe))
xe_sriov_vf_ccs_register_context(xe);
- if (xe->d3cold.allowed)
+ if (xe->d3cold.target_state != XE_D3HOT)
xe_late_bind_fw_load(&xe->late_bind);
out:
@@ -1046,13 +1047,13 @@ int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold)
}
/**
- * xe_pm_d3cold_allowed_toggle - Check conditions to toggle d3cold.allowed
+ * xe_pm_d3cold_target_state_toggle - Check conditions to toggle target_state
* @xe: xe device instance
*
* To be called during runtime_pm idle callback.
* Check for all the D3Cold conditions ahead of runtime suspend.
*/
-void xe_pm_d3cold_allowed_toggle(struct xe_device *xe)
+void xe_pm_d3cold_target_state_toggle(struct xe_device *xe)
{
struct ttm_resource_manager *man;
u32 total_vram_used_mb = 0;
@@ -1060,7 +1061,7 @@ void xe_pm_d3cold_allowed_toggle(struct xe_device *xe)
int i;
if (!xe->d3cold.capable) {
- xe->d3cold.allowed = false;
+ xe->d3cold.target_state = XE_D3HOT;
return;
}
@@ -1075,9 +1076,9 @@ void xe_pm_d3cold_allowed_toggle(struct xe_device *xe)
mutex_lock(&xe->d3cold.lock);
if (total_vram_used_mb < xe->d3cold.vram_threshold)
- xe->d3cold.allowed = true;
+ xe->d3cold.target_state = XE_D3COLD_OFF;
else
- xe->d3cold.allowed = false;
+ xe->d3cold.target_state = XE_D3HOT;
mutex_unlock(&xe->d3cold.lock);
}
diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h
index 3d5a8c4a4971..f6c09841b0ae 100644
--- a/drivers/gpu/drm/xe/xe_pm.h
+++ b/drivers/gpu/drm/xe/xe_pm.h
@@ -12,6 +12,12 @@
struct xe_device;
+enum xe_d3_state {
+ XE_D3HOT = 0,
+ XE_D3COLD_VRSR,
+ XE_D3COLD_OFF,
+};
+
int xe_pm_suspend(struct xe_device *xe);
int xe_pm_resume(struct xe_device *xe);
@@ -30,7 +36,7 @@ void xe_pm_runtime_get_noresume(struct xe_device *xe);
bool xe_pm_runtime_resume_and_get(struct xe_device *xe);
void xe_pm_assert_unbounded_bridge(struct xe_device *xe);
int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold);
-void xe_pm_d3cold_allowed_toggle(struct xe_device *xe);
+void xe_pm_d3cold_target_state_toggle(struct xe_device *xe);
bool xe_rpm_reclaim_safe(const struct xe_device *xe);
struct task_struct *xe_pm_read_callback_task(struct xe_device *xe);
int xe_pm_block_on_suspend(struct xe_device *xe);
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 09/12] drm/xe/pm: D3cold target state
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (7 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 10/12] drm/xe/vrsr: Enable VRSR Badal Nilawar
` (2 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Trade-off D3cold target state based upon current vram usage.
If vram usage is greater than vram_d3cold_threshold and GPU
is VRSR capable target D3cold state is D3cold-VRSR
otherwise target state is D3cold-Off.
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
---
drivers/gpu/drm/xe/xe_pm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index aa38dbe1e368..f599513edca6 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -167,6 +167,14 @@ static void xe_rpm_lockmap_release(const struct xe_device *xe)
&xe_pm_runtime_d3cold_map);
}
+static void xe_pm_suspend_prepare(struct xe_device *xe)
+{
+ if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE)
+ xe_pm_d3cold_target_state_toggle(xe);
+ else
+ xe->d3cold.target_state = XE_D3COLD_OFF;
+}
+
/**
* xe_pm_suspend - Helper for System suspend, i.e. S0->S3 / S0->S2idle
* @xe: xe device instance
@@ -183,6 +191,8 @@ int xe_pm_suspend(struct xe_device *xe)
xe_pm_block_begin_signalling();
trace_xe_pm_suspend(xe, __builtin_return_address(0));
+ xe_pm_suspend_prepare(xe);
+
err = xe_pxp_pm_suspend(xe->pxp);
if (err)
goto err;
@@ -1077,10 +1087,14 @@ void xe_pm_d3cold_target_state_toggle(struct xe_device *xe)
if (total_vram_used_mb < xe->d3cold.vram_threshold)
xe->d3cold.target_state = XE_D3COLD_OFF;
+ else if (xe->d3cold.vrsr_capable)
+ xe->d3cold.target_state = XE_D3COLD_VRSR;
else
xe->d3cold.target_state = XE_D3HOT;
mutex_unlock(&xe->d3cold.lock);
+
+ drm_dbg(&xe->drm, "Xe D3cold target state %d\n", xe->d3cold.target_state);
}
/**
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 10/12] drm/xe/vrsr: Enable VRSR
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (8 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 09/12] drm/xe/pm: D3cold target state Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable Badal Nilawar
11 siblings, 0 replies; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
From: Anshuman Gupta <anshuman.gupta@intel.com>
Enable VRSR in runtime suspend and also in System wide suspend.
Also fix couple of typo in xe_pm.c.
V2: Disable VRSR in runtime/system resume path
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Acked-by: Karthik Poosa <karthik.poosa@intel.com>
---
drivers/gpu/drm/xe/xe_pci.c | 4 +--
drivers/gpu/drm/xe/xe_pm.c | 52 ++++++++++++++++++++++++++++---------
2 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index eb60cf44c1d7..2f1b6d52514c 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1067,7 +1067,7 @@ static int xe_pci_suspend(struct device *dev)
/*
* Enabling D3Cold is needed for S2Idle/S0ix.
- * It is save to allow here since xe_pm_suspend has evicted
+ * It is safe to allow here since xe_pm_suspend has evicted
* the local memory and the direct complete optimization is disabled.
*/
d3cold_toggle(pdev, D3COLD_ENABLE);
@@ -1084,7 +1084,7 @@ static int xe_pci_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
int err;
- /* Give back the D3Cold decision to the runtime P M*/
+ /* Give back the D3Cold decision to the runtime PM */
d3cold_toggle(pdev, D3COLD_DISABLE);
err = pci_set_power_state(pdev, PCI_D0);
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index f599513edca6..84cd9e84f548 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -204,10 +204,12 @@ int xe_pm_suspend(struct xe_device *xe)
xe_display_pm_suspend(xe);
- /* FIXME: Super racey... */
- err = xe_bo_evict_all(xe);
- if (err)
- goto err_display;
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
+ /* FIXME: Super racey... */
+ err = xe_bo_evict_all(xe);
+ if (err)
+ goto err;
+ }
for_each_gt(gt, xe, id) {
err = xe_gt_suspend(gt);
@@ -221,6 +223,12 @@ int xe_pm_suspend(struct xe_device *xe)
xe_i2c_pm_suspend(xe);
+ if (xe->d3cold.target_state == XE_D3COLD_VRSR) {
+ err = xe_pm_vrsr_enable(xe);
+ if (err)
+ goto err_display;
+ }
+
drm_dbg(&xe->drm, "Device suspended\n");
xe_pm_block_end_signalling();
@@ -262,15 +270,20 @@ int xe_pm_resume(struct xe_device *xe)
if (err)
return err;
+ if (xe->d3cold.target_state == XE_D3COLD_VRSR)
+ xe_pm_vrsr_disable(xe);
+
xe_display_pm_resume_early(xe);
/*
* This only restores pinned memory which is the memory required for the
* GT(s) to resume.
*/
- err = xe_bo_restore_early(xe);
- if (err)
- goto err;
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
+ err = xe_bo_restore_early(xe);
+ if (err)
+ goto err;
+ }
xe_i2c_pm_resume(xe, true);
@@ -281,9 +294,11 @@ int xe_pm_resume(struct xe_device *xe)
xe_display_pm_resume(xe);
- err = xe_bo_restore_late(xe);
- if (err)
- goto err;
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
+ err = xe_bo_restore_late(xe);
+ if (err)
+ goto err;
+ }
xe_pxp_pm_resume(xe->pxp);
@@ -729,7 +744,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
xe_display_pm_runtime_suspend(xe);
- if (xe->d3cold.target_state) {
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
err = xe_bo_evict_all(xe);
if (err)
goto out_resume;
@@ -747,6 +762,14 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
xe_i2c_pm_suspend(xe);
+ if (xe->d3cold.target_state == XE_D3COLD_VRSR) {
+ err = xe_pm_vrsr_enable(xe);
+ if (err) {
+ drm_err(&xe->drm, "Failed to enable VRSR: %d\n", err);
+ goto out_resume;
+ }
+ }
+
xe_rpm_lockmap_release(xe);
xe_pm_write_callback_task(xe, NULL);
return 0;
@@ -787,7 +810,12 @@ int xe_pm_runtime_resume(struct xe_device *xe)
goto out;
xe_display_pm_resume_early(xe);
+ }
+ if (xe->d3cold.target_state == XE_D3COLD_VRSR)
+ xe_pm_vrsr_disable(xe);
+
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
/*
* This only restores pinned memory which is the memory
* required for the GT(s) to resume.
@@ -807,7 +835,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
xe_display_pm_runtime_resume(xe);
- if (xe->d3cold.target_state) {
+ if (xe->d3cold.target_state == XE_D3COLD_OFF) {
err = xe_bo_restore_late(xe);
if (err)
goto out;
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (9 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 10/12] drm/xe/vrsr: Enable VRSR Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-17 11:00 ` Matthew Auld
2025-10-15 8:07 ` [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable Badal Nilawar
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
In D3hot and D3cold-VRSR, VRAM remains active, so it is not necessary
to evict user BOs.
Cc: Matthew Auld <matthew.auld@intel.com>
Co-developed-by: Sk Anirban <sk.anirban@intel.com>
Signed-off-by: Sk Anirban <sk.anirban@intel.com>
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
drivers/gpu/drm/xe/xe_pm.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index 84cd9e84f548..51ff9b90fbfd 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -169,7 +169,7 @@ static void xe_rpm_lockmap_release(const struct xe_device *xe)
static void xe_pm_suspend_prepare(struct xe_device *xe)
{
- if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE)
+ if (pm_suspend_default_s2idle())
xe_pm_d3cold_target_state_toggle(xe);
else
xe->d3cold.target_state = XE_D3COLD_OFF;
@@ -191,8 +191,6 @@ int xe_pm_suspend(struct xe_device *xe)
xe_pm_block_begin_signalling();
trace_xe_pm_suspend(xe, __builtin_return_address(0));
- xe_pm_suspend_prepare(xe);
-
err = xe_pxp_pm_suspend(xe->pxp);
if (err)
goto err;
@@ -543,8 +541,12 @@ static int xe_pm_notifier_callback(struct notifier_block *nb,
int err = 0;
switch (action) {
- case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
+ xe_pm_suspend_prepare(xe);
+ if (xe->d3cold.target_state != XE_D3COLD_OFF)
+ break;
+ fallthrough;
+ case PM_HIBERNATION_PREPARE:
{
struct xe_validation_ctx ctx;
@@ -569,8 +571,11 @@ static int xe_pm_notifier_callback(struct notifier_block *nb,
xe_pm_block_end_signalling();
break;
}
- case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
+ if (xe->d3cold.target_state != XE_D3COLD_OFF)
+ break;
+ fallthrough;
+ case PM_POST_HIBERNATION:
complete_all(&xe->pm_block);
xe_pm_wake_rebind_workers(xe);
xe_bo_notifier_unprepare_all_pinned(xe);
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
` (10 preceding siblings ...)
2025-10-15 8:07 ` [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state Badal Nilawar
@ 2025-10-15 8:07 ` Badal Nilawar
2025-10-15 8:43 ` Poosa, Karthik
11 siblings, 1 reply; 22+ messages in thread
From: Badal Nilawar @ 2025-10-15 8:07 UTC (permalink / raw)
To: intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
Add a debugfs node named vrsr_capable to check if the device
supports VRSR.
V2: Use debugfs_create_bool for vrsr_capable node (Karthik)
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
---
drivers/gpu/drm/xe/xe_debugfs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 1c3c9557a9bd..11d1942c196d 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -402,6 +402,9 @@ void xe_debugfs_register(struct xe_device *xe)
debugfs_create_file("disable_late_binding", 0600, root, xe,
&disable_late_binding_fops);
+ debugfs_create_bool("vrsr_capable", 0400, root,
+ &xe->d3cold.vrsr_capable);
+
for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
man = ttm_manager_type(bdev, mem_type);
--
2.34.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
2025-10-15 8:07 ` [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum Badal Nilawar
@ 2025-10-15 8:39 ` Raag Jadav
2025-10-15 9:04 ` Nilawar, Badal
0 siblings, 1 reply; 22+ messages in thread
From: Raag Jadav @ 2025-10-15 8:39 UTC (permalink / raw)
To: Badal Nilawar
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On Wed, Oct 15, 2025 at 01:37:06PM +0530, Badal Nilawar wrote:
> From: Anshuman Gupta <anshuman.gupta@intel.com>
>
> Add xe_d3_state enum to add support for VRAM Self Refresh
> d3cold state.
>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
...
> @@ -787,7 +787,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
> goto out;
> }
>
> - xe_i2c_pm_resume(xe, xe->d3cold.allowed);
> + if (xe->d3cold.target_state != XE_D3HOT)
> + xe_i2c_pm_resume(xe, true);
Does this require an if condition?
Raag
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable
2025-10-15 8:07 ` [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable Badal Nilawar
@ 2025-10-15 8:43 ` Poosa, Karthik
0 siblings, 0 replies; 22+ messages in thread
From: Poosa, Karthik @ 2025-10-15 8:43 UTC (permalink / raw)
To: Badal Nilawar, intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar
On 15-10-2025 13:37, Badal Nilawar wrote:
> Add a debugfs node named vrsr_capable to check if the device
> supports VRSR.
>
> V2: Use debugfs_create_bool for vrsr_capable node (Karthik)
>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> ---
> drivers/gpu/drm/xe/xe_debugfs.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
> index 1c3c9557a9bd..11d1942c196d 100644
> --- a/drivers/gpu/drm/xe/xe_debugfs.c
> +++ b/drivers/gpu/drm/xe/xe_debugfs.c
> @@ -402,6 +402,9 @@ void xe_debugfs_register(struct xe_device *xe)
> debugfs_create_file("disable_late_binding", 0600, root, xe,
> &disable_late_binding_fops);
>
> + debugfs_create_bool("vrsr_capable", 0400, root,
> + &xe->d3cold.vrsr_capable);
> +
> for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
> man = ttm_manager_type(bdev, mem_type);
>
Looks good.
Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
2025-10-15 8:39 ` Raag Jadav
@ 2025-10-15 9:04 ` Nilawar, Badal
2025-10-15 9:08 ` Nilawar, Badal
2025-10-15 9:08 ` Gupta, Anshuman
0 siblings, 2 replies; 22+ messages in thread
From: Nilawar, Badal @ 2025-10-15 9:04 UTC (permalink / raw)
To: Raag Jadav
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On 15-10-2025 14:09, Raag Jadav wrote:
> On Wed, Oct 15, 2025 at 01:37:06PM +0530, Badal Nilawar wrote:
>> From: Anshuman Gupta <anshuman.gupta@intel.com>
>>
>> Add xe_d3_state enum to add support for VRAM Self Refresh
>> d3cold state.
>>
>> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
>> Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
> ...
>
>> @@ -787,7 +787,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
>> goto out;
>> }
>>
>> - xe_i2c_pm_resume(xe, xe->d3cold.allowed);
>> + if (xe->d3cold.target_state != XE_D3HOT)
>> + xe_i2c_pm_resume(xe, true);
> Does this require an if condition?
Added it to handle D3cold and D3cold-VRSR target state. Am I missing
something?
Thanks,
Badal
>
> Raag
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
2025-10-15 9:04 ` Nilawar, Badal
@ 2025-10-15 9:08 ` Nilawar, Badal
2025-10-15 9:08 ` Gupta, Anshuman
1 sibling, 0 replies; 22+ messages in thread
From: Nilawar, Badal @ 2025-10-15 9:08 UTC (permalink / raw)
To: Raag Jadav
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On 15-10-2025 14:34, Nilawar, Badal wrote:
>
> On 15-10-2025 14:09, Raag Jadav wrote:
>> On Wed, Oct 15, 2025 at 01:37:06PM +0530, Badal Nilawar wrote:
>>> From: Anshuman Gupta <anshuman.gupta@intel.com>
>>>
>>> Add xe_d3_state enum to add support for VRAM Self Refresh
>>> d3cold state.
>>>
>>> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
>>> Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
>> ...
>>
>>> @@ -787,7 +787,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
>>> goto out;
>>> }
>>> - xe_i2c_pm_resume(xe, xe->d3cold.allowed);
>>> + if (xe->d3cold.target_state != XE_D3HOT)
>>> + xe_i2c_pm_resume(xe, true);
>> Does this require an if condition?
>
> Added it to handle D3cold and D3cold-VRSR target state. Am I missing
> something?
Got it, to re-configure PMCSR need to handle false case as well.
>
> Thanks,
> Badal
>
>>
>> Raag
^ permalink raw reply [flat|nested] 22+ messages in thread
* RE: [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
2025-10-15 9:04 ` Nilawar, Badal
2025-10-15 9:08 ` Nilawar, Badal
@ 2025-10-15 9:08 ` Gupta, Anshuman
1 sibling, 0 replies; 22+ messages in thread
From: Gupta, Anshuman @ 2025-10-15 9:08 UTC (permalink / raw)
To: Nilawar, Badal, Jadav, Raag
Cc: intel-xe@lists.freedesktop.org, linux-acpi@vger.kernel.org,
linux-pci@vger.kernel.org, rafael@kernel.org, lenb@kernel.org,
bhelgaas@google.com, ilpo.jarvinen@linux.intel.com,
De Marchi, Lucas, Vivi, Rodrigo, Gupta, Varun,
ville.syrjala@linux.intel.com, Shankar, Uma, Poosa, Karthik
> -----Original Message-----
> From: Nilawar, Badal <badal.nilawar@intel.com>
> Sent: Wednesday, October 15, 2025 2:35 PM
> To: Jadav, Raag <raag.jadav@intel.com>
> Cc: intel-xe@lists.freedesktop.org; linux-acpi@vger.kernel.org; linux-
> pci@vger.kernel.org; Gupta, Anshuman <anshuman.gupta@intel.com>;
> rafael@kernel.org; lenb@kernel.org; bhelgaas@google.com;
> ilpo.jarvinen@linux.intel.com; De Marchi, Lucas <lucas.demarchi@intel.com>;
> Vivi, Rodrigo <rodrigo.vivi@intel.com>; Gupta, Varun
> <varun.gupta@intel.com>; ville.syrjala@linux.intel.com; Shankar, Uma
> <uma.shankar@intel.com>; Poosa, Karthik <karthik.poosa@intel.com>
> Subject: Re: [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum
>
>
> On 15-10-2025 14:09, Raag Jadav wrote:
> > On Wed, Oct 15, 2025 at 01:37:06PM +0530, Badal Nilawar wrote:
> >> From: Anshuman Gupta <anshuman.gupta@intel.com>
> >>
> >> Add xe_d3_state enum to add support for VRAM Self Refresh d3cold
> >> state.
> >>
> >> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> >> Reviewed-by: Karthik Poosa <karthik.poosa@intel.com>
> > ...
> >
> >> @@ -787,7 +787,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
> >> goto out;
> >> }
> >>
> >> - xe_i2c_pm_resume(xe, xe->d3cold.allowed);
> >> + if (xe->d3cold.target_state != XE_D3HOT)
> >> + xe_i2c_pm_resume(xe, true);
> > Does this require an if condition?
>
> Added it to handle D3cold and D3cold-VRSR target state. Am I missing
> something?
Do we have separate function to resume i2c during d3hot ?
What will the default state of i2c during d3hot resume.
Thanks,
Anshuman
>
> Thanks,
> Badal
>
> >
> > Raag
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state
2025-10-15 8:07 ` [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state Badal Nilawar
@ 2025-10-17 11:00 ` Matthew Auld
0 siblings, 0 replies; 22+ messages in thread
From: Matthew Auld @ 2025-10-17 11:00 UTC (permalink / raw)
To: Badal Nilawar, intel-xe, linux-acpi, linux-pci
Cc: anshuman.gupta, rafael, lenb, bhelgaas, ilpo.jarvinen,
lucas.demarchi, rodrigo.vivi, varun.gupta, ville.syrjala,
uma.shankar, karthik.poosa
On 15/10/2025 09:07, Badal Nilawar wrote:
> In D3hot and D3cold-VRSR, VRAM remains active, so it is not necessary
> to evict user BOs.
>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Co-developed-by: Sk Anirban <sk.anirban@intel.com>
> Signed-off-by: Sk Anirban <sk.anirban@intel.com>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> ---
> drivers/gpu/drm/xe/xe_pm.c | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
> index 84cd9e84f548..51ff9b90fbfd 100644
> --- a/drivers/gpu/drm/xe/xe_pm.c
> +++ b/drivers/gpu/drm/xe/xe_pm.c
> @@ -169,7 +169,7 @@ static void xe_rpm_lockmap_release(const struct xe_device *xe)
>
> static void xe_pm_suspend_prepare(struct xe_device *xe)
> {
> - if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE)
> + if (pm_suspend_default_s2idle())
> xe_pm_d3cold_target_state_toggle(xe);
> else
> xe->d3cold.target_state = XE_D3COLD_OFF;
> @@ -191,8 +191,6 @@ int xe_pm_suspend(struct xe_device *xe)
> xe_pm_block_begin_signalling();
> trace_xe_pm_suspend(xe, __builtin_return_address(0));
>
> - xe_pm_suspend_prepare(xe);
> -
> err = xe_pxp_pm_suspend(xe->pxp);
> if (err)
> goto err;
> @@ -543,8 +541,12 @@ static int xe_pm_notifier_callback(struct notifier_block *nb,
> int err = 0;
>
> switch (action) {
> - case PM_HIBERNATION_PREPARE:
> case PM_SUSPEND_PREPARE:
> + xe_pm_suspend_prepare(xe);
> + if (xe->d3cold.target_state != XE_D3COLD_OFF)
> + break;
I think this will break hibernation on igpu platforms with flat-CSS? We
need evict_all() to move CCS from stolen memory back to normal RAM such
that it is saved and then restored correctly on resume from hibernation.
What is the value of target_state for a hibernation event? Does the
evict_all() still get called later? AFAICT it is not called any more.
> + fallthrough;
> + case PM_HIBERNATION_PREPARE:
> {
> struct xe_validation_ctx ctx;
>
> @@ -569,8 +571,11 @@ static int xe_pm_notifier_callback(struct notifier_block *nb,
> xe_pm_block_end_signalling();
> break;
> }
> - case PM_POST_HIBERNATION:
> case PM_POST_SUSPEND:
> + if (xe->d3cold.target_state != XE_D3COLD_OFF)
> + break;
> + fallthrough;
> + case PM_POST_HIBERNATION:
> complete_all(&xe->pm_block);
> xe_pm_wake_rebind_workers(xe);
> xe_bo_notifier_unprepare_all_pinned(xe);
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method
2025-10-15 8:06 ` [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method Badal Nilawar
@ 2025-10-27 19:03 ` Rafael J. Wysocki
0 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2025-10-27 19:03 UTC (permalink / raw)
To: Badal Nilawar
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On Wed, Oct 15, 2025 at 10:02 AM Badal Nilawar <badal.nilawar@intel.com> wrote:
>
> From: Anshuman Gupta <anshuman.gupta@intel.com>
>
> Implement _DSM method 0Ah, as per PCI Firmware r3.3, sec 4.6.10,
> to request auxiliary power required by the device when in D3cold state.
>
> Note that this implementation assumes only a single device below the
> Downstream Port will request for Aux Power Limit under a given
> Root Port/Downstream Port because it does not track and aggregate
> requests from all child devices below the Downstream Port as required
> by PCI Firmware r3.3, sec 4.6.10.
>
> Co-developed-by: Badal Nilawar <badal.nilawar@intel.com>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
> V2(Bjorn/Rafael):
> - Call acpi_dsm_check() to find method 0Ah supported
> - Return retry interval to caller
> V3(Kuppuswamy)
> - Add NULL check for retry interval
> V4
> - Define enums for aux power request status (Rafael)
> - Add Co-developed-by and clean up Signed-off-by (Kappuswamy)
> (Bjorn)
> - Instead of root pci device pass the pci device of driver, traverse
> up the tree and discover _DSM
> - Allow only function 0 of device to request aux power
> - Allow retry_interval to be NULL
> - Refine commit message and function description
> ---
> drivers/pci/pci-acpi.c | 114 +++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 9 ++++
> 2 files changed, 123 insertions(+)
>
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 9369377725fa..c7eab1e75dd5 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -1418,6 +1418,120 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
> ACPI_FREE(obj);
> }
>
> +static struct pci_dev *pci_acpi_check_dsm(struct pci_dev *dev, u64 rev, u64 funcs)
The name of the function should be more specific than this, at least
to indicate that it is about the downstream port _DSM.
> +{
> + struct pci_dev *bdev;
> + acpi_handle handle;
> +
> + if (!dev)
> + return ERR_PTR(-EINVAL);
dev has been checked against NULL already by the caller.
> +
> + bdev = dev;
> + while (bdev) {
And there would be fewer code lines if a for () loop were used here.
> + handle = ACPI_HANDLE(&bdev->dev);
> + if (handle && acpi_check_dsm(handle, &pci_acpi_dsm_guid, rev, 1 << funcs))
> + return bdev;
> +
> + bdev = pci_upstream_bridge(bdev);
> + }
> +
> + return ERR_PTR(-ENODEV);
Personally, I don't see much value in putting this code into a
separate function.
> +}
> +
> +enum aux_pwr_req_status {
> + AUX_PWR_REQ_DENIED = 0x0,
> + AUX_PWR_REQ_GRANTED = 0x1,
> + AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL = 0x2,
> + AUX_PWR_REQ_RETRY_INTERVAL_MIN = 0x11,
> + AUX_PWR_REQ_RETRY_INTERVAL_MAX = 0x1F
> +};
> +
> +/**
> + * pci_acpi_request_d3cold_aux_power - Request aux power while device is in D3cold
> + * @dev: PCI device instance
> + * @requested_mw: Requested auxiliary power in milliwatts
> + * @retry_interval: Retry interval returned by platform to retry auxiliary
> + * power request
> + *
> + * Request auxilary power to platform firmware, via Root Port/Switch Downstream
> + * Port ACPI _DSM Function 0Ah, needed for the PCI device when it is in D3cold.
> + * Evaluate the _DSM and handle the response accordingly.
> + *
> + * For Multi-Function Devices, driver for Function 0 is required to report an
> + * aggregate power requirement covering all functions contained within the
> + * device.
> + *
> + * Note: Aggregation across multiple child devices beneath the Root/Switch Downstream
> + * Port is not supported.
"Note: " isn't particularly useful here IMV.
> + *
> + * Return: Returns 0 on success and errno on failure.
> + */
> +int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> + u32 *retry_interval)
> +{
> + union acpi_object in_obj = {
> + .integer.type = ACPI_TYPE_INTEGER,
> + .integer.value = requested_mw,
> + };
> +
> + union acpi_object *out_obj;
> + int result, ret = -EINVAL;
> + struct pci_dev *bdev;
> +
> + if (!dev || PCI_FUNC(dev->devfn) != 0)
I'm not sure about the PCI_FUNC(dev->devfn) check.
Synchronization between drivers in this respect can be somewhat
tricky. It would be more straightforward to allow the first caller of
this for a given port with the _DSM under it to "win" in all cases,
including different functions within the same device (this happens in
the other cases anyway IIUC).
> + return -EINVAL;
> +
> + bdev = pci_acpi_check_dsm(dev, 4, 1 << DSM_PCI_D3COLD_AUX_POWER_LIMIT);
> +
> + if (IS_ERR(bdev))
> + return PTR_ERR(bdev);
> +
> + out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
> + &pci_acpi_dsm_guid, 4,
> + DSM_PCI_D3COLD_AUX_POWER_LIMIT,
> + &in_obj, ACPI_TYPE_INTEGER);
> + if (!out_obj)
> + return -EINVAL;
> +
> + result = out_obj->integer.value;
out_obj can be freed here and the code below can be made to return an
error code right away in multiple places.
> + if (retry_interval)
> + *retry_interval = 0;
> +
> + switch (result) {
> + case AUX_PWR_REQ_DENIED:
> + pci_dbg(bdev, "D3cold Aux Power %u mW request denied\n",
> + requested_mw);
> + break;
> + case AUX_PWR_REQ_GRANTED:
> + pci_info(bdev, "D3cold Aux Power request granted: %u mW\n",
> + requested_mw);
> + ret = 0;
> + break;
> + case AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL:
> + pci_info(bdev, "D3cold Aux Power: Main power won't be removed\n");
> + ret = -EBUSY;
> + break;
> + default:
> + if (result >= AUX_PWR_REQ_RETRY_INTERVAL_MIN &&
> + result <= AUX_PWR_REQ_RETRY_INTERVAL_MAX) {
> + pci_info(bdev, "D3cold Aux Power request needs retry interval: %u seconds\n",
> + result & 0xF);
> + if (retry_interval) {
> + *retry_interval = result & 0xF;
> + ret = -EAGAIN;
> + }
> + } else {
> + pci_err(bdev, "D3cold Aux Power: Reserved or unsupported response: 0x%x\n",
> + result);
> + }
> + break;
> + }
> +
> + ACPI_FREE(out_obj);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(pci_acpi_request_d3cold_aux_power);
> +
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request
2025-10-15 8:07 ` [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request Badal Nilawar
@ 2025-10-27 19:11 ` Rafael J. Wysocki
0 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2025-10-27 19:11 UTC (permalink / raw)
To: Badal Nilawar
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On Wed, Oct 15, 2025 at 10:02 AM Badal Nilawar <badal.nilawar@intel.com> wrote:
>
> Since aggregation of auxiliary power across multiple devices under a
> Root or Switch Downstream Port is not supported, allow only one device
> is to request auxiliary power
>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Anshuman Gupta <anshuman.gupta@intel.com>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
I would prefer this one to be folded into the previous patch. It
would be easier to review for me then.
> ---
> V1:
> - Use guard(mutex) for new mutex (Rafael)
> - Add mutex_detroy (Ilpo Järvinen)
> - %s/pci_warn/pci_info/ for -EAGAIN
> - Allow the same device to re-request auxiliary power if it has already been granted
> ---
> drivers/acpi/scan.c | 3 +++
> drivers/pci/pci-acpi.c | 22 ++++++++++++++++++++++
> include/acpi/acpi_bus.h | 3 +++
> 3 files changed, 28 insertions(+)
>
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index ef16d58b2949..4573fb0f4f3e 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -518,6 +518,7 @@ static void acpi_device_release(struct device *dev)
> acpi_free_properties(acpi_dev);
> acpi_free_pnp_ids(&acpi_dev->pnp);
> acpi_free_power_resources_lists(acpi_dev);
> + mutex_destroy(&acpi_dev->power.aux_pwr_lock);
> kfree(acpi_dev);
> }
>
> @@ -746,6 +747,8 @@ int acpi_device_add(struct acpi_device *device)
> INIT_LIST_HEAD(&device->physical_node_list);
> INIT_LIST_HEAD(&device->del_list);
> mutex_init(&device->physical_node_lock);
> + mutex_init(&device->power.aux_pwr_lock);
> + device->power.dev = NULL;
>
> mutex_lock(&acpi_device_lock);
>
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index c7eab1e75dd5..74f118016b1d 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -1477,6 +1477,7 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> union acpi_object *out_obj;
> int result, ret = -EINVAL;
> struct pci_dev *bdev;
> + struct acpi_device *adev;
>
> if (!dev || PCI_FUNC(dev->devfn) != 0)
> return -EINVAL;
> @@ -1486,6 +1487,19 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> if (IS_ERR(bdev))
> return PTR_ERR(bdev);
>
> + adev = ACPI_COMPANION(&bdev->dev);
> + if (!adev)
> + return -EINVAL;
> +
> + guard(mutex)(&adev->power.aux_pwr_lock);
> +
> + /* Check if aux power already granted to different device */
> + if (adev->power.dev && adev->power.dev != &dev->dev) {
> + pci_info(to_pci_dev(adev->power.dev), "D3cold Aux Power request already granted: %u mW\n",
> + adev->power.aux_power_limit);
> + return -EPERM;
Why this error code?
> + }
> +
> out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
> &pci_acpi_dsm_guid, 4,
> DSM_PCI_D3COLD_AUX_POWER_LIMIT,
> @@ -1501,14 +1515,20 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> case AUX_PWR_REQ_DENIED:
> pci_dbg(bdev, "D3cold Aux Power %u mW request denied\n",
> requested_mw);
> + adev->power.aux_power_limit = 0;
> + adev->power.dev = NULL;
> break;
> case AUX_PWR_REQ_GRANTED:
> pci_info(bdev, "D3cold Aux Power request granted: %u mW\n",
> requested_mw);
> + adev->power.aux_power_limit = requested_mw;
> + adev->power.dev = &dev->dev;
> ret = 0;
> break;
> case AUX_PWR_REQ_NO_MAIN_PWR_REMOVAL:
> pci_info(bdev, "D3cold Aux Power: Main power won't be removed\n");
> + adev->power.aux_power_limit = 0;
> + adev->power.dev = NULL;
> ret = -EBUSY;
I forgot to ask about this when reviewing the previous patch: Is it
really an error situation?
The AML tells you that main power is not going to be removed, so aux
power is not necessary. Why would it be a problem?
> break;
> default:
> @@ -1524,6 +1544,8 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> pci_err(bdev, "D3cold Aux Power: Reserved or unsupported response: 0x%x\n",
> result);
> }
> + adev->power.aux_power_limit = 0;
> + adev->power.dev = NULL;
> break;
> }
>
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index aad1a95e6863..cfa0c7233f13 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -294,6 +294,9 @@ struct acpi_device_power {
> struct acpi_device_power_flags flags;
> struct acpi_device_power_state states[ACPI_D_STATE_COUNT]; /* Power states (D0-D3Cold) */
> u8 state_for_enumeration; /* Deepest power state for enumeration */
> + u32 aux_power_limit; /* aux power limit granted by platform firmware */
> + struct device *dev; /* device to which aux power is granted */
Call this aux_power_dev, please.
> + struct mutex aux_pwr_lock; /* prevent concurrent aux power limit requests */
> };
>
> struct acpi_dep_data {
> --
Is there a way to revoke a previously requested aux power limit?
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method
2025-10-15 8:07 ` [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method Badal Nilawar
@ 2025-10-27 19:18 ` Rafael J. Wysocki
0 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2025-10-27 19:18 UTC (permalink / raw)
To: Badal Nilawar
Cc: intel-xe, linux-acpi, linux-pci, anshuman.gupta, rafael, lenb,
bhelgaas, ilpo.jarvinen, lucas.demarchi, rodrigo.vivi,
varun.gupta, ville.syrjala, uma.shankar, karthik.poosa
On Wed, Oct 15, 2025 at 10:02 AM Badal Nilawar <badal.nilawar@intel.com> wrote:
>
> From: Anshuman Gupta <anshuman.gupta@intel.com>
>
> Implement _DSM Method 0Bh as per PCI Firmware r3.3, sec 4.6.10.
Can you please describe it here briefly for the benefit of people
without access to the PCI Firmware r3.3 specification?
And how is this related to the aux power limit the first two patches are about?
> Co-developed-by: Badal Nilawar <badal.nilawar@intel.com>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
> V2:
> - Call acpi_check_dsm() to find method 0Bh supported
> V3(Kappuswamy/Rafael):
> - %s/pci_warn/pci_info/ when PERST# Assertion Delay request fails
> ---
> drivers/pci/pci-acpi.c | 53 ++++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 9 ++++++-
> 2 files changed, 61 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 74f118016b1d..230077200ce8 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -1554,6 +1554,59 @@ int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> }
> EXPORT_SYMBOL_GPL(pci_acpi_request_d3cold_aux_power);
>
> +/**
> + * pci_acpi_add_perst_assertion_delay - Request PERST# Delay via ACPI DSM
> + * @dev: PCI device instance
> + * @delay_us: Requested delay_us
> + *
> + * Request PERST# Assertion Delay to platform firmware, via Root Port/
> + * Switch Downstream Port ACPI _DSM Function 0Bh, for the specified
> + * PCI device.
> + * Evaluate the _DSM and handle the response accordingly.
> + *
> + * Return: returns 0 on success and errno on failure.
> + */
> +int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev, u32 delay_us)
> +{
> + union acpi_object in_obj = {
> + .integer.type = ACPI_TYPE_INTEGER,
> + .integer.value = delay_us,
> + };
> +
> + union acpi_object *out_obj;
> + int result, ret = -EINVAL;
> + struct pci_dev *bdev;
> +
> + if (!dev)
> + return -EINVAL;
> +
> + bdev = pci_acpi_check_dsm(dev, 4, 1 << DSM_PCI_PERST_ASSERTION_DELAY);
> +
> + if (IS_ERR(bdev))
> + return PTR_ERR(bdev);
> +
> + out_obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&bdev->dev),
> + &pci_acpi_dsm_guid, 4,
> + DSM_PCI_PERST_ASSERTION_DELAY,
> + &in_obj, ACPI_TYPE_INTEGER);
> + if (!out_obj)
> + return -EINVAL;
> +
> + result = out_obj->integer.value;
Freeing out_obj here would allow error handling below to be more
straightforward.
> +
> + if (result == delay_us) {
> + pci_info(dev, "PERST# Assertion Delay set to %u microseconds\n", delay_us);
> + ret = 0;
> + } else {
> + pci_info(dev, "PERST# Assertion Delay request failed, using %u microseconds\n",
> + result);
> + }
> +
> + ACPI_FREE(out_obj);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(pci_acpi_add_perst_assertion_delay);
> +
> static void pci_acpi_set_external_facing(struct pci_dev *dev)
> {
> u8 val;
> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> index ba48e7ddb360..4d8b8cea019e 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -122,6 +122,7 @@ extern const guid_t pci_acpi_dsm_guid;
> #define DSM_PCI_POWER_ON_RESET_DELAY 0x08
> #define DSM_PCI_DEVICE_READINESS_DURATIONS 0x09
> #define DSM_PCI_D3COLD_AUX_POWER_LIMIT 0x0A
> +#define DSM_PCI_PERST_ASSERTION_DELAY 0x0B
>
> #ifdef CONFIG_PCIE_EDR
> void pci_acpi_add_edr_notifier(struct pci_dev *pdev);
> @@ -135,7 +136,7 @@ int pci_acpi_set_companion_lookup_hook(struct acpi_device *(*func)(struct pci_de
> void pci_acpi_clear_companion_lookup_hook(void);
> int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev, u32 requested_mw,
> u32 *retry_interval);
> -
> +int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev, u32 delay_us);
> #else /* CONFIG_ACPI */
> static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
> static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
> @@ -145,6 +146,12 @@ static inline int pci_acpi_request_d3cold_aux_power(struct pci_dev *dev,
> {
> return -EOPNOTSUPP;
> }
> +
> +static inline int pci_acpi_add_perst_assertion_delay(struct pci_dev *dev,
> + u32 delay_us)
> +{
> + return -EOPNOTSUPP;
> +}
> #endif /* CONFIG_ACPI */
>
> #endif /* _PCI_ACPI_H_ */
> --
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2025-10-27 19:18 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-15 8:06 [PATCH v5 00/12] VRAM Self Refresh Badal Nilawar
2025-10-15 8:06 ` [PATCH v5 01/12] PCI/ACPI: Add D3cold Aux Power Limit_DSM method Badal Nilawar
2025-10-27 19:03 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 02/12] PCI/ACPI: Per Root/Switch Downstream Port allow one aux power limit request Badal Nilawar
2025-10-27 19:11 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 03/12] PCI/ACPI: Add PERST# Assertion Delay _DSM method Badal Nilawar
2025-10-27 19:18 ` Rafael J. Wysocki
2025-10-15 8:07 ` [PATCH v5 04/12] drm/xe/vrsr: Introduce flag has_vrsr Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 05/12] drm/xe/vrsr: Detect VRSR Capability Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 06/12] drm/xe/vrsr: Initialize VRSR feature Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 07/12] drm/xe/vrsr: Enable VRSR on default VGA boot device Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 08/12] drm/xe/vrsr: Refactor d3cold.allowed to a enum Badal Nilawar
2025-10-15 8:39 ` Raag Jadav
2025-10-15 9:04 ` Nilawar, Badal
2025-10-15 9:08 ` Nilawar, Badal
2025-10-15 9:08 ` Gupta, Anshuman
2025-10-15 8:07 ` [PATCH v5 09/12] drm/xe/pm: D3cold target state Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 10/12] drm/xe/vrsr: Enable VRSR Badal Nilawar
2025-10-15 8:07 ` [PATCH v5 11/12] drm/xe/pm/s2idle: Don't evict user BOs for D3hot and D3cold-VRSR state Badal Nilawar
2025-10-17 11:00 ` Matthew Auld
2025-10-15 8:07 ` [PATCH v5 12/12] drm/xe/vrsr: Introduce a debugfs node named vrsr_capable Badal Nilawar
2025-10-15 8:43 ` Poosa, Karthik
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).