Add two sysfs files as interfaces to inspect or change UMA carveout
size. These files are:

- uma_carveout_options: a read-only file listing all the available
  UMA allocation options and their index.

- uma_carveout: a file that is both readable and writable. On read,
  it shows the index of the current setting. Writing a valid index
  into this file allows users to change the UMA carveout size to that
  option on the next boot.

Co-developed-by: Mario Limonciello (AMD) <[email protected]>
Signed-off-by: Mario Limonciello (AMD) <[email protected]>
Signed-off-by: Yo-Jung Leo Lin (AMD) <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 95 +++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 58cc3bc9d42d..1ebfd925b761 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1855,11 +1855,102 @@ const struct attribute_group 
amdgpu_vbios_version_attr_group = {
        .is_visible = amdgpu_vbios_version_attrs_is_visible,
 };
 
+static ssize_t uma_carveout_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = drm_to_adev(ddev);
+       struct atom_context *ctx = adev->mode_info.atom_context;
+
+       return sysfs_emit(buf, "%u\n", ctx->uma_carveout_index);
+}
+static ssize_t uma_carveout_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = drm_to_adev(ddev);
+       struct atom_context *ctx = adev->mode_info.atom_context;
+       struct uma_carveout_option *opt;
+       unsigned long val;
+       uint8_t flags;
+       int r;
+
+       r = kstrtoul(buf, 10, &val);
+       if (r)
+               return r;
+
+       if (val >= ctx->uma_carveout_nr)
+               return -EINVAL;
+
+       opt = &ctx->uma_carveout_options[val];
+
+       if (!opt->uma_carveout_option_flags.flags.Auto &&
+           !opt->uma_carveout_option_flags.flags.Custom) {
+               drm_err_once(ddev, "Option %ul not supported due to lack of 
Custom/Auto flag", r);
+               return -EINVAL;
+       }
+
+       flags = opt->uma_carveout_option_flags.all8;
+       flags &= ~((uint8_t)opt->uma_carveout_option_flags.flags.Custom);
+
+       r = amdgpu_acpi_set_uma_allocation_size(adev, val, flags);
+       if (r)
+               return r;
+       ctx->uma_carveout_index = val;
+
+       return count;
+}
+static DEVICE_ATTR_RW(uma_carveout);
+
+static ssize_t uma_carveout_options_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = drm_to_adev(ddev);
+       struct atom_context *ctx = adev->mode_info.atom_context;
+       ssize_t size = 0;
+
+       for (int i = 0; i < ctx->uma_carveout_nr; i++) {
+               size += sysfs_emit_at(buf, size, "%d: %s (%u GB)\n",
+                                     i,
+                                     ctx->uma_carveout_options[i].optionName,
+                                     
ctx->uma_carveout_options[i].memoryCarvedGb);
+       }
+
+       return size;
+}
+static DEVICE_ATTR_RO(uma_carveout_options);
+
+static struct attribute *amdgpu_uma_attrs[] = {
+       &dev_attr_uma_carveout.attr,
+       &dev_attr_uma_carveout_options.attr,
+       NULL
+};
+
+const struct attribute_group amdgpu_uma_attr_group = {
+       .attrs = amdgpu_uma_attrs
+};
+
 int amdgpu_atombios_sysfs_init(struct amdgpu_device *adev)
 {
-       if (adev->mode_info.atom_context)
-               return devm_device_add_group(adev->dev,
+       int r;
+
+       if (adev->mode_info.atom_context) {
+               r = devm_device_add_group(adev->dev,
                                             &amdgpu_vbios_version_attr_group);
+               if (r)
+                       return r;
+       }
+       if (adev->mode_info.atom_context->uma_carveout_options &&
+           adev->mode_info.atom_context->uma_carveout_nr) {
+               r = devm_device_add_group(adev->dev,
+                                          &amdgpu_uma_attr_group);
+               if (r)
+                       return r;
+       }
 
        return 0;
 }

-- 
2.43.0

Reply via email to