NPS mode change request doesn't allow to request the current mode. This
causes an issue where a user stores a request and later wants to cancel
the request by writing the current mode back. Th pending request stays
the same as before.

Allow user to change the mode by comparing against the cached request.
Writing the current mode back clears the pending request without asking
for a reload.

Fixes: 012be6f22c01 ("drm/amdgpu: Add sysfs interfaces for NPS mode")
Signed-off-by: Lijo Lazar <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 52 ++++++++++++++++++-------
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h |  4 ++
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c   | 13 +++++++
 3 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index d25ca903e21b..87d78fd34e23 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -1398,6 +1398,40 @@ static ssize_t available_memory_partition_show(struct 
device *dev,
        return size;
 }
 
+void amdgpu_gmc_set_requested_nps_mode(struct amdgpu_device *adev,
+                                      enum amdgpu_memory_partition mode)
+{
+       struct amdgpu_hive_info *hive;
+
+       /* If device is part of hive, all devices in the hive should request the
+        * same mode. Hence store the requested mode in hive.
+        */
+       hive = amdgpu_get_xgmi_hive(adev);
+       if (hive) {
+               atomic_set(&hive->requested_nps_mode, mode);
+               amdgpu_put_xgmi_hive(hive);
+       } else {
+               adev->gmc.requested_nps_mode = mode;
+       }
+}
+
+enum amdgpu_memory_partition
+amdgpu_gmc_get_requested_nps_mode(struct amdgpu_device *adev)
+{
+       struct amdgpu_hive_info *hive;
+       enum amdgpu_memory_partition mode;
+
+       hive = amdgpu_get_xgmi_hive(adev);
+       if (hive) {
+               mode = atomic_read(&hive->requested_nps_mode);
+               amdgpu_put_xgmi_hive(hive);
+       } else {
+               mode = adev->gmc.requested_nps_mode;
+       }
+
+       return mode;
+}
+
 static ssize_t current_memory_partition_store(struct device *dev,
                                              struct device_attribute *attr,
                                              const char *buf, size_t count)
@@ -1405,7 +1439,6 @@ static ssize_t current_memory_partition_store(struct 
device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = drm_to_adev(ddev);
        enum amdgpu_memory_partition mode;
-       struct amdgpu_hive_info *hive;
        int i;
 
        mode = UNKNOWN_MEMORY_PARTITION_MODE;
@@ -1419,23 +1452,16 @@ static ssize_t current_memory_partition_store(struct 
device *dev,
        if (mode == UNKNOWN_MEMORY_PARTITION_MODE)
                return -EINVAL;
 
-       if (mode == adev->gmc.gmc_funcs->query_mem_partition_mode(adev)) {
+       if (mode == amdgpu_gmc_get_requested_nps_mode(adev)) {
                dev_info(
                        adev->dev,
-                       "requested NPS mode is same as current NPS mode, 
skipping\n");
+                       "requested NPS mode is same as current/already 
requested NPS mode, skipping\n");
                return count;
        }
 
-       /* If device is part of hive, all devices in the hive should request the
-        * same mode. Hence store the requested mode in hive.
-        */
-       hive = amdgpu_get_xgmi_hive(adev);
-       if (hive) {
-               atomic_set(&hive->requested_nps_mode, mode);
-               amdgpu_put_xgmi_hive(hive);
-       } else {
-               adev->gmc.requested_nps_mode = mode;
-       }
+       amdgpu_gmc_set_requested_nps_mode(adev, mode);
+       if (mode == amdgpu_gmc_query_memory_partition(adev))
+               return count;
 
        dev_info(
                adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index 76e6f1f96913..89f1ee829eea 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -484,6 +484,10 @@ enum amdgpu_memory_partition
 amdgpu_gmc_get_memory_partition(struct amdgpu_device *adev, u32 *supp_modes);
 enum amdgpu_memory_partition
 amdgpu_gmc_query_memory_partition(struct amdgpu_device *adev);
+void amdgpu_gmc_set_requested_nps_mode(struct amdgpu_device *adev,
+                                      enum amdgpu_memory_partition mode);
+enum amdgpu_memory_partition
+amdgpu_gmc_get_requested_nps_mode(struct amdgpu_device *adev);
 int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev);
 void amdgpu_gmc_init_sw_mem_ranges(struct amdgpu_device *adev,
                                   struct amdgpu_mem_partition_info 
*mem_ranges);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 85ba228f002d..5c233acba084 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1617,6 +1617,7 @@ static int gmc_v9_0_early_init(struct amdgpu_ip_block 
*ip_block)
 static int gmc_v9_0_late_init(struct amdgpu_ip_block *ip_block)
 {
        struct amdgpu_device *adev = ip_block->adev;
+       bool nps_switch_support;
        int r;
 
        r = amdgpu_gmc_allocate_vm_inv_eng(adev);
@@ -1641,6 +1642,18 @@ static int gmc_v9_0_late_init(struct amdgpu_ip_block 
*ip_block)
                amdgpu_ras_reset_error_count(adev, AMDGPU_RAS_BLOCK__HDP);
        }
 
+       nps_switch_support = !adev->gmc.xgmi.connected_to_cpu &&
+                            (hweight32(adev->gmc.supported_nps_modes &
+                                       AMDGPU_ALL_NPS_MASK) > 1);
+       /* Initialize requested NPS mode to be the same as current mode */
+       if (nps_switch_support) {
+               enum amdgpu_memory_partition mode =
+                       amdgpu_gmc_get_requested_nps_mode(adev);
+               if (mode == UNKNOWN_MEMORY_PARTITION_MODE)
+                       amdgpu_gmc_set_requested_nps_mode(
+                               adev, amdgpu_gmc_query_memory_partition(adev));
+       }
+
        return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0);
 }
 
-- 
2.49.0

Reply via email to