2 * Copyright 2015 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: monk liu <monk.liu@amd.com>
28 static void amdgpu_ctx_do_release(struct kref
*ref
)
30 struct amdgpu_ctx
*ctx
;
31 struct amdgpu_ctx_mgr
*mgr
;
33 ctx
= container_of(ref
, struct amdgpu_ctx
, refcount
);
34 mgr
= &ctx
->fpriv
->ctx_mgr
;
36 idr_remove(&mgr
->ctx_handles
, ctx
->id
);
40 int amdgpu_ctx_alloc(struct amdgpu_device
*adev
, struct amdgpu_fpriv
*fpriv
, uint32_t *id
, uint32_t flags
)
43 struct amdgpu_ctx
*ctx
;
44 struct amdgpu_ctx_mgr
*mgr
= &fpriv
->ctx_mgr
;
46 ctx
= kmalloc(sizeof(*ctx
), GFP_KERNEL
);
50 mutex_lock(&mgr
->lock
);
51 r
= idr_alloc(&mgr
->ctx_handles
, ctx
, 0, 0, GFP_KERNEL
);
53 mutex_unlock(&mgr
->lock
);
59 memset(ctx
, 0, sizeof(*ctx
));
62 kref_init(&ctx
->refcount
);
63 mutex_unlock(&mgr
->lock
);
68 int amdgpu_ctx_free(struct amdgpu_device
*adev
, struct amdgpu_fpriv
*fpriv
, uint32_t id
)
70 struct amdgpu_ctx
*ctx
;
71 struct amdgpu_ctx_mgr
*mgr
= &fpriv
->ctx_mgr
;
73 mutex_lock(&mgr
->lock
);
74 ctx
= idr_find(&mgr
->ctx_handles
, id
);
76 kref_put(&ctx
->refcount
, amdgpu_ctx_do_release
);
77 mutex_unlock(&mgr
->lock
);
80 mutex_unlock(&mgr
->lock
);
84 static int amdgpu_ctx_query(struct amdgpu_device
*adev
,
85 struct amdgpu_fpriv
*fpriv
, uint32_t id
,
86 union drm_amdgpu_ctx_out
*out
)
88 struct amdgpu_ctx
*ctx
;
89 struct amdgpu_ctx_mgr
*mgr
= &fpriv
->ctx_mgr
;
90 unsigned reset_counter
;
92 mutex_lock(&mgr
->lock
);
93 ctx
= idr_find(&mgr
->ctx_handles
, id
);
95 mutex_unlock(&mgr
->lock
);
99 /* TODO: these two are always zero */
100 out
->state
.flags
= ctx
->state
.flags
;
101 out
->state
.hangs
= ctx
->state
.hangs
;
103 /* determine if a GPU reset has occured since the last call */
104 reset_counter
= atomic_read(&adev
->gpu_reset_counter
);
105 /* TODO: this should ideally return NO, GUILTY, or INNOCENT. */
106 if (ctx
->reset_counter
== reset_counter
)
107 out
->state
.reset_status
= AMDGPU_CTX_NO_RESET
;
109 out
->state
.reset_status
= AMDGPU_CTX_UNKNOWN_RESET
;
110 ctx
->reset_counter
= reset_counter
;
112 mutex_unlock(&mgr
->lock
);
116 void amdgpu_ctx_fini(struct amdgpu_fpriv
*fpriv
)
119 struct amdgpu_ctx
*ctx
;
121 struct amdgpu_ctx_mgr
*mgr
= &fpriv
->ctx_mgr
;
122 idp
= &mgr
->ctx_handles
;
124 idr_for_each_entry(idp
,ctx
,id
) {
125 if (kref_put(&ctx
->refcount
, amdgpu_ctx_do_release
) != 1)
126 DRM_ERROR("ctx (id=%ul) is still alive\n",ctx
->id
);
129 mutex_destroy(&mgr
->lock
);
132 int amdgpu_ctx_ioctl(struct drm_device
*dev
, void *data
,
133 struct drm_file
*filp
)
139 union drm_amdgpu_ctx
*args
= data
;
140 struct amdgpu_device
*adev
= dev
->dev_private
;
141 struct amdgpu_fpriv
*fpriv
= filp
->driver_priv
;
144 id
= args
->in
.ctx_id
;
145 flags
= args
->in
.flags
;
147 switch (args
->in
.op
) {
148 case AMDGPU_CTX_OP_ALLOC_CTX
:
149 r
= amdgpu_ctx_alloc(adev
, fpriv
, &id
, flags
);
150 args
->out
.alloc
.ctx_id
= id
;
152 case AMDGPU_CTX_OP_FREE_CTX
:
153 r
= amdgpu_ctx_free(adev
, fpriv
, id
);
155 case AMDGPU_CTX_OP_QUERY_STATE
:
156 r
= amdgpu_ctx_query(adev
, fpriv
, id
, &args
->out
);
165 struct amdgpu_ctx
*amdgpu_ctx_get(struct amdgpu_fpriv
*fpriv
, uint32_t id
)
167 struct amdgpu_ctx
*ctx
;
168 struct amdgpu_ctx_mgr
*mgr
= &fpriv
->ctx_mgr
;
170 mutex_lock(&mgr
->lock
);
171 ctx
= idr_find(&mgr
->ctx_handles
, id
);
173 kref_get(&ctx
->refcount
);
174 mutex_unlock(&mgr
->lock
);
178 int amdgpu_ctx_put(struct amdgpu_ctx
*ctx
)
180 struct amdgpu_fpriv
*fpriv
;
181 struct amdgpu_ctx_mgr
*mgr
;
187 mgr
= &fpriv
->ctx_mgr
;
188 mutex_lock(&mgr
->lock
);
189 kref_put(&ctx
->refcount
, amdgpu_ctx_do_release
);
190 mutex_unlock(&mgr
->lock
);