Commit f48fd9c8 authored by Marcel Holtmann's avatar Marcel Holtmann

Bluetooth: Create per controller workqueue

Instead of having a global workqueue for all controllers, it makes
more sense to have a workqueue per controller.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 844c0972
...@@ -107,6 +107,8 @@ struct hci_dev { ...@@ -107,6 +107,8 @@ struct hci_dev {
unsigned long acl_last_tx; unsigned long acl_last_tx;
unsigned long sco_last_tx; unsigned long sco_last_tx;
struct workqueue_struct *workqueue;
struct tasklet_struct cmd_task; struct tasklet_struct cmd_task;
struct tasklet_struct rx_task; struct tasklet_struct rx_task;
struct tasklet_struct tx_task; struct tasklet_struct tx_task;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/rfkill.h> #include <linux/rfkill.h>
...@@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev)
write_unlock_bh(&hci_dev_list_lock); write_unlock_bh(&hci_dev_list_lock);
hdev->workqueue = create_singlethread_workqueue(hdev->name);
if (!hdev->workqueue)
goto nomem;
hci_register_sysfs(hdev); hci_register_sysfs(hdev);
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
...@@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_REG); hci_notify(hdev, HCI_DEV_REG);
return id; return id;
nomem:
write_lock_bh(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock_bh(&hci_dev_list_lock);
return -ENOMEM;
} }
EXPORT_SYMBOL(hci_register_dev); EXPORT_SYMBOL(hci_register_dev);
...@@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev) ...@@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_unregister_sysfs(hdev); hci_unregister_sysfs(hdev);
destroy_workqueue(hdev->workqueue);
__hci_dev_put(hdev); __hci_dev_put(hdev);
return 0; return 0;
......
...@@ -14,8 +14,6 @@ static struct class *bt_class; ...@@ -14,8 +14,6 @@ static struct class *bt_class;
struct dentry *bt_debugfs = NULL; struct dentry *bt_debugfs = NULL;
EXPORT_SYMBOL_GPL(bt_debugfs); EXPORT_SYMBOL_GPL(bt_debugfs);
static struct workqueue_struct *bt_workq;
static inline char *link_typetostr(int type) static inline char *link_typetostr(int type)
{ {
switch (type) { switch (type) {
...@@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) ...@@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
{ {
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
queue_work(bt_workq, &conn->work_add); queue_work(conn->hdev->workqueue, &conn->work_add);
} }
void hci_conn_del_sysfs(struct hci_conn *conn) void hci_conn_del_sysfs(struct hci_conn *conn)
{ {
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
queue_work(bt_workq, &conn->work_del); queue_work(conn->hdev->workqueue, &conn->work_del);
} }
static inline char *host_bustostr(int bus) static inline char *host_bustostr(int bus)
...@@ -487,17 +485,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev) ...@@ -487,17 +485,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
int __init bt_sysfs_init(void) int __init bt_sysfs_init(void)
{ {
bt_workq = create_singlethread_workqueue("bluetooth");
if (!bt_workq)
return -ENOMEM;
bt_debugfs = debugfs_create_dir("bluetooth", NULL); bt_debugfs = debugfs_create_dir("bluetooth", NULL);
bt_class = class_create(THIS_MODULE, "bluetooth"); bt_class = class_create(THIS_MODULE, "bluetooth");
if (IS_ERR(bt_class)) { if (IS_ERR(bt_class))
destroy_workqueue(bt_workq);
return PTR_ERR(bt_class); return PTR_ERR(bt_class);
}
return 0; return 0;
} }
...@@ -507,6 +499,4 @@ void bt_sysfs_cleanup(void) ...@@ -507,6 +499,4 @@ void bt_sysfs_cleanup(void)
class_destroy(bt_class); class_destroy(bt_class);
debugfs_remove_recursive(bt_debugfs); debugfs_remove_recursive(bt_debugfs);
destroy_workqueue(bt_workq);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment