1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <linux/fault-inject.h> 7 8 #include <drm/drm_managed.h> 9 10 #include "xe_device.h" 11 #include "xe_ggtt.h" 12 #include "xe_gt.h" 13 #include "xe_memirq.h" 14 #include "xe_migrate.h" 15 #include "xe_pcode.h" 16 #include "xe_sa.h" 17 #include "xe_svm.h" 18 #include "xe_tile.h" 19 #include "xe_tile_sysfs.h" 20 #include "xe_ttm_vram_mgr.h" 21 #include "xe_wa.h" 22 23 /** 24 * DOC: Multi-tile Design 25 * 26 * Different vendors use the term "tile" a bit differently, but in the Intel 27 * world, a 'tile' is pretty close to what most people would think of as being 28 * a complete GPU. When multiple GPUs are placed behind a single PCI device, 29 * that's what is referred to as a "multi-tile device." In such cases, pretty 30 * much all hardware is replicated per-tile, although certain responsibilities 31 * like PCI communication, reporting of interrupts to the OS, etc. are handled 32 * solely by the "root tile." A multi-tile platform takes care of tying the 33 * tiles together in a way such that interrupt notifications from remote tiles 34 * are forwarded to the root tile, the per-tile vram is combined into a single 35 * address space, etc. 36 * 37 * In contrast, a "GT" (which officially stands for "Graphics Technology") is 38 * the subset of a GPU/tile that is responsible for implementing graphics 39 * and/or media operations. The GT is where a lot of the driver implementation 40 * happens since it's where the hardware engines, the execution units, and the 41 * GuC all reside. 42 * 43 * Historically most Intel devices were single-tile devices that contained a 44 * single GT. PVC is an example of an Intel platform built on a multi-tile 45 * design (i.e., multiple GPUs behind a single PCI device); each PVC tile only 46 * has a single GT. In contrast, platforms like MTL that have separate chips 47 * for render and media IP are still only a single logical GPU, but the 48 * graphics and media IP blocks are each exposed as a separate GT within that 49 * single GPU. This is important from a software perspective because multi-GT 50 * platforms like MTL only replicate a subset of the GPU hardware and behave 51 * differently than multi-tile platforms like PVC where nearly everything is 52 * replicated. 53 * 54 * Per-tile functionality (shared by all GTs within the tile): 55 * - Complete 4MB MMIO space (containing SGunit/SoC registers, GT 56 * registers, display registers, etc.) 57 * - Global GTT 58 * - VRAM (if discrete) 59 * - Interrupt flows 60 * - Migration context 61 * - kernel batchbuffer pool 62 * - Primary GT 63 * - Media GT (if media version >= 13) 64 * 65 * Per-GT functionality: 66 * - GuC 67 * - Hardware engines 68 * - Programmable hardware units (subslices, EUs) 69 * - GSI subset of registers (multiple copies of these registers reside 70 * within the complete MMIO space provided by the tile, but at different 71 * offsets --- 0 for render, 0x380000 for media) 72 * - Multicast register steering 73 * - TLBs to cache page table translations 74 * - Reset capability 75 * - Low-level power management (e.g., C6) 76 * - Clock frequency 77 * - MOCS and PAT programming 78 */ 79 80 /** 81 * xe_tile_alloc - Perform per-tile memory allocation 82 * @tile: Tile to perform allocations for 83 * 84 * Allocates various per-tile data structures using DRM-managed allocations. 85 * Does not touch the hardware. 86 * 87 * Returns -ENOMEM if allocations fail, otherwise 0. 88 */ 89 static int xe_tile_alloc(struct xe_tile *tile) 90 { 91 tile->mem.ggtt = xe_ggtt_alloc(tile); 92 if (!tile->mem.ggtt) 93 return -ENOMEM; 94 95 return 0; 96 } 97 98 /** 99 * xe_tile_init_early - Initialize the tile and primary GT 100 * @tile: Tile to initialize 101 * @xe: Parent Xe device 102 * @id: Tile ID 103 * 104 * Initializes per-tile resources that don't require any interactions with the 105 * hardware or any knowledge about the Graphics/Media IP version. 106 * 107 * Returns: 0 on success, negative error code on error. 108 */ 109 int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id) 110 { 111 int err; 112 113 tile->xe = xe; 114 tile->id = id; 115 116 err = xe_tile_alloc(tile); 117 if (err) 118 return err; 119 120 tile->primary_gt = xe_gt_alloc(tile); 121 if (IS_ERR(tile->primary_gt)) 122 return PTR_ERR(tile->primary_gt); 123 124 xe_pcode_init(tile); 125 126 return 0; 127 } 128 ALLOW_ERROR_INJECTION(xe_tile_init_early, ERRNO); /* See xe_pci_probe() */ 129 130 static int tile_ttm_mgr_init(struct xe_tile *tile) 131 { 132 struct xe_device *xe = tile_to_xe(tile); 133 int err; 134 135 if (tile->mem.vram.usable_size) { 136 err = xe_ttm_vram_mgr_init(tile, &tile->mem.vram.ttm); 137 if (err) 138 return err; 139 xe->info.mem_region_mask |= BIT(tile->id) << 1; 140 } 141 142 return 0; 143 } 144 145 /** 146 * xe_tile_init_noalloc - Init tile up to the point where allocations can happen. 147 * @tile: The tile to initialize. 148 * 149 * This function prepares the tile to allow memory allocations to VRAM, but is 150 * not allowed to allocate memory itself. This state is useful for display 151 * readout, because the inherited display framebuffer will otherwise be 152 * overwritten as it is usually put at the start of VRAM. 153 * 154 * Note that since this is tile initialization, it should not perform any 155 * GT-specific operations, and thus does not need to hold GT forcewake. 156 * 157 * Returns: 0 on success, negative error code on error. 158 */ 159 int xe_tile_init_noalloc(struct xe_tile *tile) 160 { 161 struct xe_device *xe = tile_to_xe(tile); 162 int err; 163 164 err = tile_ttm_mgr_init(tile); 165 if (err) 166 return err; 167 168 xe_wa_apply_tile_workarounds(tile); 169 170 if (xe->info.has_usm && IS_DGFX(xe)) 171 xe_devm_add(tile, &tile->mem.vram); 172 173 return xe_tile_sysfs_init(tile); 174 } 175 176 int xe_tile_init(struct xe_tile *tile) 177 { 178 int err; 179 180 err = xe_memirq_init(&tile->memirq); 181 if (err) 182 return err; 183 184 tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); 185 if (IS_ERR(tile->mem.kernel_bb_pool)) 186 return PTR_ERR(tile->mem.kernel_bb_pool); 187 188 return 0; 189 } 190 void xe_tile_migrate_wait(struct xe_tile *tile) 191 { 192 xe_migrate_wait(tile->migrate); 193 } 194