From: Samuel Holland samuel@sholland.org
[ Upstream commit 3b799254cf6f481460719023d7a18f46651e5e7f ]
If hci_uart_tty_close() or hci_uart_unregister_device() is called while hu->init_ready is scheduled, hci_register_dev() could be called after the hci_uart is torn down. Avoid this by ensuring the work is complete or canceled before checking the HCI_UART_REGISTERED flag.
Fixes: 9f2aee848fe6 ("Bluetooth: Add delayed init sequence support for UART controllers") Signed-off-by: Samuel Holland samuel@sholland.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_ldisc.c | 1 + drivers/bluetooth/hci_serdev.c | 2 ++ 2 files changed, 3 insertions(+)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index efeb8137ec67..48560e646e53 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -545,6 +545,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) clear_bit(HCI_UART_PROTO_READY, &hu->flags); percpu_up_write(&hu->proto_lock);
+ cancel_work_sync(&hu->init_ready); cancel_work_sync(&hu->write_work);
if (hdev) { diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index d3fb0d657fa5..7b3aade431e5 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -369,6 +369,8 @@ void hci_uart_unregister_device(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev;
clear_bit(HCI_UART_PROTO_READY, &hu->flags); + + cancel_work_sync(&hu->init_ready); if (test_bit(HCI_UART_REGISTERED, &hu->flags)) hci_unregister_dev(hdev); hci_free_dev(hdev);