* [PATCH v1] Bluetooth: hci_uart: fix race during initialization
@ 2024-11-27 12:38 Arseniy Krasnov
2024-12-16 11:58 ` Arseniy Krasnov
2024-12-16 14:52 ` Luiz Augusto von Dentz
0 siblings, 2 replies; 5+ messages in thread
From: Arseniy Krasnov @ 2024-11-27 12:38 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-bluetooth, linux-kernel, oxffffaa, ddrokosov
'hci_register_dev()' calls power up function, which is executed by
kworker - 'hci_power_on()'. This function does access to bluetooth chip
using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'.
Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and
if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after
'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will
be executed before setting this bit. In that case HCI init logic fails.
Patch adds one more bit in addition to 'HCI_UART_PROTO_READY' which
allows to perform power up logic without original bit set.
Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
---
drivers/bluetooth/hci_ldisc.c | 19 ++++++++++++++-----
drivers/bluetooth/hci_uart.h | 1 +
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 30192bb083549..2e20f00649bd7 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
if (!skb) {
percpu_down_read(&hu->proto_lock);
- if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
+ test_bit(HCI_UART_PROTO_INIT, &hu->flags))
skb = hu->proto->dequeue(hu);
percpu_up_read(&hu->proto_lock);
@@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
if (!percpu_down_read_trylock(&hu->proto_lock))
return 0;
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags))
goto no_schedule;
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
@@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
percpu_down_read(&hu->proto_lock);
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return -EUNATCH;
}
@@ -582,7 +585,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
if (tty != hu->tty)
return;
- if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
+ test_bit(HCI_UART_PROTO_INIT, &hu->flags))
hci_uart_tx_wakeup(hu);
}
@@ -608,7 +612,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
percpu_down_read(&hu->proto_lock);
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return;
}
@@ -704,12 +709,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
hu->proto = p;
+ set_bit(HCI_UART_PROTO_INIT, &hu->flags);
+
err = hci_uart_register_dev(hu);
if (err) {
return err;
}
set_bit(HCI_UART_PROTO_READY, &hu->flags);
+ clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
+
return 0;
}
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 00bf7ae82c5b7..39f39704be41f 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -89,6 +89,7 @@ struct hci_uart {
#define HCI_UART_REGISTERED 1
#define HCI_UART_PROTO_READY 2
#define HCI_UART_NO_SUSPEND_NOTIFIER 3
+#define HCI_UART_PROTO_INIT 4
/* TX states */
#define HCI_UART_SENDING 1
--
2.30.1
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v1] Bluetooth: hci_uart: fix race during initialization
2024-11-27 12:38 [PATCH v1] Bluetooth: hci_uart: fix race during initialization Arseniy Krasnov
@ 2024-12-16 11:58 ` Arseniy Krasnov
2024-12-16 14:52 ` Luiz Augusto von Dentz
1 sibling, 0 replies; 5+ messages in thread
From: Arseniy Krasnov @ 2024-12-16 11:58 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-bluetooth, linux-kernel, oxffffaa, ddrokosov
Hi, sorry, pls ping
Thanks
On 27.11.2024 15:38, Arseniy Krasnov wrote:
> 'hci_register_dev()' calls power up function, which is executed by
> kworker - 'hci_power_on()'. This function does access to bluetooth chip
> using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'.
> Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and
> if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after
> 'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will
> be executed before setting this bit. In that case HCI init logic fails.
>
> Patch adds one more bit in addition to 'HCI_UART_PROTO_READY' which
> allows to perform power up logic without original bit set.
>
> Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
> ---
> drivers/bluetooth/hci_ldisc.c | 19 ++++++++++++++-----
> drivers/bluetooth/hci_uart.h | 1 +
> 2 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
> index 30192bb083549..2e20f00649bd7 100644
> --- a/drivers/bluetooth/hci_ldisc.c
> +++ b/drivers/bluetooth/hci_ldisc.c
> @@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
> if (!skb) {
> percpu_down_read(&hu->proto_lock);
>
> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> skb = hu->proto->dequeue(hu);
>
> percpu_up_read(&hu->proto_lock);
> @@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
> if (!percpu_down_read_trylock(&hu->proto_lock))
> return 0;
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> goto no_schedule;
>
> set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
> @@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
>
> percpu_down_read(&hu->proto_lock);
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
> percpu_up_read(&hu->proto_lock);
> return -EUNATCH;
> }
> @@ -582,7 +585,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
> if (tty != hu->tty)
> return;
>
> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> hci_uart_tx_wakeup(hu);
> }
>
> @@ -608,7 +612,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
>
> percpu_down_read(&hu->proto_lock);
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
> percpu_up_read(&hu->proto_lock);
> return;
> }
> @@ -704,12 +709,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
>
> hu->proto = p;
>
> + set_bit(HCI_UART_PROTO_INIT, &hu->flags);
> +
> err = hci_uart_register_dev(hu);
> if (err) {
> return err;
> }
>
> set_bit(HCI_UART_PROTO_READY, &hu->flags);
> + clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
> +
> return 0;
> }
>
> diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
> index 00bf7ae82c5b7..39f39704be41f 100644
> --- a/drivers/bluetooth/hci_uart.h
> +++ b/drivers/bluetooth/hci_uart.h
> @@ -89,6 +89,7 @@ struct hci_uart {
> #define HCI_UART_REGISTERED 1
> #define HCI_UART_PROTO_READY 2
> #define HCI_UART_NO_SUSPEND_NOTIFIER 3
> +#define HCI_UART_PROTO_INIT 4
>
> /* TX states */
> #define HCI_UART_SENDING 1
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v1] Bluetooth: hci_uart: fix race during initialization
2024-11-27 12:38 [PATCH v1] Bluetooth: hci_uart: fix race during initialization Arseniy Krasnov
2024-12-16 11:58 ` Arseniy Krasnov
@ 2024-12-16 14:52 ` Luiz Augusto von Dentz
2024-12-16 15:06 ` Arseniy Krasnov
1 sibling, 1 reply; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2024-12-16 14:52 UTC (permalink / raw)
To: Arseniy Krasnov
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, oxffffaa, ddrokosov
Hi Arseniy,
On Wed, Nov 27, 2024 at 7:38 AM Arseniy Krasnov
<avkrasnov@salutedevices.com> wrote:
>
> 'hci_register_dev()' calls power up function, which is executed by
> kworker - 'hci_power_on()'. This function does access to bluetooth chip
> using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'.
> Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and
> if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after
> 'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will
> be executed before setting this bit. In that case HCI init logic fails.
>
> Patch adds one more bit in addition to 'HCI_UART_PROTO_READY' which
> allows to perform power up logic without original bit set.
>
> Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
> ---
> drivers/bluetooth/hci_ldisc.c | 19 ++++++++++++++-----
> drivers/bluetooth/hci_uart.h | 1 +
> 2 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
> index 30192bb083549..2e20f00649bd7 100644
> --- a/drivers/bluetooth/hci_ldisc.c
> +++ b/drivers/bluetooth/hci_ldisc.c
> @@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
> if (!skb) {
> percpu_down_read(&hu->proto_lock);
>
> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> skb = hu->proto->dequeue(hu);
>
> percpu_up_read(&hu->proto_lock);
> @@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
> if (!percpu_down_read_trylock(&hu->proto_lock))
> return 0;
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> goto no_schedule;
>
> set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
> @@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
>
> percpu_down_read(&hu->proto_lock);
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
> percpu_up_read(&hu->proto_lock);
> return -EUNATCH;
> }
> @@ -582,7 +585,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
> if (tty != hu->tty)
> return;
>
> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
> hci_uart_tx_wakeup(hu);
> }
>
> @@ -608,7 +612,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
>
> percpu_down_read(&hu->proto_lock);
>
> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
> percpu_up_read(&hu->proto_lock);
> return;
> }
> @@ -704,12 +709,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
>
> hu->proto = p;
>
> + set_bit(HCI_UART_PROTO_INIT, &hu->flags);
> +
> err = hci_uart_register_dev(hu);
> if (err) {
> return err;
> }
>
> set_bit(HCI_UART_PROTO_READY, &hu->flags);
> + clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
This should be quite obvious, why don't you just move the
HCI_UART_PROTO_READY above hci_uart_register_dev?
> return 0;
> }
>
> diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
> index 00bf7ae82c5b7..39f39704be41f 100644
> --- a/drivers/bluetooth/hci_uart.h
> +++ b/drivers/bluetooth/hci_uart.h
> @@ -89,6 +89,7 @@ struct hci_uart {
> #define HCI_UART_REGISTERED 1
> #define HCI_UART_PROTO_READY 2
> #define HCI_UART_NO_SUSPEND_NOTIFIER 3
> +#define HCI_UART_PROTO_INIT 4
>
> /* TX states */
> #define HCI_UART_SENDING 1
> --
> 2.30.1
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v1] Bluetooth: hci_uart: fix race during initialization
2024-12-16 14:52 ` Luiz Augusto von Dentz
@ 2024-12-16 15:06 ` Arseniy Krasnov
0 siblings, 0 replies; 5+ messages in thread
From: Arseniy Krasnov @ 2024-12-16 15:06 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, oxffffaa, ddrokosov
On 16.12.2024 17:52, Luiz Augusto von Dentz wrote:
> Hi Arseniy,
>
> On Wed, Nov 27, 2024 at 7:38 AM Arseniy Krasnov
> <avkrasnov@salutedevices.com> wrote:
>>
>> 'hci_register_dev()' calls power up function, which is executed by
>> kworker - 'hci_power_on()'. This function does access to bluetooth chip
>> using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'.
>> Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and
>> if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after
>> 'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will
>> be executed before setting this bit. In that case HCI init logic fails.
>>
>> Patch adds one more bit in addition to 'HCI_UART_PROTO_READY' which
>> allows to perform power up logic without original bit set.
>>
>> Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
>> ---
>> drivers/bluetooth/hci_ldisc.c | 19 ++++++++++++++-----
>> drivers/bluetooth/hci_uart.h | 1 +
>> 2 files changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
>> index 30192bb083549..2e20f00649bd7 100644
>> --- a/drivers/bluetooth/hci_ldisc.c
>> +++ b/drivers/bluetooth/hci_ldisc.c
>> @@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
>> if (!skb) {
>> percpu_down_read(&hu->proto_lock);
>>
>> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
>> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
>> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
>> skb = hu->proto->dequeue(hu);
>>
>> percpu_up_read(&hu->proto_lock);
>> @@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
>> if (!percpu_down_read_trylock(&hu->proto_lock))
>> return 0;
>>
>> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
>> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
>> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags))
>> goto no_schedule;
>>
>> set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
>> @@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
>>
>> percpu_down_read(&hu->proto_lock);
>>
>> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
>> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
>> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
>> percpu_up_read(&hu->proto_lock);
>> return -EUNATCH;
>> }
>> @@ -582,7 +585,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
>> if (tty != hu->tty)
>> return;
>>
>> - if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
>> + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
>> + test_bit(HCI_UART_PROTO_INIT, &hu->flags))
>> hci_uart_tx_wakeup(hu);
>> }
>>
>> @@ -608,7 +612,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
>>
>> percpu_down_read(&hu->proto_lock);
>>
>> - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
>> + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
>> + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
>> percpu_up_read(&hu->proto_lock);
>> return;
>> }
>> @@ -704,12 +709,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
>>
>> hu->proto = p;
>>
>> + set_bit(HCI_UART_PROTO_INIT, &hu->flags);
>> +
>> err = hci_uart_register_dev(hu);
>> if (err) {
>> return err;
>> }
>>
>> set_bit(HCI_UART_PROTO_READY, &hu->flags);
>> + clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
>
> This should be quite obvious, why don't you just move the
> HCI_UART_PROTO_READY above hci_uart_register_dev?
>
Hi, this is simplest way, but I had doubts that this may be so obvious because
I don't have enough experience in bt logic.
I'll send v2 with it.
Thanks
>> return 0;
>> }
>>
>> diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
>> index 00bf7ae82c5b7..39f39704be41f 100644
>> --- a/drivers/bluetooth/hci_uart.h
>> +++ b/drivers/bluetooth/hci_uart.h
>> @@ -89,6 +89,7 @@ struct hci_uart {
>> #define HCI_UART_REGISTERED 1
>> #define HCI_UART_PROTO_READY 2
>> #define HCI_UART_NO_SUSPEND_NOTIFIER 3
>> +#define HCI_UART_PROTO_INIT 4
>>
>> /* TX states */
>> #define HCI_UART_SENDING 1
>> --
>> 2.30.1
>
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v1] Bluetooth: hci_uart: fix race during initialization
@ 2025-02-12 9:52 Arseniy Krasnov
0 siblings, 0 replies; 5+ messages in thread
From: Arseniy Krasnov @ 2025-02-12 9:52 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: oxffffaa, linux-kernel, linux-bluetooth, kernel
Do not set 'HCI_UART_PROTO_READY' before call 'hci_uart_register_dev()'.
Possible race is when someone calls 'hci_tty_uart_close()' after this bit
is set, but 'hci_uart_register_dev()' wasn't done. This leads to access
to uninitialized fields. To fix it let's set this bit after device was
registered (as before patch c411c62cc133) and to fix previous problem let's
add one more bit in addition to 'HCI_UART_PROTO_READY' which allows to
perform power up without original bit set (pls see commit c411c62cc133).
Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
Reported-by: syzbot+683f8cb11b94b1824c77@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/linux-bluetooth/d159c57f-8490-4c26-79da-6ad3612c4a14@salutedevices.com/
Fixes: c411c62cc133 ("Bluetooth: hci_uart: fix race during initialization")
---
drivers/bluetooth/hci_ldisc.c | 20 ++++++++++++++------
drivers/bluetooth/hci_uart.h | 1 +
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 2651e2e33f2a1..2f322f890b81f 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
if (!skb) {
percpu_down_read(&hu->proto_lock);
- if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
+ test_bit(HCI_UART_PROTO_INIT, &hu->flags))
skb = hu->proto->dequeue(hu);
percpu_up_read(&hu->proto_lock);
@@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
if (!percpu_down_read_trylock(&hu->proto_lock))
return 0;
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags))
goto no_schedule;
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
@@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
percpu_down_read(&hu->proto_lock);
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return -EUNATCH;
}
@@ -585,7 +588,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
if (tty != hu->tty)
return;
- if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags) ||
+ test_bit(HCI_UART_PROTO_INIT, &hu->flags))
hci_uart_tx_wakeup(hu);
}
@@ -611,7 +615,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
percpu_down_read(&hu->proto_lock);
- if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) &&
+ !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) {
percpu_up_read(&hu->proto_lock);
return;
}
@@ -707,13 +712,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
hu->proto = p;
- set_bit(HCI_UART_PROTO_READY, &hu->flags);
+ set_bit(HCI_UART_PROTO_INIT, &hu->flags);
err = hci_uart_register_dev(hu);
if (err) {
return err;
}
+ set_bit(HCI_UART_PROTO_READY, &hu->flags);
+ clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
+
return 0;
}
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index fbf3079b92a53..5ea5dd80e297c 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -90,6 +90,7 @@ struct hci_uart {
#define HCI_UART_REGISTERED 1
#define HCI_UART_PROTO_READY 2
#define HCI_UART_NO_SUSPEND_NOTIFIER 3
+#define HCI_UART_PROTO_INIT 4
/* TX states */
#define HCI_UART_SENDING 1
--
2.30.1
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-02-12 9:52 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-11-27 12:38 [PATCH v1] Bluetooth: hci_uart: fix race during initialization Arseniy Krasnov
2024-12-16 11:58 ` Arseniy Krasnov
2024-12-16 14:52 ` Luiz Augusto von Dentz
2024-12-16 15:06 ` Arseniy Krasnov
2025-02-12 9:52 Arseniy Krasnov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®