Merge "Bluetooth: Fix timeout configuration for AMP channels" into msm-3.0
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 30536a2..312de3f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -294,8 +294,6 @@
struct l2cap_conf_prm {
__u8 fcs;
- __le16 retrans_timeout;
- __le16 monitor_timeout;
__le32 flush_to;
};
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index cf6cf59..ded74dc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3212,6 +3212,44 @@
return chan;
}
+static void l2cap_get_ertm_timeouts(struct l2cap_conf_rfc *rfc,
+ struct l2cap_pinfo *pi)
+{
+ if (pi->amp_id && pi->ampcon) {
+ u64 ertm_to = pi->ampcon->hdev->amp_be_flush_to;
+
+ /* Class 1 devices have must have ERTM timeouts
+ * exceeding the Link Supervision Timeout. The
+ * default Link Supervision Timeout for AMP
+ * controllers is 10 seconds.
+ *
+ * Class 1 devices use 0xffffffff for their
+ * best-effort flush timeout, so the clamping logic
+ * will result in a timeout that meets the above
+ * requirement. ERTM timeouts are 16-bit values, so
+ * the maximum timeout is 65.535 seconds.
+ */
+
+ /* Convert timeout to milliseconds and round */
+ ertm_to = div_u64(ertm_to + 999, 1000);
+
+ /* This is the recommended formula for class 2 devices
+ * that start ERTM timers when packets are sent to the
+ * controller.
+ */
+ ertm_to = 3 * ertm_to + 500;
+
+ if (ertm_to > 0xffff)
+ ertm_to = 0xffff;
+
+ rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
+ rfc->monitor_timeout = rfc->retrans_timeout;
+ } else {
+ rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ }
+}
+
int l2cap_build_conf_req(struct sock *sk, void *data)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -3262,10 +3300,10 @@
rfc.txwin_size = L2CAP_TX_WIN_MAX_ENHANCED;
else
rfc.txwin_size = pi->tx_win;
- rfc.max_transmit = pi->max_tx;
- rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
- rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ rfc.max_transmit = pi->max_tx;
+ rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ l2cap_get_ertm_timeouts(&rfc, pi);
+
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->imtu)
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
@@ -3337,30 +3375,16 @@
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
- u32 be_flush_to;
BT_DBG("sk %p", sk);
- /* convert to milliseconds, round up */
- be_flush_to = (pi->conn->hcon->hdev->amp_be_flush_to + 999) / 1000;
-
switch (pi->mode) {
case L2CAP_MODE_ERTM:
rfc.mode = L2CAP_MODE_ERTM;
rfc.txwin_size = pi->tx_win;
rfc.max_transmit = pi->max_tx;
- if (pi->amp_move_id) {
- rfc.retrans_timeout =
- cpu_to_le16((3 * be_flush_to) + 500);
- rfc.monitor_timeout =
- cpu_to_le16((3 * be_flush_to) + 500);
- } else {
- rfc.retrans_timeout =
- cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout =
- cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
- }
rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ l2cap_get_ertm_timeouts(&rfc, pi);
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->imtu)
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
@@ -3374,17 +3398,16 @@
(unsigned long) &rfc);
if (pi->conn->feat_mask & L2CAP_FEAT_FCS) {
-
/* TODO assign fcs for br/edr based on socket config option */
- if (pi->amp_move_id)
+ /* FCS is not used with AMP because it is redundant - lower
+ * layers already include a checksum. */
+ if (pi->amp_id)
pi->local_conf.fcs = L2CAP_FCS_NONE;
else
pi->local_conf.fcs = L2CAP_FCS_CRC16;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- pi->local_conf.fcs);
-
- pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs);
+ pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
}
req->dcid = cpu_to_le16(pi->dcid);
@@ -3546,15 +3569,9 @@
case L2CAP_MODE_ERTM:
if (!(pi->conf_state & L2CAP_CONF_EXT_WIN_RECV))
pi->remote_tx_win = rfc.txwin_size;
-
pi->remote_max_tx = rfc.max_transmit;
-
pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
-
- rfc.retrans_timeout =
- cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout =
- cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ l2cap_get_ertm_timeouts(&rfc, pi);
pi->conf_state |= L2CAP_CONF_MODE_DONE;
@@ -3660,9 +3677,6 @@
case L2CAP_CONF_RFC:
if (olen == sizeof(rfc))
memcpy(&rfc, (void *) val, olen);
- if (pi->mode != rfc.mode ||
- rfc.mode == L2CAP_MODE_BASIC)
- result = L2CAP_CONF_UNACCEPT;
break;
case L2CAP_CONF_FCS:
@@ -3698,6 +3712,9 @@
BT_DBG("result 0x%2.2x cur mode 0x%2.2x req mode 0x%2.2x",
result, pi->mode, rfc.mode);
+ if (pi->mode != rfc.mode || rfc.mode == L2CAP_MODE_BASIC)
+ result = L2CAP_CONF_UNACCEPT;
+
if (result == L2CAP_CONF_SUCCESS) {
/* Configure output options and let the other side know
* which ones we don't like. */
@@ -3717,38 +3734,26 @@
pi->remote_tx_win);
}
+ pi->remote_mps = rfc.max_pdu_size;
+
if (rfc.mode == L2CAP_MODE_ERTM) {
- pi->remote_conf.retrans_timeout =
- le16_to_cpu(rfc.retrans_timeout);
- pi->remote_conf.monitor_timeout =
- le16_to_cpu(rfc.monitor_timeout);
-
- BT_DBG("remote conf monitor timeout %d",
- pi->remote_conf.monitor_timeout);
-
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ l2cap_get_ertm_timeouts(&rfc, pi);
+ } else {
+ rfc.retrans_timeout = 0;
+ rfc.monitor_timeout = 0;
}
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+ sizeof(rfc), (unsigned long) &rfc);
}
if (result != L2CAP_CONF_SUCCESS)
goto done;
- pi->fcs = pi->remote_conf.fcs | pi->local_conf.fcs ;
+ pi->fcs = pi->remote_conf.fcs | pi->local_conf.fcs;
- if (pi->rx_state == L2CAP_ERTM_RX_STATE_WAIT_F_FLAG) {
+ if (pi->rx_state == L2CAP_ERTM_RX_STATE_WAIT_F_FLAG)
pi->flush_to = pi->remote_conf.flush_to;
- pi->retrans_timeout = pi->remote_conf.retrans_timeout;
-
- if (pi->amp_move_id)
- pi->monitor_timeout = pi->remote_conf.monitor_timeout;
- else
- pi->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- BT_DBG("mode %d monitor timeout %d",
- pi->mode, pi->monitor_timeout);
-
- }
done:
rsp->scid = cpu_to_le16(pi->dcid);
@@ -3972,34 +3977,41 @@
if (type == L2CAP_CONF_RFC) {
if (olen == sizeof(rfc))
memcpy(&rfc, (void *)val, olen);
- if (rfc.mode != pi->mode &&
- rfc.mode != L2CAP_MODE_ERTM) {
- err = -ECONNREFUSED;
- goto done;
+
+ if (rfc.mode != pi->mode) {
+ l2cap_send_disconn_req(pi->conn, sk,
+ ECONNRESET);
+ return -ECONNRESET;
}
- break;
+
+ goto done;
}
}
}
+ BT_ERR("Expected RFC option was missing, using existing values");
+
+ rfc.mode = pi->mode;
+ rfc.retrans_timeout = cpu_to_le16(pi->retrans_timeout);
+ rfc.monitor_timeout = cpu_to_le16(pi->monitor_timeout);
+
done:
l2cap_ertm_stop_ack_timer(pi);
l2cap_ertm_stop_retrans_timer(pi);
l2cap_ertm_stop_monitor_timer(pi);
+ pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ if (pi->mode == L2CAP_MODE_ERTM) {
+ pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+ pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+ }
+
if (l2cap_pi(sk)->reconf_state == L2CAP_RECONF_ACC) {
l2cap_pi(sk)->reconf_state = L2CAP_RECONF_NONE;
/* Respond to poll */
err = l2cap_answer_move_poll(sk);
-
} else if (l2cap_pi(sk)->reconf_state == L2CAP_RECONF_INT) {
-
- /* If moving to BR/EDR, use default timeout defined by
- * the spec */
- if (pi->amp_move_id == 0)
- pi->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
-
if (pi->mode == L2CAP_MODE_ERTM) {
l2cap_ertm_tx(sk, NULL, NULL,
L2CAP_ERTM_EVENT_EXPLICIT_POLL);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 93e7b04..94cacde 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
@@ -1123,8 +1123,6 @@
static void set_default_config(struct l2cap_conf_prm *conf_prm)
{
conf_prm->fcs = L2CAP_FCS_CRC16;
- conf_prm->retrans_timeout = 0;
- conf_prm->monitor_timeout = 0;
conf_prm->flush_to = L2CAP_DEFAULT_FLUSH_TO;
}
@@ -1186,14 +1184,6 @@
pi->extended_control = 0;
pi->local_conf.fcs = pi->fcs;
- if (pi->mode == L2CAP_MODE_BASIC) {
- pi->local_conf.retrans_timeout = 0;
- pi->local_conf.monitor_timeout = 0;
- } else {
- pi->local_conf.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
- pi->local_conf.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- }
-
pi->local_conf.flush_to = pi->flush_to;
set_default_config(&pi->remote_conf);