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

drm/xe: Make xe_ggtt_node struct independent

In some rare cases, the drm_mm node cannot be removed synchronously
due to runtime PM conditions. In this situation, the node removal will
be delegated to a workqueue that will be able to wake up the device
before removing the node.

However, in this situation, the lifetime of the xe_ggtt_node cannot
be restricted to the lifetime of the parent object. So, this patch
introduces the infrastructure so the xe_ggtt_node struct can be
allocated in advance and freed when needed.

By having the ggtt backpointer, it also ensure that the init function
is always called before any attempt to insert or reserve the node
in the GGTT.

v2: s/xe_ggtt_node_force_fini/xe_ggtt_node_fini and use it
internaly (Brost)
v3: - Use GF_NOFS for node allocation (CI)
- Avoid ggtt argument, now that we have it inside the node (Lucas)
- Fix some missed fini cases (CI)
v4: - Fix SRIOV critical case where config->ggtt_region was
lost (Michal)
- Avoid ggtt argument also on removal (missed case on v3) (Michal)
- Remove useless checks (Michal)
- Return 0 instead of negative errno on a u32 addr. (Michal)
- s/xe_ggtt_assign/xe_ggtt_node_assign for coherence, while we
are touching it (Michal)
v5: - Fix VFs' ggtt_balloon

Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240821193842.352557-11-rodrigo.vivi@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

+215 -105
+2 -2
drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h
··· 20 20 21 21 struct i915_vma { 22 22 struct xe_bo *bo, *dpt; 23 - struct xe_ggtt_node node; 23 + struct xe_ggtt_node *node; 24 24 }; 25 25 26 26 #define i915_ggtt_clear_scanout(bo) do { } while (0) ··· 29 29 30 30 static inline u32 i915_ggtt_offset(const struct i915_vma *vma) 31 31 { 32 - return vma->node.base.start; 32 + return vma->node->base.start; 33 33 } 34 34 35 35 #endif
+26 -13
drivers/gpu/drm/xe/display/xe_fb_pin.c
··· 204 204 if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) 205 205 align = max_t(u32, align, SZ_64K); 206 206 207 - if (bo->ggtt_node.base.size && view->type == I915_GTT_VIEW_NORMAL) { 207 + if (bo->ggtt_node && view->type == I915_GTT_VIEW_NORMAL) { 208 208 vma->node = bo->ggtt_node; 209 209 } else if (view->type == I915_GTT_VIEW_NORMAL) { 210 210 u32 x, size = bo->ttm.base.size; 211 211 212 - ret = xe_ggtt_node_insert_locked(ggtt, &vma->node, size, align, 0); 213 - if (ret) 212 + vma->node = xe_ggtt_node_init(ggtt); 213 + if (IS_ERR(vma->node)) { 214 + ret = PTR_ERR(vma->node); 214 215 goto out_unlock; 216 + } 217 + 218 + ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); 219 + if (ret) { 220 + xe_ggtt_node_fini(vma->node); 221 + goto out_unlock; 222 + } 215 223 216 224 for (x = 0; x < size; x += XE_PAGE_SIZE) { 217 225 u64 pte = ggtt->pt_ops->pte_encode_bo(bo, x, 218 226 xe->pat.idx[XE_CACHE_NONE]); 219 227 220 - ggtt->pt_ops->ggtt_set_pte(ggtt, vma->node.base.start + x, pte); 228 + ggtt->pt_ops->ggtt_set_pte(ggtt, vma->node->base.start + x, pte); 221 229 } 222 230 } else { 223 231 u32 i, ggtt_ofs; ··· 234 226 /* display seems to use tiles instead of bytes here, so convert it back.. */ 235 227 u32 size = intel_rotation_info_size(rot_info) * XE_PAGE_SIZE; 236 228 237 - ret = xe_ggtt_node_insert_locked(ggtt, &vma->node, size, align, 0); 238 - if (ret) 229 + vma->node = xe_ggtt_node_init(ggtt); 230 + if (IS_ERR(vma->node)) { 231 + ret = PTR_ERR(vma->node); 239 232 goto out_unlock; 233 + } 240 234 241 - ggtt_ofs = vma->node.base.start; 235 + ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); 236 + if (ret) { 237 + xe_ggtt_node_fini(vma->node); 238 + goto out_unlock; 239 + } 240 + 241 + ggtt_ofs = vma->node->base.start; 242 242 243 243 for (i = 0; i < ARRAY_SIZE(rot_info->plane); i++) 244 244 write_ggtt_rotated(bo, ggtt, &ggtt_ofs, ··· 334 318 335 319 static void __xe_unpin_fb_vma(struct i915_vma *vma) 336 320 { 337 - struct xe_device *xe = to_xe_device(vma->bo->ttm.base.dev); 338 - struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; 339 - 340 321 if (vma->dpt) 341 322 xe_bo_unpin_map_no_vm(vma->dpt); 342 - else if (!xe_ggtt_node_allocated(&vma->bo->ggtt_node) || 343 - vma->bo->ggtt_node.base.start != vma->node.base.start) 344 - xe_ggtt_node_remove(ggtt, &vma->node, false); 323 + else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node) || 324 + vma->bo->ggtt_node->base.start != vma->node->base.start) 325 + xe_ggtt_node_remove(vma->node, false); 345 326 346 327 ttm_bo_reserve(&vma->bo->ttm, false, false, NULL); 347 328 ttm_bo_unpin(&vma->bo->ttm);
+1 -1
drivers/gpu/drm/xe/xe_bo.c
··· 1120 1120 1121 1121 xe_assert(xe, list_empty(&ttm_bo->base.gpuva.list)); 1122 1122 1123 - if (bo->ggtt_node.base.size) 1123 + if (bo->ggtt_node && bo->ggtt_node->base.size) 1124 1124 xe_ggtt_remove_bo(bo->tile->mem.ggtt, bo); 1125 1125 1126 1126 #ifdef CONFIG_PROC_FS
+6 -3
drivers/gpu/drm/xe/xe_bo.h
··· 194 194 static inline u32 195 195 xe_bo_ggtt_addr(struct xe_bo *bo) 196 196 { 197 - XE_WARN_ON(bo->ggtt_node.base.size > bo->size); 198 - XE_WARN_ON(bo->ggtt_node.base.start + bo->ggtt_node.base.size > (1ull << 32)); 199 - return bo->ggtt_node.base.start; 197 + if (XE_WARN_ON(!bo->ggtt_node)) 198 + return 0; 199 + 200 + XE_WARN_ON(bo->ggtt_node->base.size > bo->size); 201 + XE_WARN_ON(bo->ggtt_node->base.start + bo->ggtt_node->base.size > (1ull << 32)); 202 + return bo->ggtt_node->base.start; 200 203 } 201 204 202 205 int xe_bo_vmap(struct xe_bo *bo);
+1 -1
drivers/gpu/drm/xe/xe_bo_types.h
··· 40 40 /** @placement: current placement for this BO */ 41 41 struct ttm_placement placement; 42 42 /** @ggtt_node: GGTT node if this BO is mapped in the GGTT */ 43 - struct xe_ggtt_node ggtt_node; 43 + struct xe_ggtt_node *ggtt_node; 44 44 /** @vmap: iosys map of this buffer */ 45 45 struct iosys_map vmap; 46 46 /** @ttm_kmap: TTM bo kmap object for internal use only. Keep off. */
+1 -1
drivers/gpu/drm/xe/xe_device_types.h
··· 204 204 struct xe_memirq memirq; 205 205 206 206 /** @sriov.vf.ggtt_balloon: GGTT regions excluded from use. */ 207 - struct xe_ggtt_node ggtt_balloon[2]; 207 + struct xe_ggtt_node *ggtt_balloon[2]; 208 208 } vf; 209 209 } sriov; 210 210
+104 -36
drivers/gpu/drm/xe/xe_ggtt.c
··· 348 348 349 349 /** 350 350 * xe_ggtt_node_insert_balloon - prevent allocation of specified GGTT addresses 351 - * @ggtt: the &xe_ggtt where we want to make reservation 352 351 * @node: the &xe_ggtt_node to hold reserved GGTT node 353 352 * @start: the starting GGTT address of the reserved region 354 353 * @end: then end GGTT address of the reserved region ··· 356 357 * 357 358 * Return: 0 on success or a negative error code on failure. 358 359 */ 359 - int xe_ggtt_node_insert_balloon(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, u64 start, u64 end) 360 + int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) 360 361 { 362 + struct xe_ggtt *ggtt = node->ggtt; 361 363 int err; 362 364 363 365 xe_tile_assert(ggtt->tile, start < end); ··· 385 385 386 386 /** 387 387 * xe_ggtt_node_remove_balloon - release a reserved GGTT region 388 - * @ggtt: the &xe_ggtt where reserved node belongs 389 388 * @node: the &xe_ggtt_node with reserved GGTT region 390 389 * 391 390 * See xe_ggtt_node_insert_balloon() for details. 392 391 */ 393 - void xe_ggtt_node_remove_balloon(struct xe_ggtt *ggtt, struct xe_ggtt_node *node) 392 + void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node) 394 393 { 395 - if (!drm_mm_node_allocated(&node->base)) 394 + if (!node || !node->ggtt) 396 395 return; 397 396 398 - xe_ggtt_dump_node(ggtt, &node->base, "remove-balloon"); 397 + if (!drm_mm_node_allocated(&node->base)) 398 + goto free_node; 399 399 400 - mutex_lock(&ggtt->lock); 400 + xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon"); 401 + 402 + mutex_lock(&node->ggtt->lock); 401 403 drm_mm_remove_node(&node->base); 402 - mutex_unlock(&ggtt->lock); 404 + mutex_unlock(&node->ggtt->lock); 405 + 406 + free_node: 407 + xe_ggtt_node_fini(node); 403 408 } 404 409 405 410 /** 406 411 * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT 407 - * @ggtt: the &xe_ggtt where node will be inserted 408 412 * @node: the &xe_ggtt_node to be inserted 409 413 * @size: size of the node 410 414 * @align: alignment constrain of the node 411 415 * @mm_flags: flags to control the node behavior 412 416 * 417 + * It cannot be called without first having called xe_ggtt_init() once. 413 418 * To be used in cases where ggtt->lock is already taken. 414 419 * 415 420 * Return: 0 on success or a negative error code on failure. 416 421 */ 417 - int xe_ggtt_node_insert_locked(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 422 + int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, 418 423 u32 size, u32 align, u32 mm_flags) 419 424 { 420 - return drm_mm_insert_node_generic(&ggtt->mm, &node->base, size, align, 0, 425 + return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, align, 0, 421 426 mm_flags); 422 427 } 423 428 424 429 /** 425 430 * xe_ggtt_node_insert - Insert a &xe_ggtt_node into the GGTT 426 - * @ggtt: the &xe_ggtt where node will be inserted 427 431 * @node: the &xe_ggtt_node to be inserted 428 432 * @size: size of the node 429 433 * @align: alignment constrain of the node 430 434 * 435 + * It cannot be called without first having called xe_ggtt_init() once. 436 + * 431 437 * Return: 0 on success or a negative error code on failure. 432 438 */ 433 - int xe_ggtt_node_insert(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 434 - u32 size, u32 align) 439 + int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align) 435 440 { 436 441 int ret; 437 442 438 - mutex_lock(&ggtt->lock); 439 - ret = xe_ggtt_node_insert_locked(ggtt, node, size, 440 - align, DRM_MM_INSERT_HIGH); 441 - mutex_unlock(&ggtt->lock); 443 + if (!node || !node->ggtt) 444 + return -ENOENT; 445 + 446 + mutex_lock(&node->ggtt->lock); 447 + ret = xe_ggtt_node_insert_locked(node, size, align, 448 + DRM_MM_INSERT_HIGH); 449 + mutex_unlock(&node->ggtt->lock); 442 450 443 451 return ret; 444 452 } 445 453 446 454 /** 455 + * xe_ggtt_node_init - Initialize %xe_ggtt_node struct 456 + * @ggtt: the &xe_ggtt where the new node will later be inserted/reserved. 457 + * 458 + * This function will allocated the struct %xe_ggtt_node and return it's pointer. 459 + * This struct will then be freed after the node removal upon xe_ggtt_node_remove() 460 + * or xe_ggtt_node_remove_balloon(). 461 + * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated 462 + * in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), 463 + * xe_ggtt_node_insert_balloon() will ensure the node is inserted or reserved in GGTT. 464 + * 465 + * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. 466 + **/ 467 + struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt) 468 + { 469 + struct xe_ggtt_node *node = kzalloc(sizeof(*node), GFP_NOFS); 470 + 471 + if (!node) 472 + return ERR_PTR(-ENOMEM); 473 + 474 + node->ggtt = ggtt; 475 + return node; 476 + } 477 + 478 + /** 479 + * xe_ggtt_node_fini - Forcebly finalize %xe_ggtt_node struct 480 + * @node: the &xe_ggtt_node to be freed 481 + * 482 + * If anything went wrong with either xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), 483 + * or xe_ggtt_node_insert_balloon(); and this @node is not going to be reused, then, 484 + * this function needs to be called to free the %xe_ggtt_node struct 485 + **/ 486 + void xe_ggtt_node_fini(struct xe_ggtt_node *node) 487 + { 488 + kfree(node); 489 + } 490 + 491 + /** 447 492 * xe_ggtt_node_remove - Remove a &xe_ggtt_node from the GGTT 448 - * @ggtt: the &xe_ggtt where node will be removed 449 493 * @node: the &xe_ggtt_node to be removed 450 494 * @invalidate: if node needs invalidation upon removal 451 495 */ 452 - void xe_ggtt_node_remove(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 453 - bool invalidate) 496 + void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate) 454 497 { 498 + struct xe_ggtt *ggtt = node->ggtt; 455 499 struct xe_device *xe = tile_to_xe(ggtt->tile); 456 500 bool bound; 457 501 int idx; 502 + 503 + if (!node || !node->ggtt) 504 + return; 458 505 459 506 bound = drm_dev_enter(&xe->drm, &idx); 460 507 if (bound) ··· 515 468 mutex_unlock(&ggtt->lock); 516 469 517 470 if (!bound) 518 - return; 471 + goto free_node; 519 472 520 473 if (invalidate) 521 474 xe_ggtt_invalidate(ggtt); 522 475 523 476 xe_pm_runtime_put(xe); 524 477 drm_dev_exit(idx); 478 + 479 + free_node: 480 + xe_ggtt_node_fini(node); 525 481 } 526 482 527 483 /** 528 - * xe_ggtt_node_allocated - Check if node is allocated 484 + * xe_ggtt_node_allocated - Check if node is allocated in GGTT 529 485 * @node: the &xe_ggtt_node to be inspected 530 486 * 531 487 * Return: True if allocated, False otherwise. 532 488 */ 533 489 bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node) 534 490 { 491 + if (!node || !node->ggtt) 492 + return false; 493 + 535 494 return drm_mm_node_allocated(&node->base); 536 495 } 537 496 ··· 550 497 { 551 498 u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; 552 499 u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; 553 - u64 start = bo->ggtt_node.base.start; 500 + u64 start; 554 501 u64 offset, pte; 502 + 503 + if (XE_WARN_ON(!bo->ggtt_node)) 504 + return; 505 + 506 + start = bo->ggtt_node->base.start; 555 507 556 508 for (offset = 0; offset < bo->size; offset += XE_PAGE_SIZE) { 557 509 pte = ggtt->pt_ops->pte_encode_bo(bo, offset, pat_index); ··· 573 515 if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) 574 516 alignment = SZ_64K; 575 517 576 - if (XE_WARN_ON(bo->ggtt_node.base.size)) { 518 + if (XE_WARN_ON(bo->ggtt_node)) { 577 519 /* Someone's already inserted this BO in the GGTT */ 578 - xe_tile_assert(ggtt->tile, bo->ggtt_node.base.size == bo->size); 520 + xe_tile_assert(ggtt->tile, bo->ggtt_node->base.size == bo->size); 579 521 return 0; 580 522 } 581 523 ··· 584 526 return err; 585 527 586 528 xe_pm_runtime_get_noresume(tile_to_xe(ggtt->tile)); 529 + 530 + bo->ggtt_node = xe_ggtt_node_init(ggtt); 531 + if (IS_ERR(bo->ggtt_node)) { 532 + err = PTR_ERR(bo->ggtt_node); 533 + goto out; 534 + } 535 + 587 536 mutex_lock(&ggtt->lock); 588 - err = drm_mm_insert_node_in_range(&ggtt->mm, &bo->ggtt_node.base, bo->size, 537 + err = drm_mm_insert_node_in_range(&ggtt->mm, &bo->ggtt_node->base, bo->size, 589 538 alignment, 0, start, end, 0); 590 - if (!err) 539 + if (err) 540 + xe_ggtt_node_fini(bo->ggtt_node); 541 + else 591 542 xe_ggtt_map_bo(ggtt, bo); 592 543 mutex_unlock(&ggtt->lock); 593 544 594 545 if (!err && bo->flags & XE_BO_FLAG_GGTT_INVALIDATE) 595 546 xe_ggtt_invalidate(ggtt); 547 + 548 + out: 596 549 xe_pm_runtime_put(tile_to_xe(ggtt->tile)); 597 550 598 551 return err; ··· 643 574 */ 644 575 void xe_ggtt_remove_bo(struct xe_ggtt *ggtt, struct xe_bo *bo) 645 576 { 646 - if (XE_WARN_ON(!bo->ggtt_node.base.size)) 577 + if (XE_WARN_ON(!bo->ggtt_node)) 647 578 return; 648 579 649 580 /* This BO is not currently in the GGTT */ 650 - xe_tile_assert(ggtt->tile, bo->ggtt_node.base.size == bo->size); 581 + xe_tile_assert(ggtt->tile, bo->ggtt_node->base.size == bo->size); 651 582 652 - xe_ggtt_node_remove(ggtt, &bo->ggtt_node, 583 + xe_ggtt_node_remove(bo->ggtt_node, 653 584 bo->flags & XE_BO_FLAG_GGTT_INVALIDATE); 654 585 } 655 586 ··· 716 647 717 648 /** 718 649 * xe_ggtt_assign - assign a GGTT region to the VF 719 - * @ggtt: the &xe_ggtt where the node belongs 720 650 * @node: the &xe_ggtt_node to update 721 651 * @vfid: the VF identifier 722 652 * ··· 723 655 * In addition to PTE's VFID bits 11:2 also PRESENT bit 0 is set as on some 724 656 * platforms VFs can't modify that either. 725 657 */ 726 - void xe_ggtt_assign(struct xe_ggtt *ggtt, const struct xe_ggtt_node *node, u16 vfid) 658 + void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid) 727 659 { 728 - mutex_lock(&ggtt->lock); 729 - xe_ggtt_assign_locked(ggtt, &node->base, vfid); 730 - mutex_unlock(&ggtt->lock); 660 + mutex_lock(&node->ggtt->lock); 661 + xe_ggtt_assign_locked(node->ggtt, &node->base, vfid); 662 + mutex_unlock(&node->ggtt->lock); 731 663 } 732 664 #endif 733 665
+8 -9
drivers/gpu/drm/xe/xe_ggtt.h
··· 13 13 int xe_ggtt_init_early(struct xe_ggtt *ggtt); 14 14 int xe_ggtt_init(struct xe_ggtt *ggtt); 15 15 16 - int xe_ggtt_node_insert_balloon(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 16 + struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt); 17 + void xe_ggtt_node_fini(struct xe_ggtt_node *node); 18 + int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, 17 19 u64 start, u64 size); 18 - void xe_ggtt_node_remove_balloon(struct xe_ggtt *ggtt, struct xe_ggtt_node *node); 20 + void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node); 19 21 20 - int xe_ggtt_node_insert(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 21 - u32 size, u32 align); 22 - int xe_ggtt_node_insert_locked(struct xe_ggtt *ggtt, 23 - struct xe_ggtt_node *node, 22 + int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); 23 + int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, 24 24 u32 size, u32 align, u32 mm_flags); 25 - void xe_ggtt_node_remove(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, 26 - bool invalidate); 25 + void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); 27 26 bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); 28 27 void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo); 29 28 int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo); ··· 35 36 u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer *p); 36 37 37 38 #ifdef CONFIG_PCI_IOV 38 - void xe_ggtt_assign(struct xe_ggtt *ggtt, const struct xe_ggtt_node *node, u16 vfid); 39 + void xe_ggtt_assign(const struct xe_ggtt_node *node, u16 vfid); 39 40 #endif 40 41 41 42 #endif
+7 -1
drivers/gpu/drm/xe/xe_ggtt_types.h
··· 50 50 }; 51 51 52 52 /** 53 - * struct xe_ggtt_node - A node in GGTT 53 + * struct xe_ggtt_node - A node in GGTT. 54 + * 55 + * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node 56 + * insertion, reservation, or 'ballooning'. 57 + * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). 54 58 */ 55 59 struct xe_ggtt_node { 60 + /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ 61 + struct xe_ggtt *ggtt; 56 62 /** @base: A drm_mm_node */ 57 63 struct drm_mm_node base; 58 64 };
+29 -20
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
··· 232 232 { 233 233 u32 n = 0; 234 234 235 - if (xe_ggtt_node_allocated(&config->ggtt_region)) { 235 + if (xe_ggtt_node_allocated(config->ggtt_region)) { 236 236 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_GGTT_START); 237 - cfg[n++] = lower_32_bits(config->ggtt_region.base.start); 238 - cfg[n++] = upper_32_bits(config->ggtt_region.base.start); 237 + cfg[n++] = lower_32_bits(config->ggtt_region->base.start); 238 + cfg[n++] = upper_32_bits(config->ggtt_region->base.start); 239 239 240 240 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_GGTT_SIZE); 241 - cfg[n++] = lower_32_bits(config->ggtt_region.base.size); 242 - cfg[n++] = upper_32_bits(config->ggtt_region.base.size); 241 + cfg[n++] = lower_32_bits(config->ggtt_region->base.size); 242 + cfg[n++] = upper_32_bits(config->ggtt_region->base.size); 243 243 } 244 244 245 245 return n; ··· 371 371 372 372 static void pf_release_ggtt(struct xe_tile *tile, struct xe_ggtt_node *node) 373 373 { 374 - struct xe_ggtt *ggtt = tile->mem.ggtt; 375 - 376 374 if (xe_ggtt_node_allocated(node)) { 377 375 /* 378 376 * explicit GGTT PTE assignment to the PF using xe_ggtt_assign() 379 377 * is redundant, as PTE will be implicitly re-assigned to PF by 380 378 * the xe_ggtt_clear() called by below xe_ggtt_remove_node(). 381 379 */ 382 - xe_ggtt_node_remove(ggtt, node, false); 380 + xe_ggtt_node_remove(node, false); 383 381 } 384 382 } 385 383 386 384 static void pf_release_vf_config_ggtt(struct xe_gt *gt, struct xe_gt_sriov_config *config) 387 385 { 388 - pf_release_ggtt(gt_to_tile(gt), &config->ggtt_region); 386 + pf_release_ggtt(gt_to_tile(gt), config->ggtt_region); 387 + config->ggtt_region = NULL; 389 388 } 390 389 391 390 static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) 392 391 { 393 392 struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); 394 - struct xe_ggtt_node *node = &config->ggtt_region; 393 + struct xe_ggtt_node *node = config->ggtt_region; 395 394 struct xe_tile *tile = gt_to_tile(gt); 396 395 struct xe_ggtt *ggtt = tile->mem.ggtt; 397 396 u64 alignment = pf_get_ggtt_alignment(gt); ··· 414 415 if (!size) 415 416 return 0; 416 417 417 - err = xe_ggtt_node_insert(ggtt, node, size, alignment); 418 - if (unlikely(err)) 419 - return err; 418 + node = xe_ggtt_node_init(ggtt); 419 + if (IS_ERR(node)) 420 + return PTR_ERR(node); 420 421 421 - xe_ggtt_assign(ggtt, node, vfid); 422 + err = xe_ggtt_node_insert(node, size, alignment); 423 + if (unlikely(err)) 424 + goto err; 425 + 426 + xe_ggtt_assign(node, vfid); 422 427 xe_gt_sriov_dbg_verbose(gt, "VF%u assigned GGTT %llx-%llx\n", 423 428 vfid, node->base.start, node->base.start + node->base.size - 1); 424 429 425 430 err = pf_distribute_config_ggtt(gt->tile, vfid, node->base.start, node->base.size); 426 431 if (unlikely(err)) 427 - return err; 432 + goto err; 428 433 434 + config->ggtt_region = node; 429 435 return 0; 436 + err: 437 + xe_ggtt_node_fini(node); 438 + return err; 430 439 } 431 440 432 441 static u64 pf_get_vf_config_ggtt(struct xe_gt *gt, unsigned int vfid) 433 442 { 434 443 struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); 435 - struct xe_ggtt_node *node = &config->ggtt_region; 444 + struct xe_ggtt_node *node = config->ggtt_region; 436 445 437 446 xe_gt_assert(gt, !xe_gt_is_media_type(gt)); 438 447 return xe_ggtt_node_allocated(node) ? node->base.size : 0; ··· 2013 2006 2014 2007 for (n = 1; n <= total_vfs; n++) { 2015 2008 config = &gt->sriov.pf.vfs[n].config; 2016 - if (!xe_ggtt_node_allocated(&config->ggtt_region)) 2009 + if (!xe_ggtt_node_allocated(config->ggtt_region)) 2017 2010 continue; 2018 2011 2019 - string_get_size(config->ggtt_region.base.size, 1, STRING_UNITS_2, buf, sizeof(buf)); 2012 + string_get_size(config->ggtt_region->base.size, 1, STRING_UNITS_2, 2013 + buf, sizeof(buf)); 2020 2014 drm_printf(p, "VF%u:\t%#0llx-%#llx\t(%s)\n", 2021 - n, config->ggtt_region.base.start, 2022 - config->ggtt_region.base.start + config->ggtt_region.base.size - 1, buf); 2015 + n, config->ggtt_region->base.start, 2016 + config->ggtt_region->base.start + config->ggtt_region->base.size - 1, 2017 + buf); 2023 2018 } 2024 2019 2025 2020 return 0;
+1 -1
drivers/gpu/drm/xe/xe_gt_sriov_pf_config_types.h
··· 18 18 */ 19 19 struct xe_gt_sriov_config { 20 20 /** @ggtt_region: GGTT region assigned to the VF. */ 21 - struct xe_ggtt_node ggtt_region; 21 + struct xe_ggtt_node *ggtt_region; 22 22 /** @lmem_obj: LMEM allocation for use by the VF. */ 23 23 struct xe_bo *lmem_obj; 24 24 /** @num_ctxs: number of GuC contexts IDs. */
+29 -17
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
··· 495 495 return gt->sriov.vf.self_config.lmem_size; 496 496 } 497 497 498 + static struct xe_ggtt_node * 499 + vf_balloon_ggtt_node(struct xe_ggtt *ggtt, u64 start, u64 end) 500 + { 501 + struct xe_ggtt_node *node; 502 + int err; 503 + 504 + node = xe_ggtt_node_init(ggtt); 505 + if (IS_ERR(node)) 506 + return node; 507 + 508 + err = xe_ggtt_node_insert_balloon(node, start, end); 509 + if (err) { 510 + xe_ggtt_node_fini(node); 511 + return ERR_PTR(err); 512 + } 513 + 514 + return node; 515 + } 516 + 498 517 static int vf_balloon_ggtt(struct xe_gt *gt) 499 518 { 500 519 struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; ··· 521 502 struct xe_ggtt *ggtt = tile->mem.ggtt; 522 503 struct xe_device *xe = gt_to_xe(gt); 523 504 u64 start, end; 524 - int err; 525 505 526 506 xe_gt_assert(gt, IS_SRIOV_VF(xe)); 527 507 xe_gt_assert(gt, !xe_gt_is_media_type(gt)); ··· 546 528 start = xe_wopcm_size(xe); 547 529 end = config->ggtt_base; 548 530 if (end != start) { 549 - err = xe_ggtt_node_insert_balloon(ggtt, &tile->sriov.vf.ggtt_balloon[0], 550 - start, end); 551 - if (err) 552 - goto failed; 531 + tile->sriov.vf.ggtt_balloon[0] = vf_balloon_ggtt_node(ggtt, start, end); 532 + if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) 533 + return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); 553 534 } 554 535 555 536 start = config->ggtt_base + config->ggtt_size; 556 537 end = GUC_GGTT_TOP; 557 538 if (end != start) { 558 - err = xe_ggtt_node_insert_balloon(ggtt, &tile->sriov.vf.ggtt_balloon[1], 559 - start, end); 560 - if (err) 561 - goto deballoon; 539 + tile->sriov.vf.ggtt_balloon[1] = vf_balloon_ggtt_node(ggtt, start, end); 540 + if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { 541 + xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); 542 + return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); 543 + } 562 544 } 563 545 564 546 return 0; 565 - 566 - deballoon: 567 - xe_ggtt_node_remove_balloon(ggtt, &tile->sriov.vf.ggtt_balloon[0]); 568 - failed: 569 - return err; 570 547 } 571 548 572 549 static void deballoon_ggtt(struct drm_device *drm, void *arg) 573 550 { 574 551 struct xe_tile *tile = arg; 575 - struct xe_ggtt *ggtt = tile->mem.ggtt; 576 552 577 553 xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 578 - xe_ggtt_node_remove_balloon(ggtt, &tile->sriov.vf.ggtt_balloon[1]); 579 - xe_ggtt_node_remove_balloon(ggtt, &tile->sriov.vf.ggtt_balloon[0]); 554 + xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[1]); 555 + xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); 580 556 } 581 557 582 558 /**