diff options
Diffstat (limited to 'net/bluetooth/hci_sysfs.c')
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 74 |
1 files changed, 41 insertions, 33 deletions
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index b7c51082ddeb..4cc3624bd22d 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -9,7 +9,7 @@ | |||
9 | struct class *bt_class = NULL; | 9 | struct class *bt_class = NULL; |
10 | EXPORT_SYMBOL_GPL(bt_class); | 10 | EXPORT_SYMBOL_GPL(bt_class); |
11 | 11 | ||
12 | static struct workqueue_struct *bluetooth; | 12 | static struct workqueue_struct *bt_workq; |
13 | 13 | ||
14 | static inline char *link_typetostr(int type) | 14 | static inline char *link_typetostr(int type) |
15 | { | 15 | { |
@@ -88,35 +88,19 @@ static struct device_type bt_link = { | |||
88 | static void add_conn(struct work_struct *work) | 88 | static void add_conn(struct work_struct *work) |
89 | { | 89 | { |
90 | struct hci_conn *conn = container_of(work, struct hci_conn, work_add); | 90 | struct hci_conn *conn = container_of(work, struct hci_conn, work_add); |
91 | struct hci_dev *hdev = conn->hdev; | ||
92 | |||
93 | /* ensure previous del is complete */ | ||
94 | flush_work(&conn->work_del); | ||
91 | 95 | ||
92 | /* ensure previous add/del is complete */ | 96 | dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); |
93 | flush_workqueue(bluetooth); | ||
94 | 97 | ||
95 | if (device_add(&conn->dev) < 0) { | 98 | if (device_add(&conn->dev) < 0) { |
96 | BT_ERR("Failed to register connection device"); | 99 | BT_ERR("Failed to register connection device"); |
97 | return; | 100 | return; |
98 | } | 101 | } |
99 | } | ||
100 | 102 | ||
101 | void hci_conn_add_sysfs(struct hci_conn *conn) | 103 | hci_dev_hold(hdev); |
102 | { | ||
103 | struct hci_dev *hdev = conn->hdev; | ||
104 | |||
105 | BT_DBG("conn %p", conn); | ||
106 | |||
107 | conn->dev.type = &bt_link; | ||
108 | conn->dev.class = bt_class; | ||
109 | conn->dev.parent = &hdev->dev; | ||
110 | |||
111 | dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); | ||
112 | |||
113 | dev_set_drvdata(&conn->dev, conn); | ||
114 | |||
115 | device_initialize(&conn->dev); | ||
116 | |||
117 | INIT_WORK(&conn->work_add, add_conn); | ||
118 | |||
119 | queue_work(bluetooth, &conn->work_add); | ||
120 | } | 104 | } |
121 | 105 | ||
122 | /* | 106 | /* |
@@ -134,8 +118,11 @@ static void del_conn(struct work_struct *work) | |||
134 | struct hci_conn *conn = container_of(work, struct hci_conn, work_del); | 118 | struct hci_conn *conn = container_of(work, struct hci_conn, work_del); |
135 | struct hci_dev *hdev = conn->hdev; | 119 | struct hci_dev *hdev = conn->hdev; |
136 | 120 | ||
137 | /* ensure previous add/del is complete */ | 121 | /* ensure previous add is complete */ |
138 | flush_workqueue(bluetooth); | 122 | flush_work(&conn->work_add); |
123 | |||
124 | if (!device_is_registered(&conn->dev)) | ||
125 | return; | ||
139 | 126 | ||
140 | while (1) { | 127 | while (1) { |
141 | struct device *dev; | 128 | struct device *dev; |
@@ -149,19 +136,40 @@ static void del_conn(struct work_struct *work) | |||
149 | 136 | ||
150 | device_del(&conn->dev); | 137 | device_del(&conn->dev); |
151 | put_device(&conn->dev); | 138 | put_device(&conn->dev); |
139 | |||
152 | hci_dev_put(hdev); | 140 | hci_dev_put(hdev); |
153 | } | 141 | } |
154 | 142 | ||
155 | void hci_conn_del_sysfs(struct hci_conn *conn) | 143 | void hci_conn_init_sysfs(struct hci_conn *conn) |
156 | { | 144 | { |
145 | struct hci_dev *hdev = conn->hdev; | ||
146 | |||
157 | BT_DBG("conn %p", conn); | 147 | BT_DBG("conn %p", conn); |
158 | 148 | ||
159 | if (!device_is_registered(&conn->dev)) | 149 | conn->dev.type = &bt_link; |
160 | return; | 150 | conn->dev.class = bt_class; |
151 | conn->dev.parent = &hdev->dev; | ||
152 | |||
153 | dev_set_drvdata(&conn->dev, conn); | ||
154 | |||
155 | device_initialize(&conn->dev); | ||
161 | 156 | ||
157 | INIT_WORK(&conn->work_add, add_conn); | ||
162 | INIT_WORK(&conn->work_del, del_conn); | 158 | INIT_WORK(&conn->work_del, del_conn); |
159 | } | ||
160 | |||
161 | void hci_conn_add_sysfs(struct hci_conn *conn) | ||
162 | { | ||
163 | BT_DBG("conn %p", conn); | ||
164 | |||
165 | queue_work(bt_workq, &conn->work_add); | ||
166 | } | ||
167 | |||
168 | void hci_conn_del_sysfs(struct hci_conn *conn) | ||
169 | { | ||
170 | BT_DBG("conn %p", conn); | ||
163 | 171 | ||
164 | queue_work(bluetooth, &conn->work_del); | 172 | queue_work(bt_workq, &conn->work_del); |
165 | } | 173 | } |
166 | 174 | ||
167 | static inline char *host_typetostr(int type) | 175 | static inline char *host_typetostr(int type) |
@@ -438,13 +446,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | |||
438 | 446 | ||
439 | int __init bt_sysfs_init(void) | 447 | int __init bt_sysfs_init(void) |
440 | { | 448 | { |
441 | bluetooth = create_singlethread_workqueue("bluetooth"); | 449 | bt_workq = create_singlethread_workqueue("bluetooth"); |
442 | if (!bluetooth) | 450 | if (!bt_workq) |
443 | return -ENOMEM; | 451 | return -ENOMEM; |
444 | 452 | ||
445 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 453 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
446 | if (IS_ERR(bt_class)) { | 454 | if (IS_ERR(bt_class)) { |
447 | destroy_workqueue(bluetooth); | 455 | destroy_workqueue(bt_workq); |
448 | return PTR_ERR(bt_class); | 456 | return PTR_ERR(bt_class); |
449 | } | 457 | } |
450 | 458 | ||
@@ -453,7 +461,7 @@ int __init bt_sysfs_init(void) | |||
453 | 461 | ||
454 | void bt_sysfs_cleanup(void) | 462 | void bt_sysfs_cleanup(void) |
455 | { | 463 | { |
456 | destroy_workqueue(bluetooth); | 464 | destroy_workqueue(bt_workq); |
457 | 465 | ||
458 | class_destroy(bt_class); | 466 | class_destroy(bt_class); |
459 | } | 467 | } |