From 1113e52ffee7b45def230d10edb1f2924c7b3f9e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 11 Jan 2024 19:56:03 +0100 Subject: [PATCH] drm/xe: Fix potential deadlock in __fini_dbm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Doorbell Manager is in unclean state during fini phase, for debug purposes we try to print it's state, but we missed the fact that we are already holding a lock so the xe_guc_db_mgr_print() will deadlock since it also attempts to grab the same lock. Fixes: 587c73343ac7 ("drm/xe: Introduce GuC Doorbells Manager") Cc: Piotr PiĆ³rkowski Reviewed-by: Piotr PiĆ³rkowski Link: https://lore.kernel.org/r/20240111185603.673-1-michal.wajdeczko@intel.com Signed-off-by: Michal Wajdeczko --- drivers/gpu/drm/xe/xe_guc_db_mgr.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_db_mgr.c b/drivers/gpu/drm/xe/xe_guc_db_mgr.c index c1c04575d82d..8d9a0287df6b 100644 --- a/drivers/gpu/drm/xe/xe_guc_db_mgr.c +++ b/drivers/gpu/drm/xe/xe_guc_db_mgr.c @@ -46,6 +46,8 @@ static struct xe_device *dbm_to_xe(struct xe_guc_db_mgr *dbm) #define dbm_assert(_dbm, _cond) xe_gt_assert(dbm_to_gt(_dbm), _cond) #define dbm_mutex(_dbm) (&dbm_to_guc(_dbm)->submission_state.lock) +static void dbm_print_locked(struct xe_guc_db_mgr *dbm, struct drm_printer *p, int indent); + static void __fini_dbm(struct drm_device *drm, void *arg) { struct xe_guc_db_mgr *dbm = arg; @@ -59,7 +61,7 @@ static void __fini_dbm(struct drm_device *drm, void *arg) xe_gt_err(dbm_to_gt(dbm), "GuC doorbells manager unclean (%u/%u)\n", weight, dbm->count); - xe_guc_db_mgr_print(dbm, &p, 1); + dbm_print_locked(dbm, &p, 1); } bitmap_free(dbm->bitmap); @@ -219,14 +221,7 @@ void xe_guc_db_mgr_release_range(struct xe_guc_db_mgr *dbm, mutex_unlock(dbm_mutex(dbm)); } -/** - * xe_guc_db_mgr_print() - Print status of GuC Doorbells Manager. - * @dbm: the &xe_guc_db_mgr to print - * @p: the &drm_printer to print to - * @indent: tab indentation level - */ -void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm, - struct drm_printer *p, int indent) +static void dbm_print_locked(struct xe_guc_db_mgr *dbm, struct drm_printer *p, int indent) { unsigned int rs, re; unsigned int total; @@ -235,8 +230,6 @@ void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm, if (!dbm->bitmap) return; - mutex_lock(dbm_mutex(dbm)); - total = 0; for_each_clear_bitrange(rs, re, dbm->bitmap, dbm->count) { drm_printf_indent(p, indent, "available range: %u..%u (%u)\n", @@ -252,7 +245,19 @@ void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm, total += re - rs; } drm_printf_indent(p, indent, "reserved total: %u\n", total); +} +/** + * xe_guc_db_mgr_print() - Print status of GuC Doorbells Manager. + * @dbm: the &xe_guc_db_mgr to print + * @p: the &drm_printer to print to + * @indent: tab indentation level + */ +void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm, + struct drm_printer *p, int indent) +{ + mutex_lock(dbm_mutex(dbm)); + dbm_print_locked(dbm, p, indent); mutex_unlock(dbm_mutex(dbm)); }