|
@@ -53,7 +53,7 @@ struct rfcomm_dev {
|
|
char name[12];
|
|
char name[12];
|
|
int id;
|
|
int id;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
- int opened;
|
|
|
|
|
|
+ atomic_t opened;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
bdaddr_t src;
|
|
bdaddr_t src;
|
|
@@ -256,6 +256,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
|
dev->flags = req->flags &
|
|
dev->flags = req->flags &
|
|
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
|
|
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
|
|
|
|
|
|
|
|
+ atomic_set(&dev->opened, 0);
|
|
|
|
+
|
|
init_waitqueue_head(&dev->wait);
|
|
init_waitqueue_head(&dev->wait);
|
|
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
|
|
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
|
|
|
|
|
|
@@ -325,10 +327,10 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
|
|
{
|
|
{
|
|
BT_DBG("dev %p", 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);
|
|
write_lock_bh(&rfcomm_dev_lock);
|
|
list_del_init(&dev->list);
|
|
list_del_init(&dev->list);
|
|
@@ -684,9 +686,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
|
if (!dev)
|
|
if (!dev)
|
|
return -ENODEV;
|
|
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;
|
|
return 0;
|
|
|
|
|
|
dlc = dev->dlc;
|
|
dlc = dev->dlc;
|
|
@@ -742,9 +745,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
|
|
if (!dev)
|
|
if (!dev)
|
|
return;
|
|
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)
|
|
if (dev->tty_dev->parent)
|
|
device_move(dev->tty_dev, NULL);
|
|
device_move(dev->tty_dev, NULL);
|
|
|
|
|
|
@@ -758,6 +762,14 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
|
|
tty->driver_data = NULL;
|
|
tty->driver_data = NULL;
|
|
dev->tty = NULL;
|
|
dev->tty = NULL;
|
|
rfcomm_dlc_unlock(dev->dlc);
|
|
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);
|
|
rfcomm_dev_put(dev);
|