TTY: rfcomm/tty, use tty_port refcounting
authorJiri Slaby <jslaby@suse.cz>
Mon, 2 Apr 2012 11:54:51 +0000 (13:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 Apr 2012 19:04:31 +0000 (12:04 -0700)
Switch the refcounting from manual atomic plays with refcounter to the
one offered by tty_port.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/bluetooth/rfcomm/tty.c

index 97c2a087a9f1f4d9cd63ef9d2312fc31556cccea..da4f54515775adf2a4681c7884f8894ec6f3be25 100644 (file)
@@ -50,7 +50,6 @@ static struct tty_driver *rfcomm_tty_driver;
 struct rfcomm_dev {
        struct tty_port         port;
        struct list_head        list;
-       atomic_t                refcnt;
 
        char                    name[12];
        int                     id;
@@ -85,8 +84,17 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
 static void rfcomm_tty_wakeup(struct work_struct *work);
 
 /* ---- Device functions ---- */
-static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
+
+/*
+ * 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);
        struct rfcomm_dlc *dlc = dev->dlc;
 
        BT_DBG("dev %p dlc %p", dev, dlc);
@@ -113,23 +121,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
        module_put(THIS_MODULE);
 }
 
-static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
-{
-       atomic_inc(&dev->refcnt);
-}
-
-static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
-{
-       /* 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. */
-       if (atomic_dec_and_test(&dev->refcnt))
-               rfcomm_dev_destruct(dev);
-}
+static const struct tty_port_operations rfcomm_port_ops = {
+       .destruct = rfcomm_dev_destruct,
+};
 
 static struct rfcomm_dev *__rfcomm_dev_get(int id)
 {
@@ -154,7 +148,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
                if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
                        dev = NULL;
                else
-                       rfcomm_dev_hold(dev);
+                       tty_port_get(&dev->port);
        }
 
        spin_unlock(&rfcomm_dev_lock);
@@ -241,7 +235,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
        sprintf(dev->name, "rfcomm%d", dev->id);
 
        list_add(&dev->list, head);
-       atomic_set(&dev->refcnt, 1);
 
        bacpy(&dev->src, &req->src);
        bacpy(&dev->dst, &req->dst);
@@ -253,6 +246,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
        atomic_set(&dev->opened, 0);
 
        tty_port_init(&dev->port);
+       dev->port.ops = &rfcomm_port_ops;
        init_waitqueue_head(&dev->wait);
        INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup);
 
@@ -332,7 +326,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
        list_del_init(&dev->list);
        spin_unlock(&rfcomm_dev_lock);
 
-       rfcomm_dev_put(dev);
+       tty_port_put(&dev->port);
 }
 
 /* ---- Send buffer ---- */
@@ -349,12 +343,12 @@ static void rfcomm_wfree(struct sk_buff *skb)
        atomic_sub(skb->truesize, &dev->wmem_alloc);
        if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
                queue_work(system_nrt_wq, &dev->wakeup_task);
-       rfcomm_dev_put(dev);
+       tty_port_put(&dev->port);
 }
 
 static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
 {
-       rfcomm_dev_hold(dev);
+       tty_port_get(&dev->port);
        atomic_add(skb->truesize, &dev->wmem_alloc);
        skb->sk = (void *) dev;
        skb->destructor = rfcomm_wfree;
@@ -433,7 +427,7 @@ static int rfcomm_release_dev(void __user *arg)
                return -ENODEV;
 
        if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
-               rfcomm_dev_put(dev);
+               tty_port_put(&dev->port);
                return -EPERM;
        }
 
@@ -446,7 +440,7 @@ static int rfcomm_release_dev(void __user *arg)
 
        if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
                rfcomm_dev_del(dev);
-       rfcomm_dev_put(dev);
+       tty_port_put(&dev->port);
        return 0;
 }
 
@@ -524,7 +518,7 @@ static int rfcomm_get_dev_info(void __user *arg)
        if (copy_to_user(arg, &di, sizeof(di)))
                err = -EFAULT;
 
-       rfcomm_dev_put(dev);
+       tty_port_put(&dev->port);
        return err;
 }
 
@@ -592,7 +586,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
                                 * 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
+                                * 2. tty_port_put will deadlock if it's
                                 *    the last reference
                                 */
                                rfcomm_dlc_unlock(dlc);
@@ -602,7 +596,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
                                }
 
                                rfcomm_dev_del(dev);
-                               rfcomm_dev_put(dev);
+                               tty_port_put(&dev->port);
                                rfcomm_dlc_lock(dlc);
                        }
                } else
@@ -771,11 +765,11 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
                        list_del_init(&dev->list);
                        spin_unlock(&rfcomm_dev_lock);
 
-                       rfcomm_dev_put(dev);
+                       tty_port_put(&dev->port);
                }
        }
 
-       rfcomm_dev_put(dev);
+       tty_port_put(&dev->port);
 }
 
 static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1084,7 +1078,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
                if (rfcomm_dev_get(dev->id) == NULL)
                        return;
                rfcomm_dev_del(dev);
-               rfcomm_dev_put(dev);
+               tty_port_put(&dev->port);
        }
 }