Lines Matching +full:spare +full:- +full:regs
1 // SPDX-License-Identifier: MIT
8 #include <linux/fault-inject.h>
9 #include <linux/io-64-nonatomic-lo-hi.h>
17 #include "regs/xe_gt_regs.h"
18 #include "regs/xe_gtt_defs.h"
19 #include "regs/xe_regs.h"
38 * for resources that are accessible to privileged (i.e. kernel-mode) processes,
39 * and not tied to a specific user-level process. For example, the Graphics
40 * micro-Controller (GuC) and Display Engine (if present) utilize this Global
44 * address that can be accessed by HW. The GGTT is a flat, single-level table.
59 * GGTT. These simplifications might waste space in the GGTT (about 20-25 MBs
111 struct xe_tile *tile = ggtt->tile; in ggtt_update_access_counter()
112 struct xe_gt *affected_gt = XE_WA(tile->primary_gt, 22019338487) ? in ggtt_update_access_counter()
113 tile->primary_gt : tile->media_gt; in ggtt_update_access_counter()
114 struct xe_mmio *mmio = &affected_gt->mmio; in ggtt_update_access_counter()
115 u32 max_gtt_writes = XE_WA(ggtt->tile->primary_gt, 22019338487) ? 1100 : 63; in ggtt_update_access_counter()
121 lockdep_assert_held(&ggtt->lock); in ggtt_update_access_counter()
123 if ((++ggtt->access_count % max_gtt_writes) == 0) { in ggtt_update_access_counter()
125 ggtt->access_count = 0; in ggtt_update_access_counter()
131 xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK)); in xe_ggtt_set_pte()
132 xe_tile_assert(ggtt->tile, addr < ggtt->size); in xe_ggtt_set_pte()
134 writeq(pte, &ggtt->gsm[addr >> XE_PTE_SHIFT]); in xe_ggtt_set_pte()
145 u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB]; in xe_ggtt_clear()
146 u64 end = start + size - 1; in xe_ggtt_clear()
149 xe_tile_assert(ggtt->tile, start < end); in xe_ggtt_clear()
151 if (ggtt->scratch) in xe_ggtt_clear()
152 scratch_pte = ggtt->pt_ops->pte_encode_bo(ggtt->scratch, 0, in xe_ggtt_clear()
158 ggtt->pt_ops->ggtt_set_pte(ggtt, start, scratch_pte); in xe_ggtt_clear()
167 destroy_workqueue(ggtt->wq); in ggtt_fini_early()
168 mutex_destroy(&ggtt->lock); in ggtt_fini_early()
169 drm_mm_takedown(&ggtt->mm); in ggtt_fini_early()
176 ggtt->scratch = NULL; in ggtt_fini()
185 might_lock(&ggtt->lock); in primelockdep()
205 * xe_ggtt_init_early - Early GGTT initialization
210 * initial clear done to it yet. That will happen in the regular, non-early
217 struct xe_device *xe = tile_to_xe(ggtt->tile); in xe_ggtt_init_early()
218 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); in xe_ggtt_init_early()
228 drm_err(&xe->drm, "Hardware reported no preallocated GSM\n"); in xe_ggtt_init_early()
229 return -ENOMEM; in xe_ggtt_init_early()
232 ggtt->gsm = ggtt->tile->mmio.regs + SZ_8M; in xe_ggtt_init_early()
233 ggtt->size = (gsm_size / 8) * (u64) XE_PAGE_SIZE; in xe_ggtt_init_early()
235 if (IS_DGFX(xe) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) in xe_ggtt_init_early()
236 ggtt->flags |= XE_GGTT_FLAGS_64K; in xe_ggtt_init_early()
238 if (ggtt->size > GUC_GGTT_TOP) in xe_ggtt_init_early()
239 ggtt->size = GUC_GGTT_TOP; in xe_ggtt_init_early()
242 ggtt->pt_ops = (ggtt->tile->media_gt && in xe_ggtt_init_early()
243 XE_WA(ggtt->tile->media_gt, 22019338487)) || in xe_ggtt_init_early()
244 XE_WA(ggtt->tile->primary_gt, 22019338487) ? in xe_ggtt_init_early()
247 ggtt->pt_ops = &xelp_pt_ops; in xe_ggtt_init_early()
249 ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM); in xe_ggtt_init_early()
251 drm_mm_init(&ggtt->mm, xe_wopcm_size(xe), in xe_ggtt_init_early()
252 ggtt->size - xe_wopcm_size(xe)); in xe_ggtt_init_early()
253 mutex_init(&ggtt->lock); in xe_ggtt_init_early()
256 err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); in xe_ggtt_init_early()
261 err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0)); in xe_ggtt_init_early()
278 mutex_lock(&ggtt->lock); in xe_ggtt_initial_clear()
279 drm_mm_for_each_hole(hole, &ggtt->mm, start, end) in xe_ggtt_initial_clear()
280 xe_ggtt_clear(ggtt, start, end - start); in xe_ggtt_initial_clear()
283 mutex_unlock(&ggtt->lock); in xe_ggtt_initial_clear()
288 struct xe_ggtt *ggtt = node->ggtt; in ggtt_node_remove()
289 struct xe_device *xe = tile_to_xe(ggtt->tile); in ggtt_node_remove()
293 bound = drm_dev_enter(&xe->drm, &idx); in ggtt_node_remove()
295 mutex_lock(&ggtt->lock); in ggtt_node_remove()
297 xe_ggtt_clear(ggtt, node->base.start, node->base.size); in ggtt_node_remove()
298 drm_mm_remove_node(&node->base); in ggtt_node_remove()
299 node->base.size = 0; in ggtt_node_remove()
300 mutex_unlock(&ggtt->lock); in ggtt_node_remove()
305 if (node->invalidate_on_remove) in ggtt_node_remove()
318 struct xe_device *xe = tile_to_xe(node->ggtt->tile); in ggtt_node_remove_work_func()
326 * xe_ggtt_node_remove - Remove a &xe_ggtt_node from the GGTT
335 if (!node || !node->ggtt) in xe_ggtt_node_remove()
338 ggtt = node->ggtt; in xe_ggtt_node_remove()
339 xe = tile_to_xe(ggtt->tile); in xe_ggtt_node_remove()
341 node->invalidate_on_remove = invalidate; in xe_ggtt_node_remove()
347 queue_work(ggtt->wq, &node->delayed_removal_work); in xe_ggtt_node_remove()
352 * xe_ggtt_init - Regular non-early GGTT initialization
359 struct xe_device *xe = tile_to_xe(ggtt->tile); in xe_ggtt_init()
369 if (ggtt->flags & XE_GGTT_FLAGS_64K) in xe_ggtt_init()
372 flags |= XE_BO_FLAG_VRAM_IF_DGFX(ggtt->tile); in xe_ggtt_init()
374 ggtt->scratch = xe_managed_bo_create_pin_map(xe, ggtt->tile, XE_PAGE_SIZE, flags); in xe_ggtt_init()
375 if (IS_ERR(ggtt->scratch)) { in xe_ggtt_init()
376 err = PTR_ERR(ggtt->scratch); in xe_ggtt_init()
380 xe_map_memset(xe, &ggtt->scratch->vmap, 0, 0, ggtt->scratch->size); in xe_ggtt_init()
384 return devm_add_action_or_reset(xe->drm.dev, ggtt_fini, ggtt); in xe_ggtt_init()
386 ggtt->scratch = NULL; in xe_ggtt_init()
399 drm_warn(>_to_xe(gt)->drm, "xe_gt_tlb_invalidation_ggtt error=%d", err); in ggtt_invalidate_gt_tlb()
404 struct xe_device *xe = tile_to_xe(ggtt->tile); in xe_ggtt_invalidate()
415 ggtt_invalidate_gt_tlb(ggtt->tile->primary_gt); in xe_ggtt_invalidate()
416 ggtt_invalidate_gt_tlb(ggtt->tile->media_gt); in xe_ggtt_invalidate()
425 string_get_size(node->size, 1, STRING_UNITS_2, buf, sizeof(buf)); in xe_ggtt_dump_node()
426 xe_gt_dbg(ggtt->tile->primary_gt, "GGTT %#llx-%#llx (%s) %s\n", in xe_ggtt_dump_node()
427 node->start, node->start + node->size, buf, description); in xe_ggtt_dump_node()
432 * xe_ggtt_node_insert_balloon - prevent allocation of specified GGTT addresses
443 struct xe_ggtt *ggtt = node->ggtt; in xe_ggtt_node_insert_balloon()
446 xe_tile_assert(ggtt->tile, start < end); in xe_ggtt_node_insert_balloon()
447 xe_tile_assert(ggtt->tile, IS_ALIGNED(start, XE_PAGE_SIZE)); in xe_ggtt_node_insert_balloon()
448 xe_tile_assert(ggtt->tile, IS_ALIGNED(end, XE_PAGE_SIZE)); in xe_ggtt_node_insert_balloon()
449 xe_tile_assert(ggtt->tile, !drm_mm_node_allocated(&node->base)); in xe_ggtt_node_insert_balloon()
451 node->base.color = 0; in xe_ggtt_node_insert_balloon()
452 node->base.start = start; in xe_ggtt_node_insert_balloon()
453 node->base.size = end - start; in xe_ggtt_node_insert_balloon()
455 mutex_lock(&ggtt->lock); in xe_ggtt_node_insert_balloon()
456 err = drm_mm_reserve_node(&ggtt->mm, &node->base); in xe_ggtt_node_insert_balloon()
457 mutex_unlock(&ggtt->lock); in xe_ggtt_node_insert_balloon()
459 if (xe_gt_WARN(ggtt->tile->primary_gt, err, in xe_ggtt_node_insert_balloon()
460 "Failed to balloon GGTT %#llx-%#llx (%pe)\n", in xe_ggtt_node_insert_balloon()
461 node->base.start, node->base.start + node->base.size, ERR_PTR(err))) in xe_ggtt_node_insert_balloon()
464 xe_ggtt_dump_node(ggtt, &node->base, "balloon"); in xe_ggtt_node_insert_balloon()
469 * xe_ggtt_node_remove_balloon - release a reserved GGTT region
476 if (!node || !node->ggtt) in xe_ggtt_node_remove_balloon()
479 if (!drm_mm_node_allocated(&node->base)) in xe_ggtt_node_remove_balloon()
482 xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon"); in xe_ggtt_node_remove_balloon()
484 mutex_lock(&node->ggtt->lock); in xe_ggtt_node_remove_balloon()
485 drm_mm_remove_node(&node->base); in xe_ggtt_node_remove_balloon()
486 mutex_unlock(&node->ggtt->lock); in xe_ggtt_node_remove_balloon()
493 * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT
500 * To be used in cases where ggtt->lock is already taken.
507 return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, align, 0, in xe_ggtt_node_insert_locked()
512 * xe_ggtt_node_insert - Insert a &xe_ggtt_node into the GGTT
525 if (!node || !node->ggtt) in xe_ggtt_node_insert()
526 return -ENOENT; in xe_ggtt_node_insert()
528 mutex_lock(&node->ggtt->lock); in xe_ggtt_node_insert()
531 mutex_unlock(&node->ggtt->lock); in xe_ggtt_node_insert()
537 * xe_ggtt_node_init - Initialize %xe_ggtt_node struct
554 return ERR_PTR(-ENOMEM); in xe_ggtt_node_init()
556 INIT_WORK(&node->delayed_removal_work, ggtt_node_remove_work_func); in xe_ggtt_node_init()
557 node->ggtt = ggtt; in xe_ggtt_node_init()
563 * xe_ggtt_node_fini - Forcebly finalize %xe_ggtt_node struct
576 * xe_ggtt_node_allocated - Check if node is allocated in GGTT
583 if (!node || !node->ggtt) in xe_ggtt_node_allocated()
586 return drm_mm_node_allocated(&node->base); in xe_ggtt_node_allocated()
590 * xe_ggtt_map_bo - Map the BO into GGTT
596 u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; in xe_ggtt_map_bo()
597 u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; in xe_ggtt_map_bo()
601 if (XE_WARN_ON(!bo->ggtt_node[ggtt->tile->id])) in xe_ggtt_map_bo()
604 start = bo->ggtt_node[ggtt->tile->id]->base.start; in xe_ggtt_map_bo()
606 for (offset = 0; offset < bo->size; offset += XE_PAGE_SIZE) { in xe_ggtt_map_bo()
607 pte = ggtt->pt_ops->pte_encode_bo(bo, offset, pat_index); in xe_ggtt_map_bo()
608 ggtt->pt_ops->ggtt_set_pte(ggtt, start + offset, pte); in xe_ggtt_map_bo()
615 u64 alignment = bo->min_align > 0 ? bo->min_align : XE_PAGE_SIZE; in __xe_ggtt_insert_bo_at()
616 u8 tile_id = ggtt->tile->id; in __xe_ggtt_insert_bo_at()
619 if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) in __xe_ggtt_insert_bo_at()
622 if (XE_WARN_ON(bo->ggtt_node[tile_id])) { in __xe_ggtt_insert_bo_at()
624 xe_tile_assert(ggtt->tile, bo->ggtt_node[tile_id]->base.size == bo->size); in __xe_ggtt_insert_bo_at()
632 xe_pm_runtime_get_noresume(tile_to_xe(ggtt->tile)); in __xe_ggtt_insert_bo_at()
634 bo->ggtt_node[tile_id] = xe_ggtt_node_init(ggtt); in __xe_ggtt_insert_bo_at()
635 if (IS_ERR(bo->ggtt_node[tile_id])) { in __xe_ggtt_insert_bo_at()
636 err = PTR_ERR(bo->ggtt_node[tile_id]); in __xe_ggtt_insert_bo_at()
637 bo->ggtt_node[tile_id] = NULL; in __xe_ggtt_insert_bo_at()
641 mutex_lock(&ggtt->lock); in __xe_ggtt_insert_bo_at()
642 err = drm_mm_insert_node_in_range(&ggtt->mm, &bo->ggtt_node[tile_id]->base, in __xe_ggtt_insert_bo_at()
643 bo->size, alignment, 0, start, end, 0); in __xe_ggtt_insert_bo_at()
645 xe_ggtt_node_fini(bo->ggtt_node[tile_id]); in __xe_ggtt_insert_bo_at()
646 bo->ggtt_node[tile_id] = NULL; in __xe_ggtt_insert_bo_at()
650 mutex_unlock(&ggtt->lock); in __xe_ggtt_insert_bo_at()
652 if (!err && bo->flags & XE_BO_FLAG_GGTT_INVALIDATE) in __xe_ggtt_insert_bo_at()
656 xe_pm_runtime_put(tile_to_xe(ggtt->tile)); in __xe_ggtt_insert_bo_at()
662 * xe_ggtt_insert_bo_at - Insert BO at a specific GGTT space
677 * xe_ggtt_insert_bo - Insert BO into GGTT
689 * xe_ggtt_remove_bo - Remove a BO from the GGTT
695 u8 tile_id = ggtt->tile->id; in xe_ggtt_remove_bo()
697 if (XE_WARN_ON(!bo->ggtt_node[tile_id])) in xe_ggtt_remove_bo()
701 xe_tile_assert(ggtt->tile, bo->ggtt_node[tile_id]->base.size == bo->size); in xe_ggtt_remove_bo()
703 xe_ggtt_node_remove(bo->ggtt_node[tile_id], in xe_ggtt_remove_bo()
704 bo->flags & XE_BO_FLAG_GGTT_INVALIDATE); in xe_ggtt_remove_bo()
708 * xe_ggtt_largest_hole - Largest GGTT hole
711 * @spare: If not NULL: in: desired memory size to be spared / out: Adjusted possible spare
715 u64 xe_ggtt_largest_hole(struct xe_ggtt *ggtt, u64 alignment, u64 *spare) in xe_ggtt_largest_hole() argument
717 const struct drm_mm *mm = &ggtt->mm; in xe_ggtt_largest_hole()
719 u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); in xe_ggtt_largest_hole()
723 mutex_lock(&ggtt->lock); in xe_ggtt_largest_hole()
731 hole_size = hole_end - hole_start; in xe_ggtt_largest_hole()
732 if (spare) in xe_ggtt_largest_hole()
733 *spare -= min3(*spare, hole_size, max_hole); in xe_ggtt_largest_hole()
737 mutex_unlock(&ggtt->lock); in xe_ggtt_largest_hole()
750 u64 start = node->start; in xe_ggtt_assign_locked()
751 u64 size = node->size; in xe_ggtt_assign_locked()
752 u64 end = start + size - 1; in xe_ggtt_assign_locked()
755 lockdep_assert_held(&ggtt->lock); in xe_ggtt_assign_locked()
761 ggtt->pt_ops->ggtt_set_pte(ggtt, start, pte); in xe_ggtt_assign_locked()
769 * xe_ggtt_assign - assign a GGTT region to the VF
779 mutex_lock(&node->ggtt->lock); in xe_ggtt_assign()
780 xe_ggtt_assign_locked(node->ggtt, &node->base, vfid); in xe_ggtt_assign()
781 mutex_unlock(&node->ggtt->lock); in xe_ggtt_assign()
786 * xe_ggtt_dump - Dump GGTT for debug
796 err = mutex_lock_interruptible(&ggtt->lock); in xe_ggtt_dump()
800 drm_mm_print(&ggtt->mm, p); in xe_ggtt_dump()
801 mutex_unlock(&ggtt->lock); in xe_ggtt_dump()
806 * xe_ggtt_print_holes - Print holes
817 const struct drm_mm *mm = &ggtt->mm; in xe_ggtt_print_holes()
819 u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); in xe_ggtt_print_holes()
824 mutex_lock(&ggtt->lock); in xe_ggtt_print_holes()
832 hole_size = hole_end - hole_start; in xe_ggtt_print_holes()
836 drm_printf(p, "range:\t%#llx-%#llx\t(%s)\n", in xe_ggtt_print_holes()
837 hole_start, hole_end - 1, buf); in xe_ggtt_print_holes()
840 mutex_unlock(&ggtt->lock); in xe_ggtt_print_holes()