From b6c0632105f7d7548f1d642ba830088478d4f2b0 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Tue, 29 Jan 2008 21:14:08 -0800 Subject: [BLUETOOTH]: Add conn add/del workqueues to avoid connection fail. The bluetooth hci_conn sysfs add/del executed in the default workqueue. If the del_conn is executed after the new add_conn with same target, add_conn will failed with warning of "same kobject name". Here add btaddconn & btdelconn workqueues, flush the btdelconn workqueue in the add_conn function to avoid the issue. Signed-off-by: Dave Young Signed-off-by: David S. Miller --- net/bluetooth/hci_sysfs.c | 48 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 17f7fb72055..2726adc419d 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -12,6 +12,8 @@ #undef BT_DBG #define BT_DBG(D...) #endif +static struct workqueue_struct *btaddconn; +static struct workqueue_struct *btdelconn; static inline char *typetostr(int type) { @@ -279,6 +281,7 @@ static void add_conn(struct work_struct *work) struct hci_conn *conn = container_of(work, struct hci_conn, work); int i; + flush_workqueue(btdelconn); if (device_add(&conn->dev) < 0) { BT_ERR("Failed to register connection device"); return; @@ -313,6 +316,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn) INIT_WORK(&conn->work, add_conn); + queue_work(btaddconn, &conn->work); schedule_work(&conn->work); } @@ -349,6 +353,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn) INIT_WORK(&conn->work, del_conn); + queue_work(btdelconn, &conn->work); schedule_work(&conn->work); } @@ -398,31 +403,52 @@ int __init bt_sysfs_init(void) { int err; + btaddconn = create_singlethread_workqueue("btaddconn"); + if (!btaddconn) { + err = -ENOMEM; + goto out; + } + btdelconn = create_singlethread_workqueue("btdelconn"); + if (!btdelconn) { + err = -ENOMEM; + goto out_del; + } + bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); - if (IS_ERR(bt_platform)) - return PTR_ERR(bt_platform); + if (IS_ERR(bt_platform)) { + err = PTR_ERR(bt_platform); + goto out_platform; + } err = bus_register(&bt_bus); - if (err < 0) { - platform_device_unregister(bt_platform); - return err; - } + if (err < 0) + goto out_bus; bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { - bus_unregister(&bt_bus); - platform_device_unregister(bt_platform); - return PTR_ERR(bt_class); + err = PTR_ERR(bt_class); + goto out_class; } return 0; + +out_class: + bus_unregister(&bt_bus); +out_bus: + platform_device_unregister(bt_platform); +out_platform: + destroy_workqueue(btdelconn); +out_del: + destroy_workqueue(btaddconn); +out: + return err; } void bt_sysfs_cleanup(void) { + destroy_workqueue(btaddconn); + destroy_workqueue(btdelconn); class_destroy(bt_class); - bus_unregister(&bt_bus); - platform_device_unregister(bt_platform); } -- cgit