• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Red Hat.
3  * Copyright © 2016 Bas Nieuwenhuizen
4  * based on amdgpu winsys.
5  * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
6  * Copyright © 2015 Advanced Micro Devices, Inc.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25  * IN THE SOFTWARE.
26  */
27 #include "radv_amdgpu_winsys.h"
28 #include "radv_amdgpu_winsys_public.h"
29 #include "radv_amdgpu_surface.h"
30 #include "amdgpu_id.h"
31 #include "xf86drm.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <amdgpu_drm.h>
36 #include <assert.h>
37 #include "radv_amdgpu_cs.h"
38 #include "radv_amdgpu_bo.h"
39 #include "radv_amdgpu_surface.h"
40 
41 #define CIK_TILE_MODE_COLOR_2D			14
42 
43 #define CIK__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
44 #define     CIK__PIPE_CONFIG__ADDR_SURF_P2               0
45 #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
46 #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
47 #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
48 #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
49 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
50 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
51 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
52 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
53 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
54 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
55 #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
56 #define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16   16
57 #define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16  17
58 
radv_cik_get_num_tile_pipes(struct amdgpu_gpu_info * info)59 static unsigned radv_cik_get_num_tile_pipes(struct amdgpu_gpu_info *info)
60 {
61 	unsigned mode2d = info->gb_tile_mode[CIK_TILE_MODE_COLOR_2D];
62 
63 	switch (CIK__GB_TILE_MODE__PIPE_CONFIG(mode2d)) {
64 	case CIK__PIPE_CONFIG__ADDR_SURF_P2:
65 		return 2;
66 	case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
67 	case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
68 	case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
69 	case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
70 		return 4;
71 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
72 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
73 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
74 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
75 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
76 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
77 	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
78 		return 8;
79 	case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
80 	case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
81 		return 16;
82 	default:
83 		fprintf(stderr, "Invalid CIK pipe configuration, assuming P2\n");
84 		assert(!"this should never occur");
85 		return 2;
86 	}
87 }
88 
89 static const char *
get_chip_name(enum radeon_family family)90 get_chip_name(enum radeon_family family)
91 {
92 	switch (family) {
93 	case CHIP_TAHITI: return "AMD RADV TAHITI";
94 	case CHIP_PITCAIRN: return "AMD RADV PITCAIRN";
95 	case CHIP_VERDE: return "AMD RADV CAPE VERDE";
96 	case CHIP_OLAND: return "AMD RADV OLAND";
97 	case CHIP_HAINAN: return "AMD RADV HAINAN";
98 	case CHIP_BONAIRE: return "AMD RADV BONAIRE";
99 	case CHIP_KAVERI: return "AMD RADV KAVERI";
100 	case CHIP_KABINI: return "AMD RADV KABINI";
101 	case CHIP_HAWAII: return "AMD RADV HAWAII";
102 	case CHIP_MULLINS: return "AMD RADV MULLINS";
103 	case CHIP_TONGA: return "AMD RADV TONGA";
104 	case CHIP_ICELAND: return "AMD RADV ICELAND";
105 	case CHIP_CARRIZO: return "AMD RADV CARRIZO";
106 	case CHIP_FIJI: return "AMD RADV FIJI";
107 	case CHIP_POLARIS10: return "AMD RADV POLARIS10";
108 	case CHIP_POLARIS11: return "AMD RADV POLARIS11";
109 	case CHIP_STONEY: return "AMD RADV STONEY";
110 	default: return "AMD RADV unknown";
111 	}
112 }
113 
114 
115 static bool
do_winsys_init(struct radv_amdgpu_winsys * ws,int fd)116 do_winsys_init(struct radv_amdgpu_winsys *ws, int fd)
117 {
118 	struct amdgpu_buffer_size_alignments alignment_info = {};
119 	struct amdgpu_heap_info vram, visible_vram, gtt;
120 	struct drm_amdgpu_info_hw_ip dma = {};
121 	struct drm_amdgpu_info_hw_ip compute = {};
122 	drmDevicePtr devinfo;
123 	int r;
124 	int i, j;
125 	/* Get PCI info. */
126 	r = drmGetDevice(fd, &devinfo);
127 	if (r) {
128 		fprintf(stderr, "amdgpu: drmGetDevice failed.\n");
129 		goto fail;
130 	}
131 	ws->info.pci_domain = devinfo->businfo.pci->domain;
132 	ws->info.pci_bus = devinfo->businfo.pci->bus;
133 	ws->info.pci_dev = devinfo->businfo.pci->dev;
134 	ws->info.pci_func = devinfo->businfo.pci->func;
135 	drmFreeDevice(&devinfo);
136 
137 	/* Query hardware and driver information. */
138 	r = amdgpu_query_gpu_info(ws->dev, &ws->amdinfo);
139 	if (r) {
140 		fprintf(stderr, "amdgpu: amdgpu_query_gpu_info failed.\n");
141 		goto fail;
142 	}
143 
144 	r = amdgpu_query_buffer_size_alignment(ws->dev, &alignment_info);
145 	if (r) {
146 		fprintf(stderr, "amdgpu: amdgpu_query_buffer_size_alignment failed.\n");
147 		goto fail;
148 	}
149 
150 	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_VRAM, 0, &vram);
151 	if (r) {
152 		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(vram) failed.\n");
153 		goto fail;
154 	}
155 
156 	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_VRAM,
157 	                           AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &visible_vram);
158 	if (r) {
159 		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(visible_vram) failed.\n");
160 		goto fail;
161 	}
162 
163 	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_GTT, 0, &gtt);
164 	if (r) {
165 		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(gtt) failed.\n");
166 		goto fail;
167 	}
168 
169 	r = amdgpu_query_hw_ip_info(ws->dev, AMDGPU_HW_IP_DMA, 0, &dma);
170 	if (r) {
171 		fprintf(stderr, "amdgpu: amdgpu_query_hw_ip_info(dma) failed.\n");
172 		goto fail;
173 	}
174 
175 	r = amdgpu_query_hw_ip_info(ws->dev, AMDGPU_HW_IP_COMPUTE, 0, &compute);
176 	if (r) {
177 		fprintf(stderr, "amdgpu: amdgpu_query_hw_ip_info(compute) failed.\n");
178 		goto fail;
179 	}
180 	ws->info.pci_id = ws->amdinfo.asic_id; /* TODO: is this correct? */
181 	ws->info.vce_harvest_config = ws->amdinfo.vce_harvest_config;
182 
183 	switch (ws->info.pci_id) {
184 #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; break;
185 #include "pci_ids/radeonsi_pci_ids.h"
186 #undef CHIPSET
187 	default:
188 		fprintf(stderr, "amdgpu: Invalid PCI ID.\n");
189 		goto fail;
190 	}
191 
192 	if (ws->info.family >= CHIP_TONGA)
193 		ws->info.chip_class = VI;
194 	else if (ws->info.family >= CHIP_BONAIRE)
195 		ws->info.chip_class = CIK;
196 	else if (ws->info.family >= CHIP_TAHITI)
197 		ws->info.chip_class = SI;
198 	else {
199 		fprintf(stderr, "amdgpu: Unknown family.\n");
200 		goto fail;
201 	}
202 
203 	/* family and rev_id are for addrlib */
204 	switch (ws->info.family) {
205 	case CHIP_TAHITI:
206 		ws->family = FAMILY_SI;
207 		ws->rev_id = SI_TAHITI_P_A0;
208 		break;
209 	case CHIP_PITCAIRN:
210 		ws->family = FAMILY_SI;
211 		ws->rev_id = SI_PITCAIRN_PM_A0;
212 	  break;
213 	case CHIP_VERDE:
214 		ws->family = FAMILY_SI;
215 		ws->rev_id = SI_CAPEVERDE_M_A0;
216 		break;
217 	case CHIP_OLAND:
218 		ws->family = FAMILY_SI;
219 		ws->rev_id = SI_OLAND_M_A0;
220 		break;
221 	case CHIP_HAINAN:
222 		ws->family = FAMILY_SI;
223 		ws->rev_id = SI_HAINAN_V_A0;
224 		break;
225 	case CHIP_BONAIRE:
226 		ws->family = FAMILY_CI;
227 		ws->rev_id = CI_BONAIRE_M_A0;
228 		break;
229 	case CHIP_KAVERI:
230 		ws->family = FAMILY_KV;
231 		ws->rev_id = KV_SPECTRE_A0;
232 		break;
233 	case CHIP_KABINI:
234 		ws->family = FAMILY_KV;
235 		ws->rev_id = KB_KALINDI_A0;
236 		break;
237 	case CHIP_HAWAII:
238 		ws->family = FAMILY_CI;
239 		ws->rev_id = CI_HAWAII_P_A0;
240 		break;
241 	case CHIP_MULLINS:
242 		ws->family = FAMILY_KV;
243 		ws->rev_id = ML_GODAVARI_A0;
244 		break;
245 	case CHIP_TONGA:
246 		ws->family = FAMILY_VI;
247 		ws->rev_id = VI_TONGA_P_A0;
248 		break;
249 	case CHIP_ICELAND:
250 		ws->family = FAMILY_VI;
251 		ws->rev_id = VI_ICELAND_M_A0;
252 		break;
253 	case CHIP_CARRIZO:
254 		ws->family = FAMILY_CZ;
255 		ws->rev_id = CARRIZO_A0;
256 		break;
257 	case CHIP_STONEY:
258 		ws->family = FAMILY_CZ;
259 		ws->rev_id = STONEY_A0;
260 		break;
261 	case CHIP_FIJI:
262 		ws->family = FAMILY_VI;
263 		ws->rev_id = VI_FIJI_P_A0;
264 		break;
265 	case CHIP_POLARIS10:
266 		ws->family = FAMILY_VI;
267 		ws->rev_id = VI_POLARIS10_P_A0;
268 		break;
269 	case CHIP_POLARIS11:
270 		ws->family = FAMILY_VI;
271 		ws->rev_id = VI_POLARIS11_M_A0;
272 		break;
273 	default:
274 		fprintf(stderr, "amdgpu: Unknown family.\n");
275 		goto fail;
276 	}
277 
278 	ws->addrlib = radv_amdgpu_addr_create(&ws->amdinfo, ws->family, ws->rev_id, ws->info.chip_class);
279 	if (!ws->addrlib) {
280 		fprintf(stderr, "amdgpu: Cannot create addrlib.\n");
281 		goto fail;
282 	}
283 
284 	assert(util_is_power_of_two(dma.available_rings + 1));
285 	assert(util_is_power_of_two(compute.available_rings + 1));
286 
287 	/* Set hardware information. */
288 	ws->info.name = get_chip_name(ws->info.family);
289 	ws->info.gart_size = gtt.heap_size;
290 	ws->info.vram_size = vram.heap_size;
291 	ws->info.visible_vram_size = visible_vram.heap_size;
292 	/* convert the shader clock from KHz to MHz */
293 	ws->info.max_shader_clock = ws->amdinfo.max_engine_clk / 1000;
294 	ws->info.max_se = ws->amdinfo.num_shader_engines;
295 	ws->info.max_sh_per_se = ws->amdinfo.num_shader_arrays_per_engine;
296 	ws->info.has_uvd = 0;
297 	ws->info.vce_fw_version = 0;
298 	ws->info.has_userptr = TRUE;
299 	ws->info.num_render_backends = ws->amdinfo.rb_pipes;
300 	ws->info.clock_crystal_freq = ws->amdinfo.gpu_counter_freq;
301 	ws->info.num_tile_pipes = radv_cik_get_num_tile_pipes(&ws->amdinfo);
302 	ws->info.pipe_interleave_bytes = 256 << ((ws->amdinfo.gb_addr_cfg >> 4) & 0x7);
303 	ws->info.has_virtual_memory = TRUE;
304 	ws->info.sdma_rings = MIN2(util_bitcount(dma.available_rings),
305 	                           MAX_RINGS_PER_TYPE);
306 	ws->info.compute_rings = MIN2(util_bitcount(compute.available_rings),
307 	                              MAX_RINGS_PER_TYPE);
308 
309 	/* Get the number of good compute units. */
310 	ws->info.num_good_compute_units = 0;
311 	for (i = 0; i < ws->info.max_se; i++)
312 		for (j = 0; j < ws->info.max_sh_per_se; j++)
313 			ws->info.num_good_compute_units +=
314 				util_bitcount(ws->amdinfo.cu_bitmap[i][j]);
315 
316 	memcpy(ws->info.si_tile_mode_array, ws->amdinfo.gb_tile_mode,
317 	       sizeof(ws->amdinfo.gb_tile_mode));
318 	ws->info.enabled_rb_mask = ws->amdinfo.enabled_rb_pipes_mask;
319 
320 	memcpy(ws->info.cik_macrotile_mode_array, ws->amdinfo.gb_macro_tile_mode,
321 	       sizeof(ws->amdinfo.gb_macro_tile_mode));
322 
323 	ws->info.gart_page_size = alignment_info.size_remote;
324 
325 	if (ws->info.chip_class == SI)
326 		ws->info.gfx_ib_pad_with_type2 = TRUE;
327 
328 	ws->use_ib_bos = ws->family >= FAMILY_CI;
329 	return true;
330 fail:
331 	return false;
332 }
333 
radv_amdgpu_winsys_query_info(struct radeon_winsys * rws,struct radeon_info * info)334 static void radv_amdgpu_winsys_query_info(struct radeon_winsys *rws,
335                                      struct radeon_info *info)
336 {
337 	*info = ((struct radv_amdgpu_winsys *)rws)->info;
338 }
339 
radv_amdgpu_winsys_destroy(struct radeon_winsys * rws)340 static void radv_amdgpu_winsys_destroy(struct radeon_winsys *rws)
341 {
342 	struct radv_amdgpu_winsys *ws = (struct radv_amdgpu_winsys*)rws;
343 
344 	AddrDestroy(ws->addrlib);
345 	amdgpu_device_deinitialize(ws->dev);
346 	FREE(rws);
347 }
348 
349 struct radeon_winsys *
radv_amdgpu_winsys_create(int fd)350 radv_amdgpu_winsys_create(int fd)
351 {
352 	uint32_t drm_major, drm_minor, r;
353 	amdgpu_device_handle dev;
354 	struct radv_amdgpu_winsys *ws;
355 
356 	r = amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev);
357 	if (r)
358 		return NULL;
359 
360 	ws = calloc(1, sizeof(struct radv_amdgpu_winsys));
361 	if (!ws)
362 		goto fail;
363 
364 	ws->dev = dev;
365 	ws->info.drm_major = drm_major;
366 	ws->info.drm_minor = drm_minor;
367 	if (!do_winsys_init(ws, fd))
368 		goto winsys_fail;
369 
370 	ws->debug_all_bos = getenv("RADV_DEBUG_ALL_BOS") ? true : false;
371 	LIST_INITHEAD(&ws->global_bo_list);
372 	pthread_mutex_init(&ws->global_bo_list_lock, NULL);
373 	ws->base.query_info = radv_amdgpu_winsys_query_info;
374 	ws->base.destroy = radv_amdgpu_winsys_destroy;
375 	radv_amdgpu_bo_init_functions(ws);
376 	radv_amdgpu_cs_init_functions(ws);
377 	radv_amdgpu_surface_init_functions(ws);
378 
379 	return &ws->base;
380 
381 winsys_fail:
382 	free(ws);
383 fail:
384 	amdgpu_device_deinitialize(dev);
385 	return NULL;
386 }
387