]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amdgpu: reclaim psp fw reservation memory region
authorFrank Min <Frank.Min@amd.com>
Wed, 21 May 2025 08:46:27 +0000 (16:46 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Jun 2025 16:19:21 +0000 (12:19 -0400)
PSP v14 fw update introduced changes on memory reservation region, according
to the change driver reclaim some non-reserved region.

1. introduce 2 new psp commands to query fw reservation regions
2. add a new reservation region for psp
3. reclaim psp non-used region

Signed-off-by: Frank Min <Frank.Min@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h

index 6e833f3aad18455d50e43e3898c0d5af6b2b6525..bdd22a4bd7fe4e013d4541944bbfb1a2f8ca11f8 100644 (file)
@@ -655,6 +655,10 @@ static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
                return "BOOT_CFG";
        case GFX_CMD_ID_CONFIG_SQ_PERFMON:
                return "CONFIG_SQ_PERFMON";
+       case GFX_CMD_ID_FB_FW_RESERV_ADDR:
+               return "FB_FW_RESERV_ADDR";
+       case GFX_CMD_ID_FB_FW_RESERV_EXT_ADDR:
+               return "FB_FW_RESERV_EXT_ADDR";
        default:
                return "UNKNOWN CMD";
        }
@@ -987,6 +991,93 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
        return ret;
 }
 
+static int psp_get_fw_reservation_info(struct psp_context *psp,
+                                                  uint32_t cmd_id,
+                                                  uint64_t *addr,
+                                                  uint32_t *size)
+{
+       int ret;
+       uint32_t status;
+       struct psp_gfx_cmd_resp *cmd;
+
+       cmd = acquire_psp_cmd_buf(psp);
+
+       cmd->cmd_id = cmd_id;
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd,
+                                psp->fence_buf_mc_addr);
+       if (ret) {
+               release_psp_cmd_buf(psp);
+               return ret;
+       }
+
+       status = cmd->resp.status;
+       if (status == PSP_ERR_UNKNOWN_COMMAND) {
+               release_psp_cmd_buf(psp);
+               *addr = 0;
+               *size = 0;
+               return 0;
+       }
+
+       *addr = (uint64_t)cmd->resp.uresp.fw_reserve_info.reserve_base_address_hi << 32 |
+               cmd->resp.uresp.fw_reserve_info.reserve_base_address_lo;
+       *size = cmd->resp.uresp.fw_reserve_info.reserve_size;
+
+       release_psp_cmd_buf(psp);
+
+       return 0;
+}
+
+int psp_update_fw_reservation(struct psp_context *psp)
+{
+       int ret;
+       uint64_t reserv_addr, reserv_addr_ext;
+       uint32_t reserv_size, reserv_size_ext;
+       struct amdgpu_device *adev = psp->adev;
+
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       if ((amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 2)) &&
+           (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 3)))
+               return 0;
+
+       ret = psp_get_fw_reservation_info(psp, GFX_CMD_ID_FB_FW_RESERV_ADDR, &reserv_addr, &reserv_size);
+       if (ret)
+               return ret;
+       ret = psp_get_fw_reservation_info(psp, GFX_CMD_ID_FB_FW_RESERV_EXT_ADDR, &reserv_addr_ext, &reserv_size_ext);
+       if (ret)
+               return ret;
+
+       if (reserv_addr != adev->gmc.real_vram_size - reserv_size) {
+               dev_warn(adev->dev, "reserve fw region is not valid!\n");
+               return 0;
+       }
+
+       amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL, NULL);
+
+       reserv_size = roundup(reserv_size, SZ_1M);
+
+       ret = amdgpu_bo_create_kernel_at(adev, reserv_addr, reserv_size, &adev->mman.fw_reserved_memory, NULL);
+       if (ret) {
+               dev_err(adev->dev, "reserve fw region failed(%d)!\n", ret);
+               amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL, NULL);
+               return ret;
+       }
+
+       reserv_size_ext = roundup(reserv_size_ext, SZ_1M);
+
+       ret = amdgpu_bo_create_kernel_at(adev, reserv_addr_ext, reserv_size_ext,
+                                        &adev->mman.fw_reserved_memory_extend, NULL);
+       if (ret) {
+               dev_err(adev->dev, "reserve extend fw region failed(%d)!\n", ret);
+               amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory_extend, NULL, NULL);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
 {
        struct psp_context *psp = &adev->psp;
@@ -2464,6 +2555,14 @@ static int psp_hw_start(struct psp_context *psp)
                return ret;
        }
 
+       if (!amdgpu_in_reset(adev) && !adev->in_suspend) {
+               ret = psp_update_fw_reservation(psp);
+               if (ret) {
+                       dev_err(adev->dev, "update fw reservation failed!\n");
+                       return ret;
+               }
+       }
+
        if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
                goto skip_pin_bo;
 
index 428adc7f741de39ffdbfe76769bf345287de97a4..dbc8e1950e4e8c1e988fd450ef3031a94ad1e5e5 100644 (file)
@@ -588,7 +588,7 @@ int psp_init_cap_microcode(struct psp_context *psp,
                          const char *chip_name);
 int psp_get_fw_attestation_records_addr(struct psp_context *psp,
                                        uint64_t *output_ptr);
-
+int psp_update_fw_reservation(struct psp_context *psp);
 int psp_load_fw_list(struct psp_context *psp,
                     struct amdgpu_firmware_info **ucode_list, int ucode_count);
 void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
index 9c5df35f05b7b86396957756e6ae1c2d319b27b9..984fe8c6d4807c2bcfc9ab0ffc9d6b34c017d5e8 100644 (file)
@@ -2060,6 +2060,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
                /* return the FW reserved memory back to VRAM */
                amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL,
                                      NULL);
+               amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory_extend, NULL,
+                                     NULL);
                if (adev->mman.stolen_reserved_size)
                        amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory,
                                              NULL, NULL);
index 208b7d1d8a277bd8463b836a7d3d0a49822325dc..215c198e4aff7b995309c37c138685b81551352a 100644 (file)
@@ -86,6 +86,7 @@ struct amdgpu_mman {
        uint32_t                        discovery_tmr_size;
        /* fw reserved memory */
        struct amdgpu_bo                *fw_reserved_memory;
+       struct amdgpu_bo                *fw_reserved_memory_extend;
 
        /* firmware VRAM reservation */
        u64             fw_vram_usage_start_offset;
index f4a91b126c73c211188f59fc75a5091699a50746..73f87131a7e9f0161f953881640bc54a41859149 100644 (file)
@@ -106,7 +106,9 @@ enum psp_gfx_cmd_id
     /*IDs of performance monitoring/profiling*/
     GFX_CMD_ID_CONFIG_SQ_PERFMON  = 0x00000046,   /* Config CGTT_SQ_CLK_CTRL */
     /* Dynamic memory partitioninig (NPS mode change)*/
-    GFX_CMD_ID_FB_NPS_MODE         = 0x00000048,  /* Configure memory partitioning mode */
+    GFX_CMD_ID_FB_NPS_MODE        = 0x00000048,  /* Configure memory partitioning mode */
+    GFX_CMD_ID_FB_FW_RESERV_ADDR  = 0x00000050,  /* Query FW reservation addr */
+    GFX_CMD_ID_FB_FW_RESERV_EXT_ADDR = 0x00000051,  /* Query FW reservation extended addr */
 };
 
 /* PSP boot config sub-commands */
@@ -404,11 +406,19 @@ struct psp_gfx_uresp_bootcfg {
        uint32_t boot_cfg;      /* boot config data */
 };
 
+/* Command-specific response for fw reserve info */
+struct psp_gfx_uresp_fw_reserve_info {
+    uint32_t reserve_base_address_hi;
+    uint32_t reserve_base_address_lo;
+    uint32_t reserve_size;
+};
+
 /* Union of command-specific responses for GPCOM ring. */
 union psp_gfx_uresp {
        struct psp_gfx_uresp_reserved           reserved;
        struct psp_gfx_uresp_bootcfg            boot_cfg;
        struct psp_gfx_uresp_fwar_db_info       fwar_db_info;
+       struct psp_gfx_uresp_fw_reserve_info    fw_reserve_info;
 };
 
 /* Structure of GFX Response buffer.