Linux Audio

Check our new training course

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