All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-07 13:20 ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-07 13:20 UTC (permalink / raw)
  To: intel-gfx
  Cc: dri-devel, Maarten Lankhorst, Peter Zijlstra, Ingo Molnar,
	Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown,
	linux-kernel

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

BUG: MAX_LOCK_DEPTH too low!
turning off the locking correctness validator.
depth: 48  max: 48!
48 locks held by i915_selftest/5776:
 #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
 #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
 #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
 #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
 #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
...
 #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority,
but it requires a rework of the entire driver, which can only be
done one step at a time.

As an intermediate solution, add an acquire context to ww_mutex_trylock,
which allows us to do proper nesting annotations on the trylocks, making
the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org
---
 drivers/gpu/drm/drm_modeset_lock.c |  2 +-
 drivers/regulator/core.c           |  2 +-
 include/linux/dma-resv.h           |  2 +-
 include/linux/ww_mutex.h           | 13 +----
 kernel/locking/mutex.c             | 38 +++++++++++++
 kernel/locking/test-ww_mutex.c     | 86 ++++++++++++++++++++++--------
 lib/locking-selftest.c             |  2 +-
 7 files changed, 109 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fcfe1a03c4a1..bf8a6e823a15 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba8a191..f4d441b1a8bf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index e1ca2080a1ff..39fefb86780b 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index b77f39f319ad..0b8f28577c00 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -313,17 +313,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return mutex_trylock(&lock->base);
-}
+int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+				  struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index d2df5e68b503..5d0f5b04b568 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -1112,6 +1112,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
 	return __mutex_lock_common(lock, state, subclass, nest_lock, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @lock: mutex to lock
+ * @ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int __sched
+ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
+{
+	bool locked;
+
+	if (!ctx)
+		return mutex_trylock(&ww->base);
+
+#ifdef CONFIG_DEBUG_MUTEXES
+	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
+#endif
+
+	preempt_disable();
+	locked = __mutex_trylock(&ww->base);
+
+	if (locked) {
+		ww_mutex_set_context_fastpath(ww, ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
+	}
+	preempt_enable();
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 3e82f449b4ff..d63ac411f367 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 161108e5d2fe..71652e1c397c 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-07 13:20 ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-07 13:20 UTC (permalink / raw)
  To: intel-gfx
  Cc: dri-devel, Maarten Lankhorst, Peter Zijlstra, Ingo Molnar,
	Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown,
	linux-kernel

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

BUG: MAX_LOCK_DEPTH too low!
turning off the locking correctness validator.
depth: 48  max: 48!
48 locks held by i915_selftest/5776:
 #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
 #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
 #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
 #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
 #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
...
 #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority,
but it requires a rework of the entire driver, which can only be
done one step at a time.

As an intermediate solution, add an acquire context to ww_mutex_trylock,
which allows us to do proper nesting annotations on the trylocks, making
the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org
---
 drivers/gpu/drm/drm_modeset_lock.c |  2 +-
 drivers/regulator/core.c           |  2 +-
 include/linux/dma-resv.h           |  2 +-
 include/linux/ww_mutex.h           | 13 +----
 kernel/locking/mutex.c             | 38 +++++++++++++
 kernel/locking/test-ww_mutex.c     | 86 ++++++++++++++++++++++--------
 lib/locking-selftest.c             |  2 +-
 7 files changed, 109 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fcfe1a03c4a1..bf8a6e823a15 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba8a191..f4d441b1a8bf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index e1ca2080a1ff..39fefb86780b 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index b77f39f319ad..0b8f28577c00 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -313,17 +313,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return mutex_trylock(&lock->base);
-}
+int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+				  struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index d2df5e68b503..5d0f5b04b568 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -1112,6 +1112,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
 	return __mutex_lock_common(lock, state, subclass, nest_lock, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @lock: mutex to lock
+ * @ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int __sched
+ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
+{
+	bool locked;
+
+	if (!ctx)
+		return mutex_trylock(&ww->base);
+
+#ifdef CONFIG_DEBUG_MUTEXES
+	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
+#endif
+
+	preempt_disable();
+	locked = __mutex_trylock(&ww->base);
+
+	if (locked) {
+		ww_mutex_set_context_fastpath(ww, ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
+	}
+	preempt_enable();
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 3e82f449b4ff..d63ac411f367 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 161108e5d2fe..71652e1c397c 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for kernel/locking: Add context to ww_mutex_trylock.
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
  (?)
@ 2021-09-07 13:54 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-07 13:54 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock.
URL   : https://patchwork.freedesktop.org/series/94437/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
9eed33b42bf0 kernel/locking: Add context to ww_mutex_trylock.
-:166: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'a' - possible side-effects?
#166: FILE: kernel/locking/test-ww_mutex.c:20:
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)

-:321: WARNING:PREFER_PR_LEVEL: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(...  to printk(KERN_INFO ...
#321: FILE: kernel/locking/test-ww_mutex.c:625:
+	printk(KERN_INFO "Beginning ww mutex selftests\n");

-:354: WARNING:PREFER_PR_LEVEL: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(...  to printk(KERN_INFO ...
#354: FILE: kernel/locking/test-ww_mutex.c:665:
+	printk(KERN_INFO "All ww mutex selftests passed\n");

total: 0 errors, 2 warnings, 1 checks, 280 lines checked



^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for kernel/locking: Add context to ww_mutex_trylock.
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
  (?)
  (?)
@ 2021-09-07 14:27 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-07 14:27 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 3865 bytes --]

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock.
URL   : https://patchwork.freedesktop.org/series/94437/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10557 -> Patchwork_20976
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/index.html

New tests
---------

  New tests have been introduced between CI_DRM_10557 and Patchwork_20976:

### New IGT tests (1) ###

  * igt@i915_selftest@live@slpc:
    - Statuses : 35 pass(s)
    - Exec time: [0.42, 5.70] s

  

Known issues
------------

  Here are the changes found in Patchwork_20976 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_cs_nop@sync-fork-compute0:
    - fi-snb-2600:        NOTRUN -> [SKIP][1] ([fdo#109271]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-snb-2600/igt@amdgpu/amd_cs_nop@sync-fork-compute0.html

  * igt@amdgpu/amd_prime@amd-to-i915:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][2] ([fdo#109271]) +26 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-kbl-x1275/igt@amdgpu/amd_prime@amd-to-i915.html

  * igt@gem_huc_copy@huc-copy:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][3] ([fdo#109271] / [i915#2190])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-kbl-x1275/igt@gem_huc_copy@huc-copy.html

  * igt@kms_chamelium@hdmi-crc-fast:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][4] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-kbl-x1275/igt@kms_chamelium@hdmi-crc-fast.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-d:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][5] ([fdo#109271] / [i915#533])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-kbl-x1275/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-d.html

  * igt@runner@aborted:
    - fi-bdw-5557u:       NOTRUN -> [FAIL][6] ([i915#1602] / [i915#2029])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-bdw-5557u/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@hangcheck:
    - fi-snb-2600:        [INCOMPLETE][7] ([i915#3921]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/fi-snb-2600/igt@i915_selftest@live@hangcheck.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/fi-snb-2600/igt@i915_selftest@live@hangcheck.html

  
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1602]: https://gitlab.freedesktop.org/drm/intel/issues/1602
  [i915#2029]: https://gitlab.freedesktop.org/drm/intel/issues/2029
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533


Participating hosts (47 -> 40)
------------------------------

  Additional (1): fi-kbl-x1275 
  Missing    (8): fi-ilk-m540 bat-adls-5 bat-dg1-6 fi-hsw-4200u fi-bsw-cyan bat-adlp-4 fi-ctg-p8600 fi-bdw-samus 


Build changes
-------------

  * Linux: CI_DRM_10557 -> Patchwork_20976

  CI-20190529: 20190529
  CI_DRM_10557: e8f764006582e44658833c07aef79c8c4b1a0758 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6198: 0f17f38c3e5e2139e59f1458c149bb7a93c88bbf @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_20976: 9eed33b42bf018cfd4bb5001106a2a7f0c468524 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

9eed33b42bf0 kernel/locking: Add context to ww_mutex_trylock.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/index.html

[-- Attachment #2: Type: text/html, Size: 4922 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
  (?)
@ 2021-09-07 14:59   ` kernel test robot
  -1 siblings, 0 replies; 51+ messages in thread
From: kernel test robot @ 2021-09-07 14:59 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx
  Cc: llvm, kbuild-all, dri-devel, Maarten Lankhorst, Peter Zijlstra,
	Ingo Molnar, Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood,
	Mark Brown

[-- Attachment #1: Type: text/plain, Size: 4201 bytes --]

Hi Maarten,

I love your patch! Perhaps something to improve:

[auto build test WARNING on regulator/for-next]
[also build test WARNING on tegra-drm/drm/tegra/for-next v5.14]
[cannot apply to tip/locking/core linus/master next-20210907]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
config: mips-buildonly-randconfig-r006-20210906 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9c476172b93367d2cb88d7d3f4b1b5b456fa6020)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install mips cross compiling tool for clang build
        # apt-get install binutils-mips-linux-gnu
        # https://github.com/0day-ci/linux/commit/1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
        git checkout 1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/locking/test-ww_mutex.c:138:7: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:172:9: note: uninitialized use occurs here
           return ret;
                  ^~~
   kernel/locking/test-ww_mutex.c:138:3: note: remove the 'if' if its condition is always false
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:125:9: note: initialize the variable 'ret' to silence this warning
           int ret;
                  ^
                   = 0
   1 warning generated.


vim +138 kernel/locking/test-ww_mutex.c

   120	
   121	static int test_aa(bool trylock)
   122	{
   123		struct ww_mutex mutex;
   124		struct ww_acquire_ctx ctx;
   125		int ret;
   126		const char *from = trylock ? "trylock" : "lock";
   127	
   128		ww_mutex_init(&mutex, &ww_class);
   129		ww_acquire_init(&ctx, &ww_class);
   130	
   131		if (!trylock) {
   132			ret = ww_mutex_lock(&mutex, &ctx);
   133			if (ret) {
   134				pr_err("%s: initial lock failed!\n", __func__);
   135				goto out;
   136			}
   137		} else {
 > 138			if (!ww_mutex_trylock(&mutex, &ctx)) {
   139				pr_err("%s: initial trylock failed!\n", __func__);
   140				goto out;
   141			}
   142		}
   143	
   144		if (ww_mutex_trylock(&mutex, NULL))  {
   145			pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
   146			ww_mutex_unlock(&mutex);
   147			ret = -EINVAL;
   148			goto out;
   149		}
   150	
   151		if (ww_mutex_trylock(&mutex, &ctx))  {
   152			pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
   153			ww_mutex_unlock(&mutex);
   154			ret = -EINVAL;
   155			goto out;
   156		}
   157	
   158		ret = ww_mutex_lock(&mutex, &ctx);
   159		if (ret != -EALREADY) {
   160			pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
   161			       __func__, ret, from);
   162			if (!ret)
   163				ww_mutex_unlock(&mutex);
   164			ret = -EINVAL;
   165			goto out;
   166		}
   167	
   168		ww_mutex_unlock(&mutex);
   169		ret = 0;
   170	out:
   171		ww_acquire_fini(&ctx);
   172		return ret;
   173	}
   174	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30233 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-07 14:59   ` kernel test robot
  0 siblings, 0 replies; 51+ messages in thread
From: kernel test robot @ 2021-09-07 14:59 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx
  Cc: llvm, kbuild-all, dri-devel, Maarten Lankhorst, Peter Zijlstra,
	Ingo Molnar, Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood,
	Mark Brown

[-- Attachment #1: Type: text/plain, Size: 4201 bytes --]

Hi Maarten,

I love your patch! Perhaps something to improve:

[auto build test WARNING on regulator/for-next]
[also build test WARNING on tegra-drm/drm/tegra/for-next v5.14]
[cannot apply to tip/locking/core linus/master next-20210907]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
config: mips-buildonly-randconfig-r006-20210906 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9c476172b93367d2cb88d7d3f4b1b5b456fa6020)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install mips cross compiling tool for clang build
        # apt-get install binutils-mips-linux-gnu
        # https://github.com/0day-ci/linux/commit/1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
        git checkout 1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/locking/test-ww_mutex.c:138:7: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:172:9: note: uninitialized use occurs here
           return ret;
                  ^~~
   kernel/locking/test-ww_mutex.c:138:3: note: remove the 'if' if its condition is always false
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:125:9: note: initialize the variable 'ret' to silence this warning
           int ret;
                  ^
                   = 0
   1 warning generated.


vim +138 kernel/locking/test-ww_mutex.c

   120	
   121	static int test_aa(bool trylock)
   122	{
   123		struct ww_mutex mutex;
   124		struct ww_acquire_ctx ctx;
   125		int ret;
   126		const char *from = trylock ? "trylock" : "lock";
   127	
   128		ww_mutex_init(&mutex, &ww_class);
   129		ww_acquire_init(&ctx, &ww_class);
   130	
   131		if (!trylock) {
   132			ret = ww_mutex_lock(&mutex, &ctx);
   133			if (ret) {
   134				pr_err("%s: initial lock failed!\n", __func__);
   135				goto out;
   136			}
   137		} else {
 > 138			if (!ww_mutex_trylock(&mutex, &ctx)) {
   139				pr_err("%s: initial trylock failed!\n", __func__);
   140				goto out;
   141			}
   142		}
   143	
   144		if (ww_mutex_trylock(&mutex, NULL))  {
   145			pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
   146			ww_mutex_unlock(&mutex);
   147			ret = -EINVAL;
   148			goto out;
   149		}
   150	
   151		if (ww_mutex_trylock(&mutex, &ctx))  {
   152			pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
   153			ww_mutex_unlock(&mutex);
   154			ret = -EINVAL;
   155			goto out;
   156		}
   157	
   158		ret = ww_mutex_lock(&mutex, &ctx);
   159		if (ret != -EALREADY) {
   160			pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
   161			       __func__, ret, from);
   162			if (!ret)
   163				ww_mutex_unlock(&mutex);
   164			ret = -EINVAL;
   165			goto out;
   166		}
   167	
   168		ww_mutex_unlock(&mutex);
   169		ret = 0;
   170	out:
   171		ww_acquire_fini(&ctx);
   172		return ret;
   173	}
   174	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30233 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-07 14:59   ` kernel test robot
  0 siblings, 0 replies; 51+ messages in thread
From: kernel test robot @ 2021-09-07 14:59 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4312 bytes --]

Hi Maarten,

I love your patch! Perhaps something to improve:

[auto build test WARNING on regulator/for-next]
[also build test WARNING on tegra-drm/drm/tegra/for-next v5.14]
[cannot apply to tip/locking/core linus/master next-20210907]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
config: mips-buildonly-randconfig-r006-20210906 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9c476172b93367d2cb88d7d3f4b1b5b456fa6020)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install mips cross compiling tool for clang build
        # apt-get install binutils-mips-linux-gnu
        # https://github.com/0day-ci/linux/commit/1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220
        git checkout 1e66afa09b0aa7d6db3122f0312e10d36f6fa217
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/locking/test-ww_mutex.c:138:7: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:172:9: note: uninitialized use occurs here
           return ret;
                  ^~~
   kernel/locking/test-ww_mutex.c:138:3: note: remove the 'if' if its condition is always false
                   if (!ww_mutex_trylock(&mutex, &ctx)) {
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/locking/test-ww_mutex.c:125:9: note: initialize the variable 'ret' to silence this warning
           int ret;
                  ^
                   = 0
   1 warning generated.


vim +138 kernel/locking/test-ww_mutex.c

   120	
   121	static int test_aa(bool trylock)
   122	{
   123		struct ww_mutex mutex;
   124		struct ww_acquire_ctx ctx;
   125		int ret;
   126		const char *from = trylock ? "trylock" : "lock";
   127	
   128		ww_mutex_init(&mutex, &ww_class);
   129		ww_acquire_init(&ctx, &ww_class);
   130	
   131		if (!trylock) {
   132			ret = ww_mutex_lock(&mutex, &ctx);
   133			if (ret) {
   134				pr_err("%s: initial lock failed!\n", __func__);
   135				goto out;
   136			}
   137		} else {
 > 138			if (!ww_mutex_trylock(&mutex, &ctx)) {
   139				pr_err("%s: initial trylock failed!\n", __func__);
   140				goto out;
   141			}
   142		}
   143	
   144		if (ww_mutex_trylock(&mutex, NULL))  {
   145			pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
   146			ww_mutex_unlock(&mutex);
   147			ret = -EINVAL;
   148			goto out;
   149		}
   150	
   151		if (ww_mutex_trylock(&mutex, &ctx))  {
   152			pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
   153			ww_mutex_unlock(&mutex);
   154			ret = -EINVAL;
   155			goto out;
   156		}
   157	
   158		ret = ww_mutex_lock(&mutex, &ctx);
   159		if (ret != -EALREADY) {
   160			pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
   161			       __func__, ret, from);
   162			if (!ret)
   163				ww_mutex_unlock(&mutex);
   164			ret = -EINVAL;
   165			goto out;
   166		}
   167	
   168		ww_mutex_unlock(&mutex);
   169		ret = 0;
   170	out:
   171		ww_acquire_fini(&ctx);
   172		return ret;
   173	}
   174	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 30233 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for kernel/locking: Add context to ww_mutex_trylock.
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (3 preceding siblings ...)
  (?)
@ 2021-09-07 17:28 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-07 17:28 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 30271 bytes --]

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock.
URL   : https://patchwork.freedesktop.org/series/94437/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10557_full -> Patchwork_20976_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

New tests
---------

  New tests have been introduced between CI_DRM_10557_full and Patchwork_20976_full:

### New IGT tests (145) ###

  * igt@feature_discovery@chamelium:
    - Statuses : 6 skip(s)
    - Exec time: [0.0, 0.00] s

  * igt@feature_discovery@display:
    - Statuses : 7 pass(s)
    - Exec time: [0.0] s

  * igt@feature_discovery@display-2x:
    - Statuses : 1 pass(s) 6 skip(s)
    - Exec time: [0.0] s

  * igt@feature_discovery@display-3x:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@feature_discovery@display-4x:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@feature_discovery@psr1:
    - Statuses : 3 pass(s) 4 skip(s)
    - Exec time: [0.0, 0.00] s

  * igt@feature_discovery@psr2:
    - Statuses : 1 pass(s) 4 skip(s)
    - Exec time: [0.0] s

  * igt@gem_exec_fence@invalid-timeline-fence-array:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.02] s

  * igt@gem_exec_fence@syncobj-backward-timeline-chain-engines:
    - Statuses : 5 pass(s)
    - Exec time: [0.05, 0.50] s

  * igt@gem_exec_fence@syncobj-stationary-timeline-chain-engines:
    - Statuses : 5 pass(s) 1 skip(s)
    - Exec time: [0.0, 0.49] s

  * igt@gem_exec_fence@syncobj-timeline-chain-engines:
    - Statuses : 5 pass(s) 1 skip(s)
    - Exec time: [0.0, 0.14] s

  * igt@gem_exec_fence@syncobj-timeline-export:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.04] s

  * igt@gem_exec_fence@syncobj-timeline-invalid-flags:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@gem_exec_fence@syncobj-timeline-invalid-wait:
    - Statuses : 5 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@gem_exec_fence@syncobj-timeline-multiple-ext-nodes:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.02] s

  * igt@gem_exec_fence@syncobj-timeline-repeat:
    - Statuses : 7 pass(s)
    - Exec time: [0.30, 3.55] s

  * igt@gem_exec_fence@syncobj-timeline-signal:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.05] s

  * igt@gem_exec_fence@syncobj-timeline-unused-fence:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.03] s

  * igt@gem_exec_fence@syncobj-timeline-wait:
    - Statuses : 7 pass(s)
    - Exec time: [0.02, 0.17] s

  * igt@gem_mmap_offset@blt-coherency:
    - Statuses : 5 pass(s)
    - Exec time: [0.01, 0.08] s

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-a:
    - Statuses : 7 pass(s)
    - Exec time: [0.28, 1.17] s

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b:
    - Statuses : 6 pass(s)
    - Exec time: [0.53, 2.41] s

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c:
    - Statuses : 6 pass(s) 1 skip(s)
    - Exec time: [0.0, 2.28] s

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-d:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@32bits-limit:
    - Statuses : 4 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@device-signal-unordered:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@device-submit-unordered:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted:
    - Statuses : 4 pass(s)
    - Exec time: [0.10] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-submitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.10, 0.12] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-submitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-all-submitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-available-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-unsubmitted-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-multi-wait-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-available-unsubmitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-unsubmitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-all-submitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-available-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-unsubmitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@etime-single-wait-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@host-signal-ordered:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@host-signal-points:
    - Statuses : 6 pass(s)
    - Exec time: [0.01, 0.08] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-submitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-submitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted:
    - Statuses : 4 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@invalid-query-bad-pad:
    - Statuses : 3 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-illegal-handle:
    - Statuses : 6 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-one-illegal-handle:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-query-zero-handles:
    - Statuses : 7 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-bad-pad:
    - Statuses : 5 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-illegal-handle:
    - Statuses : 6 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-illegal-point:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-signal-one-illegal-handle:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-signal-zero-handles:
    - Statuses : 6 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-single-wait-all-available-unsubmitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-single-wait-all-unsubmitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-single-wait-available-unsubmitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-single-wait-unsubmitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-transfer-bad-pad:
    - Statuses : 6 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-transfer-illegal-handle:
    - Statuses : 5 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-transfer-non-existent-point:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@invalid-wait-bad-flags:
    - Statuses : 5 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-wait-illegal-handle:
    - Statuses : 6 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-wait-zero-handles:
    - Statuses : 7 pass(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-available-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-all-available-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.00] s

  * igt@syncobj_timeline@multi-wait-all-available-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-all-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-available-submitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-available-submitted-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-submitted:
    - Statuses : 4 pass(s)
    - Exec time: [0.00] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-submitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-submitted:
    - Statuses : 4 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-unsubmitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-for-submit-unsubmitted-submitted-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-signaled:
    - Statuses : 5 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@multi-wait-submitted-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@reset-during-wait-for-submit:
    - Statuses : 4 pass(s)
    - Exec time: [0.10] s

  * igt@syncobj_timeline@reset-multiple-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.00, 0.01] s

  * igt@syncobj_timeline@reset-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@reset-unsignaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@signal:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@signal-array:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@signal-point-0:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-all-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-all-available-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-all-for-submit-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@single-wait-all-for-submit-available-submitted:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-all-for-submit-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@single-wait-all-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-available-signaled:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-available-submitted:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-for-submit-available-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-for-submit-available-submitted:
    - Statuses : 7 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@single-wait-for-submit-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@single-wait-signaled:
    - Statuses : 6 pass(s)
    - Exec time: [0.0, 0.00] s

  * igt@syncobj_timeline@transfer-timeline-point:
    - Statuses : 5 pass(s)
    - Exec time: [0.0, 0.01] s

  * igt@syncobj_timeline@wait-all-complex:
    - Statuses : 7 pass(s)
    - Exec time: [0.21, 0.23] s

  * igt@syncobj_timeline@wait-all-delayed-signal:
    - Statuses : 7 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@wait-all-for-submit-complex:
    - Statuses : 3 pass(s)
    - Exec time: [0.22] s

  * igt@syncobj_timeline@wait-all-for-submit-delayed-submit:
    - Statuses :
    - Exec time: [None] s

  * igt@syncobj_timeline@wait-all-for-submit-snapshot:
    - Statuses : 7 pass(s)
    - Exec time: [0.08, 0.09] s

  * igt@syncobj_timeline@wait-all-interrupted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@wait-all-snapshot:
    - Statuses : 6 pass(s)
    - Exec time: [0.08, 0.09] s

  * igt@syncobj_timeline@wait-any-complex:
    - Statuses : 6 pass(s)
    - Exec time: [0.06, 0.09] s

  * igt@syncobj_timeline@wait-any-interrupted:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@wait-any-snapshot:
    - Statuses : 6 pass(s)
    - Exec time: [0.08, 0.09] s

  * igt@syncobj_timeline@wait-delayed-signal:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@wait-for-submit-complex:
    - Statuses : 4 pass(s)
    - Exec time: [0.06, 0.07] s

  * igt@syncobj_timeline@wait-for-submit-delayed-submit:
    - Statuses : 6 pass(s)
    - Exec time: [0.10, 0.11] s

  * igt@syncobj_timeline@wait-for-submit-snapshot:
    - Statuses : 6 pass(s)
    - Exec time: [0.08, 0.09] s

  

Known issues
------------

  Here are the changes found in Patchwork_20976_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_create@create-massive:
    - shard-snb:          NOTRUN -> [DMESG-WARN][1] ([i915#3002]) +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-snb7/igt@gem_create@create-massive.html
    - shard-tglb:         NOTRUN -> [DMESG-WARN][2] ([i915#3002])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@gem_create@create-massive.html

  * igt@gem_ctx_persistence@engines-mixed:
    - shard-snb:          NOTRUN -> [SKIP][3] ([fdo#109271] / [i915#1099]) +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-snb7/igt@gem_ctx_persistence@engines-mixed.html

  * igt@gem_eio@unwedge-stress:
    - shard-skl:          [PASS][4] -> [TIMEOUT][5] ([i915#2369] / [i915#3063])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-skl8/igt@gem_eio@unwedge-stress.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl9/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_fair@basic-pace@rcs0:
    - shard-tglb:         [PASS][6] -> [FAIL][7] ([i915#2842])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-tglb2/igt@gem_exec_fair@basic-pace@rcs0.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb6/igt@gem_exec_fair@basic-pace@rcs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-tglb:         NOTRUN -> [FAIL][8] ([i915#2842])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_huc_copy@huc-copy:
    - shard-apl:          NOTRUN -> [SKIP][9] ([fdo#109271] / [i915#2190])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl2/igt@gem_huc_copy@huc-copy.html

  * igt@gem_userptr_blits@coherency-sync:
    - shard-tglb:         NOTRUN -> [SKIP][10] ([fdo#110542])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@gem_userptr_blits@coherency-sync.html

  * igt@gem_userptr_blits@dmabuf-sync:
    - shard-apl:          NOTRUN -> [SKIP][11] ([fdo#109271] / [i915#3323])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl7/igt@gem_userptr_blits@dmabuf-sync.html

  * igt@gem_userptr_blits@input-checking:
    - shard-apl:          NOTRUN -> [DMESG-WARN][12] ([i915#3002])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl1/igt@gem_userptr_blits@input-checking.html

  * igt@gem_userptr_blits@unsync-unmap-after-close:
    - shard-tglb:         NOTRUN -> [SKIP][13] ([i915#3297])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@gem_userptr_blits@unsync-unmap-after-close.html

  * igt@gen9_exec_parse@bb-chained:
    - shard-iclb:         NOTRUN -> [SKIP][14] ([i915#2856])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb2/igt@gen9_exec_parse@bb-chained.html

  * igt@gen9_exec_parse@valid-registers:
    - shard-tglb:         NOTRUN -> [SKIP][15] ([i915#2856]) +2 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@gen9_exec_parse@valid-registers.html

  * igt@i915_pm_rpm@dpms-non-lpsp:
    - shard-tglb:         NOTRUN -> [SKIP][16] ([fdo#111644] / [i915#1397] / [i915#2411])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@i915_pm_rpm@dpms-non-lpsp.html

  * igt@i915_pm_rpm@system-suspend:
    - shard-skl:          [PASS][17] -> [INCOMPLETE][18] ([i915#151])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-skl2/igt@i915_pm_rpm@system-suspend.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl10/igt@i915_pm_rpm@system-suspend.html

  * igt@i915_suspend@forcewake:
    - shard-apl:          [PASS][19] -> [DMESG-WARN][20] ([i915#180]) +1 similar issue
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-apl8/igt@i915_suspend@forcewake.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl8/igt@i915_suspend@forcewake.html

  * igt@kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip:
    - shard-skl:          NOTRUN -> [SKIP][21] ([fdo#109271] / [i915#3777])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl7/igt@kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip.html

  * igt@kms_big_fb@y-tiled-64bpp-rotate-180:
    - shard-iclb:         [PASS][22] -> [DMESG-WARN][23] ([i915#3621])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-iclb5/igt@kms_big_fb@y-tiled-64bpp-rotate-180.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb1/igt@kms_big_fb@y-tiled-64bpp-rotate-180.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip:
    - shard-apl:          NOTRUN -> [SKIP][24] ([fdo#109271] / [i915#3777]) +1 similar issue
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl3/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180:
    - shard-tglb:         NOTRUN -> [SKIP][25] ([fdo#111615])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180.html

  * igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs:
    - shard-skl:          NOTRUN -> [SKIP][26] ([fdo#109271] / [i915#3886])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl7/igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][27] ([fdo#109271] / [i915#3886]) +8 similar issues
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl7/igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-b-random-ccs-data-y_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][28] ([i915#3689]) +6 similar issues
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@kms_ccs@pipe-b-random-ccs-data-y_tiled_ccs.html

  * igt@kms_ccs@pipe-d-bad-aux-stride-yf_tiled_ccs:
    - shard-iclb:         NOTRUN -> [SKIP][29] ([fdo#109278])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb2/igt@kms_ccs@pipe-d-bad-aux-stride-yf_tiled_ccs.html

  * igt@kms_cdclk@mode-transition:
    - shard-apl:          NOTRUN -> [SKIP][30] ([fdo#109271]) +260 similar issues
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl3/igt@kms_cdclk@mode-transition.html

  * igt@kms_color_chamelium@pipe-a-ctm-0-5:
    - shard-apl:          NOTRUN -> [SKIP][31] ([fdo#109271] / [fdo#111827]) +21 similar issues
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl1/igt@kms_color_chamelium@pipe-a-ctm-0-5.html

  * igt@kms_color_chamelium@pipe-a-ctm-blue-to-red:
    - shard-snb:          NOTRUN -> [SKIP][32] ([fdo#109271] / [fdo#111827]) +9 similar issues
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-snb7/igt@kms_color_chamelium@pipe-a-ctm-blue-to-red.html

  * igt@kms_color_chamelium@pipe-b-ctm-max:
    - shard-skl:          NOTRUN -> [SKIP][33] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl7/igt@kms_color_chamelium@pipe-b-ctm-max.html

  * igt@kms_color_chamelium@pipe-d-ctm-max:
    - shard-tglb:         NOTRUN -> [SKIP][34] ([fdo#109284] / [fdo#111827]) +3 similar issues
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@kms_color_chamelium@pipe-d-ctm-max.html

  * igt@kms_content_protection@atomic:
    - shard-tglb:         NOTRUN -> [SKIP][35] ([fdo#111828])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb5/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@dp-mst-lic-type-1:
    - shard-tglb:         NOTRUN -> [SKIP][36] ([i915#3116]) +1 similar issue
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@kms_content_protection@dp-mst-lic-type-1.html

  * igt@kms_content_protection@uevent:
    - shard-apl:          NOTRUN -> [FAIL][37] ([i915#2105])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-apl3/igt@kms_content_protection@uevent.html

  * igt@kms_cursor_crc@pipe-a-cursor-suspend:
    - shard-tglb:         [PASS][38] -> [INCOMPLETE][39] ([i915#2411] / [i915#2828] / [i915#456])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-tglb6/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb7/igt@kms_cursor_crc@pipe-a-cursor-suspend.html

  * igt@kms_cursor_crc@pipe-b-cursor-32x32-onscreen:
    - shard-tglb:         NOTRUN -> [SKIP][40] ([i915#3319])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@kms_cursor_crc@pipe-b-cursor-32x32-onscreen.html

  * igt@kms_cursor_crc@pipe-d-cursor-32x10-rapid-movement:
    - shard-tglb:         NOTRUN -> [SKIP][41] ([i915#3359])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@kms_cursor_crc@pipe-d-cursor-32x10-rapid-movement.html

  * igt@kms_cursor_legacy@cursorb-vs-flipb-atomic:
    - shard-tglb:         NOTRUN -> [SKIP][42] ([fdo#111825]) +14 similar issues
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb2/igt@kms_cursor_legacy@cursorb-vs-flipb-atomic.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-skl:          [PASS][43] -> [FAIL][44] ([i915#2346] / [i915#533])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-skl3/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@pipe-d-torture-move:
    - shard-skl:          NOTRUN -> [SKIP][45] ([fdo#109271]) +38 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl7/igt@kms_cursor_legacy@pipe-d-torture-move.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-skl:          [PASS][46] -> [INCOMPLETE][47] ([i915#198])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-skl3/igt@kms_fbcon_fbt@psr-suspend.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl5/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_flip@2x-flip-vs-suspend-interruptible:
    - shard-iclb:         NOTRUN -> [SKIP][48] ([fdo#109274])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb2/igt@kms_flip@2x-flip-vs-suspend-interruptible.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1:
    - shard-skl:          [PASS][49] -> [FAIL][50] ([i915#79])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-skl10/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-skl8/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile:
    - shard-iclb:         [PASS][51] -> [SKIP][52] ([i915#3701])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-iclb4/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb2/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite:
    - shard-iclb:         NOTRUN -> [SKIP][53] ([fdo#109280])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-iclb2/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-suspend:
    - shard-tglb:         [PASS][54] -> [INCOMPLETE][55] ([i915#2411] / [i915#456]) +1 similar issue
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10557/shard-tglb3/igt@kms_frontbuffer_tracking@psr-suspend.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/shard-tglb7/igt@kms_frontbuffer_tracking@psr-suspend.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20976/index.html

[-- Attachment #2: Type: text/html, Size: 36461 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-08 10:14   ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-08 10:14 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
> i915 will soon gain an eviction path that trylock a whole lot of locks
> for eviction, getting dmesg failures like below:
> 
> BUG: MAX_LOCK_DEPTH too low!
> turning off the locking correctness validator.
> depth: 48  max: 48!
> 48 locks held by i915_selftest/5776:
>  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> ...
>  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> INFO: lockdep is turned off.

> As an intermediate solution, add an acquire context to ww_mutex_trylock,
> which allows us to do proper nesting annotations on the trylocks, making
> the above lockdep splat disappear.

Fair enough I suppose.

> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @lock: mutex to lock
> + * @ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> +{
> +	bool locked;
> +
> +	if (!ctx)
> +		return mutex_trylock(&ww->base);
> +
> +#ifdef CONFIG_DEBUG_MUTEXES
> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> +#endif
> +
> +	preempt_disable();
> +	locked = __mutex_trylock(&ww->base);
> +
> +	if (locked) {
> +		ww_mutex_set_context_fastpath(ww, ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> +	}
> +	preempt_enable();
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);

You'll need a similar hunk in ww_rt_mutex.c

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-08 10:14   ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-08 10:14 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
> i915 will soon gain an eviction path that trylock a whole lot of locks
> for eviction, getting dmesg failures like below:
> 
> BUG: MAX_LOCK_DEPTH too low!
> turning off the locking correctness validator.
> depth: 48  max: 48!
> 48 locks held by i915_selftest/5776:
>  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> ...
>  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> INFO: lockdep is turned off.

> As an intermediate solution, add an acquire context to ww_mutex_trylock,
> which allows us to do proper nesting annotations on the trylocks, making
> the above lockdep splat disappear.

Fair enough I suppose.

> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @lock: mutex to lock
> + * @ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> +{
> +	bool locked;
> +
> +	if (!ctx)
> +		return mutex_trylock(&ww->base);
> +
> +#ifdef CONFIG_DEBUG_MUTEXES
> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> +#endif
> +
> +	preempt_disable();
> +	locked = __mutex_trylock(&ww->base);
> +
> +	if (locked) {
> +		ww_mutex_set_context_fastpath(ww, ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> +	}
> +	preempt_enable();
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);

You'll need a similar hunk in ww_rt_mutex.c

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-08 10:14   ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-08 18:30     ` Daniel Vetter
  -1 siblings, 0 replies; 51+ messages in thread
From: Daniel Vetter @ 2021-09-08 18:30 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Maarten Lankhorst, intel-gfx, dri-devel, Ingo Molnar,
	Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown,
	linux-kernel

On Wed, Sep 08, 2021 at 12:14:23PM +0200, Peter Zijlstra wrote:
> On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
> > i915 will soon gain an eviction path that trylock a whole lot of locks
> > for eviction, getting dmesg failures like below:
> > 
> > BUG: MAX_LOCK_DEPTH too low!
> > turning off the locking correctness validator.
> > depth: 48  max: 48!
> > 48 locks held by i915_selftest/5776:
> >  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
> >  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
> >  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
> >  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
> >  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> > ...
> >  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> > INFO: lockdep is turned off.
> 
> > As an intermediate solution, add an acquire context to ww_mutex_trylock,
> > which allows us to do proper nesting annotations on the trylocks, making
> > the above lockdep splat disappear.
> 
> Fair enough I suppose.

What's maybe missing from the commit message
- we'll probably use this for ttm too eventually
- even when we add full ww_mutex locking we'll still have the trylock
  fastpath. This is because we have a lock inversion against list locks in
  these eviction paths, and the slow path unroll to drop that list lock is
  a bit nasty (and defintely expensive).

iow even long term this here is needed in some form I think.
-Daniel

> 
> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @lock: mutex to lock
> > + * @ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int __sched
> > +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> > +{
> > +	bool locked;
> > +
> > +	if (!ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +#ifdef CONFIG_DEBUG_MUTEXES
> > +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> > +#endif
> > +
> > +	preempt_disable();
> > +	locked = __mutex_trylock(&ww->base);
> > +
> > +	if (locked) {
> > +		ww_mutex_set_context_fastpath(ww, ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> > +	}
> > +	preempt_enable();
> > +
> > +	return locked;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> 
> You'll need a similar hunk in ww_rt_mutex.c

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-08 18:30     ` Daniel Vetter
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Vetter @ 2021-09-08 18:30 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Maarten Lankhorst, intel-gfx, dri-devel, Ingo Molnar,
	Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown,
	linux-kernel

On Wed, Sep 08, 2021 at 12:14:23PM +0200, Peter Zijlstra wrote:
> On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
> > i915 will soon gain an eviction path that trylock a whole lot of locks
> > for eviction, getting dmesg failures like below:
> > 
> > BUG: MAX_LOCK_DEPTH too low!
> > turning off the locking correctness validator.
> > depth: 48  max: 48!
> > 48 locks held by i915_selftest/5776:
> >  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
> >  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
> >  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
> >  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
> >  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> > ...
> >  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> > INFO: lockdep is turned off.
> 
> > As an intermediate solution, add an acquire context to ww_mutex_trylock,
> > which allows us to do proper nesting annotations on the trylocks, making
> > the above lockdep splat disappear.
> 
> Fair enough I suppose.

What's maybe missing from the commit message
- we'll probably use this for ttm too eventually
- even when we add full ww_mutex locking we'll still have the trylock
  fastpath. This is because we have a lock inversion against list locks in
  these eviction paths, and the slow path unroll to drop that list lock is
  a bit nasty (and defintely expensive).

iow even long term this here is needed in some form I think.
-Daniel

> 
> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @lock: mutex to lock
> > + * @ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int __sched
> > +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> > +{
> > +	bool locked;
> > +
> > +	if (!ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +#ifdef CONFIG_DEBUG_MUTEXES
> > +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> > +#endif
> > +
> > +	preempt_disable();
> > +	locked = __mutex_trylock(&ww->base);
> > +
> > +	if (locked) {
> > +		ww_mutex_set_context_fastpath(ww, ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> > +	}
> > +	preempt_enable();
> > +
> > +	return locked;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> 
> You'll need a similar hunk in ww_rt_mutex.c

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-08 10:14   ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-09  5:38     ` Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-09  5:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Op 08-09-2021 om 12:14 schreef Peter Zijlstra:
> On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
>> i915 will soon gain an eviction path that trylock a whole lot of locks
>> for eviction, getting dmesg failures like below:
>>
>> BUG: MAX_LOCK_DEPTH too low!
>> turning off the locking correctness validator.
>> depth: 48  max: 48!
>> 48 locks held by i915_selftest/5776:
>>  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>>  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>>  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>>  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>>  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>> ...
>>  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>> INFO: lockdep is turned off.
>> As an intermediate solution, add an acquire context to ww_mutex_trylock,
>> which allows us to do proper nesting annotations on the trylocks, making
>> the above lockdep splat disappear.
> Fair enough I suppose.
>
>> +/**
>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>> + * @lock: mutex to lock
>> + * @ctx: optional w/w acquire context
>> + *
>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>> + *
>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
>> + *
>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>> + */
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
>> +{
>> +	bool locked;
>> +
>> +	if (!ctx)
>> +		return mutex_trylock(&ww->base);
>> +
>> +#ifdef CONFIG_DEBUG_MUTEXES
>> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
>> +#endif
>> +
>> +	preempt_disable();
>> +	locked = __mutex_trylock(&ww->base);
>> +
>> +	if (locked) {
>> +		ww_mutex_set_context_fastpath(ww, ctx);
>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
>> +	}
>> +	preempt_enable();
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
> You'll need a similar hunk in ww_rt_mutex.c

What tree has that file?


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-09  5:38     ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-09  5:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Op 08-09-2021 om 12:14 schreef Peter Zijlstra:
> On Tue, Sep 07, 2021 at 03:20:44PM +0200, Maarten Lankhorst wrote:
>> i915 will soon gain an eviction path that trylock a whole lot of locks
>> for eviction, getting dmesg failures like below:
>>
>> BUG: MAX_LOCK_DEPTH too low!
>> turning off the locking correctness validator.
>> depth: 48  max: 48!
>> 48 locks held by i915_selftest/5776:
>>  #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>>  #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>>  #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>>  #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>>  #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>  #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>> ...
>>  #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>  #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>> INFO: lockdep is turned off.
>> As an intermediate solution, add an acquire context to ww_mutex_trylock,
>> which allows us to do proper nesting annotations on the trylocks, making
>> the above lockdep splat disappear.
> Fair enough I suppose.
>
>> +/**
>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>> + * @lock: mutex to lock
>> + * @ctx: optional w/w acquire context
>> + *
>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>> + *
>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
>> + *
>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>> + */
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
>> +{
>> +	bool locked;
>> +
>> +	if (!ctx)
>> +		return mutex_trylock(&ww->base);
>> +
>> +#ifdef CONFIG_DEBUG_MUTEXES
>> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
>> +#endif
>> +
>> +	preempt_disable();
>> +	locked = __mutex_trylock(&ww->base);
>> +
>> +	if (locked) {
>> +		ww_mutex_set_context_fastpath(ww, ctx);
>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
>> +	}
>> +	preempt_enable();
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
> You'll need a similar hunk in ww_rt_mutex.c

What tree has that file?


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-09  5:38     ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-09  8:22       ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-09  8:22 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 09, 2021 at 07:38:06AM +0200, Maarten Lankhorst wrote:

> > You'll need a similar hunk in ww_rt_mutex.c
> 
> What tree has that file?

Linus' tree should have it. Per commit:

  f8635d509d80 ("locking/ww_mutex: Implement rtmutex based ww_mutex API functions")

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-09  8:22       ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-09  8:22 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 09, 2021 at 07:38:06AM +0200, Maarten Lankhorst wrote:

> > You'll need a similar hunk in ww_rt_mutex.c
> 
> What tree has that file?

Linus' tree should have it. Per commit:

  f8635d509d80 ("locking/ww_mutex: Implement rtmutex based ww_mutex API functions")

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-09  8:22       ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-09  9:32         ` Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-09  9:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 09-09-2021 om 10:22 schreef Peter Zijlstra:
> On Thu, Sep 09, 2021 at 07:38:06AM +0200, Maarten Lankhorst wrote:
>
>>> You'll need a similar hunk in ww_rt_mutex.c
>> What tree has that file?
> Linus' tree should have it. Per commit:
>
>   f8635d509d80 ("locking/ww_mutex: Implement rtmutex based ww_mutex API functions")

Ah yeah, it seems the drm integration tree missed it.

I only compile tested it against PREEMPT_RT, though it seems locking_selftests and fs/inode.c don't build correctly for me.

Improved patch below.

Also hopefully addressed Daniel's concerns.

-------8<------
From d7e867f26b7e2553b0e5b9b5b87a284467b85846 Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date: Fri, 3 Sep 2021 10:59:49 +0200
Subject: [PATCH] kernel/locking: Add context to ww_mutex_trylock, v2.

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

BUG: MAX_LOCK_DEPTH too low!
turning off the locking correctness validator.
depth: 48  max: 48!
48 locks held by i915_selftest/5776:
 #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
 #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
 #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
 #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
 #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
...
 #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority,
but it requires a rework of the entire driver, which can only be
done one step at a time.

As an intermediate solution, add an acquire context to ww_mutex_trylock,
which allows us to do proper nesting annotations on the trylocks, making
the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

TTM may be another user for this, where we could lock a buffer in a
fastpath with list locks held, without dropping all locks we hold.

Changes since v1:
- Rebase on top of the ww_rt_mutex rework.
- Add extern to ww_mutex_trylock header definition.
- Expand commit message slightly.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org
---
 drivers/gpu/drm/drm_modeset_lock.c |  2 +-
 drivers/regulator/core.c           |  2 +-
 include/linux/dma-resv.h           |  2 +-
 include/linux/ww_mutex.h           | 15 +-----
 kernel/locking/mutex.c             | 38 +++++++++++++
 kernel/locking/test-ww_mutex.c     | 86 ++++++++++++++++++++++--------
 kernel/locking/ww_rt_mutex.c       | 12 +++++
 lib/locking-selftest.c             |  2 +-
 8 files changed, 121 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fcfe1a03c4a1..bf8a6e823a15 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba8a191..f4d441b1a8bf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index 9100dd3dc21f..5de7956818a5 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -262,7 +262,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 29db736af86d..bb763085479a 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -28,12 +28,10 @@
 #ifndef CONFIG_PREEMPT_RT
 #define WW_MUTEX_BASE			mutex
 #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
 #else
 #define WW_MUTEX_BASE			rt_mutex
 #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
 #endif
 
@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return ww_mutex_base_trylock(&lock->base);
-}
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+					 struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index d456579d0952..791c28005eef 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @lock: mutex to lock
+ * @ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int __sched
+ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
+{
+	bool locked;
+
+	if (!ctx)
+		return mutex_trylock(&ww->base);
+
+#ifdef CONFIG_DEBUG_MUTEXES
+	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
+#endif
+
+	preempt_disable();
+	locked = __mutex_trylock(&ww->base);
+
+	if (locked) {
+		ww_mutex_set_context_fastpath(ww, ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
+	}
+	preempt_enable();
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 3e82f449b4ff..d63ac411f367 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 3f1fff7d2780..c4cb863edb4c 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 	return ret;
 }
 
+int __sched
+ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
+{
+	int locked = rt_mutex_trylock(&lock->base);
+
+	if (locked && ctx)
+		ww_mutex_set_context_fastpath(lock, ctx);
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 int __sched
 ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 {
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 161108e5d2fe..71652e1c397c 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 
-- 
2.33.0



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-09  9:32         ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-09  9:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 09-09-2021 om 10:22 schreef Peter Zijlstra:
> On Thu, Sep 09, 2021 at 07:38:06AM +0200, Maarten Lankhorst wrote:
>
>>> You'll need a similar hunk in ww_rt_mutex.c
>> What tree has that file?
> Linus' tree should have it. Per commit:
>
>   f8635d509d80 ("locking/ww_mutex: Implement rtmutex based ww_mutex API functions")

Ah yeah, it seems the drm integration tree missed it.

I only compile tested it against PREEMPT_RT, though it seems locking_selftests and fs/inode.c don't build correctly for me.

Improved patch below.

Also hopefully addressed Daniel's concerns.

-------8<------
From d7e867f26b7e2553b0e5b9b5b87a284467b85846 Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date: Fri, 3 Sep 2021 10:59:49 +0200
Subject: [PATCH] kernel/locking: Add context to ww_mutex_trylock, v2.

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

BUG: MAX_LOCK_DEPTH too low!
turning off the locking correctness validator.
depth: 48  max: 48!
48 locks held by i915_selftest/5776:
 #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
 #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
 #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
 #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
 #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
...
 #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
 #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority,
but it requires a rework of the entire driver, which can only be
done one step at a time.

As an intermediate solution, add an acquire context to ww_mutex_trylock,
which allows us to do proper nesting annotations on the trylocks, making
the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

TTM may be another user for this, where we could lock a buffer in a
fastpath with list locks held, without dropping all locks we hold.

Changes since v1:
- Rebase on top of the ww_rt_mutex rework.
- Add extern to ww_mutex_trylock header definition.
- Expand commit message slightly.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org
---
 drivers/gpu/drm/drm_modeset_lock.c |  2 +-
 drivers/regulator/core.c           |  2 +-
 include/linux/dma-resv.h           |  2 +-
 include/linux/ww_mutex.h           | 15 +-----
 kernel/locking/mutex.c             | 38 +++++++++++++
 kernel/locking/test-ww_mutex.c     | 86 ++++++++++++++++++++++--------
 kernel/locking/ww_rt_mutex.c       | 12 +++++
 lib/locking-selftest.c             |  2 +-
 8 files changed, 121 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fcfe1a03c4a1..bf8a6e823a15 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba8a191..f4d441b1a8bf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index 9100dd3dc21f..5de7956818a5 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -262,7 +262,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 29db736af86d..bb763085479a 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -28,12 +28,10 @@
 #ifndef CONFIG_PREEMPT_RT
 #define WW_MUTEX_BASE			mutex
 #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
 #else
 #define WW_MUTEX_BASE			rt_mutex
 #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
 #endif
 
@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return ww_mutex_base_trylock(&lock->base);
-}
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+					 struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index d456579d0952..791c28005eef 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @lock: mutex to lock
+ * @ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int __sched
+ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
+{
+	bool locked;
+
+	if (!ctx)
+		return mutex_trylock(&ww->base);
+
+#ifdef CONFIG_DEBUG_MUTEXES
+	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
+#endif
+
+	preempt_disable();
+	locked = __mutex_trylock(&ww->base);
+
+	if (locked) {
+		ww_mutex_set_context_fastpath(ww, ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
+	}
+	preempt_enable();
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 3e82f449b4ff..d63ac411f367 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 3f1fff7d2780..c4cb863edb4c 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 	return ret;
 }
 
+int __sched
+ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
+{
+	int locked = rt_mutex_trylock(&lock->base);
+
+	if (locked && ctx)
+		ww_mutex_set_context_fastpath(lock, ctx);
+
+	return locked;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 int __sched
 ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 {
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 161108e5d2fe..71652e1c397c 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 
-- 
2.33.0



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for kernel/locking: Add context to ww_mutex_trylock. (rev2)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (5 preceding siblings ...)
  (?)
@ 2021-09-09  9:50 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-09  9:50 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev2)
URL   : https://patchwork.freedesktop.org/series/94437/
State : failure

== Summary ==

Patch is empty.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-09  9:32         ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-10 15:02           ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-10 15:02 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:
> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
> index d456579d0952..791c28005eef 100644
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @lock: mutex to lock
> + * @ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> +{
> +	bool locked;
> +
> +	if (!ctx)
> +		return mutex_trylock(&ww->base);
> +
> +#ifdef CONFIG_DEBUG_MUTEXES
> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> +#endif
> +
> +	preempt_disable();
> +	locked = __mutex_trylock(&ww->base);
> +
> +	if (locked) {
> +		ww_mutex_set_context_fastpath(ww, ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> +	}
> +	preempt_enable();
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)

> diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
> index 3f1fff7d2780..c4cb863edb4c 100644
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  	return ret;
>  }
>  
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
> +{
> +	int locked = rt_mutex_trylock(&lock->base);
> +
> +	if (locked && ctx)
> +		ww_mutex_set_context_fastpath(lock, ctx);
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  int __sched
>  ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>  {

That doesn't look right, how's this for you?

---
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
 	return owner & MUTEX_FLAGS;
 }
 
+/*
+ * Returns: __mutex_owner(lock) on failure or NULL on success.
+ */
 static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
 {
 	unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,47 @@ __ww_mutex_lock(struct mutex *lock, unsi
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @ww: mutex to lock
+ * @ww_ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
+{
+	if (!ww_ctx)
+		return mutex_trylock(&ww->base);
+
+	MUTEX_WARN_ON(ww->base.magic != &ww->base);
+
+	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
+		return -EALREADY;
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__mutex_trylock(&ww->base)) {
+		ww_mutex_set_context_fastpath(ww, ww_ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -9,6 +9,34 @@
 #define WW_RT
 #include "rtmutex.c"
 
+int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
+{
+	struct rt_mutex *rtm = &lock->base;
+
+	if (!ww_ctx)
+		return rt_mutex_trylock(rtm);
+
+	if (unlikely(ww_ctx == READ_ONCE(lock->ctx)))
+		return -EALREADY;
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__rt_mutex_trylock(&rtm->rtmutex)) {
+		ww_mutex_set_context_fastpath(lock, ww_ctx);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 static int __sched
 __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 		   unsigned int state, unsigned long ip)

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-10 15:02           ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-10 15:02 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:
> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
> index d456579d0952..791c28005eef 100644
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @lock: mutex to lock
> + * @ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
> +{
> +	bool locked;
> +
> +	if (!ctx)
> +		return mutex_trylock(&ww->base);
> +
> +#ifdef CONFIG_DEBUG_MUTEXES
> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
> +#endif
> +
> +	preempt_disable();
> +	locked = __mutex_trylock(&ww->base);
> +
> +	if (locked) {
> +		ww_mutex_set_context_fastpath(ww, ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
> +	}
> +	preempt_enable();
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)

> diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
> index 3f1fff7d2780..c4cb863edb4c 100644
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  	return ret;
>  }
>  
> +int __sched
> +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
> +{
> +	int locked = rt_mutex_trylock(&lock->base);
> +
> +	if (locked && ctx)
> +		ww_mutex_set_context_fastpath(lock, ctx);
> +
> +	return locked;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  int __sched
>  ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>  {

That doesn't look right, how's this for you?

---
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
 	return owner & MUTEX_FLAGS;
 }
 
+/*
+ * Returns: __mutex_owner(lock) on failure or NULL on success.
+ */
 static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
 {
 	unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,47 @@ __ww_mutex_lock(struct mutex *lock, unsi
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @ww: mutex to lock
+ * @ww_ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
+{
+	if (!ww_ctx)
+		return mutex_trylock(&ww->base);
+
+	MUTEX_WARN_ON(ww->base.magic != &ww->base);
+
+	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
+		return -EALREADY;
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__mutex_trylock(&ww->base)) {
+		ww_mutex_set_context_fastpath(ww, ww_ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -9,6 +9,34 @@
 #define WW_RT
 #include "rtmutex.c"
 
+int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
+{
+	struct rt_mutex *rtm = &lock->base;
+
+	if (!ww_ctx)
+		return rt_mutex_trylock(rtm);
+
+	if (unlikely(ww_ctx == READ_ONCE(lock->ctx)))
+		return -EALREADY;
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__rt_mutex_trylock(&rtm->rtmutex)) {
+		ww_mutex_set_context_fastpath(lock, ww_ctx);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 static int __sched
 __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 		   unsigned int state, unsigned long ip)

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for kernel/locking: Add context to ww_mutex_trylock. (rev3)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (6 preceding siblings ...)
  (?)
@ 2021-09-10 15:36 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-10 15:36 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: intel-gfx

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev3)
URL   : https://patchwork.freedesktop.org/series/94437/
State : failure

== Summary ==

Applying: kernel/locking: Add context to ww_mutex_trylock.
error: sha1 information is lacking or useless (kernel/locking/mutex.c).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 kernel/locking: Add context to ww_mutex_trylock.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-10 15:02           ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-10 17:27             ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-10 17:27 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Fri, Sep 10, 2021 at 05:02:54PM +0200, Peter Zijlstra wrote:

> That doesn't look right, how's this for you?

Full patch for the robots here:

https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git/commit/?h=locking/core&id=826e7b8826f0af185bb93249600533c33fd69a95

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-10 17:27             ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-10 17:27 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Fri, Sep 10, 2021 at 05:02:54PM +0200, Peter Zijlstra wrote:

> That doesn't look right, how's this for you?

Full patch for the robots here:

https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git/commit/?h=locking/core&id=826e7b8826f0af185bb93249600533c33fd69a95

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-09  9:32         ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-10 18:06           ` Mark Brown
  -1 siblings, 0 replies; 51+ messages in thread
From: Mark Brown @ 2021-09-10 18:06 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, linux-kernel,
	Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 252 bytes --]

On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:

> This is also useful in regulator_lock_nested, which may avoid dropping
> regulator_nesting_mutex in the uncontended path, so use it there.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-10 18:06           ` Mark Brown
  0 siblings, 0 replies; 51+ messages in thread
From: Mark Brown @ 2021-09-10 18:06 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, linux-kernel,
	Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 252 bytes --]

On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:

> This is also useful in regulator_lock_nested, which may avoid dropping
> regulator_nesting_mutex in the uncontended path, so use it there.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-10 15:02           ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-13  8:42             ` Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-13  8:42 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 10-09-2021 om 17:02 schreef Peter Zijlstra:
> On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:
>> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
>> index d456579d0952..791c28005eef 100644
>> --- a/kernel/locking/mutex.c
>> +++ b/kernel/locking/mutex.c
>> @@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
>>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>>  }
>>  
>> +/**
>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>> + * @lock: mutex to lock
>> + * @ctx: optional w/w acquire context
>> + *
>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>> + *
>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
>> + *
>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>> + */
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
>> +{
>> +	bool locked;
>> +
>> +	if (!ctx)
>> +		return mutex_trylock(&ww->base);
>> +
>> +#ifdef CONFIG_DEBUG_MUTEXES
>> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
>> +#endif
>> +
>> +	preempt_disable();
>> +	locked = __mutex_trylock(&ww->base);
>> +
>> +	if (locked) {
>> +		ww_mutex_set_context_fastpath(ww, ctx);
>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
>> +	}
>> +	preempt_enable();
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
>> +
>>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>>  void __sched
>>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
>> diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
>> index 3f1fff7d2780..c4cb863edb4c 100644
>> --- a/kernel/locking/ww_rt_mutex.c
>> +++ b/kernel/locking/ww_rt_mutex.c
>> @@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>>  	return ret;
>>  }
>>  
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>> +{
>> +	int locked = rt_mutex_trylock(&lock->base);
>> +
>> +	if (locked && ctx)
>> +		ww_mutex_set_context_fastpath(lock, ctx);
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
>> +
>>  int __sched
>>  ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>>  {
> That doesn't look right, how's this for you?
>
> ---
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
>  	return owner & MUTEX_FLAGS;
>  }
>  
> +/*
> + * Returns: __mutex_owner(lock) on failure or NULL on success.
> + */
>  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
>  {
>  	unsigned long owner, curr = (unsigned long)current;
> @@ -736,6 +739,47 @@ __ww_mutex_lock(struct mutex *lock, unsi
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @ww: mutex to lock
> + * @ww_ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> +{
> +	if (!ww_ctx)
> +		return mutex_trylock(&ww->base);
> +
> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> +
> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> +		return -EALREADY;

I'm not 100% sure this is a good idea, because it would make the trylock weird.
For i915 I checked manually, because I didn't want to change the function signature. This is probably the other extreme.

"if (ww_mutex_trylock())" would look correct, but actually be wrong and lead to double unlock without adjustments.
Maybe we could make a ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on failure, and 0 on success?
We could keep ww_mutex_trylock without ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))

> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;

Yeah I guess this needs fixing too. Not completely sure since trylock wouldn't do the whole
ww dance, but since it's our first lock, probably best to do so regardless so other users don't trip over it.

> +
> +	if (__mutex_trylock(&ww->base)) {
> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -9,6 +9,34 @@
>  #define WW_RT
>  #include "rtmutex.c"
>  
> +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> +{
> +	struct rt_mutex *rtm = &lock->base;
> +
> +	if (!ww_ctx)
> +		return rt_mutex_trylock(rtm);
> +
> +	if (unlikely(ww_ctx == READ_ONCE(lock->ctx)))
> +		return -EALREADY;
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  static int __sched
>  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  		   unsigned int state, unsigned long ip)



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-13  8:42             ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-13  8:42 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 10-09-2021 om 17:02 schreef Peter Zijlstra:
> On Thu, Sep 09, 2021 at 11:32:18AM +0200, Maarten Lankhorst wrote:
>> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
>> index d456579d0952..791c28005eef 100644
>> --- a/kernel/locking/mutex.c
>> +++ b/kernel/locking/mutex.c
>> @@ -736,6 +736,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
>>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>>  }
>>  
>> +/**
>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>> + * @lock: mutex to lock
>> + * @ctx: optional w/w acquire context
>> + *
>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>> + *
>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>> + * specified, -EALREADY and -EDEADLK handling may happen in calls to ww_mutex_lock.
>> + *
>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>> + */
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ctx)
>> +{
>> +	bool locked;
>> +
>> +	if (!ctx)
>> +		return mutex_trylock(&ww->base);
>> +
>> +#ifdef CONFIG_DEBUG_MUTEXES
>> +	DEBUG_LOCKS_WARN_ON(ww->base.magic != &ww->base);
>> +#endif
>> +
>> +	preempt_disable();
>> +	locked = __mutex_trylock(&ww->base);
>> +
>> +	if (locked) {
>> +		ww_mutex_set_context_fastpath(ww, ctx);
>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ctx->dep_map, _RET_IP_);
>> +	}
>> +	preempt_enable();
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
>> +
>>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>>  void __sched
>>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
>> diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
>> index 3f1fff7d2780..c4cb863edb4c 100644
>> --- a/kernel/locking/ww_rt_mutex.c
>> +++ b/kernel/locking/ww_rt_mutex.c
>> @@ -50,6 +50,18 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>>  	return ret;
>>  }
>>  
>> +int __sched
>> +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>> +{
>> +	int locked = rt_mutex_trylock(&lock->base);
>> +
>> +	if (locked && ctx)
>> +		ww_mutex_set_context_fastpath(lock, ctx);
>> +
>> +	return locked;
>> +}
>> +EXPORT_SYMBOL(ww_mutex_trylock);
>> +
>>  int __sched
>>  ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
>>  {
> That doesn't look right, how's this for you?
>
> ---
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
>  	return owner & MUTEX_FLAGS;
>  }
>  
> +/*
> + * Returns: __mutex_owner(lock) on failure or NULL on success.
> + */
>  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
>  {
>  	unsigned long owner, curr = (unsigned long)current;
> @@ -736,6 +739,47 @@ __ww_mutex_lock(struct mutex *lock, unsi
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @ww: mutex to lock
> + * @ww_ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> +{
> +	if (!ww_ctx)
> +		return mutex_trylock(&ww->base);
> +
> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> +
> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> +		return -EALREADY;

I'm not 100% sure this is a good idea, because it would make the trylock weird.
For i915 I checked manually, because I didn't want to change the function signature. This is probably the other extreme.

"if (ww_mutex_trylock())" would look correct, but actually be wrong and lead to double unlock without adjustments.
Maybe we could make a ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on failure, and 0 on success?
We could keep ww_mutex_trylock without ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))

> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;

Yeah I guess this needs fixing too. Not completely sure since trylock wouldn't do the whole
ww dance, but since it's our first lock, probably best to do so regardless so other users don't trip over it.

> +
> +	if (__mutex_trylock(&ww->base)) {
> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -9,6 +9,34 @@
>  #define WW_RT
>  #include "rtmutex.c"
>  
> +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> +{
> +	struct rt_mutex *rtm = &lock->base;
> +
> +	if (!ww_ctx)
> +		return rt_mutex_trylock(rtm);
> +
> +	if (unlikely(ww_ctx == READ_ONCE(lock->ctx)))
> +		return -EALREADY;
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  static int __sched
>  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  		   unsigned int state, unsigned long ip)



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-13  8:42             ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-14  6:50               ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-14  6:50 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:

> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @ww: mutex to lock
> > + * @ww_ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	if (!ww_ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> > +
> > +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> > +		return -EALREADY;
> 
> I'm not 100% sure this is a good idea, because it would make the
> trylock weird.  For i915 I checked manually, because I didn't want to
> change the function signature. This is probably the other extreme.
> 
> "if (ww_mutex_trylock())" would look correct, but actually be wrong
> and lead to double unlock without adjustments.  Maybe we could make a
> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
> failure, and 0 on success?  We could keep ww_mutex_trylock without
> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))

Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
the trylock anyway. Let me take this out.

> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> 
> Yeah I guess this needs fixing too. Not completely sure since trylock
> wouldn't do the whole ww dance, but since it's our first lock,
> probably best to do so regardless so other users don't trip over it.

This is actually critical, because if this trylock is the first lock
acquisition for the context, there won't be any other opportunity to
reset this value.

> > +
> > +	if (__mutex_trylock(&ww->base)) {
> > +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);

Updated version below...

---
Subject: kernel/locking: Add context to ww_mutex_trylock()
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date: Thu, 9 Sep 2021 11:32:18 +0200

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

  BUG: MAX_LOCK_DEPTH too low!
  turning off the locking correctness validator.
  depth: 48  max: 48!
  48 locks held by i915_selftest/5776:
   #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
   #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
   #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
   #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
   #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  ...
   #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority, but
it requires a rework of the entire driver, which can only be done one
step at a time.

As an intermediate solution, add an acquire context to
ww_mutex_trylock, which allows us to do proper nesting annotations on
the trylocks, making the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

TTM may be another user for this, where we could lock a buffer in a
fastpath with list locks held, without dropping all locks we hold.

[peterz: rework actual ww_mutex_trylock() implementations]
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 drivers/gpu/drm/drm_modeset_lock.c |    2 
 drivers/regulator/core.c           |    2 
 include/linux/dma-resv.h           |    2 
 include/linux/ww_mutex.h           |   15 ------
 kernel/locking/mutex.c             |   41 +++++++++++++++++
 kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
 kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
 lib/locking-selftest.c             |    2 
 8 files changed, 137 insertions(+), 38 deletions(-)

--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -28,12 +28,10 @@
 #ifndef CONFIG_PREEMPT_RT
 #define WW_MUTEX_BASE			mutex
 #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
 #else
 #define WW_MUTEX_BASE			rt_mutex
 #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
 #endif
 
@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return ww_mutex_base_trylock(&lock->base);
-}
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+					 struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
 	return owner & MUTEX_FLAGS;
 }
 
+/*
+ * Returns: __mutex_owner(lock) on failure or NULL on success.
+ */
 static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
 {
 	unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @ww: mutex to lock
+ * @ww_ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
+{
+	if (!ww_ctx)
+		return mutex_trylock(&ww->base);
+
+	MUTEX_WARN_ON(ww->base.magic != &ww->base);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__mutex_trylock(&ww->base)) {
+		ww_mutex_set_context_fastpath(ww, ww_ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -9,6 +9,31 @@
 #define WW_RT
 #include "rtmutex.c"
 
+int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
+{
+	struct rt_mutex *rtm = &lock->base;
+
+	if (!ww_ctx)
+		return rt_mutex_trylock(rtm);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__rt_mutex_trylock(&rtm->rtmutex)) {
+		ww_mutex_set_context_fastpath(lock, ww_ctx);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 static int __sched
 __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 		   unsigned int state, unsigned long ip)
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-14  6:50               ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-14  6:50 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:

> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @ww: mutex to lock
> > + * @ww_ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	if (!ww_ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> > +
> > +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> > +		return -EALREADY;
> 
> I'm not 100% sure this is a good idea, because it would make the
> trylock weird.  For i915 I checked manually, because I didn't want to
> change the function signature. This is probably the other extreme.
> 
> "if (ww_mutex_trylock())" would look correct, but actually be wrong
> and lead to double unlock without adjustments.  Maybe we could make a
> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
> failure, and 0 on success?  We could keep ww_mutex_trylock without
> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))

Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
the trylock anyway. Let me take this out.

> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> 
> Yeah I guess this needs fixing too. Not completely sure since trylock
> wouldn't do the whole ww dance, but since it's our first lock,
> probably best to do so regardless so other users don't trip over it.

This is actually critical, because if this trylock is the first lock
acquisition for the context, there won't be any other opportunity to
reset this value.

> > +
> > +	if (__mutex_trylock(&ww->base)) {
> > +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);

Updated version below...

---
Subject: kernel/locking: Add context to ww_mutex_trylock()
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date: Thu, 9 Sep 2021 11:32:18 +0200

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

  BUG: MAX_LOCK_DEPTH too low!
  turning off the locking correctness validator.
  depth: 48  max: 48!
  48 locks held by i915_selftest/5776:
   #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
   #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
   #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
   #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
   #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  ...
   #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority, but
it requires a rework of the entire driver, which can only be done one
step at a time.

As an intermediate solution, add an acquire context to
ww_mutex_trylock, which allows us to do proper nesting annotations on
the trylocks, making the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

TTM may be another user for this, where we could lock a buffer in a
fastpath with list locks held, without dropping all locks we hold.

[peterz: rework actual ww_mutex_trylock() implementations]
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 drivers/gpu/drm/drm_modeset_lock.c |    2 
 drivers/regulator/core.c           |    2 
 include/linux/dma-resv.h           |    2 
 include/linux/ww_mutex.h           |   15 ------
 kernel/locking/mutex.c             |   41 +++++++++++++++++
 kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
 kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
 lib/locking-selftest.c             |    2 
 8 files changed, 137 insertions(+), 38 deletions(-)

--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -28,12 +28,10 @@
 #ifndef CONFIG_PREEMPT_RT
 #define WW_MUTEX_BASE			mutex
 #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
 #else
 #define WW_MUTEX_BASE			rt_mutex
 #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
 #endif
 
@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return ww_mutex_base_trylock(&lock->base);
-}
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+					 struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
 	return owner & MUTEX_FLAGS;
 }
 
+/*
+ * Returns: __mutex_owner(lock) on failure or NULL on success.
+ */
 static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
 {
 	unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @ww: mutex to lock
+ * @ww_ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
+{
+	if (!ww_ctx)
+		return mutex_trylock(&ww->base);
+
+	MUTEX_WARN_ON(ww->base.magic != &ww->base);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__mutex_trylock(&ww->base)) {
+		ww_mutex_set_context_fastpath(ww, ww_ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -9,6 +9,31 @@
 #define WW_RT
 #include "rtmutex.c"
 
+int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
+{
+	struct rt_mutex *rtm = &lock->base;
+
+	if (!ww_ctx)
+		return rt_mutex_trylock(rtm);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__rt_mutex_trylock(&rtm->rtmutex)) {
+		ww_mutex_set_context_fastpath(lock, ww_ctx);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 static int __sched
 __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 		   unsigned int state, unsigned long ip)
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for kernel/locking: Add context to ww_mutex_trylock. (rev4)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (7 preceding siblings ...)
  (?)
@ 2021-09-14  9:31 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-14  9:31 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: intel-gfx

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev4)
URL   : https://patchwork.freedesktop.org/series/94437/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
3e5b7ed1e30d kernel/locking: Add context to ww_mutex_trylock.
-:9: WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#9: 
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context

-:144: CHECK:AVOID_EXTERNS: extern prototypes should be avoided in .h files
#144: FILE: include/linux/ww_mutex.h:340:
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,

-:217: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'a' - possible side-effects?
#217: FILE: kernel/locking/test-ww_mutex.c:20:
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)

-:372: WARNING:PREFER_PR_LEVEL: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(...  to printk(KERN_INFO ...
#372: FILE: kernel/locking/test-ww_mutex.c:625:
+	printk(KERN_INFO "Beginning ww mutex selftests\n");

-:405: WARNING:PREFER_PR_LEVEL: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(...  to printk(KERN_INFO ...
#405: FILE: kernel/locking/test-ww_mutex.c:665:
+	printk(KERN_INFO "All ww mutex selftests passed\n");

-:457: ERROR:MISSING_SIGN_OFF: Missing Signed-off-by: line(s)

total: 1 errors, 3 warnings, 2 checks, 332 lines checked



^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BAT: failure for kernel/locking: Add context to ww_mutex_trylock. (rev4)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (8 preceding siblings ...)
  (?)
@ 2021-09-14  9:58 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-09-14  9:58 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 5179 bytes --]

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev4)
URL   : https://patchwork.freedesktop.org/series/94437/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_10579 -> Patchwork_21036
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_21036 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_21036, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_21036:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_module_load@reload:
    - fi-icl-u2:          NOTRUN -> [INCOMPLETE][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-icl-u2/igt@i915_module_load@reload.html

  * igt@i915_selftest@live@mman:
    - fi-cfl-8109u:       NOTRUN -> [INCOMPLETE][2]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-cfl-8109u/igt@i915_selftest@live@mman.html
    - fi-rkl-11600:       NOTRUN -> [INCOMPLETE][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-rkl-11600/igt@i915_selftest@live@mman.html

  
#### Warnings ####

  * igt@i915_module_load@reload:
    - fi-icl-y:           [TIMEOUT][4] -> [INCOMPLETE][5]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10579/fi-icl-y/igt@i915_module_load@reload.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-icl-y/igt@i915_module_load@reload.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@i915_module_load@reload:
    - {fi-jsl-1}:         [TIMEOUT][6] -> [INCOMPLETE][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10579/fi-jsl-1/igt@i915_module_load@reload.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-jsl-1/igt@i915_module_load@reload.html

  * igt@runner@aborted:
    - {fi-ehl-2}:         NOTRUN -> [FAIL][8]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-ehl-2/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_21036 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@runner@aborted:
    - fi-rkl-11600:       NOTRUN -> [FAIL][9] ([i915#3928])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-rkl-11600/igt@runner@aborted.html
    - fi-cfl-8109u:       NOTRUN -> [FAIL][10] ([i915#2426] / [i915#3363])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-cfl-8109u/igt@runner@aborted.html
    - fi-icl-u2:          NOTRUN -> [FAIL][11] ([i915#2426] / [i915#3363] / [i915#3690])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-icl-u2/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@core_hotunplug@unbind-rebind:
    - fi-icl-u2:          [INCOMPLETE][12] -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10579/fi-icl-u2/igt@core_hotunplug@unbind-rebind.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-icl-u2/igt@core_hotunplug@unbind-rebind.html
    - fi-rkl-11600:       [INCOMPLETE][14] -> [PASS][15]
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10579/fi-rkl-11600/igt@core_hotunplug@unbind-rebind.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-rkl-11600/igt@core_hotunplug@unbind-rebind.html
    - fi-cfl-8109u:       [INCOMPLETE][16] -> [PASS][17]
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10579/fi-cfl-8109u/igt@core_hotunplug@unbind-rebind.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/fi-cfl-8109u/igt@core_hotunplug@unbind-rebind.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [i915#2426]: https://gitlab.freedesktop.org/drm/intel/issues/2426
  [i915#3363]: https://gitlab.freedesktop.org/drm/intel/issues/3363
  [i915#3690]: https://gitlab.freedesktop.org/drm/intel/issues/3690
  [i915#3928]: https://gitlab.freedesktop.org/drm/intel/issues/3928


Participating hosts (39 -> 36)
------------------------------

  Missing    (3): fi-tgl-1115g4 fi-bsw-cyan fi-bdw-samus 


Build changes
-------------

  * Linux: CI_DRM_10579 -> Patchwork_21036

  CI-20190529: 20190529
  CI_DRM_10579: a83151fa02e8d3e90729db21ee0e3830ff8c9565 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6209: 07d6594ed02f55b68d64fa6dd7f80cfbc1ce4ef8 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_21036: 3e5b7ed1e30dd3a8399c11395786546eb4e52ab5 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

3e5b7ed1e30d kernel/locking: Add context to ww_mutex_trylock.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21036/index.html

[-- Attachment #2: Type: text/html, Size: 6229 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-14  6:50               ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-14 12:43                 ` Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-14 12:43 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
> On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
>
>>> +/**
>>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>>> + * @ww: mutex to lock
>>> + * @ww_ctx: optional w/w acquire context
>>> + *
>>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>>> + *
>>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
>>> + *
>>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>>> + */
>>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
>>> +{
>>> +	if (!ww_ctx)
>>> +		return mutex_trylock(&ww->base);
>>> +
>>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
>>> +
>>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
>>> +		return -EALREADY;
>> I'm not 100% sure this is a good idea, because it would make the
>> trylock weird.  For i915 I checked manually, because I didn't want to
>> change the function signature. This is probably the other extreme.
>>
>> "if (ww_mutex_trylock())" would look correct, but actually be wrong
>> and lead to double unlock without adjustments.  Maybe we could make a
>> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
>> failure, and 0 on success?  We could keep ww_mutex_trylock without
>> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
> Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
> the trylock anyway. Let me take this out.
>
>>> +	/*
>>> +	 * Reset the wounded flag after a kill. No other process can
>>> +	 * race and wound us here, since they can't have a valid owner
>>> +	 * pointer if we don't have any locks held.
>>> +	 */
>>> +	if (ww_ctx->acquired == 0)
>>> +		ww_ctx->wounded = 0;
>> Yeah I guess this needs fixing too. Not completely sure since trylock
>> wouldn't do the whole ww dance, but since it's our first lock,
>> probably best to do so regardless so other users don't trip over it.
> This is actually critical, because if this trylock is the first lock
> acquisition for the context, there won't be any other opportunity to
> reset this value.
>
>>> +
>>> +	if (__mutex_trylock(&ww->base)) {
>>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
>>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
>>> +		return 1;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL(ww_mutex_trylock);
> Updated version below...
>
> ---
> Subject: kernel/locking: Add context to ww_mutex_trylock()
> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Date: Thu, 9 Sep 2021 11:32:18 +0200
>
> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>
> i915 will soon gain an eviction path that trylock a whole lot of locks
> for eviction, getting dmesg failures like below:
>
>   BUG: MAX_LOCK_DEPTH too low!
>   turning off the locking correctness validator.
>   depth: 48  max: 48!
>   48 locks held by i915_selftest/5776:
>    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>   ...
>    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>   INFO: lockdep is turned off.
>
> Fixing eviction to nest into ww_class_acquire is a high priority, but
> it requires a rework of the entire driver, which can only be done one
> step at a time.
>
> As an intermediate solution, add an acquire context to
> ww_mutex_trylock, which allows us to do proper nesting annotations on
> the trylocks, making the above lockdep splat disappear.
>
> This is also useful in regulator_lock_nested, which may avoid dropping
> regulator_nesting_mutex in the uncontended path, so use it there.
>
> TTM may be another user for this, where we could lock a buffer in a
> fastpath with list locks held, without dropping all locks we hold.
>
> [peterz: rework actual ww_mutex_trylock() implementations]
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---

My original patch series with this patch in place still passes i915 selftests, looks good to me. :)

Feel free to apply.


>  drivers/gpu/drm/drm_modeset_lock.c |    2 
>  drivers/regulator/core.c           |    2 
>  include/linux/dma-resv.h           |    2 
>  include/linux/ww_mutex.h           |   15 ------
>  kernel/locking/mutex.c             |   41 +++++++++++++++++
>  kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
>  kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
>  lib/locking-selftest.c             |    2 
>  8 files changed, 137 insertions(+), 38 deletions(-)
>
> --- a/drivers/gpu/drm/drm_modeset_lock.c
> +++ b/drivers/gpu/drm/drm_modeset_lock.c
> @@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
>  	if (ctx->trylock_only) {
>  		lockdep_assert_held(&ctx->ww_ctx);
>  
> -		if (!ww_mutex_trylock(&lock->mutex))
> +		if (!ww_mutex_trylock(&lock->mutex, NULL))
>  			return -EBUSY;
>  		else
>  			return 0;
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
>  
>  	mutex_lock(&regulator_nesting_mutex);
>  
> -	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
> +	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
>  		if (rdev->mutex_owner == current)
>  			rdev->ref_cnt++;
>  		else
> --- a/include/linux/dma-resv.h
> +++ b/include/linux/dma-resv.h
> @@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
>   */
>  static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
>  {
> -	return ww_mutex_trylock(&obj->lock);
> +	return ww_mutex_trylock(&obj->lock, NULL);
>  }
>  
>  /**
> --- a/include/linux/ww_mutex.h
> +++ b/include/linux/ww_mutex.h
> @@ -28,12 +28,10 @@
>  #ifndef CONFIG_PREEMPT_RT
>  #define WW_MUTEX_BASE			mutex
>  #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
> -#define ww_mutex_base_trylock(l)	mutex_trylock(l)
>  #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
>  #else
>  #define WW_MUTEX_BASE			rt_mutex
>  #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
> -#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
>  #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
>  #endif
>  
> @@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
>  
>  extern void ww_mutex_unlock(struct ww_mutex *lock);
>  
> -/**
> - * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
> - * @lock: mutex to lock
> - *
> - * Trylocks a mutex without acquire context, so no deadlock detection is
> - * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> - */
> -static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
> -{
> -	return ww_mutex_base_trylock(&lock->base);
> -}
> +extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
> +					 struct ww_acquire_ctx *ctx);
>  
>  /***
>   * ww_mutex_destroy - mark a w/w mutex unusable
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
>  	return owner & MUTEX_FLAGS;
>  }
>  
> +/*
> + * Returns: __mutex_owner(lock) on failure or NULL on success.
> + */
>  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
>  {
>  	unsigned long owner, curr = (unsigned long)current;
> @@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @ww: mutex to lock
> + * @ww_ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> +{
> +	if (!ww_ctx)
> +		return mutex_trylock(&ww->base);
> +
> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__mutex_trylock(&ww->base)) {
> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> --- a/kernel/locking/test-ww_mutex.c
> +++ b/kernel/locking/test-ww_mutex.c
> @@ -16,6 +16,15 @@
>  static DEFINE_WD_CLASS(ww_class);
>  struct workqueue_struct *wq;
>  
> +#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
> +#define ww_acquire_init_noinject(a, b) do { \
> +		ww_acquire_init((a), (b)); \
> +		(a)->deadlock_inject_countdown = ~0U; \
> +	} while (0)
> +#else
> +#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
> +#endif
> +
>  struct test_mutex {
>  	struct work_struct work;
>  	struct ww_mutex mutex;
> @@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
>  	wait_for_completion(&mtx->go);
>  
>  	if (mtx->flags & TEST_MTX_TRY) {
> -		while (!ww_mutex_trylock(&mtx->mutex))
> +		while (!ww_mutex_trylock(&mtx->mutex, NULL))
>  			cond_resched();
>  	} else {
>  		ww_mutex_lock(&mtx->mutex, NULL);
> @@ -109,19 +118,38 @@ static int test_mutex(void)
>  	return 0;
>  }
>  
> -static int test_aa(void)
> +static int test_aa(bool trylock)
>  {
>  	struct ww_mutex mutex;
>  	struct ww_acquire_ctx ctx;
>  	int ret;
> +	const char *from = trylock ? "trylock" : "lock";
>  
>  	ww_mutex_init(&mutex, &ww_class);
>  	ww_acquire_init(&ctx, &ww_class);
>  
> -	ww_mutex_lock(&mutex, &ctx);
> +	if (!trylock) {
> +		ret = ww_mutex_lock(&mutex, &ctx);
> +		if (ret) {
> +			pr_err("%s: initial lock failed!\n", __func__);
> +			goto out;
> +		}
> +	} else {
> +		if (!ww_mutex_trylock(&mutex, &ctx)) {
> +			pr_err("%s: initial trylock failed!\n", __func__);
> +			goto out;
> +		}
> +	}
>  
> -	if (ww_mutex_trylock(&mutex))  {
> -		pr_err("%s: trylocked itself!\n", __func__);
> +	if (ww_mutex_trylock(&mutex, NULL))  {
> +		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
> +		ww_mutex_unlock(&mutex);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (ww_mutex_trylock(&mutex, &ctx))  {
> +		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
>  		ww_mutex_unlock(&mutex);
>  		ret = -EINVAL;
>  		goto out;
> @@ -129,17 +157,17 @@ static int test_aa(void)
>  
>  	ret = ww_mutex_lock(&mutex, &ctx);
>  	if (ret != -EALREADY) {
> -		pr_err("%s: missed deadlock for recursing, ret=%d\n",
> -		       __func__, ret);
> +		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
> +		       __func__, ret, from);
>  		if (!ret)
>  			ww_mutex_unlock(&mutex);
>  		ret = -EINVAL;
>  		goto out;
>  	}
>  
> +	ww_mutex_unlock(&mutex);
>  	ret = 0;
>  out:
> -	ww_mutex_unlock(&mutex);
>  	ww_acquire_fini(&ctx);
>  	return ret;
>  }
> @@ -150,7 +178,7 @@ struct test_abba {
>  	struct ww_mutex b_mutex;
>  	struct completion a_ready;
>  	struct completion b_ready;
> -	bool resolve;
> +	bool resolve, trylock;
>  	int result;
>  };
>  
> @@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
>  	struct ww_acquire_ctx ctx;
>  	int err;
>  
> -	ww_acquire_init(&ctx, &ww_class);
> -	ww_mutex_lock(&abba->b_mutex, &ctx);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
> +	if (!abba->trylock)
> +		ww_mutex_lock(&abba->b_mutex, &ctx);
> +	else
> +		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
> +
> +	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
>  
>  	complete(&abba->b_ready);
>  	wait_for_completion(&abba->a_ready);
> @@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
>  	abba->result = err;
>  }
>  
> -static int test_abba(bool resolve)
> +static int test_abba(bool trylock, bool resolve)
>  {
>  	struct test_abba abba;
>  	struct ww_acquire_ctx ctx;
> @@ -192,12 +225,18 @@ static int test_abba(bool resolve)
>  	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
>  	init_completion(&abba.a_ready);
>  	init_completion(&abba.b_ready);
> +	abba.trylock = trylock;
>  	abba.resolve = resolve;
>  
>  	schedule_work(&abba.work);
>  
> -	ww_acquire_init(&ctx, &ww_class);
> -	ww_mutex_lock(&abba.a_mutex, &ctx);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
> +	if (!trylock)
> +		ww_mutex_lock(&abba.a_mutex, &ctx);
> +	else
> +		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
> +
> +	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
>  
>  	complete(&abba.a_ready);
>  	wait_for_completion(&abba.b_ready);
> @@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
>  	struct ww_acquire_ctx ctx;
>  	int err, erra = 0;
>  
> -	ww_acquire_init(&ctx, &ww_class);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
>  	ww_mutex_lock(&cycle->a_mutex, &ctx);
>  
>  	complete(cycle->a_signal);
> @@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
>  static int __init test_ww_mutex_init(void)
>  {
>  	int ncpus = num_online_cpus();
> -	int ret;
> +	int ret, i;
> +
> +	printk(KERN_INFO "Beginning ww mutex selftests\n");
>  
>  	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
>  	if (!wq)
> @@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
>  	if (ret)
>  		return ret;
>  
> -	ret = test_aa();
> +	ret = test_aa(false);
>  	if (ret)
>  		return ret;
>  
> -	ret = test_abba(false);
> +	ret = test_aa(true);
>  	if (ret)
>  		return ret;
>  
> -	ret = test_abba(true);
> -	if (ret)
> -		return ret;
> +	for (i = 0; i < 4; i++) {
> +		ret = test_abba(i & 1, i & 2);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	ret = test_cycle(ncpus);
>  	if (ret)
> @@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
>  	if (ret)
>  		return ret;
>  
> +	printk(KERN_INFO "All ww mutex selftests passed\n");
>  	return 0;
>  }
>  
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -9,6 +9,31 @@
>  #define WW_RT
>  #include "rtmutex.c"
>  
> +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> +{
> +	struct rt_mutex *rtm = &lock->base;
> +
> +	if (!ww_ctx)
> +		return rt_mutex_trylock(rtm);
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  static int __sched
>  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  		   unsigned int state, unsigned long ip)
> --- a/lib/locking-selftest.c
> +++ b/lib/locking-selftest.c
> @@ -258,7 +258,7 @@ static void init_shared_classes(void)
>  #define WWAF(x)			ww_acquire_fini(x)
>  
>  #define WWL(x, c)		ww_mutex_lock(x, c)
> -#define WWT(x)			ww_mutex_trylock(x)
> +#define WWT(x)			ww_mutex_trylock(x, NULL)
>  #define WWL1(x)			ww_mutex_lock(x, NULL)
>  #define WWU(x)			ww_mutex_unlock(x)
>  



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-14 12:43                 ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-14 12:43 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
> On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
>
>>> +/**
>>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>>> + * @ww: mutex to lock
>>> + * @ww_ctx: optional w/w acquire context
>>> + *
>>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>>> + *
>>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
>>> + *
>>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>>> + */
>>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
>>> +{
>>> +	if (!ww_ctx)
>>> +		return mutex_trylock(&ww->base);
>>> +
>>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
>>> +
>>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
>>> +		return -EALREADY;
>> I'm not 100% sure this is a good idea, because it would make the
>> trylock weird.  For i915 I checked manually, because I didn't want to
>> change the function signature. This is probably the other extreme.
>>
>> "if (ww_mutex_trylock())" would look correct, but actually be wrong
>> and lead to double unlock without adjustments.  Maybe we could make a
>> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
>> failure, and 0 on success?  We could keep ww_mutex_trylock without
>> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
> Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
> the trylock anyway. Let me take this out.
>
>>> +	/*
>>> +	 * Reset the wounded flag after a kill. No other process can
>>> +	 * race and wound us here, since they can't have a valid owner
>>> +	 * pointer if we don't have any locks held.
>>> +	 */
>>> +	if (ww_ctx->acquired == 0)
>>> +		ww_ctx->wounded = 0;
>> Yeah I guess this needs fixing too. Not completely sure since trylock
>> wouldn't do the whole ww dance, but since it's our first lock,
>> probably best to do so regardless so other users don't trip over it.
> This is actually critical, because if this trylock is the first lock
> acquisition for the context, there won't be any other opportunity to
> reset this value.
>
>>> +
>>> +	if (__mutex_trylock(&ww->base)) {
>>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
>>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
>>> +		return 1;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL(ww_mutex_trylock);
> Updated version below...
>
> ---
> Subject: kernel/locking: Add context to ww_mutex_trylock()
> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Date: Thu, 9 Sep 2021 11:32:18 +0200
>
> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>
> i915 will soon gain an eviction path that trylock a whole lot of locks
> for eviction, getting dmesg failures like below:
>
>   BUG: MAX_LOCK_DEPTH too low!
>   turning off the locking correctness validator.
>   depth: 48  max: 48!
>   48 locks held by i915_selftest/5776:
>    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>   ...
>    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>   INFO: lockdep is turned off.
>
> Fixing eviction to nest into ww_class_acquire is a high priority, but
> it requires a rework of the entire driver, which can only be done one
> step at a time.
>
> As an intermediate solution, add an acquire context to
> ww_mutex_trylock, which allows us to do proper nesting annotations on
> the trylocks, making the above lockdep splat disappear.
>
> This is also useful in regulator_lock_nested, which may avoid dropping
> regulator_nesting_mutex in the uncontended path, so use it there.
>
> TTM may be another user for this, where we could lock a buffer in a
> fastpath with list locks held, without dropping all locks we hold.
>
> [peterz: rework actual ww_mutex_trylock() implementations]
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---

My original patch series with this patch in place still passes i915 selftests, looks good to me. :)

Feel free to apply.


>  drivers/gpu/drm/drm_modeset_lock.c |    2 
>  drivers/regulator/core.c           |    2 
>  include/linux/dma-resv.h           |    2 
>  include/linux/ww_mutex.h           |   15 ------
>  kernel/locking/mutex.c             |   41 +++++++++++++++++
>  kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
>  kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
>  lib/locking-selftest.c             |    2 
>  8 files changed, 137 insertions(+), 38 deletions(-)
>
> --- a/drivers/gpu/drm/drm_modeset_lock.c
> +++ b/drivers/gpu/drm/drm_modeset_lock.c
> @@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
>  	if (ctx->trylock_only) {
>  		lockdep_assert_held(&ctx->ww_ctx);
>  
> -		if (!ww_mutex_trylock(&lock->mutex))
> +		if (!ww_mutex_trylock(&lock->mutex, NULL))
>  			return -EBUSY;
>  		else
>  			return 0;
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
>  
>  	mutex_lock(&regulator_nesting_mutex);
>  
> -	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
> +	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
>  		if (rdev->mutex_owner == current)
>  			rdev->ref_cnt++;
>  		else
> --- a/include/linux/dma-resv.h
> +++ b/include/linux/dma-resv.h
> @@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
>   */
>  static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
>  {
> -	return ww_mutex_trylock(&obj->lock);
> +	return ww_mutex_trylock(&obj->lock, NULL);
>  }
>  
>  /**
> --- a/include/linux/ww_mutex.h
> +++ b/include/linux/ww_mutex.h
> @@ -28,12 +28,10 @@
>  #ifndef CONFIG_PREEMPT_RT
>  #define WW_MUTEX_BASE			mutex
>  #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
> -#define ww_mutex_base_trylock(l)	mutex_trylock(l)
>  #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
>  #else
>  #define WW_MUTEX_BASE			rt_mutex
>  #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
> -#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
>  #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
>  #endif
>  
> @@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
>  
>  extern void ww_mutex_unlock(struct ww_mutex *lock);
>  
> -/**
> - * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
> - * @lock: mutex to lock
> - *
> - * Trylocks a mutex without acquire context, so no deadlock detection is
> - * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> - */
> -static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
> -{
> -	return ww_mutex_base_trylock(&lock->base);
> -}
> +extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
> +					 struct ww_acquire_ctx *ctx);
>  
>  /***
>   * ww_mutex_destroy - mark a w/w mutex unusable
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
>  	return owner & MUTEX_FLAGS;
>  }
>  
> +/*
> + * Returns: __mutex_owner(lock) on failure or NULL on success.
> + */
>  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
>  {
>  	unsigned long owner, curr = (unsigned long)current;
> @@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
>  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
>  }
>  
> +/**
> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> + * @ww: mutex to lock
> + * @ww_ctx: optional w/w acquire context
> + *
> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> + *
> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> + *
> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> + */
> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> +{
> +	if (!ww_ctx)
> +		return mutex_trylock(&ww->base);
> +
> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__mutex_trylock(&ww->base)) {
> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  #ifdef CONFIG_DEBUG_LOCK_ALLOC
>  void __sched
>  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> --- a/kernel/locking/test-ww_mutex.c
> +++ b/kernel/locking/test-ww_mutex.c
> @@ -16,6 +16,15 @@
>  static DEFINE_WD_CLASS(ww_class);
>  struct workqueue_struct *wq;
>  
> +#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
> +#define ww_acquire_init_noinject(a, b) do { \
> +		ww_acquire_init((a), (b)); \
> +		(a)->deadlock_inject_countdown = ~0U; \
> +	} while (0)
> +#else
> +#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
> +#endif
> +
>  struct test_mutex {
>  	struct work_struct work;
>  	struct ww_mutex mutex;
> @@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
>  	wait_for_completion(&mtx->go);
>  
>  	if (mtx->flags & TEST_MTX_TRY) {
> -		while (!ww_mutex_trylock(&mtx->mutex))
> +		while (!ww_mutex_trylock(&mtx->mutex, NULL))
>  			cond_resched();
>  	} else {
>  		ww_mutex_lock(&mtx->mutex, NULL);
> @@ -109,19 +118,38 @@ static int test_mutex(void)
>  	return 0;
>  }
>  
> -static int test_aa(void)
> +static int test_aa(bool trylock)
>  {
>  	struct ww_mutex mutex;
>  	struct ww_acquire_ctx ctx;
>  	int ret;
> +	const char *from = trylock ? "trylock" : "lock";
>  
>  	ww_mutex_init(&mutex, &ww_class);
>  	ww_acquire_init(&ctx, &ww_class);
>  
> -	ww_mutex_lock(&mutex, &ctx);
> +	if (!trylock) {
> +		ret = ww_mutex_lock(&mutex, &ctx);
> +		if (ret) {
> +			pr_err("%s: initial lock failed!\n", __func__);
> +			goto out;
> +		}
> +	} else {
> +		if (!ww_mutex_trylock(&mutex, &ctx)) {
> +			pr_err("%s: initial trylock failed!\n", __func__);
> +			goto out;
> +		}
> +	}
>  
> -	if (ww_mutex_trylock(&mutex))  {
> -		pr_err("%s: trylocked itself!\n", __func__);
> +	if (ww_mutex_trylock(&mutex, NULL))  {
> +		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
> +		ww_mutex_unlock(&mutex);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (ww_mutex_trylock(&mutex, &ctx))  {
> +		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
>  		ww_mutex_unlock(&mutex);
>  		ret = -EINVAL;
>  		goto out;
> @@ -129,17 +157,17 @@ static int test_aa(void)
>  
>  	ret = ww_mutex_lock(&mutex, &ctx);
>  	if (ret != -EALREADY) {
> -		pr_err("%s: missed deadlock for recursing, ret=%d\n",
> -		       __func__, ret);
> +		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
> +		       __func__, ret, from);
>  		if (!ret)
>  			ww_mutex_unlock(&mutex);
>  		ret = -EINVAL;
>  		goto out;
>  	}
>  
> +	ww_mutex_unlock(&mutex);
>  	ret = 0;
>  out:
> -	ww_mutex_unlock(&mutex);
>  	ww_acquire_fini(&ctx);
>  	return ret;
>  }
> @@ -150,7 +178,7 @@ struct test_abba {
>  	struct ww_mutex b_mutex;
>  	struct completion a_ready;
>  	struct completion b_ready;
> -	bool resolve;
> +	bool resolve, trylock;
>  	int result;
>  };
>  
> @@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
>  	struct ww_acquire_ctx ctx;
>  	int err;
>  
> -	ww_acquire_init(&ctx, &ww_class);
> -	ww_mutex_lock(&abba->b_mutex, &ctx);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
> +	if (!abba->trylock)
> +		ww_mutex_lock(&abba->b_mutex, &ctx);
> +	else
> +		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
> +
> +	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
>  
>  	complete(&abba->b_ready);
>  	wait_for_completion(&abba->a_ready);
> @@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
>  	abba->result = err;
>  }
>  
> -static int test_abba(bool resolve)
> +static int test_abba(bool trylock, bool resolve)
>  {
>  	struct test_abba abba;
>  	struct ww_acquire_ctx ctx;
> @@ -192,12 +225,18 @@ static int test_abba(bool resolve)
>  	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
>  	init_completion(&abba.a_ready);
>  	init_completion(&abba.b_ready);
> +	abba.trylock = trylock;
>  	abba.resolve = resolve;
>  
>  	schedule_work(&abba.work);
>  
> -	ww_acquire_init(&ctx, &ww_class);
> -	ww_mutex_lock(&abba.a_mutex, &ctx);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
> +	if (!trylock)
> +		ww_mutex_lock(&abba.a_mutex, &ctx);
> +	else
> +		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
> +
> +	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
>  
>  	complete(&abba.a_ready);
>  	wait_for_completion(&abba.b_ready);
> @@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
>  	struct ww_acquire_ctx ctx;
>  	int err, erra = 0;
>  
> -	ww_acquire_init(&ctx, &ww_class);
> +	ww_acquire_init_noinject(&ctx, &ww_class);
>  	ww_mutex_lock(&cycle->a_mutex, &ctx);
>  
>  	complete(cycle->a_signal);
> @@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
>  static int __init test_ww_mutex_init(void)
>  {
>  	int ncpus = num_online_cpus();
> -	int ret;
> +	int ret, i;
> +
> +	printk(KERN_INFO "Beginning ww mutex selftests\n");
>  
>  	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
>  	if (!wq)
> @@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
>  	if (ret)
>  		return ret;
>  
> -	ret = test_aa();
> +	ret = test_aa(false);
>  	if (ret)
>  		return ret;
>  
> -	ret = test_abba(false);
> +	ret = test_aa(true);
>  	if (ret)
>  		return ret;
>  
> -	ret = test_abba(true);
> -	if (ret)
> -		return ret;
> +	for (i = 0; i < 4; i++) {
> +		ret = test_abba(i & 1, i & 2);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	ret = test_cycle(ncpus);
>  	if (ret)
> @@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
>  	if (ret)
>  		return ret;
>  
> +	printk(KERN_INFO "All ww mutex selftests passed\n");
>  	return 0;
>  }
>  
> --- a/kernel/locking/ww_rt_mutex.c
> +++ b/kernel/locking/ww_rt_mutex.c
> @@ -9,6 +9,31 @@
>  #define WW_RT
>  #include "rtmutex.c"
>  
> +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> +{
> +	struct rt_mutex *rtm = &lock->base;
> +
> +	if (!ww_ctx)
> +		return rt_mutex_trylock(rtm);
> +
> +	/*
> +	 * Reset the wounded flag after a kill. No other process can
> +	 * race and wound us here, since they can't have a valid owner
> +	 * pointer if we don't have any locks held.
> +	 */
> +	if (ww_ctx->acquired == 0)
> +		ww_ctx->wounded = 0;
> +
> +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ww_mutex_trylock);
> +
>  static int __sched
>  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
>  		   unsigned int state, unsigned long ip)
> --- a/lib/locking-selftest.c
> +++ b/lib/locking-selftest.c
> @@ -258,7 +258,7 @@ static void init_shared_classes(void)
>  #define WWAF(x)			ww_acquire_fini(x)
>  
>  #define WWL(x, c)		ww_mutex_lock(x, c)
> -#define WWT(x)			ww_mutex_trylock(x)
> +#define WWT(x)			ww_mutex_trylock(x, NULL)
>  #define WWL1(x)			ww_mutex_lock(x, NULL)
>  #define WWU(x)			ww_mutex_unlock(x)
>  



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-14 12:43                 ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-14 13:54                   ` Daniel Vetter
  -1 siblings, 0 replies; 51+ messages in thread
From: Daniel Vetter @ 2021-09-14 13:54 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Tue, Sep 14, 2021 at 02:43:02PM +0200, Maarten Lankhorst wrote:
> Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
> > On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
> >
> >>> +/**
> >>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> >>> + * @ww: mutex to lock
> >>> + * @ww_ctx: optional w/w acquire context
> >>> + *
> >>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> >>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> >>> + *
> >>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> >>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> >>> + *
> >>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> >>> + */
> >>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> >>> +{
> >>> +	if (!ww_ctx)
> >>> +		return mutex_trylock(&ww->base);
> >>> +
> >>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> >>> +
> >>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> >>> +		return -EALREADY;
> >> I'm not 100% sure this is a good idea, because it would make the
> >> trylock weird.  For i915 I checked manually, because I didn't want to
> >> change the function signature. This is probably the other extreme.
> >>
> >> "if (ww_mutex_trylock())" would look correct, but actually be wrong
> >> and lead to double unlock without adjustments.  Maybe we could make a
> >> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
> >> failure, and 0 on success?  We could keep ww_mutex_trylock without
> >> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
> > Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
> > the trylock anyway. Let me take this out.
> >
> >>> +	/*
> >>> +	 * Reset the wounded flag after a kill. No other process can
> >>> +	 * race and wound us here, since they can't have a valid owner
> >>> +	 * pointer if we don't have any locks held.
> >>> +	 */
> >>> +	if (ww_ctx->acquired == 0)
> >>> +		ww_ctx->wounded = 0;
> >> Yeah I guess this needs fixing too. Not completely sure since trylock
> >> wouldn't do the whole ww dance, but since it's our first lock,
> >> probably best to do so regardless so other users don't trip over it.
> > This is actually critical, because if this trylock is the first lock
> > acquisition for the context, there won't be any other opportunity to
> > reset this value.
> >
> >>> +
> >>> +	if (__mutex_trylock(&ww->base)) {
> >>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> >>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> >>> +		return 1;
> >>> +	}
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL(ww_mutex_trylock);
> > Updated version below...
> >
> > ---
> > Subject: kernel/locking: Add context to ww_mutex_trylock()
> > From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Date: Thu, 9 Sep 2021 11:32:18 +0200
> >
> > From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >
> > i915 will soon gain an eviction path that trylock a whole lot of locks
> > for eviction, getting dmesg failures like below:
> >
> >   BUG: MAX_LOCK_DEPTH too low!
> >   turning off the locking correctness validator.
> >   depth: 48  max: 48!
> >   48 locks held by i915_selftest/5776:
> >    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
> >    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
> >    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
> >    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
> >    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >   ...
> >    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >   INFO: lockdep is turned off.
> >
> > Fixing eviction to nest into ww_class_acquire is a high priority, but
> > it requires a rework of the entire driver, which can only be done one
> > step at a time.
> >
> > As an intermediate solution, add an acquire context to
> > ww_mutex_trylock, which allows us to do proper nesting annotations on
> > the trylocks, making the above lockdep splat disappear.
> >
> > This is also useful in regulator_lock_nested, which may avoid dropping
> > regulator_nesting_mutex in the uncontended path, so use it there.
> >
> > TTM may be another user for this, where we could lock a buffer in a
> > fastpath with list locks held, without dropping all locks we hold.
> >
> > [peterz: rework actual ww_mutex_trylock() implementations]
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > ---
> 
> My original patch series with this patch in place still passes i915 selftests, looks good to me. :)

For merge logistics, can we pls have a stable branch? I expect that the
i915 patches will be ready for 5.16.

Or send it in for -rc2 so that the interface change doesn't cause needless
conflicts, whatever you think is best.
-Daniel

> 
> Feel free to apply.
> 
> 
> >  drivers/gpu/drm/drm_modeset_lock.c |    2 
> >  drivers/regulator/core.c           |    2 
> >  include/linux/dma-resv.h           |    2 
> >  include/linux/ww_mutex.h           |   15 ------
> >  kernel/locking/mutex.c             |   41 +++++++++++++++++
> >  kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
> >  kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
> >  lib/locking-selftest.c             |    2 
> >  8 files changed, 137 insertions(+), 38 deletions(-)
> >
> > --- a/drivers/gpu/drm/drm_modeset_lock.c
> > +++ b/drivers/gpu/drm/drm_modeset_lock.c
> > @@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
> >  	if (ctx->trylock_only) {
> >  		lockdep_assert_held(&ctx->ww_ctx);
> >  
> > -		if (!ww_mutex_trylock(&lock->mutex))
> > +		if (!ww_mutex_trylock(&lock->mutex, NULL))
> >  			return -EBUSY;
> >  		else
> >  			return 0;
> > --- a/drivers/regulator/core.c
> > +++ b/drivers/regulator/core.c
> > @@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
> >  
> >  	mutex_lock(&regulator_nesting_mutex);
> >  
> > -	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
> > +	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
> >  		if (rdev->mutex_owner == current)
> >  			rdev->ref_cnt++;
> >  		else
> > --- a/include/linux/dma-resv.h
> > +++ b/include/linux/dma-resv.h
> > @@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
> >   */
> >  static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
> >  {
> > -	return ww_mutex_trylock(&obj->lock);
> > +	return ww_mutex_trylock(&obj->lock, NULL);
> >  }
> >  
> >  /**
> > --- a/include/linux/ww_mutex.h
> > +++ b/include/linux/ww_mutex.h
> > @@ -28,12 +28,10 @@
> >  #ifndef CONFIG_PREEMPT_RT
> >  #define WW_MUTEX_BASE			mutex
> >  #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
> > -#define ww_mutex_base_trylock(l)	mutex_trylock(l)
> >  #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
> >  #else
> >  #define WW_MUTEX_BASE			rt_mutex
> >  #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
> > -#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
> >  #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
> >  #endif
> >  
> > @@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
> >  
> >  extern void ww_mutex_unlock(struct ww_mutex *lock);
> >  
> > -/**
> > - * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
> > - * @lock: mutex to lock
> > - *
> > - * Trylocks a mutex without acquire context, so no deadlock detection is
> > - * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > - */
> > -static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
> > -{
> > -	return ww_mutex_base_trylock(&lock->base);
> > -}
> > +extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
> > +					 struct ww_acquire_ctx *ctx);
> >  
> >  /***
> >   * ww_mutex_destroy - mark a w/w mutex unusable
> > --- a/kernel/locking/mutex.c
> > +++ b/kernel/locking/mutex.c
> > @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
> >  	return owner & MUTEX_FLAGS;
> >  }
> >  
> > +/*
> > + * Returns: __mutex_owner(lock) on failure or NULL on success.
> > + */
> >  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
> >  {
> >  	unsigned long owner, curr = (unsigned long)current;
> > @@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
> >  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
> >  }
> >  
> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @ww: mutex to lock
> > + * @ww_ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	if (!ww_ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> > +
> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> > +
> > +	if (__mutex_trylock(&ww->base)) {
> > +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> > +
> >  #ifdef CONFIG_DEBUG_LOCK_ALLOC
> >  void __sched
> >  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> > --- a/kernel/locking/test-ww_mutex.c
> > +++ b/kernel/locking/test-ww_mutex.c
> > @@ -16,6 +16,15 @@
> >  static DEFINE_WD_CLASS(ww_class);
> >  struct workqueue_struct *wq;
> >  
> > +#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
> > +#define ww_acquire_init_noinject(a, b) do { \
> > +		ww_acquire_init((a), (b)); \
> > +		(a)->deadlock_inject_countdown = ~0U; \
> > +	} while (0)
> > +#else
> > +#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
> > +#endif
> > +
> >  struct test_mutex {
> >  	struct work_struct work;
> >  	struct ww_mutex mutex;
> > @@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
> >  	wait_for_completion(&mtx->go);
> >  
> >  	if (mtx->flags & TEST_MTX_TRY) {
> > -		while (!ww_mutex_trylock(&mtx->mutex))
> > +		while (!ww_mutex_trylock(&mtx->mutex, NULL))
> >  			cond_resched();
> >  	} else {
> >  		ww_mutex_lock(&mtx->mutex, NULL);
> > @@ -109,19 +118,38 @@ static int test_mutex(void)
> >  	return 0;
> >  }
> >  
> > -static int test_aa(void)
> > +static int test_aa(bool trylock)
> >  {
> >  	struct ww_mutex mutex;
> >  	struct ww_acquire_ctx ctx;
> >  	int ret;
> > +	const char *from = trylock ? "trylock" : "lock";
> >  
> >  	ww_mutex_init(&mutex, &ww_class);
> >  	ww_acquire_init(&ctx, &ww_class);
> >  
> > -	ww_mutex_lock(&mutex, &ctx);
> > +	if (!trylock) {
> > +		ret = ww_mutex_lock(&mutex, &ctx);
> > +		if (ret) {
> > +			pr_err("%s: initial lock failed!\n", __func__);
> > +			goto out;
> > +		}
> > +	} else {
> > +		if (!ww_mutex_trylock(&mutex, &ctx)) {
> > +			pr_err("%s: initial trylock failed!\n", __func__);
> > +			goto out;
> > +		}
> > +	}
> >  
> > -	if (ww_mutex_trylock(&mutex))  {
> > -		pr_err("%s: trylocked itself!\n", __func__);
> > +	if (ww_mutex_trylock(&mutex, NULL))  {
> > +		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
> > +		ww_mutex_unlock(&mutex);
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	if (ww_mutex_trylock(&mutex, &ctx))  {
> > +		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
> >  		ww_mutex_unlock(&mutex);
> >  		ret = -EINVAL;
> >  		goto out;
> > @@ -129,17 +157,17 @@ static int test_aa(void)
> >  
> >  	ret = ww_mutex_lock(&mutex, &ctx);
> >  	if (ret != -EALREADY) {
> > -		pr_err("%s: missed deadlock for recursing, ret=%d\n",
> > -		       __func__, ret);
> > +		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
> > +		       __func__, ret, from);
> >  		if (!ret)
> >  			ww_mutex_unlock(&mutex);
> >  		ret = -EINVAL;
> >  		goto out;
> >  	}
> >  
> > +	ww_mutex_unlock(&mutex);
> >  	ret = 0;
> >  out:
> > -	ww_mutex_unlock(&mutex);
> >  	ww_acquire_fini(&ctx);
> >  	return ret;
> >  }
> > @@ -150,7 +178,7 @@ struct test_abba {
> >  	struct ww_mutex b_mutex;
> >  	struct completion a_ready;
> >  	struct completion b_ready;
> > -	bool resolve;
> > +	bool resolve, trylock;
> >  	int result;
> >  };
> >  
> > @@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
> >  	struct ww_acquire_ctx ctx;
> >  	int err;
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > -	ww_mutex_lock(&abba->b_mutex, &ctx);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> > +	if (!abba->trylock)
> > +		ww_mutex_lock(&abba->b_mutex, &ctx);
> > +	else
> > +		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
> > +
> > +	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
> >  
> >  	complete(&abba->b_ready);
> >  	wait_for_completion(&abba->a_ready);
> > @@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
> >  	abba->result = err;
> >  }
> >  
> > -static int test_abba(bool resolve)
> > +static int test_abba(bool trylock, bool resolve)
> >  {
> >  	struct test_abba abba;
> >  	struct ww_acquire_ctx ctx;
> > @@ -192,12 +225,18 @@ static int test_abba(bool resolve)
> >  	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
> >  	init_completion(&abba.a_ready);
> >  	init_completion(&abba.b_ready);
> > +	abba.trylock = trylock;
> >  	abba.resolve = resolve;
> >  
> >  	schedule_work(&abba.work);
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > -	ww_mutex_lock(&abba.a_mutex, &ctx);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> > +	if (!trylock)
> > +		ww_mutex_lock(&abba.a_mutex, &ctx);
> > +	else
> > +		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
> > +
> > +	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
> >  
> >  	complete(&abba.a_ready);
> >  	wait_for_completion(&abba.b_ready);
> > @@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
> >  	struct ww_acquire_ctx ctx;
> >  	int err, erra = 0;
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> >  	ww_mutex_lock(&cycle->a_mutex, &ctx);
> >  
> >  	complete(cycle->a_signal);
> > @@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
> >  static int __init test_ww_mutex_init(void)
> >  {
> >  	int ncpus = num_online_cpus();
> > -	int ret;
> > +	int ret, i;
> > +
> > +	printk(KERN_INFO "Beginning ww mutex selftests\n");
> >  
> >  	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
> >  	if (!wq)
> > @@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_aa();
> > +	ret = test_aa(false);
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_abba(false);
> > +	ret = test_aa(true);
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_abba(true);
> > -	if (ret)
> > -		return ret;
> > +	for (i = 0; i < 4; i++) {
> > +		ret = test_abba(i & 1, i & 2);
> > +		if (ret)
> > +			return ret;
> > +	}
> >  
> >  	ret = test_cycle(ncpus);
> >  	if (ret)
> > @@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
> >  	if (ret)
> >  		return ret;
> >  
> > +	printk(KERN_INFO "All ww mutex selftests passed\n");
> >  	return 0;
> >  }
> >  
> > --- a/kernel/locking/ww_rt_mutex.c
> > +++ b/kernel/locking/ww_rt_mutex.c
> > @@ -9,6 +9,31 @@
> >  #define WW_RT
> >  #include "rtmutex.c"
> >  
> > +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	struct rt_mutex *rtm = &lock->base;
> > +
> > +	if (!ww_ctx)
> > +		return rt_mutex_trylock(rtm);
> > +
> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> > +
> > +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> > +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> > +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> > +
> >  static int __sched
> >  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
> >  		   unsigned int state, unsigned long ip)
> > --- a/lib/locking-selftest.c
> > +++ b/lib/locking-selftest.c
> > @@ -258,7 +258,7 @@ static void init_shared_classes(void)
> >  #define WWAF(x)			ww_acquire_fini(x)
> >  
> >  #define WWL(x, c)		ww_mutex_lock(x, c)
> > -#define WWT(x)			ww_mutex_trylock(x)
> > +#define WWT(x)			ww_mutex_trylock(x, NULL)
> >  #define WWL1(x)			ww_mutex_lock(x, NULL)
> >  #define WWU(x)			ww_mutex_unlock(x)
> >  
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-14 13:54                   ` Daniel Vetter
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Vetter @ 2021-09-14 13:54 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel,
	Daniel Vetter

On Tue, Sep 14, 2021 at 02:43:02PM +0200, Maarten Lankhorst wrote:
> Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
> > On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
> >
> >>> +/**
> >>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> >>> + * @ww: mutex to lock
> >>> + * @ww_ctx: optional w/w acquire context
> >>> + *
> >>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> >>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> >>> + *
> >>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> >>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> >>> + *
> >>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
> >>> + */
> >>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> >>> +{
> >>> +	if (!ww_ctx)
> >>> +		return mutex_trylock(&ww->base);
> >>> +
> >>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> >>> +
> >>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
> >>> +		return -EALREADY;
> >> I'm not 100% sure this is a good idea, because it would make the
> >> trylock weird.  For i915 I checked manually, because I didn't want to
> >> change the function signature. This is probably the other extreme.
> >>
> >> "if (ww_mutex_trylock())" would look correct, but actually be wrong
> >> and lead to double unlock without adjustments.  Maybe we could make a
> >> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
> >> failure, and 0 on success?  We could keep ww_mutex_trylock without
> >> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
> > Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
> > the trylock anyway. Let me take this out.
> >
> >>> +	/*
> >>> +	 * Reset the wounded flag after a kill. No other process can
> >>> +	 * race and wound us here, since they can't have a valid owner
> >>> +	 * pointer if we don't have any locks held.
> >>> +	 */
> >>> +	if (ww_ctx->acquired == 0)
> >>> +		ww_ctx->wounded = 0;
> >> Yeah I guess this needs fixing too. Not completely sure since trylock
> >> wouldn't do the whole ww dance, but since it's our first lock,
> >> probably best to do so regardless so other users don't trip over it.
> > This is actually critical, because if this trylock is the first lock
> > acquisition for the context, there won't be any other opportunity to
> > reset this value.
> >
> >>> +
> >>> +	if (__mutex_trylock(&ww->base)) {
> >>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> >>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> >>> +		return 1;
> >>> +	}
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL(ww_mutex_trylock);
> > Updated version below...
> >
> > ---
> > Subject: kernel/locking: Add context to ww_mutex_trylock()
> > From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Date: Thu, 9 Sep 2021 11:32:18 +0200
> >
> > From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> >
> > i915 will soon gain an eviction path that trylock a whole lot of locks
> > for eviction, getting dmesg failures like below:
> >
> >   BUG: MAX_LOCK_DEPTH too low!
> >   turning off the locking correctness validator.
> >   depth: 48  max: 48!
> >   48 locks held by i915_selftest/5776:
> >    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
> >    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
> >    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
> >    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
> >    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >   ...
> >    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
> >   INFO: lockdep is turned off.
> >
> > Fixing eviction to nest into ww_class_acquire is a high priority, but
> > it requires a rework of the entire driver, which can only be done one
> > step at a time.
> >
> > As an intermediate solution, add an acquire context to
> > ww_mutex_trylock, which allows us to do proper nesting annotations on
> > the trylocks, making the above lockdep splat disappear.
> >
> > This is also useful in regulator_lock_nested, which may avoid dropping
> > regulator_nesting_mutex in the uncontended path, so use it there.
> >
> > TTM may be another user for this, where we could lock a buffer in a
> > fastpath with list locks held, without dropping all locks we hold.
> >
> > [peterz: rework actual ww_mutex_trylock() implementations]
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > ---
> 
> My original patch series with this patch in place still passes i915 selftests, looks good to me. :)

For merge logistics, can we pls have a stable branch? I expect that the
i915 patches will be ready for 5.16.

Or send it in for -rc2 so that the interface change doesn't cause needless
conflicts, whatever you think is best.
-Daniel

> 
> Feel free to apply.
> 
> 
> >  drivers/gpu/drm/drm_modeset_lock.c |    2 
> >  drivers/regulator/core.c           |    2 
> >  include/linux/dma-resv.h           |    2 
> >  include/linux/ww_mutex.h           |   15 ------
> >  kernel/locking/mutex.c             |   41 +++++++++++++++++
> >  kernel/locking/test-ww_mutex.c     |   86 +++++++++++++++++++++++++++----------
> >  kernel/locking/ww_rt_mutex.c       |   25 ++++++++++
> >  lib/locking-selftest.c             |    2 
> >  8 files changed, 137 insertions(+), 38 deletions(-)
> >
> > --- a/drivers/gpu/drm/drm_modeset_lock.c
> > +++ b/drivers/gpu/drm/drm_modeset_lock.c
> > @@ -248,7 +248,7 @@ static inline int modeset_lock(struct dr
> >  	if (ctx->trylock_only) {
> >  		lockdep_assert_held(&ctx->ww_ctx);
> >  
> > -		if (!ww_mutex_trylock(&lock->mutex))
> > +		if (!ww_mutex_trylock(&lock->mutex, NULL))
> >  			return -EBUSY;
> >  		else
> >  			return 0;
> > --- a/drivers/regulator/core.c
> > +++ b/drivers/regulator/core.c
> > @@ -145,7 +145,7 @@ static inline int regulator_lock_nested(
> >  
> >  	mutex_lock(&regulator_nesting_mutex);
> >  
> > -	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
> > +	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
> >  		if (rdev->mutex_owner == current)
> >  			rdev->ref_cnt++;
> >  		else
> > --- a/include/linux/dma-resv.h
> > +++ b/include/linux/dma-resv.h
> > @@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_int
> >   */
> >  static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
> >  {
> > -	return ww_mutex_trylock(&obj->lock);
> > +	return ww_mutex_trylock(&obj->lock, NULL);
> >  }
> >  
> >  /**
> > --- a/include/linux/ww_mutex.h
> > +++ b/include/linux/ww_mutex.h
> > @@ -28,12 +28,10 @@
> >  #ifndef CONFIG_PREEMPT_RT
> >  #define WW_MUTEX_BASE			mutex
> >  #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
> > -#define ww_mutex_base_trylock(l)	mutex_trylock(l)
> >  #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
> >  #else
> >  #define WW_MUTEX_BASE			rt_mutex
> >  #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
> > -#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
> >  #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
> >  #endif
> >  
> > @@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct
> >  
> >  extern void ww_mutex_unlock(struct ww_mutex *lock);
> >  
> > -/**
> > - * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
> > - * @lock: mutex to lock
> > - *
> > - * Trylocks a mutex without acquire context, so no deadlock detection is
> > - * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > - */
> > -static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
> > -{
> > -	return ww_mutex_base_trylock(&lock->base);
> > -}
> > +extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
> > +					 struct ww_acquire_ctx *ctx);
> >  
> >  /***
> >   * ww_mutex_destroy - mark a w/w mutex unusable
> > --- a/kernel/locking/mutex.c
> > +++ b/kernel/locking/mutex.c
> > @@ -94,6 +94,9 @@ static inline unsigned long __owner_flag
> >  	return owner & MUTEX_FLAGS;
> >  }
> >  
> > +/*
> > + * Returns: __mutex_owner(lock) on failure or NULL on success.
> > + */
> >  static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
> >  {
> >  	unsigned long owner, curr = (unsigned long)current;
> > @@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsi
> >  	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
> >  }
> >  
> > +/**
> > + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
> > + * @ww: mutex to lock
> > + * @ww_ctx: optional w/w acquire context
> > + *
> > + * Trylocks a mutex with the optional acquire context; no deadlock detection is
> > + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
> > + *
> > + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
> > + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
> > + *
> > + * A mutex acquired with this function must be released with ww_mutex_unlock.
> > + */
> > +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	if (!ww_ctx)
> > +		return mutex_trylock(&ww->base);
> > +
> > +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
> > +
> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> > +
> > +	if (__mutex_trylock(&ww->base)) {
> > +		ww_mutex_set_context_fastpath(ww, ww_ctx);
> > +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> > +
> >  #ifdef CONFIG_DEBUG_LOCK_ALLOC
> >  void __sched
> >  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
> > --- a/kernel/locking/test-ww_mutex.c
> > +++ b/kernel/locking/test-ww_mutex.c
> > @@ -16,6 +16,15 @@
> >  static DEFINE_WD_CLASS(ww_class);
> >  struct workqueue_struct *wq;
> >  
> > +#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
> > +#define ww_acquire_init_noinject(a, b) do { \
> > +		ww_acquire_init((a), (b)); \
> > +		(a)->deadlock_inject_countdown = ~0U; \
> > +	} while (0)
> > +#else
> > +#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
> > +#endif
> > +
> >  struct test_mutex {
> >  	struct work_struct work;
> >  	struct ww_mutex mutex;
> > @@ -36,7 +45,7 @@ static void test_mutex_work(struct work_
> >  	wait_for_completion(&mtx->go);
> >  
> >  	if (mtx->flags & TEST_MTX_TRY) {
> > -		while (!ww_mutex_trylock(&mtx->mutex))
> > +		while (!ww_mutex_trylock(&mtx->mutex, NULL))
> >  			cond_resched();
> >  	} else {
> >  		ww_mutex_lock(&mtx->mutex, NULL);
> > @@ -109,19 +118,38 @@ static int test_mutex(void)
> >  	return 0;
> >  }
> >  
> > -static int test_aa(void)
> > +static int test_aa(bool trylock)
> >  {
> >  	struct ww_mutex mutex;
> >  	struct ww_acquire_ctx ctx;
> >  	int ret;
> > +	const char *from = trylock ? "trylock" : "lock";
> >  
> >  	ww_mutex_init(&mutex, &ww_class);
> >  	ww_acquire_init(&ctx, &ww_class);
> >  
> > -	ww_mutex_lock(&mutex, &ctx);
> > +	if (!trylock) {
> > +		ret = ww_mutex_lock(&mutex, &ctx);
> > +		if (ret) {
> > +			pr_err("%s: initial lock failed!\n", __func__);
> > +			goto out;
> > +		}
> > +	} else {
> > +		if (!ww_mutex_trylock(&mutex, &ctx)) {
> > +			pr_err("%s: initial trylock failed!\n", __func__);
> > +			goto out;
> > +		}
> > +	}
> >  
> > -	if (ww_mutex_trylock(&mutex))  {
> > -		pr_err("%s: trylocked itself!\n", __func__);
> > +	if (ww_mutex_trylock(&mutex, NULL))  {
> > +		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
> > +		ww_mutex_unlock(&mutex);
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	if (ww_mutex_trylock(&mutex, &ctx))  {
> > +		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
> >  		ww_mutex_unlock(&mutex);
> >  		ret = -EINVAL;
> >  		goto out;
> > @@ -129,17 +157,17 @@ static int test_aa(void)
> >  
> >  	ret = ww_mutex_lock(&mutex, &ctx);
> >  	if (ret != -EALREADY) {
> > -		pr_err("%s: missed deadlock for recursing, ret=%d\n",
> > -		       __func__, ret);
> > +		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
> > +		       __func__, ret, from);
> >  		if (!ret)
> >  			ww_mutex_unlock(&mutex);
> >  		ret = -EINVAL;
> >  		goto out;
> >  	}
> >  
> > +	ww_mutex_unlock(&mutex);
> >  	ret = 0;
> >  out:
> > -	ww_mutex_unlock(&mutex);
> >  	ww_acquire_fini(&ctx);
> >  	return ret;
> >  }
> > @@ -150,7 +178,7 @@ struct test_abba {
> >  	struct ww_mutex b_mutex;
> >  	struct completion a_ready;
> >  	struct completion b_ready;
> > -	bool resolve;
> > +	bool resolve, trylock;
> >  	int result;
> >  };
> >  
> > @@ -160,8 +188,13 @@ static void test_abba_work(struct work_s
> >  	struct ww_acquire_ctx ctx;
> >  	int err;
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > -	ww_mutex_lock(&abba->b_mutex, &ctx);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> > +	if (!abba->trylock)
> > +		ww_mutex_lock(&abba->b_mutex, &ctx);
> > +	else
> > +		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
> > +
> > +	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
> >  
> >  	complete(&abba->b_ready);
> >  	wait_for_completion(&abba->a_ready);
> > @@ -181,7 +214,7 @@ static void test_abba_work(struct work_s
> >  	abba->result = err;
> >  }
> >  
> > -static int test_abba(bool resolve)
> > +static int test_abba(bool trylock, bool resolve)
> >  {
> >  	struct test_abba abba;
> >  	struct ww_acquire_ctx ctx;
> > @@ -192,12 +225,18 @@ static int test_abba(bool resolve)
> >  	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
> >  	init_completion(&abba.a_ready);
> >  	init_completion(&abba.b_ready);
> > +	abba.trylock = trylock;
> >  	abba.resolve = resolve;
> >  
> >  	schedule_work(&abba.work);
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > -	ww_mutex_lock(&abba.a_mutex, &ctx);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> > +	if (!trylock)
> > +		ww_mutex_lock(&abba.a_mutex, &ctx);
> > +	else
> > +		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
> > +
> > +	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
> >  
> >  	complete(&abba.a_ready);
> >  	wait_for_completion(&abba.b_ready);
> > @@ -249,7 +288,7 @@ static void test_cycle_work(struct work_
> >  	struct ww_acquire_ctx ctx;
> >  	int err, erra = 0;
> >  
> > -	ww_acquire_init(&ctx, &ww_class);
> > +	ww_acquire_init_noinject(&ctx, &ww_class);
> >  	ww_mutex_lock(&cycle->a_mutex, &ctx);
> >  
> >  	complete(cycle->a_signal);
> > @@ -581,7 +620,9 @@ static int stress(int nlocks, int nthrea
> >  static int __init test_ww_mutex_init(void)
> >  {
> >  	int ncpus = num_online_cpus();
> > -	int ret;
> > +	int ret, i;
> > +
> > +	printk(KERN_INFO "Beginning ww mutex selftests\n");
> >  
> >  	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
> >  	if (!wq)
> > @@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(voi
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_aa();
> > +	ret = test_aa(false);
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_abba(false);
> > +	ret = test_aa(true);
> >  	if (ret)
> >  		return ret;
> >  
> > -	ret = test_abba(true);
> > -	if (ret)
> > -		return ret;
> > +	for (i = 0; i < 4; i++) {
> > +		ret = test_abba(i & 1, i & 2);
> > +		if (ret)
> > +			return ret;
> > +	}
> >  
> >  	ret = test_cycle(ncpus);
> >  	if (ret)
> > @@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(voi
> >  	if (ret)
> >  		return ret;
> >  
> > +	printk(KERN_INFO "All ww mutex selftests passed\n");
> >  	return 0;
> >  }
> >  
> > --- a/kernel/locking/ww_rt_mutex.c
> > +++ b/kernel/locking/ww_rt_mutex.c
> > @@ -9,6 +9,31 @@
> >  #define WW_RT
> >  #include "rtmutex.c"
> >  
> > +int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
> > +{
> > +	struct rt_mutex *rtm = &lock->base;
> > +
> > +	if (!ww_ctx)
> > +		return rt_mutex_trylock(rtm);
> > +
> > +	/*
> > +	 * Reset the wounded flag after a kill. No other process can
> > +	 * race and wound us here, since they can't have a valid owner
> > +	 * pointer if we don't have any locks held.
> > +	 */
> > +	if (ww_ctx->acquired == 0)
> > +		ww_ctx->wounded = 0;
> > +
> > +	if (__rt_mutex_trylock(&rtm->rtmutex)) {
> > +		ww_mutex_set_context_fastpath(lock, ww_ctx);
> > +		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(ww_mutex_trylock);
> > +
> >  static int __sched
> >  __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
> >  		   unsigned int state, unsigned long ip)
> > --- a/lib/locking-selftest.c
> > +++ b/lib/locking-selftest.c
> > @@ -258,7 +258,7 @@ static void init_shared_classes(void)
> >  #define WWAF(x)			ww_acquire_fini(x)
> >  
> >  #define WWL(x, c)		ww_mutex_lock(x, c)
> > -#define WWT(x)			ww_mutex_trylock(x)
> > +#define WWT(x)			ww_mutex_trylock(x, NULL)
> >  #define WWL1(x)			ww_mutex_lock(x, NULL)
> >  #define WWU(x)			ww_mutex_unlock(x)
> >  
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-14 13:54                   ` [Intel-gfx] " Daniel Vetter
@ 2021-09-16 13:00                     ` Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-16 13:00 UTC (permalink / raw)
  To: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Op 14-09-2021 om 15:54 schreef Daniel Vetter:
> On Tue, Sep 14, 2021 at 02:43:02PM +0200, Maarten Lankhorst wrote:
>> Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
>>> On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
>>>
>>>>> +/**
>>>>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>>>>> + * @ww: mutex to lock
>>>>> + * @ww_ctx: optional w/w acquire context
>>>>> + *
>>>>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>>>>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>>>>> + *
>>>>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>>>>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
>>>>> + *
>>>>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>>>>> + */
>>>>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
>>>>> +{
>>>>> +	if (!ww_ctx)
>>>>> +		return mutex_trylock(&ww->base);
>>>>> +
>>>>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
>>>>> +
>>>>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
>>>>> +		return -EALREADY;
>>>> I'm not 100% sure this is a good idea, because it would make the
>>>> trylock weird.  For i915 I checked manually, because I didn't want to
>>>> change the function signature. This is probably the other extreme.
>>>>
>>>> "if (ww_mutex_trylock())" would look correct, but actually be wrong
>>>> and lead to double unlock without adjustments.  Maybe we could make a
>>>> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
>>>> failure, and 0 on success?  We could keep ww_mutex_trylock without
>>>> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
>>> Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
>>> the trylock anyway. Let me take this out.
>>>
>>>>> +	/*
>>>>> +	 * Reset the wounded flag after a kill. No other process can
>>>>> +	 * race and wound us here, since they can't have a valid owner
>>>>> +	 * pointer if we don't have any locks held.
>>>>> +	 */
>>>>> +	if (ww_ctx->acquired == 0)
>>>>> +		ww_ctx->wounded = 0;
>>>> Yeah I guess this needs fixing too. Not completely sure since trylock
>>>> wouldn't do the whole ww dance, but since it's our first lock,
>>>> probably best to do so regardless so other users don't trip over it.
>>> This is actually critical, because if this trylock is the first lock
>>> acquisition for the context, there won't be any other opportunity to
>>> reset this value.
>>>
>>>>> +
>>>>> +	if (__mutex_trylock(&ww->base)) {
>>>>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
>>>>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
>>>>> +		return 1;
>>>>> +	}
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL(ww_mutex_trylock);
>>> Updated version below...
>>>
>>> ---
>>> Subject: kernel/locking: Add context to ww_mutex_trylock()
>>> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Date: Thu, 9 Sep 2021 11:32:18 +0200
>>>
>>> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>>
>>> i915 will soon gain an eviction path that trylock a whole lot of locks
>>> for eviction, getting dmesg failures like below:
>>>
>>>   BUG: MAX_LOCK_DEPTH too low!
>>>   turning off the locking correctness validator.
>>>   depth: 48  max: 48!
>>>   48 locks held by i915_selftest/5776:
>>>    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>>>    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>>>    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>>>    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>>>    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>   ...
>>>    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>   INFO: lockdep is turned off.
>>>
>>> Fixing eviction to nest into ww_class_acquire is a high priority, but
>>> it requires a rework of the entire driver, which can only be done one
>>> step at a time.
>>>
>>> As an intermediate solution, add an acquire context to
>>> ww_mutex_trylock, which allows us to do proper nesting annotations on
>>> the trylocks, making the above lockdep splat disappear.
>>>
>>> This is also useful in regulator_lock_nested, which may avoid dropping
>>> regulator_nesting_mutex in the uncontended path, so use it there.
>>>
>>> TTM may be another user for this, where we could lock a buffer in a
>>> fastpath with list locks held, without dropping all locks we hold.
>>>
>>> [peterz: rework actual ww_mutex_trylock() implementations]
>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
>>> ---
>> My original patch series with this patch in place still passes i915 selftests, looks good to me. :)
> For merge logistics, can we pls have a stable branch? I expect that the
> i915 patches will be ready for 5.16.
>
> Or send it in for -rc2 so that the interface change doesn't cause needless
> conflicts, whatever you think is best.
> -Daniel
Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-16 13:00                     ` Maarten Lankhorst
  0 siblings, 0 replies; 51+ messages in thread
From: Maarten Lankhorst @ 2021-09-16 13:00 UTC (permalink / raw)
  To: Peter Zijlstra, intel-gfx, dri-devel, Ingo Molnar, Will Deacon,
	Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Op 14-09-2021 om 15:54 schreef Daniel Vetter:
> On Tue, Sep 14, 2021 at 02:43:02PM +0200, Maarten Lankhorst wrote:
>> Op 14-09-2021 om 08:50 schreef Peter Zijlstra:
>>> On Mon, Sep 13, 2021 at 10:42:36AM +0200, Maarten Lankhorst wrote:
>>>
>>>>> +/**
>>>>> + * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
>>>>> + * @ww: mutex to lock
>>>>> + * @ww_ctx: optional w/w acquire context
>>>>> + *
>>>>> + * Trylocks a mutex with the optional acquire context; no deadlock detection is
>>>>> + * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
>>>>> + *
>>>>> + * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
>>>>> + * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
>>>>> + *
>>>>> + * A mutex acquired with this function must be released with ww_mutex_unlock.
>>>>> + */
>>>>> +int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
>>>>> +{
>>>>> +	if (!ww_ctx)
>>>>> +		return mutex_trylock(&ww->base);
>>>>> +
>>>>> +	MUTEX_WARN_ON(ww->base.magic != &ww->base);
>>>>> +
>>>>> +	if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
>>>>> +		return -EALREADY;
>>>> I'm not 100% sure this is a good idea, because it would make the
>>>> trylock weird.  For i915 I checked manually, because I didn't want to
>>>> change the function signature. This is probably the other extreme.
>>>>
>>>> "if (ww_mutex_trylock())" would look correct, but actually be wrong
>>>> and lead to double unlock without adjustments.  Maybe we could make a
>>>> ww_mutex_trylock_ctx_err, which would return -EALREADY or -EBUSY on
>>>> failure, and 0 on success?  We could keep ww_mutex_trylock without
>>>> ctx, probably just #define as (!ww_mutex_trylock_ctx_err(lock, NULL))
>>> Urgh, yeah. Also, I suppose that if we already own it, we'll just fail
>>> the trylock anyway. Let me take this out.
>>>
>>>>> +	/*
>>>>> +	 * Reset the wounded flag after a kill. No other process can
>>>>> +	 * race and wound us here, since they can't have a valid owner
>>>>> +	 * pointer if we don't have any locks held.
>>>>> +	 */
>>>>> +	if (ww_ctx->acquired == 0)
>>>>> +		ww_ctx->wounded = 0;
>>>> Yeah I guess this needs fixing too. Not completely sure since trylock
>>>> wouldn't do the whole ww dance, but since it's our first lock,
>>>> probably best to do so regardless so other users don't trip over it.
>>> This is actually critical, because if this trylock is the first lock
>>> acquisition for the context, there won't be any other opportunity to
>>> reset this value.
>>>
>>>>> +
>>>>> +	if (__mutex_trylock(&ww->base)) {
>>>>> +		ww_mutex_set_context_fastpath(ww, ww_ctx);
>>>>> +		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
>>>>> +		return 1;
>>>>> +	}
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +EXPORT_SYMBOL(ww_mutex_trylock);
>>> Updated version below...
>>>
>>> ---
>>> Subject: kernel/locking: Add context to ww_mutex_trylock()
>>> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Date: Thu, 9 Sep 2021 11:32:18 +0200
>>>
>>> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>>
>>> i915 will soon gain an eviction path that trylock a whole lot of locks
>>> for eviction, getting dmesg failures like below:
>>>
>>>   BUG: MAX_LOCK_DEPTH too low!
>>>   turning off the locking correctness validator.
>>>   depth: 48  max: 48!
>>>   48 locks held by i915_selftest/5776:
>>>    #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
>>>    #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
>>>    #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
>>>    #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
>>>    #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>    #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>   ...
>>>    #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>    #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
>>>   INFO: lockdep is turned off.
>>>
>>> Fixing eviction to nest into ww_class_acquire is a high priority, but
>>> it requires a rework of the entire driver, which can only be done one
>>> step at a time.
>>>
>>> As an intermediate solution, add an acquire context to
>>> ww_mutex_trylock, which allows us to do proper nesting annotations on
>>> the trylocks, making the above lockdep splat disappear.
>>>
>>> This is also useful in regulator_lock_nested, which may avoid dropping
>>> regulator_nesting_mutex in the uncontended path, so use it there.
>>>
>>> TTM may be another user for this, where we could lock a buffer in a
>>> fastpath with list locks held, without dropping all locks we hold.
>>>
>>> [peterz: rework actual ww_mutex_trylock() implementations]
>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
>>> ---
>> My original patch series with this patch in place still passes i915 selftests, looks good to me. :)
> For merge logistics, can we pls have a stable branch? I expect that the
> i915 patches will be ready for 5.16.
>
> Or send it in for -rc2 so that the interface change doesn't cause needless
> conflicts, whatever you think is best.
> -Daniel
Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-16 13:00                     ` [Intel-gfx] " Maarten Lankhorst
@ 2021-09-16 13:28                       ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-16 13:28 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:

> > For merge logistics, can we pls have a stable branch? I expect that the
> > i915 patches will be ready for 5.16.
> >
> > Or send it in for -rc2 so that the interface change doesn't cause needless
> > conflicts, whatever you think is best.

> Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)

I think I'll make tip/locking/wwmutex and include that in
tip/locking/core, let me have a poke.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-16 13:28                       ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-16 13:28 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:

> > For merge logistics, can we pls have a stable branch? I expect that the
> > i915 patches will be ready for 5.16.
> >
> > Or send it in for -rc2 so that the interface change doesn't cause needless
> > conflicts, whatever you think is best.

> Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)

I think I'll make tip/locking/wwmutex and include that in
tip/locking/core, let me have a poke.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-16 13:28                       ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-17 13:13                         ` Peter Zijlstra
  -1 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-17 13:13 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 16, 2021 at 03:28:11PM +0200, Peter Zijlstra wrote:
> On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:
> 
> > > For merge logistics, can we pls have a stable branch? I expect that the
> > > i915 patches will be ready for 5.16.
> > >
> > > Or send it in for -rc2 so that the interface change doesn't cause needless
> > > conflicts, whatever you think is best.
> 
> > Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)
> 
> I think I'll make tip/locking/wwmutex and include that in
> tip/locking/core, let me have a poke.

This is now so. Enjoy!

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-17 13:13                         ` Peter Zijlstra
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Zijlstra @ 2021-09-17 13:13 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

On Thu, Sep 16, 2021 at 03:28:11PM +0200, Peter Zijlstra wrote:
> On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:
> 
> > > For merge logistics, can we pls have a stable branch? I expect that the
> > > i915 patches will be ready for 5.16.
> > >
> > > Or send it in for -rc2 so that the interface change doesn't cause needless
> > > conflicts, whatever you think is best.
> 
> > Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)
> 
> I think I'll make tip/locking/wwmutex and include that in
> tip/locking/core, let me have a poke.

This is now so. Enjoy!

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [tip: locking/core] kernel/locking: Add context to ww_mutex_trylock()
  2021-09-14  6:50               ` [Intel-gfx] " Peter Zijlstra
  (?)
  (?)
@ 2021-09-17 13:17               ` tip-bot2 for Maarten Lankhorst
  -1 siblings, 0 replies; 51+ messages in thread
From: tip-bot2 for Maarten Lankhorst @ 2021-09-17 13:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Maarten Lankhorst, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     12235da8c80a1f9909008e4ca6036d5772b81192
Gitweb:        https://git.kernel.org/tip/12235da8c80a1f9909008e4ca6036d5772b81192
Author:        Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
AuthorDate:    Thu, 09 Sep 2021 11:32:18 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 17 Sep 2021 15:08:41 +02:00

kernel/locking: Add context to ww_mutex_trylock()

i915 will soon gain an eviction path that trylock a whole lot of locks
for eviction, getting dmesg failures like below:

  BUG: MAX_LOCK_DEPTH too low!
  turning off the locking correctness validator.
  depth: 48  max: 48!
  48 locks held by i915_selftest/5776:
   #0: ffff888101a79240 (&dev->mutex){....}-{3:3}, at: __driver_attach+0x88/0x160
   #1: ffffc900009778c0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_vma_pin.constprop.63+0x39/0x1b0 [i915]
   #2: ffff88800cf74de8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_vma_pin.constprop.63+0x5f/0x1b0 [i915]
   #3: ffff88810c7f9e38 (&vm->mutex/1){+.+.}-{3:3}, at: i915_vma_pin_ww+0x1c4/0x9d0 [i915]
   #4: ffff88810bad5768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #5: ffff88810bad60e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  ...
   #46: ffff88811964d768 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
   #47: ffff88811964e0e8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: i915_gem_evict_something+0x110/0x860 [i915]
  INFO: lockdep is turned off.

Fixing eviction to nest into ww_class_acquire is a high priority, but
it requires a rework of the entire driver, which can only be done one
step at a time.

As an intermediate solution, add an acquire context to
ww_mutex_trylock, which allows us to do proper nesting annotations on
the trylocks, making the above lockdep splat disappear.

This is also useful in regulator_lock_nested, which may avoid dropping
regulator_nesting_mutex in the uncontended path, so use it there.

TTM may be another user for this, where we could lock a buffer in a
fastpath with list locks held, without dropping all locks we hold.

[peterz: rework actual ww_mutex_trylock() implementations]
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/YUBGPdDDjKlxAuXJ@hirez.programming.kicks-ass.net
---
 drivers/gpu/drm/drm_modeset_lock.c |  2 +-
 drivers/regulator/core.c           |  2 +-
 include/linux/dma-resv.h           |  2 +-
 include/linux/ww_mutex.h           | 15 +-----
 kernel/locking/mutex.c             | 41 ++++++++++++++-
 kernel/locking/test-ww_mutex.c     | 86 +++++++++++++++++++++--------
 kernel/locking/ww_rt_mutex.c       | 25 ++++++++-
 lib/locking-selftest.c             |  2 +-
 8 files changed, 137 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index fcfe1a0..bf8a6e8 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -248,7 +248,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
 	if (ctx->trylock_only) {
 		lockdep_assert_held(&ctx->ww_ctx);
 
-		if (!ww_mutex_trylock(&lock->mutex))
+		if (!ww_mutex_trylock(&lock->mutex, NULL))
 			return -EBUSY;
 		else
 			return 0;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index ca6caba..f4d441b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -145,7 +145,7 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev,
 
 	mutex_lock(&regulator_nesting_mutex);
 
-	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
 		if (rdev->mutex_owner == current)
 			rdev->ref_cnt++;
 		else
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index e1ca208..39fefb8 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -173,7 +173,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
  */
 static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
 {
-	return ww_mutex_trylock(&obj->lock);
+	return ww_mutex_trylock(&obj->lock, NULL);
 }
 
 /**
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 29db736..bb76308 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -28,12 +28,10 @@
 #ifndef CONFIG_PREEMPT_RT
 #define WW_MUTEX_BASE			mutex
 #define ww_mutex_base_init(l,n,k)	__mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	mutex_is_locked((b))
 #else
 #define WW_MUTEX_BASE			rt_mutex
 #define ww_mutex_base_init(l,n,k)	__rt_mutex_init(l,n,k)
-#define ww_mutex_base_trylock(l)	rt_mutex_trylock(l)
 #define ww_mutex_base_is_locked(b)	rt_mutex_base_is_locked(&(b)->rtmutex)
 #endif
 
@@ -339,17 +337,8 @@ ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
 
 extern void ww_mutex_unlock(struct ww_mutex *lock);
 
-/**
- * ww_mutex_trylock - tries to acquire the w/w mutex without acquire context
- * @lock: mutex to lock
- *
- * Trylocks a mutex without acquire context, so no deadlock detection is
- * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
- */
-static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock)
-{
-	return ww_mutex_base_trylock(&lock->base);
-}
+extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
+					 struct ww_acquire_ctx *ctx);
 
 /***
  * ww_mutex_destroy - mark a w/w mutex unusable
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index d456579..2fede72 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -94,6 +94,9 @@ static inline unsigned long __owner_flags(unsigned long owner)
 	return owner & MUTEX_FLAGS;
 }
 
+/*
+ * Returns: __mutex_owner(lock) on failure or NULL on success.
+ */
 static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
 {
 	unsigned long owner, curr = (unsigned long)current;
@@ -736,6 +739,44 @@ __ww_mutex_lock(struct mutex *lock, unsigned int state, unsigned int subclass,
 	return __mutex_lock_common(lock, state, subclass, NULL, ip, ww_ctx, true);
 }
 
+/**
+ * ww_mutex_trylock - tries to acquire the w/w mutex with optional acquire context
+ * @ww: mutex to lock
+ * @ww_ctx: optional w/w acquire context
+ *
+ * Trylocks a mutex with the optional acquire context; no deadlock detection is
+ * possible. Returns 1 if the mutex has been acquired successfully, 0 otherwise.
+ *
+ * Unlike ww_mutex_lock, no deadlock handling is performed. However, if a @ctx is
+ * specified, -EALREADY handling may happen in calls to ww_mutex_trylock.
+ *
+ * A mutex acquired with this function must be released with ww_mutex_unlock.
+ */
+int ww_mutex_trylock(struct ww_mutex *ww, struct ww_acquire_ctx *ww_ctx)
+{
+	if (!ww_ctx)
+		return mutex_trylock(&ww->base);
+
+	MUTEX_WARN_ON(ww->base.magic != &ww->base);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__mutex_trylock(&ww->base)) {
+		ww_mutex_set_context_fastpath(ww, ww_ctx);
+		mutex_acquire_nest(&ww->base.dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 void __sched
 mutex_lock_nested(struct mutex *lock, unsigned int subclass)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 3e82f44..d63ac41 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -16,6 +16,15 @@
 static DEFINE_WD_CLASS(ww_class);
 struct workqueue_struct *wq;
 
+#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
+#define ww_acquire_init_noinject(a, b) do { \
+		ww_acquire_init((a), (b)); \
+		(a)->deadlock_inject_countdown = ~0U; \
+	} while (0)
+#else
+#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
+#endif
+
 struct test_mutex {
 	struct work_struct work;
 	struct ww_mutex mutex;
@@ -36,7 +45,7 @@ static void test_mutex_work(struct work_struct *work)
 	wait_for_completion(&mtx->go);
 
 	if (mtx->flags & TEST_MTX_TRY) {
-		while (!ww_mutex_trylock(&mtx->mutex))
+		while (!ww_mutex_trylock(&mtx->mutex, NULL))
 			cond_resched();
 	} else {
 		ww_mutex_lock(&mtx->mutex, NULL);
@@ -109,19 +118,38 @@ static int test_mutex(void)
 	return 0;
 }
 
-static int test_aa(void)
+static int test_aa(bool trylock)
 {
 	struct ww_mutex mutex;
 	struct ww_acquire_ctx ctx;
 	int ret;
+	const char *from = trylock ? "trylock" : "lock";
 
 	ww_mutex_init(&mutex, &ww_class);
 	ww_acquire_init(&ctx, &ww_class);
 
-	ww_mutex_lock(&mutex, &ctx);
+	if (!trylock) {
+		ret = ww_mutex_lock(&mutex, &ctx);
+		if (ret) {
+			pr_err("%s: initial lock failed!\n", __func__);
+			goto out;
+		}
+	} else {
+		if (!ww_mutex_trylock(&mutex, &ctx)) {
+			pr_err("%s: initial trylock failed!\n", __func__);
+			goto out;
+		}
+	}
 
-	if (ww_mutex_trylock(&mutex))  {
-		pr_err("%s: trylocked itself!\n", __func__);
+	if (ww_mutex_trylock(&mutex, NULL))  {
+		pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
+		ww_mutex_unlock(&mutex);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ww_mutex_trylock(&mutex, &ctx))  {
+		pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
 		ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
@@ -129,17 +157,17 @@ static int test_aa(void)
 
 	ret = ww_mutex_lock(&mutex, &ctx);
 	if (ret != -EALREADY) {
-		pr_err("%s: missed deadlock for recursing, ret=%d\n",
-		       __func__, ret);
+		pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
+		       __func__, ret, from);
 		if (!ret)
 			ww_mutex_unlock(&mutex);
 		ret = -EINVAL;
 		goto out;
 	}
 
+	ww_mutex_unlock(&mutex);
 	ret = 0;
 out:
-	ww_mutex_unlock(&mutex);
 	ww_acquire_fini(&ctx);
 	return ret;
 }
@@ -150,7 +178,7 @@ struct test_abba {
 	struct ww_mutex b_mutex;
 	struct completion a_ready;
 	struct completion b_ready;
-	bool resolve;
+	bool resolve, trylock;
 	int result;
 };
 
@@ -160,8 +188,13 @@ static void test_abba_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err;
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba->b_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!abba->trylock)
+		ww_mutex_lock(&abba->b_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
 
 	complete(&abba->b_ready);
 	wait_for_completion(&abba->a_ready);
@@ -181,7 +214,7 @@ static void test_abba_work(struct work_struct *work)
 	abba->result = err;
 }
 
-static int test_abba(bool resolve)
+static int test_abba(bool trylock, bool resolve)
 {
 	struct test_abba abba;
 	struct ww_acquire_ctx ctx;
@@ -192,12 +225,18 @@ static int test_abba(bool resolve)
 	INIT_WORK_ONSTACK(&abba.work, test_abba_work);
 	init_completion(&abba.a_ready);
 	init_completion(&abba.b_ready);
+	abba.trylock = trylock;
 	abba.resolve = resolve;
 
 	schedule_work(&abba.work);
 
-	ww_acquire_init(&ctx, &ww_class);
-	ww_mutex_lock(&abba.a_mutex, &ctx);
+	ww_acquire_init_noinject(&ctx, &ww_class);
+	if (!trylock)
+		ww_mutex_lock(&abba.a_mutex, &ctx);
+	else
+		WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
+
+	WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
 
 	complete(&abba.a_ready);
 	wait_for_completion(&abba.b_ready);
@@ -249,7 +288,7 @@ static void test_cycle_work(struct work_struct *work)
 	struct ww_acquire_ctx ctx;
 	int err, erra = 0;
 
-	ww_acquire_init(&ctx, &ww_class);
+	ww_acquire_init_noinject(&ctx, &ww_class);
 	ww_mutex_lock(&cycle->a_mutex, &ctx);
 
 	complete(cycle->a_signal);
@@ -581,7 +620,9 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
 static int __init test_ww_mutex_init(void)
 {
 	int ncpus = num_online_cpus();
-	int ret;
+	int ret, i;
+
+	printk(KERN_INFO "Beginning ww mutex selftests\n");
 
 	wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
 	if (!wq)
@@ -591,17 +632,19 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
-	ret = test_aa();
+	ret = test_aa(false);
 	if (ret)
 		return ret;
 
-	ret = test_abba(false);
+	ret = test_aa(true);
 	if (ret)
 		return ret;
 
-	ret = test_abba(true);
-	if (ret)
-		return ret;
+	for (i = 0; i < 4; i++) {
+		ret = test_abba(i & 1, i & 2);
+		if (ret)
+			return ret;
+	}
 
 	ret = test_cycle(ncpus);
 	if (ret)
@@ -619,6 +662,7 @@ static int __init test_ww_mutex_init(void)
 	if (ret)
 		return ret;
 
+	printk(KERN_INFO "All ww mutex selftests passed\n");
 	return 0;
 }
 
diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 3f1fff7..0e00205 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -9,6 +9,31 @@
 #define WW_RT
 #include "rtmutex.c"
 
+int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
+{
+	struct rt_mutex *rtm = &lock->base;
+
+	if (!ww_ctx)
+		return rt_mutex_trylock(rtm);
+
+	/*
+	 * Reset the wounded flag after a kill. No other process can
+	 * race and wound us here, since they can't have a valid owner
+	 * pointer if we don't have any locks held.
+	 */
+	if (ww_ctx->acquired == 0)
+		ww_ctx->wounded = 0;
+
+	if (__rt_mutex_trylock(&rtm->rtmutex)) {
+		ww_mutex_set_context_fastpath(lock, ww_ctx);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ww_mutex_trylock);
+
 static int __sched
 __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
 		   unsigned int state, unsigned long ip)
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 161108e..71652e1 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -258,7 +258,7 @@ static void init_shared_classes(void)
 #define WWAF(x)			ww_acquire_fini(x)
 
 #define WWL(x, c)		ww_mutex_lock(x, c)
-#define WWT(x)			ww_mutex_trylock(x)
+#define WWT(x)			ww_mutex_trylock(x, NULL)
 #define WWL1(x)			ww_mutex_lock(x, NULL)
 #define WWU(x)			ww_mutex_unlock(x)
 

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
  2021-09-17 13:13                         ` [Intel-gfx] " Peter Zijlstra
@ 2021-09-20 15:02                           ` Joonas Lahtinen
  -1 siblings, 0 replies; 51+ messages in thread
From: Joonas Lahtinen @ 2021-09-20 15:02 UTC (permalink / raw)
  To: Maarten Lankhorst, Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Quoting Peter Zijlstra (2021-09-17 16:13:19)
> On Thu, Sep 16, 2021 at 03:28:11PM +0200, Peter Zijlstra wrote:
> > On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:
> > 
> > > > For merge logistics, can we pls have a stable branch? I expect that the
> > > > i915 patches will be ready for 5.16.
> > > >
> > > > Or send it in for -rc2 so that the interface change doesn't cause needless
> > > > conflicts, whatever you think is best.
> > 
> > > Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)
> > 
> > I think I'll make tip/locking/wwmutex and include that in
> > tip/locking/core, let me have a poke.
> 
> This is now so. Enjoy!

This is now merged to drm-intel-gt-next.

Regards, Joonas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Intel-gfx] [PATCH v2] kernel/locking: Add context to ww_mutex_trylock.
@ 2021-09-20 15:02                           ` Joonas Lahtinen
  0 siblings, 0 replies; 51+ messages in thread
From: Joonas Lahtinen @ 2021-09-20 15:02 UTC (permalink / raw)
  To: Maarten Lankhorst, Peter Zijlstra
  Cc: intel-gfx, dri-devel, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, Liam Girdwood, Mark Brown, linux-kernel

Quoting Peter Zijlstra (2021-09-17 16:13:19)
> On Thu, Sep 16, 2021 at 03:28:11PM +0200, Peter Zijlstra wrote:
> > On Thu, Sep 16, 2021 at 03:00:39PM +0200, Maarten Lankhorst wrote:
> > 
> > > > For merge logistics, can we pls have a stable branch? I expect that the
> > > > i915 patches will be ready for 5.16.
> > > >
> > > > Or send it in for -rc2 so that the interface change doesn't cause needless
> > > > conflicts, whatever you think is best.
> > 
> > > Yeah, some central branch drm could pull from, would make upstreaming patches that depends on it easier. :)
> > 
> > I think I'll make tip/locking/wwmutex and include that in
> > tip/locking/core, let me have a poke.
> 
> This is now so. Enjoy!

This is now merged to drm-intel-gt-next.

Regards, Joonas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH] kernel/locking: Use a pointer in ww_mutex_trylock().
  2021-09-14  6:50               ` [Intel-gfx] " Peter Zijlstra
  (?)
@ 2021-11-04 12:27                 ` Sebastian Andrzej Siewior
  -1 siblings, 0 replies; 51+ messages in thread
From: Sebastian Andrzej Siewior @ 2021-11-04 12:27 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Maarten Lankhorst, intel-gfx, dri-devel, Ingo Molnar,
	Will Deacon, Waiman Long, Boqun Feng, Liam Girdwood, Mark Brown,
	linux-kernel, Daniel Vetter, Thomas Gleixner

mutex_acquire_nest() expects a pointer, pass the pointer.

Fixes: 12235da8c80a1 ("kernel/locking: Add context to ww_mutex_trylock()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---

Not sure why I haven't seen this earlier…

 kernel/locking/ww_rt_mutex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 0e00205cf467a..d1473c624105c 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -26,7 +26,7 @@ int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
 
 	if (__rt_mutex_trylock(&rtm->rtmutex)) {
 		ww_mutex_set_context_fastpath(lock, ww_ctx);
-		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
 		return 1;
 	}
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH] kernel/locking: Use a pointer in ww_mutex_trylock().
@ 2021-11-04 12:27                 ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 51+ messages in thread
From: Sebastian Andrzej Siewior @ 2021-11-04 12:27 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Daniel Vetter, intel-gfx, Liam Girdwood, dri-devel, linux-kernel,
	Ingo Molnar, Mark Brown, Waiman Long, Thomas Gleixner,
	Will Deacon, Boqun Feng

mutex_acquire_nest() expects a pointer, pass the pointer.

Fixes: 12235da8c80a1 ("kernel/locking: Add context to ww_mutex_trylock()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---

Not sure why I haven't seen this earlier…

 kernel/locking/ww_rt_mutex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 0e00205cf467a..d1473c624105c 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -26,7 +26,7 @@ int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
 
 	if (__rt_mutex_trylock(&rtm->rtmutex)) {
 		ww_mutex_set_context_fastpath(lock, ww_ctx);
-		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
 		return 1;
 	}
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] [PATCH] kernel/locking: Use a pointer in ww_mutex_trylock().
@ 2021-11-04 12:27                 ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 51+ messages in thread
From: Sebastian Andrzej Siewior @ 2021-11-04 12:27 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Daniel Vetter, intel-gfx, Liam Girdwood, dri-devel, linux-kernel,
	Ingo Molnar, Mark Brown, Waiman Long, Thomas Gleixner,
	Will Deacon, Boqun Feng

mutex_acquire_nest() expects a pointer, pass the pointer.

Fixes: 12235da8c80a1 ("kernel/locking: Add context to ww_mutex_trylock()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---

Not sure why I haven't seen this earlier…

 kernel/locking/ww_rt_mutex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 0e00205cf467a..d1473c624105c 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -26,7 +26,7 @@ int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
 
 	if (__rt_mutex_trylock(&rtm->rtmutex)) {
 		ww_mutex_set_context_fastpath(lock, ww_ctx);
-		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
 		return 1;
 	}
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for kernel/locking: Add context to ww_mutex_trylock. (rev5)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (9 preceding siblings ...)
  (?)
@ 2021-11-04 16:00 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-11-04 16:00 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 3810 bytes --]

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev5)
URL   : https://patchwork.freedesktop.org/series/94437/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10840 -> Patchwork_21516
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/index.html

Participating hosts (40 -> 35)
------------------------------

  Additional (1): fi-icl-u2 
  Missing    (6): bat-dg1-6 fi-tgl-u2 bat-dg1-5 fi-bsw-cyan bat-adlp-4 fi-bdw-samus 

Known issues
------------

  Here are the changes found in Patchwork_21516 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_cs_nop@fork-gfx0:
    - fi-icl-u2:          NOTRUN -> [SKIP][1] ([fdo#109315]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@amdgpu/amd_cs_nop@fork-gfx0.html

  * igt@gem_huc_copy@huc-copy:
    - fi-icl-u2:          NOTRUN -> [SKIP][2] ([i915#2190])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@gem_huc_copy@huc-copy.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-icl-u2:          NOTRUN -> [SKIP][3] ([fdo#111827]) +8 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@kms_chamelium@hdmi-hpd-fast.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-icl-u2:          NOTRUN -> [SKIP][4] ([fdo#109278]) +2 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_force_connector_basic@force-load-detect:
    - fi-icl-u2:          NOTRUN -> [SKIP][5] ([fdo#109285])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@kms_force_connector_basic@force-load-detect.html

  * igt@prime_vgem@basic-userptr:
    - fi-icl-u2:          NOTRUN -> [SKIP][6] ([i915#3301])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-icl-u2/igt@prime_vgem@basic-userptr.html

  
#### Possible fixes ####

  * igt@i915_pm_rpm@basic-pci-d3-state:
    - fi-skl-6600u:       [FAIL][7] ([i915#3239]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/fi-skl-6600u/igt@i915_pm_rpm@basic-pci-d3-state.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/fi-skl-6600u/igt@i915_pm_rpm@basic-pci-d3-state.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#3239]: https://gitlab.freedesktop.org/drm/intel/issues/3239
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3303]: https://gitlab.freedesktop.org/drm/intel/issues/3303


Build changes
-------------

  * Linux: CI_DRM_10840 -> Patchwork_21516

  CI-20190529: 20190529
  CI_DRM_10840: fd09f2e3683d7fa8894b24a15ab0356fdf922f6c @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6273: 311a141910678cd981621d0c1beebb665137b49a @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_21516: 0525c745cec9e2339e8ea1fae2fb86d0f92b4cdc @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

0525c745cec9 kernel/locking: Use a pointer in ww_mutex_trylock().

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/index.html

[-- Attachment #2: Type: text/html, Size: 4521 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for kernel/locking: Add context to ww_mutex_trylock. (rev5)
  2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
                   ` (10 preceding siblings ...)
  (?)
@ 2021-11-04 18:15 ` Patchwork
  -1 siblings, 0 replies; 51+ messages in thread
From: Patchwork @ 2021-11-04 18:15 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 30278 bytes --]

== Series Details ==

Series: kernel/locking: Add context to ww_mutex_trylock. (rev5)
URL   : https://patchwork.freedesktop.org/series/94437/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10840_full -> Patchwork_21516_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (11 -> 11)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_21516_full:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@kms_big_fb@y-tiled-16bpp-rotate-90:
    - {shard-rkl}:        [PASS][1] -> [SKIP][2] +3 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-6/igt@kms_big_fb@y-tiled-16bpp-rotate-90.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-2/igt@kms_big_fb@y-tiled-16bpp-rotate-90.html

  * igt@kms_big_fb@y-tiled-8bpp-rotate-90:
    - {shard-rkl}:        [SKIP][3] ([fdo#111614]) -> [SKIP][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-6/igt@kms_big_fb@y-tiled-8bpp-rotate-90.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-2/igt@kms_big_fb@y-tiled-8bpp-rotate-90.html

  * igt@kms_big_fb@yf-tiled-64bpp-rotate-90:
    - {shard-rkl}:        [SKIP][5] ([fdo#111615]) -> [SKIP][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-6/igt@kms_big_fb@yf-tiled-64bpp-rotate-90.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-2/igt@kms_big_fb@yf-tiled-64bpp-rotate-90.html

  * igt@kms_flip_tiling@flip-change-tiling:
    - {shard-rkl}:        NOTRUN -> [SKIP][7] +15 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-2/igt@kms_flip_tiling@flip-change-tiling.html

  
Known issues
------------

  Here are the changes found in Patchwork_21516_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_eio@in-flight-contexts-immediate:
    - shard-iclb:         [PASS][8] -> [TIMEOUT][9] ([i915#3070])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb4/igt@gem_eio@in-flight-contexts-immediate.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb8/igt@gem_eio@in-flight-contexts-immediate.html

  * igt@gem_exec_capture@pi@bcs0:
    - shard-skl:          [PASS][10] -> [INCOMPLETE][11] ([i915#2369])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-skl8/igt@gem_exec_capture@pi@bcs0.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl8/igt@gem_exec_capture@pi@bcs0.html

  * igt@gem_exec_fair@basic-pace-solo@rcs0:
    - shard-kbl:          [PASS][12] -> [FAIL][13] ([i915#2842]) +1 similar issue
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-kbl3/igt@gem_exec_fair@basic-pace-solo@rcs0.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl6/igt@gem_exec_fair@basic-pace-solo@rcs0.html

  * igt@gem_exec_fair@basic-pace@vecs0:
    - shard-tglb:         [PASS][14] -> [FAIL][15] ([i915#2842])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb5/igt@gem_exec_fair@basic-pace@vecs0.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb5/igt@gem_exec_fair@basic-pace@vecs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-glk:          [PASS][16] -> [FAIL][17] ([i915#2842])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-glk5/igt@gem_exec_fair@basic-throttle@rcs0.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-glk6/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_pread@exhaustion:
    - shard-apl:          NOTRUN -> [WARN][18] ([i915#2658])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl4/igt@gem_pread@exhaustion.html
    - shard-kbl:          NOTRUN -> [WARN][19] ([i915#2658])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl1/igt@gem_pread@exhaustion.html

  * igt@gem_pwrite@basic-exhaustion:
    - shard-skl:          NOTRUN -> [WARN][20] ([i915#2658])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@gem_pwrite@basic-exhaustion.html

  * igt@gem_userptr_blits@coherency-sync:
    - shard-tglb:         NOTRUN -> [SKIP][21] ([fdo#110542])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@gem_userptr_blits@coherency-sync.html

  * igt@gem_userptr_blits@dmabuf-sync:
    - shard-kbl:          NOTRUN -> [SKIP][22] ([fdo#109271] / [i915#3323])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl3/igt@gem_userptr_blits@dmabuf-sync.html

  * igt@gem_userptr_blits@input-checking:
    - shard-kbl:          NOTRUN -> [DMESG-WARN][23] ([i915#3002])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl2/igt@gem_userptr_blits@input-checking.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-apl:          [PASS][24] -> [DMESG-WARN][25] ([i915#180]) +3 similar issues
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-apl7/igt@gem_workarounds@suspend-resume-context.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl8/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-skl:          [PASS][26] -> [DMESG-WARN][27] ([i915#1436] / [i915#716])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-skl4/igt@gen9_exec_parse@allowed-single.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl8/igt@gen9_exec_parse@allowed-single.html

  * igt@gen9_exec_parse@bb-start-cmd:
    - shard-tglb:         NOTRUN -> [SKIP][28] ([i915#2856]) +1 similar issue
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@gen9_exec_parse@bb-start-cmd.html

  * igt@i915_selftest@live@gt_pm:
    - shard-skl:          NOTRUN -> [DMESG-FAIL][29] ([i915#1886] / [i915#2291])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl7/igt@i915_selftest@live@gt_pm.html

  * igt@i915_suspend@debugfs-reader:
    - shard-tglb:         [PASS][30] -> [INCOMPLETE][31] ([i915#456])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb2/igt@i915_suspend@debugfs-reader.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb7/igt@i915_suspend@debugfs-reader.html

  * igt@kms_async_flips@crc:
    - shard-skl:          NOTRUN -> [FAIL][32] ([i915#4272])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@kms_async_flips@crc.html

  * igt@kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip:
    - shard-skl:          NOTRUN -> [FAIL][33] ([i915#3743])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl6/igt@kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip:
    - shard-kbl:          NOTRUN -> [SKIP][34] ([fdo#109271] / [i915#3777]) +1 similar issue
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl2/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip:
    - shard-skl:          NOTRUN -> [SKIP][35] ([fdo#109271] / [i915#3777]) +1 similar issue
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip:
    - shard-tglb:         NOTRUN -> [SKIP][36] ([fdo#111615])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-iclb:         NOTRUN -> [SKIP][37] ([fdo#110723])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_joiner@2x-modeset:
    - shard-tglb:         NOTRUN -> [SKIP][38] ([i915#2705])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb3/igt@kms_big_joiner@2x-modeset.html

  * igt@kms_ccs@pipe-b-bad-aux-stride-yf_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][39] ([i915#3689]) +1 similar issue
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@kms_ccs@pipe-b-bad-aux-stride-yf_tiled_ccs.html

  * igt@kms_ccs@pipe-b-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc:
    - shard-skl:          NOTRUN -> [SKIP][40] ([fdo#109271] / [i915#3886]) +11 similar issues
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl1/igt@kms_ccs@pipe-b-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-b-crc-primary-basic-y_tiled_gen12_mc_ccs:
    - shard-kbl:          NOTRUN -> [SKIP][41] ([fdo#109271] / [i915#3886]) +7 similar issues
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl4/igt@kms_ccs@pipe-b-crc-primary-basic-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-c-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][42] ([fdo#109271] / [i915#3886]) +3 similar issues
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl4/igt@kms_ccs@pipe-c-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-d-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc:
    - shard-skl:          NOTRUN -> [SKIP][43] ([fdo#109271]) +226 similar issues
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@kms_ccs@pipe-d-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_chamelium@dp-crc-fast:
    - shard-iclb:         NOTRUN -> [SKIP][44] ([fdo#109284] / [fdo#111827]) +1 similar issue
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_chamelium@vga-hpd-for-each-pipe:
    - shard-kbl:          NOTRUN -> [SKIP][45] ([fdo#109271] / [fdo#111827]) +11 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl4/igt@kms_chamelium@vga-hpd-for-each-pipe.html

  * igt@kms_color@pipe-a-ctm-0-75:
    - shard-skl:          [PASS][46] -> [DMESG-WARN][47] ([i915#1982])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-skl10/igt@kms_color@pipe-a-ctm-0-75.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl7/igt@kms_color@pipe-a-ctm-0-75.html

  * igt@kms_color@pipe-b-ctm-0-75:
    - shard-skl:          NOTRUN -> [DMESG-WARN][48] ([i915#1982])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl8/igt@kms_color@pipe-b-ctm-0-75.html

  * igt@kms_color_chamelium@pipe-b-ctm-max:
    - shard-skl:          NOTRUN -> [SKIP][49] ([fdo#109271] / [fdo#111827]) +17 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl1/igt@kms_color_chamelium@pipe-b-ctm-max.html

  * igt@kms_color_chamelium@pipe-d-ctm-limited-range:
    - shard-tglb:         NOTRUN -> [SKIP][50] ([fdo#109284] / [fdo#111827]) +1 similar issue
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@kms_color_chamelium@pipe-d-ctm-limited-range.html
    - shard-apl:          NOTRUN -> [SKIP][51] ([fdo#109271] / [fdo#111827]) +3 similar issues
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl6/igt@kms_color_chamelium@pipe-d-ctm-limited-range.html

  * igt@kms_color_chamelium@pipe-d-degamma:
    - shard-iclb:         NOTRUN -> [SKIP][52] ([fdo#109278] / [fdo#109284] / [fdo#111827])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_color_chamelium@pipe-d-degamma.html

  * igt@kms_content_protection@atomic-dpms:
    - shard-apl:          NOTRUN -> [TIMEOUT][53] ([i915#1319])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl4/igt@kms_content_protection@atomic-dpms.html
    - shard-kbl:          NOTRUN -> [TIMEOUT][54] ([i915#1319]) +1 similar issue
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl1/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_cursor_crc@pipe-a-cursor-512x512-offscreen:
    - shard-tglb:         NOTRUN -> [SKIP][55] ([fdo#109279] / [i915#3359])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb2/igt@kms_cursor_crc@pipe-a-cursor-512x512-offscreen.html

  * igt@kms_cursor_crc@pipe-b-cursor-512x170-sliding:
    - shard-iclb:         NOTRUN -> [SKIP][56] ([fdo#109278] / [fdo#109279])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_cursor_crc@pipe-b-cursor-512x170-sliding.html

  * igt@kms_cursor_crc@pipe-c-cursor-32x10-onscreen:
    - shard-kbl:          NOTRUN -> [SKIP][57] ([fdo#109271]) +130 similar issues
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl6/igt@kms_cursor_crc@pipe-c-cursor-32x10-onscreen.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-skl:          NOTRUN -> [FAIL][58] ([i915#2346])
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_flip@flip-vs-suspend@c-dp1:
    - shard-kbl:          [PASS][59] -> [DMESG-WARN][60] ([i915#180]) +2 similar issues
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-kbl1/igt@kms_flip@flip-vs-suspend@c-dp1.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl1/igt@kms_flip@flip-vs-suspend@c-dp1.html
    - shard-apl:          NOTRUN -> [DMESG-WARN][61] ([i915#180])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl6/igt@kms_flip@flip-vs-suspend@c-dp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile:
    - shard-tglb:         NOTRUN -> [SKIP][62] ([i915#2587])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile:
    - shard-iclb:         [PASS][63] -> [SKIP][64] ([i915#3701])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb7/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt:
    - shard-tglb:         NOTRUN -> [SKIP][65] ([fdo#111825])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb8/igt@kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt.html

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-d:
    - shard-kbl:          NOTRUN -> [SKIP][66] ([fdo#109271] / [i915#533])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl2/igt@kms_pipe_crc_basic@hang-read-crc-pipe-d.html

  * igt@kms_pipe_crc_basic@read-crc-pipe-d-frame-sequence:
    - shard-skl:          NOTRUN -> [SKIP][67] ([fdo#109271] / [i915#533])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl4/igt@kms_pipe_crc_basic@read-crc-pipe-d-frame-sequence.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-7efc:
    - shard-skl:          NOTRUN -> [FAIL][68] ([fdo#108145] / [i915#265]) +3 similar issues
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl6/igt@kms_plane_alpha_blend@pipe-a-alpha-7efc.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb:
    - shard-skl:          NOTRUN -> [FAIL][69] ([i915#265])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl1/igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb:
    - shard-kbl:          NOTRUN -> [FAIL][70] ([i915#265])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl3/igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-basic:
    - shard-kbl:          NOTRUN -> [FAIL][71] ([fdo#108145] / [i915#265]) +1 similar issue
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl1/igt@kms_plane_alpha_blend@pipe-c-alpha-basic.html
    - shard-apl:          NOTRUN -> [FAIL][72] ([fdo#108145] / [i915#265])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl4/igt@kms_plane_alpha_blend@pipe-c-alpha-basic.html

  * igt@kms_plane_scaling@scaler-with-clipping-clamping@pipe-c-scaler-with-clipping-clamping:
    - shard-apl:          NOTRUN -> [SKIP][73] ([fdo#109271] / [i915#2733])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl6/igt@kms_plane_scaling@scaler-with-clipping-clamping@pipe-c-scaler-with-clipping-clamping.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-1:
    - shard-skl:          NOTRUN -> [SKIP][74] ([fdo#109271] / [i915#658]) +5 similar issues
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl7/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-1.html

  * igt@kms_psr2_sf@primary-plane-update-sf-dmg-area-1:
    - shard-kbl:          NOTRUN -> [SKIP][75] ([fdo#109271] / [i915#658]) +3 similar issues
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl4/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area-1.html

  * igt@kms_psr@psr2_primary_page_flip:
    - shard-iclb:         [PASS][76] -> [SKIP][77] ([fdo#109441]) +2 similar issues
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb2/igt@kms_psr@psr2_primary_page_flip.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb1/igt@kms_psr@psr2_primary_page_flip.html

  * igt@kms_psr@psr2_sprite_render:
    - shard-tglb:         NOTRUN -> [FAIL][78] ([i915#132] / [i915#3467])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb3/igt@kms_psr@psr2_sprite_render.html

  * igt@kms_setmode@basic:
    - shard-glk:          [PASS][79] -> [FAIL][80] ([i915#31])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-glk4/igt@kms_setmode@basic.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-glk9/igt@kms_setmode@basic.html

  * igt@kms_vblank@pipe-d-ts-continuation-idle-hang:
    - shard-iclb:         NOTRUN -> [SKIP][81] ([fdo#109278]) +2 similar issues
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@kms_vblank@pipe-d-ts-continuation-idle-hang.html

  * igt@kms_vblank@pipe-d-ts-continuation-suspend:
    - shard-tglb:         [PASS][82] -> [INCOMPLETE][83] ([i915#3896])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb2/igt@kms_vblank@pipe-d-ts-continuation-suspend.html
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb7/igt@kms_vblank@pipe-d-ts-continuation-suspend.html

  * igt@kms_writeback@writeback-pixel-formats:
    - shard-skl:          NOTRUN -> [SKIP][84] ([fdo#109271] / [i915#2437])
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl1/igt@kms_writeback@writeback-pixel-formats.html

  * igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame:
    - shard-apl:          NOTRUN -> [SKIP][85] ([fdo#109271]) +54 similar issues
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl6/igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame.html
    - shard-iclb:         NOTRUN -> [SKIP][86] ([i915#2530])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb6/igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame.html

  * igt@sysfs_clients@fair-0:
    - shard-skl:          NOTRUN -> [SKIP][87] ([fdo#109271] / [i915#2994]) +3 similar issues
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl1/igt@sysfs_clients@fair-0.html

  * igt@sysfs_clients@fair-3:
    - shard-kbl:          NOTRUN -> [SKIP][88] ([fdo#109271] / [i915#2994]) +2 similar issues
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl2/igt@sysfs_clients@fair-3.html

  * igt@sysfs_timeslice_duration@timeout@vecs0:
    - shard-tglb:         [PASS][89] -> [FAIL][90] ([i915#1755])
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb3/igt@sysfs_timeslice_duration@timeout@vecs0.html
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb3/igt@sysfs_timeslice_duration@timeout@vecs0.html

  
#### Possible fixes ####

  * igt@fbdev@info:
    - {shard-rkl}:        [SKIP][91] ([i915#2582]) -> [PASS][92]
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@fbdev@info.html
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@fbdev@info.html

  * igt@gem_ctx_persistence@many-contexts:
    - shard-iclb:         [DMESG-WARN][93] -> [PASS][94]
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb3/igt@gem_ctx_persistence@many-contexts.html
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb4/igt@gem_ctx_persistence@many-contexts.html

  * igt@gem_eio@unwedge-stress:
    - shard-tglb:         [TIMEOUT][95] ([i915#2369] / [i915#3063] / [i915#3648]) -> [PASS][96]
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb7/igt@gem_eio@unwedge-stress.html
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb2/igt@gem_eio@unwedge-stress.html
    - shard-iclb:         [TIMEOUT][97] ([i915#2369] / [i915#2481] / [i915#3070]) -> [PASS][98]
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb4/igt@gem_eio@unwedge-stress.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb2/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_fair@basic-none-solo@rcs0:
    - shard-glk:          [FAIL][99] ([i915#2842]) -> [PASS][100]
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-glk6/igt@gem_exec_fair@basic-none-solo@rcs0.html
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-glk5/igt@gem_exec_fair@basic-none-solo@rcs0.html

  * igt@gem_exec_fair@basic-pace@vecs0:
    - shard-kbl:          [FAIL][101] ([i915#2842]) -> [PASS][102] +1 similar issue
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-kbl6/igt@gem_exec_fair@basic-pace@vecs0.html
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl2/igt@gem_exec_fair@basic-pace@vecs0.html

  * igt@i915_module_load@reload-no-display:
    - shard-tglb:         [DMESG-WARN][103] ([i915#2867]) -> [PASS][104]
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb6/igt@i915_module_load@reload-no-display.html
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb6/igt@i915_module_load@reload-no-display.html

  * igt@i915_pm_dc@dc5-psr:
    - {shard-rkl}:        [SKIP][105] ([i915#658]) -> [PASS][106]
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@i915_pm_dc@dc5-psr.html
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@i915_pm_dc@dc5-psr.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-iclb:         [FAIL][107] ([i915#454]) -> [PASS][108] +1 similar issue
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb3/igt@i915_pm_dc@dc6-dpms.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb7/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_pm_rpm@dpms-mode-unset-lpsp:
    - {shard-rkl}:        [SKIP][109] ([i915#1397]) -> [PASS][110]
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@i915_pm_rpm@dpms-mode-unset-lpsp.html
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@i915_pm_rpm@dpms-mode-unset-lpsp.html

  * igt@i915_pm_rpm@gem-mmap-type@uc:
    - {shard-rkl}:        [SKIP][111] ([fdo#109308]) -> [PASS][112] +3 similar issues
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@i915_pm_rpm@gem-mmap-type@uc.html
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@i915_pm_rpm@gem-mmap-type@uc.html

  * igt@kms_ccs@pipe-a-crc-primary-basic-y_tiled_gen12_rc_ccs:
    - {shard-rkl}:        [SKIP][113] ([i915#1845]) -> [PASS][114] +7 similar issues
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_ccs@pipe-a-crc-primary-basic-y_tiled_gen12_rc_ccs.html
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_ccs@pipe-a-crc-primary-basic-y_tiled_gen12_rc_ccs.html

  * igt@kms_color@pipe-b-ctm-0-25:
    - {shard-rkl}:        [SKIP][115] ([i915#1149] / [i915#1849] / [i915#4070]) -> [PASS][116]
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_color@pipe-b-ctm-0-25.html
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_color@pipe-b-ctm-0-25.html

  * igt@kms_cursor_crc@pipe-b-cursor-64x64-onscreen:
    - {shard-rkl}:        [SKIP][117] ([fdo#112022] / [i915#4070]) -> [PASS][118] +2 similar issues
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_cursor_crc@pipe-b-cursor-64x64-onscreen.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_cursor_crc@pipe-b-cursor-64x64-onscreen.html

  * igt@kms_cursor_edge_walk@pipe-b-128x128-top-edge:
    - {shard-rkl}:        [SKIP][119] ([i915#1849] / [i915#4070]) -> [PASS][120] +1 similar issue
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_cursor_edge_walk@pipe-b-128x128-top-edge.html
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_cursor_edge_walk@pipe-b-128x128-top-edge.html

  * igt@kms_cursor_legacy@cursor-vs-flip-toggle:
    - {shard-rkl}:        [SKIP][121] ([fdo#111825] / [i915#4070]) -> [PASS][122]
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_cursor_legacy@cursor-vs-flip-toggle.html
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_cursor_legacy@cursor-vs-flip-toggle.html

  * igt@kms_cursor_legacy@flip-vs-cursor-varying-size:
    - shard-iclb:         [FAIL][123] ([i915#2346]) -> [PASS][124]
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor-varying-size.html
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-iclb3/igt@kms_cursor_legacy@flip-vs-cursor-varying-size.html

  * igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-xtiled:
    - {shard-rkl}:        [SKIP][125] ([fdo#111314]) -> [PASS][126] +1 similar issue
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-xtiled.html
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-xtiled.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-tglb:         [INCOMPLETE][127] ([i915#456]) -> [PASS][128]
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb7/igt@kms_fbcon_fbt@psr-suspend.html
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb2/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [DMESG-WARN][129] ([i915#180]) -> [PASS][130] +7 similar issues
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-kbl1/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-kbl1/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip@flip-vs-suspend-interruptible@b-dp1:
    - shard-apl:          [DMESG-WARN][131] ([i915#180]) -> [PASS][132] +3 similar issues
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-apl4/igt@kms_flip@flip-vs-suspend-interruptible@b-dp1.html
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-apl4/igt@kms_flip@flip-vs-suspend-interruptible@b-dp1.html

  * igt@kms_flip@flip-vs-suspend-interruptible@c-edp1:
    - shard-tglb:         [DMESG-WARN][133] ([i915#2411] / [i915#2867]) -> [PASS][134]
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-tglb6/igt@kms_flip@flip-vs-suspend-interruptible@c-edp1.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-tglb6/igt@kms_flip@flip-vs-suspend-interruptible@c-edp1.html

  * igt@kms_flip@flip-vs-suspend@b-edp1:
    - shard-skl:          [INCOMPLETE][135] ([i915#198]) -> [PASS][136]
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-skl6/igt@kms_flip@flip-vs-suspend@b-edp1.html
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-skl6/igt@kms_flip@flip-vs-suspend@b-edp1.html

  * igt@kms_invalid_mode@zero-hdisplay:
    - {shard-rkl}:        [SKIP][137] -> [PASS][138] +4 similar issues
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_invalid_mode@zero-hdisplay.html
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_invalid_mode@zero-hdisplay.html

  * igt@kms_pipe_crc_basic@nonblocking-crc-pipe-b-frame-sequence:
    - {shard-rkl}:        [SKIP][139] ([i915#1849]) -> [PASS][140] +8 similar issues
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10840/shard-rkl-2/igt@kms_pipe_crc_basic@nonblocking-crc-pipe-b-frame-sequence.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/shard-rkl-6/igt@kms_pipe_crc_basic@nonblocking-crc-pipe-b-frame-sequence.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [FAIL][141] ([fdo#108145] / [i915#265]) -> [PASS

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21516/index.html

[-- Attachment #2: Type: text/html, Size: 33511 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [tip: locking/core] kernel/locking: Use a pointer in ww_mutex_trylock().
  2021-11-04 12:27                 ` Sebastian Andrzej Siewior
  (?)
  (?)
@ 2021-11-17 13:59                 ` tip-bot2 for Sebastian Andrzej Siewior
  -1 siblings, 0 replies; 51+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2021-11-17 13:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Sebastian Andrzej Siewior, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     2202e15b2b1a946ce760d96748cd7477589701ab
Gitweb:        https://git.kernel.org/tip/2202e15b2b1a946ce760d96748cd7477589701ab
Author:        Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate:    Thu, 04 Nov 2021 13:27:06 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 17 Nov 2021 14:48:49 +01:00

kernel/locking: Use a pointer in ww_mutex_trylock().

mutex_acquire_nest() expects a pointer, pass the pointer.

Fixes: 12235da8c80a1 ("kernel/locking: Add context to ww_mutex_trylock()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20211104122706.frk52zxbjorso2kv@linutronix.de
---
 kernel/locking/ww_rt_mutex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c
index 0e00205..d1473c6 100644
--- a/kernel/locking/ww_rt_mutex.c
+++ b/kernel/locking/ww_rt_mutex.c
@@ -26,7 +26,7 @@ int ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx)
 
 	if (__rt_mutex_trylock(&rtm->rtmutex)) {
 		ww_mutex_set_context_fastpath(lock, ww_ctx);
-		mutex_acquire_nest(&rtm->dep_map, 0, 1, ww_ctx->dep_map, _RET_IP_);
+		mutex_acquire_nest(&rtm->dep_map, 0, 1, &ww_ctx->dep_map, _RET_IP_);
 		return 1;
 	}
 

^ permalink raw reply related	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2021-11-17 13:59 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-07 13:20 [PATCH] kernel/locking: Add context to ww_mutex_trylock Maarten Lankhorst
2021-09-07 13:20 ` [Intel-gfx] " Maarten Lankhorst
2021-09-07 13:54 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2021-09-07 14:27 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2021-09-07 14:59 ` [PATCH] " kernel test robot
2021-09-07 14:59   ` kernel test robot
2021-09-07 14:59   ` [Intel-gfx] " kernel test robot
2021-09-07 17:28 ` [Intel-gfx] ✓ Fi.CI.IGT: success for " Patchwork
2021-09-08 10:14 ` [PATCH] " Peter Zijlstra
2021-09-08 10:14   ` [Intel-gfx] " Peter Zijlstra
2021-09-08 18:30   ` Daniel Vetter
2021-09-08 18:30     ` [Intel-gfx] " Daniel Vetter
2021-09-09  5:38   ` Maarten Lankhorst
2021-09-09  5:38     ` [Intel-gfx] " Maarten Lankhorst
2021-09-09  8:22     ` Peter Zijlstra
2021-09-09  8:22       ` [Intel-gfx] " Peter Zijlstra
2021-09-09  9:32       ` [PATCH v2] " Maarten Lankhorst
2021-09-09  9:32         ` [Intel-gfx] " Maarten Lankhorst
2021-09-10 15:02         ` Peter Zijlstra
2021-09-10 15:02           ` [Intel-gfx] " Peter Zijlstra
2021-09-10 17:27           ` Peter Zijlstra
2021-09-10 17:27             ` [Intel-gfx] " Peter Zijlstra
2021-09-13  8:42           ` Maarten Lankhorst
2021-09-13  8:42             ` [Intel-gfx] " Maarten Lankhorst
2021-09-14  6:50             ` Peter Zijlstra
2021-09-14  6:50               ` [Intel-gfx] " Peter Zijlstra
2021-09-14 12:43               ` Maarten Lankhorst
2021-09-14 12:43                 ` [Intel-gfx] " Maarten Lankhorst
2021-09-14 13:54                 ` Daniel Vetter
2021-09-14 13:54                   ` [Intel-gfx] " Daniel Vetter
2021-09-16 13:00                   ` Maarten Lankhorst
2021-09-16 13:00                     ` [Intel-gfx] " Maarten Lankhorst
2021-09-16 13:28                     ` Peter Zijlstra
2021-09-16 13:28                       ` [Intel-gfx] " Peter Zijlstra
2021-09-17 13:13                       ` Peter Zijlstra
2021-09-17 13:13                         ` [Intel-gfx] " Peter Zijlstra
2021-09-20 15:02                         ` Joonas Lahtinen
2021-09-20 15:02                           ` [Intel-gfx] " Joonas Lahtinen
2021-09-17 13:17               ` [tip: locking/core] kernel/locking: Add context to ww_mutex_trylock() tip-bot2 for Maarten Lankhorst
2021-11-04 12:27               ` [PATCH] kernel/locking: Use a pointer in ww_mutex_trylock() Sebastian Andrzej Siewior
2021-11-04 12:27                 ` [Intel-gfx] " Sebastian Andrzej Siewior
2021-11-04 12:27                 ` Sebastian Andrzej Siewior
2021-11-17 13:59                 ` [tip: locking/core] " tip-bot2 for Sebastian Andrzej Siewior
2021-09-10 18:06         ` [PATCH v2] kernel/locking: Add context to ww_mutex_trylock Mark Brown
2021-09-10 18:06           ` [Intel-gfx] " Mark Brown
2021-09-09  9:50 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for kernel/locking: Add context to ww_mutex_trylock. (rev2) Patchwork
2021-09-10 15:36 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for kernel/locking: Add context to ww_mutex_trylock. (rev3) Patchwork
2021-09-14  9:31 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for kernel/locking: Add context to ww_mutex_trylock. (rev4) Patchwork
2021-09-14  9:58 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2021-11-04 16:00 ` [Intel-gfx] ✓ Fi.CI.BAT: success for kernel/locking: Add context to ww_mutex_trylock. (rev5) Patchwork
2021-11-04 18:15 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.