Commit 1113e52f authored by Michal Wajdeczko's avatar Michal Wajdeczko

drm/xe: Fix potential deadlock in __fini_dbm

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: 587c7334 ("drm/xe: Introduce GuC Doorbells Manager")
Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
Reviewed-by: default avatarPiotr Piórkowski <piotr.piorkowski@intel.com>
Link: https://lore.kernel.org/r/20240111185603.673-1-michal.wajdeczko@intel.comSigned-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
parent 33ff1f21
...@@ -46,6 +46,8 @@ static struct xe_device *dbm_to_xe(struct xe_guc_db_mgr *dbm) ...@@ -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_assert(_dbm, _cond) xe_gt_assert(dbm_to_gt(_dbm), _cond)
#define dbm_mutex(_dbm) (&dbm_to_guc(_dbm)->submission_state.lock) #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) static void __fini_dbm(struct drm_device *drm, void *arg)
{ {
struct xe_guc_db_mgr *dbm = arg; struct xe_guc_db_mgr *dbm = arg;
...@@ -59,7 +61,7 @@ static void __fini_dbm(struct drm_device *drm, void *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", xe_gt_err(dbm_to_gt(dbm), "GuC doorbells manager unclean (%u/%u)\n",
weight, dbm->count); weight, dbm->count);
xe_guc_db_mgr_print(dbm, &p, 1); dbm_print_locked(dbm, &p, 1);
} }
bitmap_free(dbm->bitmap); bitmap_free(dbm->bitmap);
...@@ -219,14 +221,7 @@ void xe_guc_db_mgr_release_range(struct xe_guc_db_mgr *dbm, ...@@ -219,14 +221,7 @@ void xe_guc_db_mgr_release_range(struct xe_guc_db_mgr *dbm,
mutex_unlock(dbm_mutex(dbm)); mutex_unlock(dbm_mutex(dbm));
} }
/** static void dbm_print_locked(struct xe_guc_db_mgr *dbm, struct drm_printer *p, int indent)
* 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)
{ {
unsigned int rs, re; unsigned int rs, re;
unsigned int total; unsigned int total;
...@@ -235,8 +230,6 @@ void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm, ...@@ -235,8 +230,6 @@ void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm,
if (!dbm->bitmap) if (!dbm->bitmap)
return; return;
mutex_lock(dbm_mutex(dbm));
total = 0; total = 0;
for_each_clear_bitrange(rs, re, dbm->bitmap, dbm->count) { for_each_clear_bitrange(rs, re, dbm->bitmap, dbm->count) {
drm_printf_indent(p, indent, "available range: %u..%u (%u)\n", 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, ...@@ -252,7 +245,19 @@ void xe_guc_db_mgr_print(struct xe_guc_db_mgr *dbm,
total += re - rs; total += re - rs;
} }
drm_printf_indent(p, indent, "reserved total: %u\n", total); 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)); mutex_unlock(dbm_mutex(dbm));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment