summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Young <hidave.darkstar@gmail.com>2008-01-29 21:14:08 -0800
committerDavid S. Miller <davem@davemloft.net>2008-01-31 19:27:12 -0800
commitb6c0632105f7d7548f1d642ba830088478d4f2b0 (patch)
tree63e06f0d8565e5704d3ebabfd1597ad995253434
parent2614fa59fa805cd488083c5602eb48533cdbc018 (diff)
[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 <hidave.darkstar@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bluetooth/hci_sysfs.c48
1 files changed, 37 insertions, 11 deletions
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);
}