linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mat Martineau <mathewm@codeaurora.org>
To: linux-bluetooth@vger.kernel.org, gustavo@padovan.org
Cc: sunnyk@codeaurora.org, marcel@holtmann.org,
	andrei.emeltchenko.news@gmail.com
Subject: [PATCHv3 09/18] Bluetooth: Move channel response
Date: Thu, 18 Oct 2012 10:58:41 -0700	[thread overview]
Message-ID: <1350583130-3241-10-git-send-email-mathewm@codeaurora.org> (raw)
In-Reply-To: <1350583130-3241-1-git-send-email-mathewm@codeaurora.org>

The move response command includes a result code indicationg
"pending", "success", or "failure" status.  A pending result is
received when the remote address is still setting up a physical link,
and will be followed by success or failure.  On success, logical link
setup will proceed.  On failure, the move is stopped.  The receiver of
a move channel response must always follow up by sending a move
channel confirm command.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 include/net/bluetooth/l2cap.h |   2 +
 net/bluetooth/l2cap_core.c    | 164 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 161 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 6d3615e..b4c3c65 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -52,6 +52,8 @@
 #define L2CAP_ENC_TIMEOUT		msecs_to_jiffies(5000)
 #define L2CAP_CONN_TIMEOUT		msecs_to_jiffies(40000)
 #define L2CAP_INFO_TIMEOUT		msecs_to_jiffies(4000)
+#define L2CAP_MOVE_TIMEOUT		msecs_to_jiffies(4000)
+#define L2CAP_MOVE_ERTX_TIMEOUT		msecs_to_jiffies(60000)
 
 #define L2CAP_A2MP_DEFAULT_MTU		670
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2fa1bb5..7e50aa4 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -128,6 +128,20 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
 	return NULL;
 }
 
+static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+						  u8 ident)
+{
+	struct l2cap_chan *c;
+
+	mutex_lock(&conn->chan_lock);
+	c = __l2cap_get_chan_by_ident(conn, ident);
+	if (c)
+		l2cap_chan_lock(c);
+	mutex_unlock(&conn->chan_lock);
+
+	return c;
+}
+
 static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 {
 	struct l2cap_chan *c;
@@ -4227,6 +4241,13 @@ static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
 }
 
+static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+			      u8 status)
+{
+	/* Placeholder */
+	return;
+}
+
 static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
 					 struct l2cap_cmd_hdr *cmd,
 					 u16 cmd_len, void *data)
@@ -4316,9 +4337,140 @@ send_move_response:
 	return 0;
 }
 
-static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
-					 struct l2cap_cmd_hdr *cmd,
-					 u16 cmd_len, void *data)
+static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
+{
+	struct l2cap_chan *chan;
+	struct hci_chan *hchan = NULL;
+
+	chan = l2cap_get_chan_by_scid(conn, icid);
+	if (!chan) {
+		l2cap_send_move_chan_cfm(conn, NULL, icid,
+					 L2CAP_MC_UNCONFIRMED);
+		return;
+	}
+
+	__clear_chan_timer(chan);
+	if (result == L2CAP_MR_PEND)
+		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
+
+	switch (chan->move_state) {
+	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+		/* Move confirm will be sent when logical link
+		 * is complete.
+		 */
+		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+		break;
+	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
+		if (result == L2CAP_MR_PEND) {
+			break;
+		} else if (test_bit(CONN_LOCAL_BUSY,
+				    &chan->conn_state)) {
+			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+		} else {
+			/* Logical link is up or moving to BR/EDR,
+			 * proceed with move */
+			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+			l2cap_send_move_chan_cfm(conn, chan, chan->scid,
+						 L2CAP_MC_CONFIRMED);
+			__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+		}
+		break;
+	case L2CAP_MOVE_WAIT_RSP:
+		/* Moving to AMP */
+		if (result == L2CAP_MR_SUCCESS) {
+			/* Remote is ready, send confirm immediately
+			 * after logical link is ready
+			 */
+			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+		} else {
+			/* Both logical link and move success
+			 * are required to confirm
+			 */
+			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
+		}
+
+		/* Placeholder - get hci_chan for logical link */
+		if (!hchan) {
+			/* Logical link not available */
+			l2cap_send_move_chan_cfm(conn, chan, chan->scid,
+						 L2CAP_MC_UNCONFIRMED);
+			break;
+		}
+
+		/* If the logical link is not yet connected, do not
+		 * send confirmation.
+		 */
+		if (hchan->state != BT_CONNECTED)
+			break;
+
+		/* Logical link is already ready to go */
+
+		chan->hs_hcon = hchan->conn;
+		chan->hs_hcon->l2cap_data = chan->conn;
+
+		if (result == L2CAP_MR_SUCCESS) {
+			/* Can confirm now */
+			l2cap_send_move_chan_cfm(conn, chan, chan->scid,
+						 L2CAP_MC_CONFIRMED);
+		} else {
+			/* Now only need move success
+			 * to confirm
+			 */
+			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+		}
+
+		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+		break;
+	default:
+		/* Any other amp move state means the move failed. */
+		chan->move_id = chan->local_amp_id;
+		chan->move_state = L2CAP_MOVE_STABLE;
+		l2cap_move_revert(chan);
+		chan->move_role = L2CAP_MOVE_ROLE_NONE;
+		l2cap_send_move_chan_cfm(conn, chan, chan->scid,
+					 L2CAP_MC_UNCONFIRMED);
+		__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+	}
+
+	l2cap_chan_unlock(chan);
+}
+
+static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
+			    u16 result)
+{
+	struct l2cap_chan *chan;
+
+	chan = l2cap_get_chan_by_ident(conn, ident);
+	if (!chan) {
+		/* Could not locate channel, icid is best guess */
+		l2cap_send_move_chan_cfm(conn, NULL, icid,
+					 L2CAP_MC_UNCONFIRMED);
+		return;
+	}
+
+	__clear_chan_timer(chan);
+
+	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+		if (result == L2CAP_MR_COLLISION) {
+			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+		} else {
+			/* Cleanup - cancel move */
+			chan->move_id = chan->local_amp_id;
+			chan->move_state = L2CAP_MOVE_STABLE;
+			l2cap_move_revert(chan);
+			chan->move_role = L2CAP_MOVE_ROLE_NONE;
+		}
+	}
+
+	l2cap_send_move_chan_cfm(conn, chan, chan->scid, L2CAP_MC_UNCONFIRMED);
+	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+
+	l2cap_chan_unlock(chan);
+}
+
+static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
+				  struct l2cap_cmd_hdr *cmd,
+				  u16 cmd_len, void *data)
 {
 	struct l2cap_move_chan_rsp *rsp = data;
 	u16 icid, result;
@@ -4331,8 +4483,10 @@ static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
 
 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
 
-	/* Placeholder: Always unconfirmed */
-	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
+	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
+		l2cap_move_continue(conn, icid, result);
+	else
+		l2cap_move_fail(conn, cmd->ident, icid, result);
 
 	return 0;
 }
-- 
1.7.12.3

--
Mat Martineau

Employee of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

  parent reply	other threads:[~2012-10-18 17:58 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-18 17:58 [PATCHv3 00/18] L2CAP signaling for AMP channel create/move Mat Martineau
2012-10-18 17:58 ` [PATCHv3 01/18] Bluetooth: Add new l2cap_chan struct members for high speed channels Mat Martineau
2012-10-18 17:58 ` [PATCHv3 02/18] Bluetooth: Add L2CAP create channel request handling Mat Martineau
2012-10-18 17:58 ` [PATCHv3 03/18] Bluetooth: Remove unnecessary intermediate function Mat Martineau
2012-10-19  7:56   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 04/18] Bluetooth: Lookup channel structure based on DCID Mat Martineau
2012-10-19  7:57   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 05/18] Bluetooth: Channel move request handling Mat Martineau
2012-10-19  8:00   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 06/18] Bluetooth: Add new ERTM receive states for channel move Mat Martineau
2012-10-19  8:06   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 07/18] Bluetooth: Add move channel confirm handling Mat Martineau
2012-10-18 21:03   ` Marcel Holtmann
2012-10-19  8:07   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 08/18] Bluetooth: Add state to hci_chan Mat Martineau
2012-10-19  8:08   ` Andrei Emeltchenko
2012-10-18 17:58 ` Mat Martineau [this message]
2012-10-18 21:05   ` [PATCHv3 09/18] Bluetooth: Move channel response Marcel Holtmann
2012-10-18 17:58 ` [PATCHv3 10/18] Bluetooth: Add logical link confirm Mat Martineau
2012-10-18 21:08   ` Marcel Holtmann
2012-10-19 21:21     ` Mat Martineau
2012-10-19  7:53   ` Andrei Emeltchenko
2012-10-19 16:44     ` Mat Martineau
2012-10-18 17:58 ` [PATCHv3 11/18] Bluetooth: Add move confirm response handling Mat Martineau
2012-10-19  8:25   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 12/18] Bluetooth: Handle physical link completion Mat Martineau
2012-10-19  8:32   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 13/18] Bluetooth: Flag ACL frames as complete for AMP controllers Mat Martineau
2012-10-19  8:44   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 14/18] Bluetooth: Do not send data during channel move Mat Martineau
2012-10-19  8:45   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 15/18] Bluetooth: Configure appropriate timeouts for AMP controllers Mat Martineau
2012-10-18 17:58 ` [PATCHv3 16/18] Bluetooth: Ignore BR/EDR packet size constraints when fragmenting for AMP Mat Martineau
2012-10-18 17:58 ` [PATCHv3 17/18] Bluetooth: Do not retransmit data during a channel move Mat Martineau
2012-10-19  8:48   ` Andrei Emeltchenko
2012-10-18 17:58 ` [PATCHv3 18/18] Bluetooth: Start channel move when socket option is changed Mat Martineau
2012-10-19  9:37   ` Andrei Emeltchenko
2012-10-19 16:16     ` Mat Martineau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1350583130-3241-10-git-send-email-mathewm@codeaurora.org \
    --to=mathewm@codeaurora.org \
    --cc=andrei.emeltchenko.news@gmail.com \
    --cc=gustavo@padovan.org \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=marcel@holtmann.org \
    --cc=sunnyk@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).