From 3f49ff05e88b80654fb6046987a8e373167f593c Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 2 Sep 2015 12:10:12 +0200 Subject: [PATCH] Bluetooth: close HCI device when user channel socket gets closed With 9380f9eacfbbee701daa416edd6625efcd3e29e1 the order of unsetting the HCI_USER_CHANNEL flag of the HCI device was reverted to ensure the device is first closed before making it available again. Due to hci_dev_close checking for HCI_USER_CHANNEL being set on the device it was never really closed and was kept opened. We're now calling hci_dev_do_close directly to make sure the device is correctly closed and we keep the correct order to unset the flag on our device object. Signed-off-by: Simon Fels Signed-off-by: Marcel Holtmann (cherry picked from bluetooth-next 4c63f83c2c2e16a13ce274ee678e28246bd33645) BugLink: http://bugs.launchpad.net/bugs/1489327 Signed-off-by: Tim Gardner --- backports/include/net/bluetooth/hci_core.h | 1 + backports/net/bluetooth/hci_core.c | 2 +- backports/net/bluetooth/hci_sock.c | 11 ++++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/backports/include/net/bluetooth/hci_core.h b/backports/include/net/bluetooth/hci_core.h index 2341628b691..001845d65e3 100644 --- a/backports/include/net/bluetooth/hci_core.h +++ b/backports/include/net/bluetooth/hci_core.h @@ -961,6 +961,7 @@ int hci_resume_dev(struct hci_dev *hdev); int hci_reset_dev(struct hci_dev *hdev); int hci_dev_open(__u16 dev); int hci_dev_close(__u16 dev); +int hci_dev_do_close(struct hci_dev *hdev); int hci_dev_reset(__u16 dev); int hci_dev_reset_stat(__u16 dev); int hci_dev_cmd(unsigned int cmd, void __user *arg); diff --git a/backports/net/bluetooth/hci_core.c b/backports/net/bluetooth/hci_core.c index 2f8fb33067e..ef0b57361da 100644 --- a/backports/net/bluetooth/hci_core.c +++ b/backports/net/bluetooth/hci_core.c @@ -1548,7 +1548,7 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) BT_DBG("All LE pending actions cleared"); } -static int hci_dev_do_close(struct hci_dev *hdev) +int hci_dev_do_close(struct hci_dev *hdev) { BT_DBG("%s %p", hdev->name, hdev); diff --git a/backports/net/bluetooth/hci_sock.c b/backports/net/bluetooth/hci_sock.c index 9a2732f7d99..b2070be2fde 100644 --- a/backports/net/bluetooth/hci_sock.c +++ b/backports/net/bluetooth/hci_sock.c @@ -503,7 +503,16 @@ static int hci_sock_release(struct socket *sock) if (hdev) { if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { - hci_dev_close(hdev->id); + /* When releasing an user channel exclusive access, + * call hci_dev_do_close directly instead of calling + * hci_dev_close to ensure the exclusive access will + * be released and the controller brought back down. + * + * The checking of HCI_AUTO_OFF is not needed in this + * case since it will have been cleared already when + * opening the user channel. + */ + hci_dev_do_close(hdev); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); mgmt_index_added(hdev); }