Am 30.09.2017 um 05:52 schrieb Horace Chen: > SR-IOV need to reserve a piece of shared VRAM at the exact place > to exchange data betweem PF and VF. The start address and size of > the shared mem are passed to guest through VBIOS structure > VRAM_UsageByFirmware. > > VRAM_UsageByFirmware is a general feature in VBIOS, it indicates > that VBIOS need to reserve a piece of memory on the VRAM. > > Because the mem address is specified. Reserve it early in > amdgpu_ttm_init to make sure that it can monoplize the space. > > Signed-off-by: Horace Chen <horace.chen at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu.h | 14 +++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 18 ++++++- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 80 ++++++++++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 ++++ > 4 files changed, 120 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > index a5b0b67..7bbc51f 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > @@ -1380,6 +1380,18 @@ struct amdgpu_atcs { > }; > > /* > + * Firmware VRAM reservation > + */ > +struct amdgpu_fw_vram_usage { > + u64 start_offset; > + u64 size; > + struct amdgpu_bo *reserved_bo; > + void *va; > +}; > + > +int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev); > + > +/* > * CGS > */ > struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev); > @@ -1588,6 +1600,8 @@ struct amdgpu_device { > struct delayed_work late_init_work; > > struct amdgpu_virt virt; > + /* firmware VRAM reservation */ > + struct amdgpu_fw_vram_usage fw_vram_usage; > > /* link all shadow bo */ > struct list_head shadow_list; > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > index ce44358..f66d33e 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > @@ -1807,6 +1807,8 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) > uint16_t data_offset; > int usage_bytes = 0; > struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; > + u64 start_addr; > + u64 size; > > if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { > firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); > @@ -1815,7 +1817,21 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) > le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware), > le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb)); > > - usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024; > + start_addr = firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware; > + size = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb; > + > + if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) == > + (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << > + ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { > + /* Firmware request VRAM reservation for SR-IOV */ > + adev->fw_vram_usage.start_offset = (start_addr & > + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; > + adev->fw_vram_usage.size = size << 10; > + /* Use the default scratch size */ > + usage_bytes = 0; > + } else { > + usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024; > + } > } > ctx->scratch_size_bytes = 0; > if (usage_bytes == 0) > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > index a86d856..c7f6d2b 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > @@ -658,6 +658,85 @@ void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) > } > > /* > + * Firmware Reservation function > + */ > +/** > + * amdgpu_fw_reserve_vram_fini - free fw reserved vram > + * > + * @adev: amdgpu_device pointer > + * > + * free fw reserved vram if it has been reserved. > + */ > +void amdgpu_fw_reserve_vram_fini(struct amdgpu_device *adev) > +{ > + > + if (adev->fw_vram_usage.reserved_bo == NULL) > + return; The check here is duplicated, amdgpu_bo_free_kernel() does a NULL check anyway so please remove. With that fixed the patch is Reviewed-by: Christian König <christian.koenig at amd.com>. Regards, Christian. > + > + amdgpu_bo_free_kernel(&adev->fw_vram_usage.reserved_bo, > + NULL, &adev->fw_vram_usage.va); > +} > + > +/** > + * amdgpu_fw_reserve_vram_init - create bo vram reservation from fw > + * > + * @adev: amdgpu_device pointer > + * > + * create bo vram reservation from fw. > + */ > +int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev) > +{ > + int r = 0; > + u64 gpu_addr; > + u64 vram_size = adev->mc.visible_vram_size; > + > + adev->fw_vram_usage.va = NULL; > + adev->fw_vram_usage.reserved_bo = NULL; > + > + if (adev->fw_vram_usage.size > 0 && > + adev->fw_vram_usage.size <= vram_size) { > + > + r = amdgpu_bo_create(adev, adev->fw_vram_usage.size, > + PAGE_SIZE, true, 0, > + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | > + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, 0, > + &adev->fw_vram_usage.reserved_bo); > + if (r) > + goto error_create; > + > + r = amdgpu_bo_reserve(adev->fw_vram_usage.reserved_bo, false); > + if (r) > + goto error_reserve; > + r = amdgpu_bo_pin_restricted(adev->fw_vram_usage.reserved_bo, > + AMDGPU_GEM_DOMAIN_VRAM, > + adev->fw_vram_usage.start_offset, > + (adev->fw_vram_usage.start_offset + > + adev->fw_vram_usage.size), &gpu_addr); > + if (r) > + goto error_pin; > + r = amdgpu_bo_kmap(adev->fw_vram_usage.reserved_bo, > + &adev->fw_vram_usage.va); > + if (r) > + goto error_kmap; > + > + amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo); > + } > + return r; > + > +error_kmap: > + amdgpu_bo_unpin(adev->fw_vram_usage.reserved_bo); > +error_pin: > + amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo); > +error_reserve: > + amdgpu_bo_unref(&adev->fw_vram_usage.reserved_bo); > +error_create: > + adev->fw_vram_usage.va = NULL; > + adev->fw_vram_usage.reserved_bo = NULL; > + return r; > +} > + > + > +/* > * GPU helpers function. > */ > /** > @@ -2331,6 +2410,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) > /* evict vram memory */ > amdgpu_bo_evict_vram(adev); > amdgpu_ib_pool_fini(adev); > + amdgpu_fw_reserve_vram_fini(adev); > amdgpu_fence_driver_fini(adev); > amdgpu_fbdev_fini(adev); > r = amdgpu_fini(adev); > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > index 1086f03..a5253cf 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > @@ -1256,6 +1256,15 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) > /* Change the size here instead of the init above so only lpfn is affected */ > amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size); > > + /* > + *The reserved vram for firmware must be pinned to the specified > + *place on the VRAM, so reserve it early. > + */ > + r = amdgpu_fw_reserve_vram_init(adev); > + if (r) { > + return r; > + } > + > r = amdgpu_bo_create_kernel(adev, adev->mc.stolen_size, PAGE_SIZE, > AMDGPU_GEM_DOMAIN_VRAM, > &adev->stolen_vga_memory,