Bluetooth: Rename __rfcomm_dev_get() to __rfcomm_dev_lookup()
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / rfcomm / tty.c
index a58d693e1e61fba29c4eb0db3f88f8cb15943d1f..4a38b5454ab00bee82a0cca4b4496e0952919f45 100644 (file)
@@ -140,7 +140,7 @@ static const struct tty_port_operations rfcomm_port_ops = {
        .carrier_raised = rfcomm_dev_carrier_raised,
 };
 
-static struct rfcomm_dev *__rfcomm_dev_get(int id)
+static struct rfcomm_dev *__rfcomm_dev_lookup(int id)
 {
        struct rfcomm_dev *dev;
 
@@ -157,7 +157,7 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
 
        spin_lock(&rfcomm_dev_lock);
 
-       dev = __rfcomm_dev_get(id);
+       dev = __rfcomm_dev_lookup(id);
 
        if (dev && !tty_port_get(&dev->port))
                dev = NULL;
@@ -167,20 +167,29 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
        return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+static void rfcomm_reparent_device(struct rfcomm_dev *dev)
 {
        struct hci_dev *hdev;
        struct hci_conn *conn;
 
        hdev = hci_get_route(&dev->dst, &dev->src);
        if (!hdev)
-               return NULL;
+               return;
 
+       /* The lookup results are unsafe to access without the
+        * hci device lock (FIXME: why is this not documented?)
+        */
+       hci_dev_lock(hdev);
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
 
-       hci_dev_put(hdev);
+       /* Just because the acl link is in the hash table is no
+        * guarantee the sysfs device has been added ...
+        */
+       if (conn && device_is_registered(&conn->dev))
+               device_move(dev->tty_dev, &conn->dev, DPM_ORDER_DEV_AFTER_PARENT);
 
-       return conn ? &conn->dev : NULL;
+       hci_dev_unlock(hdev);
+       hci_dev_put(hdev);
 }
 
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
@@ -307,6 +316,7 @@ out:
                goto free;
        }
 
+       rfcomm_reparent_device(dev);
        dev_set_drvdata(dev->tty_dev, dev);
 
        if (device_create_file(dev->tty_dev, &dev_attr_address) < 0)
@@ -589,8 +599,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 
        dev->err = err;
        if (dlc->state == BT_CONNECTED) {
-               device_move(dev->tty_dev, rfcomm_get_device(dev),
-                           DPM_ORDER_DEV_AFTER_PARENT);
+               rfcomm_reparent_device(dev);
 
                wake_up_interruptible(&dev->port.open_wait);
        } else if (dlc->state == BT_CLOSED)