aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2014-04-23 10:58:26 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-24 19:16:33 -0400
commitda64c27d3c93ee9f89956b9de86c4127eb244494 (patch)
tree379c2bedcc6f9db3461aefb81927da7d2acbcad0 /drivers/bluetooth
parent879eb9c3f9b854394c5a2014b9243c00eaa329f0 (diff)
bluetooth: hci_ldisc: fix deadlock condition
LDISCs shouldn't call tty->ops->write() from within ->write_wakeup(). ->write_wakeup() is called with port lock taken and IRQs disabled, tty->ops->write() will try to acquire the same port lock and we will deadlock. Acked-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: Peter Hurley <peter@hurleysoftware.com> Reported-by: Huang Shijie <b32955@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Tested-by: Andreas Bießmann <andreas@biessmann.de> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/hci_ldisc.c24
-rw-r--r--drivers/bluetooth/hci_uart.h1
2 files changed, 20 insertions, 5 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index f1fbf4f1e5be..e00f8f5b5c8e 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -118,10 +118,6 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
118 118
119int hci_uart_tx_wakeup(struct hci_uart *hu) 119int hci_uart_tx_wakeup(struct hci_uart *hu)
120{ 120{
121 struct tty_struct *tty = hu->tty;
122 struct hci_dev *hdev = hu->hdev;
123 struct sk_buff *skb;
124
125 if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { 121 if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
126 set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); 122 set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
127 return 0; 123 return 0;
@@ -129,6 +125,22 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
129 125
130 BT_DBG(""); 126 BT_DBG("");
131 127
128 schedule_work(&hu->write_work);
129
130 return 0;
131}
132
133static void hci_uart_write_work(struct work_struct *work)
134{
135 struct hci_uart *hu = container_of(work, struct hci_uart, write_work);
136 struct tty_struct *tty = hu->tty;
137 struct hci_dev *hdev = hu->hdev;
138 struct sk_buff *skb;
139
140 /* REVISIT: should we cope with bad skbs or ->write() returning
141 * and error value ?
142 */
143
132restart: 144restart:
133 clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); 145 clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
134 146
@@ -153,7 +165,6 @@ restart:
153 goto restart; 165 goto restart;
154 166
155 clear_bit(HCI_UART_SENDING, &hu->tx_state); 167 clear_bit(HCI_UART_SENDING, &hu->tx_state);
156 return 0;
157} 168}
158 169
159static void hci_uart_init_work(struct work_struct *work) 170static void hci_uart_init_work(struct work_struct *work)
@@ -282,6 +293,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
282 tty->receive_room = 65536; 293 tty->receive_room = 65536;
283 294
284 INIT_WORK(&hu->init_ready, hci_uart_init_work); 295 INIT_WORK(&hu->init_ready, hci_uart_init_work);
296 INIT_WORK(&hu->write_work, hci_uart_write_work);
285 297
286 spin_lock_init(&hu->rx_lock); 298 spin_lock_init(&hu->rx_lock);
287 299
@@ -319,6 +331,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
319 if (hdev) 331 if (hdev)
320 hci_uart_close(hdev); 332 hci_uart_close(hdev);
321 333
334 cancel_work_sync(&hu->write_work);
335
322 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { 336 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
323 if (hdev) { 337 if (hdev) {
324 if (test_bit(HCI_UART_REGISTERED, &hu->flags)) 338 if (test_bit(HCI_UART_REGISTERED, &hu->flags))
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index fffa61ff5cb1..12df101ca942 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -68,6 +68,7 @@ struct hci_uart {
68 unsigned long hdev_flags; 68 unsigned long hdev_flags;
69 69
70 struct work_struct init_ready; 70 struct work_struct init_ready;
71 struct work_struct write_work;
71 72
72 struct hci_uart_proto *proto; 73 struct hci_uart_proto *proto;
73 void *priv; 74 void *priv;