diff options
author | Mattijs Korpershoek <mkorpershoek@baylibre.com> | 2019-10-17 06:20:39 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-12-31 14:37:12 +0300 |
commit | 367028e7e7c6f17d8e039a43cd9d73b032430401 (patch) | |
tree | 35d8d08259ee4cc58e0a37b3bd4fa80d0de57e77 /net/bluetooth | |
parent | 3eb99789ca2cffecb2a4c4228341ef871bca6e08 (diff) | |
download | linux-367028e7e7c6f17d8e039a43cd9d73b032430401.tar.xz |
Bluetooth: hci_core: fix init for HCI_USER_CHANNEL
[ Upstream commit eb8c101e28496888a0dcfe16ab86a1bee369e820 ]
During the setup() stage, HCI device drivers expect the chip to
acknowledge its setup() completion via vendor specific frames.
If userspace opens() such HCI device in HCI_USER_CHANNEL [1] mode,
the vendor specific frames are never tranmitted to the driver, as
they are filtered in hci_rx_work().
Allow HCI devices which operate in HCI_USER_CHANNEL mode to receive
frames if the HCI device is is HCI_INIT state.
[1] https://www.spinics.net/lists/linux-bluetooth/msg37345.html
Fixes: 23500189d7e0 ("Bluetooth: Introduce new HCI socket channel for user operation")
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_core.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d6d7364838f4..ff80a9d41ce1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4215,7 +4215,14 @@ static void hci_rx_work(struct work_struct *work) hci_send_to_sock(hdev, skb); } - if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { + /* If the device has been opened in HCI_USER_CHANNEL, + * the userspace has exclusive access to device. + * When device is HCI_INIT, we still need to process + * the data packets to the driver in order + * to complete its setup(). + */ + if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + !test_bit(HCI_INIT, &hdev->flags)) { kfree_skb(skb); continue; } |