Kernel miss sync when binding bluetooth HCI interface?
by peng.cheng from LinuxQuestions.org on (#6H5WX)
Hi,
I am using hciattach to bind tty to bluetooth HCI.
There is an error printout:
Code:Bluetooth: hci0: sending frame failed (-49)After some investigation, I found the kernel may miss some sync in bluetooth codes.
1. hciattach command calls ioctl(HCIUARTSETPROTO) to set prototype, it goes down to kernel through syscall, calls hci_uart_tty_ioctl, then hci_uart_set_proto, then hci_uart_register_dev and finally set HCI_UART_PROTO_READY.
2. For hci_uart_register_dev which I mentioned in the 1st step, it calls hci_register_dev, and starts a workqueue hdev->power_on.
3. For hdev->power_on workqueue, it in further callls hci_dev_do_open, then hci_uart_setup, then set_baudrate, then __hci_cmd_sync which starts another workqueue hdev->cmd_work.
4. For hdev->cmd_work workqueue, it calls hci_send_frame, then hci_uart_send_frame, which will test HCI_PROTO_READ bit, if it is not set, then return -EUNATCH, which is -49.
So for all these complicated calls and workqueues, the workqueue which is triggered by hci_uart_register_dev, may be executed before HCI_UART_PROTO_READY which is set in hci_uart_set_proto right after hci_uart_register_dev, that leads to -49 error.
After adding a piece of code before __hci_cmd_sync in send_baudrate, it works alright
Code:do {
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
return 0;
}
udelay(100);
} while (time_before(jiffies, timeout));
I am working on kernel version v5.4, but I checked the latest kernel v6.6.7, seems it is the same.
Has anyone met a similar issue before? Is it the kernel bluetooth that lacks sync in this case?
Any help will be appreciated! Thank you!
BR,
Peng
I am using hciattach to bind tty to bluetooth HCI.
There is an error printout:
Code:Bluetooth: hci0: sending frame failed (-49)After some investigation, I found the kernel may miss some sync in bluetooth codes.
1. hciattach command calls ioctl(HCIUARTSETPROTO) to set prototype, it goes down to kernel through syscall, calls hci_uart_tty_ioctl, then hci_uart_set_proto, then hci_uart_register_dev and finally set HCI_UART_PROTO_READY.
2. For hci_uart_register_dev which I mentioned in the 1st step, it calls hci_register_dev, and starts a workqueue hdev->power_on.
3. For hdev->power_on workqueue, it in further callls hci_dev_do_open, then hci_uart_setup, then set_baudrate, then __hci_cmd_sync which starts another workqueue hdev->cmd_work.
4. For hdev->cmd_work workqueue, it calls hci_send_frame, then hci_uart_send_frame, which will test HCI_PROTO_READ bit, if it is not set, then return -EUNATCH, which is -49.
So for all these complicated calls and workqueues, the workqueue which is triggered by hci_uart_register_dev, may be executed before HCI_UART_PROTO_READY which is set in hci_uart_set_proto right after hci_uart_register_dev, that leads to -49 error.
After adding a piece of code before __hci_cmd_sync in send_baudrate, it works alright
Code:do {
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
return 0;
}
udelay(100);
} while (time_before(jiffies, timeout));
I am working on kernel version v5.4, but I checked the latest kernel v6.6.7, seems it is the same.
Has anyone met a similar issue before? Is it the kernel bluetooth that lacks sync in this case?
Any help will be appreciated! Thank you!
BR,
Peng