Currently, the available UMA allocation configs in the integrated system
information table have not been parsed. Add a helper function to retrieve
and store these configs.

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     | 32 ++++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 75 ++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h |  1 +
 drivers/gpu/drm/amd/amdgpu/atom.h                |  4 ++
 4 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 763f2b8dcf13..58cc3bc9d42d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -28,6 +28,7 @@
 #include "amdgpu.h"
 #include "amdgpu_atombios.h"
 #include "amdgpu_atomfirmware.h"
+#include "atomfirmware.h"
 #include "amdgpu_i2c.h"
 #include "amdgpu_display.h"
 
@@ -1877,6 +1878,10 @@ void amdgpu_atombios_fini(struct amdgpu_device *adev)
        if (adev->mode_info.atom_context) {
                kfree(adev->mode_info.atom_context->scratch);
                kfree(adev->mode_info.atom_context->iio);
+               kfree(adev->mode_info.atom_context->uma_carveout_options);
+               adev->mode_info.atom_context->uma_carveout_options = NULL;
+               adev->mode_info.atom_context->uma_carveout_nr = 0;
+               adev->mode_info.atom_context->uma_carveout_index = 0;
        }
        kfree(adev->mode_info.atom_context);
        adev->mode_info.atom_context = NULL;
@@ -1891,16 +1896,19 @@ void amdgpu_atombios_fini(struct amdgpu_device *adev)
  *
  * Initializes the driver info and register access callbacks for the
  * ATOM interpreter (r4xx+).
- * Returns 0 on sucess, -ENOMEM on failure.
+ * Returns 0 on success, -ENOMEM on memory allocation error, or -EINVAL on 
ATOM ROM parsing error
  * Called at driver startup.
  */
 int amdgpu_atombios_init(struct amdgpu_device *adev)
 {
        struct card_info *atom_card_info =
            kzalloc(sizeof(struct card_info), GFP_KERNEL);
+       int rc;
 
-       if (!atom_card_info)
-               return -ENOMEM;
+       if (!atom_card_info) {
+               rc = -ENOMEM;
+               goto out_card_info;
+       }
 
        adev->mode_info.atom_card_info = atom_card_info;
        atom_card_info->dev = adev_to_drm(adev);
@@ -1913,8 +1921,16 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
 
        adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, 
adev->bios);
        if (!adev->mode_info.atom_context) {
-               amdgpu_atombios_fini(adev);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_atom_ctx;
+       }
+
+       rc = amdgpu_atomfirmware_get_uma_carveout_info(adev);
+
+       if (rc) {
+               drm_dbg(adev_to_drm(adev), "Failed to get UMA carveout info: 
%d\n", rc);
+               if (rc != -ENODEV)
+                       goto out_uma_info;
        }
 
        mutex_init(&adev->mode_info.atom_context->mutex);
@@ -1930,6 +1946,12 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
        }
 
        return 0;
+
+out_uma_info:
+out_atom_ctx:
+       amdgpu_atombios_fini(adev);
+out_card_info:
+       return rc;
 }
 
 int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index 636385c80f64..698416e84f1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -21,12 +21,14 @@
  *
  */
 
+#include "linux/slab.h"
 #include <drm/amdgpu_drm.h>
 #include "amdgpu.h"
 #include "atomfirmware.h"
 #include "amdgpu_atomfirmware.h"
 #include "atom.h"
 #include "atombios.h"
+#include "atomfirmware.h"
 #include "soc15_hw_ip.h"
 
 union firmware_info {
@@ -296,6 +298,79 @@ static int convert_atom_mem_type_to_vram_type(struct 
amdgpu_device *adev,
        return vram_type;
 }
 
+static int __amdgpu_atomfirmware_get_uma_carveout_info_v2_3(struct 
amdgpu_device *adev,
+                                                           union igp_info 
*igp_info)
+{
+       struct atom_context *ctx = adev->mode_info.atom_context;
+       struct uma_carveout_option *opts;
+
+       opts = kzalloc(sizeof(igp_info->v23.UMASizeControlOption), GFP_KERNEL);
+
+       if (!opts)
+               goto out_mem;
+
+       memcpy(opts, igp_info->v23.UMASizeControlOption,
+               sizeof(igp_info->v23.UMASizeControlOption));
+
+       ctx->uma_carveout_index = igp_info->v23.UMACarveoutIndex;
+       ctx->uma_carveout_nr = igp_info->v23.UMACarveoutIndexMax;
+       ctx->uma_carveout_options = opts;
+
+       return 0;
+
+out_mem:
+       return -ENOMEM;
+}
+
+static int __amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device 
*adev,
+                                                      u8 frev, u8 crev,
+                                                      union igp_info *igp_info)
+{
+       switch (frev) {
+       case 2:
+               switch (crev) {
+               case 3:
+                       return 
__amdgpu_atomfirmware_get_uma_carveout_info_v2_3(adev, igp_info);
+               break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+       return -ENODEV;
+}
+
+int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       union igp_info *igp_info;
+       u16 data_offset, size;
+       u8 frev, crev;
+       int index;
+
+       if (!(adev->flags & AMD_IS_APU))
+               return -ENODEV;
+
+       if (!amdgpu_acpi_is_set_uma_allocation_size_supported())
+               return -ENODEV;
+
+       index = 
get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           integratedsysteminfo);
+
+       if (!amdgpu_atom_parse_data_header(mode_info->atom_context,
+                                         index, &size,
+                                         &frev, &crev, &data_offset)) {
+               return -EINVAL;
+       }
+
+       igp_info = (union igp_info *)
+                       (mode_info->atom_context->bios + data_offset);
+
+       return __amdgpu_atomfirmware_get_uma_carveout_info(adev, frev, crev, 
igp_info);
+}
+
 int
 amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
                                  int *vram_width, int *vram_type,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
index 649b5530d8ae..fb3f34a36569 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
@@ -32,6 +32,7 @@ void amdgpu_atomfirmware_scratch_regs_init(struct 
amdgpu_device *adev);
 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
        int *vram_width, int *vram_type, int *vram_vendor);
+int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h 
b/drivers/gpu/drm/amd/amdgpu/atom.h
index 825ff28731f5..f07c612f0386 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.h
+++ b/drivers/gpu/drm/amd/amdgpu/atom.h
@@ -153,6 +153,10 @@ struct atom_context {
        uint8_t vbios_ver_str[STRLEN_NORMAL];
        uint8_t date[STRLEN_NORMAL];
        uint8_t build_num[STRLEN_NORMAL];
+
+       uint8_t uma_carveout_index;
+       uint8_t uma_carveout_nr;
+       struct uma_carveout_option *uma_carveout_options;
 };
 
 extern int amdgpu_atom_debug;

-- 
2.43.0

Reply via email to