summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-10-31 15:46:34 +0200
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-11-01 20:27:09 -0200
commit419e08c1121ab346bf5f66fe0a21950529355cee (patch)
treeb6cae064f3d8dc9f5be29ced705caae341b956a9
parente58917b990ef0cc3903aa962236a0dae4f1f81a0 (diff)
downloadlinux-419e08c1121ab346bf5f66fe0a21950529355cee.tar.bz2
Bluetooth: Disconnect logical link when deleting chan
Disconnect logical link for high speed channel hs_hchan associated with L2CAP channel chan. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--include/net/bluetooth/amp.h1
-rw-r--r--net/bluetooth/amp.c14
-rw-r--r--net/bluetooth/l2cap_core.c7
3 files changed, 22 insertions, 0 deletions
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 405fb9c987ef..f1c0017f69e7 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -47,6 +47,7 @@ void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
void amp_create_logical_link(struct l2cap_chan *chan);
+void amp_disconnect_logical_link(struct hci_chan *hchan);
void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
#endif /* __AMP_H */
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 0f3fef34eabc..917e034b9aa5 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -422,6 +422,20 @@ done:
hci_dev_put(hdev);
}
+void amp_disconnect_logical_link(struct hci_chan *hchan)
+{
+ struct hci_conn *hcon = hchan->conn;
+ struct hci_cp_disconn_logical_link cp;
+
+ if (hcon->state != BT_CONNECTED) {
+ BT_DBG("hchan %p not connected", hchan);
+ return;
+ }
+
+ cp.log_handle = cpu_to_le16(hchan->handle);
+ hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK, sizeof(cp), &cp);
+}
+
void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason)
{
BT_DBG("hchan %p", hchan);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ecc5020c9242..bb2cd9eaa8a1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -578,6 +578,13 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
mgr->bredr_chan = NULL;
}
+ if (chan->hs_hchan) {
+ struct hci_chan *hs_hchan = chan->hs_hchan;
+
+ BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
+ amp_disconnect_logical_link(hs_hchan);
+ }
+
chan->ops->teardown(chan, err);
if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))