summaryrefslogtreecommitdiff
path: root/net/bluetooth/rfcomm/tty.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-06-16 11:24:00 +0200
committerIngo Molnar <mingo@elte.hu>2008-06-16 11:24:00 +0200
commit6d72b7952fa7d7c61d021398970c29afde6a4443 (patch)
tree31c00be8e2837e2db2e62c694421a93a9f4c79d7 /net/bluetooth/rfcomm/tty.c
parent6360b1fbb4a939efd34fc770c2ebd927c55506e0 (diff)
parent066519068ad2fbe98c7f45552b1f592903a9c8c8 (diff)
Merge branch 'linus' into core/rodatatip-core-rodata-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);