[PATCH] drm/xe/eustall: Resolve circular locking dependency
Ashutosh Dixit
ashutosh.dixit at intel.com
Mon Apr 21 16:04:35 UTC 2025
Resolve circular locking depedendency, and possible deadlock, caused by the
lock order inversion in the following code paths:
eu_stall_data_buf_poll_work_fn queue_delayed_work():
workqueue_lock -> stream_lock
Enable/disable
stream_lock -> workqueue_lock -> stream_lock
Rather than introduce a new lock, the taken here is drop stream_lock before
calling workqueue functions in the enable/disable functions.
Signed-off-by: Ashutosh Dixit <ashutosh.dixit at intel.com>
---
drivers/gpu/drm/xe/xe_eu_stall.c | 63 +++++++++++++++++---------------
1 file changed, 33 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c
index f2bb9168967c2..4f406228b633b 100644
--- a/drivers/gpu/drm/xe/xe_eu_stall.c
+++ b/drivers/gpu/drm/xe/xe_eu_stall.c
@@ -44,6 +44,8 @@ struct per_xecore_buf {
struct xe_eu_stall_data_stream {
bool pollin;
bool enabled;
+ bool in_enable;
+ bool in_disable;
int wait_num_reports;
int sampling_rate_mult;
wait_queue_head_t poll_wq;
@@ -762,73 +764,74 @@ static __poll_t xe_eu_stall_stream_poll(struct file *file, poll_table *wait)
return ret;
}
-static int xe_eu_stall_enable_locked(struct xe_eu_stall_data_stream *stream)
+static int xe_eu_stall_enable(struct xe_eu_stall_data_stream *stream)
{
struct xe_gt *gt = stream->gt;
int ret = 0;
- if (stream->enabled)
- return ret;
-
- stream->enabled = true;
+ mutex_lock(>->eu_stall->stream_lock);
+ if (stream->enabled || stream->in_enable)
+ goto exit;
+ stream->in_enable = true;
ret = xe_eu_stall_stream_enable(stream);
+ if (ret)
+ goto exit;
+ mutex_unlock(>->eu_stall->stream_lock);
queue_delayed_work(gt->eu_stall->buf_ptr_poll_wq,
&stream->buf_poll_work,
msecs_to_jiffies(POLL_PERIOD_MS));
+
+ mutex_lock(>->eu_stall->stream_lock);
+ stream->enabled = true;
+ stream->in_enable = false;
+exit:
+ mutex_unlock(>->eu_stall->stream_lock);
return ret;
}
-static int xe_eu_stall_disable_locked(struct xe_eu_stall_data_stream *stream)
+static int xe_eu_stall_disable(struct xe_eu_stall_data_stream *stream)
{
struct xe_gt *gt = stream->gt;
- if (!stream->enabled)
- return 0;
-
- stream->enabled = false;
-
+ mutex_lock(>->eu_stall->stream_lock);
+ if (!stream->enabled || stream->in_disable)
+ goto exit;
+ stream->in_disable = true;
xe_gt_mcr_multicast_write(gt, XEHPC_EUSTALL_BASE, 0);
+ mutex_unlock(>->eu_stall->stream_lock);
cancel_delayed_work_sync(&stream->buf_poll_work);
+ mutex_lock(>->eu_stall->stream_lock);
if (XE_WA(gt, 22016596838))
xe_gt_mcr_multicast_write(gt, ROW_CHICKEN2,
_MASKED_BIT_DISABLE(DISABLE_DOP_GATING));
xe_force_wake_put(gt_to_fw(gt), XE_FW_RENDER);
xe_pm_runtime_put(gt_to_xe(gt));
-
+ stream->enabled = false;
+ stream->in_disable = false;
+exit:
+ mutex_unlock(>->eu_stall->stream_lock);
return 0;
}
-static long xe_eu_stall_stream_ioctl_locked(struct xe_eu_stall_data_stream *stream,
- unsigned int cmd, unsigned long arg)
+static long xe_eu_stall_stream_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
+ struct xe_eu_stall_data_stream *stream = file->private_data;
+
switch (cmd) {
case DRM_XE_OBSERVATION_IOCTL_ENABLE:
- return xe_eu_stall_enable_locked(stream);
+ return xe_eu_stall_enable(stream);
case DRM_XE_OBSERVATION_IOCTL_DISABLE:
- return xe_eu_stall_disable_locked(stream);
+ return xe_eu_stall_disable(stream);
}
return -EINVAL;
}
-static long xe_eu_stall_stream_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct xe_eu_stall_data_stream *stream = file->private_data;
- struct xe_gt *gt = stream->gt;
- long ret;
-
- mutex_lock(>->eu_stall->stream_lock);
- ret = xe_eu_stall_stream_ioctl_locked(stream, cmd, arg);
- mutex_unlock(>->eu_stall->stream_lock);
-
- return ret;
-}
-
static int xe_eu_stall_stream_close(struct inode *inode, struct file *file)
{
struct xe_eu_stall_data_stream *stream = file->private_data;
@@ -836,8 +839,8 @@ static int xe_eu_stall_stream_close(struct inode *inode, struct file *file)
drm_dev_put(>->tile->xe->drm);
+ xe_eu_stall_disable(stream);
mutex_lock(>->eu_stall->stream_lock);
- xe_eu_stall_disable_locked(stream);
xe_eu_stall_data_buf_destroy(stream);
xe_eu_stall_stream_free(stream);
mutex_unlock(>->eu_stall->stream_lock);
--
2.48.1
More information about the Intel-gfx-trybot
mailing list