diff options
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 46 |
1 files changed, 12 insertions, 34 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 583f7135c811..3e078b73cc22 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -324,23 +324,6 @@ free: | |||
324 | return err; | 324 | return err; |
325 | } | 325 | } |
326 | 326 | ||
327 | static void rfcomm_dev_del(struct rfcomm_dev *dev) | ||
328 | { | ||
329 | unsigned long flags; | ||
330 | BT_DBG("dev %p", dev); | ||
331 | |||
332 | BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)); | ||
333 | |||
334 | spin_lock_irqsave(&dev->port.lock, flags); | ||
335 | if (dev->port.count > 0) { | ||
336 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
337 | return; | ||
338 | } | ||
339 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
340 | |||
341 | tty_port_put(&dev->port); | ||
342 | } | ||
343 | |||
344 | /* ---- Send buffer ---- */ | 327 | /* ---- Send buffer ---- */ |
345 | static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc) | 328 | static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc) |
346 | { | 329 | { |
@@ -454,8 +437,9 @@ static int rfcomm_release_dev(void __user *arg) | |||
454 | tty_kref_put(tty); | 437 | tty_kref_put(tty); |
455 | } | 438 | } |
456 | 439 | ||
457 | if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) | 440 | if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) |
458 | rfcomm_dev_del(dev); | 441 | tty_port_put(&dev->port); |
442 | |||
459 | tty_port_put(&dev->port); | 443 | tty_port_put(&dev->port); |
460 | return 0; | 444 | return 0; |
461 | } | 445 | } |
@@ -607,6 +591,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
607 | * rfcomm_dev_lock -> dlc lock | 591 | * rfcomm_dev_lock -> dlc lock |
608 | * 2. tty_port_put will deadlock if it's | 592 | * 2. tty_port_put will deadlock if it's |
609 | * the last reference | 593 | * the last reference |
594 | * | ||
595 | * FIXME: when we release the lock anything | ||
596 | * could happen to dev, even its destruction | ||
610 | */ | 597 | */ |
611 | rfcomm_dlc_unlock(dlc); | 598 | rfcomm_dlc_unlock(dlc); |
612 | if (rfcomm_dev_get(dev->id) == NULL) { | 599 | if (rfcomm_dev_get(dev->id) == NULL) { |
@@ -614,7 +601,10 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
614 | return; | 601 | return; |
615 | } | 602 | } |
616 | 603 | ||
617 | rfcomm_dev_del(dev); | 604 | if (!test_and_set_bit(RFCOMM_TTY_RELEASED, |
605 | &dev->flags)) | ||
606 | tty_port_put(&dev->port); | ||
607 | |||
618 | tty_port_put(&dev->port); | 608 | tty_port_put(&dev->port); |
619 | rfcomm_dlc_lock(dlc); | 609 | rfcomm_dlc_lock(dlc); |
620 | } | 610 | } |
@@ -741,16 +731,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
741 | { | 731 | { |
742 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 732 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
743 | 733 | ||
744 | if (!dev) | ||
745 | return; | ||
746 | |||
747 | BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, | 734 | BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, |
748 | dev->port.count); | 735 | dev->port.count); |
749 | 736 | ||
750 | tty_port_close(&dev->port, tty, filp); | 737 | tty_port_close(&dev->port, tty, filp); |
751 | |||
752 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
753 | tty_port_put(&dev->port); | ||
754 | } | 738 | } |
755 | 739 | ||
756 | static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) | 740 | static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -1050,17 +1034,11 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) | |||
1050 | 1034 | ||
1051 | BT_DBG("tty %p dev %p", tty, dev); | 1035 | BT_DBG("tty %p dev %p", tty, dev); |
1052 | 1036 | ||
1053 | if (!dev) | ||
1054 | return; | ||
1055 | |||
1056 | tty_port_hangup(&dev->port); | 1037 | tty_port_hangup(&dev->port); |
1057 | 1038 | ||
1058 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { | 1039 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) && |
1059 | if (rfcomm_dev_get(dev->id) == NULL) | 1040 | !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) |
1060 | return; | ||
1061 | rfcomm_dev_del(dev); | ||
1062 | tty_port_put(&dev->port); | 1041 | tty_port_put(&dev->port); |
1063 | } | ||
1064 | } | 1042 | } |
1065 | 1043 | ||
1066 | static int rfcomm_tty_tiocmget(struct tty_struct *tty) | 1044 | static int rfcomm_tty_tiocmget(struct tty_struct *tty) |