Commit a3b7f9c3 authored by Frank Min's avatar Frank Min Committed by Alex Deucher
Browse files

drm/amdgpu: reclaim psp fw reservation memory region



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: default avatarFrank Min <Frank.Min@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e2d1e96c
Loading
Loading
Loading
Loading
+99 −0
Original line number Diff line number Diff line
@@ -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;

+1 −1
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;
+11 −1
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ enum psp_gfx_cmd_id
    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_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.