summaryrefslogtreecommitdiffstats
path: root/include/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-11-12 22:22:21 +0200
committerMarcel Holtmann <marcel@holtmann.org>2014-11-13 07:49:09 +0100
commitabe84903a8efc6b83fa92161429e0e3a28bde15c (patch)
tree3b1b90b1c170c41bbd6fcdae92e8726024c37ade /include/net/bluetooth
parent24ccb9f4f7a3a5a867bbc880019cdb4b41176b63 (diff)
Bluetooth: Use proper nesting annotation for l2cap_chan lock
By default lockdep considers all L2CAP channels equal. This would mean that we get warnings if a channel is locked when another one's lock is tried to be acquired in the same thread. This kind of inter-channel locking dependencies exist in the form of parent-child channels as well as any channel wishing to elevate the security by requesting procedures on the SMP channel. To eliminate the chance for these lockdep warnings we introduce a nesting level for each channel and use that when acquiring the channel lock. For now there exists the earlier mentioned three identified categories: SMP, "normal" channels and parent channels (i.e. those in BT_LISTEN state). The nesting level is defined as atomic_t since we need access to it before the lock is actually acquired. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'include/net/bluetooth')
-rw-r--r--include/net/bluetooth/l2cap.h15
1 files changed, 14 insertions, 1 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index ead99f032f7..061e648052c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -28,6 +28,7 @@
#define __L2CAP_H
#include <asm/unaligned.h>
+#include <linux/atomic.h>
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
@@ -481,6 +482,7 @@ struct l2cap_chan {
struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan;
struct kref kref;
+ atomic_t nesting;
__u8 state;
@@ -713,6 +715,17 @@ enum {
FLAG_HOLD_HCI_CONN,
};
+/* Lock nesting levels for L2CAP channels. We need these because lockdep
+ * otherwise considers all channels equal and will e.g. complain about a
+ * connection oriented channel triggering SMP procedures or a listening
+ * channel creating and locking a child channel.
+ */
+enum {
+ L2CAP_NESTING_SMP,
+ L2CAP_NESTING_NORMAL,
+ L2CAP_NESTING_PARENT,
+};
+
enum {
L2CAP_TX_STATE_XMIT,
L2CAP_TX_STATE_WAIT_F,
@@ -778,7 +791,7 @@ void l2cap_chan_put(struct l2cap_chan *c);
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
{
- mutex_lock(&chan->lock);
+ mutex_lock_nested(&chan->lock, atomic_read(&chan->nesting));
}
static inline void l2cap_chan_unlock(struct l2cap_chan *chan)