Some kernel functions must not be called holding a specific lock. Doing
so could lead to locking problems. Currently these routines call
lock_is_held() to check for lock hold followed by WARN_ON.
Adding a common lockdep interface will help reduce the duplication of this
logic in the rest of the kernel.
Add lockdep_assert_not_held() to be used in these functions to detect
incorrect calls while holding a lock.
lockdep_assert_not_held() provides the opposite functionality of
lockdep_assert_held() which is used to assert calls that require
holding a specific lock.
The need for lockdep_assert_not_held() came up in a discussion on
ath10k patch. ath10k_drain_tx() and i915_vma_pin_ww() are examples
of functions that can use lockdep_assert_not_held().
Link: https://lore.kernel.org/lkml/37a29c383bff2fb1605241ee6c7c9be3784fb3c6.1613171185.git.skhan@linuxfoundation.org/
Link: https://lore.kernel.org/linux-wireless/871rdmu9z9.fsf@codeaurora.org/
This patch series adds lockdep_assert_not_held() and uses it in the
second patch in ath10k_drain_tx() function.
Patch 1 incorporates suggestions from Peter Zijlstra on v1 series
to avoid misfires when lockdep_off() is employed.
Patch 2 Johannes Berg's suggestions as it make it easier to read and
maintain the lock states. These are defines and a enum to avoid changes
to lock_is_held_type() and lockdep_is_held() return types.
Patch 2 is a separate patch because it adds defines to lockdep.h and
kernel/locking/lockdep.c now includes lockdep.h - decided make this
a separate patch just in case issues related to header dependencies
pop up. I can combine Patches 1&2 if that is preferred.
Patch 3 uses the new interface in ath10k_drain_tx() function. Added
Kalle Valo's Ack from v1 for this change.
Tested on the mainline from yesterday.
Shuah Khan (3):
lockdep: add lockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detect conf_mutex held ath10k_drain_tx() calls
drivers/net/wireless/ath/ath10k/mac.c | 2 ++
include/linux/lockdep.h | 18 +++++++++++++++---
kernel/locking/lockdep.c | 6 +++++-
3 files changed, 22 insertions(+), 4 deletions(-)
--
2.27.0
Some kernel functions must be called without holding a specific lock.
Add lockdep_assert_not_held() to be used in these functions to detect
incorrect calls while holding a lock.
lockdep_assert_not_held() provides the opposite functionality of
lockdep_assert_held() which is used to assert calls that require
holding a specific lock.
Incorporates suggestions from Peter Zijlstra to avoid misfires when
lockdep_off() is employed.
The need for lockdep_assert_not_held() came up in a discussion on
ath10k patch. ath10k_drain_tx() and i915_vma_pin_ww() are examples
of functions that can use lockdep_assert_not_held().
Link: https://lore.kernel.org/lkml/37a29c383bff2fb1605241ee6c7c9be3784fb3c6.1613171185.git.skhan@linuxfoundation.org/
Link: https://lore.kernel.org/linux-wireless/871rdmu9z9.fsf@codeaurora.org/
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
---
include/linux/lockdep.h | 11 ++++++++---
kernel/locking/lockdep.c | 5 ++++-
2 files changed, 12 insertions(+), 4 deletions(-)
@@ -294,8 +294,12 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);#define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0)-#define lockdep_assert_held(l) do { \-WARN_ON(debug_locks&&!lockdep_is_held(l));\+#define lockdep_assert_held(l) do { \+WARN_ON(debug_locks&&lockdep_is_held(l)==0);\+}while(0)++#define lockdep_assert_not_held(l) do { \+WARN_ON(debug_locks&&lockdep_is_held(l)==1);\}while(0)#define lockdep_assert_held_write(l) do { \
@@ -384,7 +388,8 @@ extern int lockdep_is_held(const void *);#define lockdep_is_held_type(l, r) (1)#define lockdep_assert_held(l) do { (void)(l); } while (0)-#define lockdep_assert_held_write(l) do { (void)(l); } while (0)+#define lockdep_assert_not_held(l) do { (void)(l); } while (0)+#define lockdep_assert_held_write(l) do { (void)(l); } while (0)#define lockdep_assert_held_read(l) do { (void)(l); } while (0)#define lockdep_assert_held_once(l) do { (void)(l); } while (0)
ath10k_drain_tx() must not be called with conf_mutex held as workers can
use that also. Add call to lockdep_assert_not_held() on conf_mutex to
detect if conf_mutex is held by the caller.
The idea for this patch stemmed from coming across the comment block
above the ath10k_drain_tx() while reviewing the conf_mutex holds during
to debug the conf_mutex lock assert in ath10k_debug_fw_stats_request().
Adding detection to assert on conf_mutex hold will help detect incorrect
usages that could lead to locking problems when async worker routines try
to call this routine.
Link: https://lore.kernel.org/lkml/37a29c383bff2fb1605241ee6c7c9be3784fb3c6.1613171185.git.skhan@linuxfoundation.org/
Link: https://lore.kernel.org/linux-wireless/871rdmu9z9.fsf@codeaurora.org/
Acked-by: Kalle Valo <redacted>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
---
drivers/net/wireless/ath/ath10k/mac.c | 2 ++
1 file changed, 2 insertions(+)
@@ -4567,6 +4567,8 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,/* Must not be called with conf_mutex held as workers can use that also. */voidath10k_drain_tx(structath10k*ar){+lockdep_assert_not_held(&ar->conf_mutex);+/* make sure rcu-protected mac80211 tx path itself is drained */synchronize_net();
Checkpatch didn't complain. What's your preference? Does the
following work for you?
/*
* avoid false negative lockdep_assert_not_held()
* and lockdep_assert_held()
*/
thanks,
-- Shuah