]> err.no Git - linux-2.6/blobdiff - net/bluetooth/hci_sysfs.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[linux-2.6] / net / bluetooth / hci_sysfs.c
index 2726adc419d3ff248b75b93591c68b0a9d235b0e..84360c117d4e3e8bb3e9a68d66bcde0cdf4d3d88 100644 (file)
@@ -282,6 +282,7 @@ static void add_conn(struct work_struct *work)
        int i;
 
        flush_workqueue(btdelconn);
+
        if (device_add(&conn->dev) < 0) {
                BT_ERR("Failed to register connection device");
                return;
@@ -317,31 +318,36 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
        INIT_WORK(&conn->work, add_conn);
 
        queue_work(btaddconn, &conn->work);
-       schedule_work(&conn->work);
 }
 
+/*
+ * The rfcomm tty device will possibly retain even when conn
+ * is down, and sysfs doesn't support move zombie device,
+ * so we should move the device before conn device is destroyed.
+ */
 static int __match_tty(struct device *dev, void *data)
 {
-       /* The rfcomm tty device will possibly retain even when conn
-        * is down, and sysfs doesn't support move zombie device,
-        * so we should move the device before conn device is destroyed.
-        * Due to the only child device of hci_conn dev is rfcomm
-        * tty_dev, here just return 1
-        */
-       return 1;
+       return !strncmp(dev->bus_id, "rfcomm", 6);
 }
 
 static void del_conn(struct work_struct *work)
 {
-       struct device *dev;
        struct hci_conn *conn = container_of(work, struct hci_conn, work);
+       struct hci_dev *hdev = conn->hdev;
+
+       while (1) {
+               struct device *dev;
 
-       while (dev = device_find_child(&conn->dev, NULL, __match_tty)) {
+               dev = device_find_child(&conn->dev, NULL, __match_tty);
+               if (!dev)
+                       break;
                device_move(dev, NULL);
                put_device(dev);
        }
+
        device_del(&conn->dev);
        put_device(&conn->dev);
+       hci_dev_put(hdev);
 }
 
 void hci_conn_del_sysfs(struct hci_conn *conn)
@@ -354,7 +360,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
        INIT_WORK(&conn->work, del_conn);
 
        queue_work(btdelconn, &conn->work);
-       schedule_work(&conn->work);
 }
 
 int hci_register_sysfs(struct hci_dev *hdev)
@@ -408,6 +413,7 @@ int __init bt_sysfs_init(void)
                err = -ENOMEM;
                goto out;
        }
+
        btdelconn = create_singlethread_workqueue("btdelconn");
        if (!btdelconn) {
                err = -ENOMEM;
@@ -447,8 +453,12 @@ out:
 void bt_sysfs_cleanup(void)
 {
        destroy_workqueue(btaddconn);
+
        destroy_workqueue(btdelconn);
+
        class_destroy(bt_class);
+
        bus_unregister(&bt_bus);
+
        platform_device_unregister(bt_platform);
 }