aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_ldisc.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-07-16 09:12:11 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-07-17 13:48:29 -0400
commit9f2aee848fe60325b1984653833d2d1825ec730d (patch)
treecf1f3d1a081a37421af9d9eb8918917f1deef8a3 /drivers/bluetooth/hci_ldisc.c
parentdac670b97698f7c5584b224dd68d9d612b9ad4d7 (diff)
Bluetooth: Add delayed init sequence support for UART controllers
This patch makes it possible to have UART drivers perform an internal initialization before calling hci_register_dev. This allows moving a lot of init code from user space (hciattach) to the kernel side, thereby creating a more controlled/robust initialization process. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'drivers/bluetooth/hci_ldisc.c')
-rw-r--r--drivers/bluetooth/hci_ldisc.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index b6d1f200401a..74e0966b3ead 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -156,6 +156,35 @@ restart:
156 return 0; 156 return 0;
157} 157}
158 158
159static void hci_uart_init_work(struct work_struct *work)
160{
161 struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
162 int err;
163
164 if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
165 return;
166
167 err = hci_register_dev(hu->hdev);
168 if (err < 0) {
169 BT_ERR("Can't register HCI device");
170 hci_free_dev(hu->hdev);
171 hu->hdev = NULL;
172 hu->proto->close(hu);
173 }
174
175 set_bit(HCI_UART_REGISTERED, &hu->flags);
176}
177
178int hci_uart_init_ready(struct hci_uart *hu)
179{
180 if (!test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
181 return -EALREADY;
182
183 schedule_work(&hu->init_ready);
184
185 return 0;
186}
187
159/* ------- Interface to HCI layer ------ */ 188/* ------- Interface to HCI layer ------ */
160/* Initialize device */ 189/* Initialize device */
161static int hci_uart_open(struct hci_dev *hdev) 190static int hci_uart_open(struct hci_dev *hdev)
@@ -264,6 +293,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
264 hu->tty = tty; 293 hu->tty = tty;
265 tty->receive_room = 65536; 294 tty->receive_room = 65536;
266 295
296 INIT_WORK(&hu->init_ready, hci_uart_init_work);
297
267 spin_lock_init(&hu->rx_lock); 298 spin_lock_init(&hu->rx_lock);
268 299
269 /* Flush any pending characters in the driver and line discipline. */ 300 /* Flush any pending characters in the driver and line discipline. */
@@ -302,7 +333,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
302 333
303 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { 334 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
304 if (hdev) { 335 if (hdev) {
305 hci_unregister_dev(hdev); 336 if (test_bit(HCI_UART_REGISTERED, &hu->flags))
337 hci_unregister_dev(hdev);
306 hci_free_dev(hdev); 338 hci_free_dev(hdev);
307 } 339 }
308 hu->proto->close(hu); 340 hu->proto->close(hu);
@@ -402,12 +434,17 @@ static int hci_uart_register_dev(struct hci_uart *hu)
402 else 434 else
403 hdev->dev_type = HCI_BREDR; 435 hdev->dev_type = HCI_BREDR;
404 436
437 if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
438 return 0;
439
405 if (hci_register_dev(hdev) < 0) { 440 if (hci_register_dev(hdev) < 0) {
406 BT_ERR("Can't register HCI device"); 441 BT_ERR("Can't register HCI device");
407 hci_free_dev(hdev); 442 hci_free_dev(hdev);
408 return -ENODEV; 443 return -ENODEV;
409 } 444 }
410 445
446 set_bit(HCI_UART_REGISTERED, &hu->flags);
447
411 return 0; 448 return 0;
412} 449}
413 450