diff options
author | Dave Young <hidave.darkstar@gmail.com> | 2008-01-30 00:14:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:27:12 -0500 |
commit | b6c0632105f7d7548f1d642ba830088478d4f2b0 (patch) | |
tree | 63e06f0d8565e5704d3ebabfd1597ad995253434 /net/bluetooth | |
parent | 2614fa59fa805cd488083c5602eb48533cdbc018 (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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 17f7fb720553..2726adc419d3 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #undef BT_DBG | 12 | #undef BT_DBG |
13 | #define BT_DBG(D...) | 13 | #define BT_DBG(D...) |
14 | #endif | 14 | #endif |
15 | static struct workqueue_struct *btaddconn; | ||
16 | static struct workqueue_struct *btdelconn; | ||
15 | 17 | ||
16 | static inline char *typetostr(int type) | 18 | static inline char *typetostr(int type) |
17 | { | 19 | { |
@@ -279,6 +281,7 @@ static void add_conn(struct work_struct *work) | |||
279 | struct hci_conn *conn = container_of(work, struct hci_conn, work); | 281 | struct hci_conn *conn = container_of(work, struct hci_conn, work); |
280 | int i; | 282 | int i; |
281 | 283 | ||
284 | flush_workqueue(btdelconn); | ||
282 | if (device_add(&conn->dev) < 0) { | 285 | if (device_add(&conn->dev) < 0) { |
283 | BT_ERR("Failed to register connection device"); | 286 | BT_ERR("Failed to register connection device"); |
284 | return; | 287 | return; |
@@ -313,6 +316,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn) | |||
313 | 316 | ||
314 | INIT_WORK(&conn->work, add_conn); | 317 | INIT_WORK(&conn->work, add_conn); |
315 | 318 | ||
319 | queue_work(btaddconn, &conn->work); | ||
316 | schedule_work(&conn->work); | 320 | schedule_work(&conn->work); |
317 | } | 321 | } |
318 | 322 | ||
@@ -349,6 +353,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn) | |||
349 | 353 | ||
350 | INIT_WORK(&conn->work, del_conn); | 354 | INIT_WORK(&conn->work, del_conn); |
351 | 355 | ||
356 | queue_work(btdelconn, &conn->work); | ||
352 | schedule_work(&conn->work); | 357 | schedule_work(&conn->work); |
353 | } | 358 | } |
354 | 359 | ||
@@ -398,31 +403,52 @@ int __init bt_sysfs_init(void) | |||
398 | { | 403 | { |
399 | int err; | 404 | int err; |
400 | 405 | ||
406 | btaddconn = create_singlethread_workqueue("btaddconn"); | ||
407 | if (!btaddconn) { | ||
408 | err = -ENOMEM; | ||
409 | goto out; | ||
410 | } | ||
411 | btdelconn = create_singlethread_workqueue("btdelconn"); | ||
412 | if (!btdelconn) { | ||
413 | err = -ENOMEM; | ||
414 | goto out_del; | ||
415 | } | ||
416 | |||
401 | bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); | 417 | bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); |
402 | if (IS_ERR(bt_platform)) | 418 | if (IS_ERR(bt_platform)) { |
403 | return PTR_ERR(bt_platform); | 419 | err = PTR_ERR(bt_platform); |
420 | goto out_platform; | ||
421 | } | ||
404 | 422 | ||
405 | err = bus_register(&bt_bus); | 423 | err = bus_register(&bt_bus); |
406 | if (err < 0) { | 424 | if (err < 0) |
407 | platform_device_unregister(bt_platform); | 425 | goto out_bus; |
408 | return err; | ||
409 | } | ||
410 | 426 | ||
411 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 427 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
412 | if (IS_ERR(bt_class)) { | 428 | if (IS_ERR(bt_class)) { |
413 | bus_unregister(&bt_bus); | 429 | err = PTR_ERR(bt_class); |
414 | platform_device_unregister(bt_platform); | 430 | goto out_class; |
415 | return PTR_ERR(bt_class); | ||
416 | } | 431 | } |
417 | 432 | ||
418 | return 0; | 433 | return 0; |
434 | |||
435 | out_class: | ||
436 | bus_unregister(&bt_bus); | ||
437 | out_bus: | ||
438 | platform_device_unregister(bt_platform); | ||
439 | out_platform: | ||
440 | destroy_workqueue(btdelconn); | ||
441 | out_del: | ||
442 | destroy_workqueue(btaddconn); | ||
443 | out: | ||
444 | return err; | ||
419 | } | 445 | } |
420 | 446 | ||
421 | void bt_sysfs_cleanup(void) | 447 | void bt_sysfs_cleanup(void) |
422 | { | 448 | { |
449 | destroy_workqueue(btaddconn); | ||
450 | destroy_workqueue(btdelconn); | ||
423 | class_destroy(bt_class); | 451 | class_destroy(bt_class); |
424 | |||
425 | bus_unregister(&bt_bus); | 452 | bus_unregister(&bt_bus); |
426 | |||
427 | platform_device_unregister(bt_platform); | 453 | platform_device_unregister(bt_platform); |
428 | } | 454 | } |