Merge branch 'for-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_queue_mgr.c
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
28 static 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
45 static struct amdgpu_ring *amdgpu_get_cached_map(struct amdgpu_queue_mapper *mapper,
46                                           int ring)
47 {
48         return mapper->queue_map[ring];
49 }
50
51 static 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
64 static 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
103 static 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
122 static 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  */
159 int 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  */
188 int 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  */
209 int 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_ERROR("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_ERROR("unknown ip type: %d\n", hw_ip);
259                 return -EINVAL;
260         }
261
262         if (ring >= ip_num_rings) {
263                 DRM_ERROR("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_ERROR("unknown HW IP type: %d\n", mapper->hw_ip);
296         }
297
298 out_unlock:
299         mutex_unlock(&mapper->lock);
300         return r;
301 }