Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
Hi,

On Thu, Mar 20, 2014 at 03:16:35PM -0400, Peter Hurley wrote:
> On 03/20/2014 02:25 PM, Felipe Balbi wrote:
> >On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
> >>On 03/20/2014 02:11 PM, Felipe Balbi wrote:
> >>>On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
> [ +cc Huang Shijie ]
> 
> On 03/20/2014 01:16 PM, Felipe Balbi wrote:
> >On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> >>On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> >>>Hi,
> >>>
> >>>when 8250 driver calls uart_write_wakeup(), the tty port lock is 
> >>>already
> >>>taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> >>>tty->ops->write() to actually send the characters, but that call will
> >>>try to acquire the same port lock again.
> >>>
> >>>Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> >>>Am I correct to assume that ->write_wakeup() is supposed to *just*
> >>>wakeup the bottom half so we handle ->write() in another context ?
> >>>
> >>>Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> >>
> >>It isn't because you might send all the bytes and go
> >>
> >>write
> >>write_wakeup
> >>write
> >>write wakeup
> >>...
> >>
> >>and recurse
> >
> >cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
> >you want this to be sorted out ?
> 
> hci_uart_tx_wakeup() should perform the I/O as work.
> FWIW, this was reported by Huang Shijie back on Dec 6.
> 
> I'd fix it but I have no way to test it.
> >>>
> >>>here's a build-tested only patch which is waiting for testing from other
> >>>colleagues who've got a platform to reproduce the problem:
> >>
> >>Where's the cancel_work_sync() on teardown?
> >
> >here, as a patch too this time:
> 
> Thanks. Minor edits below but, strictly speaking, not necessary.
> 
> Reviewed-by: Peter Hurley 
> 
> 
> > From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
> >From: Felipe Balbi 
> >Date: Thu, 20 Mar 2014 13:20:10 -0500
> >Subject: [PATCH] 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.
> >
> 
> I know you found it independently but ?
> 
> Reported-by: Huang Shijie 

I will never add any *-by tags without seeing it in the mailing list.
Now I can add it to the patch and send it as a real patch (git
send-email it).

> >Signed-off-by: Felipe Balbi 
> >---
> >  drivers/bluetooth/hci_ldisc.c | 20 +++-
> >  drivers/bluetooth/hci_uart.h  |  1 +
> >  2 files changed, 16 insertions(+), 5 deletions(-)
> >
> >diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
> >index 6e06f6f..ecdd765 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, >tx_state)) {
> > set_bit(HCI_UART_TX_WAKEUP, >tx_state);
> > return 0;
> >@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
> >
> > BT_DBG("");
> >
> >+schedule_work(>write_work);
> >+
> >+return 0;
> >+}
> >+
> >+static void hci_uart_write_work(struct work_struct *work)
> >+{
> >+struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
> >+struct tty_struct *tty = hu->tty;
> >+struct hci_dev *hdev = hu->hdev;
> >+struct sk_buff *skb;
> >+
> 
> + /* FIXME: if bad skb length or tty->ops->write() returns < 0 ??? */
> 
> >  restart:
> > clear_bit(HCI_UART_TX_WAKEUP, >tx_state);
> >
> >@@ -153,7 +161,6 @@ restart:
> > goto restart;
> >
> > clear_bit(HCI_UART_SENDING, >tx_state);
> >-return 0;
> >  }
> >
> >  static void hci_uart_init_work(struct work_struct *work)
> >@@ -281,6 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
> > tty->receive_room = 65536;
> >
> > INIT_WORK(>init_ready, hci_uart_init_work);
> >+INIT_WORK(>write_work, hci_uart_write_work);
> >
> > spin_lock_init(>rx_lock);
> >
> >@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
> > if (hdev)
> > hci_uart_close(hdev);
> >
> >+cancel_work_sync(>write_work);
> >+
> > if (test_and_clear_bit(HCI_UART_PROTO_SET, >flags)) {
> > if (hdev) {
> > if (test_bit(HCI_UART_REGISTERED, >flags))
> >diff --git 

Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:25 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:

On 03/20/2014 02:11 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of ->write_wakeup() calls
tty->ops->write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that ->write_wakeup() is supposed to *just*
wakeup the bottom half so we handle ->write() in another context ?

Is it legal to call tty->ops->write() from within ->write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.


here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:


Where's the cancel_work_sync() on teardown?


here, as a patch too this time:


Thanks. Minor edits below but, strictly speaking, not necessary.

Reviewed-by: Peter Hurley 



 From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
From: Felipe Balbi 
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.



I know you found it independently but ?

Reported-by: Huang Shijie 


Signed-off-by: Felipe Balbi 
---
  drivers/bluetooth/hci_ldisc.c | 20 +++-
  drivers/bluetooth/hci_uart.h  |  1 +
  2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..ecdd765 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, >tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, >tx_state);
return 0;
@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)

BT_DBG("");

+   schedule_work(>write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
+   struct tty_struct *tty = hu->tty;
+   struct hci_dev *hdev = hu->hdev;
+   struct sk_buff *skb;
+


+   /* FIXME: if bad skb length or tty->ops->write() returns < 0 ??? */


  restart:
clear_bit(HCI_UART_TX_WAKEUP, >tx_state);

@@ -153,7 +161,6 @@ restart:
goto restart;

clear_bit(HCI_UART_SENDING, >tx_state);
-   return 0;
  }

  static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;

INIT_WORK(>init_ready, hci_uart_init_work);
+   INIT_WORK(>write_work, hci_uart_write_work);

spin_lock_init(>rx_lock);

@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);

+   cancel_work_sync(>write_work);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, >flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, >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;



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
Hi,

On Thu, Mar 20, 2014 at 02:01:54PM -0500, Felipe Balbi wrote:
> > @@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
> > if (hdev)
> > hci_uart_close(hdev);
> >  
> > +   cancel_work_sync(>write_work);
> 
> forgot to commit, darn it

here it is:

From eaf7ff6f2d224f202369e4820b76a03fa664fab0 Mon Sep 17 00:00:00 2001
From: Felipe Balbi 
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.

Signed-off-by: Felipe Balbi 
---
 drivers/bluetooth/hci_ldisc.c | 20 +++-
 drivers/bluetooth/hci_uart.h  |  1 +
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..5a53e50 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, >tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, >tx_state);
return 0;
@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
 
BT_DBG("");
 
+   schedule_work(>write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
+   struct tty_struct *tty = hu->tty;
+   struct hci_dev *hdev = hu->hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, >tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, >tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;
 
INIT_WORK(>init_ready, hci_uart_init_work);
+   INIT_WORK(>write_work, hci_uart_write_work);
 
spin_lock_init(>rx_lock);
 
@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);
 
+   cancel_work_sync(>write_work);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, >flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, >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.1.286.g5172cb3


-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:25:28PM -0500, Felipe Balbi wrote:
> On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
> > On 03/20/2014 02:11 PM, Felipe Balbi wrote:
> > >On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
> > >>[ +cc Huang Shijie ]
> > >>
> > >>On 03/20/2014 01:16 PM, Felipe Balbi wrote:
> > >>>On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> > On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> > >Hi,
> > >
> > >when 8250 driver calls uart_write_wakeup(), the tty port lock is 
> > >already
> > >taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> > >tty->ops->write() to actually send the characters, but that call will
> > >try to acquire the same port lock again.
> > >
> > >Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> > >Am I correct to assume that ->write_wakeup() is supposed to *just*
> > >wakeup the bottom half so we handle ->write() in another context ?
> > >
> > >Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> > 
> > It isn't because you might send all the bytes and go
> > 
> > write
> > write_wakeup
> > write
> > write wakeup
> > ...
> > 
> > and recurse
> > >>>
> > >>>cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
> > >>>you want this to be sorted out ?
> > >>
> > >>hci_uart_tx_wakeup() should perform the I/O as work.
> > >>FWIW, this was reported by Huang Shijie back on Dec 6.
> > >>
> > >>I'd fix it but I have no way to test it.
> > >
> > >here's a build-tested only patch which is waiting for testing from other
> > >colleagues who've got a platform to reproduce the problem:
> > 
> > Where's the cancel_work_sync() on teardown?
> 
> here, as a patch too this time:
> 
> From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
> From: Felipe Balbi 
> Date: Thu, 20 Mar 2014 13:20:10 -0500
> Subject: [PATCH] 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.
> 
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/bluetooth/hci_ldisc.c | 20 +++-
>  drivers/bluetooth/hci_uart.h  |  1 +
>  2 files changed, 16 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
> index 6e06f6f..ecdd765 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, >tx_state)) {
>   set_bit(HCI_UART_TX_WAKEUP, >tx_state);
>   return 0;
> @@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
>  
>   BT_DBG("");
>  
> + schedule_work(>write_work);
> +
> + return 0;
> +}
> +
> +static void hci_uart_write_work(struct work_struct *work)
> +{
> + struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
> + struct tty_struct *tty = hu->tty;
> + struct hci_dev *hdev = hu->hdev;
> + struct sk_buff *skb;
> +
>  restart:
>   clear_bit(HCI_UART_TX_WAKEUP, >tx_state);
>  
> @@ -153,7 +161,6 @@ restart:
>   goto restart;
>  
>   clear_bit(HCI_UART_SENDING, >tx_state);
> - return 0;
>  }
>  
>  static void hci_uart_init_work(struct work_struct *work)
> @@ -281,6 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
>   tty->receive_room = 65536;
>  
>   INIT_WORK(>init_ready, hci_uart_init_work);
> + INIT_WORK(>write_work, hci_uart_write_work);
>  
>   spin_lock_init(>rx_lock);
>  
> @@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
>   if (hdev)
>   hci_uart_close(hdev);
>  
> + cancel_work_sync(>write_work);

forgot to commit, darn it

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:45 PM, Greg KH wrote:

On Thu, Mar 20, 2014 at 12:35:18PM -0500, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:29 PM, Felipe Balbi wrote:

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|
|   The driver is forbidden from calling this directly
|   from the ->write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call ->write() from
->write_wakeup(). huh ?


Patch submitted but never applied.

http://www.spinics.net/lists/linux-serial/msg11144.html


Thank you. For that patch:

Acked-by: Felipe Balbi 


Can someone resend it, this is lost in my tree for some reason...


Apologies if my mailer mangles this.

--- >% ---
From: Huang Shijie 

In the uart_handle_cts_change(), uart_write_wakeup() is called after
we call @uart_port->ops->start_tx().

The Documentation/serial/driver tells us:
---
  start_tx(port)
Start transmitting characters.

Locking: port->lock taken.
Interrupts: locally disabled.
---

So when the uart_write_wakeup() is called, the port->lock is taken by
the upper. See the following callstack:

|_ uart_write_wakeup
   |_ tty_wakeup
  |_ ld->ops->write_wakeup

With the port->lock held, we call the @write_wakeup. Some implemetation of
the @write_wakeup does not notice that the port->lock is held, and it still
tries to send data with uart_write() which will try to grab the prot->lock.
A dead lock occurs, see the following log caught in the Bluetooth by uart:


BUG: spinlock lockup suspected on CPU#0, swapper/0/0
 lock: 0xdc3f4410, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0
CPU: 0 PID: 0 Comm: swapper/0 Tainted: GW3.10.17-16839-ge4a1bef 
#1320
[<80014cbc>] (unwind_backtrace+0x0/0x138) from [<8001251c>] 
(show_stack+0x10/0x14)
[<8001251c>] (show_stack+0x10/0x14) from [<802816ac>] 
(do_raw_spin_lock+0x108/0x184)
[<802816ac>] (do_raw_spin_lock+0x108/0x184) from [<806a22b0>] 
(_raw_spin_lock_irqsave+0x54/0x60)
[<806a22b0>] (_raw_spin_lock_irqsave+0x54/0x60) from [<802f5754>] 
(uart_write+0x38/0xe0)
[<802f5754>] (uart_write+0x38/0xe0) from [<80455270>] 
(hci_uart_tx_wakeup+0xa4/0x168)
[<80455270>] (hci_uart_tx_wakeup+0xa4/0x168) from [<802dab18>] 
(tty_wakeup+0x50/0x5c)
[<802dab18>] (tty_wakeup+0x50/0x5c) from [<802f81a4>] (imx_rtsint+0x50/0x80)
[<802f81a4>] (imx_rtsint+0x50/0x80) from [<802f88f4>] (imx_int+0x158/0x17c)
[<802f88f4>] (imx_int+0x158/0x17c) from [<8007abe0>] 
(handle_irq_event_percpu+0x50/0x194)
[<8007abe0>] (handle_irq_event_percpu+0x50/0x194) from [<8007ad60>] 
(handle_irq_event+0x3c/0x5c)


This patch adds more limits to the @write_wakeup, the one who wants to
implemet the @write_wakeup should follow the limits which avoid the deadlock.

Signed-off-by: Huang Shijie 
---
 include/linux/tty_ldisc.h |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index f15c898..539ccc5 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -91,7 +91,10 @@
  * This function is called by the low-level tty driver to signal
  * that line discpline should try to send more characters to the
  * low-level driver for transmission.  If the line discpline does
- * not have any more data to send, it can just return.
+ * not have any more data to send, it can just return. If the line
+ * discipline does have some data to send, please arise a tasklet
+ * or workqueue to do the real data transfer. Do not send data in
+ * this hook, it may leads to a deadlock.
  *
  * int (*hangup)(struct tty_struct *)
  *
-- 1.7.2.rc3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Greg KH
On Thu, Mar 20, 2014 at 12:35:18PM -0500, Felipe Balbi wrote:
> On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:
> > [ +cc Huang Shijie ]
> > 
> > On 03/20/2014 01:29 PM, Felipe Balbi wrote:
> > >then we need updates to Documentation:
> > >
> > >Documentation/serial/tty.txt::
> > >
> > >|  Driver Side Interfaces:
> > >|
> > >|  receive_buf()   -   Hand buffers of bytes from the driver to the 
> > >ldisc
> > >|  for processing. Semantics currently rather
> > >|  mysterious 8(
> > >|
> > >|  write_wakeup()  -   May be called at any point between open and 
> > >close.
> > >|  The TTY_DO_WRITE_WAKEUP flag indicates if a call
> > >|  is needed but always races versus calls. Thus 
> > >the
> > >|  ldisc must be careful about setting order and to
> > >|  handle unexpected calls. Must not sleep.
> > >|
> > >|  The driver is forbidden from calling this 
> > >directly
> > >|  from the ->write call from the ldisc as the 
> > >ldisc
> > >|  is permitted to call the driver write method 
> > >from
> > >|  this function. In such a situation defer it.
> > >
> > >documentation says ldisc is allowed to call ->write() from
> > >->write_wakeup(). huh ?
> > 
> > Patch submitted but never applied.
> > 
> > http://www.spinics.net/lists/linux-serial/msg11144.html
> 
> Thank you. For that patch:
> 
> Acked-by: Felipe Balbi 

Can someone resend it, this is lost in my tree for some reason...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
> On 03/20/2014 02:11 PM, Felipe Balbi wrote:
> >On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
> >>[ +cc Huang Shijie ]
> >>
> >>On 03/20/2014 01:16 PM, Felipe Balbi wrote:
> >>>On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> >Hi,
> >
> >when 8250 driver calls uart_write_wakeup(), the tty port lock is already
> >taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> >tty->ops->write() to actually send the characters, but that call will
> >try to acquire the same port lock again.
> >
> >Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> >Am I correct to assume that ->write_wakeup() is supposed to *just*
> >wakeup the bottom half so we handle ->write() in another context ?
> >
> >Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> 
> It isn't because you might send all the bytes and go
> 
>   write
>   write_wakeup
>   write
>   write wakeup
>   ...
> 
> and recurse
> >>>
> >>>cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
> >>>you want this to be sorted out ?
> >>
> >>hci_uart_tx_wakeup() should perform the I/O as work.
> >>FWIW, this was reported by Huang Shijie back on Dec 6.
> >>
> >>I'd fix it but I have no way to test it.
> >
> >here's a build-tested only patch which is waiting for testing from other
> >colleagues who've got a platform to reproduce the problem:
> 
> Where's the cancel_work_sync() on teardown?

here, as a patch too this time:

From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
From: Felipe Balbi 
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.

Signed-off-by: Felipe Balbi 
---
 drivers/bluetooth/hci_ldisc.c | 20 +++-
 drivers/bluetooth/hci_uart.h  |  1 +
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..ecdd765 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, >tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, >tx_state);
return 0;
@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
 
BT_DBG("");
 
+   schedule_work(>write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
+   struct tty_struct *tty = hu->tty;
+   struct hci_dev *hdev = hu->hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, >tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, >tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;
 
INIT_WORK(>init_ready, hci_uart_init_work);
+   INIT_WORK(>write_work, hci_uart_write_work);
 
spin_lock_init(>rx_lock);
 
@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);
 
+   cancel_work_sync(>write_work);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, >flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, >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.1.286.g5172cb3


-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:11 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of ->write_wakeup() calls
tty->ops->write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that ->write_wakeup() is supposed to *just*
wakeup the bottom half so we handle ->write() in another context ?

Is it legal to call tty->ops->write() from within ->write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.


here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:


Where's the cancel_work_sync() on teardown?

Regards,
Peter Hurley


diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index bc68a44..789000d 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, >tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, >tx_state);
return 0;
@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)

BT_DBG("");

+   schedule_work(>write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
+   struct tty_struct *tty = hu->tty;
+   struct hci_dev *hdev = hu->hdev;
+   struct sk_buff *skb;
+
  restart:
clear_bit(HCI_UART_TX_WAKEUP, >tx_state);

@@ -153,7 +161,6 @@ restart:
goto restart;

clear_bit(HCI_UART_SENDING, >tx_state);
-   return 0;
  }

  static void hci_uart_init_work(struct work_struct *work)
@@ -289,6 +296,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;

INIT_WORK(>init_ready, hci_uart_init_work);
+   INIT_WORK(>write_work, hci_uart_write_work);

spin_lock_init(>rx_lock);

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;



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
> [ +cc Huang Shijie ]
> 
> On 03/20/2014 01:16 PM, Felipe Balbi wrote:
> >On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> >>On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> >>>Hi,
> >>>
> >>>when 8250 driver calls uart_write_wakeup(), the tty port lock is already
> >>>taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> >>>tty->ops->write() to actually send the characters, but that call will
> >>>try to acquire the same port lock again.
> >>>
> >>>Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> >>>Am I correct to assume that ->write_wakeup() is supposed to *just*
> >>>wakeup the bottom half so we handle ->write() in another context ?
> >>>
> >>>Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> >>
> >>It isn't because you might send all the bytes and go
> >>
> >>write
> >>write_wakeup
> >>write
> >>write wakeup
> >>...
> >>
> >>and recurse
> >
> >cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
> >you want this to be sorted out ?
> 
> hci_uart_tx_wakeup() should perform the I/O as work.
> FWIW, this was reported by Huang Shijie back on Dec 6.
> 
> I'd fix it but I have no way to test it.

here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index bc68a44..789000d 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, >tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, >tx_state);
return 0;
@@ -129,6 +125,18 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
 
BT_DBG("");
 
+   schedule_work(>write_work);
+
+   return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+   struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
+   struct tty_struct *tty = hu->tty;
+   struct hci_dev *hdev = hu->hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, >tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, >tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -289,6 +296,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;
 
INIT_WORK(>init_ready, hci_uart_init_work);
+   INIT_WORK(>write_work, hci_uart_write_work);
 
spin_lock_init(>rx_lock);
 
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;

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:
> [ +cc Huang Shijie ]
> 
> On 03/20/2014 01:29 PM, Felipe Balbi wrote:
> >then we need updates to Documentation:
> >
> >Documentation/serial/tty.txt::
> >
> >|  Driver Side Interfaces:
> >|
> >|  receive_buf() -   Hand buffers of bytes from the driver to the 
> >ldisc
> >|for processing. Semantics currently rather
> >|mysterious 8(
> >|
> >|  write_wakeup()-   May be called at any point between open and 
> >close.
> >|The TTY_DO_WRITE_WAKEUP flag indicates if a call
> >|is needed but always races versus calls. Thus the
> >|ldisc must be careful about setting order and to
> >|handle unexpected calls. Must not sleep.
> >|
> >|The driver is forbidden from calling this directly
> >|from the ->write call from the ldisc as the ldisc
> >|is permitted to call the driver write method from
> >|this function. In such a situation defer it.
> >
> >documentation says ldisc is allowed to call ->write() from
> >->write_wakeup(). huh ?
> 
> Patch submitted but never applied.
> 
> http://www.spinics.net/lists/linux-serial/msg11144.html

Thank you. For that patch:

Acked-by: Felipe Balbi 

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

[ +cc Huang Shijie ]

On 03/20/2014 01:29 PM, Felipe Balbi wrote:

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|
|   The driver is forbidden from calling this directly
|   from the ->write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call ->write() from
->write_wakeup(). huh ?


Patch submitted but never applied.

http://www.spinics.net/lists/linux-serial/msg11144.html

Regards,
Peter Hurley
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of ->write_wakeup() calls
tty->ops->write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that ->write_wakeup() is supposed to *just*
wakeup the bottom half so we handle ->write() in another context ?

Is it legal to call tty->ops->write() from within ->write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.

Regards,
Peter Hurley
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 12:16:22PM -0500, Felipe Balbi wrote:
> On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> > On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> > > Hi,
> > > 
> > > when 8250 driver calls uart_write_wakeup(), the tty port lock is already
> > > taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> > > tty->ops->write() to actually send the characters, but that call will
> > > try to acquire the same port lock again.
> > > 
> > > Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> > > Am I correct to assume that ->write_wakeup() is supposed to *just*
> > > wakeup the bottom half so we handle ->write() in another context ?
> > > 
> > > Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> > 
> > It isn't because you might send all the bytes and go
> > 
> > write
> > write_wakeup
> > write
> > write wakeup
> > ...
> > 
> > and recurse

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|  
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|  
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|  
|   The driver is forbidden from calling this directly
|   from the ->write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call ->write() from
->write_wakeup(). huh ?

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
> On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> > Hi,
> > 
> > when 8250 driver calls uart_write_wakeup(), the tty port lock is already
> > taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> > tty->ops->write() to actually send the characters, but that call will
> > try to acquire the same port lock again.
> > 
> > Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> > Am I correct to assume that ->write_wakeup() is supposed to *just*
> > wakeup the bottom half so we handle ->write() in another context ?
> > 
> > Is it legal to call tty->ops->write() from within ->write_wakeup() ?
> 
> It isn't because you might send all the bytes and go
> 
>   write
>   write_wakeup
>   write
>   write wakeup
>   ...
> 
> and recurse

cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Alan Cox
On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
> Hi,
> 
> when 8250 driver calls uart_write_wakeup(), the tty port lock is already
> taken. hci_ldisc.c's implementation of ->write_wakeup() calls
> tty->ops->write() to actually send the characters, but that call will
> try to acquire the same port lock again.
> 
> Looking at other line disciplines that looks like a bug in hci_ldisc.c.
> Am I correct to assume that ->write_wakeup() is supposed to *just*
> wakeup the bottom half so we handle ->write() in another context ?
> 
> Is it legal to call tty->ops->write() from within ->write_wakeup() ?

It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse

Alan


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Alan Cox
On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
 Hi,
 
 when 8250 driver calls uart_write_wakeup(), the tty port lock is already
 taken. hci_ldisc.c's implementation of -write_wakeup() calls
 tty-ops-write() to actually send the characters, but that call will
 try to acquire the same port lock again.
 
 Looking at other line disciplines that looks like a bug in hci_ldisc.c.
 Am I correct to assume that -write_wakeup() is supposed to *just*
 wakeup the bottom half so we handle -write() in another context ?
 
 Is it legal to call tty-ops-write() from within -write_wakeup() ?

It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse

Alan


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


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
 On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
  Hi,
  
  when 8250 driver calls uart_write_wakeup(), the tty port lock is already
  taken. hci_ldisc.c's implementation of -write_wakeup() calls
  tty-ops-write() to actually send the characters, but that call will
  try to acquire the same port lock again.
  
  Looking at other line disciplines that looks like a bug in hci_ldisc.c.
  Am I correct to assume that -write_wakeup() is supposed to *just*
  wakeup the bottom half so we handle -write() in another context ?
  
  Is it legal to call tty-ops-write() from within -write_wakeup() ?
 
 It isn't because you might send all the bytes and go
 
   write
   write_wakeup
   write
   write wakeup
   ...
 
 and recurse

cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 12:16:22PM -0500, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
  On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
   Hi,
   
   when 8250 driver calls uart_write_wakeup(), the tty port lock is already
   taken. hci_ldisc.c's implementation of -write_wakeup() calls
   tty-ops-write() to actually send the characters, but that call will
   try to acquire the same port lock again.
   
   Looking at other line disciplines that looks like a bug in hci_ldisc.c.
   Am I correct to assume that -write_wakeup() is supposed to *just*
   wakeup the bottom half so we handle -write() in another context ?
   
   Is it legal to call tty-ops-write() from within -write_wakeup() ?
  
  It isn't because you might send all the bytes and go
  
  write
  write_wakeup
  write
  write wakeup
  ...
  
  and recurse

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|  
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|  
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|  
|   The driver is forbidden from calling this directly
|   from the -write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call -write() from
-write_wakeup(). huh ?

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of -write_wakeup() calls
tty-ops-write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that -write_wakeup() is supposed to *just*
wakeup the bottom half so we handle -write() in another context ?

Is it legal to call tty-ops-write() from within -write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.

Regards,
Peter Hurley
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

[ +cc Huang Shijie ]

On 03/20/2014 01:29 PM, Felipe Balbi wrote:

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|
|   The driver is forbidden from calling this directly
|   from the -write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call -write() from
-write_wakeup(). huh ?


Patch submitted but never applied.

http://www.spinics.net/lists/linux-serial/msg11144.html

Regards,
Peter Hurley
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:
 [ +cc Huang Shijie ]
 
 On 03/20/2014 01:29 PM, Felipe Balbi wrote:
 then we need updates to Documentation:
 
 Documentation/serial/tty.txt::
 
 |  Driver Side Interfaces:
 |
 |  receive_buf() -   Hand buffers of bytes from the driver to the 
 ldisc
 |for processing. Semantics currently rather
 |mysterious 8(
 |
 |  write_wakeup()-   May be called at any point between open and 
 close.
 |The TTY_DO_WRITE_WAKEUP flag indicates if a call
 |is needed but always races versus calls. Thus the
 |ldisc must be careful about setting order and to
 |handle unexpected calls. Must not sleep.
 |
 |The driver is forbidden from calling this directly
 |from the -write call from the ldisc as the ldisc
 |is permitted to call the driver write method from
 |this function. In such a situation defer it.
 
 documentation says ldisc is allowed to call -write() from
 -write_wakeup(). huh ?
 
 Patch submitted but never applied.
 
 http://www.spinics.net/lists/linux-serial/msg11144.html

Thank you. For that patch:

Acked-by: Felipe Balbi ba...@ti.com

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
 [ +cc Huang Shijie ]
 
 On 03/20/2014 01:16 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
 On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
 Hi,
 
 when 8250 driver calls uart_write_wakeup(), the tty port lock is already
 taken. hci_ldisc.c's implementation of -write_wakeup() calls
 tty-ops-write() to actually send the characters, but that call will
 try to acquire the same port lock again.
 
 Looking at other line disciplines that looks like a bug in hci_ldisc.c.
 Am I correct to assume that -write_wakeup() is supposed to *just*
 wakeup the bottom half so we handle -write() in another context ?
 
 Is it legal to call tty-ops-write() from within -write_wakeup() ?
 
 It isn't because you might send all the bytes and go
 
 write
 write_wakeup
 write
 write wakeup
 ...
 
 and recurse
 
 cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
 you want this to be sorted out ?
 
 hci_uart_tx_wakeup() should perform the I/O as work.
 FWIW, this was reported by Huang Shijie back on Dec 6.
 
 I'd fix it but I have no way to test it.

here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index bc68a44..789000d 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,18 @@ 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, init_ready);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -289,6 +296,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);
 
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;

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:11 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of -write_wakeup() calls
tty-ops-write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that -write_wakeup() is supposed to *just*
wakeup the bottom half so we handle -write() in another context ?

Is it legal to call tty-ops-write() from within -write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.


here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:


Where's the cancel_work_sync() on teardown?

Regards,
Peter Hurley


diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index bc68a44..789000d 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,18 @@ 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, init_ready);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+
  restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);

@@ -153,7 +161,6 @@ restart:
goto restart;

clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
  }

  static void hci_uart_init_work(struct work_struct *work)
@@ -289,6 +296,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);

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;



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


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
 On 03/20/2014 02:11 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
 [ +cc Huang Shijie ]
 
 On 03/20/2014 01:16 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
 On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
 Hi,
 
 when 8250 driver calls uart_write_wakeup(), the tty port lock is already
 taken. hci_ldisc.c's implementation of -write_wakeup() calls
 tty-ops-write() to actually send the characters, but that call will
 try to acquire the same port lock again.
 
 Looking at other line disciplines that looks like a bug in hci_ldisc.c.
 Am I correct to assume that -write_wakeup() is supposed to *just*
 wakeup the bottom half so we handle -write() in another context ?
 
 Is it legal to call tty-ops-write() from within -write_wakeup() ?
 
 It isn't because you might send all the bytes and go
 
   write
   write_wakeup
   write
   write wakeup
   ...
 
 and recurse
 
 cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
 you want this to be sorted out ?
 
 hci_uart_tx_wakeup() should perform the I/O as work.
 FWIW, this was reported by Huang Shijie back on Dec 6.
 
 I'd fix it but I have no way to test it.
 
 here's a build-tested only patch which is waiting for testing from other
 colleagues who've got a platform to reproduce the problem:
 
 Where's the cancel_work_sync() on teardown?

here, as a patch too this time:

From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
From: Felipe Balbi ba...@ti.com
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.

Signed-off-by: Felipe Balbi ba...@ti.com
---
 drivers/bluetooth/hci_ldisc.c | 20 +++-
 drivers/bluetooth/hci_uart.h  |  1 +
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..ecdd765 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,18 @@ 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, init_ready);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,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);
 
@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);
 
+   cancel_work_sync(hy-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.1.286.g5172cb3


-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Greg KH
On Thu, Mar 20, 2014 at 12:35:18PM -0500, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:
  [ +cc Huang Shijie ]
  
  On 03/20/2014 01:29 PM, Felipe Balbi wrote:
  then we need updates to Documentation:
  
  Documentation/serial/tty.txt::
  
  |  Driver Side Interfaces:
  |
  |  receive_buf()   -   Hand buffers of bytes from the driver to the 
  ldisc
  |  for processing. Semantics currently rather
  |  mysterious 8(
  |
  |  write_wakeup()  -   May be called at any point between open and 
  close.
  |  The TTY_DO_WRITE_WAKEUP flag indicates if a call
  |  is needed but always races versus calls. Thus 
  the
  |  ldisc must be careful about setting order and to
  |  handle unexpected calls. Must not sleep.
  |
  |  The driver is forbidden from calling this 
  directly
  |  from the -write call from the ldisc as the 
  ldisc
  |  is permitted to call the driver write method 
  from
  |  this function. In such a situation defer it.
  
  documentation says ldisc is allowed to call -write() from
  -write_wakeup(). huh ?
  
  Patch submitted but never applied.
  
  http://www.spinics.net/lists/linux-serial/msg11144.html
 
 Thank you. For that patch:
 
 Acked-by: Felipe Balbi ba...@ti.com

Can someone resend it, this is lost in my tree for some reason...
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:45 PM, Greg KH wrote:

On Thu, Mar 20, 2014 at 12:35:18PM -0500, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:34:57PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:29 PM, Felipe Balbi wrote:

then we need updates to Documentation:

Documentation/serial/tty.txt::

|  Driver Side Interfaces:
|
|  receive_buf()-   Hand buffers of bytes from the driver to the 
ldisc
|   for processing. Semantics currently rather
|   mysterious 8(
|
|  write_wakeup()   -   May be called at any point between open and 
close.
|   The TTY_DO_WRITE_WAKEUP flag indicates if a call
|   is needed but always races versus calls. Thus the
|   ldisc must be careful about setting order and to
|   handle unexpected calls. Must not sleep.
|
|   The driver is forbidden from calling this directly
|   from the -write call from the ldisc as the ldisc
|   is permitted to call the driver write method from
|   this function. In such a situation defer it.

documentation says ldisc is allowed to call -write() from
-write_wakeup(). huh ?


Patch submitted but never applied.

http://www.spinics.net/lists/linux-serial/msg11144.html


Thank you. For that patch:

Acked-by: Felipe Balbi ba...@ti.com


Can someone resend it, this is lost in my tree for some reason...


Apologies if my mailer mangles this.

--- % ---
From: Huang Shijie b32...@freescale.com

In the uart_handle_cts_change(), uart_write_wakeup() is called after
we call @uart_port-ops-start_tx().

The Documentation/serial/driver tells us:
---
  start_tx(port)
Start transmitting characters.

Locking: port-lock taken.
Interrupts: locally disabled.
---

So when the uart_write_wakeup() is called, the port-lock is taken by
the upper. See the following callstack:

|_ uart_write_wakeup
   |_ tty_wakeup
  |_ ld-ops-write_wakeup

With the port-lock held, we call the @write_wakeup. Some implemetation of
the @write_wakeup does not notice that the port-lock is held, and it still
tries to send data with uart_write() which will try to grab the prot-lock.
A dead lock occurs, see the following log caught in the Bluetooth by uart:


BUG: spinlock lockup suspected on CPU#0, swapper/0/0
 lock: 0xdc3f4410, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0
CPU: 0 PID: 0 Comm: swapper/0 Tainted: GW3.10.17-16839-ge4a1bef 
#1320
[80014cbc] (unwind_backtrace+0x0/0x138) from [8001251c] 
(show_stack+0x10/0x14)
[8001251c] (show_stack+0x10/0x14) from [802816ac] 
(do_raw_spin_lock+0x108/0x184)
[802816ac] (do_raw_spin_lock+0x108/0x184) from [806a22b0] 
(_raw_spin_lock_irqsave+0x54/0x60)
[806a22b0] (_raw_spin_lock_irqsave+0x54/0x60) from [802f5754] 
(uart_write+0x38/0xe0)
[802f5754] (uart_write+0x38/0xe0) from [80455270] 
(hci_uart_tx_wakeup+0xa4/0x168)
[80455270] (hci_uart_tx_wakeup+0xa4/0x168) from [802dab18] 
(tty_wakeup+0x50/0x5c)
[802dab18] (tty_wakeup+0x50/0x5c) from [802f81a4] (imx_rtsint+0x50/0x80)
[802f81a4] (imx_rtsint+0x50/0x80) from [802f88f4] (imx_int+0x158/0x17c)
[802f88f4] (imx_int+0x158/0x17c) from [8007abe0] 
(handle_irq_event_percpu+0x50/0x194)
[8007abe0] (handle_irq_event_percpu+0x50/0x194) from [8007ad60] 
(handle_irq_event+0x3c/0x5c)


This patch adds more limits to the @write_wakeup, the one who wants to
implemet the @write_wakeup should follow the limits which avoid the deadlock.

Signed-off-by: Huang Shijie b32...@freescale.com
---
 include/linux/tty_ldisc.h |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index f15c898..539ccc5 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -91,7 +91,10 @@
  * This function is called by the low-level tty driver to signal
  * that line discpline should try to send more characters to the
  * low-level driver for transmission.  If the line discpline does
- * not have any more data to send, it can just return.
+ * not have any more data to send, it can just return. If the line
+ * discipline does have some data to send, please arise a tasklet
+ * or workqueue to do the real data transfer. Do not send data in
+ * this hook, it may leads to a deadlock.
  *
  * int (*hangup)(struct tty_struct *)
  *
-- 1.7.2.rc3
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
On Thu, Mar 20, 2014 at 01:25:28PM -0500, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
  On 03/20/2014 02:11 PM, Felipe Balbi wrote:
  On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
  [ +cc Huang Shijie ]
  
  On 03/20/2014 01:16 PM, Felipe Balbi wrote:
  On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
  On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
  Hi,
  
  when 8250 driver calls uart_write_wakeup(), the tty port lock is 
  already
  taken. hci_ldisc.c's implementation of -write_wakeup() calls
  tty-ops-write() to actually send the characters, but that call will
  try to acquire the same port lock again.
  
  Looking at other line disciplines that looks like a bug in hci_ldisc.c.
  Am I correct to assume that -write_wakeup() is supposed to *just*
  wakeup the bottom half so we handle -write() in another context ?
  
  Is it legal to call tty-ops-write() from within -write_wakeup() ?
  
  It isn't because you might send all the bytes and go
  
  write
  write_wakeup
  write
  write wakeup
  ...
  
  and recurse
  
  cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
  you want this to be sorted out ?
  
  hci_uart_tx_wakeup() should perform the I/O as work.
  FWIW, this was reported by Huang Shijie back on Dec 6.
  
  I'd fix it but I have no way to test it.
  
  here's a build-tested only patch which is waiting for testing from other
  colleagues who've got a platform to reproduce the problem:
  
  Where's the cancel_work_sync() on teardown?
 
 here, as a patch too this time:
 
 From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
 From: Felipe Balbi ba...@ti.com
 Date: Thu, 20 Mar 2014 13:20:10 -0500
 Subject: [PATCH] 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.
 
 Signed-off-by: Felipe Balbi ba...@ti.com
 ---
  drivers/bluetooth/hci_ldisc.c | 20 +++-
  drivers/bluetooth/hci_uart.h  |  1 +
  2 files changed, 16 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
 index 6e06f6f..ecdd765 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,18 @@ 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, init_ready);
 + struct tty_struct *tty = hu-tty;
 + struct hci_dev *hdev = hu-hdev;
 + struct sk_buff *skb;
 +
  restart:
   clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
  
 @@ -153,7 +161,6 @@ restart:
   goto restart;
  
   clear_bit(HCI_UART_SENDING, hu-tx_state);
 - return 0;
  }
  
  static void hci_uart_init_work(struct work_struct *work)
 @@ -281,6 +288,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);
  
 @@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
   if (hdev)
   hci_uart_close(hdev);
  
 + cancel_work_sync(hy-write_work);

forgot to commit, darn it

-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
Hi,

On Thu, Mar 20, 2014 at 02:01:54PM -0500, Felipe Balbi wrote:
  @@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
  if (hdev)
  hci_uart_close(hdev);
   
  +   cancel_work_sync(hy-write_work);
 
 forgot to commit, darn it

here it is:

From eaf7ff6f2d224f202369e4820b76a03fa664fab0 Mon Sep 17 00:00:00 2001
From: Felipe Balbi ba...@ti.com
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.

Signed-off-by: Felipe Balbi ba...@ti.com
---
 drivers/bluetooth/hci_ldisc.c | 20 +++-
 drivers/bluetooth/hci_uart.h  |  1 +
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..5a53e50 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,18 @@ 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, init_ready);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+
 restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
 
@@ -153,7 +161,6 @@ restart:
goto restart;
 
clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
 }
 
 static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,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);
 
@@ -318,6 +326,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.1.286.g5172cb3


-- 
balbi


signature.asc
Description: Digital signature


Re: hci_ldsic nested locking problem

2014-03-20 Thread Peter Hurley

On 03/20/2014 02:25 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:

On 03/20/2014 02:11 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:

[ +cc Huang Shijie ]

On 03/20/2014 01:16 PM, Felipe Balbi wrote:

On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:

On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:

Hi,

when 8250 driver calls uart_write_wakeup(), the tty port lock is already
taken. hci_ldisc.c's implementation of -write_wakeup() calls
tty-ops-write() to actually send the characters, but that call will
try to acquire the same port lock again.

Looking at other line disciplines that looks like a bug in hci_ldisc.c.
Am I correct to assume that -write_wakeup() is supposed to *just*
wakeup the bottom half so we handle -write() in another context ?

Is it legal to call tty-ops-write() from within -write_wakeup() ?


It isn't because you might send all the bytes and go

write
write_wakeup
write
write wakeup
...

and recurse


cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
you want this to be sorted out ?


hci_uart_tx_wakeup() should perform the I/O as work.
FWIW, this was reported by Huang Shijie back on Dec 6.

I'd fix it but I have no way to test it.


here's a build-tested only patch which is waiting for testing from other
colleagues who've got a platform to reproduce the problem:


Where's the cancel_work_sync() on teardown?


here, as a patch too this time:


Thanks. Minor edits below but, strictly speaking, not necessary.

Reviewed-by: Peter Hurley pe...@hurleysoftware.com



 From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
From: Felipe Balbi ba...@ti.com
Date: Thu, 20 Mar 2014 13:20:10 -0500
Subject: [PATCH] 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.



I know you found it independently but ?

Reported-by: Huang Shijie b32...@freescale.com


Signed-off-by: Felipe Balbi ba...@ti.com
---
  drivers/bluetooth/hci_ldisc.c | 20 +++-
  drivers/bluetooth/hci_uart.h  |  1 +
  2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 6e06f6f..ecdd765 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,18 @@ 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, init_ready);
+   struct tty_struct *tty = hu-tty;
+   struct hci_dev *hdev = hu-hdev;
+   struct sk_buff *skb;
+


+   /* FIXME: if bad skb length or tty-ops-write() returns  0 ??? */


  restart:
clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);

@@ -153,7 +161,6 @@ restart:
goto restart;

clear_bit(HCI_UART_SENDING, hu-tx_state);
-   return 0;
  }

  static void hci_uart_init_work(struct work_struct *work)
@@ -281,6 +288,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);

@@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);

+   cancel_work_sync(hy-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;



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

Re: hci_ldsic nested locking problem

2014-03-20 Thread Felipe Balbi
Hi,

On Thu, Mar 20, 2014 at 03:16:35PM -0400, Peter Hurley wrote:
 On 03/20/2014 02:25 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 02:21:17PM -0400, Peter Hurley wrote:
 On 03/20/2014 02:11 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 01:31:40PM -0400, Peter Hurley wrote:
 [ +cc Huang Shijie ]
 
 On 03/20/2014 01:16 PM, Felipe Balbi wrote:
 On Thu, Mar 20, 2014 at 04:42:16PM +, Alan Cox wrote:
 On Thu, 2014-03-20 at 11:34 -0500, Felipe Balbi wrote:
 Hi,
 
 when 8250 driver calls uart_write_wakeup(), the tty port lock is 
 already
 taken. hci_ldisc.c's implementation of -write_wakeup() calls
 tty-ops-write() to actually send the characters, but that call will
 try to acquire the same port lock again.
 
 Looking at other line disciplines that looks like a bug in hci_ldisc.c.
 Am I correct to assume that -write_wakeup() is supposed to *just*
 wakeup the bottom half so we handle -write() in another context ?
 
 Is it legal to call tty-ops-write() from within -write_wakeup() ?
 
 It isn't because you might send all the bytes and go
 
 write
 write_wakeup
 write
 write wakeup
 ...
 
 and recurse
 
 cool, so there really is a bug in hci_ldisc. Marcel, any tips on how do
 you want this to be sorted out ?
 
 hci_uart_tx_wakeup() should perform the I/O as work.
 FWIW, this was reported by Huang Shijie back on Dec 6.
 
 I'd fix it but I have no way to test it.
 
 here's a build-tested only patch which is waiting for testing from other
 colleagues who've got a platform to reproduce the problem:
 
 Where's the cancel_work_sync() on teardown?
 
 here, as a patch too this time:
 
 Thanks. Minor edits below but, strictly speaking, not necessary.
 
 Reviewed-by: Peter Hurley pe...@hurleysoftware.com
 
 
  From 3ee6b74833f154df64a6164476b854846206a3f2 Mon Sep 17 00:00:00 2001
 From: Felipe Balbi ba...@ti.com
 Date: Thu, 20 Mar 2014 13:20:10 -0500
 Subject: [PATCH] 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.
 
 
 I know you found it independently but ?
 
 Reported-by: Huang Shijie b32...@freescale.com

I will never add any *-by tags without seeing it in the mailing list.
Now I can add it to the patch and send it as a real patch (git
send-email it).

 Signed-off-by: Felipe Balbi ba...@ti.com
 ---
   drivers/bluetooth/hci_ldisc.c | 20 +++-
   drivers/bluetooth/hci_uart.h  |  1 +
   2 files changed, 16 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
 index 6e06f6f..ecdd765 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,18 @@ 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, init_ready);
 +struct tty_struct *tty = hu-tty;
 +struct hci_dev *hdev = hu-hdev;
 +struct sk_buff *skb;
 +
 
 + /* FIXME: if bad skb length or tty-ops-write() returns  0 ??? */
 
   restart:
  clear_bit(HCI_UART_TX_WAKEUP, hu-tx_state);
 
 @@ -153,7 +161,6 @@ restart:
  goto restart;
 
  clear_bit(HCI_UART_SENDING, hu-tx_state);
 -return 0;
   }
 
   static void hci_uart_init_work(struct work_struct *work)
 @@ -281,6 +288,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);
 
 @@ -318,6 +326,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
  if (hdev)
  hci_uart_close(hdev);
 
 +cancel_work_sync(hy-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