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);