فهرست منبع

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: Marcel Holtmann <marcel@holtmann.org>
Marcel Holtmann 15 سال پیش
والد
کامیت
f48fd9c8cd
3فایلهای تغییر یافته به همراه19 افزوده شده و 13 حذف شده
  1. 2 0
      include/net/bluetooth/hci_core.h
  2. 14 0
      net/bluetooth/hci_core.c
  3. 3 13
      net/bluetooth/hci_sysfs.c

+ 2 - 0
include/net/bluetooth/hci_core.h

@@ -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;

+ 14 - 0
net/bluetooth/hci_core.c

@@ -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)
 
 
 	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)
 	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)
 
 
 	hci_unregister_sysfs(hdev);
 	hci_unregister_sysfs(hdev);
 
 
+	destroy_workqueue(hdev->workqueue);
+
 	__hci_dev_put(hdev);
 	__hci_dev_put(hdev);
 
 
 	return 0;
 	return 0;

+ 3 - 13
net/bluetooth/hci_sysfs.c

@@ -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)
 {
 {
 	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)
 
 
 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)) {
-		destroy_workqueue(bt_workq);
+	if (IS_ERR(bt_class))
 		return PTR_ERR(bt_class);
 		return PTR_ERR(bt_class);
-	}
 
 
 	return 0;
 	return 0;
 }
 }
@@ -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);
 }
 }