|
@@ -76,13 +76,6 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
|
|
|
|
|
|
/* ---- Device functions ---- */
|
|
|
|
|
|
-/*
|
|
|
- * The reason this isn't actually a race, as you no doubt have a little voice
|
|
|
- * screaming at you in your head, is that the refcount should never actually
|
|
|
- * reach zero unless the device has already been taken off the list, in
|
|
|
- * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
|
|
|
- * rfcomm_dev_destruct() anyway.
|
|
|
- */
|
|
|
static void rfcomm_dev_destruct(struct tty_port *port)
|
|
|
{
|
|
|
struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
|
|
@@ -90,10 +83,9 @@ static void rfcomm_dev_destruct(struct tty_port *port)
|
|
|
|
|
|
BT_DBG("dev %p dlc %p", dev, dlc);
|
|
|
|
|
|
- /* Refcount should only hit zero when called from rfcomm_dev_del()
|
|
|
- which will have taken us off the list. Everything else are
|
|
|
- refcounting bugs. */
|
|
|
- BUG_ON(!list_empty(&dev->list));
|
|
|
+ spin_lock(&rfcomm_dev_lock);
|
|
|
+ list_del(&dev->list);
|
|
|
+ spin_unlock(&rfcomm_dev_lock);
|
|
|
|
|
|
rfcomm_dlc_lock(dlc);
|
|
|
/* Detach DLC if it's owned by this dev */
|
|
@@ -282,7 +274,9 @@ out:
|
|
|
dev->id, NULL);
|
|
|
if (IS_ERR(dev->tty_dev)) {
|
|
|
err = PTR_ERR(dev->tty_dev);
|
|
|
+ spin_lock(&rfcomm_dev_lock);
|
|
|
list_del(&dev->list);
|
|
|
+ spin_unlock(&rfcomm_dev_lock);
|
|
|
goto free;
|
|
|
}
|
|
|
|
|
@@ -315,10 +309,6 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
|
|
|
}
|
|
|
spin_unlock_irqrestore(&dev->port.lock, flags);
|
|
|
|
|
|
- spin_lock(&rfcomm_dev_lock);
|
|
|
- list_del_init(&dev->list);
|
|
|
- spin_unlock(&rfcomm_dev_lock);
|
|
|
-
|
|
|
tty_port_put(&dev->port);
|
|
|
}
|
|
|
|
|
@@ -750,13 +740,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
|
|
|
dev->port.tty = NULL;
|
|
|
rfcomm_dlc_unlock(dev->dlc);
|
|
|
|
|
|
- if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
|
|
|
- spin_lock(&rfcomm_dev_lock);
|
|
|
- list_del_init(&dev->list);
|
|
|
- spin_unlock(&rfcomm_dev_lock);
|
|
|
-
|
|
|
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
|
|
tty_port_put(&dev->port);
|
|
|
- }
|
|
|
} else
|
|
|
spin_unlock_irqrestore(&dev->port.lock, flags);
|
|
|
|