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