Skip to content

Commit

Permalink
drm/xe: fix unbalanced rpm put() with fence_fini()
Browse files Browse the repository at this point in the history
Currently we can call fence_fini() twice if something goes wrong when
sending the GuC CT for the tlb request, since we signal the fence and
return an error, leading to the caller also calling fini() on the error
path in the case of stack version of the flow, which leads to an extra
rpm put() which might later cause device to enter suspend when it
shouldn't. It looks like we can just drop the fini() call since the
fence signaller side will already call this for us.

There are known mysterious splats with device going to sleep even with
an rpm ref, and this could be one candidate.

v2 (Matt B):
  - Prefer warning if we detect double fini()

Fixes: f002702 ("drm/xe: Hold a PM ref when GT TLB invalidations are inflight")
Signed-off-by: Matthew Auld <[email protected]>
Cc: Matthew Brost <[email protected]>
Cc: Nirmoy Das <[email protected]>
Reviewed-by: Matthew Brost <[email protected]>
Reviewed-by: Nirmoy Das <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
(cherry picked from commit cfcbc05)
Signed-off-by: Lucas De Marchi <[email protected]>
  • Loading branch information
matt-auld authored and lucasdemarchi committed Oct 16, 2024
1 parent 4ceead3 commit 03a86c2
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 23 deletions.
29 changes: 13 additions & 16 deletions drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ static long tlb_timeout_jiffies(struct xe_gt *gt)
return hw_tlb_timeout + 2 * delay;
}

static void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fence)
{
if (WARN_ON_ONCE(!fence->gt))
return;

xe_pm_runtime_put(gt_to_xe(fence->gt));
fence->gt = NULL; /* fini() should be called once */
}

static void
__invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence)
{
Expand Down Expand Up @@ -204,7 +213,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
tlb_timeout_jiffies(gt));
}
spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
} else if (ret < 0) {
} else {
__invalidation_fence_signal(xe, fence);
}
if (!ret) {
Expand Down Expand Up @@ -267,10 +276,8 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)

xe_gt_tlb_invalidation_fence_init(gt, &fence, true);
ret = xe_gt_tlb_invalidation_guc(gt, &fence);
if (ret < 0) {
xe_gt_tlb_invalidation_fence_fini(&fence);
if (ret)
return ret;
}

xe_gt_tlb_invalidation_fence_wait(&fence);
} else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) {
Expand Down Expand Up @@ -496,7 +503,8 @@ static const struct dma_fence_ops invalidation_fence_ops = {
* @stack: fence is stack variable
*
* Initialize TLB invalidation fence for use. xe_gt_tlb_invalidation_fence_fini
* must be called if fence is not signaled.
* will be automatically called when fence is signalled (all fences must signal),
* even on error.
*/
void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,
Expand All @@ -516,14 +524,3 @@ void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
dma_fence_get(&fence->base);
fence->gt = gt;
}

/**
* xe_gt_tlb_invalidation_fence_fini - Finalize TLB invalidation fence
* @fence: TLB invalidation fence to finalize
*
* Drop PM ref which fence took durinig init.
*/
void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fence)
{
xe_pm_runtime_put(gt_to_xe(fence->gt));
}
1 change: 0 additions & 1 deletion drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,
bool stack);
void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fence);

static inline void
xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence)
Expand Down
8 changes: 2 additions & 6 deletions drivers/gpu/drm/xe/xe_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3199,10 +3199,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)

ret = xe_gt_tlb_invalidation_vma(tile->primary_gt,
&fence[fence_id], vma);
if (ret < 0) {
xe_gt_tlb_invalidation_fence_fini(&fence[fence_id]);
if (ret)
goto wait;
}
++fence_id;

if (!tile->media_gt)
Expand All @@ -3214,10 +3212,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)

ret = xe_gt_tlb_invalidation_vma(tile->media_gt,
&fence[fence_id], vma);
if (ret < 0) {
xe_gt_tlb_invalidation_fence_fini(&fence[fence_id]);
if (ret)
goto wait;
}
++fence_id;
}
}
Expand Down

0 comments on commit 03a86c2

Please sign in to comment.