xref: /dflybsd-src/sys/dev/drm/amd/amdgpu/amdgpu_queue_mgr.c (revision 789731325bde747251c28a37e0a00ed4efb88c46)
1b843c749SSergey Zigachev /*
2b843c749SSergey Zigachev  * Copyright 2017 Valve Corporation
3b843c749SSergey Zigachev  *
4b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
5b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
6b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
7b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
9b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
10b843c749SSergey Zigachev  *
11b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
12b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
13b843c749SSergey Zigachev  *
14b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
21b843c749SSergey Zigachev  *
22b843c749SSergey Zigachev  * Authors: Andres Rodriguez
23b843c749SSergey Zigachev  */
24b843c749SSergey Zigachev 
25b843c749SSergey Zigachev #include "amdgpu.h"
26b843c749SSergey Zigachev #include "amdgpu_ring.h"
27b843c749SSergey Zigachev 
amdgpu_queue_mapper_init(struct amdgpu_queue_mapper * mapper,int hw_ip)28b843c749SSergey Zigachev static int amdgpu_queue_mapper_init(struct amdgpu_queue_mapper *mapper,
29b843c749SSergey Zigachev 				    int hw_ip)
30b843c749SSergey Zigachev {
31b843c749SSergey Zigachev 	if (!mapper)
32b843c749SSergey Zigachev 		return -EINVAL;
33b843c749SSergey Zigachev 
34b843c749SSergey Zigachev 	if (hw_ip > AMDGPU_MAX_IP_NUM)
35b843c749SSergey Zigachev 		return -EINVAL;
36b843c749SSergey Zigachev 
37b843c749SSergey Zigachev 	mapper->hw_ip = hw_ip;
38*78973132SSergey Zigachev 	lockinit(&mapper->lock, "aqml", 0, LK_CANRECURSE);
39b843c749SSergey Zigachev 
40b843c749SSergey Zigachev 	memset(mapper->queue_map, 0, sizeof(mapper->queue_map));
41b843c749SSergey Zigachev 
42b843c749SSergey Zigachev 	return 0;
43b843c749SSergey Zigachev }
44b843c749SSergey Zigachev 
amdgpu_get_cached_map(struct amdgpu_queue_mapper * mapper,int ring)45b843c749SSergey Zigachev static struct amdgpu_ring *amdgpu_get_cached_map(struct amdgpu_queue_mapper *mapper,
46b843c749SSergey Zigachev 					  int ring)
47b843c749SSergey Zigachev {
48b843c749SSergey Zigachev 	return mapper->queue_map[ring];
49b843c749SSergey Zigachev }
50b843c749SSergey Zigachev 
amdgpu_update_cached_map(struct amdgpu_queue_mapper * mapper,int ring,struct amdgpu_ring * pring)51b843c749SSergey Zigachev static int amdgpu_update_cached_map(struct amdgpu_queue_mapper *mapper,
52b843c749SSergey Zigachev 			     int ring, struct amdgpu_ring *pring)
53b843c749SSergey Zigachev {
54b843c749SSergey Zigachev 	if (WARN_ON(mapper->queue_map[ring])) {
55b843c749SSergey Zigachev 		DRM_ERROR("Un-expected ring re-map\n");
56b843c749SSergey Zigachev 		return -EINVAL;
57b843c749SSergey Zigachev 	}
58b843c749SSergey Zigachev 
59b843c749SSergey Zigachev 	mapper->queue_map[ring] = pring;
60b843c749SSergey Zigachev 
61b843c749SSergey Zigachev 	return 0;
62b843c749SSergey Zigachev }
63b843c749SSergey Zigachev 
amdgpu_identity_map(struct amdgpu_device * adev,struct amdgpu_queue_mapper * mapper,u32 ring,struct amdgpu_ring ** out_ring)64b843c749SSergey Zigachev static int amdgpu_identity_map(struct amdgpu_device *adev,
65b843c749SSergey Zigachev 			       struct amdgpu_queue_mapper *mapper,
66b843c749SSergey Zigachev 			       u32 ring,
67b843c749SSergey Zigachev 			       struct amdgpu_ring **out_ring)
68b843c749SSergey Zigachev {
69b843c749SSergey Zigachev 	switch (mapper->hw_ip) {
70b843c749SSergey Zigachev 	case AMDGPU_HW_IP_GFX:
71b843c749SSergey Zigachev 		*out_ring = &adev->gfx.gfx_ring[ring];
72b843c749SSergey Zigachev 		break;
73b843c749SSergey Zigachev 	case AMDGPU_HW_IP_COMPUTE:
74b843c749SSergey Zigachev 		*out_ring = &adev->gfx.compute_ring[ring];
75b843c749SSergey Zigachev 		break;
76b843c749SSergey Zigachev 	case AMDGPU_HW_IP_DMA:
77b843c749SSergey Zigachev 		*out_ring = &adev->sdma.instance[ring].ring;
78b843c749SSergey Zigachev 		break;
79b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD:
80b843c749SSergey Zigachev 		*out_ring = &adev->uvd.inst[0].ring;
81b843c749SSergey Zigachev 		break;
82b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCE:
83b843c749SSergey Zigachev 		*out_ring = &adev->vce.ring[ring];
84b843c749SSergey Zigachev 		break;
85b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD_ENC:
86b843c749SSergey Zigachev 		*out_ring = &adev->uvd.inst[0].ring_enc[ring];
87b843c749SSergey Zigachev 		break;
88b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_DEC:
89b843c749SSergey Zigachev 		*out_ring = &adev->vcn.ring_dec;
90b843c749SSergey Zigachev 		break;
91b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_ENC:
92b843c749SSergey Zigachev 		*out_ring = &adev->vcn.ring_enc[ring];
93b843c749SSergey Zigachev 		break;
94b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_JPEG:
95b843c749SSergey Zigachev 		*out_ring = &adev->vcn.ring_jpeg;
96b843c749SSergey Zigachev 		break;
97b843c749SSergey Zigachev 	default:
98b843c749SSergey Zigachev 		*out_ring = NULL;
99b843c749SSergey Zigachev 		DRM_ERROR("unknown HW IP type: %d\n", mapper->hw_ip);
100b843c749SSergey Zigachev 		return -EINVAL;
101b843c749SSergey Zigachev 	}
102b843c749SSergey Zigachev 
103b843c749SSergey Zigachev 	return amdgpu_update_cached_map(mapper, ring, *out_ring);
104b843c749SSergey Zigachev }
105b843c749SSergey Zigachev 
amdgpu_hw_ip_to_ring_type(int hw_ip)106b843c749SSergey Zigachev static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip)
107b843c749SSergey Zigachev {
108b843c749SSergey Zigachev 	switch (hw_ip) {
109b843c749SSergey Zigachev 	case AMDGPU_HW_IP_GFX:
110b843c749SSergey Zigachev 		return AMDGPU_RING_TYPE_GFX;
111b843c749SSergey Zigachev 	case AMDGPU_HW_IP_COMPUTE:
112b843c749SSergey Zigachev 		return AMDGPU_RING_TYPE_COMPUTE;
113b843c749SSergey Zigachev 	case AMDGPU_HW_IP_DMA:
114b843c749SSergey Zigachev 		return AMDGPU_RING_TYPE_SDMA;
115b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD:
116b843c749SSergey Zigachev 		return AMDGPU_RING_TYPE_UVD;
117b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCE:
118b843c749SSergey Zigachev 		return AMDGPU_RING_TYPE_VCE;
119b843c749SSergey Zigachev 	default:
120b843c749SSergey Zigachev 		DRM_ERROR("Invalid HW IP specified %d\n", hw_ip);
121b843c749SSergey Zigachev 		return -1;
122b843c749SSergey Zigachev 	}
123b843c749SSergey Zigachev }
124b843c749SSergey Zigachev 
amdgpu_lru_map(struct amdgpu_device * adev,struct amdgpu_queue_mapper * mapper,u32 user_ring,bool lru_pipe_order,struct amdgpu_ring ** out_ring)125b843c749SSergey Zigachev static int amdgpu_lru_map(struct amdgpu_device *adev,
126b843c749SSergey Zigachev 			  struct amdgpu_queue_mapper *mapper,
127b843c749SSergey Zigachev 			  u32 user_ring, bool lru_pipe_order,
128b843c749SSergey Zigachev 			  struct amdgpu_ring **out_ring)
129b843c749SSergey Zigachev {
130b843c749SSergey Zigachev 	int r, i, j;
131b843c749SSergey Zigachev 	int ring_type = amdgpu_hw_ip_to_ring_type(mapper->hw_ip);
132b843c749SSergey Zigachev 	int ring_blacklist[AMDGPU_MAX_RINGS];
133b843c749SSergey Zigachev 	struct amdgpu_ring *ring;
134b843c749SSergey Zigachev 
135b843c749SSergey Zigachev 	/* 0 is a valid ring index, so initialize to -1 */
136b843c749SSergey Zigachev 	memset(ring_blacklist, 0xff, sizeof(ring_blacklist));
137b843c749SSergey Zigachev 
138b843c749SSergey Zigachev 	for (i = 0, j = 0; i < AMDGPU_MAX_RINGS; i++) {
139b843c749SSergey Zigachev 		ring = mapper->queue_map[i];
140b843c749SSergey Zigachev 		if (ring)
141b843c749SSergey Zigachev 			ring_blacklist[j++] = ring->idx;
142b843c749SSergey Zigachev 	}
143b843c749SSergey Zigachev 
144b843c749SSergey Zigachev 	r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist,
145b843c749SSergey Zigachev 				j, lru_pipe_order, out_ring);
146b843c749SSergey Zigachev 	if (r)
147b843c749SSergey Zigachev 		return r;
148b843c749SSergey Zigachev 
149b843c749SSergey Zigachev 	return amdgpu_update_cached_map(mapper, user_ring, *out_ring);
150b843c749SSergey Zigachev }
151b843c749SSergey Zigachev 
152b843c749SSergey Zigachev /**
153b843c749SSergey Zigachev  * amdgpu_queue_mgr_init - init an amdgpu_queue_mgr struct
154b843c749SSergey Zigachev  *
155b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
156b843c749SSergey Zigachev  * @mgr: amdgpu_queue_mgr structure holding queue information
157b843c749SSergey Zigachev  *
158b843c749SSergey Zigachev  * Initialize the the selected @mgr (all asics).
159b843c749SSergey Zigachev  *
160b843c749SSergey Zigachev  * Returns 0 on success, error on failure.
161b843c749SSergey Zigachev  */
amdgpu_queue_mgr_init(struct amdgpu_device * adev,struct amdgpu_queue_mgr * mgr)162b843c749SSergey Zigachev int amdgpu_queue_mgr_init(struct amdgpu_device *adev,
163b843c749SSergey Zigachev 			  struct amdgpu_queue_mgr *mgr)
164b843c749SSergey Zigachev {
165b843c749SSergey Zigachev 	int i, r;
166b843c749SSergey Zigachev 
167b843c749SSergey Zigachev 	if (!adev || !mgr)
168b843c749SSergey Zigachev 		return -EINVAL;
169b843c749SSergey Zigachev 
170b843c749SSergey Zigachev 	memset(mgr, 0, sizeof(*mgr));
171b843c749SSergey Zigachev 
172b843c749SSergey Zigachev 	for (i = 0; i < AMDGPU_MAX_IP_NUM; ++i) {
173b843c749SSergey Zigachev 		r = amdgpu_queue_mapper_init(&mgr->mapper[i], i);
174b843c749SSergey Zigachev 		if (r)
175b843c749SSergey Zigachev 			return r;
176b843c749SSergey Zigachev 	}
177b843c749SSergey Zigachev 
178b843c749SSergey Zigachev 	return 0;
179b843c749SSergey Zigachev }
180b843c749SSergey Zigachev 
181b843c749SSergey Zigachev /**
182b843c749SSergey Zigachev  * amdgpu_queue_mgr_fini - de-initialize an amdgpu_queue_mgr struct
183b843c749SSergey Zigachev  *
184b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
185b843c749SSergey Zigachev  * @mgr: amdgpu_queue_mgr structure holding queue information
186b843c749SSergey Zigachev  *
187b843c749SSergey Zigachev  * De-initialize the the selected @mgr (all asics).
188b843c749SSergey Zigachev  *
189b843c749SSergey Zigachev  * Returns 0 on success, error on failure.
190b843c749SSergey Zigachev  */
amdgpu_queue_mgr_fini(struct amdgpu_device * adev,struct amdgpu_queue_mgr * mgr)191b843c749SSergey Zigachev int amdgpu_queue_mgr_fini(struct amdgpu_device *adev,
192b843c749SSergey Zigachev 			  struct amdgpu_queue_mgr *mgr)
193b843c749SSergey Zigachev {
194b843c749SSergey Zigachev 	return 0;
195b843c749SSergey Zigachev }
196b843c749SSergey Zigachev 
197b843c749SSergey Zigachev /**
198b843c749SSergey Zigachev  * amdgpu_queue_mgr_map - Map a userspace ring id to an amdgpu_ring
199b843c749SSergey Zigachev  *
200b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
201b843c749SSergey Zigachev  * @mgr: amdgpu_queue_mgr structure holding queue information
202b843c749SSergey Zigachev  * @hw_ip: HW IP enum
203b843c749SSergey Zigachev  * @instance: HW instance
204b843c749SSergey Zigachev  * @ring: user ring id
205b843c749SSergey Zigachev  * @our_ring: pointer to mapped amdgpu_ring
206b843c749SSergey Zigachev  *
207b843c749SSergey Zigachev  * Map a userspace ring id to an appropriate kernel ring. Different
208b843c749SSergey Zigachev  * policies are configurable at a HW IP level.
209b843c749SSergey Zigachev  *
210b843c749SSergey Zigachev  * Returns 0 on success, error on failure.
211b843c749SSergey Zigachev  */
amdgpu_queue_mgr_map(struct amdgpu_device * adev,struct amdgpu_queue_mgr * mgr,u32 hw_ip,u32 instance,u32 ring,struct amdgpu_ring ** out_ring)212b843c749SSergey Zigachev int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
213b843c749SSergey Zigachev 			 struct amdgpu_queue_mgr *mgr,
214b843c749SSergey Zigachev 			 u32 hw_ip, u32 instance, u32 ring,
215b843c749SSergey Zigachev 			 struct amdgpu_ring **out_ring)
216b843c749SSergey Zigachev {
217b843c749SSergey Zigachev 	int i, r, ip_num_rings = 0;
218b843c749SSergey Zigachev 	struct amdgpu_queue_mapper *mapper = &mgr->mapper[hw_ip];
219b843c749SSergey Zigachev 
220b843c749SSergey Zigachev 	if (!adev || !mgr || !out_ring)
221b843c749SSergey Zigachev 		return -EINVAL;
222b843c749SSergey Zigachev 
223b843c749SSergey Zigachev 	if (hw_ip >= AMDGPU_MAX_IP_NUM)
224b843c749SSergey Zigachev 		return -EINVAL;
225b843c749SSergey Zigachev 
226b843c749SSergey Zigachev 	if (ring >= AMDGPU_MAX_RINGS)
227b843c749SSergey Zigachev 		return -EINVAL;
228b843c749SSergey Zigachev 
229b843c749SSergey Zigachev 	/* Right now all IPs have only one instance - multiple rings. */
230b843c749SSergey Zigachev 	if (instance != 0) {
231b843c749SSergey Zigachev 		DRM_DEBUG("invalid ip instance: %d\n", instance);
232b843c749SSergey Zigachev 		return -EINVAL;
233b843c749SSergey Zigachev 	}
234b843c749SSergey Zigachev 
235b843c749SSergey Zigachev 	switch (hw_ip) {
236b843c749SSergey Zigachev 	case AMDGPU_HW_IP_GFX:
237b843c749SSergey Zigachev 		ip_num_rings = adev->gfx.num_gfx_rings;
238b843c749SSergey Zigachev 		break;
239b843c749SSergey Zigachev 	case AMDGPU_HW_IP_COMPUTE:
240b843c749SSergey Zigachev 		ip_num_rings = adev->gfx.num_compute_rings;
241b843c749SSergey Zigachev 		break;
242b843c749SSergey Zigachev 	case AMDGPU_HW_IP_DMA:
243b843c749SSergey Zigachev 		ip_num_rings = adev->sdma.num_instances;
244b843c749SSergey Zigachev 		break;
245b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD:
246b843c749SSergey Zigachev 		for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
247b843c749SSergey Zigachev 			if (!(adev->uvd.harvest_config & (1 << i)))
248b843c749SSergey Zigachev 				ip_num_rings++;
249b843c749SSergey Zigachev 		}
250b843c749SSergey Zigachev 		break;
251b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCE:
252b843c749SSergey Zigachev 		ip_num_rings = adev->vce.num_rings;
253b843c749SSergey Zigachev 		break;
254b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD_ENC:
255b843c749SSergey Zigachev 		for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
256b843c749SSergey Zigachev 			if (!(adev->uvd.harvest_config & (1 << i)))
257b843c749SSergey Zigachev 				ip_num_rings++;
258b843c749SSergey Zigachev 		}
259b843c749SSergey Zigachev 		ip_num_rings =
260b843c749SSergey Zigachev 			adev->uvd.num_enc_rings * ip_num_rings;
261b843c749SSergey Zigachev 		break;
262b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_DEC:
263b843c749SSergey Zigachev 		ip_num_rings = 1;
264b843c749SSergey Zigachev 		break;
265b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_ENC:
266b843c749SSergey Zigachev 		ip_num_rings = adev->vcn.num_enc_rings;
267b843c749SSergey Zigachev 		break;
268b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_JPEG:
269b843c749SSergey Zigachev 		ip_num_rings = 1;
270b843c749SSergey Zigachev 		break;
271b843c749SSergey Zigachev 	default:
272b843c749SSergey Zigachev 		DRM_DEBUG("unknown ip type: %d\n", hw_ip);
273b843c749SSergey Zigachev 		return -EINVAL;
274b843c749SSergey Zigachev 	}
275b843c749SSergey Zigachev 
276b843c749SSergey Zigachev 	if (ring >= ip_num_rings) {
277b843c749SSergey Zigachev 		DRM_DEBUG("Ring index:%d exceeds maximum:%d for ip:%d\n",
278b843c749SSergey Zigachev 			  ring, ip_num_rings, hw_ip);
279b843c749SSergey Zigachev 		return -EINVAL;
280b843c749SSergey Zigachev 	}
281b843c749SSergey Zigachev 
282b843c749SSergey Zigachev 	mutex_lock(&mapper->lock);
283b843c749SSergey Zigachev 
284b843c749SSergey Zigachev 	*out_ring = amdgpu_get_cached_map(mapper, ring);
285b843c749SSergey Zigachev 	if (*out_ring) {
286b843c749SSergey Zigachev 		/* cache hit */
287b843c749SSergey Zigachev 		r = 0;
288b843c749SSergey Zigachev 		goto out_unlock;
289b843c749SSergey Zigachev 	}
290b843c749SSergey Zigachev 
291b843c749SSergey Zigachev 	switch (mapper->hw_ip) {
292b843c749SSergey Zigachev 	case AMDGPU_HW_IP_GFX:
293b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD:
294b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCE:
295b843c749SSergey Zigachev 	case AMDGPU_HW_IP_UVD_ENC:
296b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_DEC:
297b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_ENC:
298b843c749SSergey Zigachev 	case AMDGPU_HW_IP_VCN_JPEG:
299b843c749SSergey Zigachev 		r = amdgpu_identity_map(adev, mapper, ring, out_ring);
300b843c749SSergey Zigachev 		break;
301b843c749SSergey Zigachev 	case AMDGPU_HW_IP_DMA:
302b843c749SSergey Zigachev 		r = amdgpu_lru_map(adev, mapper, ring, false, out_ring);
303b843c749SSergey Zigachev 		break;
304b843c749SSergey Zigachev 	case AMDGPU_HW_IP_COMPUTE:
305b843c749SSergey Zigachev 		r = amdgpu_lru_map(adev, mapper, ring, true, out_ring);
306b843c749SSergey Zigachev 		break;
307b843c749SSergey Zigachev 	default:
308b843c749SSergey Zigachev 		*out_ring = NULL;
309b843c749SSergey Zigachev 		r = -EINVAL;
310b843c749SSergey Zigachev 		DRM_DEBUG("unknown HW IP type: %d\n", mapper->hw_ip);
311b843c749SSergey Zigachev 	}
312b843c749SSergey Zigachev 
313b843c749SSergey Zigachev out_unlock:
314b843c749SSergey Zigachev 	mutex_unlock(&mapper->lock);
315b843c749SSergey Zigachev 	return r;
316b843c749SSergey Zigachev }
317