mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Likun Gao <Likun.Gao@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
47ab777c16
commit
01bdc7e219
|
|
@ -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)
|
||||
static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
|
||||
bool *is_tmr_in_sysmem)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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,51 +283,93 @@ 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
} else {
|
||||
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||
/* 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;
|
||||
|
||||
amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
|
||||
adev->discovery.size, false);
|
||||
adev->discovery.reserve_tmr = true;
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
|
||||
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 {
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev,
|
||||
uint8_t *binary,
|
||||
const char *fw_name)
|
||||
uint8_t *binary,
|
||||
const char *fw_name)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int r;
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user