[PATCH 3/3] drm/amdgpu: Reserve shared memory on VRAM for SR-IOV
Horace Chen
horace.chen at amd.com
Wed Sep 27 09:23:51 UTC 2017
SR-IOV need to reserve a piece of shared VRAM 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.
Signed-off-by: Horace Chen <horace.chen at amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 17 ++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 18 +++++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 62 ++++++++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 ++++
4 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index a5b0b67..ac53dba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1380,6 +1380,21 @@ struct amdgpu_atcs {
};
/*
+ * Firmware VRAM reservation
+ */
+#define KB_TO_BYTE(x) ((x) << 10)
+#define BYTE_TO_KB(x) ((x) >> 10)
+
+struct amdgpu_fw_vram_usage {
+ uint32_t start_address_in_kb;
+ uint16_t size_in_kb;
+ struct amdgpu_bo *reserved_bo;
+ volatile uint32_t *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 +1603,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..56bfddf 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;
+ uint32_t start_addr;
+ uint16_t 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_address_in_kb =
+ start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK);
+ adev->fw_vram_usage.size_in_kb = size;
+ /* 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..3da87cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -658,6 +658,66 @@ 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 is reserved.
+ */
+void amdgpu_fw_reserve_vram_fini(struct amdgpu_device *adev)
+{
+
+ if (adev->fw_vram_usage.reserved_bo == NULL)
+ return;
+
+ amdgpu_bo_free_vram_specified(&adev->fw_vram_usage.reserved_bo, NULL,
+ (void **)&adev->fw_vram_usage.va);
+ adev->fw_vram_usage.reserved_bo = NULL;
+}
+
+/**
+ * amdgpu_fw_reserve_vram_fini - 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;
+ u64 start_addr;
+ u32 size;
+
+ adev->fw_vram_usage.va = NULL;
+ adev->fw_vram_usage.reserved_bo = NULL;
+
+ if (adev->fw_vram_usage.size_in_kb > 0 &&
+ KB_TO_BYTE((u64)adev->fw_vram_usage.size_in_kb) <= vram_size) {
+
+ start_addr =
+ KB_TO_BYTE((u64)adev->fw_vram_usage.start_address_in_kb);
+ size = KB_TO_BYTE((u64)adev->fw_vram_usage.size_in_kb);
+
+ r = amdgpu_bo_create_vram_specified(adev,
+ start_addr, size, PAGE_SIZE,
+ AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+ AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
+ &adev->fw_vram_usage.reserved_bo,
+ &gpu_addr, (void **)&adev->fw_vram_usage.va);
+ if (r)
+ dev_info(adev->dev, "Reserve VRAM for firmware failed");
+ }
+
+ return r;
+}
+
+
+/*
* GPU helpers function.
*/
/**
@@ -2055,6 +2115,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->vm_manager.vm_pte_num_rings = 0;
adev->gart.gart_funcs = NULL;
adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
+ adev->fw_vram_usage.size_in_kb = 0;
adev->smc_rreg = &amdgpu_invalid_rreg;
adev->smc_wreg = &amdgpu_invalid_wreg;
@@ -2331,6 +2392,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,
--
2.7.4
More information about the amd-gfx
mailing list