.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * |
---|
3 | 4 | * Bluetooth HCI UART driver |
---|
.. | .. |
---|
5 | 6 | * Copyright (C) 2000-2001 Qualcomm Incorporated |
---|
6 | 7 | * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> |
---|
7 | 8 | * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> |
---|
8 | | - * |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or modify |
---|
11 | | - * it under the terms of the GNU General Public License as published by |
---|
12 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
13 | | - * (at your option) any later version. |
---|
14 | | - * |
---|
15 | | - * This program is distributed in the hope that it will be useful, |
---|
16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
18 | | - * GNU General Public License for more details. |
---|
19 | | - * |
---|
20 | | - * You should have received a copy of the GNU General Public License |
---|
21 | | - * along with this program; if not, write to the Free Software |
---|
22 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
23 | | - * |
---|
24 | 9 | */ |
---|
25 | 10 | |
---|
26 | 11 | #include <linux/module.h> |
---|
.. | .. |
---|
142 | 127 | if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) |
---|
143 | 128 | goto no_schedule; |
---|
144 | 129 | |
---|
145 | | - if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { |
---|
146 | | - set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); |
---|
| 130 | + set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); |
---|
| 131 | + if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) |
---|
147 | 132 | goto no_schedule; |
---|
148 | | - } |
---|
149 | 133 | |
---|
150 | 134 | BT_DBG(""); |
---|
151 | 135 | |
---|
.. | .. |
---|
194 | 178 | kfree_skb(skb); |
---|
195 | 179 | } |
---|
196 | 180 | |
---|
| 181 | + clear_bit(HCI_UART_SENDING, &hu->tx_state); |
---|
197 | 182 | if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) |
---|
198 | 183 | goto restart; |
---|
199 | 184 | |
---|
200 | | - clear_bit(HCI_UART_SENDING, &hu->tx_state); |
---|
| 185 | + wake_up_bit(&hu->tx_state, HCI_UART_SENDING); |
---|
201 | 186 | } |
---|
202 | 187 | |
---|
203 | 188 | void hci_uart_init_work(struct work_struct *work) |
---|
.. | .. |
---|
231 | 216 | schedule_work(&hu->init_ready); |
---|
232 | 217 | |
---|
233 | 218 | return 0; |
---|
| 219 | +} |
---|
| 220 | + |
---|
| 221 | +int hci_uart_wait_until_sent(struct hci_uart *hu) |
---|
| 222 | +{ |
---|
| 223 | + return wait_on_bit_timeout(&hu->tx_state, HCI_UART_SENDING, |
---|
| 224 | + TASK_INTERRUPTIBLE, |
---|
| 225 | + msecs_to_jiffies(2000)); |
---|
234 | 226 | } |
---|
235 | 227 | |
---|
236 | 228 | /* ------- Interface to HCI layer ------ */ |
---|
.. | .. |
---|
295 | 287 | percpu_up_read(&hu->proto_lock); |
---|
296 | 288 | return -EUNATCH; |
---|
297 | 289 | } |
---|
298 | | - |
---|
299 | | - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) |
---|
300 | | - return -EUNATCH; |
---|
301 | 290 | |
---|
302 | 291 | hu->proto->enqueue(hu, skb); |
---|
303 | 292 | percpu_up_read(&hu->proto_lock); |
---|
.. | .. |
---|
506 | 495 | BT_ERR("Can't allocate control structure"); |
---|
507 | 496 | return -ENFILE; |
---|
508 | 497 | } |
---|
| 498 | + if (percpu_init_rwsem(&hu->proto_lock)) { |
---|
| 499 | + BT_ERR("Can't allocate semaphore structure"); |
---|
| 500 | + kfree(hu); |
---|
| 501 | + return -ENOMEM; |
---|
| 502 | + } |
---|
509 | 503 | |
---|
510 | 504 | tty->disc_data = hu; |
---|
511 | 505 | hu->tty = tty; |
---|
.. | .. |
---|
517 | 511 | |
---|
518 | 512 | INIT_WORK(&hu->init_ready, hci_uart_init_work); |
---|
519 | 513 | INIT_WORK(&hu->write_work, hci_uart_write_work); |
---|
520 | | - |
---|
521 | | - percpu_init_rwsem(&hu->proto_lock); |
---|
522 | 514 | |
---|
523 | 515 | /* Flush any pending characters in the driver */ |
---|
524 | 516 | tty_driver_flush_buffer(tty); |
---|
.. | .. |
---|
817 | 809 | * We don't provide read/write/poll interface for user space. |
---|
818 | 810 | */ |
---|
819 | 811 | static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, |
---|
820 | | - unsigned char __user *buf, size_t nr) |
---|
| 812 | + unsigned char *buf, size_t nr, |
---|
| 813 | + void **cookie, unsigned long offset) |
---|
821 | 814 | { |
---|
822 | 815 | return 0; |
---|
823 | 816 | } |
---|
.. | .. |
---|
834 | 827 | return 0; |
---|
835 | 828 | } |
---|
836 | 829 | |
---|
| 830 | +static struct tty_ldisc_ops hci_uart_ldisc = { |
---|
| 831 | + .owner = THIS_MODULE, |
---|
| 832 | + .magic = TTY_LDISC_MAGIC, |
---|
| 833 | + .name = "n_hci", |
---|
| 834 | + .open = hci_uart_tty_open, |
---|
| 835 | + .close = hci_uart_tty_close, |
---|
| 836 | + .read = hci_uart_tty_read, |
---|
| 837 | + .write = hci_uart_tty_write, |
---|
| 838 | + .ioctl = hci_uart_tty_ioctl, |
---|
| 839 | + .compat_ioctl = hci_uart_tty_ioctl, |
---|
| 840 | + .poll = hci_uart_tty_poll, |
---|
| 841 | + .receive_buf = hci_uart_tty_receive, |
---|
| 842 | + .write_wakeup = hci_uart_tty_wakeup, |
---|
| 843 | +}; |
---|
| 844 | + |
---|
837 | 845 | static int __init hci_uart_init(void) |
---|
838 | 846 | { |
---|
839 | | - static struct tty_ldisc_ops hci_uart_ldisc; |
---|
840 | 847 | int err; |
---|
841 | 848 | |
---|
842 | 849 | BT_INFO("HCI UART driver ver %s", VERSION); |
---|
843 | 850 | |
---|
844 | 851 | /* Register the tty discipline */ |
---|
845 | | - |
---|
846 | | - memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc)); |
---|
847 | | - hci_uart_ldisc.magic = TTY_LDISC_MAGIC; |
---|
848 | | - hci_uart_ldisc.name = "n_hci"; |
---|
849 | | - hci_uart_ldisc.open = hci_uart_tty_open; |
---|
850 | | - hci_uart_ldisc.close = hci_uart_tty_close; |
---|
851 | | - hci_uart_ldisc.read = hci_uart_tty_read; |
---|
852 | | - hci_uart_ldisc.write = hci_uart_tty_write; |
---|
853 | | - hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; |
---|
854 | | - hci_uart_ldisc.poll = hci_uart_tty_poll; |
---|
855 | | - hci_uart_ldisc.receive_buf = hci_uart_tty_receive; |
---|
856 | | - hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; |
---|
857 | | - hci_uart_ldisc.owner = THIS_MODULE; |
---|
858 | | - |
---|
859 | 852 | err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); |
---|
860 | 853 | if (err) { |
---|
861 | 854 | BT_ERR("HCI line discipline registration failed. (%d)", err); |
---|