diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2012-07-16 09:12:11 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-07-17 13:48:29 -0400 |
commit | 9f2aee848fe60325b1984653833d2d1825ec730d (patch) | |
tree | cf1f3d1a081a37421af9d9eb8918917f1deef8a3 /drivers/bluetooth/hci_ldisc.c | |
parent | dac670b97698f7c5584b224dd68d9d612b9ad4d7 (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.c | 39 |
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 | ||
159 | static 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 | |||
178 | int 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 */ |
161 | static int hci_uart_open(struct hci_dev *hdev) | 190 | static 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 | ||