summaryrefslogtreecommitdiff
path: root/net/bluetooth/rfcomm/tty.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-06-16 11:24:17 +0200
committerIngo Molnar <mingo@elte.hu>2008-06-16 11:24:17 +0200
commit9583f3d9c00974911daf227cbaa12d6c1caaabad (patch)
treef37466204ecbfea37c7d567fd06c9bece0cc663d /net/bluetooth/rfcomm/tty.c
parent962cf36c5bf6d2840b8d66ee9a606fae2f540bbd (diff)
parent066519068ad2fbe98c7f45552b1f592903a9c8c8 (diff)
Merge branch 'linus' into core/softirqtip-core-softirq-2008-06-16_09.24_Mon
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r--net/bluetooth/rfcomm/tty.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index c3f749abb2d0..c9191871c1e0 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -566,11 +566,22 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
if (dlc->state == BT_CLOSED) {
if (!dev->tty) {
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
- if (rfcomm_dev_get(dev->id) == NULL)
+ /* Drop DLC lock here to avoid deadlock
+ * 1. rfcomm_dev_get will take rfcomm_dev_lock
+ * but in rfcomm_dev_add there's lock order:
+ * rfcomm_dev_lock -> dlc lock
+ * 2. rfcomm_dev_put will deadlock if it's
+ * the last reference
+ */
+ rfcomm_dlc_unlock(dlc);
+ if (rfcomm_dev_get(dev->id) == NULL) {
+ rfcomm_dlc_lock(dlc);
return;
+ }
rfcomm_dev_del(dev);
rfcomm_dev_put(dev);
+ rfcomm_dlc_lock(dlc);
}
} else
tty_hangup(dev->tty);