Re: [PATCH 02/13] bluetooth: hci_ldisc: fix deadlock condition

2014-04-24 Thread Andreas Bießmann
Dear Felipe Balbi,

On Wed, Apr 23, 2014 at 09:58:26AM -0500, Felipe Balbi wrote:
 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 mar...@holtmann.org
 Reviewed-by: Peter Hurley pe...@hurleysoftware.com
 Reported-by: Huang Shijie b32...@freescale.com
 Signed-off-by: Felipe Balbi ba...@ti.com

Tested-by: Andreas Bießmann andr...@biessmann.de

on custom TI AM37xx board with 3.4.87. Therefore I vote for adding this to
stable branches (at least 3.4). It applies with a slight line shifting
(init_work is not available there).

I wonder if you have seen my approach [1] to fix this deadlock.  This stuff is
quiet new to me. As I understood the work_queue has a bit more overhead than a
tasklet. Therefore I implemented my fix with a tasklet. Would be great if one
could shed some light on that.

Best regards

Andreas Bießmann

[1] https://lkml.org/lkml/2014/4/16/425

 ---
  drivers/bluetooth/hci_ldisc.c | 24 +++-
  drivers/bluetooth/hci_uart.h  |  1 +
  2 files changed, 20 insertions(+), 5 deletions(-)
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/13] bluetooth: hci_ldisc: fix deadlock condition

2014-04-23 Thread Felipe Balbi
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 mar...@holtmann.org
Reviewed-by: Peter Hurley pe...@hurleysoftware.com
Reported-by: Huang Shijie b32...@freescale.com
Signed-off-by: Felipe Balbi ba...@ti.com
---
 drivers/bluetooth/hci_ldisc.c | 24 +++-
 drivers/bluetooth/hci_uart.h  |  1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index f1fbf4f..e00f8f5 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)
 
 int hci_uart_tx_wakeup(struct hci_uart *hu)
 {
-   struct tty_struct *tty = hu-tty;
-   struct hci_dev *hdev = hu-hdev;
-   struct sk_buff *skb;
-
if (test_and_set_bit(HCI_UART_SENDING, hu-tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
return 0;
@@ -129,6 +125,22 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
 
BT_DBG();
 
+   schedule_work(hu-write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, write_work);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+
+   /* REVISIT: should we cope with bad skbs or -write() returning
+* and error value ?
+*/
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
 
@@ -153,7 +165,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -282,6 +293,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty-receive_room = 65536;
 
INIT_WORK(hu-init_ready, hci_uart_init_work);
+   INIT_WORK(hu-write_work, hci_uart_write_work);
 
spin_lock_init(hu-rx_lock);
 
@@ -319,6 +331,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);
 
+   cancel_work_sync(hu-write_work);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, hu-flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, hu-flags))
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index fffa61f..12df101 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -68,6 +68,7 @@ struct hci_uart {
unsigned long   hdev_flags;
 
struct work_struct  init_ready;
+   struct work_struct  write_work;
 
struct hci_uart_proto   *proto;
void*priv;
-- 
1.9.2.459.g68773ac

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html