Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6c06321 authored by Dave Young's avatar Dave Young Committed by David S. Miller
Browse files

[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: default avatarDave Young <hidave.darkstar@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2614fa59
Loading
Loading
Loading
Loading
+37 −11
Original line number Diff line number Diff line
@@ -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);
}