* [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets @ 2025-10-09 3:31 Ellen Pan 2025-10-09 12:31 ` Christian König 2025-10-09 15:24 ` Lazar, Lijo 0 siblings, 2 replies; 5+ messages in thread From: Ellen Pan @ 2025-10-09 3:31 UTC (permalink / raw) To: amd-gfx; +Cc: Alexander.Deucher, Christian.Koenig, Shravankumar.Gande, Ellen Pan 1. Added VF logic to init IP discovery using the offsets from dynamic(v2) critical regions; 2. Added VF logic to init bios image using the offsets from dynamic(v2) critical regions; Signed-off-by: Ellen Pan <yunru.pan@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 12 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 5 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 47 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 3 ++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 00e96419fcda..2cbb24ede86e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -114,7 +114,17 @@ static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev) adev->bios = NULL; vram_base = pci_resource_start(adev->pdev, 0); - bios = ioremap_wc(vram_base, size); + + if (amdgpu_sriov_vf(adev) && adev->virt.init_data_done) { + resource_size_t bios_offset; + + if (amdgpu_virt_get_bios_info(adev, &bios_offset, &size)) + return false; + + bios = ioremap_wc(vram_base + bios_offset, size); + } else + bios = ioremap_wc(vram_base, size); + if (!bios) return false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 73401f0aeb34..0dd9ff576cdc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -292,6 +292,11 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, } } + if ((adev->virt.req_init_data_ver == GPU_CRIT_REGION_V2) && adev->virt.init_data_done) { + ret = amdgpu_virt_init_ip_discovery(adev, binary); + return ret; + } + vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); if (!vram_size || vram_size == U32_MAX) sz_valid = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index e9dbab53cb06..9181acef4e9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -954,6 +954,53 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev) return r; } +int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t *binary) +{ + uint32_t ip_discovery_offset = + adev->virt.crit_region_offsets[AMD_SRIOV_MSG_IPD_TABLE_ID]; + uint32_t ip_discovery_size = + adev->virt.crit_region_sizes_kb[AMD_SRIOV_MSG_IPD_TABLE_ID] << 10; + uint64_t pos = 0; + + dev_info(adev->dev, "use ip discovery information copied from dynamic crit_region_table at offset 0x%x with size of 0x%x bytes.\n", ip_discovery_offset, ip_discovery_size); + + if (!IS_ALIGNED(ip_discovery_offset, 4) || !IS_ALIGNED(ip_discovery_size, 4)) { + DRM_ERROR("IP discovery data not aligned to 4 bytes\n"); + return -EINVAL; + } + + if (ip_discovery_size > DISCOVERY_TMR_SIZE) { + DRM_ERROR("Invalid IP discovery size: 0x%x\n", ip_discovery_size); + return -EINVAL; + } + + pos = (uint64_t)ip_discovery_offset; + amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, + ip_discovery_size, false); + + return 0; +} + +int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, + resource_size_t *bios_offset, resource_size_t *bios_size) +{ + uint32_t vbios_offset = adev->virt.crit_region_offsets[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID]; + uint32_t vbios_size = + adev->virt.crit_region_sizes_kb[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID] << 10; + + dev_info(adev->dev, "use bios information copied from dynamic crit_region_table at offset 0x%x with size of 0x%x bytes.\n", vbios_offset, vbios_size); + + if (vbios_size > *bios_size) { + DRM_ERROR("Invalid vbios size: 0x%x\n", vbios_size); + return -EINVAL; + } + + *bios_offset = vbios_offset; + *bios_size = vbios_size; + + return 0; +} + void amdgpu_virt_init(struct amdgpu_device *adev) { bool is_sriov = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 5f6014b2f349..d122347ff666 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -434,6 +434,9 @@ void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev); void amdgpu_virt_init(struct amdgpu_device *adev); int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); +int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t *binary); +int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, + resource_size_t *bios_offset, resource_size_t *bios_size); bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets 2025-10-09 3:31 [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan @ 2025-10-09 12:31 ` Christian König 2025-10-09 15:24 ` Lazar, Lijo 1 sibling, 0 replies; 5+ messages in thread From: Christian König @ 2025-10-09 12:31 UTC (permalink / raw) To: Ellen Pan, amd-gfx; +Cc: Alexander.Deucher, Shravankumar.Gande On 09.10.25 05:31, Ellen Pan wrote: > 1. Added VF logic to init IP discovery using the offsets from dynamic(v2) critical regions; > 2. Added VF logic to init bios image using the offsets from dynamic(v2) critical regions; > > Signed-off-by: Ellen Pan <yunru.pan@amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 12 ++++- > drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 5 ++ > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 47 +++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 3 ++ > 4 files changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c > index 00e96419fcda..2cbb24ede86e 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c > @@ -114,7 +114,17 @@ static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev) > > adev->bios = NULL; > vram_base = pci_resource_start(adev->pdev, 0); > - bios = ioremap_wc(vram_base, size); > + > + if (amdgpu_sriov_vf(adev) && adev->virt.init_data_done) { > + resource_size_t bios_offset; > + > + if (amdgpu_virt_get_bios_info(adev, &bios_offset, &size)) > + return false; > + > + bios = ioremap_wc(vram_base + bios_offset, size); > + } else > + bios = ioremap_wc(vram_base, size); > + It would probably better to give offset as parameter to amdgpu_read_bios_from_vram(). There is already a comment saying "this is required for SR-IOV" where that code would make perfect sense. > if (!bios) > return false; > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c > index 73401f0aeb34..0dd9ff576cdc 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c > @@ -292,6 +292,11 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, > } > } > > + if ((adev->virt.req_init_data_ver == GPU_CRIT_REGION_V2) && adev->virt.init_data_done) { > + ret = amdgpu_virt_init_ip_discovery(adev, binary); > + return ret; > + } > + It is probably better to rework the code here and put all the SRIOV handling into the calling function. And then call either amdgpu_discovery_read_binary_from_mem() or amdgpu_virt_init_ip_discovery() and not delegate the call to another function after calling the first one. > vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); > if (!vram_size || vram_size == U32_MAX) > sz_valid = false; > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c > index e9dbab53cb06..9181acef4e9b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c > @@ -954,6 +954,53 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev) > return r; > } > > +int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t *binary) > +{ > + uint32_t ip_discovery_offset = > + adev->virt.crit_region_offsets[AMD_SRIOV_MSG_IPD_TABLE_ID]; > + uint32_t ip_discovery_size = > + adev->virt.crit_region_sizes_kb[AMD_SRIOV_MSG_IPD_TABLE_ID] << 10; > + uint64_t pos = 0; > + > + dev_info(adev->dev, "use ip discovery information copied from dynamic crit_region_table at offset 0x%x with size of 0x%x bytes.\n", ip_discovery_offset, ip_discovery_size); That line is to long, please use checkpatch.pl. > + > + if (!IS_ALIGNED(ip_discovery_offset, 4) || !IS_ALIGNED(ip_discovery_size, 4)) { > + DRM_ERROR("IP discovery data not aligned to 4 bytes\n"); > + return -EINVAL; > + } > + > + if (ip_discovery_size > DISCOVERY_TMR_SIZE) { > + DRM_ERROR("Invalid IP discovery size: 0x%x\n", ip_discovery_size); > + return -EINVAL; > + } > + > + pos = (uint64_t)ip_discovery_offset; > + amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, > + ip_discovery_size, false); > + > + return 0; > +} > + > +int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, > + resource_size_t *bios_offset, resource_size_t *bios_size) > +{ > + uint32_t vbios_offset = adev->virt.crit_region_offsets[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID]; > + uint32_t vbios_size = > + adev->virt.crit_region_sizes_kb[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID] << 10; > + > + dev_info(adev->dev, "use bios information copied from dynamic crit_region_table at offset 0x%x with size of 0x%x bytes.\n", vbios_offset, vbios_size); Same here. Regards, Christian. > + > + if (vbios_size > *bios_size) { > + DRM_ERROR("Invalid vbios size: 0x%x\n", vbios_size); > + return -EINVAL; > + } > + > + *bios_offset = vbios_offset; > + *bios_size = vbios_size; > + > + return 0; > +} > + > void amdgpu_virt_init(struct amdgpu_device *adev) > { > bool is_sriov = false; > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h > index 5f6014b2f349..d122347ff666 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h > @@ -434,6 +434,9 @@ void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev); > void amdgpu_virt_init(struct amdgpu_device *adev); > > int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); > +int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t *binary); > +int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, > + resource_size_t *bios_offset, resource_size_t *bios_size); > > bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); > int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); ^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets 2025-10-09 3:31 [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan 2025-10-09 12:31 ` Christian König @ 2025-10-09 15:24 ` Lazar, Lijo 1 sibling, 0 replies; 5+ messages in thread From: Lazar, Lijo @ 2025-10-09 15:24 UTC (permalink / raw) To: Pan, Ellen, amd-gfx@lists.freedesktop.org Cc: Deucher, Alexander, Koenig, Christian, Gande, Shravan kumar, Pan, Ellen [Public] >-----Original Message----- >From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Ellen >Pan >Sent: Thursday, October 9, 2025 9:01 AM >To: amd-gfx@lists.freedesktop.org >Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian ><Christian.Koenig@amd.com>; Gande, Shravan kumar ><Shravankumar.Gande@amd.com>; Pan, Ellen <Yunru.Pan@amd.com> >Subject: [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init >from dynamic crit_region offsets > >1. Added VF logic to init IP discovery using the offsets from dynamic(v2) critical >regions; 2. Added VF logic to init bios image using the offsets from dynamic(v2) >critical regions; > >Signed-off-by: Ellen Pan <yunru.pan@amd.com> >--- > drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 12 ++++- > drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 5 ++ > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 47 >+++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 3 ++ > 4 files changed, 66 insertions(+), 1 deletion(-) > >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >index 00e96419fcda..2cbb24ede86e 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >@@ -114,7 +114,17 @@ static bool amdgpu_read_bios_from_vram(struct >amdgpu_device *adev) > > adev->bios = NULL; > vram_base = pci_resource_start(adev->pdev, 0); >- bios = ioremap_wc(vram_base, size); >+ >+ if (amdgpu_sriov_vf(adev) && adev->virt.init_data_done) { >+ resource_size_t bios_offset; >+ >+ if (amdgpu_virt_get_bios_info(adev, &bios_offset, &size)) >+ return false; >+ >+ bios = ioremap_wc(vram_base + bios_offset, size); >+ } else >+ bios = ioremap_wc(vram_base, size); >+ > if (!bios) > return false; > >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >index 73401f0aeb34..0dd9ff576cdc 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >@@ -292,6 +292,11 @@ static int >amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, > } > } > >+ if ((adev->virt.req_init_data_ver == GPU_CRIT_REGION_V2) && adev- >>virt.init_data_done) { >+ ret = amdgpu_virt_init_ip_discovery(adev, binary); >+ return ret; >+ } [lijo] For bios and discovery, could you keep it uniform - either virt_functions reads/returns the binary/size on its own way or returns the size/offset for both? Thanks, Lijo >+ > vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); > if (!vram_size || vram_size == U32_MAX) > sz_valid = false; >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >index e9dbab53cb06..9181acef4e9b 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >@@ -954,6 +954,53 @@ int amdgpu_virt_init_critical_region(struct >amdgpu_device *adev) > return r; > } > >+int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t >+*binary) { >+ uint32_t ip_discovery_offset = >+ adev- >>virt.crit_region_offsets[AMD_SRIOV_MSG_IPD_TABLE_ID]; >+ uint32_t ip_discovery_size = >+ adev- >>virt.crit_region_sizes_kb[AMD_SRIOV_MSG_IPD_TABLE_ID] << 10; >+ uint64_t pos = 0; >+ >+ dev_info(adev->dev, "use ip discovery information copied from >dynamic >+crit_region_table at offset 0x%x with size of 0x%x bytes.\n", >+ip_discovery_offset, ip_discovery_size); >+ >+ if (!IS_ALIGNED(ip_discovery_offset, 4) || >!IS_ALIGNED(ip_discovery_size, 4)) { >+ DRM_ERROR("IP discovery data not aligned to 4 bytes\n"); >+ return -EINVAL; >+ } >+ >+ if (ip_discovery_size > DISCOVERY_TMR_SIZE) { >+ DRM_ERROR("Invalid IP discovery size: 0x%x\n", >ip_discovery_size); >+ return -EINVAL; >+ } >+ >+ pos = (uint64_t)ip_discovery_offset; >+ amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, >+ ip_discovery_size, false); >+ >+ return 0; >+} >+ >+int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, >+ resource_size_t *bios_offset, resource_size_t *bios_size) { >+ uint32_t vbios_offset = adev- >>virt.crit_region_offsets[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID]; >+ uint32_t vbios_size = >+ adev- >>virt.crit_region_sizes_kb[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID] << >+10; >+ >+ dev_info(adev->dev, "use bios information copied from dynamic >+crit_region_table at offset 0x%x with size of 0x%x bytes.\n", >+vbios_offset, vbios_size); >+ >+ if (vbios_size > *bios_size) { >+ DRM_ERROR("Invalid vbios size: 0x%x\n", vbios_size); >+ return -EINVAL; >+ } >+ >+ *bios_offset = vbios_offset; >+ *bios_size = vbios_size; >+ >+ return 0; >+} >+ > void amdgpu_virt_init(struct amdgpu_device *adev) { > bool is_sriov = false; >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >index 5f6014b2f349..d122347ff666 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >@@ -434,6 +434,9 @@ void amdgpu_virt_fini_data_exchange(struct >amdgpu_device *adev); void amdgpu_virt_init(struct amdgpu_device *adev); > > int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); >+int amdgpu_virt_init_ip_discovery(struct amdgpu_device *adev, uint8_t >+*binary); int amdgpu_virt_get_bios_info(struct amdgpu_device *adev, >+ resource_size_t *bios_offset, >resource_size_t *bios_size); > > bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); int >amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); >-- >2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/6] drm/amdgpu: Updated naming of SRIOV critical region offsets/sizes with _V1 suffix @ 2025-10-10 4:43 Ellen Pan 2025-10-10 4:43 ` [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan 0 siblings, 1 reply; 5+ messages in thread From: Ellen Pan @ 2025-10-10 4:43 UTC (permalink / raw) To: amd-gfx Cc: Alexander.Deucher, Christian.Koenig, Lijo.Lazar, Jeffrey.Chan, Ellen Pan - This change prepares the later patches to intro _v2 suffix to SRIOV critical regions Signed-off-by: Ellen Pan <yunru.pan@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 20 ++++---- drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 57 ++++++++++++++------- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 3328ab63376b..e95adf0407a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -686,7 +686,7 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) /* got through this logic in early init stage to get necessary flags, e.g. rlcg_acc related*/ adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *) - (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); + (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10)); amdgpu_virt_read_pf2vf_data(adev); } @@ -703,21 +703,21 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev) if (adev->mman.fw_vram_usage_va) { adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *) - (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); + (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10)); adev->virt.fw_reserve.p_vf2pf = (struct amd_sriov_msg_vf2pf_info_header *) - (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10)); + (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10)); adev->virt.fw_reserve.ras_telemetry = - (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB << 10)); + (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10)); } else if (adev->mman.drv_vram_usage_va) { adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *) - (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); + (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10)); adev->virt.fw_reserve.p_vf2pf = (struct amd_sriov_msg_vf2pf_info_header *) - (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10)); + (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10)); adev->virt.fw_reserve.ras_telemetry = - (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB << 10)); + (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10)); } amdgpu_virt_read_pf2vf_data(adev); @@ -1304,7 +1304,7 @@ static int amdgpu_virt_cache_host_error_counts(struct amdgpu_device *adev, checksum = host_telemetry->header.checksum; used_size = host_telemetry->header.used_size; - if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10)) + if (used_size > (AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1 << 10)) return 0; tmp = kmemdup(&host_telemetry->body.error_count, used_size, GFP_KERNEL); @@ -1383,7 +1383,7 @@ amdgpu_virt_write_cpers_to_ring(struct amdgpu_device *adev, checksum = host_telemetry->header.checksum; used_size = host_telemetry->header.used_size; - if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10)) + if (used_size > (AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1 << 10)) return -EINVAL; cper_dump = kmemdup(&host_telemetry->body.cper_dump, used_size, GFP_KERNEL); @@ -1515,7 +1515,7 @@ static int amdgpu_virt_cache_chk_criti_hit(struct amdgpu_device *adev, checksum = host_telemetry->header.checksum; used_size = host_telemetry->header.used_size; - if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10)) + if (used_size > (AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1 << 10)) return 0; tmp = kmemdup(&host_telemetry->body.chk_criti, used_size, GFP_KERNEL); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index 3a79ed7d8031..3b35154e2df6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -23,26 +23,47 @@ #ifndef AMDGV_SRIOV_MSG__H_ #define AMDGV_SRIOV_MSG__H_ -/* unit in kilobytes */ -#define AMD_SRIOV_MSG_VBIOS_OFFSET 0 -#define AMD_SRIOV_MSG_VBIOS_SIZE_KB 64 -#define AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB AMD_SRIOV_MSG_VBIOS_SIZE_KB -#define AMD_SRIOV_MSG_DATAEXCHANGE_SIZE_KB 4 -#define AMD_SRIOV_MSG_TMR_OFFSET_KB 2048 -#define AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB 2 -#define AMD_SRIOV_RAS_TELEMETRY_SIZE_KB 64 /* - * layout + * layout v1 * 0 64KB 65KB 66KB 68KB 132KB * | VBIOS | PF2VF | VF2PF | Bad Page | RAS Telemetry Region | ... * | 64KB | 1KB | 1KB | 2KB | 64KB | ... */ -#define AMD_SRIOV_MSG_SIZE_KB 1 -#define AMD_SRIOV_MSG_PF2VF_OFFSET_KB AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB -#define AMD_SRIOV_MSG_VF2PF_OFFSET_KB (AMD_SRIOV_MSG_PF2VF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB) -#define AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB (AMD_SRIOV_MSG_VF2PF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB) -#define AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB (AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB + AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB) +/* + * layout v2 (offsets are dynamically allocated and the offsets below are examples) + * 0 1KB 64KB 65KB 66KB 68KB 132KB + * | INITD_H | VBIOS | PF2VF | VF2PF | Bad Page | RAS Telemetry Region | ... + * | 1KB | 64KB | 1KB | 1KB | 2KB | 64KB | ... + * + * Note: PF2VF + VF2PF + Bad Page = DataExchange region (allocated contiguously) + */ + +/* v1 layout sizes */ +#define AMD_SRIOV_MSG_VBIOS_SIZE_KB_V1 64 +#define AMD_SRIOV_MSG_PF2VF_SIZE_KB_V1 1 +#define AMD_SRIOV_MSG_VF2PF_SIZE_KB_V1 1 +#define AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB_V1 2 +#define AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1 64 +#define AMD_SRIOV_MSG_DATAEXCHANGE_SIZE_KB_V1 \ + (AMD_SRIOV_MSG_PF2VF_SIZE_KB_V1 + AMD_SRIOV_MSG_VF2PF_SIZE_KB_V1 + \ + AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB_V1) + +/* v1 offsets */ +#define AMD_SRIOV_MSG_VBIOS_OFFSET_V1 0 +#define AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB_V1 AMD_SRIOV_MSG_VBIOS_SIZE_KB_V1 +#define AMD_SRIOV_MSG_TMR_OFFSET_KB 2048 +#define AMD_SRIOV_MSG_SIZE_KB_V1 1 +#define AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB_V1 +#define AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 \ + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 + AMD_SRIOV_MSG_SIZE_KB_V1) +#define AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB_V1 \ + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 + AMD_SRIOV_MSG_SIZE_KB_V1) +#define AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 \ + (AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB_V1 + AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB_V1) +#define AMD_SRIOV_MSG_INIT_DATA_TOT_SIZE_KB_V1 \ + (AMD_SRIOV_MSG_VBIOS_SIZE_KB_V1 + AMD_SRIOV_MSG_DATAEXCHANGE_SIZE_KB_V1 + \ + AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1) /* * PF2VF history log: @@ -436,12 +457,12 @@ unsigned int amd_sriov_msg_checksum(void *obj, unsigned long obj_size, unsigned #define _stringification(s) #s _Static_assert( - sizeof(struct amd_sriov_msg_vf2pf_info) == AMD_SRIOV_MSG_SIZE_KB << 10, - "amd_sriov_msg_vf2pf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB) " KB"); + sizeof(struct amd_sriov_msg_vf2pf_info) == AMD_SRIOV_MSG_SIZE_KB_V1 << 10, + "amd_sriov_msg_vf2pf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB_V1) " KB"); _Static_assert( - sizeof(struct amd_sriov_msg_pf2vf_info) == AMD_SRIOV_MSG_SIZE_KB << 10, - "amd_sriov_msg_pf2vf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB) " KB"); + sizeof(struct amd_sriov_msg_pf2vf_info) == AMD_SRIOV_MSG_SIZE_KB_V1 << 10, + "amd_sriov_msg_pf2vf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB_V1) " KB"); _Static_assert(AMD_SRIOV_MSG_RESERVE_UCODE % 4 == 0, "AMD_SRIOV_MSG_RESERVE_UCODE must be multiple of 4"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets 2025-10-10 4:43 [PATCH 1/6] drm/amdgpu: Updated naming of SRIOV critical region offsets/sizes with _V1 suffix Ellen Pan @ 2025-10-10 4:43 ` Ellen Pan 2025-10-10 10:46 ` Lazar, Lijo 0 siblings, 1 reply; 5+ messages in thread From: Ellen Pan @ 2025-10-10 4:43 UTC (permalink / raw) To: amd-gfx Cc: Alexander.Deucher, Christian.Koenig, Lijo.Lazar, Jeffrey.Chan, Ellen Pan 1. Added VF logic in amdgpu_virt to init IP discovery using the offsets from dynamic(v2) critical regions; 2. Added VF logic in amdgpu_virt to init bios image using the offsets from dynamic(v2) critical regions; Signed-off-by: Ellen Pan <yunru.pan@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 26 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 33 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 107 ++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 + 5 files changed, 142 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2a0df4cabb99..d320118858bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -416,6 +416,7 @@ int amdgpu_device_ip_block_add(struct amdgpu_device *adev, /* * BIOS. */ +bool amdgpu_check_atom_bios(struct amdgpu_device *adev, size_t size); bool amdgpu_get_bios(struct amdgpu_device *adev); bool amdgpu_read_bios(struct amdgpu_device *adev); bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 00e96419fcda..787584956214 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -47,7 +47,7 @@ /* Check if current bios is an ATOM BIOS. * Return true if it is ATOM BIOS. Otherwise, return false. */ -static bool check_atom_bios(struct amdgpu_device *adev, size_t size) +bool amdgpu_check_atom_bios(struct amdgpu_device *adev, size_t size) { uint16_t tmp, bios_header_start; uint8_t *bios = adev->bios; @@ -96,7 +96,8 @@ void amdgpu_bios_release(struct amdgpu_device *adev) * part of the system bios. On boot, the system bios puts a * copy of the igp rom at the start of vram if a discrete card is * present. - * For SR-IOV, the vbios image is also put in VRAM in the VF. + * For SR-IOV, if dynamic critical region is not enabled, + * the vbios image is also put at the start of VRAM in the VF. */ static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev) { @@ -127,7 +128,7 @@ static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev) memcpy_fromio(adev->bios, bios, size); iounmap(bios); - if (!check_atom_bios(adev, size)) { + if (!amdgpu_check_atom_bios(adev, size)) { amdgpu_bios_release(adev); return false; } @@ -155,7 +156,7 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) memcpy_fromio(adev->bios, bios, size); pci_unmap_rom(adev->pdev, bios); - if (!check_atom_bios(adev, size)) { + if (!amdgpu_check_atom_bios(adev, size)) { amdgpu_bios_release(adev); return false; } @@ -195,7 +196,7 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev) /* read complete BIOS */ amdgpu_asic_read_bios_from_rom(adev, adev->bios, len); - if (!check_atom_bios(adev, len)) { + if (!amdgpu_check_atom_bios(adev, len)) { amdgpu_bios_release(adev); return false; } @@ -225,7 +226,7 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) memcpy_fromio(adev->bios, bios, romlen); iounmap(bios); - if (!check_atom_bios(adev, romlen)) + if (!amdgpu_check_atom_bios(adev, romlen)) goto free_bios; adev->bios_size = romlen; @@ -334,7 +335,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) break; } - if (!check_atom_bios(adev, size)) { + if (!amdgpu_check_atom_bios(adev, size)) { amdgpu_bios_release(adev); return false; } @@ -399,7 +400,7 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) vhdr->ImageLength, GFP_KERNEL); - if (!check_atom_bios(adev, vhdr->ImageLength)) { + if (!amdgpu_check_atom_bios(adev, vhdr->ImageLength)) { amdgpu_bios_release(adev); return false; } @@ -467,9 +468,14 @@ static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev) } /* this is required for SR-IOV */ - if (amdgpu_read_bios_from_vram(adev)) { - dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n"); + if (amdgpu_sriov_vf(adev) && amdgpu_virt_read_bios_from_vram(adev)) { + dev_info(adev->dev, "Fetched VBIOS from dynamic VRAM BAR\n"); goto success; + } else { + if (amdgpu_read_bios_from_vram(adev)) { + dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n"); + goto success; + } } if (amdgpu_prefer_rom_resource(adev)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 73401f0aeb34..de8676d6ff9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -275,21 +275,18 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, int i, ret = 0; u32 msg; - if (!amdgpu_sriov_vf(adev)) { - /* It can take up to two second for IFWI init to complete on some dGPUs, - * but generally it should be in the 60-100ms range. Normally this starts - * as soon as the device gets power so by the time the OS loads this has long - * completed. However, when a card is hotplugged via e.g., USB4, we need to - * wait for this to complete. Once the C2PMSG is updated, we can - * continue. - */ - - for (i = 0; i < 2000; i++) { - msg = RREG32(mmMP0_SMN_C2PMSG_33); - if (msg & 0x80000000) - break; - msleep(1); - } + /* It can take up to two second for IFWI init to complete on some dGPUs, + * but generally it should be in the 60-100ms range. Normally this starts + * as soon as the device gets power so by the time the OS loads this has long + * completed. However, when a card is hotplugged via e.g., USB4, we need to + * wait for this to complete. Once the C2PMSG is updated, we can + * continue. + */ + for (i = 0; i < 2000; i++) { + msg = RREG32(mmMP0_SMN_C2PMSG_33); + if (msg & 0x80000000) + break; + msleep(1); } vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); @@ -467,8 +464,10 @@ 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, adev->mman.discovery_bin); + if (amdgpu_sriov_vf(adev)) + r = amdgpu_virt_init_discovery_from_mem(adev, adev->mman.discovery_bin); + else + r = amdgpu_discovery_read_binary_from_mem(adev, adev->mman.discovery_bin); if (r) goto out; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 461e83728594..67d5f15a72a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -965,6 +965,113 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev) return r; } +int amdgpu_virt_init_discovery_from_mem(struct amdgpu_device *adev, uint8_t *binary) +{ + uint64_t vram_size; + uint32_t ip_discovery_offset, ip_discovery_size; + uint64_t pos = 0; + + /* Get dynamic offset for IPD if dynamic critical region is enabled */ + if (adev->virt.is_dynamic_crit_regn_enabled) { + ip_discovery_offset = + adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset; + ip_discovery_size = + adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10; + + dev_info(adev->dev, + "Got IPD info from dynamic crit_region at offset 0x%x with size of 0x%x bytes.\n", + ip_discovery_offset, ip_discovery_size); + + if (!IS_ALIGNED(ip_discovery_offset, 4) || !IS_ALIGNED(ip_discovery_size, 4)) { + dev_err(adev->dev, "IP discovery data not aligned to 4 bytes\n"); + return -EINVAL; + } + + if (ip_discovery_size > DISCOVERY_TMR_SIZE) { + dev_err(adev->dev, "Invalid IP discovery size: 0x%x\n", ip_discovery_size); + return -EINVAL; + } + + pos = (uint64_t)ip_discovery_offset; + amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, + ip_discovery_size, false); + } else { + vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); + if (!vram_size || vram_size == U32_MAX) + return -EINVAL; + + vram_size <<= 20; + + pos = vram_size - DISCOVERY_TMR_OFFSET; + amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, + adev->mman.discovery_tmr_size, false); + } + + return 0; +} + +/* For SR-IOV, if dynamic critical region is enabled, + * the vbios image is put at a dynamic offset of VRAM in the VF. + * If dynamic critical region is disabled, exit early to proceed + * the same seq as on baremetal. + */ +bool amdgpu_virt_read_bios_from_vram(struct amdgpu_device *adev) +{ + uint8_t __iomem *bios; + resource_size_t vram_base; + resource_size_t size = 256 * 1024; /* ??? */ + uint32_t vbios_offset = 0; + uint32_t vbios_size = 0; + + /* Exit early if it's not initialized */ + if (!adev->virt.is_dynamic_crit_regn_enabled) + return false; + + if (amdgpu_device_need_post(adev)) + return false; + + /* FB BAR not enabled */ + if (pci_resource_len(adev->pdev, 0) == 0) + return false; + + adev->bios = NULL; + vram_base = pci_resource_start(adev->pdev, 0); + + vbios_offset = adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].offset; + vbios_size = + adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].size_kb << 10; + if (vbios_size > size) { + dev_err(adev->dev, "Invalid vbios size: 0x%x\n", vbios_size); + return false; + } + + dev_info(adev->dev, + "Got bios info from dynamic crit_region_table at offset 0x%x with size of 0x%x bytes.\n", + vbios_offset, vbios_size); + + size = vbios_size; + + bios = ioremap_wc(vram_base + vbios_offset, size); + if (!bios) + return false; + + adev->bios = kmalloc(size, GFP_KERNEL); + if (!adev->bios) { + iounmap(bios); + return false; + } + adev->bios_size = size; + memcpy_fromio(adev->bios, bios, size); + iounmap(bios); + + if (!check_atom_bios(adev, size)) { + amdgpu_bios_release(adev); + return false; + } + + return true; +} + void amdgpu_virt_init(struct amdgpu_device *adev) { bool is_sriov = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index bc1fc1c6daba..f2aa306f4192 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -438,6 +438,8 @@ void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev); void amdgpu_virt_init(struct amdgpu_device *adev); int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); +int amdgpu_virt_init_discovery_from_mem(struct amdgpu_device *adev, uint8_t *binary); +bool amdgpu_virt_read_bios_from_vram(struct amdgpu_device *adev); bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* RE: [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets 2025-10-10 4:43 ` [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan @ 2025-10-10 10:46 ` Lazar, Lijo 0 siblings, 0 replies; 5+ messages in thread From: Lazar, Lijo @ 2025-10-10 10:46 UTC (permalink / raw) To: Pan, Ellen, amd-gfx@lists.freedesktop.org Cc: Deucher, Alexander, Koenig, Christian, Chan, Hing Pong [AMD Official Use Only - AMD Internal Distribution Only] >-----Original Message----- >From: Pan, Ellen <Yunru.Pan@amd.com> >Sent: Friday, October 10, 2025 10:13 AM >To: amd-gfx@lists.freedesktop.org >Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian ><Christian.Koenig@amd.com>; Lazar, Lijo <Lijo.Lazar@amd.com>; Chan, Hing >Pong <Jeffrey.Chan@amd.com>; Pan, Ellen <Yunru.Pan@amd.com> >Subject: [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init >from dynamic crit_region offsets > >1. Added VF logic in amdgpu_virt to init IP discovery using the offsets from >dynamic(v2) critical regions; 2. Added VF logic in amdgpu_virt to init bios image >using the offsets from dynamic(v2) critical regions; > >Signed-off-by: Ellen Pan <yunru.pan@amd.com> >--- > drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + > drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 26 +++-- > drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 33 +++--- > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 107 >++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 + > 5 files changed, 142 insertions(+), 27 deletions(-) > >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h >b/drivers/gpu/drm/amd/amdgpu/amdgpu.h >index 2a0df4cabb99..d320118858bc 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h >@@ -416,6 +416,7 @@ int amdgpu_device_ip_block_add(struct >amdgpu_device *adev, > /* > * BIOS. > */ >+bool amdgpu_check_atom_bios(struct amdgpu_device *adev, size_t size); > bool amdgpu_get_bios(struct amdgpu_device *adev); bool >amdgpu_read_bios(struct amdgpu_device *adev); bool >amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev, diff --git >a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >index 00e96419fcda..787584956214 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c >@@ -47,7 +47,7 @@ > /* Check if current bios is an ATOM BIOS. > * Return true if it is ATOM BIOS. Otherwise, return false. > */ >-static bool check_atom_bios(struct amdgpu_device *adev, size_t size) >+bool amdgpu_check_atom_bios(struct amdgpu_device *adev, size_t size) > { > uint16_t tmp, bios_header_start; > uint8_t *bios = adev->bios; >@@ -96,7 +96,8 @@ void amdgpu_bios_release(struct amdgpu_device *adev) > * part of the system bios. On boot, the system bios puts a > * copy of the igp rom at the start of vram if a discrete card is > * present. >- * For SR-IOV, the vbios image is also put in VRAM in the VF. >+ * For SR-IOV, if dynamic critical region is not enabled, >+ * the vbios image is also put at the start of VRAM in the VF. > */ > static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev) { >@@ -127,7 +128,7 @@ static bool amdgpu_read_bios_from_vram(struct >amdgpu_device *adev) > memcpy_fromio(adev->bios, bios, size); > iounmap(bios); > >- if (!check_atom_bios(adev, size)) { >+ if (!amdgpu_check_atom_bios(adev, size)) { > amdgpu_bios_release(adev); > return false; > } >@@ -155,7 +156,7 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) > memcpy_fromio(adev->bios, bios, size); > pci_unmap_rom(adev->pdev, bios); > >- if (!check_atom_bios(adev, size)) { >+ if (!amdgpu_check_atom_bios(adev, size)) { > amdgpu_bios_release(adev); > return false; > } >@@ -195,7 +196,7 @@ static bool amdgpu_read_bios_from_rom(struct >amdgpu_device *adev) > /* read complete BIOS */ > amdgpu_asic_read_bios_from_rom(adev, adev->bios, len); > >- if (!check_atom_bios(adev, len)) { >+ if (!amdgpu_check_atom_bios(adev, len)) { > amdgpu_bios_release(adev); > return false; > } >@@ -225,7 +226,7 @@ static bool amdgpu_read_platform_bios(struct >amdgpu_device *adev) > memcpy_fromio(adev->bios, bios, romlen); > iounmap(bios); > >- if (!check_atom_bios(adev, romlen)) >+ if (!amdgpu_check_atom_bios(adev, romlen)) > goto free_bios; > > adev->bios_size = romlen; >@@ -334,7 +335,7 @@ static bool amdgpu_atrm_get_bios(struct >amdgpu_device *adev) > break; > } > >- if (!check_atom_bios(adev, size)) { >+ if (!amdgpu_check_atom_bios(adev, size)) { > amdgpu_bios_release(adev); > return false; > } >@@ -399,7 +400,7 @@ static bool amdgpu_acpi_vfct_bios(struct >amdgpu_device *adev) > vhdr->ImageLength, > GFP_KERNEL); > >- if (!check_atom_bios(adev, vhdr->ImageLength)) { >+ if (!amdgpu_check_atom_bios(adev, vhdr- >>ImageLength)) { > amdgpu_bios_release(adev); > return false; > } >@@ -467,9 +468,14 @@ static bool amdgpu_get_bios_dgpu(struct >amdgpu_device *adev) > } > > /* this is required for SR-IOV */ >- if (amdgpu_read_bios_from_vram(adev)) { >- dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n"); >+ if (amdgpu_sriov_vf(adev) && >amdgpu_virt_read_bios_from_vram(adev)) { >+ dev_info(adev->dev, "Fetched VBIOS from dynamic VRAM >BAR\n"); > goto success; >+ } else { >+ if (amdgpu_read_bios_from_vram(adev)) { >+ dev_info(adev->dev, "Fetched VBIOS from VRAM >BAR\n"); >+ goto success; >+ } > } > > if (amdgpu_prefer_rom_resource(adev)) { diff --git >a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >index 73401f0aeb34..de8676d6ff9c 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c >@@ -275,21 +275,18 @@ static int >amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, > int i, ret = 0; > u32 msg; > >- if (!amdgpu_sriov_vf(adev)) { >- /* It can take up to two second for IFWI init to complete on >some dGPUs, >- * but generally it should be in the 60-100ms range. Normally >this starts >- * as soon as the device gets power so by the time the OS loads >this has long >- * completed. However, when a card is hotplugged via e.g., >USB4, we need to >- * wait for this to complete. Once the C2PMSG is updated, we >can >- * continue. >- */ >- >- for (i = 0; i < 2000; i++) { >- msg = RREG32(mmMP0_SMN_C2PMSG_33); >- if (msg & 0x80000000) >- break; >- msleep(1); >- } >+ /* It can take up to two second for IFWI init to complete on some >dGPUs, >+ * but generally it should be in the 60-100ms range. Normally this >starts >+ * as soon as the device gets power so by the time the OS loads this has >long >+ * completed. However, when a card is hotplugged via e.g., USB4, we >need to >+ * wait for this to complete. Once the C2PMSG is updated, we can >+ * continue. >+ */ >+ for (i = 0; i < 2000; i++) { >+ msg = RREG32(mmMP0_SMN_C2PMSG_33); >+ if (msg & 0x80000000) >+ break; >+ msleep(1); > } > > vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); @@ -467,8 >+464,10 @@ 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, adev->mman.discovery_bin); >+ if (amdgpu_sriov_vf(adev)) >+ r = amdgpu_virt_init_discovery_from_mem(adev, >adev->mman.discovery_bin); >+ else >+ r = amdgpu_discovery_read_binary_from_mem(adev, >+adev->mman.discovery_bin); > if (r) > goto out; > } >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >index 461e83728594..67d5f15a72a1 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c >@@ -965,6 +965,113 @@ int amdgpu_virt_init_critical_region(struct >amdgpu_device *adev) > return r; > } > >+int amdgpu_virt_init_discovery_from_mem(struct amdgpu_device *adev, >+uint8_t *binary) { >+ uint64_t vram_size; >+ uint32_t ip_discovery_offset, ip_discovery_size; >+ uint64_t pos = 0; >+ >+ /* Get dynamic offset for IPD if dynamic critical region is enabled */ >+ if (adev->virt.is_dynamic_crit_regn_enabled) { >+ ip_discovery_offset = >+ adev- >>virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset; >+ ip_discovery_size = >+ adev- >>virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10; >+ >+ dev_info(adev->dev, >+ "Got IPD info from dynamic crit_region at offset 0x%x >with size of 0x%x bytes.\n", >+ ip_discovery_offset, ip_discovery_size); >+ >+ if (!IS_ALIGNED(ip_discovery_offset, 4) || >!IS_ALIGNED(ip_discovery_size, 4)) { >+ dev_err(adev->dev, "IP discovery data not aligned to 4 >bytes\n"); >+ return -EINVAL; >+ } >+ >+ if (ip_discovery_size > DISCOVERY_TMR_SIZE) { >+ dev_err(adev->dev, "Invalid IP discovery size: 0x%x\n", >ip_discovery_size); >+ return -EINVAL; >+ } >+ >+ pos = (uint64_t)ip_discovery_offset; >+ amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, >+ ip_discovery_size, false); [lijo] The intent of my comment to the earlier version is only to fetch the binary and the corresponding size. u8 *bin; u32 size; r =amdgpu_virt_get_image(adev, BIOS, &bin, &size); r = 0 // Pass r = -EOPNOSUPP // Not supported Anything else = some real issue. Check BIOS etc. will be done inside amdgpu_bios file itself similar to how it is done for other methods. On unsupported ones, it continues with the legacy path. Same for discovery image as well - amdgpu_virt_get_image(adev, DISCOVERY, &bin, &size) Thanks, Lijo >+ } else { >+ vram_size = RREG32(mmRCC_CONFIG_MEMSIZE); >+ if (!vram_size || vram_size == U32_MAX) >+ return -EINVAL; >+ >+ vram_size <<= 20; >+ >+ pos = vram_size - DISCOVERY_TMR_OFFSET; >+ amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, >+ adev->mman.discovery_tmr_size, >false); >+ } >+ >+ return 0; >+} >+ >+/* For SR-IOV, if dynamic critical region is enabled, >+ * the vbios image is put at a dynamic offset of VRAM in the VF. >+ * If dynamic critical region is disabled, exit early to proceed >+ * the same seq as on baremetal. >+ */ >+bool amdgpu_virt_read_bios_from_vram(struct amdgpu_device *adev) { >+ uint8_t __iomem *bios; >+ resource_size_t vram_base; >+ resource_size_t size = 256 * 1024; /* ??? */ >+ uint32_t vbios_offset = 0; >+ uint32_t vbios_size = 0; >+ >+ /* Exit early if it's not initialized */ >+ if (!adev->virt.is_dynamic_crit_regn_enabled) >+ return false; >+ >+ if (amdgpu_device_need_post(adev)) >+ return false; >+ >+ /* FB BAR not enabled */ >+ if (pci_resource_len(adev->pdev, 0) == 0) >+ return false; >+ >+ adev->bios = NULL; >+ vram_base = pci_resource_start(adev->pdev, 0); >+ >+ vbios_offset = adev- >>virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].offset; >+ vbios_size = >+ adev- >>virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].size_kb << 10; >+ if (vbios_size > size) { >+ dev_err(adev->dev, "Invalid vbios size: 0x%x\n", vbios_size); >+ return false; >+ } >+ >+ dev_info(adev->dev, >+ "Got bios info from dynamic crit_region_table at offset 0x%x >with size of 0x%x bytes.\n", >+ vbios_offset, vbios_size); >+ >+ size = vbios_size; >+ >+ bios = ioremap_wc(vram_base + vbios_offset, size); >+ if (!bios) >+ return false; >+ >+ adev->bios = kmalloc(size, GFP_KERNEL); >+ if (!adev->bios) { >+ iounmap(bios); >+ return false; >+ } >+ adev->bios_size = size; >+ memcpy_fromio(adev->bios, bios, size); >+ iounmap(bios); >+ >+ if (!check_atom_bios(adev, size)) { >+ amdgpu_bios_release(adev); >+ return false; >+ } >+ >+ return true; >+} >+ > void amdgpu_virt_init(struct amdgpu_device *adev) { > bool is_sriov = false; >diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >index bc1fc1c6daba..f2aa306f4192 100644 >--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h >@@ -438,6 +438,8 @@ void amdgpu_virt_fini_data_exchange(struct >amdgpu_device *adev); void amdgpu_virt_init(struct amdgpu_device *adev); > > int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); >+int amdgpu_virt_init_discovery_from_mem(struct amdgpu_device *adev, >+uint8_t *binary); bool amdgpu_virt_read_bios_from_vram(struct >+amdgpu_device *adev); > > bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); int >amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev); >-- >2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-10-10 10:46 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-10-09 3:31 [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan 2025-10-09 12:31 ` Christian König 2025-10-09 15:24 ` Lazar, Lijo -- strict thread matches above, loose matches on Subject: below -- 2025-10-10 4:43 [PATCH 1/6] drm/amdgpu: Updated naming of SRIOV critical region offsets/sizes with _V1 suffix Ellen Pan 2025-10-10 4:43 ` [PATCH 5/6] drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets Ellen Pan 2025-10-10 10:46 ` Lazar, Lijo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox