From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: Re: [RFC V1 07/16] Bluetooth: hci_ldisc: Add protocol check to hci_uart_tx_wakeup() From: Marcel Holtmann In-Reply-To: <1490723429-28870-8-git-send-email-Dean_Jenkins@mentor.com> Date: Thu, 30 Mar 2017 12:11:34 +0200 Cc: "Gustavo F. Padovan" , Johan Hedberg , linux-bluetooth@vger.kernel.org Message-Id: <55813485-14F7-4AB0-8AF4-2D9FE0792019@holtmann.org> References: <1490723429-28870-1-git-send-email-Dean_Jenkins@mentor.com> <1490723429-28870-8-git-send-email-Dean_Jenkins@mentor.com> To: Dean Jenkins Sender: linux-bluetooth-owner@vger.kernel.org List-ID: Hi Dean, > Before attempting to schedule a work-item onto hu->write_work in > hci_uart_tx_wakeup(), check that the Data Link protocol layer is > still bound to the HCI UART driver. > > Failure to perform this protocol check causes a race condition between > the work queue hu->write_work running hci_uart_write_work() and the > Data Link protocol layer being unbound (closed) in hci_uart_tty_close(). > > Note hci_uart_tty_close() does have a "cancel_work_sync(&hu->write_work)" > but it is ineffective because it cannot prevent work-items being added > to hu->write_work after cancel_work_sync() has run. > > Therefore, add a check for HCI_UART_PROTO_READY into hci_uart_tx_wakeup() > which prevents scheduling of the work queue when HCI_UART_PROTO_READY > is in the clear state. However, note a small race condition remains > because the hci_uart_tx_wakeup() thread can run in parallel with the > hci_uart_tty_close() thread so it is possible that a schedule of > hu->write_work can occur when HCI_UART_PROTO_READY is cleared. A complete > solution needs locking of the threads which is implemented in a future > commit. > > Signed-off-by: Dean Jenkins > --- > drivers/bluetooth/hci_ldisc.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c > index c4b801b..a1bb4d64b9 100644 > --- a/drivers/bluetooth/hci_ldisc.c > +++ b/drivers/bluetooth/hci_ldisc.c > @@ -125,15 +125,19 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) > > int hci_uart_tx_wakeup(struct hci_uart *hu) > { > + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) > + goto no_schedule; > + > if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { > set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); > - return 0; > + goto no_schedule; > } > > BT_DBG(""); > > schedule_work(&hu->write_work); > > +no_schedule: > return 0; > } so instead of calling no_schedule label, just keep calling return 0 directly. Regards Marcel