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

Configure Feed

Select the types of activity you want to include in your feed.

drm/xe: Rewrite GGTT VF initialization

The previous code was using a complicated system with 2 balloons to
set GGTT size and adjust GGTT offset. While it works, it's overly
complicated.

A better approach is to set the offset and size when initializing GGTT,
this removes the need for adding balloons. The resize function only
needs readjust ggtt->start to have GGTT at the new offset.

This removes the need to manipulate the internals of xe_ggtt outside
of xe_ggtt, and cleans up a lot of now unneeded code.

Co-developed-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patch.msgid.link/20260206112108.1453809-9-dev@lankhorst.se
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>

+76 -352
+50 -137
drivers/gpu/drm/xe/xe_ggtt.c
··· 70 70 * struct xe_ggtt_node - A node in GGTT. 71 71 * 72 72 * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node 73 - * insertion, reservation, or 'ballooning'. 74 - * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). 73 + * insertion or reservation. 74 + * It will, then, be finalized by xe_ggtt_node_remove(). 75 75 */ 76 76 struct xe_ggtt_node { 77 77 /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ ··· 347 347 ggtt_start = wopcm; 348 348 ggtt_size = (gsm_size / 8) * (u64)XE_PAGE_SIZE - ggtt_start; 349 349 } else { 350 - /* GGTT is expected to be 4GiB */ 351 - ggtt_start = wopcm; 352 - ggtt_size = SZ_4G - ggtt_start; 350 + ggtt_start = xe_tile_sriov_vf_ggtt_base(ggtt->tile); 351 + ggtt_size = xe_tile_sriov_vf_ggtt(ggtt->tile); 352 + 353 + if (ggtt_start < wopcm || 354 + ggtt_start + ggtt_size > GUC_GGTT_TOP) { 355 + xe_tile_err(ggtt->tile, "Invalid GGTT configuration: %#llx-%#llx\n", 356 + ggtt_start, ggtt_start + ggtt_size - 1); 357 + return -ERANGE; 358 + } 353 359 } 354 360 355 361 ggtt->gsm = ggtt->tile->mmio.regs + SZ_8M; ··· 383 377 if (err) 384 378 return err; 385 379 386 - err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); 387 - if (err) 388 - return err; 389 - 390 - if (IS_SRIOV_VF(xe)) { 391 - err = xe_tile_sriov_vf_prepare_ggtt(ggtt->tile); 392 - if (err) 393 - return err; 394 - } 395 - 396 - return 0; 380 + return devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); 397 381 } 398 382 ALLOW_ERROR_INJECTION(xe_ggtt_init_early, ERRNO); /* See xe_pci_probe() */ 399 383 ··· 534 538 ggtt_invalidate_gt_tlb(ggtt->tile->media_gt); 535 539 } 536 540 537 - static void xe_ggtt_dump_node(struct xe_ggtt *ggtt, 538 - const struct drm_mm_node *node, const char *description) 539 - { 540 - char buf[10]; 541 - 542 - if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { 543 - string_get_size(node->size, 1, STRING_UNITS_2, buf, sizeof(buf)); 544 - xe_tile_dbg(ggtt->tile, "GGTT %#llx-%#llx (%s) %s\n", 545 - node->start, node->start + node->size, buf, description); 546 - } 547 - } 548 - 549 541 /** 550 - * xe_ggtt_node_insert_balloon_locked - prevent allocation of specified GGTT addresses 551 - * @node: the &xe_ggtt_node to hold reserved GGTT node 552 - * @start: the starting GGTT address of the reserved region 553 - * @end: then end GGTT address of the reserved region 554 - * 555 - * To be used in cases where ggtt->lock is already taken. 556 - * Use xe_ggtt_node_remove_balloon_locked() to release a reserved GGTT node. 557 - * 558 - * Return: 0 on success or a negative error code on failure. 559 - */ 560 - int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 end) 561 - { 562 - struct xe_ggtt *ggtt = node->ggtt; 563 - int err; 564 - 565 - xe_tile_assert(ggtt->tile, start < end); 566 - xe_tile_assert(ggtt->tile, IS_ALIGNED(start, XE_PAGE_SIZE)); 567 - xe_tile_assert(ggtt->tile, IS_ALIGNED(end, XE_PAGE_SIZE)); 568 - xe_tile_assert(ggtt->tile, !drm_mm_node_allocated(&node->base)); 569 - xe_tile_assert(ggtt->tile, start >= ggtt->start); 570 - lockdep_assert_held(&ggtt->lock); 571 - 572 - node->base.color = 0; 573 - node->base.start = start - ggtt->start; 574 - node->base.size = end - start; 575 - 576 - err = drm_mm_reserve_node(&ggtt->mm, &node->base); 577 - 578 - if (xe_tile_WARN(ggtt->tile, err, "Failed to balloon GGTT %#llx-%#llx (%pe)\n", 579 - xe_ggtt_node_addr(node), xe_ggtt_node_addr(node) + node->base.size, ERR_PTR(err))) 580 - return err; 581 - 582 - xe_ggtt_dump_node(ggtt, &node->base, "balloon"); 583 - return 0; 584 - } 585 - 586 - /** 587 - * xe_ggtt_node_remove_balloon_locked - release a reserved GGTT region 588 - * @node: the &xe_ggtt_node with reserved GGTT region 589 - * 590 - * To be used in cases where ggtt->lock is already taken. 591 - * See xe_ggtt_node_insert_balloon_locked() for details. 592 - */ 593 - void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) 594 - { 595 - if (!xe_ggtt_node_allocated(node)) 596 - return; 597 - 598 - lockdep_assert_held(&node->ggtt->lock); 599 - 600 - xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon"); 601 - 602 - drm_mm_remove_node(&node->base); 603 - } 604 - 605 - static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size) 606 - { 607 - struct xe_tile *tile = ggtt->tile; 608 - 609 - xe_tile_assert(tile, start >= ggtt->start); 610 - xe_tile_assert(tile, start + size <= ggtt->start + ggtt->size); 611 - } 612 - 613 - /** 614 - * xe_ggtt_shift_nodes_locked - Shift GGTT nodes to adjust for a change in usable address range. 542 + * xe_ggtt_shift_nodes() - Shift GGTT nodes to adjust for a change in usable address range. 615 543 * @ggtt: the &xe_ggtt struct instance 616 - * @shift: change to the location of area provisioned for current VF 544 + * @new_start: new location of area provisioned for current VF 617 545 * 618 - * This function moves all nodes from the GGTT VM, to a temp list. These nodes are expected 619 - * to represent allocations in range formerly assigned to current VF, before the range changed. 620 - * When the GGTT VM is completely clear of any nodes, they are re-added with shifted offsets. 546 + * Ensure that all struct &xe_ggtt_node are moved to the @new_start base address 547 + * by changing the base offset of the GGTT. 621 548 * 622 - * The function has no ability of failing - because it shifts existing nodes, without 623 - * any additional processing. If the nodes were successfully existing at the old address, 624 - * they will do the same at the new one. A fail inside this function would indicate that 625 - * the list of nodes was either already damaged, or that the shift brings the address range 626 - * outside of valid bounds. Both cases justify an assert rather than error code. 549 + * This function may be called multiple times during recovery, but if 550 + * @new_start is unchanged from the current base, it's a noop. 551 + * 552 + * @new_start should be a value between xe_wopcm_size() and #GUC_GGTT_TOP. 627 553 */ 628 - void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift) 554 + void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, u64 new_start) 629 555 { 630 - struct xe_tile *tile __maybe_unused = ggtt->tile; 631 - struct drm_mm_node *node, *tmpn; 632 - LIST_HEAD(temp_list_head); 556 + guard(mutex)(&ggtt->lock); 633 557 634 - lockdep_assert_held(&ggtt->lock); 558 + xe_tile_assert(ggtt->tile, new_start >= xe_wopcm_size(tile_to_xe(ggtt->tile))); 559 + xe_tile_assert(ggtt->tile, new_start + ggtt->size <= GUC_GGTT_TOP); 635 560 636 - if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) 637 - drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) 638 - xe_ggtt_assert_fit(ggtt, node->start + shift, node->size); 639 - 640 - drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) { 641 - drm_mm_remove_node(node); 642 - list_add(&node->node_list, &temp_list_head); 643 - } 644 - 645 - list_for_each_entry_safe(node, tmpn, &temp_list_head, node_list) { 646 - list_del(&node->node_list); 647 - node->start += shift; 648 - drm_mm_reserve_node(&ggtt->mm, node); 649 - xe_tile_assert(tile, drm_mm_node_allocated(node)); 650 - } 561 + /* pairs with READ_ONCE in xe_ggtt_node_addr() */ 562 + WRITE_ONCE(ggtt->start, new_start); 651 563 } 652 564 653 565 static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, ··· 596 692 * 597 693 * This function will allocate the struct %xe_ggtt_node and return its pointer. 598 694 * This struct will then be freed after the node removal upon xe_ggtt_node_remove() 599 - * or xe_ggtt_node_remove_balloon_locked(). 600 - * 601 - * Having %xe_ggtt_node struct allocated doesn't mean that the node is already 602 - * allocated in GGTT. Only xe_ggtt_node_insert(), allocation through 603 - * xe_ggtt_node_insert_transform(), or xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved 604 - * in GGTT. 695 + * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated 696 + * in GGTT. Only xe_ggtt_node_insert() will ensure the node is inserted or reserved in GGTT. 605 697 * 606 698 * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. 607 699 **/ ··· 618 718 * xe_ggtt_node_fini - Forcebly finalize %xe_ggtt_node struct 619 719 * @node: the &xe_ggtt_node to be freed 620 720 * 621 - * If anything went wrong with either xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), 622 - * or xe_ggtt_node_insert_balloon_locked(); and this @node is not going to be reused, then, 623 - * this function needs to be called to free the %xe_ggtt_node struct 721 + * If anything went wrong with either xe_ggtt_node_insert() and this @node is 722 + * not going to be reused, then this function needs to be called to free the 723 + * %xe_ggtt_node struct 624 724 **/ 625 725 void xe_ggtt_node_fini(struct xe_ggtt_node *node) 626 726 { ··· 792 892 } 793 893 794 894 mutex_lock(&ggtt->lock); 795 - xe_tile_assert(ggtt->tile, start >= ggtt->start || !start); 796 - xe_tile_assert(ggtt->tile, end >= ggtt->start); 797 - 798 - if (start) 895 + /* 896 + * When inheriting the initial framebuffer, the framebuffer is 897 + * physically located at VRAM address 0, and usually at GGTT address 0 too. 898 + * 899 + * The display code will ask for a GGTT allocation between end of BO and 900 + * remainder of GGTT, unaware that the start is reserved by WOPCM. 901 + */ 902 + if (start >= ggtt->start) 799 903 start -= ggtt->start; 904 + else 905 + start = 0; 800 906 801 - end -= ggtt->start; 907 + /* Should never happen, but since we handle start, fail graciously for end */ 908 + if (end >= ggtt->start) 909 + end -= ggtt->start; 910 + else 911 + end = 0; 912 + 913 + xe_tile_assert(ggtt->tile, end >= start + xe_bo_size(bo)); 802 914 803 915 err = drm_mm_insert_node_in_range(&ggtt->mm, &bo->ggtt_node[tile_id]->base, 804 916 xe_bo_size(bo), alignment, 0, start, end, 0); ··· 1132 1220 */ 1133 1221 u64 xe_ggtt_node_addr(const struct xe_ggtt_node *node) 1134 1222 { 1135 - return node->base.start + node->ggtt->start; 1223 + /* pairs with WRITE_ONCE in xe_ggtt_shift_nodes() */ 1224 + return node->base.start + READ_ONCE(node->ggtt->start); 1136 1225 } 1137 1226 1138 1227 /**
+1 -4
drivers/gpu/drm/xe/xe_ggtt.h
··· 19 19 20 20 struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt); 21 21 void xe_ggtt_node_fini(struct xe_ggtt_node *node); 22 - int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, 23 - u64 start, u64 size); 24 - void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); 25 - void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift); 22 + void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, u64 new_base); 26 23 u64 xe_ggtt_start(struct xe_ggtt *ggtt); 27 24 u64 xe_ggtt_size(struct xe_ggtt *ggtt); 28 25
+21 -14
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
··· 488 488 static int vf_get_ggtt_info(struct xe_gt *gt) 489 489 { 490 490 struct xe_tile *tile = gt_to_tile(gt); 491 - struct xe_ggtt *ggtt = tile->mem.ggtt; 492 491 struct xe_guc *guc = &gt->uc.guc; 493 492 u64 start, size, ggtt_size; 494 - s64 shift; 495 493 int err; 496 494 497 495 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 498 - 499 - guard(mutex)(&ggtt->lock); 500 496 501 497 err = guc_action_query_single_klv64(guc, GUC_KLV_VF_CFG_GGTT_START_KEY, &start); 502 498 if (unlikely(err)) ··· 505 509 if (!size) 506 510 return -ENODATA; 507 511 512 + xe_tile_sriov_vf_ggtt_base_store(tile, start); 508 513 ggtt_size = xe_tile_sriov_vf_ggtt(tile); 509 - if (ggtt_size && ggtt_size != size) { 514 + if (!ggtt_size) { 515 + /* 516 + * This function is called once during xe_guc_init_noalloc(), 517 + * at which point ggtt_size = 0 and we have to initialize everything, 518 + * and GGTT is not yet initialized. 519 + * 520 + * Return early as there's nothing to fixup. 521 + */ 522 + xe_tile_sriov_vf_ggtt_store(tile, size); 523 + return 0; 524 + } 525 + 526 + if (ggtt_size != size) { 510 527 xe_gt_sriov_err(gt, "Unexpected GGTT reassignment: %lluK != %lluK\n", 511 528 size / SZ_1K, ggtt_size / SZ_1K); 512 529 return -EREMCHG; ··· 528 519 xe_gt_sriov_dbg_verbose(gt, "GGTT %#llx-%#llx = %lluK\n", 529 520 start, start + size - 1, size / SZ_1K); 530 521 531 - shift = start - (s64)xe_tile_sriov_vf_ggtt_base(tile); 532 - xe_tile_sriov_vf_ggtt_base_store(tile, start); 533 - xe_tile_sriov_vf_ggtt_store(tile, size); 534 - 535 - if (shift && shift != start) { 536 - xe_gt_sriov_info(gt, "Shifting GGTT base by %lld to 0x%016llx\n", 537 - shift, start); 538 - xe_tile_sriov_vf_fixup_ggtt_nodes_locked(gt_to_tile(gt), shift); 539 - } 522 + /* 523 + * This function can be called repeatedly from post migration fixups, 524 + * at which point we inform the GGTT of the new base address. 525 + * xe_ggtt_shift_nodes() may be called multiple times for each migration, 526 + * but will be a noop if the base is unchanged. 527 + */ 528 + xe_ggtt_shift_nodes(tile->mem.ggtt, start); 540 529 541 530 if (xe_sriov_vf_migration_supported(gt_to_xe(gt))) { 542 531 WRITE_ONCE(gt->sriov.vf.migration.ggtt_need_fixes, false);
+4 -194
drivers/gpu/drm/xe/xe_tile_sriov_vf.c
··· 14 14 #include "xe_tile_sriov_vf.h" 15 15 #include "xe_wopcm.h" 16 16 17 - static int vf_init_ggtt_balloons(struct xe_tile *tile) 18 - { 19 - struct xe_ggtt *ggtt = tile->mem.ggtt; 20 - 21 - xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 22 - 23 - tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); 24 - if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) 25 - return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); 26 - 27 - tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); 28 - if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { 29 - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); 30 - return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); 31 - } 32 - 33 - return 0; 34 - } 35 - 36 - /** 37 - * xe_tile_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range. 38 - * @tile: the &xe_tile struct instance 39 - * 40 - * Return: 0 on success or a negative error code on failure. 41 - */ 42 - static int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) 43 - { 44 - u64 ggtt_base = tile->sriov.vf.self_config.ggtt_base; 45 - u64 ggtt_size = tile->sriov.vf.self_config.ggtt_size; 46 - struct xe_device *xe = tile_to_xe(tile); 47 - u64 wopcm = xe_wopcm_size(xe); 48 - u64 start, end; 49 - int err; 50 - 51 - xe_tile_assert(tile, IS_SRIOV_VF(xe)); 52 - xe_tile_assert(tile, ggtt_size); 53 - lockdep_assert_held(&tile->mem.ggtt->lock); 54 - 55 - /* 56 - * VF can only use part of the GGTT as allocated by the PF: 57 - * 58 - * WOPCM GUC_GGTT_TOP 59 - * |<------------ Total GGTT size ------------------>| 60 - * 61 - * VF GGTT base -->|<- size ->| 62 - * 63 - * +--------------------+----------+-----------------+ 64 - * |////////////////////| block |\\\\\\\\\\\\\\\\\| 65 - * +--------------------+----------+-----------------+ 66 - * 67 - * |<--- balloon[0] --->|<-- VF -->|<-- balloon[1] ->| 68 - */ 69 - 70 - if (ggtt_base < wopcm || ggtt_base > GUC_GGTT_TOP || 71 - ggtt_size > GUC_GGTT_TOP - ggtt_base) { 72 - xe_sriov_err(xe, "tile%u: Invalid GGTT configuration: %#llx-%#llx\n", 73 - tile->id, ggtt_base, ggtt_base + ggtt_size - 1); 74 - return -ERANGE; 75 - } 76 - 77 - start = wopcm; 78 - end = ggtt_base; 79 - if (end != start) { 80 - err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], 81 - start, end); 82 - if (err) 83 - return err; 84 - } 85 - 86 - start = ggtt_base + ggtt_size; 87 - end = GUC_GGTT_TOP; 88 - if (end != start) { 89 - err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1], 90 - start, end); 91 - if (err) { 92 - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); 93 - return err; 94 - } 95 - } 96 - 97 - return 0; 98 - } 99 - 100 - static int vf_balloon_ggtt(struct xe_tile *tile) 101 - { 102 - struct xe_ggtt *ggtt = tile->mem.ggtt; 103 - int err; 104 - 105 - mutex_lock(&ggtt->lock); 106 - err = xe_tile_sriov_vf_balloon_ggtt_locked(tile); 107 - mutex_unlock(&ggtt->lock); 108 - 109 - return err; 110 - } 111 - 112 - /** 113 - * xe_tile_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. 114 - * @tile: the &xe_tile struct instance 115 - */ 116 - void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile) 117 - { 118 - xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 119 - 120 - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); 121 - xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); 122 - } 123 - 124 - static void vf_deballoon_ggtt(struct xe_tile *tile) 125 - { 126 - mutex_lock(&tile->mem.ggtt->lock); 127 - xe_tile_sriov_vf_deballoon_ggtt_locked(tile); 128 - mutex_unlock(&tile->mem.ggtt->lock); 129 - } 130 - 131 - static void vf_fini_ggtt_balloons(struct xe_tile *tile) 132 - { 133 - xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 134 - 135 - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); 136 - xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); 137 - } 138 - 139 - static void cleanup_ggtt(struct drm_device *drm, void *arg) 140 - { 141 - struct xe_tile *tile = arg; 142 - 143 - vf_deballoon_ggtt(tile); 144 - vf_fini_ggtt_balloons(tile); 145 - } 146 - 147 - /** 148 - * xe_tile_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration. 149 - * @tile: the &xe_tile 150 - * 151 - * This function is for VF use only. 152 - * 153 - * Return: 0 on success or a negative error code on failure. 154 - */ 155 - int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile) 156 - { 157 - struct xe_device *xe = tile_to_xe(tile); 158 - int err; 159 - 160 - err = vf_init_ggtt_balloons(tile); 161 - if (err) 162 - return err; 163 - 164 - err = vf_balloon_ggtt(tile); 165 - if (err) { 166 - vf_fini_ggtt_balloons(tile); 167 - return err; 168 - } 169 - 170 - return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, tile); 171 - } 172 - 173 17 /** 174 18 * DOC: GGTT nodes shifting during VF post-migration recovery 175 19 * 176 20 * The first fixup applied to the VF KMD structures as part of post-migration 177 21 * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved 178 22 * from range previously assigned to this VF, into newly provisioned area. 179 - * The changes include balloons, which are resized accordingly. 180 - * 181 - * The balloon nodes are there to eliminate unavailable ranges from use: one 182 - * reserves the GGTT area below the range for current VF, and another one 183 - * reserves area above. 184 23 * 185 24 * Below is a GGTT layout of example VF, with a certain address range assigned to 186 25 * said VF, and inaccessible areas above and below: ··· 36 197 * Hardware enforced access rules before migration: 37 198 * 38 199 * |<------- inaccessible for VF ------->|<VF owned>|<-- inaccessible for VF ->| 39 - * 40 - * GGTT nodes used for tracking allocations: 41 - * 42 - * |<---------- balloon ------------>|<- nodes->|<----- balloon ------>| 43 200 * 44 201 * After the migration, GGTT area assigned to the VF might have shifted, either 45 202 * to lower or to higher address. But we expect the total size and extra areas to ··· 54 219 * So the VF has a new slice of GGTT assigned, and during migration process, the 55 220 * memory content was copied to that new area. But the &xe_ggtt nodes are still 56 221 * tracking allocations using the old addresses. The nodes within VF owned area 57 - * have to be shifted, and balloon nodes need to be resized to properly mask out 58 - * areas not owned by the VF. 222 + * have to be shifted, and the start offset for GGTT adjusted. 59 223 * 60 - * Fixed &xe_ggtt nodes used for tracking allocations: 61 - * 62 - * |<------ balloon ------>|<- nodes->|<----------- balloon ----------->| 63 - * 64 - * Due to use of GPU profiles, we do not expect the old and new GGTT ares to 224 + * Due to use of GPU profiles, we do not expect the old and new GGTT areas to 65 225 * overlap; but our node shifting will fix addresses properly regardless. 66 226 */ 67 - 68 - /** 69 - * xe_tile_sriov_vf_fixup_ggtt_nodes_locked - Shift GGTT allocations to match assigned range. 70 - * @tile: the &xe_tile struct instance 71 - * @shift: the shift value 72 - * 73 - * Since Global GTT is not virtualized, each VF has an assigned range 74 - * within the global space. This range might have changed during migration, 75 - * which requires all memory addresses pointing to GGTT to be shifted. 76 - */ 77 - void xe_tile_sriov_vf_fixup_ggtt_nodes_locked(struct xe_tile *tile, s64 shift) 78 - { 79 - struct xe_ggtt *ggtt = tile->mem.ggtt; 80 - 81 - lockdep_assert_held(&ggtt->lock); 82 - 83 - xe_tile_sriov_vf_deballoon_ggtt_locked(tile); 84 - xe_ggtt_shift_nodes_locked(ggtt, shift); 85 - xe_tile_sriov_vf_balloon_ggtt_locked(tile); 86 - } 87 227 88 228 /** 89 229 * xe_tile_sriov_vf_lmem - VF LMEM configuration. ··· 140 330 141 331 xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 142 332 143 - return config->ggtt_base; 333 + return READ_ONCE(config->ggtt_base); 144 334 } 145 335 146 336 /** ··· 156 346 157 347 xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 158 348 159 - config->ggtt_base = ggtt_base; 349 + WRITE_ONCE(config->ggtt_base, ggtt_base); 160 350 }
-3
drivers/gpu/drm/xe/xe_tile_sriov_vf.h
··· 10 10 11 11 struct xe_tile; 12 12 13 - int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile); 14 - void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile); 15 - void xe_tile_sriov_vf_fixup_ggtt_nodes_locked(struct xe_tile *tile, s64 shift); 16 13 u64 xe_tile_sriov_vf_ggtt(struct xe_tile *tile); 17 14 void xe_tile_sriov_vf_ggtt_store(struct xe_tile *tile, u64 ggtt_size); 18 15 u64 xe_tile_sriov_vf_ggtt_base(struct xe_tile *tile);