aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
diff options
context:
space:
mode:
authorHorace Chen <horace.chen@amd.com>2017-10-09 04:17:16 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-10-19 15:26:59 -0400
commit2dc8f81e4f822cfe8f6475da968ab2dd5881b8d8 (patch)
tree6598c1b183930a262552b4609172d97c690fc543 /drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
parent0ae94444c08a0adf2fab4aab26be0646ee445a19 (diff)
drm/amdgpu: SR-IOV data exchange between PF&VF
SR-IOV need to exchange some data between PF&VF through shared VRAM PF will copy some necessary firmware and information to the shared VRAM. It also requires some information from VF. PF will send a key through mailbox2 to help guest calculate checksum so that it can verify whether the data is correct. So check the data on the specified offset of the shared VRAM, if the checksum is right, read values from it and write some VF information next to the data from PF. Signed-off-by: Horace Chen <horace.chen@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index ab05121b9272..ed7be2eb24b0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -274,3 +274,78 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev)
274 (void *)&adev->virt.mm_table.cpu_addr); 274 (void *)&adev->virt.mm_table.cpu_addr);
275 adev->virt.mm_table.gpu_addr = 0; 275 adev->virt.mm_table.gpu_addr = 0;
276} 276}
277
278
279int amdgpu_virt_fw_reserve_get_checksum(void *obj,
280 unsigned long obj_size,
281 unsigned int key,
282 unsigned int chksum)
283{
284 unsigned int ret = key;
285 unsigned long i = 0;
286 unsigned char *pos;
287
288 pos = (char *)obj;
289 /* calculate checksum */
290 for (i = 0; i < obj_size; ++i)
291 ret += *(pos + i);
292 /* minus the chksum itself */
293 pos = (char *)&chksum;
294 for (i = 0; i < sizeof(chksum); ++i)
295 ret -= *(pos + i);
296 return ret;
297}
298
299void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
300{
301 uint32_t pf2vf_ver = 0;
302 uint32_t pf2vf_size = 0;
303 uint32_t checksum = 0;
304 uint32_t checkval;
305 char *str;
306
307 adev->virt.fw_reserve.p_pf2vf = NULL;
308 adev->virt.fw_reserve.p_vf2pf = NULL;
309
310 if (adev->fw_vram_usage.va != NULL) {
311 adev->virt.fw_reserve.p_pf2vf =
312 (struct amdgim_pf2vf_info_header *)(
313 adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET);
314 pf2vf_ver = adev->virt.fw_reserve.p_pf2vf->version;
315 AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size);
316 AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum);
317
318 /* pf2vf message must be in 4K */
319 if (pf2vf_size > 0 && pf2vf_size < 4096) {
320 checkval = amdgpu_virt_fw_reserve_get_checksum(
321 adev->virt.fw_reserve.p_pf2vf, pf2vf_size,
322 adev->virt.fw_reserve.checksum_key, checksum);
323 if (checkval == checksum) {
324 adev->virt.fw_reserve.p_vf2pf =
325 ((void *)adev->virt.fw_reserve.p_pf2vf +
326 pf2vf_size);
327 memset((void *)adev->virt.fw_reserve.p_vf2pf, 0,
328 sizeof(amdgim_vf2pf_info));
329 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.version,
330 AMDGPU_FW_VRAM_VF2PF_VER);
331 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.size,
332 sizeof(amdgim_vf2pf_info));
333 AMDGPU_FW_VRAM_VF2PF_READ(adev, driver_version,
334 &str);
335 if (THIS_MODULE->version != NULL)
336 strcpy(str, THIS_MODULE->version);
337 else
338 strcpy(str, "N/A");
339 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, driver_cert,
340 0);
341 AMDGPU_FW_VRAM_VF2PF_WRITE(adev, checksum,
342 amdgpu_virt_fw_reserve_get_checksum(
343 adev->virt.fw_reserve.p_vf2pf,
344 pf2vf_size,
345 adev->virt.fw_reserve.checksum_key, 0));
346 }
347 }
348 }
349}
350
351