summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSudha Bheemanna <b.sudha@samsung.com>2016-10-04 14:46:13 +0530
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:53:28 +0900
commitc5262bfa09c8285e17c73b8cc532efc49a76ef1f (patch)
tree9bf1818f5600143a6e75abd8786f710a4c4a3f34
parentd4e62d53870f259cce1868920432576ee749ab51 (diff)
downloadlinux-exynos-c5262bfa09c8285e17c73b8cc532efc49a76ef1f.tar.gz
linux-exynos-c5262bfa09c8285e17c73b8cc532efc49a76ef1f.tar.bz2
linux-exynos-c5262bfa09c8285e17c73b8cc532efc49a76ef1f.zip
Bluetooth: Increase supervision timeout to fix issues
Too small supervision timeout causes sudden link loss when remote device has multiple links and it cannot manage those properly. To protect such a case, it needs to widen supervision timeout. Change-Id: I6e0cef7d5d5b6f1c3635ee1c1b59c550438dfd9f Signed-off-by: Sudha Bheemanna <b.sudha@samsung.com>
-rw-r--r--net/bluetooth/l2cap_core.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e39da6127b25..254bdc1214ca 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1487,6 +1487,24 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
mutex_unlock(&conn->chan_lock);
}
+#ifdef TIZEN_BT
+int l2cap_update_connection_param(struct l2cap_conn *conn, u16 min, u16 max,
+ u16 latency, u16 to_multiplier)
+{
+ struct l2cap_conn_param_update_req req;
+
+ req.min = cpu_to_le16(min);
+ req.max = cpu_to_le16(max);
+ req.latency = cpu_to_le16(latency);
+ req.to_multiplier = cpu_to_le16(to_multiplier);
+
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONN_PARAM_UPDATE_REQ,
+ sizeof(req), &req);
+
+ return 0;
+}
+#endif
+
static void l2cap_le_conn_ready(struct l2cap_conn *conn)
{
struct hci_conn *hcon = conn->hcon;
@@ -1500,6 +1518,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
if (hcon->out)
smp_conn_security(hcon, hcon->pending_sec_level);
+#ifndef TIZEN_BT
/* For LE slave connections, make sure the connection interval
* is in the range of the minium and maximum interval that has
* been configured for this connection. If not, then trigger
@@ -1518,6 +1537,32 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
}
+#else
+ /* Too small supervision timeout causes sudden link loss, when remote
+ * device has multiple links and it cannot manage those properly.
+ * To protect such a case, it needs to widen supervision timeout.
+ */
+ if (hcon->role == HCI_ROLE_SLAVE &&
+ hcon->le_supv_timeout < hdev->le_supv_timeout) {
+ if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC &&
+ hcon->features[0][0] & HCI_LE_CONN_PARAM_REQ_PROC) {
+ BT_DBG("use hci_le_conn_update");
+ hci_le_conn_update(hcon,
+ hcon->le_conn_min_interval,
+ hcon->le_conn_max_interval,
+ hcon->le_conn_latency,
+ hdev->le_supv_timeout);
+ } else {
+ BT_DBG("use l2cap conn_update");
+ l2cap_update_connection_param(conn,
+ hcon->le_conn_min_interval,
+ hcon->le_conn_max_interval,
+ hcon->le_conn_latency,
+ hdev->le_supv_timeout);
+ }
+ }
+
+#endif
}
static void l2cap_conn_ready(struct l2cap_conn *conn)