Commit 01bdc7e2 authored by Hawking Zhang's avatar Hawking Zhang Committed by Alex Deucher
Browse files

drm/amdgpu: New interface to get IP discovery binary v3



Implement a driver path to read the IP discovery
binary offset and size from DRIVER_SCRATCH registers
BIOS signals usage by setting a feature flag that
instructs the driver to use this method. Otherwise,
fallback to legacy approach.

v2: Simplify discovery offset/size retrieval in
get_tmr_info

v3: Update get_tmr_info to cover discovery offset
and size retrieval for both bare-metal and sriov

Signed-off-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: default avatarLikun Gao <Likun.Gao@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 47ab777c
Loading
Loading
Loading
Loading
+92 −73
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ MODULE_FIRMWARE("amdgpu/picasso_ip_discovery.bin");
MODULE_FIRMWARE("amdgpu/arcturus_ip_discovery.bin");
MODULE_FIRMWARE("amdgpu/aldebaran_ip_discovery.bin");

/* Note: These registers are consistent across all the SOCs */
#define mmIP_DISCOVERY_VERSION  0x16A00
#define mmRCC_CONFIG_MEMSIZE	0xde3
#define mmMP0_SMN_C2PMSG_33	0x16061
@@ -139,6 +140,10 @@ MODULE_FIRMWARE("amdgpu/aldebaran_ip_discovery.bin");
#define mmMM_INDEX_HI		0x6
#define mmMM_DATA		0x1

#define mmDRIVER_SCRATCH_0	0x94
#define mmDRIVER_SCRATCH_1	0x95
#define mmDRIVER_SCRATCH_2	0x96

static const char *hw_id_names[HW_ID_MAX] = {
	[MP1_HWID]		= "MP1",
	[MP2_HWID]		= "MP2",
@@ -253,39 +258,12 @@ static int hw_id_map[MAX_HWIP] = {
	[ATU_HWIP]	= ATU_HWID,
};

static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
{
	u64 tmr_offset, tmr_size, pos;
	void *discv_regn;
	int ret;

	ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
	if (ret)
		return ret;

	pos = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;

	/* This region is read-only and reserved from system use */
	discv_regn = memremap(pos, adev->discovery.size, MEMREMAP_WC);
	if (discv_regn) {
		memcpy(binary, discv_regn, adev->discovery.size);
		memunmap(discv_regn);
		return 0;
	}

	return -ENOENT;
}

#define IP_DISCOVERY_V2		2
#define IP_DISCOVERY_V4		4

static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
						 uint8_t *binary)
static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
					 bool *is_tmr_in_sysmem)
{
	bool sz_valid = true;
	uint64_t vram_size;
	int i, ret = 0;
	u32 msg;
	u64 vram_size, tmr_offset, tmr_size;
	u32 msg, tmr_offset_lo, tmr_offset_hi;
	int i, ret;

	if (!amdgpu_sriov_vf(adev)) {
		/* It can take up to two second for IFWI init to complete on some dGPUs,
@@ -305,45 +283,87 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
	}

	vram_size = RREG32(mmRCC_CONFIG_MEMSIZE);
	if (!vram_size || vram_size == U32_MAX)
		sz_valid = false;
	if (vram_size == U32_MAX)
		return -ENXIO;
	else if (!vram_size)
		*is_tmr_in_sysmem = true;
	else
		vram_size <<= 20;
		*is_tmr_in_sysmem = false;

	/* init the default tmr size and offset */
	adev->discovery.size = DISCOVERY_TMR_SIZE;
	if (vram_size)
		adev->discovery.offset = (vram_size << 20) - DISCOVERY_TMR_OFFSET;

	/*
	 * If in VRAM, discovery TMR is marked for reservation. If it is in system mem,
	 * then it is not required to be reserved.
	 */
	if (sz_valid) {
	if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
			/* For SRIOV VFs with dynamic critical region enabled,
			 * we will get the IPD binary via below call.
			 * If dynamic critical is disabled, fall through to normal seq.
			 */
			if (amdgpu_virt_get_dynamic_data_info(adev,
						AMD_SRIOV_MSG_IPD_TABLE_ID, binary,
						&adev->discovery.size)) {
				dev_err(adev->dev,
						"failed to read discovery info from dynamic critical region.");
				ret = -EINVAL;
				goto exit;
			}
		adev->discovery.offset =
			adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset;
		adev->discovery.size =
			adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10;
		if (!adev->discovery.offset || !adev->discovery.size)
			return -EINVAL;
	} else {
			uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
		tmr_size = RREG32(mmDRIVER_SCRATCH_2);
		if (tmr_size) {
			/* It's preferred to transition to PSP mailbox reg interface
			 * for both bare-metal and passthrough if available */
			adev->discovery.size = (u32)tmr_size;
			tmr_offset_lo = RREG32(mmDRIVER_SCRATCH_0);
			tmr_offset_hi = RREG32(mmDRIVER_SCRATCH_1);
			adev->discovery.offset = ((u64)le32_to_cpu(tmr_offset_hi) << 32 |
						  le32_to_cpu(tmr_offset_lo));
		} else if (!vram_size) {
			/* fall back to apci approach to query tmr offset if vram_size is 0 */
			ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
			if (ret)
				return ret;
			adev->discovery.size = (u32)tmr_size;
			adev->discovery.offset = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;
		}
	}

	adev->discovery.bin = kzalloc(adev->discovery.size, GFP_KERNEL);
	if (!adev->discovery.bin)
		return -ENOMEM;
	adev->discovery.debugfs_blob.data = adev->discovery.bin;
	adev->discovery.debugfs_blob.size = adev->discovery.size;

	return 0;
}

static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
{
	void *discv_regn;

	/* This region is read-only and reserved from system use */
	discv_regn = memremap(adev->discovery.offset, adev->discovery.size, MEMREMAP_WC);
	if (discv_regn) {
		memcpy(binary, discv_regn, adev->discovery.size);
		memunmap(discv_regn);
		return 0;
	}

	return -ENOENT;
}

#define IP_DISCOVERY_V2		2
#define IP_DISCOVERY_V4		4

			amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
						 uint8_t *binary,
						 bool is_tmr_in_sysmem)
{
	int ret = 0;

	if (!is_tmr_in_sysmem) {
		amdgpu_device_vram_access(adev, adev->discovery.offset,
					  (uint32_t *)binary,
					  adev->discovery.size, false);
		adev->discovery.reserve_tmr = true;
		}
	} else {
		ret = amdgpu_discovery_read_binary_from_sysmem(adev, binary);
	}

	if (ret)
		dev_err(adev->dev,
			"failed to read discovery info from memory, vram size read: %llx",
			vram_size);
exit:
	return ret;
}

@@ -602,14 +622,12 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
	uint16_t size;
	uint16_t checksum;
	uint16_t table_id;
	bool is_tmr_in_sysmem;
	int r;

	adev->discovery.bin = kzalloc(DISCOVERY_TMR_SIZE, GFP_KERNEL);
	if (!adev->discovery.bin)
		return -ENOMEM;
	adev->discovery.size = DISCOVERY_TMR_SIZE;
	adev->discovery.debugfs_blob.data = adev->discovery.bin;
	adev->discovery.debugfs_blob.size = adev->discovery.size;
	r = amdgpu_discovery_get_tmr_info(adev, &is_tmr_in_sysmem);
	if (r)
		return r;

	discovery_bin = adev->discovery.bin;
	/* Read from file if it is the preferred option */
@@ -622,7 +640,8 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
			goto out;
	} else {
		drm_dbg(&adev->ddev, "use ip discovery information from memory");
		r = amdgpu_discovery_read_binary_from_mem(adev, discovery_bin);
		r = amdgpu_discovery_read_binary_from_mem(adev, discovery_bin,
							  is_tmr_in_sysmem);
		if (r)
			goto out;
	}
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ struct drm_printer;
struct amdgpu_discovery_info {
	struct debugfs_blob_wrapper debugfs_blob;
	struct ip_discovery_top *ip_top;
	uint64_t offset;
	uint32_t size;
	uint8_t *bin;
	bool reserve_tmr;