1 1.8 riastrad /* $NetBSD: amdgpu_ctx.c,v 1.8 2021/12/19 12:38:41 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2015 Advanced Micro Devices, Inc. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice shall be included in 14 1.1 riastrad * all copies or substantial portions of the Software. 15 1.1 riastrad * 16 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 1.1 riastrad * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 23 1.1 riastrad * 24 1.1 riastrad * Authors: monk liu <monk.liu (at) amd.com> 25 1.1 riastrad */ 26 1.1 riastrad 27 1.1 riastrad #include <sys/cdefs.h> 28 1.8 riastrad __KERNEL_RCSID(0, "$NetBSD: amdgpu_ctx.c,v 1.8 2021/12/19 12:38:41 riastradh Exp $"); 29 1.1 riastrad 30 1.6 riastrad #include <drm/drm_auth.h> 31 1.1 riastrad #include "amdgpu.h" 32 1.6 riastrad #include "amdgpu_sched.h" 33 1.6 riastrad #include "amdgpu_ras.h" 34 1.1 riastrad 35 1.5 riastrad #include <linux/nbsd-namespace.h> 36 1.6 riastrad #define to_amdgpu_ctx_entity(e) \ 37 1.6 riastrad container_of((e), struct amdgpu_ctx_entity, entity) 38 1.5 riastrad 39 1.6 riastrad const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = { 40 1.6 riastrad [AMDGPU_HW_IP_GFX] = 1, 41 1.6 riastrad [AMDGPU_HW_IP_COMPUTE] = 4, 42 1.6 riastrad [AMDGPU_HW_IP_DMA] = 2, 43 1.6 riastrad [AMDGPU_HW_IP_UVD] = 1, 44 1.6 riastrad [AMDGPU_HW_IP_VCE] = 1, 45 1.6 riastrad [AMDGPU_HW_IP_UVD_ENC] = 1, 46 1.6 riastrad [AMDGPU_HW_IP_VCN_DEC] = 1, 47 1.6 riastrad [AMDGPU_HW_IP_VCN_ENC] = 1, 48 1.6 riastrad [AMDGPU_HW_IP_VCN_JPEG] = 1, 49 1.6 riastrad }; 50 1.6 riastrad 51 1.6 riastrad static int amdgpu_ctx_priority_permit(struct drm_file *filp, 52 1.6 riastrad enum drm_sched_priority priority) 53 1.6 riastrad { 54 1.6 riastrad if (priority < 0 || priority >= DRM_SCHED_PRIORITY_MAX) 55 1.6 riastrad return -EINVAL; 56 1.6 riastrad 57 1.6 riastrad /* NORMAL and below are accessible by everyone */ 58 1.6 riastrad if (priority <= DRM_SCHED_PRIORITY_NORMAL) 59 1.6 riastrad return 0; 60 1.6 riastrad 61 1.6 riastrad if (capable(CAP_SYS_NICE)) 62 1.6 riastrad return 0; 63 1.6 riastrad 64 1.6 riastrad if (drm_is_current_master(filp)) 65 1.6 riastrad return 0; 66 1.6 riastrad 67 1.6 riastrad return -EACCES; 68 1.6 riastrad } 69 1.6 riastrad 70 1.6 riastrad static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, const u32 hw_ip, const u32 ring) 71 1.6 riastrad { 72 1.6 riastrad struct amdgpu_device *adev = ctx->adev; 73 1.6 riastrad struct amdgpu_ctx_entity *entity; 74 1.6 riastrad struct drm_gpu_scheduler **scheds = NULL, *sched = NULL; 75 1.6 riastrad unsigned num_scheds = 0; 76 1.6 riastrad enum drm_sched_priority priority; 77 1.6 riastrad int r; 78 1.6 riastrad 79 1.6 riastrad entity = kcalloc(1, offsetof(typeof(*entity), fences[amdgpu_sched_jobs]), 80 1.6 riastrad GFP_KERNEL); 81 1.6 riastrad if (!entity) 82 1.6 riastrad return -ENOMEM; 83 1.6 riastrad 84 1.6 riastrad entity->sequence = 1; 85 1.6 riastrad priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ? 86 1.6 riastrad ctx->init_priority : ctx->override_priority; 87 1.6 riastrad switch (hw_ip) { 88 1.6 riastrad case AMDGPU_HW_IP_GFX: 89 1.6 riastrad sched = &adev->gfx.gfx_ring[0].sched; 90 1.6 riastrad scheds = &sched; 91 1.6 riastrad num_scheds = 1; 92 1.6 riastrad break; 93 1.6 riastrad case AMDGPU_HW_IP_COMPUTE: 94 1.6 riastrad scheds = adev->gfx.compute_sched; 95 1.6 riastrad num_scheds = adev->gfx.num_compute_sched; 96 1.6 riastrad break; 97 1.6 riastrad case AMDGPU_HW_IP_DMA: 98 1.6 riastrad scheds = adev->sdma.sdma_sched; 99 1.6 riastrad num_scheds = adev->sdma.num_sdma_sched; 100 1.6 riastrad break; 101 1.6 riastrad case AMDGPU_HW_IP_UVD: 102 1.6 riastrad sched = &adev->uvd.inst[0].ring.sched; 103 1.6 riastrad scheds = &sched; 104 1.6 riastrad num_scheds = 1; 105 1.6 riastrad break; 106 1.6 riastrad case AMDGPU_HW_IP_VCE: 107 1.6 riastrad sched = &adev->vce.ring[0].sched; 108 1.6 riastrad scheds = &sched; 109 1.6 riastrad num_scheds = 1; 110 1.6 riastrad break; 111 1.6 riastrad case AMDGPU_HW_IP_UVD_ENC: 112 1.6 riastrad sched = &adev->uvd.inst[0].ring_enc[0].sched; 113 1.6 riastrad scheds = &sched; 114 1.6 riastrad num_scheds = 1; 115 1.6 riastrad break; 116 1.6 riastrad case AMDGPU_HW_IP_VCN_DEC: 117 1.6 riastrad scheds = adev->vcn.vcn_dec_sched; 118 1.6 riastrad num_scheds = adev->vcn.num_vcn_dec_sched; 119 1.6 riastrad break; 120 1.6 riastrad case AMDGPU_HW_IP_VCN_ENC: 121 1.6 riastrad scheds = adev->vcn.vcn_enc_sched; 122 1.6 riastrad num_scheds = adev->vcn.num_vcn_enc_sched; 123 1.6 riastrad break; 124 1.6 riastrad case AMDGPU_HW_IP_VCN_JPEG: 125 1.6 riastrad scheds = adev->jpeg.jpeg_sched; 126 1.6 riastrad num_scheds = adev->jpeg.num_jpeg_sched; 127 1.6 riastrad break; 128 1.6 riastrad } 129 1.6 riastrad 130 1.6 riastrad r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds, 131 1.6 riastrad &ctx->guilty); 132 1.6 riastrad if (r) 133 1.6 riastrad goto error_free_entity; 134 1.6 riastrad 135 1.6 riastrad ctx->entities[hw_ip][ring] = entity; 136 1.6 riastrad return 0; 137 1.6 riastrad 138 1.6 riastrad error_free_entity: 139 1.6 riastrad kfree(entity); 140 1.6 riastrad 141 1.6 riastrad return r; 142 1.6 riastrad } 143 1.6 riastrad 144 1.6 riastrad static int amdgpu_ctx_init(struct amdgpu_device *adev, 145 1.6 riastrad enum drm_sched_priority priority, 146 1.6 riastrad struct drm_file *filp, 147 1.6 riastrad struct amdgpu_ctx *ctx) 148 1.1 riastrad { 149 1.1 riastrad int r; 150 1.1 riastrad 151 1.6 riastrad r = amdgpu_ctx_priority_permit(filp, priority); 152 1.6 riastrad if (r) 153 1.6 riastrad return r; 154 1.6 riastrad 155 1.1 riastrad memset(ctx, 0, sizeof(*ctx)); 156 1.6 riastrad 157 1.1 riastrad ctx->adev = adev; 158 1.6 riastrad 159 1.1 riastrad kref_init(&ctx->refcount); 160 1.1 riastrad spin_lock_init(&ctx->ring_lock); 161 1.6 riastrad mutex_init(&ctx->lock); 162 1.1 riastrad 163 1.6 riastrad ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); 164 1.6 riastrad ctx->reset_counter_query = ctx->reset_counter; 165 1.6 riastrad ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter); 166 1.6 riastrad ctx->init_priority = priority; 167 1.6 riastrad ctx->override_priority = DRM_SCHED_PRIORITY_UNSET; 168 1.1 riastrad 169 1.1 riastrad return 0; 170 1.6 riastrad 171 1.1 riastrad } 172 1.1 riastrad 173 1.6 riastrad static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity) 174 1.1 riastrad { 175 1.6 riastrad 176 1.6 riastrad int i; 177 1.6 riastrad 178 1.6 riastrad if (!entity) 179 1.6 riastrad return; 180 1.6 riastrad 181 1.6 riastrad for (i = 0; i < amdgpu_sched_jobs; ++i) 182 1.6 riastrad dma_fence_put(entity->fences[i]); 183 1.6 riastrad 184 1.6 riastrad kfree(entity); 185 1.6 riastrad } 186 1.6 riastrad 187 1.6 riastrad static void amdgpu_ctx_fini(struct kref *ref) 188 1.6 riastrad { 189 1.6 riastrad struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount); 190 1.1 riastrad struct amdgpu_device *adev = ctx->adev; 191 1.1 riastrad unsigned i, j; 192 1.1 riastrad 193 1.1 riastrad if (!adev) 194 1.1 riastrad return; 195 1.1 riastrad 196 1.6 riastrad for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { 197 1.6 riastrad for (j = 0; j < AMDGPU_MAX_ENTITY_NUM; ++j) { 198 1.6 riastrad amdgpu_ctx_fini_entity(ctx->entities[i][j]); 199 1.6 riastrad ctx->entities[i][j] = NULL; 200 1.6 riastrad } 201 1.6 riastrad } 202 1.6 riastrad 203 1.6 riastrad mutex_destroy(&ctx->lock); 204 1.7 riastrad spin_lock_destroy(&ctx->ring_lock); 205 1.6 riastrad kfree(ctx); 206 1.6 riastrad } 207 1.6 riastrad 208 1.6 riastrad int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance, 209 1.6 riastrad u32 ring, struct drm_sched_entity **entity) 210 1.6 riastrad { 211 1.6 riastrad int r; 212 1.6 riastrad 213 1.6 riastrad if (hw_ip >= AMDGPU_HW_IP_NUM) { 214 1.6 riastrad DRM_ERROR("unknown HW IP type: %d\n", hw_ip); 215 1.6 riastrad return -EINVAL; 216 1.6 riastrad } 217 1.6 riastrad 218 1.6 riastrad /* Right now all IPs have only one instance - multiple rings. */ 219 1.6 riastrad if (instance != 0) { 220 1.6 riastrad DRM_DEBUG("invalid ip instance: %d\n", instance); 221 1.6 riastrad return -EINVAL; 222 1.6 riastrad } 223 1.6 riastrad 224 1.6 riastrad if (ring >= amdgpu_ctx_num_entities[hw_ip]) { 225 1.6 riastrad DRM_DEBUG("invalid ring: %d %d\n", hw_ip, ring); 226 1.6 riastrad return -EINVAL; 227 1.6 riastrad } 228 1.6 riastrad 229 1.6 riastrad if (ctx->entities[hw_ip][ring] == NULL) { 230 1.6 riastrad r = amdgpu_ctx_init_entity(ctx, hw_ip, ring); 231 1.6 riastrad if (r) 232 1.6 riastrad return r; 233 1.1 riastrad } 234 1.6 riastrad 235 1.6 riastrad *entity = &ctx->entities[hw_ip][ring]->entity; 236 1.6 riastrad return 0; 237 1.1 riastrad } 238 1.1 riastrad 239 1.1 riastrad static int amdgpu_ctx_alloc(struct amdgpu_device *adev, 240 1.1 riastrad struct amdgpu_fpriv *fpriv, 241 1.6 riastrad struct drm_file *filp, 242 1.6 riastrad enum drm_sched_priority priority, 243 1.1 riastrad uint32_t *id) 244 1.1 riastrad { 245 1.1 riastrad struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; 246 1.1 riastrad struct amdgpu_ctx *ctx; 247 1.1 riastrad int r; 248 1.1 riastrad 249 1.1 riastrad ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 250 1.1 riastrad if (!ctx) 251 1.1 riastrad return -ENOMEM; 252 1.1 riastrad 253 1.4 riastrad idr_preload(GFP_KERNEL); 254 1.1 riastrad mutex_lock(&mgr->lock); 255 1.6 riastrad r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL); 256 1.1 riastrad if (r < 0) { 257 1.1 riastrad mutex_unlock(&mgr->lock); 258 1.4 riastrad idr_preload_end(); 259 1.1 riastrad kfree(ctx); 260 1.1 riastrad return r; 261 1.1 riastrad } 262 1.6 riastrad 263 1.1 riastrad *id = (uint32_t)r; 264 1.6 riastrad r = amdgpu_ctx_init(adev, priority, filp, ctx); 265 1.6 riastrad if (r) { 266 1.6 riastrad idr_remove(&mgr->ctx_handles, *id); 267 1.6 riastrad *id = 0; 268 1.6 riastrad kfree(ctx); 269 1.6 riastrad } 270 1.1 riastrad mutex_unlock(&mgr->lock); 271 1.4 riastrad idr_preload_end(); 272 1.1 riastrad 273 1.1 riastrad return r; 274 1.1 riastrad } 275 1.1 riastrad 276 1.1 riastrad static void amdgpu_ctx_do_release(struct kref *ref) 277 1.1 riastrad { 278 1.1 riastrad struct amdgpu_ctx *ctx; 279 1.6 riastrad u32 i, j; 280 1.1 riastrad 281 1.1 riastrad ctx = container_of(ref, struct amdgpu_ctx, refcount); 282 1.6 riastrad for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { 283 1.6 riastrad for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) { 284 1.6 riastrad if (!ctx->entities[i][j]) 285 1.6 riastrad continue; 286 1.1 riastrad 287 1.6 riastrad drm_sched_entity_destroy(&ctx->entities[i][j]->entity); 288 1.6 riastrad } 289 1.6 riastrad } 290 1.1 riastrad 291 1.6 riastrad amdgpu_ctx_fini(ref); 292 1.1 riastrad } 293 1.1 riastrad 294 1.1 riastrad static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id) 295 1.1 riastrad { 296 1.1 riastrad struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; 297 1.1 riastrad struct amdgpu_ctx *ctx; 298 1.1 riastrad 299 1.1 riastrad mutex_lock(&mgr->lock); 300 1.6 riastrad ctx = idr_remove(&mgr->ctx_handles, id); 301 1.6 riastrad if (ctx) 302 1.1 riastrad kref_put(&ctx->refcount, amdgpu_ctx_do_release); 303 1.1 riastrad mutex_unlock(&mgr->lock); 304 1.6 riastrad return ctx ? 0 : -EINVAL; 305 1.1 riastrad } 306 1.1 riastrad 307 1.1 riastrad static int amdgpu_ctx_query(struct amdgpu_device *adev, 308 1.1 riastrad struct amdgpu_fpriv *fpriv, uint32_t id, 309 1.1 riastrad union drm_amdgpu_ctx_out *out) 310 1.1 riastrad { 311 1.1 riastrad struct amdgpu_ctx *ctx; 312 1.1 riastrad struct amdgpu_ctx_mgr *mgr; 313 1.1 riastrad unsigned reset_counter; 314 1.1 riastrad 315 1.1 riastrad if (!fpriv) 316 1.1 riastrad return -EINVAL; 317 1.1 riastrad 318 1.1 riastrad mgr = &fpriv->ctx_mgr; 319 1.1 riastrad mutex_lock(&mgr->lock); 320 1.1 riastrad ctx = idr_find(&mgr->ctx_handles, id); 321 1.1 riastrad if (!ctx) { 322 1.1 riastrad mutex_unlock(&mgr->lock); 323 1.1 riastrad return -EINVAL; 324 1.1 riastrad } 325 1.1 riastrad 326 1.1 riastrad /* TODO: these two are always zero */ 327 1.1 riastrad out->state.flags = 0x0; 328 1.1 riastrad out->state.hangs = 0x0; 329 1.1 riastrad 330 1.1 riastrad /* determine if a GPU reset has occured since the last call */ 331 1.1 riastrad reset_counter = atomic_read(&adev->gpu_reset_counter); 332 1.1 riastrad /* TODO: this should ideally return NO, GUILTY, or INNOCENT. */ 333 1.6 riastrad if (ctx->reset_counter_query == reset_counter) 334 1.1 riastrad out->state.reset_status = AMDGPU_CTX_NO_RESET; 335 1.1 riastrad else 336 1.1 riastrad out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET; 337 1.6 riastrad ctx->reset_counter_query = reset_counter; 338 1.6 riastrad 339 1.6 riastrad mutex_unlock(&mgr->lock); 340 1.6 riastrad return 0; 341 1.6 riastrad } 342 1.6 riastrad 343 1.6 riastrad static int amdgpu_ctx_query2(struct amdgpu_device *adev, 344 1.6 riastrad struct amdgpu_fpriv *fpriv, uint32_t id, 345 1.6 riastrad union drm_amdgpu_ctx_out *out) 346 1.6 riastrad { 347 1.6 riastrad struct amdgpu_ctx *ctx; 348 1.6 riastrad struct amdgpu_ctx_mgr *mgr; 349 1.6 riastrad unsigned long ras_counter; 350 1.6 riastrad 351 1.6 riastrad if (!fpriv) 352 1.6 riastrad return -EINVAL; 353 1.6 riastrad 354 1.6 riastrad mgr = &fpriv->ctx_mgr; 355 1.6 riastrad mutex_lock(&mgr->lock); 356 1.6 riastrad ctx = idr_find(&mgr->ctx_handles, id); 357 1.6 riastrad if (!ctx) { 358 1.6 riastrad mutex_unlock(&mgr->lock); 359 1.6 riastrad return -EINVAL; 360 1.6 riastrad } 361 1.6 riastrad 362 1.6 riastrad out->state.flags = 0x0; 363 1.6 riastrad out->state.hangs = 0x0; 364 1.6 riastrad 365 1.6 riastrad if (ctx->reset_counter != atomic_read(&adev->gpu_reset_counter)) 366 1.6 riastrad out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET; 367 1.6 riastrad 368 1.6 riastrad if (ctx->vram_lost_counter != atomic_read(&adev->vram_lost_counter)) 369 1.6 riastrad out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST; 370 1.6 riastrad 371 1.6 riastrad if (atomic_read(&ctx->guilty)) 372 1.6 riastrad out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY; 373 1.6 riastrad 374 1.6 riastrad /*query ue count*/ 375 1.6 riastrad ras_counter = amdgpu_ras_query_error_count(adev, false); 376 1.6 riastrad /*ras counter is monotonic increasing*/ 377 1.6 riastrad if (ras_counter != ctx->ras_counter_ue) { 378 1.6 riastrad out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE; 379 1.6 riastrad ctx->ras_counter_ue = ras_counter; 380 1.6 riastrad } 381 1.6 riastrad 382 1.6 riastrad /*query ce count*/ 383 1.6 riastrad ras_counter = amdgpu_ras_query_error_count(adev, true); 384 1.6 riastrad if (ras_counter != ctx->ras_counter_ce) { 385 1.6 riastrad out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE; 386 1.6 riastrad ctx->ras_counter_ce = ras_counter; 387 1.6 riastrad } 388 1.1 riastrad 389 1.1 riastrad mutex_unlock(&mgr->lock); 390 1.1 riastrad return 0; 391 1.1 riastrad } 392 1.1 riastrad 393 1.1 riastrad int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, 394 1.1 riastrad struct drm_file *filp) 395 1.1 riastrad { 396 1.1 riastrad int r; 397 1.1 riastrad uint32_t id; 398 1.6 riastrad enum drm_sched_priority priority; 399 1.1 riastrad 400 1.1 riastrad union drm_amdgpu_ctx *args = data; 401 1.1 riastrad struct amdgpu_device *adev = dev->dev_private; 402 1.1 riastrad struct amdgpu_fpriv *fpriv = filp->driver_priv; 403 1.1 riastrad 404 1.1 riastrad r = 0; 405 1.1 riastrad id = args->in.ctx_id; 406 1.6 riastrad priority = amdgpu_to_sched_priority(args->in.priority); 407 1.6 riastrad 408 1.6 riastrad /* For backwards compatibility reasons, we need to accept 409 1.6 riastrad * ioctls with garbage in the priority field */ 410 1.6 riastrad if (priority == DRM_SCHED_PRIORITY_INVALID) 411 1.6 riastrad priority = DRM_SCHED_PRIORITY_NORMAL; 412 1.1 riastrad 413 1.1 riastrad switch (args->in.op) { 414 1.6 riastrad case AMDGPU_CTX_OP_ALLOC_CTX: 415 1.6 riastrad r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id); 416 1.6 riastrad args->out.alloc.ctx_id = id; 417 1.6 riastrad break; 418 1.6 riastrad case AMDGPU_CTX_OP_FREE_CTX: 419 1.6 riastrad r = amdgpu_ctx_free(fpriv, id); 420 1.6 riastrad break; 421 1.6 riastrad case AMDGPU_CTX_OP_QUERY_STATE: 422 1.6 riastrad r = amdgpu_ctx_query(adev, fpriv, id, &args->out); 423 1.6 riastrad break; 424 1.6 riastrad case AMDGPU_CTX_OP_QUERY_STATE2: 425 1.6 riastrad r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); 426 1.6 riastrad break; 427 1.6 riastrad default: 428 1.6 riastrad return -EINVAL; 429 1.1 riastrad } 430 1.1 riastrad 431 1.1 riastrad return r; 432 1.1 riastrad } 433 1.1 riastrad 434 1.1 riastrad struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id) 435 1.1 riastrad { 436 1.1 riastrad struct amdgpu_ctx *ctx; 437 1.1 riastrad struct amdgpu_ctx_mgr *mgr; 438 1.1 riastrad 439 1.1 riastrad if (!fpriv) 440 1.1 riastrad return NULL; 441 1.1 riastrad 442 1.1 riastrad mgr = &fpriv->ctx_mgr; 443 1.1 riastrad 444 1.1 riastrad mutex_lock(&mgr->lock); 445 1.1 riastrad ctx = idr_find(&mgr->ctx_handles, id); 446 1.1 riastrad if (ctx) 447 1.1 riastrad kref_get(&ctx->refcount); 448 1.1 riastrad mutex_unlock(&mgr->lock); 449 1.1 riastrad return ctx; 450 1.1 riastrad } 451 1.1 riastrad 452 1.1 riastrad int amdgpu_ctx_put(struct amdgpu_ctx *ctx) 453 1.1 riastrad { 454 1.1 riastrad if (ctx == NULL) 455 1.1 riastrad return -EINVAL; 456 1.1 riastrad 457 1.1 riastrad kref_put(&ctx->refcount, amdgpu_ctx_do_release); 458 1.1 riastrad return 0; 459 1.1 riastrad } 460 1.1 riastrad 461 1.6 riastrad void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, 462 1.6 riastrad struct drm_sched_entity *entity, 463 1.6 riastrad struct dma_fence *fence, uint64_t* handle) 464 1.6 riastrad { 465 1.6 riastrad struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); 466 1.8 riastrad uint64_t seq; 467 1.6 riastrad struct dma_fence *other = NULL; 468 1.1 riastrad unsigned idx = 0; 469 1.1 riastrad 470 1.8 riastrad spin_lock(&ctx->ring_lock); 471 1.8 riastrad seq = centity->sequence; 472 1.6 riastrad idx = seq & (amdgpu_sched_jobs - 1); 473 1.6 riastrad other = centity->fences[idx]; 474 1.6 riastrad if (other) 475 1.6 riastrad BUG_ON(!dma_fence_is_signaled(other)); 476 1.1 riastrad 477 1.6 riastrad dma_fence_get(fence); 478 1.6 riastrad centity->fences[idx] = fence; 479 1.6 riastrad centity->sequence++; 480 1.1 riastrad spin_unlock(&ctx->ring_lock); 481 1.1 riastrad 482 1.6 riastrad dma_fence_put(other); 483 1.6 riastrad if (handle) 484 1.6 riastrad *handle = seq; 485 1.1 riastrad } 486 1.1 riastrad 487 1.6 riastrad struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, 488 1.6 riastrad struct drm_sched_entity *entity, 489 1.6 riastrad uint64_t seq) 490 1.1 riastrad { 491 1.6 riastrad struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); 492 1.6 riastrad struct dma_fence *fence; 493 1.1 riastrad 494 1.1 riastrad spin_lock(&ctx->ring_lock); 495 1.1 riastrad 496 1.6 riastrad if (seq == ~0ull) 497 1.6 riastrad seq = centity->sequence - 1; 498 1.6 riastrad 499 1.6 riastrad if (seq >= centity->sequence) { 500 1.1 riastrad spin_unlock(&ctx->ring_lock); 501 1.1 riastrad return ERR_PTR(-EINVAL); 502 1.1 riastrad } 503 1.1 riastrad 504 1.1 riastrad 505 1.6 riastrad if (seq + amdgpu_sched_jobs < centity->sequence) { 506 1.1 riastrad spin_unlock(&ctx->ring_lock); 507 1.1 riastrad return NULL; 508 1.1 riastrad } 509 1.1 riastrad 510 1.6 riastrad fence = dma_fence_get(centity->fences[seq & (amdgpu_sched_jobs - 1)]); 511 1.1 riastrad spin_unlock(&ctx->ring_lock); 512 1.1 riastrad 513 1.1 riastrad return fence; 514 1.1 riastrad } 515 1.1 riastrad 516 1.6 riastrad void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, 517 1.6 riastrad enum drm_sched_priority priority) 518 1.6 riastrad { 519 1.6 riastrad enum drm_sched_priority ctx_prio; 520 1.6 riastrad unsigned i, j; 521 1.6 riastrad 522 1.6 riastrad ctx->override_priority = priority; 523 1.6 riastrad 524 1.6 riastrad ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ? 525 1.6 riastrad ctx->init_priority : ctx->override_priority; 526 1.6 riastrad for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { 527 1.6 riastrad for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) { 528 1.6 riastrad struct drm_sched_entity *entity; 529 1.6 riastrad 530 1.6 riastrad if (!ctx->entities[i][j]) 531 1.6 riastrad continue; 532 1.6 riastrad 533 1.6 riastrad entity = &ctx->entities[i][j]->entity; 534 1.6 riastrad drm_sched_entity_set_priority(entity, ctx_prio); 535 1.6 riastrad } 536 1.6 riastrad } 537 1.6 riastrad } 538 1.6 riastrad 539 1.6 riastrad int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, 540 1.6 riastrad struct drm_sched_entity *entity) 541 1.6 riastrad { 542 1.6 riastrad struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); 543 1.6 riastrad struct dma_fence *other; 544 1.6 riastrad unsigned idx; 545 1.6 riastrad long r; 546 1.6 riastrad 547 1.6 riastrad spin_lock(&ctx->ring_lock); 548 1.6 riastrad idx = centity->sequence & (amdgpu_sched_jobs - 1); 549 1.6 riastrad other = dma_fence_get(centity->fences[idx]); 550 1.6 riastrad spin_unlock(&ctx->ring_lock); 551 1.6 riastrad 552 1.6 riastrad if (!other) 553 1.6 riastrad return 0; 554 1.6 riastrad 555 1.6 riastrad r = dma_fence_wait(other, true); 556 1.6 riastrad if (r < 0 && r != -ERESTARTSYS) 557 1.6 riastrad DRM_ERROR("Error (%ld) waiting for fence!\n", r); 558 1.6 riastrad 559 1.6 riastrad dma_fence_put(other); 560 1.6 riastrad return r; 561 1.6 riastrad } 562 1.6 riastrad 563 1.1 riastrad void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr) 564 1.1 riastrad { 565 1.1 riastrad mutex_init(&mgr->lock); 566 1.1 riastrad idr_init(&mgr->ctx_handles); 567 1.1 riastrad } 568 1.1 riastrad 569 1.6 riastrad long amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr, long timeout) 570 1.6 riastrad { 571 1.6 riastrad struct amdgpu_ctx *ctx; 572 1.6 riastrad struct idr *idp; 573 1.6 riastrad uint32_t id, i, j; 574 1.6 riastrad 575 1.6 riastrad idp = &mgr->ctx_handles; 576 1.6 riastrad 577 1.6 riastrad mutex_lock(&mgr->lock); 578 1.6 riastrad idr_for_each_entry(idp, ctx, id) { 579 1.6 riastrad for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { 580 1.6 riastrad for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) { 581 1.6 riastrad struct drm_sched_entity *entity; 582 1.6 riastrad 583 1.6 riastrad if (!ctx->entities[i][j]) 584 1.6 riastrad continue; 585 1.6 riastrad 586 1.6 riastrad entity = &ctx->entities[i][j]->entity; 587 1.6 riastrad timeout = drm_sched_entity_flush(entity, timeout); 588 1.6 riastrad } 589 1.6 riastrad } 590 1.6 riastrad } 591 1.6 riastrad mutex_unlock(&mgr->lock); 592 1.6 riastrad return timeout; 593 1.6 riastrad } 594 1.6 riastrad 595 1.6 riastrad void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr) 596 1.6 riastrad { 597 1.6 riastrad struct amdgpu_ctx *ctx; 598 1.6 riastrad struct idr *idp; 599 1.6 riastrad uint32_t id, i, j; 600 1.6 riastrad 601 1.6 riastrad idp = &mgr->ctx_handles; 602 1.6 riastrad 603 1.6 riastrad idr_for_each_entry(idp, ctx, id) { 604 1.6 riastrad if (kref_read(&ctx->refcount) != 1) { 605 1.6 riastrad DRM_ERROR("ctx %p is still alive\n", ctx); 606 1.6 riastrad continue; 607 1.6 riastrad } 608 1.6 riastrad 609 1.6 riastrad for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { 610 1.6 riastrad for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) { 611 1.6 riastrad struct drm_sched_entity *entity; 612 1.6 riastrad 613 1.6 riastrad if (!ctx->entities[i][j]) 614 1.6 riastrad continue; 615 1.6 riastrad 616 1.6 riastrad entity = &ctx->entities[i][j]->entity; 617 1.6 riastrad drm_sched_entity_fini(entity); 618 1.6 riastrad } 619 1.6 riastrad } 620 1.6 riastrad } 621 1.6 riastrad } 622 1.6 riastrad 623 1.1 riastrad void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr) 624 1.1 riastrad { 625 1.1 riastrad struct amdgpu_ctx *ctx; 626 1.1 riastrad struct idr *idp; 627 1.1 riastrad uint32_t id; 628 1.1 riastrad 629 1.6 riastrad amdgpu_ctx_mgr_entity_fini(mgr); 630 1.6 riastrad 631 1.1 riastrad idp = &mgr->ctx_handles; 632 1.1 riastrad 633 1.1 riastrad idr_for_each_entry(idp, ctx, id) { 634 1.6 riastrad if (kref_put(&ctx->refcount, amdgpu_ctx_fini) != 1) 635 1.1 riastrad DRM_ERROR("ctx %p is still alive\n", ctx); 636 1.1 riastrad } 637 1.1 riastrad 638 1.1 riastrad idr_destroy(&mgr->ctx_handles); 639 1.1 riastrad mutex_destroy(&mgr->lock); 640 1.1 riastrad } 641 1.6 riastrad 642 1.6 riastrad void amdgpu_ctx_init_sched(struct amdgpu_device *adev) 643 1.6 riastrad { 644 1.6 riastrad int i, j; 645 1.6 riastrad 646 1.6 riastrad for (i = 0; i < adev->gfx.num_gfx_rings; i++) { 647 1.6 riastrad adev->gfx.gfx_sched[i] = &adev->gfx.gfx_ring[i].sched; 648 1.6 riastrad adev->gfx.num_gfx_sched++; 649 1.6 riastrad } 650 1.6 riastrad 651 1.6 riastrad for (i = 0; i < adev->gfx.num_compute_rings; i++) { 652 1.6 riastrad adev->gfx.compute_sched[i] = &adev->gfx.compute_ring[i].sched; 653 1.6 riastrad adev->gfx.num_compute_sched++; 654 1.6 riastrad } 655 1.6 riastrad 656 1.6 riastrad for (i = 0; i < adev->sdma.num_instances; i++) { 657 1.6 riastrad adev->sdma.sdma_sched[i] = &adev->sdma.instance[i].ring.sched; 658 1.6 riastrad adev->sdma.num_sdma_sched++; 659 1.6 riastrad } 660 1.6 riastrad 661 1.6 riastrad for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 662 1.6 riastrad if (adev->vcn.harvest_config & (1 << i)) 663 1.6 riastrad continue; 664 1.6 riastrad adev->vcn.vcn_dec_sched[adev->vcn.num_vcn_dec_sched++] = 665 1.6 riastrad &adev->vcn.inst[i].ring_dec.sched; 666 1.6 riastrad } 667 1.6 riastrad 668 1.6 riastrad for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 669 1.6 riastrad if (adev->vcn.harvest_config & (1 << i)) 670 1.6 riastrad continue; 671 1.6 riastrad for (j = 0; j < adev->vcn.num_enc_rings; ++j) 672 1.6 riastrad adev->vcn.vcn_enc_sched[adev->vcn.num_vcn_enc_sched++] = 673 1.6 riastrad &adev->vcn.inst[i].ring_enc[j].sched; 674 1.6 riastrad } 675 1.6 riastrad 676 1.6 riastrad for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 677 1.6 riastrad if (adev->jpeg.harvest_config & (1 << i)) 678 1.6 riastrad continue; 679 1.6 riastrad adev->jpeg.jpeg_sched[adev->jpeg.num_jpeg_sched++] = 680 1.6 riastrad &adev->jpeg.inst[i].ring_dec.sched; 681 1.6 riastrad } 682 1.6 riastrad } 683