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) <superm1@kernel.org>
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Yo-Jung Leo Lin (AMD) <Leo.Lin@amd.com>
---
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