Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: export function to flush TLB via pasid

This can be used directly from amdgpu and amdkfd to invalidate
TLB through pasid.
It supports gmc v7, v8, v9 and v10.

Signed-off-by: Alex Sierra <alex.sierra@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Alex Sierra and committed by
Alex Deucher
ea930000 4f01f1e5

+223
+6
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
··· 92 92 /* flush the vm tlb via mmio */ 93 93 void (*flush_gpu_tlb)(struct amdgpu_device *adev, uint32_t vmid, 94 94 uint32_t vmhub, uint32_t flush_type); 95 + /* flush the vm tlb via pasid */ 96 + int (*flush_gpu_tlb_pasid)(struct amdgpu_device *adev, uint16_t pasid, 97 + uint32_t flush_type, bool all_hub); 95 98 /* flush the vm tlb via ring */ 96 99 uint64_t (*emit_flush_gpu_tlb)(struct amdgpu_ring *ring, unsigned vmid, 97 100 uint64_t pd_addr); ··· 219 216 }; 220 217 221 218 #define amdgpu_gmc_flush_gpu_tlb(adev, vmid, vmhub, type) ((adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid), (vmhub), (type))) 219 + #define amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, type, allhub) \ 220 + ((adev)->gmc.gmc_funcs->flush_gpu_tlb_pasid \ 221 + ((adev), (pasid), (type), (allhub))) 222 222 #define amdgpu_gmc_emit_flush_gpu_tlb(r, vmid, addr) (r)->adev->gmc.gmc_funcs->emit_flush_gpu_tlb((r), (vmid), (addr)) 223 223 #define amdgpu_gmc_emit_pasid_mapping(r, vmid, pasid) (r)->adev->gmc.gmc_funcs->emit_pasid_mapping((r), (vmid), (pasid)) 224 224 #define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags))
+74
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
··· 30 30 #include "hdp/hdp_5_0_0_sh_mask.h" 31 31 #include "gc/gc_10_1_0_sh_mask.h" 32 32 #include "mmhub/mmhub_2_0_0_sh_mask.h" 33 + #include "athub/athub_2_0_0_sh_mask.h" 34 + #include "athub/athub_2_0_0_offset.h" 33 35 #include "dcn/dcn_2_0_0_offset.h" 34 36 #include "dcn/dcn_2_0_0_sh_mask.h" 35 37 #include "oss/osssys_5_0_0_offset.h" ··· 39 37 #include "navi10_enum.h" 40 38 41 39 #include "soc15.h" 40 + #include "soc15d.h" 42 41 #include "soc15_common.h" 43 42 44 43 #include "nbio_v2_3.h" ··· 237 234 (!amdgpu_sriov_vf(adev))); 238 235 } 239 236 237 + static bool gmc_v10_0_get_atc_vmid_pasid_mapping_info( 238 + struct amdgpu_device *adev, 239 + uint8_t vmid, uint16_t *p_pasid) 240 + { 241 + uint32_t value; 242 + 243 + value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) 244 + + vmid); 245 + *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK; 246 + 247 + return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK); 248 + } 249 + 240 250 /* 241 251 * GART 242 252 * VMID 0 is the physical GPU addresses as used by the kernel. ··· 394 378 error_alloc: 395 379 mutex_unlock(&adev->mman.gtt_window_lock); 396 380 DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r); 381 + } 382 + 383 + /** 384 + * gmc_v10_0_flush_gpu_tlb_pasid - tlb flush via pasid 385 + * 386 + * @adev: amdgpu_device pointer 387 + * @pasid: pasid to be flush 388 + * 389 + * Flush the TLB for the requested pasid. 390 + */ 391 + static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, 392 + uint16_t pasid, uint32_t flush_type, 393 + bool all_hub) 394 + { 395 + int vmid, i; 396 + signed long r; 397 + uint32_t seq; 398 + uint16_t queried_pasid; 399 + bool ret; 400 + struct amdgpu_ring *ring = &adev->gfx.kiq.ring; 401 + struct amdgpu_kiq *kiq = &adev->gfx.kiq; 402 + 403 + if (amdgpu_emu_mode == 0 && ring->sched.ready) { 404 + spin_lock(&adev->gfx.kiq.ring_lock); 405 + amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size); 406 + kiq->pmf->kiq_invalidate_tlbs(ring, 407 + pasid, flush_type, all_hub); 408 + amdgpu_fence_emit_polling(ring, &seq); 409 + amdgpu_ring_commit(ring); 410 + spin_unlock(&adev->gfx.kiq.ring_lock); 411 + r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); 412 + if (r < 1) { 413 + DRM_ERROR("wait for kiq fence error: %ld.\n", r); 414 + return -ETIME; 415 + } 416 + 417 + return 0; 418 + } 419 + 420 + for (vmid = 1; vmid < 16; vmid++) { 421 + 422 + ret = gmc_v10_0_get_atc_vmid_pasid_mapping_info(adev, vmid, 423 + &queried_pasid); 424 + if (ret && queried_pasid == pasid) { 425 + if (all_hub) { 426 + for (i = 0; i < adev->num_vmhubs; i++) 427 + gmc_v10_0_flush_gpu_tlb(adev, vmid, 428 + i, 0); 429 + } else { 430 + gmc_v10_0_flush_gpu_tlb(adev, vmid, 431 + AMDGPU_GFXHUB_0, 0); 432 + } 433 + break; 434 + } 435 + } 436 + 437 + return 0; 397 438 } 398 439 399 440 static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, ··· 604 531 605 532 static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = { 606 533 .flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb, 534 + .flush_gpu_tlb_pasid = gmc_v10_0_flush_gpu_tlb_pasid, 607 535 .emit_flush_gpu_tlb = gmc_v10_0_emit_flush_gpu_tlb, 608 536 .emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping, 609 537 .map_mtype = gmc_v10_0_map_mtype,
+33
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
··· 418 418 return 0; 419 419 } 420 420 421 + /** 422 + * gmc_v7_0_flush_gpu_tlb_pasid - tlb flush via pasid 423 + * 424 + * @adev: amdgpu_device pointer 425 + * @pasid: pasid to be flush 426 + * 427 + * Flush the TLB for the requested pasid. 428 + */ 429 + static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, 430 + uint16_t pasid, uint32_t flush_type, 431 + bool all_hub) 432 + { 433 + int vmid; 434 + unsigned int tmp; 435 + 436 + if (adev->in_gpu_reset) 437 + return -EIO; 438 + 439 + for (vmid = 1; vmid < 16; vmid++) { 440 + 441 + tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid); 442 + if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) && 443 + (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) { 444 + WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid); 445 + RREG32(mmVM_INVALIDATE_RESPONSE); 446 + break; 447 + } 448 + } 449 + 450 + return 0; 451 + } 452 + 421 453 /* 422 454 * GART 423 455 * VMID 0 is the physical GPU addresses as used by the kernel. ··· 1365 1333 1366 1334 static const struct amdgpu_gmc_funcs gmc_v7_0_gmc_funcs = { 1367 1335 .flush_gpu_tlb = gmc_v7_0_flush_gpu_tlb, 1336 + .flush_gpu_tlb_pasid = gmc_v7_0_flush_gpu_tlb_pasid, 1368 1337 .emit_flush_gpu_tlb = gmc_v7_0_emit_flush_gpu_tlb, 1369 1338 .emit_pasid_mapping = gmc_v7_0_emit_pasid_mapping, 1370 1339 .set_prt = gmc_v7_0_set_prt,
+34
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
··· 620 620 return 0; 621 621 } 622 622 623 + /** 624 + * gmc_v8_0_flush_gpu_tlb_pasid - tlb flush via pasid 625 + * 626 + * @adev: amdgpu_device pointer 627 + * @pasid: pasid to be flush 628 + * 629 + * Flush the TLB for the requested pasid. 630 + */ 631 + static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, 632 + uint16_t pasid, uint32_t flush_type, 633 + bool all_hub) 634 + { 635 + int vmid; 636 + unsigned int tmp; 637 + 638 + if (adev->in_gpu_reset) 639 + return -EIO; 640 + 641 + for (vmid = 1; vmid < 16; vmid++) { 642 + 643 + tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid); 644 + if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) && 645 + (tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) { 646 + WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid); 647 + RREG32(mmVM_INVALIDATE_RESPONSE); 648 + break; 649 + } 650 + } 651 + 652 + return 0; 653 + 654 + } 655 + 623 656 /* 624 657 * GART 625 658 * VMID 0 is the physical GPU addresses as used by the kernel. ··· 1733 1700 1734 1701 static const struct amdgpu_gmc_funcs gmc_v8_0_gmc_funcs = { 1735 1702 .flush_gpu_tlb = gmc_v8_0_flush_gpu_tlb, 1703 + .flush_gpu_tlb_pasid = gmc_v8_0_flush_gpu_tlb_pasid, 1736 1704 .emit_flush_gpu_tlb = gmc_v8_0_emit_flush_gpu_tlb, 1737 1705 .emit_pasid_mapping = gmc_v8_0_emit_pasid_mapping, 1738 1706 .set_prt = gmc_v8_0_set_prt,
+76
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 38 38 #include "dce/dce_12_0_sh_mask.h" 39 39 #include "vega10_enum.h" 40 40 #include "mmhub/mmhub_1_0_offset.h" 41 + #include "athub/athub_1_0_sh_mask.h" 41 42 #include "athub/athub_1_0_offset.h" 42 43 #include "oss/osssys_4_0_offset.h" 43 44 44 45 #include "soc15.h" 46 + #include "soc15d.h" 45 47 #include "soc15_common.h" 46 48 #include "umc/umc_6_0_sh_mask.h" 47 49 ··· 443 441 adev->pdev->device == 0x15d8))); 444 442 } 445 443 444 + static bool gmc_v9_0_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, 445 + uint8_t vmid, uint16_t *p_pasid) 446 + { 447 + uint32_t value; 448 + 449 + value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) 450 + + vmid); 451 + *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK; 452 + 453 + return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK); 454 + } 455 + 446 456 /* 447 457 * GART 448 458 * VMID 0 is the physical GPU addresses as used by the kernel. ··· 551 537 return; 552 538 553 539 DRM_ERROR("Timeout waiting for VM flush ACK!\n"); 540 + } 541 + 542 + /** 543 + * gmc_v9_0_flush_gpu_tlb_pasid - tlb flush via pasid 544 + * 545 + * @adev: amdgpu_device pointer 546 + * @pasid: pasid to be flush 547 + * 548 + * Flush the TLB for the requested pasid. 549 + */ 550 + static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, 551 + uint16_t pasid, uint32_t flush_type, 552 + bool all_hub) 553 + { 554 + int vmid, i; 555 + signed long r; 556 + uint32_t seq; 557 + uint16_t queried_pasid; 558 + bool ret; 559 + struct amdgpu_ring *ring = &adev->gfx.kiq.ring; 560 + struct amdgpu_kiq *kiq = &adev->gfx.kiq; 561 + 562 + if (adev->in_gpu_reset) 563 + return -EIO; 564 + 565 + if (ring->sched.ready) { 566 + spin_lock(&adev->gfx.kiq.ring_lock); 567 + amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size); 568 + kiq->pmf->kiq_invalidate_tlbs(ring, 569 + pasid, flush_type, all_hub); 570 + amdgpu_fence_emit_polling(ring, &seq); 571 + amdgpu_ring_commit(ring); 572 + spin_unlock(&adev->gfx.kiq.ring_lock); 573 + r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); 574 + if (r < 1) { 575 + DRM_ERROR("wait for kiq fence error: %ld.\n", r); 576 + return -ETIME; 577 + } 578 + 579 + return 0; 580 + } 581 + 582 + for (vmid = 1; vmid < 16; vmid++) { 583 + 584 + ret = gmc_v9_0_get_atc_vmid_pasid_mapping_info(adev, vmid, 585 + &queried_pasid); 586 + if (ret && queried_pasid == pasid) { 587 + if (all_hub) { 588 + for (i = 0; i < adev->num_vmhubs; i++) 589 + gmc_v9_0_flush_gpu_tlb(adev, vmid, 590 + i, 0); 591 + } else { 592 + gmc_v9_0_flush_gpu_tlb(adev, vmid, 593 + AMDGPU_GFXHUB_0, 0); 594 + } 595 + break; 596 + } 597 + } 598 + 599 + return 0; 600 + 554 601 } 555 602 556 603 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, ··· 775 700 776 701 static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = { 777 702 .flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb, 703 + .flush_gpu_tlb_pasid = gmc_v9_0_flush_gpu_tlb_pasid, 778 704 .emit_flush_gpu_tlb = gmc_v9_0_emit_flush_gpu_tlb, 779 705 .emit_pasid_mapping = gmc_v9_0_emit_pasid_mapping, 780 706 .map_mtype = gmc_v9_0_map_mtype,