char                    name[12];
        int                     id;
        unsigned long           flags;
-       int                     opened;
+       atomic_t                opened;
        int                     err;
 
        bdaddr_t                src;
        dev->flags = req->flags &
                ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
 
+       atomic_set(&dev->opened, 0);
+
        init_waitqueue_head(&dev->wait);
        tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
 
 {
        BT_DBG("dev %p", dev);
 
-       if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
-               BUG_ON(1);
-       else
-               set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
+       BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
+
+       if (atomic_read(&dev->opened) > 0)
+               return;
 
        write_lock_bh(&rfcomm_dev_lock);
        list_del_init(&dev->list);
        if (!dev)
                return -ENODEV;
 
-       BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);
+       BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
+                               dev->channel, atomic_read(&dev->opened));
 
-       if (dev->opened++ != 0)
+       if (atomic_inc_return(&dev->opened) > 1)
                return 0;
 
        dlc = dev->dlc;
        if (!dev)
                return;
 
-       BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
+       BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
+                                               atomic_read(&dev->opened));
 
-       if (--dev->opened == 0) {
+       if (atomic_dec_and_test(&dev->opened)) {
                if (dev->tty_dev->parent)
                        device_move(dev->tty_dev, NULL);
 
                tty->driver_data = NULL;
                dev->tty = NULL;
                rfcomm_dlc_unlock(dev->dlc);
+
+               if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
+                       write_lock_bh(&rfcomm_dev_lock);
+                       list_del_init(&dev->list);
+                       write_unlock_bh(&rfcomm_dev_lock);
+
+                       rfcomm_dev_put(dev);
+               }
        }
 
        rfcomm_dev_put(dev);