Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: drop userq fence driver refs out of fence process()

amdgpu_userq_wait_ioctl() takes extra references on waited-on fence
drivers and stores them in waitq->fence_drv_xa. When a new userq fence is
created, those references are transferred into userq_fence->fence_drv_array
so they can be released when the fence completes.

However, those inherited references are currently only dropped from
amdgpu_userq_fence_driver_process(). If a fence never reaches that path,
such as it is already signaled when created, so we need to explicitly release
those fences in that case.

v2: use a list(list_cut_before) for managing the signal userq driver fences.(Christian)
Link: https://patchwork.freedesktop.org/patch/718078/?series=164763&rev=2
v3: Doesn't cache the userq first unsignaled fence and use the cut before list
head directly.(Christian)

Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Prike Liang <Prike.Liang@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Prike Liang and committed by
Alex Deucher
dd88d42d b250a43b

+33 -14
+33 -14
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
··· 145 145 amdgpu_userq_fence_driver_put(userq->fence_drv); 146 146 } 147 147 148 + static void 149 + amdgpu_userq_fence_put_fence_drv_array(struct amdgpu_userq_fence *userq_fence) 150 + { 151 + unsigned long i; 152 + for (i = 0; i < userq_fence->fence_drv_array_count; i++) 153 + amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]); 154 + userq_fence->fence_drv_array_count = 0; 155 + } 156 + 148 157 void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_drv) 149 158 { 150 159 struct amdgpu_userq_fence *userq_fence, *tmp; 160 + LIST_HEAD(to_be_signaled); 151 161 struct dma_fence *fence; 152 162 unsigned long flags; 153 163 u64 rptr; 154 - int i; 155 164 156 165 if (!fence_drv) 157 166 return; ··· 168 159 spin_lock_irqsave(&fence_drv->fence_list_lock, flags); 169 160 rptr = amdgpu_userq_fence_read(fence_drv); 170 161 171 - list_for_each_entry_safe(userq_fence, tmp, &fence_drv->fences, link) { 172 - fence = &userq_fence->base; 173 - 174 - if (rptr < fence->seqno) 162 + list_for_each_entry(userq_fence, &fence_drv->fences, link) { 163 + if (rptr < userq_fence->base.seqno) 175 164 break; 165 + } 176 166 167 + list_cut_before(&to_be_signaled, &fence_drv->fences, 168 + &userq_fence->link); 169 + spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags); 170 + 171 + list_for_each_entry_safe(userq_fence, tmp, &to_be_signaled, link) { 172 + fence = &userq_fence->base; 173 + list_del_init(&userq_fence->link); 177 174 dma_fence_signal(fence); 178 - 179 - for (i = 0; i < userq_fence->fence_drv_array_count; i++) 180 - amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]); 181 - 182 - list_del(&userq_fence->link); 175 + /* Drop fence_drv_array outside fence_list_lock 176 + * to avoid the recursion lock. 177 + */ 178 + amdgpu_userq_fence_put_fence_drv_array(userq_fence); 183 179 dma_fence_put(fence); 184 180 } 185 - spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags); 181 + 186 182 } 187 183 188 184 void amdgpu_userq_fence_driver_destroy(struct kref *ref) ··· 242 228 struct amdgpu_userq_fence_driver *fence_drv; 243 229 struct dma_fence *fence; 244 230 unsigned long flags; 231 + bool signaled = false; 245 232 246 233 fence_drv = userq->fence_drv; 247 234 if (!fence_drv) ··· 289 274 290 275 /* Check if hardware has already processed the job */ 291 276 spin_lock_irqsave(&fence_drv->fence_list_lock, flags); 292 - if (!dma_fence_is_signaled(fence)) 277 + if (!dma_fence_is_signaled(fence)) { 293 278 list_add_tail(&userq_fence->link, &fence_drv->fences); 294 - else 279 + } else { 280 + signaled = true; 295 281 dma_fence_put(fence); 296 - 282 + } 297 283 spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags); 284 + 285 + if (signaled) 286 + amdgpu_userq_fence_put_fence_drv_array(userq_fence); 298 287 299 288 *f = fence; 300 289