summaryrefslogtreecommitdiffstats
path: root/include/net/bluetooth
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-01 21:15:45 +0200
committerMarcel Holtmann <marcel@holtmann.org>2010-05-10 09:28:53 +0200
commitdfc909befbfe967bd7f46ef33b6969c1b7f3cf42 (patch)
treecec8545cce920fe194a2d167467a1ca500c2616d /include/net/bluetooth
parentBluetooth: Add wait_queue to wait ack of all sent packets (diff)
downloadlinux-dfc909befbfe967bd7f46ef33b6969c1b7f3cf42.tar.xz
linux-dfc909befbfe967bd7f46ef33b6969c1b7f3cf42.zip
Bluetooth: Fix race condition on l2cap_ertm_send()
l2cap_ertm_send() can be called both from user context and bottom half context. The socket locks for that contexts are different, the user context uses a mutex(which can sleep) and the second one uses a spinlock_bh. That creates a race condition when we have interruptions on both contexts at the same time. The better way to solve this is to add a new spinlock to lock l2cap_ertm_send() and the vars it access. The other solution was to defer l2cap_ertm_send() with a workqueue, but we the sending process already has one defer on the hci layer. It's not a good idea add another one. The patch refactor the code to create l2cap_retransmit_frames(), then we encapulate the lock of l2cap_ertm_send() for some call. It also changes l2cap_retransmit_frame() to l2cap_retransmit_one_frame() to avoid confusion Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'include/net/bluetooth')
-rw-r--r--include/net/bluetooth/l2cap.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d0185cc04c14..7c695bfd853c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -353,6 +353,7 @@ struct l2cap_pinfo {
__le16 sport;
+ spinlock_t send_lock;
struct timer_list retrans_timer;
struct timer_list monitor_timer;
struct timer_list ack_timer;