xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 0cd75f7e)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
7422e925bSMat Martineau    Copyright (c) 2012 Code Aurora Forum.  All rights reserved.
80a708f8fSGustavo F. Padovan 
90a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
100a708f8fSGustavo F. Padovan 
110a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
120a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
130a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
140a708f8fSGustavo F. Padovan 
150a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
160a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
180a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
190a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
200a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
210a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
220a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
230a708f8fSGustavo F. Padovan 
240a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
250a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
260a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
270a708f8fSGustavo F. Padovan */
280a708f8fSGustavo F. Padovan 
29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
300a708f8fSGustavo F. Padovan 
310a708f8fSGustavo F. Padovan #include <linux/module.h>
320a708f8fSGustavo F. Padovan 
330a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
340a708f8fSGustavo F. Padovan #include <linux/crc16.h>
350a708f8fSGustavo F. Padovan 
360a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
370a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
380a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
397ef9fbf0SMarcel Holtmann 
40ac4b7236SMarcel Holtmann #include "smp.h"
417024728eSMarcel Holtmann #include "a2mp.h"
427ef9fbf0SMarcel Holtmann #include "amp.h"
430a708f8fSGustavo F. Padovan 
44d1de6d46SMat Martineau bool disable_ertm;
450a708f8fSGustavo F. Padovan 
46547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
47d40bffbcSMarcel Holtmann static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
480a708f8fSGustavo F. Padovan 
49b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
50b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
510a708f8fSGustavo F. Padovan 
520a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
530a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
544519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
554519de9aSGustavo F. Padovan 			   void *data);
56710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
575e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
580a708f8fSGustavo F. Padovan 
59d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
60608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
61608bcc6dSMat Martineau 
624f1654e0SMarcel Holtmann static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
634f1654e0SMarcel Holtmann {
644f1654e0SMarcel Holtmann 	if (hcon->type == LE_LINK) {
654f1654e0SMarcel Holtmann 		if (type == ADDR_LE_DEV_PUBLIC)
664f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
674f1654e0SMarcel Holtmann 		else
684f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
694f1654e0SMarcel Holtmann 	}
704f1654e0SMarcel Holtmann 
714f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
724f1654e0SMarcel Holtmann }
734f1654e0SMarcel Holtmann 
740a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7571ba0e56SGustavo F. Padovan 
762d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
772d792818SGustavo Padovan 						   u16 cid)
780a708f8fSGustavo F. Padovan {
793df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
80baa7e1faSGustavo F. Padovan 
813df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
823df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
833df91ea2SAndrei Emeltchenko 			return c;
840a708f8fSGustavo F. Padovan 	}
853df91ea2SAndrei Emeltchenko 	return NULL;
86baa7e1faSGustavo F. Padovan }
870a708f8fSGustavo F. Padovan 
882d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
892d792818SGustavo Padovan 						   u16 cid)
900a708f8fSGustavo F. Padovan {
913df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
92baa7e1faSGustavo F. Padovan 
933df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
943df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
953df91ea2SAndrei Emeltchenko 			return c;
960a708f8fSGustavo F. Padovan 	}
973df91ea2SAndrei Emeltchenko 	return NULL;
98baa7e1faSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
1000a708f8fSGustavo F. Padovan /* Find channel with given SCID.
101ef191adeSMat Martineau  * Returns locked channel. */
1022d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1032d792818SGustavo Padovan 						 u16 cid)
1040a708f8fSGustavo F. Padovan {
10548454079SGustavo F. Padovan 	struct l2cap_chan *c;
106baa7e1faSGustavo F. Padovan 
1073df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
108baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
109ef191adeSMat Martineau 	if (c)
110ef191adeSMat Martineau 		l2cap_chan_lock(c);
1113df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1123df91ea2SAndrei Emeltchenko 
11348454079SGustavo F. Padovan 	return c;
1140a708f8fSGustavo F. Padovan }
1150a708f8fSGustavo F. Padovan 
116b1a130b7SMat Martineau /* Find channel with given DCID.
117b1a130b7SMat Martineau  * Returns locked channel.
118b1a130b7SMat Martineau  */
119b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
120b1a130b7SMat Martineau 						 u16 cid)
121b1a130b7SMat Martineau {
122b1a130b7SMat Martineau 	struct l2cap_chan *c;
123b1a130b7SMat Martineau 
124b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
125b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
126b1a130b7SMat Martineau 	if (c)
127b1a130b7SMat Martineau 		l2cap_chan_lock(c);
128b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
129b1a130b7SMat Martineau 
130b1a130b7SMat Martineau 	return c;
131b1a130b7SMat Martineau }
132b1a130b7SMat Martineau 
1332d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1342d792818SGustavo Padovan 						    u8 ident)
1350a708f8fSGustavo F. Padovan {
1363df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
137baa7e1faSGustavo F. Padovan 
1383df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1393df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1403df91ea2SAndrei Emeltchenko 			return c;
1410a708f8fSGustavo F. Padovan 	}
1423df91ea2SAndrei Emeltchenko 	return NULL;
143baa7e1faSGustavo F. Padovan }
1440a708f8fSGustavo F. Padovan 
1455b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1465b155ef9SMat Martineau 						  u8 ident)
1475b155ef9SMat Martineau {
1485b155ef9SMat Martineau 	struct l2cap_chan *c;
1495b155ef9SMat Martineau 
1505b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1515b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1525b155ef9SMat Martineau 	if (c)
1535b155ef9SMat Martineau 		l2cap_chan_lock(c);
1545b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1555b155ef9SMat Martineau 
1565b155ef9SMat Martineau 	return c;
1575b155ef9SMat Martineau }
1585b155ef9SMat Martineau 
15923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1609e4425ffSGustavo F. Padovan {
16123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1629e4425ffSGustavo F. Padovan 
16323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
1647eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
16523691d75SGustavo F. Padovan 			return c;
1669e4425ffSGustavo F. Padovan 	}
167250938cbSSzymon Janc 	return NULL;
168250938cbSSzymon Janc }
1699e4425ffSGustavo F. Padovan 
1709e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1719e4425ffSGustavo F. Padovan {
17273b2ec18SGustavo F. Padovan 	int err;
17373b2ec18SGustavo F. Padovan 
174333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1759e4425ffSGustavo F. Padovan 
17623691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
17773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
17873b2ec18SGustavo F. Padovan 		goto done;
1799e4425ffSGustavo F. Padovan 	}
1809e4425ffSGustavo F. Padovan 
18173b2ec18SGustavo F. Padovan 	if (psm) {
1829e4425ffSGustavo F. Padovan 		chan->psm = psm;
1839e4425ffSGustavo F. Padovan 		chan->sport = psm;
18473b2ec18SGustavo F. Padovan 		err = 0;
18573b2ec18SGustavo F. Padovan 	} else {
18673b2ec18SGustavo F. Padovan 		u16 p;
1879e4425ffSGustavo F. Padovan 
18873b2ec18SGustavo F. Padovan 		err = -EINVAL;
18973b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
19023691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
19173b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
19273b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
19373b2ec18SGustavo F. Padovan 				err = 0;
19473b2ec18SGustavo F. Padovan 				break;
19573b2ec18SGustavo F. Padovan 			}
19673b2ec18SGustavo F. Padovan 	}
19773b2ec18SGustavo F. Padovan 
19873b2ec18SGustavo F. Padovan done:
199333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
20073b2ec18SGustavo F. Padovan 	return err;
2019e4425ffSGustavo F. Padovan }
2029e4425ffSGustavo F. Padovan 
2039e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2049e4425ffSGustavo F. Padovan {
205333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2069e4425ffSGustavo F. Padovan 
2079e4425ffSGustavo F. Padovan 	chan->scid = scid;
2089e4425ffSGustavo F. Padovan 
209333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2109e4425ffSGustavo F. Padovan 
2119e4425ffSGustavo F. Padovan 	return 0;
2129e4425ffSGustavo F. Padovan }
2139e4425ffSGustavo F. Padovan 
214baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2150a708f8fSGustavo F. Padovan {
2160a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
2170a708f8fSGustavo F. Padovan 
2180a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
219baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2200a708f8fSGustavo F. Padovan 			return cid;
2210a708f8fSGustavo F. Padovan 	}
2220a708f8fSGustavo F. Padovan 
2230a708f8fSGustavo F. Padovan 	return 0;
2240a708f8fSGustavo F. Padovan }
2250a708f8fSGustavo F. Padovan 
226f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
22789bc500eSGustavo F. Padovan {
22842d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
229badaaa00SGustavo F. Padovan 	       state_to_string(state));
230badaaa00SGustavo F. Padovan 
23189bc500eSGustavo F. Padovan 	chan->state = state;
23253f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
23389bc500eSGustavo F. Padovan }
23489bc500eSGustavo F. Padovan 
235f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
236f8e73017SGustavo Padovan 						int state, int err)
2372e0052e4SAndrei Emeltchenko {
238f8e73017SGustavo Padovan 	chan->state = state;
23953f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2402e0052e4SAndrei Emeltchenko }
2412e0052e4SAndrei Emeltchenko 
2422e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2432e0052e4SAndrei Emeltchenko {
244f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2452e0052e4SAndrei Emeltchenko }
2462e0052e4SAndrei Emeltchenko 
2474239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2484239d16fSMat Martineau {
2494239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2504239d16fSMat Martineau 	    chan->retrans_timeout) {
2514239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2524239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2534239d16fSMat Martineau 	}
2544239d16fSMat Martineau }
2554239d16fSMat Martineau 
2564239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2574239d16fSMat Martineau {
2584239d16fSMat Martineau 	__clear_retrans_timer(chan);
2594239d16fSMat Martineau 	if (chan->monitor_timeout) {
2604239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2614239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2624239d16fSMat Martineau 	}
2634239d16fSMat Martineau }
2644239d16fSMat Martineau 
265608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
266608bcc6dSMat Martineau 					       u16 seq)
267608bcc6dSMat Martineau {
268608bcc6dSMat Martineau 	struct sk_buff *skb;
269608bcc6dSMat Martineau 
270608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
271608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
272608bcc6dSMat Martineau 			return skb;
273608bcc6dSMat Martineau 	}
274608bcc6dSMat Martineau 
275608bcc6dSMat Martineau 	return NULL;
276608bcc6dSMat Martineau }
277608bcc6dSMat Martineau 
2783c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2793c588192SMat Martineau 
2803c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2813c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2823c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2833c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2843c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2853c588192SMat Martineau  * and removed from the head in constant time, without further memory
2863c588192SMat Martineau  * allocs or frees.
2873c588192SMat Martineau  */
2883c588192SMat Martineau 
2893c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2903c588192SMat Martineau {
2913c588192SMat Martineau 	size_t alloc_size, i;
2923c588192SMat Martineau 
2933c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2943c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2953c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2963c588192SMat Martineau 	 */
2973c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2983c588192SMat Martineau 
2993c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
3003c588192SMat Martineau 	if (!seq_list->list)
3013c588192SMat Martineau 		return -ENOMEM;
3023c588192SMat Martineau 
3033c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3043c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3053c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3063c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3073c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3083c588192SMat Martineau 
3093c588192SMat Martineau 	return 0;
3103c588192SMat Martineau }
3113c588192SMat Martineau 
3123c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3133c588192SMat Martineau {
3143c588192SMat Martineau 	kfree(seq_list->list);
3153c588192SMat Martineau }
3163c588192SMat Martineau 
3173c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3183c588192SMat Martineau 					   u16 seq)
3193c588192SMat Martineau {
3203c588192SMat Martineau 	/* Constant-time check for list membership */
3213c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3223c588192SMat Martineau }
3233c588192SMat Martineau 
3243c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
3253c588192SMat Martineau {
3263c588192SMat Martineau 	u16 mask = seq_list->mask;
3273c588192SMat Martineau 
3283c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
3293c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
3303c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
3313c588192SMat Martineau 	} else if (seq_list->head == seq) {
3323c588192SMat Martineau 		/* Head can be removed in constant time */
3333c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
3343c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3353c588192SMat Martineau 
3363c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3373c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3393c588192SMat Martineau 		}
3403c588192SMat Martineau 	} else {
3413c588192SMat Martineau 		/* Walk the list to find the sequence number */
3423c588192SMat Martineau 		u16 prev = seq_list->head;
3433c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3443c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3453c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3463c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3473c588192SMat Martineau 		}
3483c588192SMat Martineau 
3493c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3503c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3513c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3523c588192SMat Martineau 		if (seq_list->tail == seq)
3533c588192SMat Martineau 			seq_list->tail = prev;
3543c588192SMat Martineau 	}
3553c588192SMat Martineau 	return seq;
3563c588192SMat Martineau }
3573c588192SMat Martineau 
3583c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3593c588192SMat Martineau {
3603c588192SMat Martineau 	/* Remove the head in constant time */
3613c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3623c588192SMat Martineau }
3633c588192SMat Martineau 
3643c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3653c588192SMat Martineau {
3663c588192SMat Martineau 	u16 i;
367f522ae36SGustavo Padovan 
368f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
369f522ae36SGustavo Padovan 		return;
370f522ae36SGustavo Padovan 
3713c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3723c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3733c588192SMat Martineau 
3743c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3753c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3763c588192SMat Martineau }
3773c588192SMat Martineau 
3783c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3793c588192SMat Martineau {
3803c588192SMat Martineau 	u16 mask = seq_list->mask;
3813c588192SMat Martineau 
3823c588192SMat Martineau 	/* All appends happen in constant time */
3833c588192SMat Martineau 
384f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
385f522ae36SGustavo Padovan 		return;
386f522ae36SGustavo Padovan 
3873c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3883c588192SMat Martineau 		seq_list->head = seq;
3893c588192SMat Martineau 	else
3903c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3913c588192SMat Martineau 
3923c588192SMat Martineau 	seq_list->tail = seq;
3933c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3943c588192SMat Martineau }
3953c588192SMat Martineau 
396721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
397ab07801dSGustavo F. Padovan {
398721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
399721c4181SGustavo F. Padovan 					       chan_timer.work);
4003df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
401ab07801dSGustavo F. Padovan 	int reason;
402ab07801dSGustavo F. Padovan 
403e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
404ab07801dSGustavo F. Padovan 
4053df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4066be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
407ab07801dSGustavo F. Padovan 
40889bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
409ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
41089bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
411ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
412ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
413ab07801dSGustavo F. Padovan 	else
414ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
415ab07801dSGustavo F. Padovan 
4160f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
417ab07801dSGustavo F. Padovan 
4186be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
419ab07801dSGustavo F. Padovan 
42080b98027SGustavo Padovan 	chan->ops->close(chan);
4213df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4223df91ea2SAndrei Emeltchenko 
423371fd835SUlisses Furquim 	l2cap_chan_put(chan);
424ab07801dSGustavo F. Padovan }
425ab07801dSGustavo F. Padovan 
426eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4270a708f8fSGustavo F. Padovan {
42848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4290a708f8fSGustavo F. Padovan 
43048454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
43148454079SGustavo F. Padovan 	if (!chan)
43248454079SGustavo F. Padovan 		return NULL;
4330a708f8fSGustavo F. Padovan 
434c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
435c03b355eSAndrei Emeltchenko 
436333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
43723691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
438333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
43923691d75SGustavo F. Padovan 
440721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
441ab07801dSGustavo F. Padovan 
44289bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
44389bc500eSGustavo F. Padovan 
444144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
44571ba0e56SGustavo F. Padovan 
4462827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4472827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4482827011fSMat Martineau 
449eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
450abc545b8SSzymon Janc 
45148454079SGustavo F. Padovan 	return chan;
4520a708f8fSGustavo F. Padovan }
4530a708f8fSGustavo F. Padovan 
454144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4556ff5abbfSGustavo F. Padovan {
456144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
457144ad330SSyam Sidhardhan 
4584af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4594af66c69SJaganath Kanakkassery 
460333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46123691d75SGustavo F. Padovan 	list_del(&chan->global_l);
462333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
46323691d75SGustavo F. Padovan 
4644af66c69SJaganath Kanakkassery 	kfree(chan);
4656ff5abbfSGustavo F. Padovan }
4666ff5abbfSGustavo F. Padovan 
46730648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
46830648372SJaganath Kanakkassery {
469144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
47030648372SJaganath Kanakkassery 
471144ad330SSyam Sidhardhan 	kref_get(&c->kref);
47230648372SJaganath Kanakkassery }
47330648372SJaganath Kanakkassery 
47430648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
47530648372SJaganath Kanakkassery {
476144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
47730648372SJaganath Kanakkassery 
478144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
47930648372SJaganath Kanakkassery }
48030648372SJaganath Kanakkassery 
481bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
482bd4b1653SAndrei Emeltchenko {
483bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
484bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
485bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
486bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
487c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
488bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
489bd4b1653SAndrei Emeltchenko 
490bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
491bd4b1653SAndrei Emeltchenko }
492bd4b1653SAndrei Emeltchenko 
49338319713SJohan Hedberg void l2cap_le_flowctl_init(struct l2cap_chan *chan)
49438319713SJohan Hedberg {
49538319713SJohan Hedberg 	chan->imtu = L2CAP_DEFAULT_MTU;
49638319713SJohan Hedberg 	chan->omtu = L2CAP_LE_MIN_MTU;
49738319713SJohan Hedberg 	chan->mode = L2CAP_MODE_LE_FLOWCTL;
4980cd75f7eSJohan Hedberg 	chan->tx_credits = 0;
4990cd75f7eSJohan Hedberg 	chan->rx_credits = L2CAP_LE_MAX_CREDITS;
50038319713SJohan Hedberg }
50138319713SJohan Hedberg 
50293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5030a708f8fSGustavo F. Padovan {
5040a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
505097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5060a708f8fSGustavo F. Padovan 
5079f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5080a708f8fSGustavo F. Padovan 
5098c1d787bSGustavo F. Padovan 	chan->conn = conn;
5100a708f8fSGustavo F. Padovan 
5115491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5125491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
513b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
514b62f328bSVille Tervo 			/* LE connection */
5156fcb06a2SAndre Guedes 			chan->omtu = L2CAP_DEFAULT_MTU;
5169f22398cSJohan Hedberg 			if (chan->dcid == L2CAP_CID_ATT)
517073d1cf3SJohan Hedberg 				chan->scid = L2CAP_CID_ATT;
5189f22398cSJohan Hedberg 			else
5199f22398cSJohan Hedberg 				chan->scid = l2cap_alloc_cid(conn);
520b62f328bSVille Tervo 		} else {
5210a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
522fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
5230c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
524b62f328bSVille Tervo 		}
5255491120eSAndrei Emeltchenko 		break;
5265491120eSAndrei Emeltchenko 
5275491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5280a708f8fSGustavo F. Padovan 		/* Connectionless socket */
529fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
530fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5310c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5325491120eSAndrei Emeltchenko 		break;
5335491120eSAndrei Emeltchenko 
534416fa752SAndrei Emeltchenko 	case L2CAP_CHAN_CONN_FIX_A2MP:
535416fa752SAndrei Emeltchenko 		chan->scid = L2CAP_CID_A2MP;
536416fa752SAndrei Emeltchenko 		chan->dcid = L2CAP_CID_A2MP;
537416fa752SAndrei Emeltchenko 		chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
538416fa752SAndrei Emeltchenko 		chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
539416fa752SAndrei Emeltchenko 		break;
540416fa752SAndrei Emeltchenko 
5415491120eSAndrei Emeltchenko 	default:
5420a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
543fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
544fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5450c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5460a708f8fSGustavo F. Padovan 	}
5470a708f8fSGustavo F. Padovan 
5488f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5498f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5508f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5518f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5528f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5538936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5548f7975b1SAndrei Emeltchenko 
555371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
556baa7e1faSGustavo F. Padovan 
5575ee9891dSJohan Hedberg 	hci_conn_hold(conn->hcon);
5585ee9891dSJohan Hedberg 
5593df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
560643162a8SAndrei Emeltchenko }
561643162a8SAndrei Emeltchenko 
562466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
563643162a8SAndrei Emeltchenko {
564643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
565643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5670a708f8fSGustavo F. Padovan }
5680a708f8fSGustavo F. Padovan 
569466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5700a708f8fSGustavo F. Padovan {
5718c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5720a708f8fSGustavo F. Padovan 
573c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5740a708f8fSGustavo F. Padovan 
57549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5760a708f8fSGustavo F. Padovan 
5770a708f8fSGustavo F. Padovan 	if (conn) {
57856f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
579baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5803df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5813d57dc68SGustavo F. Padovan 
582371fd835SUlisses Furquim 		l2cap_chan_put(chan);
583baa7e1faSGustavo F. Padovan 
5848c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5853cabbfdaSAndrei Emeltchenko 
5863cabbfdaSAndrei Emeltchenko 		if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
58776a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
58856f60984SAndrei Emeltchenko 
58956f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
59056f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
5910a708f8fSGustavo F. Padovan 	}
5920a708f8fSGustavo F. Padovan 
593419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
594419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
595419e08c1SAndrei Emeltchenko 
596419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
597419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
598419e08c1SAndrei Emeltchenko 	}
599419e08c1SAndrei Emeltchenko 
600c0df7f6eSAndrei Emeltchenko 	chan->ops->teardown(chan, err);
6016be36555SAndrei Emeltchenko 
6022827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6036ff5abbfSGustavo F. Padovan 		return;
6042ead70b8SGustavo F. Padovan 
605ee556f66SGustavo Padovan 	switch(chan->mode) {
606ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
607ee556f66SGustavo Padovan 		break;
6080a708f8fSGustavo F. Padovan 
60938319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
61038319713SJohan Hedberg 		break;
61138319713SJohan Hedberg 
612ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6131a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6141a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6151a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6160a708f8fSGustavo F. Padovan 
617f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6180a708f8fSGustavo F. Padovan 
6193c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6203c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
621ee556f66SGustavo Padovan 
622ee556f66SGustavo Padovan 		/* fall through */
623ee556f66SGustavo Padovan 
624ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
625ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
626ee556f66SGustavo Padovan 		break;
6270a708f8fSGustavo F. Padovan 	}
628ee556f66SGustavo Padovan 
629ee556f66SGustavo Padovan 	return;
6300a708f8fSGustavo F. Padovan }
6310a708f8fSGustavo F. Padovan 
63227e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
63327e2d4c8SJohan Hedberg {
63427e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
63527e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
63627e2d4c8SJohan Hedberg 	u16 result;
63727e2d4c8SJohan Hedberg 
63827e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
63927e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHORIZATION;
64027e2d4c8SJohan Hedberg 	else
64127e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
64227e2d4c8SJohan Hedberg 
64327e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
64427e2d4c8SJohan Hedberg 
64527e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
64627e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
64727e2d4c8SJohan Hedberg 	rsp.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
6480cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
64927e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
65027e2d4c8SJohan Hedberg 
65127e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
65227e2d4c8SJohan Hedberg 		       &rsp);
65327e2d4c8SJohan Hedberg }
65427e2d4c8SJohan Hedberg 
655791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
656791d60f7SJohan Hedberg {
657791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
658791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
659791d60f7SJohan Hedberg 	u16 result;
660791d60f7SJohan Hedberg 
661791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
662791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
663791d60f7SJohan Hedberg 	else
664791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
665791d60f7SJohan Hedberg 
666791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
667791d60f7SJohan Hedberg 
668791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
669791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
670791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
671791d60f7SJohan Hedberg 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
672791d60f7SJohan Hedberg 
673791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
674791d60f7SJohan Hedberg }
675791d60f7SJohan Hedberg 
6760f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
6774519de9aSGustavo F. Padovan {
6784519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6794519de9aSGustavo F. Padovan 
6807eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
6814519de9aSGustavo F. Padovan 
68289bc500eSGustavo F. Padovan 	switch (chan->state) {
6834519de9aSGustavo F. Padovan 	case BT_LISTEN:
684c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
6854519de9aSGustavo F. Padovan 		break;
6864519de9aSGustavo F. Padovan 
6874519de9aSGustavo F. Padovan 	case BT_CONNECTED:
6884519de9aSGustavo F. Padovan 	case BT_CONFIG:
689cea04ce3SJohan Hedberg 		/* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
690cea04ce3SJohan Hedberg 		 * check for chan->psm.
691cea04ce3SJohan Hedberg 		 */
692cea04ce3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
6938d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
6945e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
6954519de9aSGustavo F. Padovan 		} else
6964519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
6974519de9aSGustavo F. Padovan 		break;
6984519de9aSGustavo F. Padovan 
6994519de9aSGustavo F. Padovan 	case BT_CONNECT2:
700791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
701791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
702791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
70327e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
70427e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7054519de9aSGustavo F. Padovan 		}
7064519de9aSGustavo F. Padovan 
7074519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7084519de9aSGustavo F. Padovan 		break;
7094519de9aSGustavo F. Padovan 
7104519de9aSGustavo F. Padovan 	case BT_CONNECT:
7114519de9aSGustavo F. Padovan 	case BT_DISCONN:
7124519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7134519de9aSGustavo F. Padovan 		break;
7144519de9aSGustavo F. Padovan 
7154519de9aSGustavo F. Padovan 	default:
716c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7174519de9aSGustavo F. Padovan 		break;
7184519de9aSGustavo F. Padovan 	}
7194519de9aSGustavo F. Padovan }
7204519de9aSGustavo F. Padovan 
7214343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7220a708f8fSGustavo F. Padovan {
7236a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7246a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7254343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7260a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7270a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7280a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7290a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7300a708f8fSGustavo F. Padovan 		default:
7310a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7320a708f8fSGustavo F. Padovan 		}
7336a974b50SMarcel Holtmann 		break;
7343124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
7353124b843SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
7363124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7373124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7383124b843SMarcel Holtmann 		}
7393124b843SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH)
7403124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7413124b843SMarcel Holtmann 		else
7423124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7433124b843SMarcel Holtmann 		break;
7446a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
7456a974b50SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
7464343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7474343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
7480a708f8fSGustavo F. Padovan 
7494343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_HIGH)
7500a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
7510a708f8fSGustavo F. Padovan 			else
7520a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
7536a974b50SMarcel Holtmann 		}
7546a974b50SMarcel Holtmann 		/* fall through */
7556a974b50SMarcel Holtmann 	default:
7564343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7570a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7580a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
7590a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7600a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
7610a708f8fSGustavo F. Padovan 		default:
7620a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7630a708f8fSGustavo F. Padovan 		}
7646a974b50SMarcel Holtmann 		break;
7650a708f8fSGustavo F. Padovan 	}
7660a708f8fSGustavo F. Padovan }
7670a708f8fSGustavo F. Padovan 
7680a708f8fSGustavo F. Padovan /* Service level security */
769d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
7700a708f8fSGustavo F. Padovan {
7718c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7720a708f8fSGustavo F. Padovan 	__u8 auth_type;
7730a708f8fSGustavo F. Padovan 
774a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
775a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
776a17de2feSJohan Hedberg 
7774343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
7780a708f8fSGustavo F. Padovan 
7794343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
7800a708f8fSGustavo F. Padovan }
7810a708f8fSGustavo F. Padovan 
782b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
7830a708f8fSGustavo F. Padovan {
7840a708f8fSGustavo F. Padovan 	u8 id;
7850a708f8fSGustavo F. Padovan 
7860a708f8fSGustavo F. Padovan 	/* Get next available identificator.
7870a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
7880a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
7890a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
7900a708f8fSGustavo F. Padovan 	 */
7910a708f8fSGustavo F. Padovan 
792333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
7930a708f8fSGustavo F. Padovan 
7940a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
7950a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
7960a708f8fSGustavo F. Padovan 
7970a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
7980a708f8fSGustavo F. Padovan 
799333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
8000a708f8fSGustavo F. Padovan 
8010a708f8fSGustavo F. Padovan 	return id;
8020a708f8fSGustavo F. Padovan }
8030a708f8fSGustavo F. Padovan 
8042d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8052d792818SGustavo Padovan 			   void *data)
8060a708f8fSGustavo F. Padovan {
8070a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8080a708f8fSGustavo F. Padovan 	u8 flags;
8090a708f8fSGustavo F. Padovan 
8100a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8110a708f8fSGustavo F. Padovan 
8120a708f8fSGustavo F. Padovan 	if (!skb)
8130a708f8fSGustavo F. Padovan 		return;
8140a708f8fSGustavo F. Padovan 
8150a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
8160a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8170a708f8fSGustavo F. Padovan 	else
8180a708f8fSGustavo F. Padovan 		flags = ACL_START;
8190a708f8fSGustavo F. Padovan 
82014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8215e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
82214b12d0bSJaikumar Ganesh 
82373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8240a708f8fSGustavo F. Padovan }
8250a708f8fSGustavo F. Padovan 
82602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
82702b0fbb9SMat Martineau {
82802b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
82902b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
83002b0fbb9SMat Martineau }
83102b0fbb9SMat Martineau 
83273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
83373d80debSLuiz Augusto von Dentz {
83473d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
83573d80debSLuiz Augusto von Dentz 	u16 flags;
83673d80debSLuiz Augusto von Dentz 
83773d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
83873d80debSLuiz Augusto von Dentz 	       skb->priority);
83973d80debSLuiz Augusto von Dentz 
840d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
841d5f8a75dSMat Martineau 		if (chan->hs_hchan)
842d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
843d5f8a75dSMat Martineau 		else
844d5f8a75dSMat Martineau 			kfree_skb(skb);
845d5f8a75dSMat Martineau 
846d5f8a75dSMat Martineau 		return;
847d5f8a75dSMat Martineau 	}
848d5f8a75dSMat Martineau 
84973d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
85073d80debSLuiz Augusto von Dentz 	    lmp_no_flush_capable(hcon->hdev))
85173d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
85273d80debSLuiz Augusto von Dentz 	else
85373d80debSLuiz Augusto von Dentz 		flags = ACL_START;
85473d80debSLuiz Augusto von Dentz 
85573d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
85673d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
8570a708f8fSGustavo F. Padovan }
8580a708f8fSGustavo F. Padovan 
859b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
860b5c6aaedSMat Martineau {
861b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
862b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
863b5c6aaedSMat Martineau 
864b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
865b5c6aaedSMat Martineau 		/* S-Frame */
866b5c6aaedSMat Martineau 		control->sframe = 1;
867b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
868b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
869b5c6aaedSMat Martineau 
870b5c6aaedSMat Martineau 		control->sar = 0;
871b5c6aaedSMat Martineau 		control->txseq = 0;
872b5c6aaedSMat Martineau 	} else {
873b5c6aaedSMat Martineau 		/* I-Frame */
874b5c6aaedSMat Martineau 		control->sframe = 0;
875b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
876b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
877b5c6aaedSMat Martineau 
878b5c6aaedSMat Martineau 		control->poll = 0;
879b5c6aaedSMat Martineau 		control->super = 0;
880b5c6aaedSMat Martineau 	}
881b5c6aaedSMat Martineau }
882b5c6aaedSMat Martineau 
883b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
884b5c6aaedSMat Martineau {
885b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
886b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
887b5c6aaedSMat Martineau 
888b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
889b5c6aaedSMat Martineau 		/* S-Frame */
890b5c6aaedSMat Martineau 		control->sframe = 1;
891b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
892b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
893b5c6aaedSMat Martineau 
894b5c6aaedSMat Martineau 		control->sar = 0;
895b5c6aaedSMat Martineau 		control->txseq = 0;
896b5c6aaedSMat Martineau 	} else {
897b5c6aaedSMat Martineau 		/* I-Frame */
898b5c6aaedSMat Martineau 		control->sframe = 0;
899b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
900b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
901b5c6aaedSMat Martineau 
902b5c6aaedSMat Martineau 		control->poll = 0;
903b5c6aaedSMat Martineau 		control->super = 0;
904b5c6aaedSMat Martineau 	}
905b5c6aaedSMat Martineau }
906b5c6aaedSMat Martineau 
907b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
908b5c6aaedSMat Martineau 				    struct sk_buff *skb)
909b5c6aaedSMat Martineau {
910b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
911b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
912b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
913cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
914b5c6aaedSMat Martineau 	} else {
915b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
916b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
917cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
918b5c6aaedSMat Martineau 	}
919b5c6aaedSMat Martineau }
920b5c6aaedSMat Martineau 
921b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
922b5c6aaedSMat Martineau {
923b5c6aaedSMat Martineau 	u32 packed;
924b5c6aaedSMat Martineau 
925b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
926b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
927b5c6aaedSMat Martineau 
928b5c6aaedSMat Martineau 	if (control->sframe) {
929b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
930b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
931b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
932b5c6aaedSMat Martineau 	} else {
933b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
934b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
935b5c6aaedSMat Martineau 	}
936b5c6aaedSMat Martineau 
937b5c6aaedSMat Martineau 	return packed;
938b5c6aaedSMat Martineau }
939b5c6aaedSMat Martineau 
940b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
941b5c6aaedSMat Martineau {
942b5c6aaedSMat Martineau 	u16 packed;
943b5c6aaedSMat Martineau 
944b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
945b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
946b5c6aaedSMat Martineau 
947b5c6aaedSMat Martineau 	if (control->sframe) {
948b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
949b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
950b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
951b5c6aaedSMat Martineau 	} else {
952b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
953b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
954b5c6aaedSMat Martineau 	}
955b5c6aaedSMat Martineau 
956b5c6aaedSMat Martineau 	return packed;
957b5c6aaedSMat Martineau }
958b5c6aaedSMat Martineau 
959b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
960b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
961b5c6aaedSMat Martineau 				  struct sk_buff *skb)
962b5c6aaedSMat Martineau {
963b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
964b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
965b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
966b5c6aaedSMat Martineau 	} else {
967b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
968b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
969b5c6aaedSMat Martineau 	}
970b5c6aaedSMat Martineau }
971b5c6aaedSMat Martineau 
972ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
973ba7aa64fSGustavo Padovan {
974ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
975ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
976ba7aa64fSGustavo Padovan 	else
977ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
978ba7aa64fSGustavo Padovan }
979ba7aa64fSGustavo Padovan 
980a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
981a67d7f6fSMat Martineau 					       u32 control)
9820a708f8fSGustavo F. Padovan {
9830a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
9840a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
985ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
9860a708f8fSGustavo F. Padovan 
9870a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
98803a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
9890a708f8fSGustavo F. Padovan 
990a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
9910a708f8fSGustavo F. Padovan 
9920a708f8fSGustavo F. Padovan 	if (!skb)
993a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
9940a708f8fSGustavo F. Padovan 
9950a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
9960a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
997fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
99888843ab0SAndrei Emeltchenko 
999a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1000a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1001a67d7f6fSMat Martineau 	else
1002a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10030a708f8fSGustavo F. Padovan 
100447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1005a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
100603a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10070a708f8fSGustavo F. Padovan 	}
10080a708f8fSGustavo F. Padovan 
100973d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1010a67d7f6fSMat Martineau 	return skb;
1011a67d7f6fSMat Martineau }
1012a67d7f6fSMat Martineau 
1013a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1014a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1015a67d7f6fSMat Martineau {
1016a67d7f6fSMat Martineau 	struct sk_buff *skb;
1017a67d7f6fSMat Martineau 	u32 control_field;
1018a67d7f6fSMat Martineau 
1019a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1020a67d7f6fSMat Martineau 
1021a67d7f6fSMat Martineau 	if (!control->sframe)
1022a67d7f6fSMat Martineau 		return;
1023a67d7f6fSMat Martineau 
1024b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1025b99e13adSMat Martineau 		return;
1026b99e13adSMat Martineau 
1027a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1028a67d7f6fSMat Martineau 	    !control->poll)
1029a67d7f6fSMat Martineau 		control->final = 1;
1030a67d7f6fSMat Martineau 
1031a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1032a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1033a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1034a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1035a67d7f6fSMat Martineau 
1036a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1037a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1038a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1039a67d7f6fSMat Martineau 	}
1040a67d7f6fSMat Martineau 
1041a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1042a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1043a67d7f6fSMat Martineau 
1044a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1045a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1046a67d7f6fSMat Martineau 	else
1047a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1048a67d7f6fSMat Martineau 
1049a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1050a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
105173d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
10520a708f8fSGustavo F. Padovan }
10530a708f8fSGustavo F. Padovan 
1054c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
10550a708f8fSGustavo F. Padovan {
1056c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
10570a708f8fSGustavo F. Padovan 
1058c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1059c9e3d5e0SMat Martineau 
1060c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1061c9e3d5e0SMat Martineau 	control.sframe = 1;
1062c9e3d5e0SMat Martineau 	control.poll = poll;
1063c9e3d5e0SMat Martineau 
1064c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1065c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1066c9e3d5e0SMat Martineau 	else
1067c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1068c9e3d5e0SMat Martineau 
1069c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1070c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
10710a708f8fSGustavo F. Padovan }
10720a708f8fSGustavo F. Padovan 
1073b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
10740a708f8fSGustavo F. Padovan {
1075c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
10760a708f8fSGustavo F. Padovan }
10770a708f8fSGustavo F. Padovan 
107893c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
107993c3e8f5SAndrei Emeltchenko {
108093c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
10811df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
10821df7b17aSMarcel Holtmann 	bool amp_available = false;
108393c3e8f5SAndrei Emeltchenko 
10841df7b17aSMarcel Holtmann 	if (!conn->hs_enabled)
10851df7b17aSMarcel Holtmann 		return false;
10861df7b17aSMarcel Holtmann 
10871df7b17aSMarcel Holtmann 	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
10881df7b17aSMarcel Holtmann 		return false;
10891df7b17aSMarcel Holtmann 
10901df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
10911df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
10921df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
10931df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
10941df7b17aSMarcel Holtmann 			amp_available = true;
10951df7b17aSMarcel Holtmann 			break;
10961df7b17aSMarcel Holtmann 		}
10971df7b17aSMarcel Holtmann 	}
10981df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
10991df7b17aSMarcel Holtmann 
11001df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11011df7b17aSMarcel Holtmann 		return amp_available;
1102848566b3SMarcel Holtmann 
110393c3e8f5SAndrei Emeltchenko 	return false;
110493c3e8f5SAndrei Emeltchenko }
110593c3e8f5SAndrei Emeltchenko 
11065ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11075ce66b59SAndrei Emeltchenko {
11085ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11095ce66b59SAndrei Emeltchenko 	return true;
11105ce66b59SAndrei Emeltchenko }
11115ce66b59SAndrei Emeltchenko 
11122766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11139b27f350SAndrei Emeltchenko {
11149b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11159b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11169b27f350SAndrei Emeltchenko 
11179b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11189b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11199b27f350SAndrei Emeltchenko 
11209b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11219b27f350SAndrei Emeltchenko 
11229b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11239b27f350SAndrei Emeltchenko 
11249b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11259b27f350SAndrei Emeltchenko }
11269b27f350SAndrei Emeltchenko 
11278eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11288eb200bdSMat Martineau {
11298eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11308eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11318eb200bdSMat Martineau 	req.psm  = chan->psm;
11328eb200bdSMat Martineau 	req.amp_id = amp_id;
11338eb200bdSMat Martineau 
11348eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
11358eb200bdSMat Martineau 
11368eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
11378eb200bdSMat Martineau 		       sizeof(req), &req);
11388eb200bdSMat Martineau }
11398eb200bdSMat Martineau 
114002b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
114102b0fbb9SMat Martineau {
114202b0fbb9SMat Martineau 	struct sk_buff *skb;
114302b0fbb9SMat Martineau 
114402b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
114502b0fbb9SMat Martineau 
114602b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
114702b0fbb9SMat Martineau 		return;
114802b0fbb9SMat Martineau 
114902b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
115002b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
115102b0fbb9SMat Martineau 	__clear_ack_timer(chan);
115202b0fbb9SMat Martineau 
115302b0fbb9SMat Martineau 	chan->retry_count = 0;
115402b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
115502b0fbb9SMat Martineau 		if (bt_cb(skb)->control.retries)
115602b0fbb9SMat Martineau 			bt_cb(skb)->control.retries = 1;
115702b0fbb9SMat Martineau 		else
115802b0fbb9SMat Martineau 			break;
115902b0fbb9SMat Martineau 	}
116002b0fbb9SMat Martineau 
116102b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
116202b0fbb9SMat Martineau 
116302b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
116402b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
116502b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
116602b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
116702b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
116802b0fbb9SMat Martineau 
116902b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
117002b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
117102b0fbb9SMat Martineau 
117202b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
117302b0fbb9SMat Martineau }
117402b0fbb9SMat Martineau 
11755f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
11765f3847a4SMat Martineau {
11775f3847a4SMat Martineau 	u8 move_role = chan->move_role;
11785f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
11795f3847a4SMat Martineau 
11805f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
11815f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
11825f3847a4SMat Martineau 
11835f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
11845f3847a4SMat Martineau 		return;
11855f3847a4SMat Martineau 
11865f3847a4SMat Martineau 	switch (move_role) {
11875f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
11885f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
11895f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
11905f3847a4SMat Martineau 		break;
11915f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
11925f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
11935f3847a4SMat Martineau 		break;
11945f3847a4SMat Martineau 	}
11955f3847a4SMat Martineau }
11965f3847a4SMat Martineau 
11979f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
11989f0caeb1SVinicius Costa Gomes {
11992827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12009f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12019f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12029f0caeb1SVinicius Costa Gomes 
120354a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12049f0caeb1SVinicius Costa Gomes 
120554a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12069f0caeb1SVinicius Costa Gomes }
12079f0caeb1SVinicius Costa Gomes 
1208f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1209f1496deeSJohan Hedberg {
1210f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1211f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1212f1496deeSJohan Hedberg 
1213f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1214f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1215f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
1216f1496deeSJohan Hedberg 	req.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
12170cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1218f1496deeSJohan Hedberg 
1219f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1220f1496deeSJohan Hedberg 
1221f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1222f1496deeSJohan Hedberg 		       sizeof(req), &req);
1223f1496deeSJohan Hedberg }
1224f1496deeSJohan Hedberg 
1225f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1226f1496deeSJohan Hedberg {
1227f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1228f1496deeSJohan Hedberg 
1229f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1230f1496deeSJohan Hedberg 		return;
1231f1496deeSJohan Hedberg 
1232f1496deeSJohan Hedberg 	if (!chan->psm) {
1233f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1234f1496deeSJohan Hedberg 		return;
1235f1496deeSJohan Hedberg 	}
1236f1496deeSJohan Hedberg 
1237f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1238f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1239f1496deeSJohan Hedberg }
1240f1496deeSJohan Hedberg 
124193c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
124293c3e8f5SAndrei Emeltchenko {
124393c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
124493c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
124593c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1246f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1247f1496deeSJohan Hedberg 		l2cap_le_start(chan);
124893c3e8f5SAndrei Emeltchenko 	} else {
124993c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
125093c3e8f5SAndrei Emeltchenko 	}
125193c3e8f5SAndrei Emeltchenko }
125293c3e8f5SAndrei Emeltchenko 
1253fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
12540a708f8fSGustavo F. Padovan {
12558c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
12560a708f8fSGustavo F. Padovan 
12579f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
125896ac34fbSJohan Hedberg 		l2cap_le_start(chan);
12599f0caeb1SVinicius Costa Gomes 		return;
12609f0caeb1SVinicius Costa Gomes 	}
12619f0caeb1SVinicius Costa Gomes 
12620a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
12630a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
12640a708f8fSGustavo F. Padovan 			return;
12650a708f8fSGustavo F. Padovan 
1266d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
126793c3e8f5SAndrei Emeltchenko 		    __l2cap_no_conn_pending(chan)) {
126893c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
126993c3e8f5SAndrei Emeltchenko 		}
12700a708f8fSGustavo F. Padovan 	} else {
12710a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
1272ac73498cSAndrei Emeltchenko 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
12730a708f8fSGustavo F. Padovan 
12740a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
12750a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
12760a708f8fSGustavo F. Padovan 
1277ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
12780a708f8fSGustavo F. Padovan 
12792d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
12802d792818SGustavo Padovan 			       sizeof(req), &req);
12810a708f8fSGustavo F. Padovan 	}
12820a708f8fSGustavo F. Padovan }
12830a708f8fSGustavo F. Padovan 
12840a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
12850a708f8fSGustavo F. Padovan {
12860a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
12870a708f8fSGustavo F. Padovan 	if (!disable_ertm)
12880a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
12890a708f8fSGustavo F. Padovan 
12900a708f8fSGustavo F. Padovan 	switch (mode) {
12910a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
12920a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
12930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
12940a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
12950a708f8fSGustavo F. Padovan 	default:
12960a708f8fSGustavo F. Padovan 		return 0x00;
12970a708f8fSGustavo F. Padovan 	}
12980a708f8fSGustavo F. Padovan }
12990a708f8fSGustavo F. Padovan 
13005e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
13010a708f8fSGustavo F. Padovan {
13025e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
13030a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
13040a708f8fSGustavo F. Padovan 
13050a708f8fSGustavo F. Padovan 	if (!conn)
13060a708f8fSGustavo F. Padovan 		return;
13070a708f8fSGustavo F. Padovan 
1308aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
13091a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
13101a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
13111a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
13120a708f8fSGustavo F. Padovan 	}
13130a708f8fSGustavo F. Padovan 
1314416fa752SAndrei Emeltchenko 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1315d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1316416fa752SAndrei Emeltchenko 		return;
1317416fa752SAndrei Emeltchenko 	}
1318416fa752SAndrei Emeltchenko 
1319fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1320fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
13212d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
13222d792818SGustavo Padovan 		       sizeof(req), &req);
13230a708f8fSGustavo F. Padovan 
1324f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
13250a708f8fSGustavo F. Padovan }
13260a708f8fSGustavo F. Padovan 
13270a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
13280a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
13290a708f8fSGustavo F. Padovan {
13303df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
13310a708f8fSGustavo F. Padovan 
13320a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
13330a708f8fSGustavo F. Padovan 
13343df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13350a708f8fSGustavo F. Padovan 
13363df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
13376be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13380a708f8fSGustavo F. Padovan 
1339715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
13406be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
13410a708f8fSGustavo F. Padovan 			continue;
13420a708f8fSGustavo F. Padovan 		}
13430a708f8fSGustavo F. Padovan 
134489bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1345d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1346b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
13476be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13480a708f8fSGustavo F. Padovan 				continue;
13490a708f8fSGustavo F. Padovan 			}
13500a708f8fSGustavo F. Padovan 
1351c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1352c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1353c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
13540f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
13556be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13560a708f8fSGustavo F. Padovan 				continue;
13570a708f8fSGustavo F. Padovan 			}
13580a708f8fSGustavo F. Padovan 
135993c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
13600a708f8fSGustavo F. Padovan 
136189bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
13620a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
13630a708f8fSGustavo F. Padovan 			char buf[128];
1364fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1365fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
13660a708f8fSGustavo F. Padovan 
1367d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
1368bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1369ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1370ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
13712dc4e510SGustavo Padovan 					chan->ops->defer(chan);
13720a708f8fSGustavo F. Padovan 
13730a708f8fSGustavo F. Padovan 				} else {
1374acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1375ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1376ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
13770a708f8fSGustavo F. Padovan 				}
13780a708f8fSGustavo F. Padovan 			} else {
1379ac73498cSAndrei Emeltchenko 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1380ac73498cSAndrei Emeltchenko 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
13810a708f8fSGustavo F. Padovan 			}
13820a708f8fSGustavo F. Padovan 
1383fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1384fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
13850a708f8fSGustavo F. Padovan 
1386c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
13870a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
13886be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13890a708f8fSGustavo F. Padovan 				continue;
13900a708f8fSGustavo F. Padovan 			}
13910a708f8fSGustavo F. Padovan 
1392c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
13930a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
139473ffa904SGustavo F. Padovan 				       l2cap_build_conf_req(chan, buf), buf);
139573ffa904SGustavo F. Padovan 			chan->num_conf_req++;
13960a708f8fSGustavo F. Padovan 		}
13970a708f8fSGustavo F. Padovan 
13986be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13990a708f8fSGustavo F. Padovan 	}
14000a708f8fSGustavo F. Padovan 
14013df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
14020a708f8fSGustavo F. Padovan }
14030a708f8fSGustavo F. Padovan 
1404c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1405b62f328bSVille Tervo  * Returns closest match, locked.
1406b62f328bSVille Tervo  */
1407d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1408c2287681SIdo Yariv 						    bdaddr_t *src,
1409c2287681SIdo Yariv 						    bdaddr_t *dst)
1410b62f328bSVille Tervo {
141123691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1412b62f328bSVille Tervo 
141323691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1414b62f328bSVille Tervo 
141523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
141689bc500eSGustavo F. Padovan 		if (state && c->state != state)
1417b62f328bSVille Tervo 			continue;
1418b62f328bSVille Tervo 
141923691d75SGustavo F. Padovan 		if (c->scid == cid) {
1420c2287681SIdo Yariv 			int src_match, dst_match;
1421c2287681SIdo Yariv 			int src_any, dst_any;
1422c2287681SIdo Yariv 
1423b62f328bSVille Tervo 			/* Exact match. */
14247eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
14257eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1426c2287681SIdo Yariv 			if (src_match && dst_match) {
142723691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
142823691d75SGustavo F. Padovan 				return c;
142923691d75SGustavo F. Padovan 			}
1430b62f328bSVille Tervo 
1431b62f328bSVille Tervo 			/* Closest match */
14327eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
14337eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1434c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1435c2287681SIdo Yariv 			    (src_any && dst_any))
143623691d75SGustavo F. Padovan 				c1 = c;
1437b62f328bSVille Tervo 		}
1438b62f328bSVille Tervo 	}
1439280f294fSGustavo F. Padovan 
144023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1441b62f328bSVille Tervo 
144223691d75SGustavo F. Padovan 	return c1;
1443b62f328bSVille Tervo }
1444b62f328bSVille Tervo 
1445b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1446b62f328bSVille Tervo {
1447cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
144823691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1449cc8dba2bSMarcel Holtmann 	u8 dst_type;
1450b62f328bSVille Tervo 
1451b62f328bSVille Tervo 	BT_DBG("");
1452b62f328bSVille Tervo 
1453b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
1454073d1cf3SJohan Hedberg 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
1455cc8dba2bSMarcel Holtmann 					  &hcon->src, &hcon->dst);
145623691d75SGustavo F. Padovan 	if (!pchan)
1457b62f328bSVille Tervo 		return;
1458b62f328bSVille Tervo 
145944f3b0fbSJohan Hedberg 	/* Client ATT sockets should override the server one */
146044f3b0fbSJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
146144f3b0fbSJohan Hedberg 		return;
146244f3b0fbSJohan Hedberg 
1463cc8dba2bSMarcel Holtmann 	dst_type = bdaddr_type(hcon, hcon->dst_type);
1464cc8dba2bSMarcel Holtmann 
1465cc8dba2bSMarcel Holtmann 	/* If device is blocked, do not create a channel for it */
1466cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
1467cc8dba2bSMarcel Holtmann 		return;
1468cc8dba2bSMarcel Holtmann 
14698ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
147062f3a2cfSGustavo F. Padovan 
147180b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
147280808e43SGustavo F. Padovan 	if (!chan)
1473b62f328bSVille Tervo 		goto clean;
1474b62f328bSVille Tervo 
14759f22398cSJohan Hedberg 	chan->dcid = L2CAP_CID_ATT;
14769f22398cSJohan Hedberg 
1477cc8dba2bSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
1478cc8dba2bSMarcel Holtmann 	bacpy(&chan->dst, &hcon->dst);
1479cc8dba2bSMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
1480cc8dba2bSMarcel Holtmann 	chan->dst_type = dst_type;
1481b62f328bSVille Tervo 
148244f3b0fbSJohan Hedberg 	__l2cap_chan_add(conn, chan);
148348454079SGustavo F. Padovan 
1484b62f328bSVille Tervo clean:
14858ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
1486b62f328bSVille Tervo }
1487b62f328bSVille Tervo 
14880a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
14890a708f8fSGustavo F. Padovan {
149048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1491cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
14920a708f8fSGustavo F. Padovan 
14930a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
14940a708f8fSGustavo F. Padovan 
1495d8729922SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1496d8729922SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1497d8729922SJohan Hedberg 	 */
1498cc110922SVinicius Costa Gomes 	if (hcon->out && hcon->type == LE_LINK)
1499cc110922SVinicius Costa Gomes 		smp_conn_security(hcon, hcon->pending_sec_level);
1500160dc6acSVinicius Costa Gomes 
15013df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15020a708f8fSGustavo F. Padovan 
150344f3b0fbSJohan Hedberg 	if (hcon->type == LE_LINK)
150444f3b0fbSJohan Hedberg 		l2cap_le_conn_ready(conn);
150544f3b0fbSJohan Hedberg 
15063df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1507baa7e1faSGustavo F. Padovan 
15086be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15090a708f8fSGustavo F. Padovan 
1510416fa752SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1511416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1512416fa752SAndrei Emeltchenko 			continue;
1513416fa752SAndrei Emeltchenko 		}
1514416fa752SAndrei Emeltchenko 
1515cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1516f1496deeSJohan Hedberg 			l2cap_le_start(chan);
151763128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
151874e75740SGustavo Padovan 			l2cap_chan_ready(chan);
1519b501d6a1SAnderson Briglia 
15201c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1521fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15221c244f79SGustavo Padovan 		}
15230a708f8fSGustavo F. Padovan 
15246be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15250a708f8fSGustavo F. Padovan 	}
15260a708f8fSGustavo F. Padovan 
15273df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15280a708f8fSGustavo F. Padovan }
15290a708f8fSGustavo F. Padovan 
15300a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15310a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15320a708f8fSGustavo F. Padovan {
153348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15340a708f8fSGustavo F. Padovan 
15350a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15360a708f8fSGustavo F. Padovan 
15373df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15380a708f8fSGustavo F. Padovan 
15393df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1540ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
15411d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
15420a708f8fSGustavo F. Padovan 	}
15430a708f8fSGustavo F. Padovan 
15443df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15450a708f8fSGustavo F. Padovan }
15460a708f8fSGustavo F. Padovan 
1547f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
15480a708f8fSGustavo F. Padovan {
1549f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1550030013d8SGustavo F. Padovan 					       info_timer.work);
15510a708f8fSGustavo F. Padovan 
15520a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
15530a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
15540a708f8fSGustavo F. Padovan 
15550a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
15560a708f8fSGustavo F. Padovan }
15570a708f8fSGustavo F. Padovan 
15582c8e1411SDavid Herrmann /*
15592c8e1411SDavid Herrmann  * l2cap_user
15602c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
15612c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
15622c8e1411SDavid Herrmann  * during unregistration.
15632c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
15642c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
15652c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
15662c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
15672c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
15682c8e1411SDavid Herrmann  * any time if they don't.
15692c8e1411SDavid Herrmann  */
15702c8e1411SDavid Herrmann 
15712c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
15722c8e1411SDavid Herrmann {
15732c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
15742c8e1411SDavid Herrmann 	int ret;
15752c8e1411SDavid Herrmann 
15762c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
15772c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
15782c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
15792c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
15802c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
15812c8e1411SDavid Herrmann 	 * here, too. */
15822c8e1411SDavid Herrmann 
15832c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
15842c8e1411SDavid Herrmann 
15852c8e1411SDavid Herrmann 	if (user->list.next || user->list.prev) {
15862c8e1411SDavid Herrmann 		ret = -EINVAL;
15872c8e1411SDavid Herrmann 		goto out_unlock;
15882c8e1411SDavid Herrmann 	}
15892c8e1411SDavid Herrmann 
15902c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
15912c8e1411SDavid Herrmann 	if (!conn->hchan) {
15922c8e1411SDavid Herrmann 		ret = -ENODEV;
15932c8e1411SDavid Herrmann 		goto out_unlock;
15942c8e1411SDavid Herrmann 	}
15952c8e1411SDavid Herrmann 
15962c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
15972c8e1411SDavid Herrmann 	if (ret)
15982c8e1411SDavid Herrmann 		goto out_unlock;
15992c8e1411SDavid Herrmann 
16002c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16012c8e1411SDavid Herrmann 	ret = 0;
16022c8e1411SDavid Herrmann 
16032c8e1411SDavid Herrmann out_unlock:
16042c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16052c8e1411SDavid Herrmann 	return ret;
16062c8e1411SDavid Herrmann }
16072c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16082c8e1411SDavid Herrmann 
16092c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16102c8e1411SDavid Herrmann {
16112c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16122c8e1411SDavid Herrmann 
16132c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16142c8e1411SDavid Herrmann 
16152c8e1411SDavid Herrmann 	if (!user->list.next || !user->list.prev)
16162c8e1411SDavid Herrmann 		goto out_unlock;
16172c8e1411SDavid Herrmann 
16182c8e1411SDavid Herrmann 	list_del(&user->list);
16192c8e1411SDavid Herrmann 	user->list.next = NULL;
16202c8e1411SDavid Herrmann 	user->list.prev = NULL;
16212c8e1411SDavid Herrmann 	user->remove(conn, user);
16222c8e1411SDavid Herrmann 
16232c8e1411SDavid Herrmann out_unlock:
16242c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16252c8e1411SDavid Herrmann }
16262c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16272c8e1411SDavid Herrmann 
16282c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16292c8e1411SDavid Herrmann {
16302c8e1411SDavid Herrmann 	struct l2cap_user *user;
16312c8e1411SDavid Herrmann 
16322c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16332c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
16342c8e1411SDavid Herrmann 		list_del(&user->list);
16352c8e1411SDavid Herrmann 		user->list.next = NULL;
16362c8e1411SDavid Herrmann 		user->list.prev = NULL;
16372c8e1411SDavid Herrmann 		user->remove(conn, user);
16382c8e1411SDavid Herrmann 	}
16392c8e1411SDavid Herrmann }
16402c8e1411SDavid Herrmann 
16415d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
16425d3de7dfSVinicius Costa Gomes {
16435d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
16445d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
16455d3de7dfSVinicius Costa Gomes 
16465d3de7dfSVinicius Costa Gomes 	if (!conn)
16475d3de7dfSVinicius Costa Gomes 		return;
16485d3de7dfSVinicius Costa Gomes 
16495d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
16505d3de7dfSVinicius Costa Gomes 
16515d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
16525d3de7dfSVinicius Costa Gomes 
16532c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
16542c8e1411SDavid Herrmann 
16553df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16563df91ea2SAndrei Emeltchenko 
16575d3de7dfSVinicius Costa Gomes 	/* Kill channels */
16585d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
165961d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
16606be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16616be36555SAndrei Emeltchenko 
16625d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
16636be36555SAndrei Emeltchenko 
16646be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16656be36555SAndrei Emeltchenko 
166680b98027SGustavo Padovan 		chan->ops->close(chan);
166761d6ef3eSMat Martineau 		l2cap_chan_put(chan);
16685d3de7dfSVinicius Costa Gomes 	}
16695d3de7dfSVinicius Costa Gomes 
16703df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16713df91ea2SAndrei Emeltchenko 
167273d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
167373d80debSLuiz Augusto von Dentz 
16745d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1675127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
16765d3de7dfSVinicius Costa Gomes 
167751a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1678127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
16798aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1680d26a2345SVinicius Costa Gomes 	}
16815d3de7dfSVinicius Costa Gomes 
16825d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
16839c903e37SDavid Herrmann 	conn->hchan = NULL;
16849c903e37SDavid Herrmann 	l2cap_conn_put(conn);
16855d3de7dfSVinicius Costa Gomes }
16865d3de7dfSVinicius Costa Gomes 
16876c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
16885d3de7dfSVinicius Costa Gomes {
16896c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
16906c9d42a1SGustavo F. Padovan 					       security_timer.work);
16915d3de7dfSVinicius Costa Gomes 
1692d06cc416SJohan Hedberg 	BT_DBG("conn %p", conn);
1693d06cc416SJohan Hedberg 
1694d06cc416SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1695d06cc416SJohan Hedberg 		smp_chan_destroy(conn);
16965d3de7dfSVinicius Costa Gomes 		l2cap_conn_del(conn->hcon, ETIMEDOUT);
16975d3de7dfSVinicius Costa Gomes 	}
1698d06cc416SJohan Hedberg }
16995d3de7dfSVinicius Costa Gomes 
1700baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
17010a708f8fSGustavo F. Padovan {
17020a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
170373d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
17040a708f8fSGustavo F. Padovan 
1705baf43251SClaudio Takahasi 	if (conn)
17060a708f8fSGustavo F. Padovan 		return conn;
17070a708f8fSGustavo F. Padovan 
170873d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
170973d80debSLuiz Augusto von Dentz 	if (!hchan)
17100a708f8fSGustavo F. Padovan 		return NULL;
17110a708f8fSGustavo F. Padovan 
17128bcde1f2SGustavo Padovan 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
171373d80debSLuiz Augusto von Dentz 	if (!conn) {
171473d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
171573d80debSLuiz Augusto von Dentz 		return NULL;
171673d80debSLuiz Augusto von Dentz 	}
171773d80debSLuiz Augusto von Dentz 
17189c903e37SDavid Herrmann 	kref_init(&conn->ref);
17190a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
17200a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
17219c903e37SDavid Herrmann 	hci_conn_get(conn->hcon);
172273d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
17230a708f8fSGustavo F. Padovan 
172473d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
17250a708f8fSGustavo F. Padovan 
1726dcc042d5SAndrei Emeltchenko 	switch (hcon->type) {
1727dcc042d5SAndrei Emeltchenko 	case LE_LINK:
1728dcc042d5SAndrei Emeltchenko 		if (hcon->hdev->le_mtu) {
1729acd7d370SVille Tervo 			conn->mtu = hcon->hdev->le_mtu;
1730dcc042d5SAndrei Emeltchenko 			break;
1731dcc042d5SAndrei Emeltchenko 		}
1732dcc042d5SAndrei Emeltchenko 		/* fall through */
1733dcc042d5SAndrei Emeltchenko 	default:
17340a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1735dcc042d5SAndrei Emeltchenko 		break;
1736dcc042d5SAndrei Emeltchenko 	}
1737acd7d370SVille Tervo 
17380a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
17390a708f8fSGustavo F. Padovan 
1740848566b3SMarcel Holtmann 	if (hcon->type == ACL_LINK)
1741848566b3SMarcel Holtmann 		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
1742848566b3SMarcel Holtmann 					    &hcon->hdev->dev_flags);
1743848566b3SMarcel Holtmann 
17440a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
17453df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1746baa7e1faSGustavo F. Padovan 
1747baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
17482c8e1411SDavid Herrmann 	INIT_LIST_HEAD(&conn->users);
17490a708f8fSGustavo F. Padovan 
17505d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
17516c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
17525d3de7dfSVinicius Costa Gomes 	else
1753030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
17540a708f8fSGustavo F. Padovan 
17559f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
17560a708f8fSGustavo F. Padovan 
17570a708f8fSGustavo F. Padovan 	return conn;
17580a708f8fSGustavo F. Padovan }
17590a708f8fSGustavo F. Padovan 
17609c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17619c903e37SDavid Herrmann {
17629c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17639c903e37SDavid Herrmann 
17649c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17659c903e37SDavid Herrmann 	kfree(conn);
17669c903e37SDavid Herrmann }
17679c903e37SDavid Herrmann 
17689c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn)
17699c903e37SDavid Herrmann {
17709c903e37SDavid Herrmann 	kref_get(&conn->ref);
17719c903e37SDavid Herrmann }
17729c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
17739c903e37SDavid Herrmann 
17749c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
17759c903e37SDavid Herrmann {
17769c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
17779c903e37SDavid Herrmann }
17789c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
17799c903e37SDavid Herrmann 
17800a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
17810a708f8fSGustavo F. Padovan 
1782c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
17830a708f8fSGustavo F. Padovan  * Returns closest match.
17840a708f8fSGustavo F. Padovan  */
1785c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1786c2287681SIdo Yariv 						   bdaddr_t *src,
1787bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1788bf20fd4eSJohan Hedberg 						   u8 link_type)
17890a708f8fSGustavo F. Padovan {
179023691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
17910a708f8fSGustavo F. Padovan 
179223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
17930a708f8fSGustavo F. Padovan 
179423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
179589bc500eSGustavo F. Padovan 		if (state && c->state != state)
17960a708f8fSGustavo F. Padovan 			continue;
17970a708f8fSGustavo F. Padovan 
1798bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1799bf20fd4eSJohan Hedberg 			continue;
1800bf20fd4eSJohan Hedberg 
1801bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1802bf20fd4eSJohan Hedberg 			continue;
1803bf20fd4eSJohan Hedberg 
180423691d75SGustavo F. Padovan 		if (c->psm == psm) {
1805c2287681SIdo Yariv 			int src_match, dst_match;
1806c2287681SIdo Yariv 			int src_any, dst_any;
1807c2287681SIdo Yariv 
18080a708f8fSGustavo F. Padovan 			/* Exact match. */
18097eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18107eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1811c2287681SIdo Yariv 			if (src_match && dst_match) {
1812a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
181323691d75SGustavo F. Padovan 				return c;
181423691d75SGustavo F. Padovan 			}
18150a708f8fSGustavo F. Padovan 
18160a708f8fSGustavo F. Padovan 			/* Closest match */
18177eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18187eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1819c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1820c2287681SIdo Yariv 			    (src_any && dst_any))
182123691d75SGustavo F. Padovan 				c1 = c;
18220a708f8fSGustavo F. Padovan 		}
18230a708f8fSGustavo F. Padovan 	}
18240a708f8fSGustavo F. Padovan 
182523691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18260a708f8fSGustavo F. Padovan 
182723691d75SGustavo F. Padovan 	return c1;
18280a708f8fSGustavo F. Padovan }
18290a708f8fSGustavo F. Padovan 
18308e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
18318e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
18320a708f8fSGustavo F. Padovan {
18330a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
18340a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
18350a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
18360a708f8fSGustavo F. Padovan 	__u8 auth_type;
18370a708f8fSGustavo F. Padovan 	int err;
18380a708f8fSGustavo F. Padovan 
18397eafc59eSMarcel Holtmann 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
1840ab19516aSSyam Sidhardhan 	       dst_type, __le16_to_cpu(psm));
18410a708f8fSGustavo F. Padovan 
18427eafc59eSMarcel Holtmann 	hdev = hci_get_route(dst, &chan->src);
18430a708f8fSGustavo F. Padovan 	if (!hdev)
18440a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
18450a708f8fSGustavo F. Padovan 
184609fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
18470a708f8fSGustavo F. Padovan 
18486be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
184903a00194SGustavo F. Padovan 
185003a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
185103a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
185203a00194SGustavo F. Padovan 	    chan->chan_type != L2CAP_CHAN_RAW) {
185303a00194SGustavo F. Padovan 		err = -EINVAL;
185403a00194SGustavo F. Padovan 		goto done;
185503a00194SGustavo F. Padovan 	}
185603a00194SGustavo F. Padovan 
185703a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
185803a00194SGustavo F. Padovan 		err = -EINVAL;
185903a00194SGustavo F. Padovan 		goto done;
186003a00194SGustavo F. Padovan 	}
186103a00194SGustavo F. Padovan 
186203a00194SGustavo F. Padovan 	switch (chan->mode) {
186303a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
186438319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
186503a00194SGustavo F. Padovan 		break;
186603a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
186703a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
186803a00194SGustavo F. Padovan 		if (!disable_ertm)
186903a00194SGustavo F. Padovan 			break;
187003a00194SGustavo F. Padovan 		/* fall through */
187103a00194SGustavo F. Padovan 	default:
187203a00194SGustavo F. Padovan 		err = -ENOTSUPP;
187303a00194SGustavo F. Padovan 		goto done;
187403a00194SGustavo F. Padovan 	}
187503a00194SGustavo F. Padovan 
18760797e01dSGustavo Padovan 	switch (chan->state) {
187703a00194SGustavo F. Padovan 	case BT_CONNECT:
187803a00194SGustavo F. Padovan 	case BT_CONNECT2:
187903a00194SGustavo F. Padovan 	case BT_CONFIG:
188003a00194SGustavo F. Padovan 		/* Already connecting */
188103a00194SGustavo F. Padovan 		err = 0;
188203a00194SGustavo F. Padovan 		goto done;
188303a00194SGustavo F. Padovan 
188403a00194SGustavo F. Padovan 	case BT_CONNECTED:
188503a00194SGustavo F. Padovan 		/* Already connected */
188603a00194SGustavo F. Padovan 		err = -EISCONN;
188703a00194SGustavo F. Padovan 		goto done;
188803a00194SGustavo F. Padovan 
188903a00194SGustavo F. Padovan 	case BT_OPEN:
189003a00194SGustavo F. Padovan 	case BT_BOUND:
189103a00194SGustavo F. Padovan 		/* Can connect */
189203a00194SGustavo F. Padovan 		break;
189303a00194SGustavo F. Padovan 
189403a00194SGustavo F. Padovan 	default:
189503a00194SGustavo F. Padovan 		err = -EBADFD;
189603a00194SGustavo F. Padovan 		goto done;
189703a00194SGustavo F. Padovan 	}
189803a00194SGustavo F. Padovan 
189903a00194SGustavo F. Padovan 	/* Set destination address and psm */
19007eafc59eSMarcel Holtmann 	bacpy(&chan->dst, dst);
19014f1654e0SMarcel Holtmann 	chan->dst_type = dst_type;
19026be36555SAndrei Emeltchenko 
190303a00194SGustavo F. Padovan 	chan->psm = psm;
190403a00194SGustavo F. Padovan 	chan->dcid = cid;
19050a708f8fSGustavo F. Padovan 
19064343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
19070a708f8fSGustavo F. Padovan 
1908f224ca5fSJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
19098e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
19104343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1911acd7d370SVille Tervo 	else
19128e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
19134343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1914acd7d370SVille Tervo 
191530e76272SVille Tervo 	if (IS_ERR(hcon)) {
191630e76272SVille Tervo 		err = PTR_ERR(hcon);
19170a708f8fSGustavo F. Padovan 		goto done;
191830e76272SVille Tervo 	}
19190a708f8fSGustavo F. Padovan 
1920baf43251SClaudio Takahasi 	conn = l2cap_conn_add(hcon);
19210a708f8fSGustavo F. Padovan 	if (!conn) {
192276a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
192330e76272SVille Tervo 		err = -ENOMEM;
19240a708f8fSGustavo F. Padovan 		goto done;
19250a708f8fSGustavo F. Padovan 	}
19260a708f8fSGustavo F. Padovan 
1927141d5706SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
192876a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
1929141d5706SJohan Hedberg 		err = -EBUSY;
19309f0caeb1SVinicius Costa Gomes 		goto done;
19319f0caeb1SVinicius Costa Gomes 	}
19329f0caeb1SVinicius Costa Gomes 
19330a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
19347eafc59eSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
19354f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
19360a708f8fSGustavo F. Padovan 
19376be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
193848454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
19396be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
194048454079SGustavo F. Padovan 
19415ee9891dSJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
19425ee9891dSJohan Hedberg 	hci_conn_drop(hcon);
19435ee9891dSJohan Hedberg 
19446be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
19458d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
19460a708f8fSGustavo F. Padovan 
19470a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1948715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1949c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1950d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
19516be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
19520a708f8fSGustavo F. Padovan 		} else
1953fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
19540a708f8fSGustavo F. Padovan 	}
19550a708f8fSGustavo F. Padovan 
195630e76272SVille Tervo 	err = 0;
195730e76272SVille Tervo 
19580a708f8fSGustavo F. Padovan done:
19596be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
196009fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
19610a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
19620a708f8fSGustavo F. Padovan 	return err;
19630a708f8fSGustavo F. Padovan }
19640a708f8fSGustavo F. Padovan 
1965721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
19660a708f8fSGustavo F. Padovan {
1967721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1968721c4181SGustavo F. Padovan 					       monitor_timer.work);
19690a708f8fSGustavo F. Padovan 
1970525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
19710a708f8fSGustavo F. Padovan 
19726be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
19736be36555SAndrei Emeltchenko 
197480909e04SMat Martineau 	if (!chan->conn) {
19756be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
19768d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
19770a708f8fSGustavo F. Padovan 		return;
19780a708f8fSGustavo F. Padovan 	}
19790a708f8fSGustavo F. Padovan 
1980401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
19810a708f8fSGustavo F. Padovan 
19826be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
19838d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
19840a708f8fSGustavo F. Padovan }
19850a708f8fSGustavo F. Padovan 
1986721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
19870a708f8fSGustavo F. Padovan {
1988721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1989721c4181SGustavo F. Padovan 					       retrans_timer.work);
19900a708f8fSGustavo F. Padovan 
199149208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
19920a708f8fSGustavo F. Padovan 
19936be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
19946be36555SAndrei Emeltchenko 
199580909e04SMat Martineau 	if (!chan->conn) {
199680909e04SMat Martineau 		l2cap_chan_unlock(chan);
199780909e04SMat Martineau 		l2cap_chan_put(chan);
199880909e04SMat Martineau 		return;
199980909e04SMat Martineau 	}
20000a708f8fSGustavo F. Padovan 
2001401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20026be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20038d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20040a708f8fSGustavo F. Padovan }
20050a708f8fSGustavo F. Padovan 
2006d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20073733937dSMat Martineau 				 struct sk_buff_head *skbs)
20080a708f8fSGustavo F. Padovan {
20090a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20103733937dSMat Martineau 	struct l2cap_ctrl *control;
20110a708f8fSGustavo F. Padovan 
20123733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20133733937dSMat Martineau 
2014b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2015b99e13adSMat Martineau 		return;
2016b99e13adSMat Martineau 
20173733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20183733937dSMat Martineau 
20193733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20203733937dSMat Martineau 
20213733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20223733937dSMat Martineau 
20233733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
20243733937dSMat Martineau 		control = &bt_cb(skb)->control;
20253733937dSMat Martineau 
20263733937dSMat Martineau 		control->reqseq = 0;
20273733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20283733937dSMat Martineau 
20293733937dSMat Martineau 		__pack_control(chan, control, skb);
20300a708f8fSGustavo F. Padovan 
203147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20323733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20333733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20340a708f8fSGustavo F. Padovan 		}
20350a708f8fSGustavo F. Padovan 
20364343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20370a708f8fSGustavo F. Padovan 
2038b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20393733937dSMat Martineau 
2040836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20413733937dSMat Martineau 		chan->frames_sent++;
20420a708f8fSGustavo F. Padovan 	}
20430a708f8fSGustavo F. Padovan }
20440a708f8fSGustavo F. Padovan 
204567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20460a708f8fSGustavo F. Padovan {
20470a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
204818a48e76SMat Martineau 	struct l2cap_ctrl *control;
204918a48e76SMat Martineau 	int sent = 0;
205018a48e76SMat Martineau 
205118a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20520a708f8fSGustavo F. Padovan 
205389bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20540a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20550a708f8fSGustavo F. Padovan 
205694122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
205794122bbeSMat Martineau 		return 0;
205894122bbeSMat Martineau 
2059b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2060b99e13adSMat Martineau 		return 0;
2061b99e13adSMat Martineau 
206218a48e76SMat Martineau 	while (chan->tx_send_head &&
206318a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
206418a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
20650a708f8fSGustavo F. Padovan 
206618a48e76SMat Martineau 		skb = chan->tx_send_head;
20670a708f8fSGustavo F. Padovan 
206818a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
206918a48e76SMat Martineau 		control = &bt_cb(skb)->control;
20700a708f8fSGustavo F. Padovan 
2071e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
207218a48e76SMat Martineau 			control->final = 1;
2073e2ab4353SGustavo F. Padovan 
207418a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
207518a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
207618a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
20770a708f8fSGustavo F. Padovan 
207818a48e76SMat Martineau 		__pack_control(chan, control, skb);
20790a708f8fSGustavo F. Padovan 
208047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
208118a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
208218a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20830a708f8fSGustavo F. Padovan 		}
20840a708f8fSGustavo F. Padovan 
208518a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
208618a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
208718a48e76SMat Martineau 		 */
208818a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
208918a48e76SMat Martineau 
209018a48e76SMat Martineau 		if (!tx_skb)
209118a48e76SMat Martineau 			break;
20920a708f8fSGustavo F. Padovan 
20931a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
20940a708f8fSGustavo F. Padovan 
2095836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20966a026610SGustavo F. Padovan 		chan->unacked_frames++;
20976a026610SGustavo F. Padovan 		chan->frames_sent++;
209818a48e76SMat Martineau 		sent++;
20990a708f8fSGustavo F. Padovan 
210058d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
210158d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21020a708f8fSGustavo F. Padovan 		else
210358d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
210418a48e76SMat Martineau 
210518a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2106b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21070a708f8fSGustavo F. Padovan 	}
21080a708f8fSGustavo F. Padovan 
2109b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2110b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
211118a48e76SMat Martineau 
211218a48e76SMat Martineau 	return sent;
21130a708f8fSGustavo F. Padovan }
21140a708f8fSGustavo F. Padovan 
2115e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2116e1fbd4c1SMat Martineau {
2117e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2118e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2119e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2120e1fbd4c1SMat Martineau 	u16 seq;
2121e1fbd4c1SMat Martineau 
2122e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2123e1fbd4c1SMat Martineau 
2124e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2125e1fbd4c1SMat Martineau 		return;
2126e1fbd4c1SMat Martineau 
2127b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2128b99e13adSMat Martineau 		return;
2129b99e13adSMat Martineau 
2130e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2131e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2132e1fbd4c1SMat Martineau 
2133e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2134e1fbd4c1SMat Martineau 		if (!skb) {
2135e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2136e1fbd4c1SMat Martineau 			       seq);
2137e1fbd4c1SMat Martineau 			continue;
2138e1fbd4c1SMat Martineau 		}
2139e1fbd4c1SMat Martineau 
2140e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
2141e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
2142e1fbd4c1SMat Martineau 
2143e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2144e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
2145e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21465e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2147e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2148e1fbd4c1SMat Martineau 			break;
2149e1fbd4c1SMat Martineau 		}
2150e1fbd4c1SMat Martineau 
2151e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2152e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2153e1fbd4c1SMat Martineau 			control.final = 1;
2154e1fbd4c1SMat Martineau 		else
2155e1fbd4c1SMat Martineau 			control.final = 0;
2156e1fbd4c1SMat Martineau 
2157e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2158e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2159e1fbd4c1SMat Martineau 			 * writeable copy
2160e1fbd4c1SMat Martineau 			 */
21618bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2162e1fbd4c1SMat Martineau 		} else {
21638bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2164e1fbd4c1SMat Martineau 		}
2165e1fbd4c1SMat Martineau 
2166e1fbd4c1SMat Martineau 		if (!tx_skb) {
2167e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2168e1fbd4c1SMat Martineau 			break;
2169e1fbd4c1SMat Martineau 		}
2170e1fbd4c1SMat Martineau 
2171e1fbd4c1SMat Martineau 		/* Update skb contents */
2172e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2173e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2174e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2175e1fbd4c1SMat Martineau 		} else {
2176e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2177e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2178e1fbd4c1SMat Martineau 		}
2179e1fbd4c1SMat Martineau 
2180e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
2181e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
2182e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
2183e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
2184e1fbd4c1SMat Martineau 		}
2185e1fbd4c1SMat Martineau 
2186e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2187e1fbd4c1SMat Martineau 
2188e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2189e1fbd4c1SMat Martineau 
2190e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2191e1fbd4c1SMat Martineau 	}
2192e1fbd4c1SMat Martineau }
2193e1fbd4c1SMat Martineau 
2194f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2195f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2196f80842a8SMat Martineau {
2197f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2198f80842a8SMat Martineau 
2199f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2200f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2201f80842a8SMat Martineau }
2202f80842a8SMat Martineau 
2203d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2204d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2205d2a7ac5dSMat Martineau {
2206e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2207e1fbd4c1SMat Martineau 
2208e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2209e1fbd4c1SMat Martineau 
2210e1fbd4c1SMat Martineau 	if (control->poll)
2211e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2212e1fbd4c1SMat Martineau 
2213e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2214e1fbd4c1SMat Martineau 
2215e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2216e1fbd4c1SMat Martineau 		return;
2217e1fbd4c1SMat Martineau 
2218e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2219e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2220e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
2221e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2222e1fbd4c1SMat Martineau 				break;
2223e1fbd4c1SMat Martineau 		}
2224e1fbd4c1SMat Martineau 
2225e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2226e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2227e1fbd4c1SMat Martineau 				break;
2228e1fbd4c1SMat Martineau 
2229e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2230e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
2231e1fbd4c1SMat Martineau 		}
2232e1fbd4c1SMat Martineau 
2233e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2234e1fbd4c1SMat Martineau 	}
2235d2a7ac5dSMat Martineau }
2236d2a7ac5dSMat Martineau 
2237b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2238b17e73bbSSzymon Janc {
22390a0aba42SMat Martineau 	struct l2cap_ctrl control;
22400a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22410a0aba42SMat Martineau 					 chan->last_acked_seq);
22420a0aba42SMat Martineau 	int threshold;
22430a0aba42SMat Martineau 
22440a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22450a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22460a0aba42SMat Martineau 
22470a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22480a0aba42SMat Martineau 	control.sframe = 1;
22490a0aba42SMat Martineau 
22500a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22510a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2252b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22530a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22540a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22550a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22560a0aba42SMat Martineau 	} else {
22570a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22580a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22590a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22600a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22610a0aba42SMat Martineau 				frames_to_ack = 0;
22620a0aba42SMat Martineau 		}
22630a0aba42SMat Martineau 
2264c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
22650a0aba42SMat Martineau 		 * Calculate without mul or div
22660a0aba42SMat Martineau 		 */
2267c20f8e35SMat Martineau 		threshold = chan->ack_win;
22680a0aba42SMat Martineau 		threshold += threshold << 1;
22690a0aba42SMat Martineau 		threshold >>= 2;
22700a0aba42SMat Martineau 
2271b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
22720a0aba42SMat Martineau 		       threshold);
22730a0aba42SMat Martineau 
22740a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
22750a0aba42SMat Martineau 			__clear_ack_timer(chan);
22760a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
22770a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
22780a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
22790a0aba42SMat Martineau 			frames_to_ack = 0;
22800a0aba42SMat Martineau 		}
22810a0aba42SMat Martineau 
22820a0aba42SMat Martineau 		if (frames_to_ack)
22830a0aba42SMat Martineau 			__set_ack_timer(chan);
22840a0aba42SMat Martineau 	}
2285b17e73bbSSzymon Janc }
2286b17e73bbSSzymon Janc 
228704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
228804124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
228904124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
22900a708f8fSGustavo F. Padovan {
22910952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
22920a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
229390338947SGustavo Padovan 	int sent = 0;
22940a708f8fSGustavo F. Padovan 
22950a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
22960a708f8fSGustavo F. Padovan 		return -EFAULT;
22970a708f8fSGustavo F. Padovan 
22980a708f8fSGustavo F. Padovan 	sent += count;
22990a708f8fSGustavo F. Padovan 	len  -= count;
23000a708f8fSGustavo F. Padovan 
23010a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23020a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23030a708f8fSGustavo F. Padovan 	while (len) {
2304fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2305fbe00700SGustavo Padovan 
23060a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23070a708f8fSGustavo F. Padovan 
2308fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
230990338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2310fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2311fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23122f7719ceSAndrei Emeltchenko 
2313fbe00700SGustavo Padovan 		*frag = tmp;
2314fbe00700SGustavo Padovan 
23150a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
23160a708f8fSGustavo F. Padovan 			return -EFAULT;
23170a708f8fSGustavo F. Padovan 
23185e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
23195e59b791SLuiz Augusto von Dentz 
23200a708f8fSGustavo F. Padovan 		sent += count;
23210a708f8fSGustavo F. Padovan 		len  -= count;
23220a708f8fSGustavo F. Padovan 
23232d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23242d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23252d0ed3d5SGustavo Padovan 
23260a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23270a708f8fSGustavo F. Padovan 	}
23280a708f8fSGustavo F. Padovan 
23290a708f8fSGustavo F. Padovan 	return sent;
23300a708f8fSGustavo F. Padovan }
23310a708f8fSGustavo F. Padovan 
23325e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23335e59b791SLuiz Augusto von Dentz 						 struct msghdr *msg, size_t len,
23345e59b791SLuiz Augusto von Dentz 						 u32 priority)
23350a708f8fSGustavo F. Padovan {
23368c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23370a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
233803a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23390a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23400a708f8fSGustavo F. Padovan 
234143b1b8dfSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
234243b1b8dfSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len, priority);
23430a708f8fSGustavo F. Padovan 
23440a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23452f7719ceSAndrei Emeltchenko 
23462f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
234790338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
234890338947SGustavo Padovan 	if (IS_ERR(skb))
234990338947SGustavo Padovan 		return skb;
23500a708f8fSGustavo F. Padovan 
23515e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23525e59b791SLuiz Augusto von Dentz 
23530a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23540a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2355fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2356daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
235743b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23580a708f8fSGustavo F. Padovan 
23590952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23600a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23610a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23620a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23630a708f8fSGustavo F. Padovan 	}
23640a708f8fSGustavo F. Padovan 	return skb;
23650a708f8fSGustavo F. Padovan }
23660a708f8fSGustavo F. Padovan 
23675e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
23685e59b791SLuiz Augusto von Dentz 					      struct msghdr *msg, size_t len,
23695e59b791SLuiz Augusto von Dentz 					      u32 priority)
23700a708f8fSGustavo F. Padovan {
23718c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23720a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2373f2ba7faeSGustavo Padovan 	int err, count;
23740a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23750a708f8fSGustavo F. Padovan 
2376b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
23770a708f8fSGustavo F. Padovan 
2378f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
23792f7719ceSAndrei Emeltchenko 
2380f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
238190338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
238290338947SGustavo Padovan 	if (IS_ERR(skb))
238390338947SGustavo Padovan 		return skb;
23840a708f8fSGustavo F. Padovan 
23855e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23865e59b791SLuiz Augusto von Dentz 
23870a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23880a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2389fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
23906ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
23910a708f8fSGustavo F. Padovan 
23920952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23930a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23940a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23950a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23960a708f8fSGustavo F. Padovan 	}
23970a708f8fSGustavo F. Padovan 	return skb;
23980a708f8fSGustavo F. Padovan }
23990a708f8fSGustavo F. Padovan 
2400ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2401ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
240294122bbeSMat Martineau 					       u16 sdulen)
24030a708f8fSGustavo F. Padovan {
24048c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24050a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2406e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24070a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24080a708f8fSGustavo F. Padovan 
2409b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24100a708f8fSGustavo F. Padovan 
24110a708f8fSGustavo F. Padovan 	if (!conn)
24120a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24130a708f8fSGustavo F. Padovan 
2414ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2415e4ca6d98SAndrei Emeltchenko 
24160a708f8fSGustavo F. Padovan 	if (sdulen)
241703a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24180a708f8fSGustavo F. Padovan 
241947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
242003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24210a708f8fSGustavo F. Padovan 
24220a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24232f7719ceSAndrei Emeltchenko 
24242f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
242590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
242690338947SGustavo Padovan 	if (IS_ERR(skb))
242790338947SGustavo Padovan 		return skb;
24280a708f8fSGustavo F. Padovan 
24290a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24300a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2431fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24320a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
243388843ab0SAndrei Emeltchenko 
243418a48e76SMat Martineau 	/* Control header is populated later */
243518a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
243618a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
243718a48e76SMat Martineau 	else
243818a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
243988843ab0SAndrei Emeltchenko 
24400a708f8fSGustavo F. Padovan 	if (sdulen)
244103a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24420a708f8fSGustavo F. Padovan 
24430952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24440a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24450a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24460a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24470a708f8fSGustavo F. Padovan 	}
24480a708f8fSGustavo F. Padovan 
244918a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
24503ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
24510a708f8fSGustavo F. Padovan 	return skb;
24520a708f8fSGustavo F. Padovan }
24530a708f8fSGustavo F. Padovan 
245494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
245594122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
245694122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24570a708f8fSGustavo F. Padovan {
24580a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
245994122bbeSMat Martineau 	u16 sdu_len;
246094122bbeSMat Martineau 	size_t pdu_len;
246194122bbeSMat Martineau 	u8 sar;
24620a708f8fSGustavo F. Padovan 
2463b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24640a708f8fSGustavo F. Padovan 
246594122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
246694122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
246794122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
246894122bbeSMat Martineau 	 */
246994122bbeSMat Martineau 
247094122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
247194122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
247294122bbeSMat Martineau 
2473a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2474a549574dSMat Martineau 	if (!chan->hs_hcon)
247594122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
247694122bbeSMat Martineau 
247794122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
247835d401dfSGustavo Padovan 	if (chan->fcs)
247935d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
248035d401dfSGustavo Padovan 
2481ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
248294122bbeSMat Martineau 
248394122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
248494122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
248594122bbeSMat Martineau 
248694122bbeSMat Martineau 	if (len <= pdu_len) {
248794122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
248894122bbeSMat Martineau 		sdu_len = 0;
248994122bbeSMat Martineau 		pdu_len = len;
249094122bbeSMat Martineau 	} else {
249194122bbeSMat Martineau 		sar = L2CAP_SAR_START;
249294122bbeSMat Martineau 		sdu_len = len;
249394122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
249494122bbeSMat Martineau 	}
24950a708f8fSGustavo F. Padovan 
24960a708f8fSGustavo F. Padovan 	while (len > 0) {
249794122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
24980a708f8fSGustavo F. Padovan 
24990a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
250094122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25010a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25020a708f8fSGustavo F. Padovan 		}
25030a708f8fSGustavo F. Padovan 
250494122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
250594122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25060a708f8fSGustavo F. Padovan 
250794122bbeSMat Martineau 		len -= pdu_len;
250894122bbeSMat Martineau 		if (sdu_len) {
250994122bbeSMat Martineau 			sdu_len = 0;
251094122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
251194122bbeSMat Martineau 		}
251294122bbeSMat Martineau 
251394122bbeSMat Martineau 		if (len <= pdu_len) {
251494122bbeSMat Martineau 			sar = L2CAP_SAR_END;
251594122bbeSMat Martineau 			pdu_len = len;
251694122bbeSMat Martineau 		} else {
251794122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
251894122bbeSMat Martineau 		}
251994122bbeSMat Martineau 	}
252094122bbeSMat Martineau 
2521f0f62799SGustavo Padovan 	return 0;
25220a708f8fSGustavo F. Padovan }
25230a708f8fSGustavo F. Padovan 
25245e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
25255e59b791SLuiz Augusto von Dentz 		    u32 priority)
25269a91a04aSGustavo F. Padovan {
25279a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
25289a91a04aSGustavo F. Padovan 	int err;
252994122bbeSMat Martineau 	struct sk_buff_head seg_queue;
25309a91a04aSGustavo F. Padovan 
253131e8ce80SSeung-Woo Kim 	if (!chan->conn)
253231e8ce80SSeung-Woo Kim 		return -ENOTCONN;
253331e8ce80SSeung-Woo Kim 
25349a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2535715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
25365e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
25379a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25389a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25399a91a04aSGustavo F. Padovan 
25409a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25419a91a04aSGustavo F. Padovan 		return len;
25429a91a04aSGustavo F. Padovan 	}
25439a91a04aSGustavo F. Padovan 
25449a91a04aSGustavo F. Padovan 	switch (chan->mode) {
25459a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
254638319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
25479a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
25489a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
25499a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
25509a91a04aSGustavo F. Padovan 
25519a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
25525e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
25539a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25549a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25559a91a04aSGustavo F. Padovan 
25569a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25579a91a04aSGustavo F. Padovan 		err = len;
25589a91a04aSGustavo F. Padovan 		break;
25599a91a04aSGustavo F. Padovan 
25609a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
25619a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
256294122bbeSMat Martineau 		/* Check outgoing MTU */
256394122bbeSMat Martineau 		if (len > chan->omtu) {
256494122bbeSMat Martineau 			err = -EMSGSIZE;
25659a91a04aSGustavo F. Padovan 			break;
25669a91a04aSGustavo F. Padovan 		}
25679a91a04aSGustavo F. Padovan 
256894122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
256994122bbeSMat Martineau 
257094122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
257194122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
257294122bbeSMat Martineau 		 * allocation.
257394122bbeSMat Martineau 		 */
257494122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
257594122bbeSMat Martineau 
257694122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
257794122bbeSMat Martineau 		 * check that it is still connected.
257894122bbeSMat Martineau 		 */
257994122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
258094122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
258194122bbeSMat Martineau 			err = -ENOTCONN;
25829a91a04aSGustavo F. Padovan 		}
25839a91a04aSGustavo F. Padovan 
258494122bbeSMat Martineau 		if (err)
258594122bbeSMat Martineau 			break;
258694122bbeSMat Martineau 
25873733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2588d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
25893733937dSMat Martineau 		else
2590d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
259194122bbeSMat Martineau 
25929a91a04aSGustavo F. Padovan 		err = len;
25939a91a04aSGustavo F. Padovan 
259494122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
259594122bbeSMat Martineau 		 * seg_queue and need to be purged.
259694122bbeSMat Martineau 		 */
259794122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
25989a91a04aSGustavo F. Padovan 		break;
25999a91a04aSGustavo F. Padovan 
26009a91a04aSGustavo F. Padovan 	default:
26019a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
26029a91a04aSGustavo F. Padovan 		err = -EBADFD;
26039a91a04aSGustavo F. Padovan 	}
26049a91a04aSGustavo F. Padovan 
26059a91a04aSGustavo F. Padovan 	return err;
26069a91a04aSGustavo F. Padovan }
26079a91a04aSGustavo F. Padovan 
2608d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2609d2a7ac5dSMat Martineau {
2610bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2611bed68bdeSMat Martineau 	u16 seq;
2612bed68bdeSMat Martineau 
2613b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2614bed68bdeSMat Martineau 
2615bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2616bed68bdeSMat Martineau 	control.sframe = 1;
2617bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2618bed68bdeSMat Martineau 
2619bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2620bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2621bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2622bed68bdeSMat Martineau 			control.reqseq = seq;
2623bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2624bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2625bed68bdeSMat Martineau 		}
2626bed68bdeSMat Martineau 	}
2627bed68bdeSMat Martineau 
2628bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2629d2a7ac5dSMat Martineau }
2630d2a7ac5dSMat Martineau 
2631d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2632d2a7ac5dSMat Martineau {
2633bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2634bed68bdeSMat Martineau 
2635bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2636bed68bdeSMat Martineau 
2637bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2638bed68bdeSMat Martineau 		return;
2639bed68bdeSMat Martineau 
2640bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2641bed68bdeSMat Martineau 	control.sframe = 1;
2642bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2643bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2644bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2645d2a7ac5dSMat Martineau }
2646d2a7ac5dSMat Martineau 
2647d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2648d2a7ac5dSMat Martineau {
2649bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2650bed68bdeSMat Martineau 	u16 initial_head;
2651bed68bdeSMat Martineau 	u16 seq;
2652bed68bdeSMat Martineau 
2653b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2654bed68bdeSMat Martineau 
2655bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2656bed68bdeSMat Martineau 	control.sframe = 1;
2657bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2658bed68bdeSMat Martineau 
2659bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2660bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2661bed68bdeSMat Martineau 
2662bed68bdeSMat Martineau 	do {
2663bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2664bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2665bed68bdeSMat Martineau 			break;
2666bed68bdeSMat Martineau 
2667bed68bdeSMat Martineau 		control.reqseq = seq;
2668bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2669bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2670bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2671d2a7ac5dSMat Martineau }
2672d2a7ac5dSMat Martineau 
2673608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2674608bcc6dSMat Martineau {
2675608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2676608bcc6dSMat Martineau 	u16 ackseq;
2677608bcc6dSMat Martineau 
2678b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2679608bcc6dSMat Martineau 
2680608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2681608bcc6dSMat Martineau 		return;
2682608bcc6dSMat Martineau 
2683b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2684608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2685608bcc6dSMat Martineau 
2686608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2687608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2688608bcc6dSMat Martineau 
2689608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2690608bcc6dSMat Martineau 		if (acked_skb) {
2691608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2692608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2693608bcc6dSMat Martineau 			chan->unacked_frames--;
2694608bcc6dSMat Martineau 		}
2695608bcc6dSMat Martineau 	}
2696608bcc6dSMat Martineau 
2697608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2698608bcc6dSMat Martineau 
2699608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2700608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2701608bcc6dSMat Martineau 
2702b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2703608bcc6dSMat Martineau }
2704608bcc6dSMat Martineau 
2705608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2706608bcc6dSMat Martineau {
2707608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2708608bcc6dSMat Martineau 
2709608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2710608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2711608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2712608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2713608bcc6dSMat Martineau }
2714608bcc6dSMat Martineau 
2715d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2716608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2717608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2718608bcc6dSMat Martineau {
2719608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2720608bcc6dSMat Martineau 	       event);
2721608bcc6dSMat Martineau 
2722608bcc6dSMat Martineau 	switch (event) {
2723608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2724608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2725608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2726608bcc6dSMat Martineau 
2727608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2728608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2729608bcc6dSMat Martineau 		break;
2730608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2731608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2732608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2733608bcc6dSMat Martineau 
2734608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2735608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2736608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2737608bcc6dSMat Martineau 			 */
2738608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2739608bcc6dSMat Martineau 		}
2740608bcc6dSMat Martineau 
2741608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2742608bcc6dSMat Martineau 
2743608bcc6dSMat Martineau 		break;
2744608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2745608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2746608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2747608bcc6dSMat Martineau 
2748608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2749608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2750608bcc6dSMat Martineau 
2751608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2752608bcc6dSMat Martineau 			local_control.sframe = 1;
2753608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2754608bcc6dSMat Martineau 			local_control.poll = 1;
2755608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2756a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2757608bcc6dSMat Martineau 
2758608bcc6dSMat Martineau 			chan->retry_count = 1;
2759608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2760608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2761608bcc6dSMat Martineau 		}
2762608bcc6dSMat Martineau 		break;
2763608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2764608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2765608bcc6dSMat Martineau 		break;
2766608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2767608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2768608bcc6dSMat Martineau 		chan->retry_count = 1;
2769608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2770608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2771608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2772608bcc6dSMat Martineau 		break;
2773608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2774608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2775608bcc6dSMat Martineau 		chan->retry_count = 1;
2776608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2777608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2778608bcc6dSMat Martineau 		break;
2779608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2780608bcc6dSMat Martineau 		/* Nothing to process */
2781608bcc6dSMat Martineau 		break;
2782608bcc6dSMat Martineau 	default:
2783608bcc6dSMat Martineau 		break;
2784608bcc6dSMat Martineau 	}
2785608bcc6dSMat Martineau }
2786608bcc6dSMat Martineau 
2787d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2788608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2789608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2790608bcc6dSMat Martineau {
2791608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2792608bcc6dSMat Martineau 	       event);
2793608bcc6dSMat Martineau 
2794608bcc6dSMat Martineau 	switch (event) {
2795608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2796608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2797608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2798608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2799608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2800608bcc6dSMat Martineau 		break;
2801608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2802608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2803608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2804608bcc6dSMat Martineau 
2805608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2806608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2807608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2808608bcc6dSMat Martineau 			 */
2809608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2810608bcc6dSMat Martineau 		}
2811608bcc6dSMat Martineau 
2812608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2813608bcc6dSMat Martineau 
2814608bcc6dSMat Martineau 		break;
2815608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2816608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2817608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2818608bcc6dSMat Martineau 
2819608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2820608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2821608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2822608bcc6dSMat Martineau 			local_control.sframe = 1;
2823608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2824608bcc6dSMat Martineau 			local_control.poll = 1;
2825608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2826a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2827608bcc6dSMat Martineau 
2828608bcc6dSMat Martineau 			chan->retry_count = 1;
2829608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2830608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2831608bcc6dSMat Martineau 		}
2832608bcc6dSMat Martineau 		break;
2833608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2834608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2835608bcc6dSMat Martineau 
2836608bcc6dSMat Martineau 		/* Fall through */
2837608bcc6dSMat Martineau 
2838608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2839608bcc6dSMat Martineau 		if (control && control->final) {
2840608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2841608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2842608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2843608bcc6dSMat Martineau 			chan->retry_count = 0;
2844608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2845608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2846608bcc6dSMat Martineau 		}
2847608bcc6dSMat Martineau 		break;
2848608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2849608bcc6dSMat Martineau 		/* Ignore */
2850608bcc6dSMat Martineau 		break;
2851608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2852608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2853608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2854608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2855608bcc6dSMat Martineau 			chan->retry_count++;
2856608bcc6dSMat Martineau 		} else {
28575e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
2858608bcc6dSMat Martineau 		}
2859608bcc6dSMat Martineau 		break;
2860608bcc6dSMat Martineau 	default:
2861608bcc6dSMat Martineau 		break;
2862608bcc6dSMat Martineau 	}
2863608bcc6dSMat Martineau }
2864608bcc6dSMat Martineau 
2865d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2866608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2867608bcc6dSMat Martineau {
2868608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2869608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2870608bcc6dSMat Martineau 
2871608bcc6dSMat Martineau 	switch (chan->tx_state) {
2872608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2873d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2874608bcc6dSMat Martineau 		break;
2875608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2876d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2877608bcc6dSMat Martineau 		break;
2878608bcc6dSMat Martineau 	default:
2879608bcc6dSMat Martineau 		/* Ignore event */
2880608bcc6dSMat Martineau 		break;
2881608bcc6dSMat Martineau 	}
2882608bcc6dSMat Martineau }
2883608bcc6dSMat Martineau 
28844b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
28854b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
28864b51dae9SMat Martineau {
28874b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2888401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
28894b51dae9SMat Martineau }
28904b51dae9SMat Martineau 
2891f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2892f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2893f80842a8SMat Martineau {
2894f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2895401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2896f80842a8SMat Martineau }
2897f80842a8SMat Martineau 
28980a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
28990a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
29000a708f8fSGustavo F. Padovan {
29010a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
290248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
29030a708f8fSGustavo F. Padovan 
29040a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
29050a708f8fSGustavo F. Padovan 
29063df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
29073d57dc68SGustavo F. Padovan 
29083df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
2909715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
29100a708f8fSGustavo F. Padovan 			continue;
29110a708f8fSGustavo F. Padovan 
29127f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
29137f5396a7SGustavo Padovan 		if (bt_cb(skb)->chan == chan)
29140a708f8fSGustavo F. Padovan 			continue;
29157f5396a7SGustavo Padovan 
29168bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
29170a708f8fSGustavo F. Padovan 		if (!nskb)
29180a708f8fSGustavo F. Padovan 			continue;
291980b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
29200a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
29210a708f8fSGustavo F. Padovan 	}
29223d57dc68SGustavo F. Padovan 
29233df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
29240a708f8fSGustavo F. Padovan }
29250a708f8fSGustavo F. Padovan 
29260a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
2927b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2928b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
29290a708f8fSGustavo F. Padovan {
29300a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
29310a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
29320a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
29330a708f8fSGustavo F. Padovan 	int len, count;
29340a708f8fSGustavo F. Padovan 
2935b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29360a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
29370a708f8fSGustavo F. Padovan 
2938300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2939300b962eSAnderson Lizardo 		return NULL;
2940300b962eSAnderson Lizardo 
29410a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29420a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
29430a708f8fSGustavo F. Padovan 
29448bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
29450a708f8fSGustavo F. Padovan 	if (!skb)
29460a708f8fSGustavo F. Padovan 		return NULL;
29470a708f8fSGustavo F. Padovan 
29480a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
29490a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29503300d9a9SClaudio Takahasi 
29513300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
2952ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29533300d9a9SClaudio Takahasi 	else
2954ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
29550a708f8fSGustavo F. Padovan 
29560a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
29570a708f8fSGustavo F. Padovan 	cmd->code  = code;
29580a708f8fSGustavo F. Padovan 	cmd->ident = ident;
29590a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
29600a708f8fSGustavo F. Padovan 
29610a708f8fSGustavo F. Padovan 	if (dlen) {
29620a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
29630a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
29640a708f8fSGustavo F. Padovan 		data += count;
29650a708f8fSGustavo F. Padovan 	}
29660a708f8fSGustavo F. Padovan 
29670a708f8fSGustavo F. Padovan 	len -= skb->len;
29680a708f8fSGustavo F. Padovan 
29690a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
29700a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
29710a708f8fSGustavo F. Padovan 	while (len) {
29720a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
29730a708f8fSGustavo F. Padovan 
29748bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
29750a708f8fSGustavo F. Padovan 		if (!*frag)
29760a708f8fSGustavo F. Padovan 			goto fail;
29770a708f8fSGustavo F. Padovan 
29780a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
29790a708f8fSGustavo F. Padovan 
29800a708f8fSGustavo F. Padovan 		len  -= count;
29810a708f8fSGustavo F. Padovan 		data += count;
29820a708f8fSGustavo F. Padovan 
29830a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
29840a708f8fSGustavo F. Padovan 	}
29850a708f8fSGustavo F. Padovan 
29860a708f8fSGustavo F. Padovan 	return skb;
29870a708f8fSGustavo F. Padovan 
29880a708f8fSGustavo F. Padovan fail:
29890a708f8fSGustavo F. Padovan 	kfree_skb(skb);
29900a708f8fSGustavo F. Padovan 	return NULL;
29910a708f8fSGustavo F. Padovan }
29920a708f8fSGustavo F. Padovan 
29932d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
29942d792818SGustavo Padovan 				     unsigned long *val)
29950a708f8fSGustavo F. Padovan {
29960a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
29970a708f8fSGustavo F. Padovan 	int len;
29980a708f8fSGustavo F. Padovan 
29990a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
30000a708f8fSGustavo F. Padovan 	*ptr += len;
30010a708f8fSGustavo F. Padovan 
30020a708f8fSGustavo F. Padovan 	*type = opt->type;
30030a708f8fSGustavo F. Padovan 	*olen = opt->len;
30040a708f8fSGustavo F. Padovan 
30050a708f8fSGustavo F. Padovan 	switch (opt->len) {
30060a708f8fSGustavo F. Padovan 	case 1:
30070a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
30080a708f8fSGustavo F. Padovan 		break;
30090a708f8fSGustavo F. Padovan 
30100a708f8fSGustavo F. Padovan 	case 2:
30110a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
30120a708f8fSGustavo F. Padovan 		break;
30130a708f8fSGustavo F. Padovan 
30140a708f8fSGustavo F. Padovan 	case 4:
30150a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
30160a708f8fSGustavo F. Padovan 		break;
30170a708f8fSGustavo F. Padovan 
30180a708f8fSGustavo F. Padovan 	default:
30190a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
30200a708f8fSGustavo F. Padovan 		break;
30210a708f8fSGustavo F. Padovan 	}
30220a708f8fSGustavo F. Padovan 
3023b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30240a708f8fSGustavo F. Padovan 	return len;
30250a708f8fSGustavo F. Padovan }
30260a708f8fSGustavo F. Padovan 
30270a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
30280a708f8fSGustavo F. Padovan {
30290a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
30300a708f8fSGustavo F. Padovan 
3031b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30320a708f8fSGustavo F. Padovan 
30330a708f8fSGustavo F. Padovan 	opt->type = type;
30340a708f8fSGustavo F. Padovan 	opt->len  = len;
30350a708f8fSGustavo F. Padovan 
30360a708f8fSGustavo F. Padovan 	switch (len) {
30370a708f8fSGustavo F. Padovan 	case 1:
30380a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
30390a708f8fSGustavo F. Padovan 		break;
30400a708f8fSGustavo F. Padovan 
30410a708f8fSGustavo F. Padovan 	case 2:
30420a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
30430a708f8fSGustavo F. Padovan 		break;
30440a708f8fSGustavo F. Padovan 
30450a708f8fSGustavo F. Padovan 	case 4:
30460a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
30470a708f8fSGustavo F. Padovan 		break;
30480a708f8fSGustavo F. Padovan 
30490a708f8fSGustavo F. Padovan 	default:
30500a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
30510a708f8fSGustavo F. Padovan 		break;
30520a708f8fSGustavo F. Padovan 	}
30530a708f8fSGustavo F. Padovan 
30540a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
30550a708f8fSGustavo F. Padovan }
30560a708f8fSGustavo F. Padovan 
3057f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
3058f89cef09SAndrei Emeltchenko {
3059f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3060f89cef09SAndrei Emeltchenko 
3061f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3062f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3063f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3064f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3065f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3066f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3067ac73498cSAndrei Emeltchenko 		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
30688936fa6dSAndrei Emeltchenko 		efs.flush_to	= __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3069f89cef09SAndrei Emeltchenko 		break;
3070f89cef09SAndrei Emeltchenko 
3071f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3072f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3073f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3074f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3075f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3076f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3077f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3078f89cef09SAndrei Emeltchenko 		break;
3079f89cef09SAndrei Emeltchenko 
3080f89cef09SAndrei Emeltchenko 	default:
3081f89cef09SAndrei Emeltchenko 		return;
3082f89cef09SAndrei Emeltchenko 	}
3083f89cef09SAndrei Emeltchenko 
3084f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3085f89cef09SAndrei Emeltchenko 			   (unsigned long) &efs);
3086f89cef09SAndrei Emeltchenko }
3087f89cef09SAndrei Emeltchenko 
3088721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
30890a708f8fSGustavo F. Padovan {
3090721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3091721c4181SGustavo F. Padovan 					       ack_timer.work);
30920362520bSMat Martineau 	u16 frames_to_ack;
30930a708f8fSGustavo F. Padovan 
30942fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
30952fb9b3d4SGustavo F. Padovan 
30966be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
30976be36555SAndrei Emeltchenko 
30980362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
30990362520bSMat Martineau 				     chan->last_acked_seq);
31000362520bSMat Martineau 
31010362520bSMat Martineau 	if (frames_to_ack)
31020362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
31036be36555SAndrei Emeltchenko 
31046be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
310509bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
31060a708f8fSGustavo F. Padovan }
31070a708f8fSGustavo F. Padovan 
3108466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
31090a708f8fSGustavo F. Padovan {
31103c588192SMat Martineau 	int err;
31113c588192SMat Martineau 
3112105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3113105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
311442e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
31156a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
311642e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
31176a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3118105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3119105bdf9eSMat Martineau 	chan->sdu = NULL;
3120105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3121105bdf9eSMat Martineau 	chan->sdu_len = 0;
3122105bdf9eSMat Martineau 
3123d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3124d34c34fbSMat Martineau 
31256ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
31266ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
312708333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
312808333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
312908333283SMat Martineau 
3130105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3131105bdf9eSMat Martineau 		return 0;
3132105bdf9eSMat Martineau 
3133105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3134105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
31350a708f8fSGustavo F. Padovan 
3136721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3137721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3138721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
31390a708f8fSGustavo F. Padovan 
3140f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
31410a708f8fSGustavo F. Padovan 
31423c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31433c588192SMat Martineau 	if (err < 0)
31443c588192SMat Martineau 		return err;
31453c588192SMat Martineau 
31469dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31479dc9affcSMat Martineau 	if (err < 0)
31489dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
31499dc9affcSMat Martineau 
31509dc9affcSMat Martineau 	return err;
31510a708f8fSGustavo F. Padovan }
31520a708f8fSGustavo F. Padovan 
31530a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31540a708f8fSGustavo F. Padovan {
31550a708f8fSGustavo F. Padovan 	switch (mode) {
31560a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
31570a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
31580a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
31590a708f8fSGustavo F. Padovan 			return mode;
31600a708f8fSGustavo F. Padovan 		/* fall through */
31610a708f8fSGustavo F. Padovan 	default:
31620a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
31630a708f8fSGustavo F. Padovan 	}
31640a708f8fSGustavo F. Padovan }
31650a708f8fSGustavo F. Padovan 
3166848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31676327eb98SAndrei Emeltchenko {
3168848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
31696327eb98SAndrei Emeltchenko }
31706327eb98SAndrei Emeltchenko 
3171848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3172f89cef09SAndrei Emeltchenko {
3173848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
3174f89cef09SAndrei Emeltchenko }
3175f89cef09SAndrei Emeltchenko 
317636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
317736c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
317836c86c85SMat Martineau {
31796ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
318036c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
318136c86c85SMat Martineau 
318236c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
318336c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
318436c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
318536c86c85SMat Martineau 		 * controllers is 10 seconds.
318636c86c85SMat Martineau 		 *
318736c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
318836c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
318936c86c85SMat Martineau 		 * will result in a timeout that meets the above
319036c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
319136c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
319236c86c85SMat Martineau 		 */
319336c86c85SMat Martineau 
319436c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
319536c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
319636c86c85SMat Martineau 
319736c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
319836c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
319936c86c85SMat Martineau 		 * controller.
320036c86c85SMat Martineau 		 */
320136c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
320236c86c85SMat Martineau 
320336c86c85SMat Martineau 		if (ertm_to > 0xffff)
320436c86c85SMat Martineau 			ertm_to = 0xffff;
320536c86c85SMat Martineau 
320636c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
320736c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
320836c86c85SMat Martineau 	} else {
320936c86c85SMat Martineau 		rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
321036c86c85SMat Martineau 		rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
321136c86c85SMat Martineau 	}
321236c86c85SMat Martineau }
321336c86c85SMat Martineau 
32146327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
32156327eb98SAndrei Emeltchenko {
32166327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3217848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
32186327eb98SAndrei Emeltchenko 		/* use extended control field */
32196327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3220836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3221836be934SAndrei Emeltchenko 	} else {
32226327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
32236327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3224836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3225836be934SAndrei Emeltchenko 	}
3226c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
32276327eb98SAndrei Emeltchenko }
32286327eb98SAndrei Emeltchenko 
3229710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
32300a708f8fSGustavo F. Padovan {
32310a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
32320c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32330a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3234c8f79162SAndrei Emeltchenko 	u16 size;
32350a708f8fSGustavo F. Padovan 
323649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
32370a708f8fSGustavo F. Padovan 
323873ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
32390a708f8fSGustavo F. Padovan 		goto done;
32400a708f8fSGustavo F. Padovan 
32410c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32420a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
32430a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3244c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32450a708f8fSGustavo F. Padovan 			break;
32460a708f8fSGustavo F. Padovan 
3247848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3248f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3249f89cef09SAndrei Emeltchenko 
32500a708f8fSGustavo F. Padovan 		/* fall through */
32510a708f8fSGustavo F. Padovan 	default:
32528c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32530a708f8fSGustavo F. Padovan 		break;
32540a708f8fSGustavo F. Padovan 	}
32550a708f8fSGustavo F. Padovan 
32560a708f8fSGustavo F. Padovan done:
32570c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
32580c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
32590a708f8fSGustavo F. Padovan 
32600c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32610a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
32628c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32638c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32640a708f8fSGustavo F. Padovan 			break;
32650a708f8fSGustavo F. Padovan 
32660a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
32670a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
32680a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
32690a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
32700a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
32710a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
32720a708f8fSGustavo F. Padovan 
32730a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
32740a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
32750a708f8fSGustavo F. Padovan 		break;
32760a708f8fSGustavo F. Padovan 
32770a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
32780a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
327947d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
328036c86c85SMat Martineau 
328136c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3282c8f79162SAndrei Emeltchenko 
3283c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
32842d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3285c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3286c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
32870a708f8fSGustavo F. Padovan 
32886327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
32896327eb98SAndrei Emeltchenko 
32906327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
32916327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
32920a708f8fSGustavo F. Padovan 
32930a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
32940a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
32950a708f8fSGustavo F. Padovan 
3296f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3297f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3298f89cef09SAndrei Emeltchenko 
32996327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
33006327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
33016327eb98SAndrei Emeltchenko 					   chan->tx_win);
330260918918SAndrei Emeltchenko 
330360918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
330460918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3305f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
330660918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
330760918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
330860918918SAndrei Emeltchenko 						   chan->fcs);
330960918918SAndrei Emeltchenko 			}
33100a708f8fSGustavo F. Padovan 		break;
33110a708f8fSGustavo F. Padovan 
33120a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3313273759e2SMat Martineau 		l2cap_txwin_setup(chan);
33140a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
33150a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
33160a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
33170a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
33180a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3319c8f79162SAndrei Emeltchenko 
3320c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33212d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3322c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3323c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
33240a708f8fSGustavo F. Padovan 
33250a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
33260a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
33270a708f8fSGustavo F. Padovan 
3328f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3329f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3330f89cef09SAndrei Emeltchenko 
333160918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
333247d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3333f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
333447d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
333560918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
333660918918SAndrei Emeltchenko 						   chan->fcs);
33370a708f8fSGustavo F. Padovan 			}
33380a708f8fSGustavo F. Padovan 		break;
33390a708f8fSGustavo F. Padovan 	}
33400a708f8fSGustavo F. Padovan 
3341fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
334259e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
33430a708f8fSGustavo F. Padovan 
33440a708f8fSGustavo F. Padovan 	return ptr - data;
33450a708f8fSGustavo F. Padovan }
33460a708f8fSGustavo F. Padovan 
334773ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
33480a708f8fSGustavo F. Padovan {
33490a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
33500a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
335173ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
335273ffa904SGustavo F. Padovan 	int len = chan->conf_len;
33530a708f8fSGustavo F. Padovan 	int type, hint, olen;
33540a708f8fSGustavo F. Padovan 	unsigned long val;
33550a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
335642dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
335742dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
33580a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
33590a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3360c8f79162SAndrei Emeltchenko 	u16 size;
33610a708f8fSGustavo F. Padovan 
336273ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
33630a708f8fSGustavo F. Padovan 
33640a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33650a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33660a708f8fSGustavo F. Padovan 
33670a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
33680a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
33690a708f8fSGustavo F. Padovan 
33700a708f8fSGustavo F. Padovan 		switch (type) {
33710a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
33720a708f8fSGustavo F. Padovan 			mtu = val;
33730a708f8fSGustavo F. Padovan 			break;
33740a708f8fSGustavo F. Padovan 
33750a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
33760c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
33770a708f8fSGustavo F. Padovan 			break;
33780a708f8fSGustavo F. Padovan 
33790a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
33800a708f8fSGustavo F. Padovan 			break;
33810a708f8fSGustavo F. Padovan 
33820a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
33830a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
33840a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
33850a708f8fSGustavo F. Padovan 			break;
33860a708f8fSGustavo F. Padovan 
33870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
33880a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3389f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
339042dceae2SAndrei Emeltchenko 			break;
33910a708f8fSGustavo F. Padovan 
339242dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
339342dceae2SAndrei Emeltchenko 			remote_efs = 1;
339442dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
339542dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
33960a708f8fSGustavo F. Padovan 			break;
33970a708f8fSGustavo F. Padovan 
33986327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3399848566b3SMarcel Holtmann 			if (!chan->conn->hs_enabled)
34006327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
34016327eb98SAndrei Emeltchenko 
34026327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
34036327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3404836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
34056327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
34060a708f8fSGustavo F. Padovan 			break;
34070a708f8fSGustavo F. Padovan 
34080a708f8fSGustavo F. Padovan 		default:
34090a708f8fSGustavo F. Padovan 			if (hint)
34100a708f8fSGustavo F. Padovan 				break;
34110a708f8fSGustavo F. Padovan 
34120a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
34130a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
34140a708f8fSGustavo F. Padovan 			break;
34150a708f8fSGustavo F. Padovan 		}
34160a708f8fSGustavo F. Padovan 	}
34170a708f8fSGustavo F. Padovan 
341873ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
34190a708f8fSGustavo F. Padovan 		goto done;
34200a708f8fSGustavo F. Padovan 
34210c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34220a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34230a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3424c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
34250c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
34268c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
34270a708f8fSGustavo F. Padovan 			break;
34280a708f8fSGustavo F. Padovan 		}
34290a708f8fSGustavo F. Padovan 
343042dceae2SAndrei Emeltchenko 		if (remote_efs) {
3431848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
343242dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
343342dceae2SAndrei Emeltchenko 			else
343442dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
343542dceae2SAndrei Emeltchenko 		}
343642dceae2SAndrei Emeltchenko 
34370c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
34380a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34390a708f8fSGustavo F. Padovan 
34400a708f8fSGustavo F. Padovan 		break;
34410a708f8fSGustavo F. Padovan 	}
34420a708f8fSGustavo F. Padovan 
34430a708f8fSGustavo F. Padovan done:
34440c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
34450a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
34460c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
34470a708f8fSGustavo F. Padovan 
344873ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
34490a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34500a708f8fSGustavo F. Padovan 
34512d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34522d792818SGustavo Padovan 				   (unsigned long) &rfc);
34530a708f8fSGustavo F. Padovan 	}
34540a708f8fSGustavo F. Padovan 
34550a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
34560a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
34570a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
34580a708f8fSGustavo F. Padovan 
34590a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
34600a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
34610a708f8fSGustavo F. Padovan 		else {
34620c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3463c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
34640a708f8fSGustavo F. Padovan 		}
34650c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
34660a708f8fSGustavo F. Padovan 
346742dceae2SAndrei Emeltchenko 		if (remote_efs) {
346842dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
346942dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
347042dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
347142dceae2SAndrei Emeltchenko 
347242dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
347342dceae2SAndrei Emeltchenko 
347442dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
347542dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
347642dceae2SAndrei Emeltchenko 
347742dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
347842dceae2SAndrei Emeltchenko 						   sizeof(efs),
347942dceae2SAndrei Emeltchenko 						   (unsigned long) &efs);
34800e8b207eSAndrei Emeltchenko 			} else {
34813e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
34820e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
34830e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
348442dceae2SAndrei Emeltchenko 			}
348542dceae2SAndrei Emeltchenko 		}
348642dceae2SAndrei Emeltchenko 
34870a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
34880a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
348947d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3490c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
34910a708f8fSGustavo F. Padovan 			break;
34920a708f8fSGustavo F. Padovan 
34930a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
34946327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
34952c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
34966327eb98SAndrei Emeltchenko 			else
34976327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
34986327eb98SAndrei Emeltchenko 
34992c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
35000a708f8fSGustavo F. Padovan 
3501c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35022d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35032d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3504c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3505c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35060a708f8fSGustavo F. Padovan 
350736c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
35080a708f8fSGustavo F. Padovan 
3509c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35100a708f8fSGustavo F. Padovan 
35110a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
35120a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
35130a708f8fSGustavo F. Padovan 
351442dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
351542dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
351642dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
351742dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
351842dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
351942dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
352042dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
352142dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
352242dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
352342dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
352442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35252d792818SGustavo Padovan 						   sizeof(efs),
35262d792818SGustavo Padovan 						   (unsigned long) &efs);
352742dceae2SAndrei Emeltchenko 			}
35280a708f8fSGustavo F. Padovan 			break;
35290a708f8fSGustavo F. Padovan 
35300a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3531c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35322d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35332d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3534c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3535c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35360a708f8fSGustavo F. Padovan 
3537c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35380a708f8fSGustavo F. Padovan 
35392d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
35402d792818SGustavo Padovan 					   (unsigned long) &rfc);
35410a708f8fSGustavo F. Padovan 
35420a708f8fSGustavo F. Padovan 			break;
35430a708f8fSGustavo F. Padovan 
35440a708f8fSGustavo F. Padovan 		default:
35450a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
35460a708f8fSGustavo F. Padovan 
35470a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
35480c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
35490a708f8fSGustavo F. Padovan 		}
35500a708f8fSGustavo F. Padovan 
35510a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3552c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35530a708f8fSGustavo F. Padovan 	}
3554fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
35550a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
355659e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
35570a708f8fSGustavo F. Padovan 
35580a708f8fSGustavo F. Padovan 	return ptr - data;
35590a708f8fSGustavo F. Padovan }
35600a708f8fSGustavo F. Padovan 
35612d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
35622d792818SGustavo Padovan 				void *data, u16 *result)
35630a708f8fSGustavo F. Padovan {
35640a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
35650a708f8fSGustavo F. Padovan 	void *ptr = req->data;
35660a708f8fSGustavo F. Padovan 	int type, olen;
35670a708f8fSGustavo F. Padovan 	unsigned long val;
356836e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
356966af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
35700a708f8fSGustavo F. Padovan 
3571fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
35720a708f8fSGustavo F. Padovan 
35730a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35740a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
35750a708f8fSGustavo F. Padovan 
35760a708f8fSGustavo F. Padovan 		switch (type) {
35770a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
35780a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
35790a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
35800c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
35810a708f8fSGustavo F. Padovan 			} else
35820c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
35830c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
35840a708f8fSGustavo F. Padovan 			break;
35850a708f8fSGustavo F. Padovan 
35860a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
35870c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35880a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
35890c1bc5c6SGustavo F. Padovan 					   2, chan->flush_to);
35900a708f8fSGustavo F. Padovan 			break;
35910a708f8fSGustavo F. Padovan 
35920a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
35930a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
35940a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
35950a708f8fSGustavo F. Padovan 
3596c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
35970c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
35980a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
35990a708f8fSGustavo F. Padovan 
360047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
36010a708f8fSGustavo F. Padovan 
36020a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
36030a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
36040a708f8fSGustavo F. Padovan 			break;
36056327eb98SAndrei Emeltchenko 
36066327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3607c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
36083e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
36093e6b3b95SGustavo F. Padovan 					   chan->tx_win);
36106327eb98SAndrei Emeltchenko 			break;
361166af7aafSAndrei Emeltchenko 
361266af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
361366af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
361466af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
361566af7aafSAndrei Emeltchenko 
361666af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
361766af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
361866af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
361966af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
362066af7aafSAndrei Emeltchenko 
36212d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
36222d792818SGustavo Padovan 					   (unsigned long) &efs);
362366af7aafSAndrei Emeltchenko 			break;
3624cbabee78SAndrei Emeltchenko 
3625cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3626cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3627cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3628f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3629cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3630cbabee78SAndrei Emeltchenko 			break;
36310a708f8fSGustavo F. Padovan 		}
36320a708f8fSGustavo F. Padovan 	}
36330a708f8fSGustavo F. Padovan 
36340c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36350a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
36360a708f8fSGustavo F. Padovan 
36370c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
36380a708f8fSGustavo F. Padovan 
36390e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36400a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36410a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
364247d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
364347d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
364447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3645c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3646c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3647c20f8e35SMat Martineau 						      rfc.txwin_size);
364866af7aafSAndrei Emeltchenko 
364966af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
365066af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
365166af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
365266af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
365366af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
365466af7aafSAndrei Emeltchenko 				chan->local_flush_to =
365566af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
365666af7aafSAndrei Emeltchenko 			}
36570a708f8fSGustavo F. Padovan 			break;
365866af7aafSAndrei Emeltchenko 
36590a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
366047d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
36610a708f8fSGustavo F. Padovan 		}
36620a708f8fSGustavo F. Padovan 	}
36630a708f8fSGustavo F. Padovan 
3664fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
366559e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
36660a708f8fSGustavo F. Padovan 
36670a708f8fSGustavo F. Padovan 	return ptr - data;
36680a708f8fSGustavo F. Padovan }
36690a708f8fSGustavo F. Padovan 
36702d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
36712d792818SGustavo Padovan 				u16 result, u16 flags)
36720a708f8fSGustavo F. Padovan {
36730a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
36740a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
36750a708f8fSGustavo F. Padovan 
3676fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
36770a708f8fSGustavo F. Padovan 
3678fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
36790a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
36800a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
36810a708f8fSGustavo F. Padovan 
36820a708f8fSGustavo F. Padovan 	return ptr - data;
36830a708f8fSGustavo F. Padovan }
36840a708f8fSGustavo F. Padovan 
368527e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
368627e2d4c8SJohan Hedberg {
368727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
368827e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
368927e2d4c8SJohan Hedberg 
369027e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
369127e2d4c8SJohan Hedberg 
369227e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
369327e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
369427e2d4c8SJohan Hedberg 	rsp.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
36950cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
369627e2d4c8SJohan Hedberg 	rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
369727e2d4c8SJohan Hedberg 
369827e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
369927e2d4c8SJohan Hedberg 		       &rsp);
370027e2d4c8SJohan Hedberg }
370127e2d4c8SJohan Hedberg 
37028c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3703710f9b0aSGustavo F. Padovan {
3704710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
37058c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3706710f9b0aSGustavo F. Padovan 	u8 buf[128];
3707439f34acSAndrei Emeltchenko 	u8 rsp_code;
3708710f9b0aSGustavo F. Padovan 
3709fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3710fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3711ac73498cSAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3712ac73498cSAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3713439f34acSAndrei Emeltchenko 
3714439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3715439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3716439f34acSAndrei Emeltchenko 	else
3717439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3718439f34acSAndrei Emeltchenko 
3719439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3720439f34acSAndrei Emeltchenko 
3721439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3722710f9b0aSGustavo F. Padovan 
3723c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3724710f9b0aSGustavo F. Padovan 		return;
3725710f9b0aSGustavo F. Padovan 
3726710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3727710f9b0aSGustavo F. Padovan 		       l2cap_build_conf_req(chan, buf), buf);
3728710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3729710f9b0aSGustavo F. Padovan }
3730710f9b0aSGustavo F. Padovan 
373147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
37320a708f8fSGustavo F. Padovan {
37330a708f8fSGustavo F. Padovan 	int type, olen;
37340a708f8fSGustavo F. Padovan 	unsigned long val;
3735c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3736c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3737c20f8e35SMat Martineau 	 */
3738c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3739c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3740c20f8e35SMat Martineau 		.mode = chan->mode,
3741c20f8e35SMat Martineau 		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3742c20f8e35SMat Martineau 		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3743c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3744c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3745c20f8e35SMat Martineau 	};
37460a708f8fSGustavo F. Padovan 
374747d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
37480a708f8fSGustavo F. Padovan 
37490c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
37500a708f8fSGustavo F. Padovan 		return;
37510a708f8fSGustavo F. Padovan 
37520a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37530a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37540a708f8fSGustavo F. Padovan 
3755c20f8e35SMat Martineau 		switch (type) {
3756c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3757c20f8e35SMat Martineau 			if (olen == sizeof(rfc))
37580a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
3759c20f8e35SMat Martineau 			break;
3760c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3761c20f8e35SMat Martineau 			txwin_ext = val;
3762c20f8e35SMat Martineau 			break;
3763c20f8e35SMat Martineau 		}
37640a708f8fSGustavo F. Padovan 	}
37650a708f8fSGustavo F. Padovan 
37660a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
37670a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
376847d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
376947d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
377047d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3771c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3772c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3773c20f8e35SMat Martineau 		else
3774c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3775c20f8e35SMat Martineau 					      rfc.txwin_size);
37760a708f8fSGustavo F. Padovan 		break;
37770a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
377847d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
37790a708f8fSGustavo F. Padovan 	}
37800a708f8fSGustavo F. Padovan }
37810a708f8fSGustavo F. Padovan 
37822d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3783cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3784cb3b3152SJohan Hedberg 				    u8 *data)
37850a708f8fSGustavo F. Padovan {
3786e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
37870a708f8fSGustavo F. Padovan 
3788cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3789cb3b3152SJohan Hedberg 		return -EPROTO;
3790cb3b3152SJohan Hedberg 
3791e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
37920a708f8fSGustavo F. Padovan 		return 0;
37930a708f8fSGustavo F. Padovan 
37940a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
37950a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
379617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
37970a708f8fSGustavo F. Padovan 
37980a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
37990a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
38000a708f8fSGustavo F. Padovan 
38010a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
38020a708f8fSGustavo F. Padovan 	}
38030a708f8fSGustavo F. Padovan 
38040a708f8fSGustavo F. Padovan 	return 0;
38050a708f8fSGustavo F. Padovan }
38060a708f8fSGustavo F. Padovan 
38071700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
38081700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
38094c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
38100a708f8fSGustavo F. Padovan {
38110a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
38120a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
381323691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
38140a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
38150a708f8fSGustavo F. Padovan 
38160a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
38170a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
38180a708f8fSGustavo F. Padovan 
3819097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
38200a708f8fSGustavo F. Padovan 
38210a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
38226f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3823bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
382423691d75SGustavo F. Padovan 	if (!pchan) {
38250a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
38260a708f8fSGustavo F. Padovan 		goto sendresp;
38270a708f8fSGustavo F. Padovan 	}
38280a708f8fSGustavo F. Padovan 
38293df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38308ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
38310a708f8fSGustavo F. Padovan 
38320a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
38332983fd68SAndrei Emeltchenko 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
38340a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
38359f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
38360a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
38370a708f8fSGustavo F. Padovan 		goto response;
38380a708f8fSGustavo F. Padovan 	}
38390a708f8fSGustavo F. Padovan 
38400a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
38410a708f8fSGustavo F. Padovan 
38422dfa1003SGustavo Padovan 	/* Check if we already have channel with that dcid */
38432dfa1003SGustavo Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid))
38442dfa1003SGustavo Padovan 		goto response;
38452dfa1003SGustavo Padovan 
384680b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
384780808e43SGustavo F. Padovan 	if (!chan)
38480a708f8fSGustavo F. Padovan 		goto response;
38490a708f8fSGustavo F. Padovan 
3850330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
3851330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
3852330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
3853330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3854330b6c15SSyam Sidhardhan 	 */
3855330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3856330b6c15SSyam Sidhardhan 
38577eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
38587eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
38594f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
38604f1654e0SMarcel Holtmann 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
3861fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3862fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
38631700915fSMat Martineau 	chan->local_amp_id = amp_id;
38640a708f8fSGustavo F. Padovan 
38656be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
386648454079SGustavo F. Padovan 
3867fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
38680a708f8fSGustavo F. Padovan 
38698d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
38700a708f8fSGustavo F. Padovan 
3871fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
38720a708f8fSGustavo F. Padovan 
38730a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3874d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3875bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
3876f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
38770a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
38780a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
38792dc4e510SGustavo Padovan 				chan->ops->defer(chan);
38800a708f8fSGustavo F. Padovan 			} else {
38811700915fSMat Martineau 				/* Force pending result for AMP controllers.
38821700915fSMat Martineau 				 * The connection will succeed after the
38831700915fSMat Martineau 				 * physical link is up.
38841700915fSMat Martineau 				 */
38856ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
3886f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
38870a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
38886ed971caSMarcel Holtmann 				} else {
3889f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
38906ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
38911700915fSMat Martineau 				}
38920a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
38930a708f8fSGustavo F. Padovan 			}
38940a708f8fSGustavo F. Padovan 		} else {
3895f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
38960a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
38970a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
38980a708f8fSGustavo F. Padovan 		}
38990a708f8fSGustavo F. Padovan 	} else {
3900f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
39010a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
39020a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
39030a708f8fSGustavo F. Padovan 	}
39040a708f8fSGustavo F. Padovan 
39050a708f8fSGustavo F. Padovan response:
39068ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
39073df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
39080a708f8fSGustavo F. Padovan 
39090a708f8fSGustavo F. Padovan sendresp:
39100a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
39110a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
39120a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
39130a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
39144c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
39150a708f8fSGustavo F. Padovan 
39160a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
39170a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
3918ac73498cSAndrei Emeltchenko 		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
39190a708f8fSGustavo F. Padovan 
39200a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
39210a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
39220a708f8fSGustavo F. Padovan 
3923ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
39240a708f8fSGustavo F. Padovan 
39252d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
39262d792818SGustavo Padovan 			       sizeof(info), &info);
39270a708f8fSGustavo F. Padovan 	}
39280a708f8fSGustavo F. Padovan 
3929c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
39300a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
39310a708f8fSGustavo F. Padovan 		u8 buf[128];
3932c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
39330a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
393473ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
393573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
39360a708f8fSGustavo F. Padovan 	}
39371700915fSMat Martineau 
39381700915fSMat Martineau 	return chan;
39394c89b6aaSMat Martineau }
39400a708f8fSGustavo F. Padovan 
39414c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
3942cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
39434c89b6aaSMat Martineau {
39447b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
39457b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
39467b064edaSJaganath Kanakkassery 
3947cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
3948cb3b3152SJohan Hedberg 		return -EPROTO;
3949cb3b3152SJohan Hedberg 
39507b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
39517b064edaSJaganath Kanakkassery 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
39527b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
39537b064edaSJaganath Kanakkassery 		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
39547b064edaSJaganath Kanakkassery 				      hcon->dst_type, 0, NULL, 0,
39557b064edaSJaganath Kanakkassery 				      hcon->dev_class);
39567b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
39577b064edaSJaganath Kanakkassery 
3958300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
39590a708f8fSGustavo F. Padovan 	return 0;
39600a708f8fSGustavo F. Padovan }
39610a708f8fSGustavo F. Padovan 
39625909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
3963cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3964cb3b3152SJohan Hedberg 				    u8 *data)
39650a708f8fSGustavo F. Padovan {
39660a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
39670a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
396848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
39690a708f8fSGustavo F. Padovan 	u8 req[128];
39703df91ea2SAndrei Emeltchenko 	int err;
39710a708f8fSGustavo F. Padovan 
3972cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
3973cb3b3152SJohan Hedberg 		return -EPROTO;
3974cb3b3152SJohan Hedberg 
39750a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
39760a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
39770a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
39780a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
39790a708f8fSGustavo F. Padovan 
39801b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
39811b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
39820a708f8fSGustavo F. Padovan 
39833df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
39843df91ea2SAndrei Emeltchenko 
39850a708f8fSGustavo F. Padovan 	if (scid) {
39863df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
39873df91ea2SAndrei Emeltchenko 		if (!chan) {
398821870b52SJohan Hedberg 			err = -EBADSLT;
39893df91ea2SAndrei Emeltchenko 			goto unlock;
39903df91ea2SAndrei Emeltchenko 		}
39910a708f8fSGustavo F. Padovan 	} else {
39923df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
39933df91ea2SAndrei Emeltchenko 		if (!chan) {
399421870b52SJohan Hedberg 			err = -EBADSLT;
39953df91ea2SAndrei Emeltchenko 			goto unlock;
39963df91ea2SAndrei Emeltchenko 		}
39970a708f8fSGustavo F. Padovan 	}
39980a708f8fSGustavo F. Padovan 
39993df91ea2SAndrei Emeltchenko 	err = 0;
40003df91ea2SAndrei Emeltchenko 
40016be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
400248454079SGustavo F. Padovan 
40030a708f8fSGustavo F. Padovan 	switch (result) {
40040a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
400589bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4006fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4007fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4008c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
40090a708f8fSGustavo F. Padovan 
4010c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
40110a708f8fSGustavo F. Padovan 			break;
40120a708f8fSGustavo F. Padovan 
40130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
401473ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, req), req);
401573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40160a708f8fSGustavo F. Padovan 		break;
40170a708f8fSGustavo F. Padovan 
40180a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4019c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
40200a708f8fSGustavo F. Padovan 		break;
40210a708f8fSGustavo F. Padovan 
40220a708f8fSGustavo F. Padovan 	default:
402348454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
40240a708f8fSGustavo F. Padovan 		break;
40250a708f8fSGustavo F. Padovan 	}
40260a708f8fSGustavo F. Padovan 
40276be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
40283df91ea2SAndrei Emeltchenko 
40293df91ea2SAndrei Emeltchenko unlock:
40303df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40313df91ea2SAndrei Emeltchenko 
40323df91ea2SAndrei Emeltchenko 	return err;
40330a708f8fSGustavo F. Padovan }
40340a708f8fSGustavo F. Padovan 
403547d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
40360a708f8fSGustavo F. Padovan {
40370a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
40380a708f8fSGustavo F. Padovan 	 * sides request it.
40390a708f8fSGustavo F. Padovan 	 */
40400c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
404147d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4042f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
404347d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
40440a708f8fSGustavo F. Padovan }
40450a708f8fSGustavo F. Padovan 
404629d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
404729d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
404829d8a590SAndrei Emeltchenko {
404929d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
405029d8a590SAndrei Emeltchenko 
405129d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
405229d8a590SAndrei Emeltchenko 	       flags);
405329d8a590SAndrei Emeltchenko 
405429d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
405529d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
405629d8a590SAndrei Emeltchenko 
405729d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
405829d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
405929d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
406029d8a590SAndrei Emeltchenko }
406129d8a590SAndrei Emeltchenko 
4062662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4063662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4064662d652dSJohan Hedberg {
4065662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4066662d652dSJohan Hedberg 
4067662d652dSJohan Hedberg 	rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
4068662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4069662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4070662d652dSJohan Hedberg 
4071662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4072662d652dSJohan Hedberg }
4073662d652dSJohan Hedberg 
40742d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
40752d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
40762d792818SGustavo Padovan 				   u8 *data)
40770a708f8fSGustavo F. Padovan {
40780a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
40790a708f8fSGustavo F. Padovan 	u16 dcid, flags;
40800a708f8fSGustavo F. Padovan 	u8 rsp[64];
408148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
40823c588192SMat Martineau 	int len, err = 0;
40830a708f8fSGustavo F. Padovan 
4084cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4085cb3b3152SJohan Hedberg 		return -EPROTO;
4086cb3b3152SJohan Hedberg 
40870a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
40880a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
40890a708f8fSGustavo F. Padovan 
40900a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
40910a708f8fSGustavo F. Padovan 
4092baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4093662d652dSJohan Hedberg 	if (!chan) {
4094662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4095662d652dSJohan Hedberg 		return 0;
4096662d652dSJohan Hedberg 	}
40970a708f8fSGustavo F. Padovan 
4098033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4099662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4100662d652dSJohan Hedberg 				       chan->dcid);
41010a708f8fSGustavo F. Padovan 		goto unlock;
41020a708f8fSGustavo F. Padovan 	}
41030a708f8fSGustavo F. Padovan 
41040a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
41050a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4106cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
41070a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4108fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41090a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
41100a708f8fSGustavo F. Padovan 		goto unlock;
41110a708f8fSGustavo F. Padovan 	}
41120a708f8fSGustavo F. Padovan 
41130a708f8fSGustavo F. Padovan 	/* Store config. */
411473ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
411573ffa904SGustavo F. Padovan 	chan->conf_len += len;
41160a708f8fSGustavo F. Padovan 
411759e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
41180a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
41190a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4120fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41215325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
41220a708f8fSGustavo F. Padovan 		goto unlock;
41230a708f8fSGustavo F. Padovan 	}
41240a708f8fSGustavo F. Padovan 
41250a708f8fSGustavo F. Padovan 	/* Complete config. */
412673ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
41270a708f8fSGustavo F. Padovan 	if (len < 0) {
41285e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
41290a708f8fSGustavo F. Padovan 		goto unlock;
41300a708f8fSGustavo F. Padovan 	}
41310a708f8fSGustavo F. Padovan 
41321500109bSMat Martineau 	chan->ident = cmd->ident;
41330a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
413473ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
41350a708f8fSGustavo F. Padovan 
41360a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
413773ffa904SGustavo F. Padovan 	chan->conf_len = 0;
41380a708f8fSGustavo F. Padovan 
4139c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
41400a708f8fSGustavo F. Padovan 		goto unlock;
41410a708f8fSGustavo F. Padovan 
4142c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
414347d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
41440a708f8fSGustavo F. Padovan 
4145105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4146105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
41473c588192SMat Martineau 			err = l2cap_ertm_init(chan);
41480a708f8fSGustavo F. Padovan 
41493c588192SMat Martineau 		if (err < 0)
41505e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
41513c588192SMat Martineau 		else
4152cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
41533c588192SMat Martineau 
41540a708f8fSGustavo F. Padovan 		goto unlock;
41550a708f8fSGustavo F. Padovan 	}
41560a708f8fSGustavo F. Padovan 
4157c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
41580a708f8fSGustavo F. Padovan 		u8 buf[64];
41590a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
416073ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
416173ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41620a708f8fSGustavo F. Padovan 	}
41630a708f8fSGustavo F. Padovan 
41640e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
41650e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
41660e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
41670e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
41680e8b207eSAndrei Emeltchenko 
41690e8b207eSAndrei Emeltchenko 		/* check compatibility */
41700e8b207eSAndrei Emeltchenko 
417179de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4172f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
417329d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
417479de886dSAndrei Emeltchenko 		else
417579de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
41760e8b207eSAndrei Emeltchenko 	}
41770e8b207eSAndrei Emeltchenko 
41780a708f8fSGustavo F. Padovan unlock:
41796be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
41803c588192SMat Martineau 	return err;
41810a708f8fSGustavo F. Padovan }
41820a708f8fSGustavo F. Padovan 
41832d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4184cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4185cb3b3152SJohan Hedberg 				   u8 *data)
41860a708f8fSGustavo F. Padovan {
41870a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
41880a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
418948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4190cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
41913c588192SMat Martineau 	int err = 0;
41920a708f8fSGustavo F. Padovan 
4193cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4194cb3b3152SJohan Hedberg 		return -EPROTO;
4195cb3b3152SJohan Hedberg 
41960a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
41970a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
41980a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
41990a708f8fSGustavo F. Padovan 
420061386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
420161386cbaSAndrei Emeltchenko 	       result, len);
42020a708f8fSGustavo F. Padovan 
4203baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
420448454079SGustavo F. Padovan 	if (!chan)
42050a708f8fSGustavo F. Padovan 		return 0;
42060a708f8fSGustavo F. Padovan 
42070a708f8fSGustavo F. Padovan 	switch (result) {
42080a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
420947d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
42100e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42110a708f8fSGustavo F. Padovan 		break;
42120a708f8fSGustavo F. Padovan 
42130e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
42140e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42150e8b207eSAndrei Emeltchenko 
42160e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42170e8b207eSAndrei Emeltchenko 			char buf[64];
42180e8b207eSAndrei Emeltchenko 
42190e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
42200e8b207eSAndrei Emeltchenko 						   buf, &result);
42210e8b207eSAndrei Emeltchenko 			if (len < 0) {
42225e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42230e8b207eSAndrei Emeltchenko 				goto done;
42240e8b207eSAndrei Emeltchenko 			}
42250e8b207eSAndrei Emeltchenko 
4226f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
422779de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
422879de886dSAndrei Emeltchenko 							0);
42295ce66b59SAndrei Emeltchenko 			} else {
42305ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
42315ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
423279de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
42330e8b207eSAndrei Emeltchenko 				}
42345ce66b59SAndrei Emeltchenko 			}
42355ce66b59SAndrei Emeltchenko 		}
42360e8b207eSAndrei Emeltchenko 		goto done;
42370e8b207eSAndrei Emeltchenko 
42380a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
423973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
42400a708f8fSGustavo F. Padovan 			char req[64];
42410a708f8fSGustavo F. Padovan 
42420a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
42435e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42440a708f8fSGustavo F. Padovan 				goto done;
42450a708f8fSGustavo F. Padovan 			}
42460a708f8fSGustavo F. Padovan 
42470a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
42480a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4249b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4250b4450035SGustavo F. Padovan 						   req, &result);
42510a708f8fSGustavo F. Padovan 			if (len < 0) {
42525e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42530a708f8fSGustavo F. Padovan 				goto done;
42540a708f8fSGustavo F. Padovan 			}
42550a708f8fSGustavo F. Padovan 
42560a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
42570a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
425873ffa904SGustavo F. Padovan 			chan->num_conf_req++;
42590a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
42600a708f8fSGustavo F. Padovan 				goto done;
42610a708f8fSGustavo F. Padovan 			break;
42620a708f8fSGustavo F. Padovan 		}
42630a708f8fSGustavo F. Padovan 
42640a708f8fSGustavo F. Padovan 	default:
42656be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
42662e0052e4SAndrei Emeltchenko 
4267ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
42685e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42690a708f8fSGustavo F. Padovan 		goto done;
42700a708f8fSGustavo F. Padovan 	}
42710a708f8fSGustavo F. Padovan 
427259e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
42730a708f8fSGustavo F. Padovan 		goto done;
42740a708f8fSGustavo F. Padovan 
4275c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
42760a708f8fSGustavo F. Padovan 
4277c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
427847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
42790a708f8fSGustavo F. Padovan 
4280105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4281105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
42823c588192SMat Martineau 			err = l2cap_ertm_init(chan);
42830a708f8fSGustavo F. Padovan 
42843c588192SMat Martineau 		if (err < 0)
42855e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
42863c588192SMat Martineau 		else
4287cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
42880a708f8fSGustavo F. Padovan 	}
42890a708f8fSGustavo F. Padovan 
42900a708f8fSGustavo F. Padovan done:
42916be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
42923c588192SMat Martineau 	return err;
42930a708f8fSGustavo F. Padovan }
42940a708f8fSGustavo F. Padovan 
42952d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4296cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4297cb3b3152SJohan Hedberg 				       u8 *data)
42980a708f8fSGustavo F. Padovan {
42990a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
43000a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
43010a708f8fSGustavo F. Padovan 	u16 dcid, scid;
430248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43030a708f8fSGustavo F. Padovan 
4304cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4305cb3b3152SJohan Hedberg 		return -EPROTO;
4306cb3b3152SJohan Hedberg 
43070a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
43080a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
43090a708f8fSGustavo F. Padovan 
43100a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
43110a708f8fSGustavo F. Padovan 
43123df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43133df91ea2SAndrei Emeltchenko 
43143df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
43153df91ea2SAndrei Emeltchenko 	if (!chan) {
43163df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4317662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4318662d652dSJohan Hedberg 		return 0;
43193df91ea2SAndrei Emeltchenko 	}
43200a708f8fSGustavo F. Padovan 
43216be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
43226be36555SAndrei Emeltchenko 
4323fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4324fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
43250a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
43260a708f8fSGustavo F. Padovan 
43275ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
43280a708f8fSGustavo F. Padovan 
432961d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
433048454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
43316be36555SAndrei Emeltchenko 
43326be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43330a708f8fSGustavo F. Padovan 
433480b98027SGustavo Padovan 	chan->ops->close(chan);
433561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
43363df91ea2SAndrei Emeltchenko 
43373df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43383df91ea2SAndrei Emeltchenko 
43390a708f8fSGustavo F. Padovan 	return 0;
43400a708f8fSGustavo F. Padovan }
43410a708f8fSGustavo F. Padovan 
43422d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4343cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4344cb3b3152SJohan Hedberg 				       u8 *data)
43450a708f8fSGustavo F. Padovan {
43460a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
43470a708f8fSGustavo F. Padovan 	u16 dcid, scid;
434848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43490a708f8fSGustavo F. Padovan 
4350cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4351cb3b3152SJohan Hedberg 		return -EPROTO;
4352cb3b3152SJohan Hedberg 
43530a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
43540a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
43550a708f8fSGustavo F. Padovan 
43560a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
43570a708f8fSGustavo F. Padovan 
43583df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43593df91ea2SAndrei Emeltchenko 
43603df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
43613df91ea2SAndrei Emeltchenko 	if (!chan) {
43623df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
43630a708f8fSGustavo F. Padovan 		return 0;
43643df91ea2SAndrei Emeltchenko 	}
43650a708f8fSGustavo F. Padovan 
43666be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
436748454079SGustavo F. Padovan 
436861d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
436948454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
43706be36555SAndrei Emeltchenko 
43716be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43720a708f8fSGustavo F. Padovan 
437380b98027SGustavo Padovan 	chan->ops->close(chan);
437461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
43753df91ea2SAndrei Emeltchenko 
43763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43773df91ea2SAndrei Emeltchenko 
43780a708f8fSGustavo F. Padovan 	return 0;
43790a708f8fSGustavo F. Padovan }
43800a708f8fSGustavo F. Padovan 
43812d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4382cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4383cb3b3152SJohan Hedberg 					u8 *data)
43840a708f8fSGustavo F. Padovan {
43850a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
43860a708f8fSGustavo F. Padovan 	u16 type;
43870a708f8fSGustavo F. Padovan 
4388cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4389cb3b3152SJohan Hedberg 		return -EPROTO;
4390cb3b3152SJohan Hedberg 
43910a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
43940a708f8fSGustavo F. Padovan 
43950a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
43960a708f8fSGustavo F. Padovan 		u8 buf[8];
43970a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
43980a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4399ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
4400ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
44010a708f8fSGustavo F. Padovan 		if (!disable_ertm)
44020a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
44030a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
4404848566b3SMarcel Holtmann 		if (conn->hs_enabled)
44056327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
44066327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4407a5fd6f30SAndrei Emeltchenko 
44080a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
44092d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44102d792818SGustavo Padovan 			       buf);
44110a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
44120a708f8fSGustavo F. Padovan 		u8 buf[12];
44130a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
441450a147cdSMat Martineau 
4415848566b3SMarcel Holtmann 		if (conn->hs_enabled)
441650a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
441750a147cdSMat Martineau 		else
441850a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
441950a147cdSMat Martineau 
4420ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4421ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
4422c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
44232d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44242d792818SGustavo Padovan 			       buf);
44250a708f8fSGustavo F. Padovan 	} else {
44260a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
44270a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4428ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
44292d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
44302d792818SGustavo Padovan 			       &rsp);
44310a708f8fSGustavo F. Padovan 	}
44320a708f8fSGustavo F. Padovan 
44330a708f8fSGustavo F. Padovan 	return 0;
44340a708f8fSGustavo F. Padovan }
44350a708f8fSGustavo F. Padovan 
44362d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4437cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4438cb3b3152SJohan Hedberg 					u8 *data)
44390a708f8fSGustavo F. Padovan {
44400a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
44410a708f8fSGustavo F. Padovan 	u16 type, result;
44420a708f8fSGustavo F. Padovan 
44433f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4444cb3b3152SJohan Hedberg 		return -EPROTO;
4445cb3b3152SJohan Hedberg 
44460a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
44470a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
44480a708f8fSGustavo F. Padovan 
44490a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
44500a708f8fSGustavo F. Padovan 
4451e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4452e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4453e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4454e90165beSAndrei Emeltchenko 		return 0;
4455e90165beSAndrei Emeltchenko 
445617cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
44570a708f8fSGustavo F. Padovan 
44580a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
44590a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
44600a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
44610a708f8fSGustavo F. Padovan 
44620a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
44630a708f8fSGustavo F. Padovan 
44640a708f8fSGustavo F. Padovan 		return 0;
44650a708f8fSGustavo F. Padovan 	}
44660a708f8fSGustavo F. Padovan 
4467978c93b9SAndrei Emeltchenko 	switch (type) {
4468978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
44690a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
44700a708f8fSGustavo F. Padovan 
44710a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
44720a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4473ac73498cSAndrei Emeltchenko 			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
44740a708f8fSGustavo F. Padovan 
44750a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
44760a708f8fSGustavo F. Padovan 
44770a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
44780a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
44790a708f8fSGustavo F. Padovan 		} else {
44800a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
44810a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
44820a708f8fSGustavo F. Padovan 
44830a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
44840a708f8fSGustavo F. Padovan 		}
4485978c93b9SAndrei Emeltchenko 		break;
4486978c93b9SAndrei Emeltchenko 
4487978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
4488978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
44890a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
44900a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
44910a708f8fSGustavo F. Padovan 
44920a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4493978c93b9SAndrei Emeltchenko 		break;
44940a708f8fSGustavo F. Padovan 	}
44950a708f8fSGustavo F. Padovan 
44960a708f8fSGustavo F. Padovan 	return 0;
44970a708f8fSGustavo F. Padovan }
44980a708f8fSGustavo F. Padovan 
44991700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
45002d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
45012d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4502f94ff6ffSMat Martineau {
4503f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
45046e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
45051700915fSMat Martineau 	struct l2cap_chan *chan;
45066e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4507f94ff6ffSMat Martineau 	u16 psm, scid;
4508f94ff6ffSMat Martineau 
4509f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4510f94ff6ffSMat Martineau 		return -EPROTO;
4511f94ff6ffSMat Martineau 
4512848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
4513f94ff6ffSMat Martineau 		return -EINVAL;
4514f94ff6ffSMat Martineau 
4515f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4516f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4517f94ff6ffSMat Martineau 
4518ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4519f94ff6ffSMat Martineau 
45206e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
45216ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
45226e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45236e1df6a6SAndrei Emeltchenko 			      req->amp_id);
45246e1df6a6SAndrei Emeltchenko 		return 0;
45256e1df6a6SAndrei Emeltchenko 	}
45261700915fSMat Martineau 
45271700915fSMat Martineau 	/* Validate AMP controller id */
45281700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
45296e1df6a6SAndrei Emeltchenko 	if (!hdev)
45306e1df6a6SAndrei Emeltchenko 		goto error;
45311700915fSMat Martineau 
45326e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
45336e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
45346e1df6a6SAndrei Emeltchenko 		goto error;
45356e1df6a6SAndrei Emeltchenko 	}
45366e1df6a6SAndrei Emeltchenko 
45376e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45386e1df6a6SAndrei Emeltchenko 			     req->amp_id);
45396e1df6a6SAndrei Emeltchenko 	if (chan) {
45406e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
45416e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
45426e1df6a6SAndrei Emeltchenko 
454398e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
454498e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
45456e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
45466e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4547662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4548662d652dSJohan Hedberg 					       chan->dcid);
4549662d652dSJohan Hedberg 			return 0;
45506e1df6a6SAndrei Emeltchenko 		}
45516e1df6a6SAndrei Emeltchenko 
45526e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
45536e1df6a6SAndrei Emeltchenko 
45546e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
45556e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4556fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
45576e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
45586e1df6a6SAndrei Emeltchenko 	}
45596e1df6a6SAndrei Emeltchenko 
45606e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
45616e1df6a6SAndrei Emeltchenko 
45626e1df6a6SAndrei Emeltchenko 	return 0;
45636e1df6a6SAndrei Emeltchenko 
45646e1df6a6SAndrei Emeltchenko error:
4565f94ff6ffSMat Martineau 	rsp.dcid = 0;
4566f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
45671700915fSMat Martineau 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
45688ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4569f94ff6ffSMat Martineau 
4570f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4571f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4572f94ff6ffSMat Martineau 
4573dc280801SJohan Hedberg 	return 0;
4574f94ff6ffSMat Martineau }
4575f94ff6ffSMat Martineau 
45768eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
45778eb200bdSMat Martineau {
45788eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
45798eb200bdSMat Martineau 	u8 ident;
45808eb200bdSMat Martineau 
45818eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
45828eb200bdSMat Martineau 
45838eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
45848eb200bdSMat Martineau 	chan->ident = ident;
45858eb200bdSMat Martineau 
45868eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
45878eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
45888eb200bdSMat Martineau 
45898eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
45908eb200bdSMat Martineau 		       &req);
45918eb200bdSMat Martineau 
45928eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
45938eb200bdSMat Martineau }
45948eb200bdSMat Martineau 
45951500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
45968d5a04a1SMat Martineau {
45978d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
45988d5a04a1SMat Martineau 
45991500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46008d5a04a1SMat Martineau 
46011500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
46028d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
46038d5a04a1SMat Martineau 
46041500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
46051500109bSMat Martineau 		       sizeof(rsp), &rsp);
46068d5a04a1SMat Martineau }
46078d5a04a1SMat Martineau 
46085b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
46098d5a04a1SMat Martineau {
46108d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46118d5a04a1SMat Martineau 
46125b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46138d5a04a1SMat Martineau 
46145b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
46158d5a04a1SMat Martineau 
46165b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
46178d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
46188d5a04a1SMat Martineau 
46195b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
46205b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46215b155ef9SMat Martineau 
46225b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
46235b155ef9SMat Martineau }
46245b155ef9SMat Martineau 
46255b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
46265b155ef9SMat Martineau {
46275b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46285b155ef9SMat Martineau 
46295b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
46305b155ef9SMat Martineau 
46315b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
46325b155ef9SMat Martineau 	cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
46335b155ef9SMat Martineau 
46345b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
46355b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46368d5a04a1SMat Martineau }
46378d5a04a1SMat Martineau 
46388d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
46398d5a04a1SMat Martineau 					 u16 icid)
46408d5a04a1SMat Martineau {
46418d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
46428d5a04a1SMat Martineau 
4643ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
46448d5a04a1SMat Martineau 
46458d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
46468d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
46478d5a04a1SMat Martineau }
46488d5a04a1SMat Martineau 
46495f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
46505f3847a4SMat Martineau {
46515f3847a4SMat Martineau 	chan->hs_hchan = NULL;
46525f3847a4SMat Martineau 	chan->hs_hcon = NULL;
46535f3847a4SMat Martineau 
46545f3847a4SMat Martineau 	/* Placeholder - release the logical link */
46555f3847a4SMat Martineau }
46565f3847a4SMat Martineau 
46571500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
46581500109bSMat Martineau {
46591500109bSMat Martineau 	/* Logical link setup failed */
46601500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
46611500109bSMat Martineau 		/* Create channel failure, disconnect */
46625e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
46631500109bSMat Martineau 		return;
46641500109bSMat Martineau 	}
46651500109bSMat Martineau 
46661500109bSMat Martineau 	switch (chan->move_role) {
46671500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
46681500109bSMat Martineau 		l2cap_move_done(chan);
46691500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
46701500109bSMat Martineau 		break;
46711500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
46721500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
46731500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
46741500109bSMat Martineau 			/* Remote has only sent pending or
46751500109bSMat Martineau 			 * success responses, clean up
46761500109bSMat Martineau 			 */
46771500109bSMat Martineau 			l2cap_move_done(chan);
46781500109bSMat Martineau 		}
46791500109bSMat Martineau 
46801500109bSMat Martineau 		/* Other amp move states imply that the move
46811500109bSMat Martineau 		 * has already aborted
46821500109bSMat Martineau 		 */
46831500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
46841500109bSMat Martineau 		break;
46851500109bSMat Martineau 	}
46861500109bSMat Martineau }
46871500109bSMat Martineau 
46881500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
46891500109bSMat Martineau 					struct hci_chan *hchan)
46901500109bSMat Martineau {
46911500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
46921500109bSMat Martineau 
4693336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
46941500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
46951500109bSMat Martineau 
469635ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
46971500109bSMat Martineau 
46981500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4699fe79c6feSAndrei Emeltchenko 		int err;
47001500109bSMat Martineau 
47011500109bSMat Martineau 		set_default_fcs(chan);
47021500109bSMat Martineau 
47031500109bSMat Martineau 		err = l2cap_ertm_init(chan);
47041500109bSMat Martineau 		if (err < 0)
47055e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
47061500109bSMat Martineau 		else
47071500109bSMat Martineau 			l2cap_chan_ready(chan);
47081500109bSMat Martineau 	}
47091500109bSMat Martineau }
47101500109bSMat Martineau 
47111500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
47121500109bSMat Martineau 				      struct hci_chan *hchan)
47131500109bSMat Martineau {
47141500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
47151500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
47161500109bSMat Martineau 
47171500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
47181500109bSMat Martineau 
47191500109bSMat Martineau 	switch (chan->move_state) {
47201500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
47211500109bSMat Martineau 		/* Move confirm will be sent after a success
47221500109bSMat Martineau 		 * response is received
47231500109bSMat Martineau 		 */
47241500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
47251500109bSMat Martineau 		break;
47261500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
47271500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
47281500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
47291500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
47301500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
47311500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
47321500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
47331500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
47341500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
47351500109bSMat Martineau 		}
47361500109bSMat Martineau 		break;
47371500109bSMat Martineau 	default:
47381500109bSMat Martineau 		/* Move was not in expected state, free the channel */
47391500109bSMat Martineau 		__release_logical_link(chan);
47401500109bSMat Martineau 
47411500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
47421500109bSMat Martineau 	}
47431500109bSMat Martineau }
47441500109bSMat Martineau 
47451500109bSMat Martineau /* Call with chan locked */
474627695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
47475b155ef9SMat Martineau 		       u8 status)
47485b155ef9SMat Martineau {
47491500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
47501500109bSMat Martineau 
47511500109bSMat Martineau 	if (status) {
47521500109bSMat Martineau 		l2cap_logical_fail(chan);
47531500109bSMat Martineau 		__release_logical_link(chan);
47545b155ef9SMat Martineau 		return;
47555b155ef9SMat Martineau 	}
47565b155ef9SMat Martineau 
47571500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
47581500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
47596ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
47601500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
47611500109bSMat Martineau 	} else {
47621500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
47631500109bSMat Martineau 	}
47641500109bSMat Martineau }
47651500109bSMat Martineau 
47663f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
47673f7a56c4SMat Martineau {
47683f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
47693f7a56c4SMat Martineau 
47706ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
47713f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
47723f7a56c4SMat Martineau 			return;
47733f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
47743f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
47753f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
47763f7a56c4SMat Martineau 	} else {
47773f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
47783f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
47793f7a56c4SMat Martineau 		chan->move_id = 0;
47803f7a56c4SMat Martineau 		l2cap_move_setup(chan);
47813f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
47823f7a56c4SMat Martineau 	}
47833f7a56c4SMat Martineau }
47843f7a56c4SMat Martineau 
47858eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
47868eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
47878eb200bdSMat Martineau {
478862748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
478962748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
479062748ca1SAndrei Emeltchenko 
479112d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
479212d6cc60SAndrei Emeltchenko 
479362748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
479462748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
479562748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
479662748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
479762748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
479862748ca1SAndrei Emeltchenko 		} else {
479962748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
480062748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
480162748ca1SAndrei Emeltchenko 		}
480262748ca1SAndrei Emeltchenko 
480362748ca1SAndrei Emeltchenko 		return;
480462748ca1SAndrei Emeltchenko 	}
480562748ca1SAndrei Emeltchenko 
480662748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
480762748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
48088eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
48098eb200bdSMat Martineau 		char buf[128];
48108eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
48118eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
48128eb200bdSMat Martineau 
48138eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
48148eb200bdSMat Martineau 			/* Send successful response */
481562cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
481662cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
48178eb200bdSMat Martineau 		} else {
48188eb200bdSMat Martineau 			/* Send negative response */
481962cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
482062cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
48218eb200bdSMat Martineau 		}
48228eb200bdSMat Martineau 
48238eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
48248eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
48258eb200bdSMat Martineau 
48268eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4827f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
48288eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
48298eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
48308eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
48318eb200bdSMat Martineau 				       l2cap_build_conf_req(chan, buf), buf);
48328eb200bdSMat Martineau 			chan->num_conf_req++;
48338eb200bdSMat Martineau 		}
48348eb200bdSMat Martineau 	}
48358eb200bdSMat Martineau }
48368eb200bdSMat Martineau 
48378eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
48388eb200bdSMat Martineau 				   u8 remote_amp_id)
48398eb200bdSMat Martineau {
48408eb200bdSMat Martineau 	l2cap_move_setup(chan);
48418eb200bdSMat Martineau 	chan->move_id = local_amp_id;
48428eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
48438eb200bdSMat Martineau 
48448eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
48458eb200bdSMat Martineau }
48468eb200bdSMat Martineau 
48478eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
48488eb200bdSMat Martineau {
48498eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
48508eb200bdSMat Martineau 
48518eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
48528eb200bdSMat Martineau 
48538eb200bdSMat Martineau 	if (hchan) {
48548eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
48558eb200bdSMat Martineau 			/* Logical link is ready to go */
48568eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
48578eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
48588eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48598eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48608eb200bdSMat Martineau 
48618eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
48628eb200bdSMat Martineau 		} else {
48638eb200bdSMat Martineau 			/* Wait for logical link to be ready */
48648eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
48658eb200bdSMat Martineau 		}
48668eb200bdSMat Martineau 	} else {
48678eb200bdSMat Martineau 		/* Logical link not available */
48688eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
48698eb200bdSMat Martineau 	}
48708eb200bdSMat Martineau }
48718eb200bdSMat Martineau 
48728eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
48738eb200bdSMat Martineau {
48748eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
48758eb200bdSMat Martineau 		u8 rsp_result;
48768eb200bdSMat Martineau 		if (result == -EINVAL)
48778eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
48788eb200bdSMat Martineau 		else
48798eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
48808eb200bdSMat Martineau 
48818eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
48828eb200bdSMat Martineau 	}
48838eb200bdSMat Martineau 
48848eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
48858eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
48868eb200bdSMat Martineau 
48878eb200bdSMat Martineau 	/* Restart data transmission */
48888eb200bdSMat Martineau 	l2cap_ertm_send(chan);
48898eb200bdSMat Martineau }
48908eb200bdSMat Martineau 
4891a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
4892a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
48938eb200bdSMat Martineau {
4894770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
4895fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
4896770bfefaSAndrei Emeltchenko 
48978eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
48988eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
48998eb200bdSMat Martineau 
49008eb200bdSMat Martineau 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
49018eb200bdSMat Martineau 		l2cap_chan_unlock(chan);
49028eb200bdSMat Martineau 		return;
49038eb200bdSMat Martineau 	}
49048eb200bdSMat Martineau 
49058eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
49068eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
49078eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
49088eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
49098eb200bdSMat Martineau 	} else {
49108eb200bdSMat Martineau 		switch (chan->move_role) {
49118eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
49128eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
49138eb200bdSMat Martineau 					       remote_amp_id);
49148eb200bdSMat Martineau 			break;
49158eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
49168eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
49178eb200bdSMat Martineau 			break;
49188eb200bdSMat Martineau 		default:
49198eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
49208eb200bdSMat Martineau 			break;
49218eb200bdSMat Martineau 		}
49228eb200bdSMat Martineau 	}
49238eb200bdSMat Martineau }
49248eb200bdSMat Martineau 
49258d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
4926ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
4927ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
49288d5a04a1SMat Martineau {
49298d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
49301500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
493102b0fbb9SMat Martineau 	struct l2cap_chan *chan;
49328d5a04a1SMat Martineau 	u16 icid = 0;
49338d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
49348d5a04a1SMat Martineau 
49358d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
49368d5a04a1SMat Martineau 		return -EPROTO;
49378d5a04a1SMat Martineau 
49388d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
49398d5a04a1SMat Martineau 
4940ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
49418d5a04a1SMat Martineau 
4942848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
49438d5a04a1SMat Martineau 		return -EINVAL;
49448d5a04a1SMat Martineau 
494502b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
494602b0fbb9SMat Martineau 	if (!chan) {
49471500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
49481500109bSMat Martineau 		rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
49491500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
49501500109bSMat Martineau 			       sizeof(rsp), &rsp);
495102b0fbb9SMat Martineau 		return 0;
495202b0fbb9SMat Martineau 	}
495302b0fbb9SMat Martineau 
49541500109bSMat Martineau 	chan->ident = cmd->ident;
49551500109bSMat Martineau 
495602b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
495702b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
495802b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
495902b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
496002b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
496102b0fbb9SMat Martineau 		goto send_move_response;
496202b0fbb9SMat Martineau 	}
496302b0fbb9SMat Martineau 
496402b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
496502b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
496602b0fbb9SMat Martineau 		goto send_move_response;
496702b0fbb9SMat Martineau 	}
496802b0fbb9SMat Martineau 
49696ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
497002b0fbb9SMat Martineau 		struct hci_dev *hdev;
497102b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
497202b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
497302b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
497402b0fbb9SMat Martineau 			if (hdev)
497502b0fbb9SMat Martineau 				hci_dev_put(hdev);
497602b0fbb9SMat Martineau 
497702b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
497802b0fbb9SMat Martineau 			goto send_move_response;
497902b0fbb9SMat Martineau 		}
498002b0fbb9SMat Martineau 		hci_dev_put(hdev);
498102b0fbb9SMat Martineau 	}
498202b0fbb9SMat Martineau 
498302b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
498402b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
498502b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
498602b0fbb9SMat Martineau 	 */
498702b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
498802b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
49896f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
499002b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
499102b0fbb9SMat Martineau 		goto send_move_response;
499202b0fbb9SMat Martineau 	}
499302b0fbb9SMat Martineau 
499402b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
499502b0fbb9SMat Martineau 	l2cap_move_setup(chan);
499602b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
499702b0fbb9SMat Martineau 	icid = chan->dcid;
499802b0fbb9SMat Martineau 
49996ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
500002b0fbb9SMat Martineau 		/* Moving to BR/EDR */
500102b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
500202b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
500302b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
500402b0fbb9SMat Martineau 		} else {
500502b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
500602b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
500702b0fbb9SMat Martineau 		}
500802b0fbb9SMat Martineau 	} else {
500902b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
501002b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
501102b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
501202b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
501302b0fbb9SMat Martineau 	}
501402b0fbb9SMat Martineau 
501502b0fbb9SMat Martineau send_move_response:
50161500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
50178d5a04a1SMat Martineau 
501802b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
501902b0fbb9SMat Martineau 
50208d5a04a1SMat Martineau 	return 0;
50218d5a04a1SMat Martineau }
50228d5a04a1SMat Martineau 
50235b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
50245b155ef9SMat Martineau {
50255b155ef9SMat Martineau 	struct l2cap_chan *chan;
50265b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
50275b155ef9SMat Martineau 
50285b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
50295b155ef9SMat Martineau 	if (!chan) {
50305b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
50315b155ef9SMat Martineau 		return;
50325b155ef9SMat Martineau 	}
50335b155ef9SMat Martineau 
50345b155ef9SMat Martineau 	__clear_chan_timer(chan);
50355b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
50365b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
50375b155ef9SMat Martineau 
50385b155ef9SMat Martineau 	switch (chan->move_state) {
50395b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50405b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
50415b155ef9SMat Martineau 		 * is complete.
50425b155ef9SMat Martineau 		 */
50435b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50445b155ef9SMat Martineau 		break;
50455b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
50465b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
50475b155ef9SMat Martineau 			break;
50485b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
50495b155ef9SMat Martineau 				    &chan->conn_state)) {
50505b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50515b155ef9SMat Martineau 		} else {
50525b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
50535b155ef9SMat Martineau 			 * proceed with move
50545b155ef9SMat Martineau 			 */
50555b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50565b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50575b155ef9SMat Martineau 		}
50585b155ef9SMat Martineau 		break;
50595b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
50605b155ef9SMat Martineau 		/* Moving to AMP */
50615b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
50625b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
50635b155ef9SMat Martineau 			 * after logical link is ready
50645b155ef9SMat Martineau 			 */
50655b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50665b155ef9SMat Martineau 		} else {
50675b155ef9SMat Martineau 			/* Both logical link and move success
50685b155ef9SMat Martineau 			 * are required to confirm
50695b155ef9SMat Martineau 			 */
50705b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
50715b155ef9SMat Martineau 		}
50725b155ef9SMat Martineau 
50735b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
50745b155ef9SMat Martineau 		if (!hchan) {
50755b155ef9SMat Martineau 			/* Logical link not available */
50765b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
50775b155ef9SMat Martineau 			break;
50785b155ef9SMat Martineau 		}
50795b155ef9SMat Martineau 
50805b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
50815b155ef9SMat Martineau 		 * send confirmation.
50825b155ef9SMat Martineau 		 */
50835b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
50845b155ef9SMat Martineau 			break;
50855b155ef9SMat Martineau 
50865b155ef9SMat Martineau 		/* Logical link is already ready to go */
50875b155ef9SMat Martineau 
50885b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
50895b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
50905b155ef9SMat Martineau 
50915b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
50925b155ef9SMat Martineau 			/* Can confirm now */
50935b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50945b155ef9SMat Martineau 		} else {
50955b155ef9SMat Martineau 			/* Now only need move success
50965b155ef9SMat Martineau 			 * to confirm
50975b155ef9SMat Martineau 			 */
50985b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50995b155ef9SMat Martineau 		}
51005b155ef9SMat Martineau 
51015b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
51025b155ef9SMat Martineau 		break;
51035b155ef9SMat Martineau 	default:
51045b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
51055b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
51065b155ef9SMat Martineau 		l2cap_move_done(chan);
51075b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51085b155ef9SMat Martineau 	}
51095b155ef9SMat Martineau 
51105b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51115b155ef9SMat Martineau }
51125b155ef9SMat Martineau 
51135b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
51145b155ef9SMat Martineau 			    u16 result)
51155b155ef9SMat Martineau {
51165b155ef9SMat Martineau 	struct l2cap_chan *chan;
51175b155ef9SMat Martineau 
51185b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
51195b155ef9SMat Martineau 	if (!chan) {
51205b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
51215b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51225b155ef9SMat Martineau 		return;
51235b155ef9SMat Martineau 	}
51245b155ef9SMat Martineau 
51255b155ef9SMat Martineau 	__clear_chan_timer(chan);
51265b155ef9SMat Martineau 
51275b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
51285b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
51295b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
51305b155ef9SMat Martineau 		} else {
51315b155ef9SMat Martineau 			/* Cleanup - cancel move */
51325b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
51335b155ef9SMat Martineau 			l2cap_move_done(chan);
51345b155ef9SMat Martineau 		}
51355b155ef9SMat Martineau 	}
51365b155ef9SMat Martineau 
51375b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51385b155ef9SMat Martineau 
51395b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51405b155ef9SMat Martineau }
51415b155ef9SMat Martineau 
51425b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5143ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5144ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
51458d5a04a1SMat Martineau {
51468d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
51478d5a04a1SMat Martineau 	u16 icid, result;
51488d5a04a1SMat Martineau 
51498d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
51508d5a04a1SMat Martineau 		return -EPROTO;
51518d5a04a1SMat Martineau 
51528d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
51538d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
51548d5a04a1SMat Martineau 
5155ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
51568d5a04a1SMat Martineau 
51575b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
51585b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
51595b155ef9SMat Martineau 	else
51605b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
51618d5a04a1SMat Martineau 
51628d5a04a1SMat Martineau 	return 0;
51638d5a04a1SMat Martineau }
51648d5a04a1SMat Martineau 
51655f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5166ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5167ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
51688d5a04a1SMat Martineau {
51698d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
51705f3847a4SMat Martineau 	struct l2cap_chan *chan;
51718d5a04a1SMat Martineau 	u16 icid, result;
51728d5a04a1SMat Martineau 
51738d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
51748d5a04a1SMat Martineau 		return -EPROTO;
51758d5a04a1SMat Martineau 
51768d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
51778d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
51788d5a04a1SMat Martineau 
5179ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
51808d5a04a1SMat Martineau 
51815f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
51825f3847a4SMat Martineau 	if (!chan) {
51835f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
51848d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
51855f3847a4SMat Martineau 		return 0;
51865f3847a4SMat Martineau 	}
51875f3847a4SMat Martineau 
51885f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
51895f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
51905f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
51916ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
51925f3847a4SMat Martineau 				__release_logical_link(chan);
51935f3847a4SMat Martineau 		} else {
51945f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
51955f3847a4SMat Martineau 		}
51965f3847a4SMat Martineau 
51975f3847a4SMat Martineau 		l2cap_move_done(chan);
51985f3847a4SMat Martineau 	}
51995f3847a4SMat Martineau 
52005f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
52015f3847a4SMat Martineau 
52025f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
52038d5a04a1SMat Martineau 
52048d5a04a1SMat Martineau 	return 0;
52058d5a04a1SMat Martineau }
52068d5a04a1SMat Martineau 
52078d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5208ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5209ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
52108d5a04a1SMat Martineau {
52118d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
52123fd71a0aSMat Martineau 	struct l2cap_chan *chan;
52138d5a04a1SMat Martineau 	u16 icid;
52148d5a04a1SMat Martineau 
52158d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
52168d5a04a1SMat Martineau 		return -EPROTO;
52178d5a04a1SMat Martineau 
52188d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
52198d5a04a1SMat Martineau 
5220ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
52218d5a04a1SMat Martineau 
52223fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
52233fd71a0aSMat Martineau 	if (!chan)
52243fd71a0aSMat Martineau 		return 0;
52253fd71a0aSMat Martineau 
52263fd71a0aSMat Martineau 	__clear_chan_timer(chan);
52273fd71a0aSMat Martineau 
52283fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
52293fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
52303fd71a0aSMat Martineau 
52316ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
52323fd71a0aSMat Martineau 			__release_logical_link(chan);
52333fd71a0aSMat Martineau 
52343fd71a0aSMat Martineau 		l2cap_move_done(chan);
52353fd71a0aSMat Martineau 	}
52363fd71a0aSMat Martineau 
52373fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
52383fd71a0aSMat Martineau 
52398d5a04a1SMat Martineau 	return 0;
52408d5a04a1SMat Martineau }
52418d5a04a1SMat Martineau 
5242e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
5243de73115aSClaudio Takahasi 					 u16 to_multiplier)
5244de73115aSClaudio Takahasi {
5245de73115aSClaudio Takahasi 	u16 max_latency;
5246de73115aSClaudio Takahasi 
5247de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
5248de73115aSClaudio Takahasi 		return -EINVAL;
5249de73115aSClaudio Takahasi 
5250de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
5251de73115aSClaudio Takahasi 		return -EINVAL;
5252de73115aSClaudio Takahasi 
5253de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
5254de73115aSClaudio Takahasi 		return -EINVAL;
5255de73115aSClaudio Takahasi 
5256de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
5257de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
5258de73115aSClaudio Takahasi 		return -EINVAL;
5259de73115aSClaudio Takahasi 
5260de73115aSClaudio Takahasi 	return 0;
5261de73115aSClaudio Takahasi }
5262de73115aSClaudio Takahasi 
5263de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
52642d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5265203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5266de73115aSClaudio Takahasi {
5267de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5268de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5269de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5270203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
52712ce603ebSClaudio Takahasi 	int err;
5272de73115aSClaudio Takahasi 
5273de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
5274de73115aSClaudio Takahasi 		return -EINVAL;
5275de73115aSClaudio Takahasi 
5276de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5277de73115aSClaudio Takahasi 		return -EPROTO;
5278de73115aSClaudio Takahasi 
5279de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5280de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5281de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5282de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5283de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5284de73115aSClaudio Takahasi 
5285de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5286de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5287de73115aSClaudio Takahasi 
5288de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
52892ce603ebSClaudio Takahasi 
52902ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
52912ce603ebSClaudio Takahasi 	if (err)
5292ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5293de73115aSClaudio Takahasi 	else
5294ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5295de73115aSClaudio Takahasi 
5296de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5297de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5298de73115aSClaudio Takahasi 
52992ce603ebSClaudio Takahasi 	if (!err)
53002ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
53012ce603ebSClaudio Takahasi 
5302de73115aSClaudio Takahasi 	return 0;
5303de73115aSClaudio Takahasi }
5304de73115aSClaudio Takahasi 
5305f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5306f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5307f1496deeSJohan Hedberg 				u8 *data)
5308f1496deeSJohan Hedberg {
5309f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
5310f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5311f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
5312f1496deeSJohan Hedberg 	int err;
5313f1496deeSJohan Hedberg 
5314f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5315f1496deeSJohan Hedberg 		return -EPROTO;
5316f1496deeSJohan Hedberg 
5317f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5318f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5319f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5320f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5321f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5322f1496deeSJohan Hedberg 
5323f1496deeSJohan Hedberg 	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
5324f1496deeSJohan Hedberg 		return -EPROTO;
5325f1496deeSJohan Hedberg 
5326f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5327f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5328f1496deeSJohan Hedberg 
5329f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5330f1496deeSJohan Hedberg 
5331f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5332f1496deeSJohan Hedberg 	if (!chan) {
5333f1496deeSJohan Hedberg 		err = -EBADSLT;
5334f1496deeSJohan Hedberg 		goto unlock;
5335f1496deeSJohan Hedberg 	}
5336f1496deeSJohan Hedberg 
5337f1496deeSJohan Hedberg 	err = 0;
5338f1496deeSJohan Hedberg 
5339f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5340f1496deeSJohan Hedberg 
5341f1496deeSJohan Hedberg 	switch (result) {
5342f1496deeSJohan Hedberg 	case L2CAP_CR_SUCCESS:
5343f1496deeSJohan Hedberg 		chan->ident = 0;
5344f1496deeSJohan Hedberg 		chan->dcid = dcid;
5345f1496deeSJohan Hedberg 		chan->omtu = mtu;
5346f1496deeSJohan Hedberg 		chan->remote_mps = mps;
53470cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5348f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5349f1496deeSJohan Hedberg 		break;
5350f1496deeSJohan Hedberg 
5351f1496deeSJohan Hedberg 	default:
5352f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5353f1496deeSJohan Hedberg 		break;
5354f1496deeSJohan Hedberg 	}
5355f1496deeSJohan Hedberg 
5356f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5357f1496deeSJohan Hedberg 
5358f1496deeSJohan Hedberg unlock:
5359f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5360f1496deeSJohan Hedberg 
5361f1496deeSJohan Hedberg 	return err;
5362f1496deeSJohan Hedberg }
5363f1496deeSJohan Hedberg 
53643300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
53652d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
53662d792818SGustavo Padovan 				      u8 *data)
53673300d9a9SClaudio Takahasi {
53683300d9a9SClaudio Takahasi 	int err = 0;
53693300d9a9SClaudio Takahasi 
53703300d9a9SClaudio Takahasi 	switch (cmd->code) {
53713300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5372cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
53733300d9a9SClaudio Takahasi 		break;
53743300d9a9SClaudio Takahasi 
53753300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5376cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
53773300d9a9SClaudio Takahasi 		break;
53783300d9a9SClaudio Takahasi 
53793300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5380f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
53819245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
53823300d9a9SClaudio Takahasi 		break;
53833300d9a9SClaudio Takahasi 
53843300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
53853300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
53863300d9a9SClaudio Takahasi 		break;
53873300d9a9SClaudio Takahasi 
53883300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
53899245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
53903300d9a9SClaudio Takahasi 		break;
53913300d9a9SClaudio Takahasi 
53923300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5393cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
53943300d9a9SClaudio Takahasi 		break;
53953300d9a9SClaudio Takahasi 
53963300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
53979245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
53983300d9a9SClaudio Takahasi 		break;
53993300d9a9SClaudio Takahasi 
54003300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
54013300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
54023300d9a9SClaudio Takahasi 		break;
54033300d9a9SClaudio Takahasi 
54043300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
54053300d9a9SClaudio Takahasi 		break;
54063300d9a9SClaudio Takahasi 
54073300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5408cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
54093300d9a9SClaudio Takahasi 		break;
54103300d9a9SClaudio Takahasi 
54113300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
54129245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
54133300d9a9SClaudio Takahasi 		break;
54143300d9a9SClaudio Takahasi 
5415f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5416f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5417f94ff6ffSMat Martineau 		break;
5418f94ff6ffSMat Martineau 
54198d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
54208d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
54218d5a04a1SMat Martineau 		break;
54228d5a04a1SMat Martineau 
54238d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
54249245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
54258d5a04a1SMat Martineau 		break;
54268d5a04a1SMat Martineau 
54278d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
54288d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
54298d5a04a1SMat Martineau 		break;
54308d5a04a1SMat Martineau 
54318d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
54329245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
54338d5a04a1SMat Martineau 		break;
54348d5a04a1SMat Martineau 
54353300d9a9SClaudio Takahasi 	default:
54363300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
54373300d9a9SClaudio Takahasi 		err = -EINVAL;
54383300d9a9SClaudio Takahasi 		break;
54393300d9a9SClaudio Takahasi 	}
54403300d9a9SClaudio Takahasi 
54413300d9a9SClaudio Takahasi 	return err;
54423300d9a9SClaudio Takahasi }
54433300d9a9SClaudio Takahasi 
544427e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
544527e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
544627e2d4c8SJohan Hedberg 				u8 *data)
544727e2d4c8SJohan Hedberg {
544827e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
544927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
545027e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
54510cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
545227e2d4c8SJohan Hedberg 	__le16 psm;
545327e2d4c8SJohan Hedberg 	u8 result;
545427e2d4c8SJohan Hedberg 
545527e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
545627e2d4c8SJohan Hedberg 		return -EPROTO;
545727e2d4c8SJohan Hedberg 
545827e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
545927e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
546027e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
546127e2d4c8SJohan Hedberg 	psm  = req->psm;
546227e2d4c8SJohan Hedberg 	dcid = 0;
54630cd75f7eSJohan Hedberg 	credits = 0;
546427e2d4c8SJohan Hedberg 
546527e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
546627e2d4c8SJohan Hedberg 		return -EPROTO;
546727e2d4c8SJohan Hedberg 
546827e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
546927e2d4c8SJohan Hedberg 	       scid, mtu, mps);
547027e2d4c8SJohan Hedberg 
547127e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
547227e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
547327e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
547427e2d4c8SJohan Hedberg 	if (!pchan) {
547527e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
547627e2d4c8SJohan Hedberg 		chan = NULL;
547727e2d4c8SJohan Hedberg 		goto response;
547827e2d4c8SJohan Hedberg 	}
547927e2d4c8SJohan Hedberg 
548027e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
548127e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
548227e2d4c8SJohan Hedberg 
548327e2d4c8SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
548427e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHENTICATION;
548527e2d4c8SJohan Hedberg 		chan = NULL;
548627e2d4c8SJohan Hedberg 		goto response_unlock;
548727e2d4c8SJohan Hedberg 	}
548827e2d4c8SJohan Hedberg 
548927e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
549027e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
549127e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
549227e2d4c8SJohan Hedberg 		chan = NULL;
549327e2d4c8SJohan Hedberg 		goto response_unlock;
549427e2d4c8SJohan Hedberg 	}
549527e2d4c8SJohan Hedberg 
549627e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
549727e2d4c8SJohan Hedberg 	if (!chan) {
549827e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
549927e2d4c8SJohan Hedberg 		goto response_unlock;
550027e2d4c8SJohan Hedberg 	}
550127e2d4c8SJohan Hedberg 
550227e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
550327e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
550427e2d4c8SJohan Hedberg 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
550527e2d4c8SJohan Hedberg 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
550627e2d4c8SJohan Hedberg 	chan->psm  = psm;
550727e2d4c8SJohan Hedberg 	chan->dcid = scid;
550827e2d4c8SJohan Hedberg 	chan->omtu = mtu;
550927e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
55100cd75f7eSJohan Hedberg 	chan->tx_credits = __le16_to_cpu(req->credits);
551127e2d4c8SJohan Hedberg 
551227e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
551327e2d4c8SJohan Hedberg 	dcid = chan->scid;
55140cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
551527e2d4c8SJohan Hedberg 
551627e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
551727e2d4c8SJohan Hedberg 
551827e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
551927e2d4c8SJohan Hedberg 
552027e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
552127e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
552227e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
552327e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
552427e2d4c8SJohan Hedberg 	} else {
552527e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
552627e2d4c8SJohan Hedberg 		result = L2CAP_CR_SUCCESS;
552727e2d4c8SJohan Hedberg 	}
552827e2d4c8SJohan Hedberg 
552927e2d4c8SJohan Hedberg response_unlock:
553027e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
553127e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
553227e2d4c8SJohan Hedberg 
553327e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
553427e2d4c8SJohan Hedberg 		return 0;
553527e2d4c8SJohan Hedberg 
553627e2d4c8SJohan Hedberg response:
553727e2d4c8SJohan Hedberg 	if (chan) {
553827e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
553927e2d4c8SJohan Hedberg 		rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
554027e2d4c8SJohan Hedberg 	} else {
554127e2d4c8SJohan Hedberg 		rsp.mtu = 0;
554227e2d4c8SJohan Hedberg 		rsp.mps = 0;
554327e2d4c8SJohan Hedberg 	}
554427e2d4c8SJohan Hedberg 
554527e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
55460cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
554727e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
554827e2d4c8SJohan Hedberg 
554927e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
555027e2d4c8SJohan Hedberg 
555127e2d4c8SJohan Hedberg 	return 0;
555227e2d4c8SJohan Hedberg }
555327e2d4c8SJohan Hedberg 
55543300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5555203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5556203e639eSJohan Hedberg 				   u8 *data)
55573300d9a9SClaudio Takahasi {
5558b5ecba64SJohan Hedberg 	int err = 0;
5559b5ecba64SJohan Hedberg 
55603300d9a9SClaudio Takahasi 	switch (cmd->code) {
55613300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5562b5ecba64SJohan Hedberg 		break;
55633300d9a9SClaudio Takahasi 
55643300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5565b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5566b5ecba64SJohan Hedberg 		break;
55673300d9a9SClaudio Takahasi 
55683300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5569b5ecba64SJohan Hedberg 		break;
55703300d9a9SClaudio Takahasi 
5571f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5572f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5573b5ecba64SJohan Hedberg 		break;
5574f1496deeSJohan Hedberg 
557527e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5576b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5577b5ecba64SJohan Hedberg 		break;
557827e2d4c8SJohan Hedberg 
55793defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5580b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5581b5ecba64SJohan Hedberg 		break;
55823defe01aSJohan Hedberg 
55833defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
55843defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5585b5ecba64SJohan Hedberg 		break;
55863defe01aSJohan Hedberg 
55873300d9a9SClaudio Takahasi 	default:
55883300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5589b5ecba64SJohan Hedberg 		err = -EINVAL;
5590b5ecba64SJohan Hedberg 		break;
55913300d9a9SClaudio Takahasi 	}
5592b5ecba64SJohan Hedberg 
5593b5ecba64SJohan Hedberg 	return err;
55943300d9a9SClaudio Takahasi }
55953300d9a9SClaudio Takahasi 
5596c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5597c5623556SJohan Hedberg 					struct sk_buff *skb)
5598c5623556SJohan Hedberg {
559969c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
56004f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
56014f3e219dSMarcel Holtmann 	u16 len;
5602c5623556SJohan Hedberg 	int err;
5603c5623556SJohan Hedberg 
560469c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
56053b166295SMarcel Holtmann 		goto drop;
560669c4e4e8SJohan Hedberg 
56074f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
56084f3e219dSMarcel Holtmann 		goto drop;
5609c5623556SJohan Hedberg 
56104f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
56114f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5612c5623556SJohan Hedberg 
56134f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5614c5623556SJohan Hedberg 
56154f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
56164f3e219dSMarcel Holtmann 
56174f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5618c5623556SJohan Hedberg 		BT_DBG("corrupted command");
56194f3e219dSMarcel Holtmann 		goto drop;
5620c5623556SJohan Hedberg 	}
5621c5623556SJohan Hedberg 
5622203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5623c5623556SJohan Hedberg 	if (err) {
5624c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5625c5623556SJohan Hedberg 
5626c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5627c5623556SJohan Hedberg 
5628a521149aSJohan Hedberg 		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
56294f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5630c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5631c5623556SJohan Hedberg 	}
5632c5623556SJohan Hedberg 
56333b166295SMarcel Holtmann drop:
5634c5623556SJohan Hedberg 	kfree_skb(skb);
5635c5623556SJohan Hedberg }
5636c5623556SJohan Hedberg 
56373300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
56383300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
56390a708f8fSGustavo F. Padovan {
564069c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
56410a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
56420a708f8fSGustavo F. Padovan 	int len = skb->len;
56430a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
56443300d9a9SClaudio Takahasi 	int err;
56450a708f8fSGustavo F. Padovan 
56460a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
56470a708f8fSGustavo F. Padovan 
564869c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
56493b166295SMarcel Holtmann 		goto drop;
565069c4e4e8SJohan Hedberg 
56510a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
56520a708f8fSGustavo F. Padovan 		u16 cmd_len;
56530a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
56540a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
56550a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
56560a708f8fSGustavo F. Padovan 
56570a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
56580a708f8fSGustavo F. Padovan 
56592d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
56602d792818SGustavo Padovan 		       cmd.ident);
56610a708f8fSGustavo F. Padovan 
56620a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
56630a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
56640a708f8fSGustavo F. Padovan 			break;
56650a708f8fSGustavo F. Padovan 		}
56660a708f8fSGustavo F. Padovan 
56673300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
56680a708f8fSGustavo F. Padovan 		if (err) {
5669e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
56702c6d1a2eSGustavo F. Padovan 
56712c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
56720a708f8fSGustavo F. Padovan 
5673a521149aSJohan Hedberg 			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
56742d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
56752d792818SGustavo Padovan 				       sizeof(rej), &rej);
56760a708f8fSGustavo F. Padovan 		}
56770a708f8fSGustavo F. Padovan 
56780a708f8fSGustavo F. Padovan 		data += cmd_len;
56790a708f8fSGustavo F. Padovan 		len  -= cmd_len;
56800a708f8fSGustavo F. Padovan 	}
56810a708f8fSGustavo F. Padovan 
56823b166295SMarcel Holtmann drop:
56830a708f8fSGustavo F. Padovan 	kfree_skb(skb);
56840a708f8fSGustavo F. Padovan }
56850a708f8fSGustavo F. Padovan 
568647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
56870a708f8fSGustavo F. Padovan {
56880a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5689e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5690e4ca6d98SAndrei Emeltchenko 
5691e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5692e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5693e4ca6d98SAndrei Emeltchenko 	else
5694e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
56950a708f8fSGustavo F. Padovan 
569647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
569703a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
56980a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
56990a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
57000a708f8fSGustavo F. Padovan 
57010a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
57020a708f8fSGustavo F. Padovan 			return -EBADMSG;
57030a708f8fSGustavo F. Padovan 	}
57040a708f8fSGustavo F. Padovan 	return 0;
57050a708f8fSGustavo F. Padovan }
57060a708f8fSGustavo F. Padovan 
57076ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
57080a708f8fSGustavo F. Padovan {
5709e31f7633SMat Martineau 	struct l2cap_ctrl control;
57100a708f8fSGustavo F. Padovan 
5711e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
57120a708f8fSGustavo F. Padovan 
5713e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5714e31f7633SMat Martineau 	control.sframe = 1;
5715e31f7633SMat Martineau 	control.final = 1;
5716e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5717e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
57180a708f8fSGustavo F. Padovan 
5719e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5720e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5721e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
57220a708f8fSGustavo F. Padovan 	}
57230a708f8fSGustavo F. Padovan 
5724e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5725e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5726e31f7633SMat Martineau 		__set_retrans_timer(chan);
57270a708f8fSGustavo F. Padovan 
5728e31f7633SMat Martineau 	/* Send pending iframes */
5729525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
57300a708f8fSGustavo F. Padovan 
5731e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5732e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5733e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5734e31f7633SMat Martineau 		 * send it now.
5735e31f7633SMat Martineau 		 */
5736e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5737e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
57380a708f8fSGustavo F. Padovan 	}
57390a708f8fSGustavo F. Padovan }
57400a708f8fSGustavo F. Padovan 
57412d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
57422d792818SGustavo Padovan 			    struct sk_buff **last_frag)
57430a708f8fSGustavo F. Padovan {
574484084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
574584084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
574684084a31SMat Martineau 	 */
574784084a31SMat Martineau 	if (!skb_has_frag_list(skb))
574884084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
574984084a31SMat Martineau 
575084084a31SMat Martineau 	new_frag->next = NULL;
575184084a31SMat Martineau 
575284084a31SMat Martineau 	(*last_frag)->next = new_frag;
575384084a31SMat Martineau 	*last_frag = new_frag;
575484084a31SMat Martineau 
575584084a31SMat Martineau 	skb->len += new_frag->len;
575684084a31SMat Martineau 	skb->data_len += new_frag->len;
575784084a31SMat Martineau 	skb->truesize += new_frag->truesize;
575884084a31SMat Martineau }
575984084a31SMat Martineau 
57604b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
57614b51dae9SMat Martineau 				struct l2cap_ctrl *control)
576284084a31SMat Martineau {
576384084a31SMat Martineau 	int err = -EINVAL;
57640a708f8fSGustavo F. Padovan 
57654b51dae9SMat Martineau 	switch (control->sar) {
57667e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
576784084a31SMat Martineau 		if (chan->sdu)
576884084a31SMat Martineau 			break;
57690a708f8fSGustavo F. Padovan 
577080b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
577184084a31SMat Martineau 		break;
57720a708f8fSGustavo F. Padovan 
57737e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
577484084a31SMat Martineau 		if (chan->sdu)
577584084a31SMat Martineau 			break;
57760a708f8fSGustavo F. Padovan 
57776f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
577803a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
57790a708f8fSGustavo F. Padovan 
578084084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
578184084a31SMat Martineau 			err = -EMSGSIZE;
578284084a31SMat Martineau 			break;
578384084a31SMat Martineau 		}
57840a708f8fSGustavo F. Padovan 
578584084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
578684084a31SMat Martineau 			break;
578784084a31SMat Martineau 
578884084a31SMat Martineau 		chan->sdu = skb;
578984084a31SMat Martineau 		chan->sdu_last_frag = skb;
579084084a31SMat Martineau 
579184084a31SMat Martineau 		skb = NULL;
579284084a31SMat Martineau 		err = 0;
57930a708f8fSGustavo F. Padovan 		break;
57940a708f8fSGustavo F. Padovan 
57957e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
57966f61fd47SGustavo F. Padovan 		if (!chan->sdu)
579784084a31SMat Martineau 			break;
57980a708f8fSGustavo F. Padovan 
579984084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
580084084a31SMat Martineau 				&chan->sdu_last_frag);
580184084a31SMat Martineau 		skb = NULL;
58020a708f8fSGustavo F. Padovan 
580384084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
580484084a31SMat Martineau 			break;
58050a708f8fSGustavo F. Padovan 
580684084a31SMat Martineau 		err = 0;
58070a708f8fSGustavo F. Padovan 		break;
58080a708f8fSGustavo F. Padovan 
58097e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
58106f61fd47SGustavo F. Padovan 		if (!chan->sdu)
581184084a31SMat Martineau 			break;
58120a708f8fSGustavo F. Padovan 
581384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
581484084a31SMat Martineau 				&chan->sdu_last_frag);
581584084a31SMat Martineau 		skb = NULL;
58160a708f8fSGustavo F. Padovan 
581784084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
581884084a31SMat Martineau 			break;
58190a708f8fSGustavo F. Padovan 
582080b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
58210a708f8fSGustavo F. Padovan 
582284084a31SMat Martineau 		if (!err) {
582384084a31SMat Martineau 			/* Reassembly complete */
582484084a31SMat Martineau 			chan->sdu = NULL;
582584084a31SMat Martineau 			chan->sdu_last_frag = NULL;
582684084a31SMat Martineau 			chan->sdu_len = 0;
58270a708f8fSGustavo F. Padovan 		}
58280a708f8fSGustavo F. Padovan 		break;
58290a708f8fSGustavo F. Padovan 	}
58300a708f8fSGustavo F. Padovan 
583184084a31SMat Martineau 	if (err) {
58320a708f8fSGustavo F. Padovan 		kfree_skb(skb);
58336f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
58346f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
583584084a31SMat Martineau 		chan->sdu_last_frag = NULL;
583684084a31SMat Martineau 		chan->sdu_len = 0;
583784084a31SMat Martineau 	}
58380a708f8fSGustavo F. Padovan 
583984084a31SMat Martineau 	return err;
58400a708f8fSGustavo F. Padovan }
58410a708f8fSGustavo F. Padovan 
584232b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
584332b32735SMat Martineau {
584432b32735SMat Martineau 	/* Placeholder */
584532b32735SMat Martineau 	return 0;
584632b32735SMat Martineau }
584732b32735SMat Martineau 
5848e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
58490a708f8fSGustavo F. Padovan {
585061aa4f5bSMat Martineau 	u8 event;
585161aa4f5bSMat Martineau 
585261aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
585361aa4f5bSMat Martineau 		return;
585461aa4f5bSMat Martineau 
585561aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
5856401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
58570a708f8fSGustavo F. Padovan }
58580a708f8fSGustavo F. Padovan 
5859d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
5860d2a7ac5dSMat Martineau {
586163838725SMat Martineau 	int err = 0;
586263838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
586363838725SMat Martineau 	 * until a gap is encountered.
586463838725SMat Martineau 	 */
586563838725SMat Martineau 
586663838725SMat Martineau 	BT_DBG("chan %p", chan);
586763838725SMat Martineau 
586863838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
586963838725SMat Martineau 		struct sk_buff *skb;
587063838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
587163838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
587263838725SMat Martineau 
587363838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
587463838725SMat Martineau 
587563838725SMat Martineau 		if (!skb)
587663838725SMat Martineau 			break;
587763838725SMat Martineau 
587863838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
587963838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
588063838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
588163838725SMat Martineau 		if (err)
588263838725SMat Martineau 			break;
588363838725SMat Martineau 	}
588463838725SMat Martineau 
588563838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
588663838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
588763838725SMat Martineau 		l2cap_send_ack(chan);
588863838725SMat Martineau 	}
588963838725SMat Martineau 
589063838725SMat Martineau 	return err;
5891d2a7ac5dSMat Martineau }
5892d2a7ac5dSMat Martineau 
5893d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
5894d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
5895d2a7ac5dSMat Martineau {
5896f80842a8SMat Martineau 	struct sk_buff *skb;
5897f80842a8SMat Martineau 
5898f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
5899f80842a8SMat Martineau 
5900f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
5901f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
59025e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5903f80842a8SMat Martineau 		return;
5904f80842a8SMat Martineau 	}
5905f80842a8SMat Martineau 
5906f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5907f80842a8SMat Martineau 
5908f80842a8SMat Martineau 	if (skb == NULL) {
5909f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
5910f80842a8SMat Martineau 		       control->reqseq);
5911f80842a8SMat Martineau 		return;
5912f80842a8SMat Martineau 	}
5913f80842a8SMat Martineau 
5914f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
5915f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
59165e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5917f80842a8SMat Martineau 		return;
5918f80842a8SMat Martineau 	}
5919f80842a8SMat Martineau 
5920f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5921f80842a8SMat Martineau 
5922f80842a8SMat Martineau 	if (control->poll) {
5923f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
5924f80842a8SMat Martineau 
5925f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
5926f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
5927f80842a8SMat Martineau 		l2cap_ertm_send(chan);
5928f80842a8SMat Martineau 
5929f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5930f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
5931f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
5932f80842a8SMat Martineau 		}
5933f80842a8SMat Martineau 	} else {
5934f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
5935f80842a8SMat Martineau 
5936f80842a8SMat Martineau 		if (control->final) {
5937f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
5938f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
5939f80842a8SMat Martineau 						&chan->conn_state))
5940f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
5941f80842a8SMat Martineau 		} else {
5942f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
5943f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5944f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
5945f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
5946f80842a8SMat Martineau 			}
5947f80842a8SMat Martineau 		}
5948f80842a8SMat Martineau 	}
5949d2a7ac5dSMat Martineau }
5950d2a7ac5dSMat Martineau 
5951d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
5952d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
5953d2a7ac5dSMat Martineau {
5954fcd289dfSMat Martineau 	struct sk_buff *skb;
5955fcd289dfSMat Martineau 
5956fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
5957fcd289dfSMat Martineau 
5958fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
5959fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
59605e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5961fcd289dfSMat Martineau 		return;
5962fcd289dfSMat Martineau 	}
5963fcd289dfSMat Martineau 
5964fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5965fcd289dfSMat Martineau 
5966fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
5967fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
5968fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
59695e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5970fcd289dfSMat Martineau 		return;
5971fcd289dfSMat Martineau 	}
5972fcd289dfSMat Martineau 
5973fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5974fcd289dfSMat Martineau 
5975fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
5976fcd289dfSMat Martineau 
5977fcd289dfSMat Martineau 	if (control->final) {
5978fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
5979fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
5980fcd289dfSMat Martineau 	} else {
5981fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
5982fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
5983fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
5984fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
5985fcd289dfSMat Martineau 	}
5986d2a7ac5dSMat Martineau }
5987d2a7ac5dSMat Martineau 
59884b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
59894b51dae9SMat Martineau {
59904b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
59914b51dae9SMat Martineau 
59924b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
59934b51dae9SMat Martineau 	       chan->expected_tx_seq);
59944b51dae9SMat Martineau 
59954b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
59964b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
59974b51dae9SMat Martineau 		    chan->tx_win) {
59984b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
59994b51dae9SMat Martineau 			 * invalid packets.
60004b51dae9SMat Martineau 			 */
60014b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
60024b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
60034b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
60044b51dae9SMat Martineau 			} else {
60054b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
60064b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
60074b51dae9SMat Martineau 			}
60084b51dae9SMat Martineau 		}
60094b51dae9SMat Martineau 
60104b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
60114b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
60124b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
60134b51dae9SMat Martineau 		}
60144b51dae9SMat Martineau 
60154b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
60164b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
60174b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
60184b51dae9SMat Martineau 		}
60194b51dae9SMat Martineau 
60204b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
60214b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
60224b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
60234b51dae9SMat Martineau 		}
60244b51dae9SMat Martineau 	}
60254b51dae9SMat Martineau 
60264b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
60274b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
60284b51dae9SMat Martineau 		    chan->tx_win) {
60294b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
60304b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
60314b51dae9SMat Martineau 		} else {
60324b51dae9SMat Martineau 			BT_DBG("Expected");
60334b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
60344b51dae9SMat Martineau 		}
60354b51dae9SMat Martineau 	}
60364b51dae9SMat Martineau 
60374b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
60382d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
60394b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
60404b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
60414b51dae9SMat Martineau 	}
60424b51dae9SMat Martineau 
60434b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
60444b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
60454b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
60464b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
60474b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
60484b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
60494b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
60504b51dae9SMat Martineau 		 * request.
60514b51dae9SMat Martineau 		 *
60524b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
60534b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
60544b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
60554b51dae9SMat Martineau 		 *
60564b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
60574b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
60584b51dae9SMat Martineau 		 * causes a disconnect.
60594b51dae9SMat Martineau 		 */
60604b51dae9SMat Martineau 
60614b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
60624b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
60634b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
60644b51dae9SMat Martineau 		} else {
60654b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
60664b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
60674b51dae9SMat Martineau 		}
60684b51dae9SMat Martineau 	} else {
60694b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
60704b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
60714b51dae9SMat Martineau 	}
60724b51dae9SMat Martineau }
60734b51dae9SMat Martineau 
6074d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6075d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6076d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6077d2a7ac5dSMat Martineau {
6078d2a7ac5dSMat Martineau 	int err = 0;
6079941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6080d2a7ac5dSMat Martineau 
6081d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6082d2a7ac5dSMat Martineau 	       event);
6083d2a7ac5dSMat Martineau 
6084d2a7ac5dSMat Martineau 	switch (event) {
6085d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6086d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6087d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6088d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6089d2a7ac5dSMat Martineau 
6090d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6091d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6092d2a7ac5dSMat Martineau 				       control->txseq);
6093d2a7ac5dSMat Martineau 				break;
6094d2a7ac5dSMat Martineau 			}
6095d2a7ac5dSMat Martineau 
6096d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6097d2a7ac5dSMat Martineau 							   control->txseq);
6098d2a7ac5dSMat Martineau 
6099d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6100941247f9SPeter Senna Tschudin 			skb_in_use = true;
6101d2a7ac5dSMat Martineau 
6102d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6103d2a7ac5dSMat Martineau 			if (err)
6104d2a7ac5dSMat Martineau 				break;
6105d2a7ac5dSMat Martineau 
6106d2a7ac5dSMat Martineau 			if (control->final) {
6107d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6108d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6109d2a7ac5dSMat Martineau 					control->final = 0;
6110d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6111d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6112d2a7ac5dSMat Martineau 				}
6113d2a7ac5dSMat Martineau 			}
6114d2a7ac5dSMat Martineau 
6115d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6116d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6117d2a7ac5dSMat Martineau 			break;
6118d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6119d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6120d2a7ac5dSMat Martineau 
6121d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6122d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6123d2a7ac5dSMat Martineau 			 * when local busy is exited.
6124d2a7ac5dSMat Martineau 			 */
6125d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6126d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6127d2a7ac5dSMat Martineau 				       control->txseq);
6128d2a7ac5dSMat Martineau 				break;
6129d2a7ac5dSMat Martineau 			}
6130d2a7ac5dSMat Martineau 
6131d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6132d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6133d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6134d2a7ac5dSMat Martineau 			 */
6135d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6136941247f9SPeter Senna Tschudin 			skb_in_use = true;
6137d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6138d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6139d2a7ac5dSMat Martineau 
6140d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6141d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6142d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6143d2a7ac5dSMat Martineau 
6144d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6145d2a7ac5dSMat Martineau 			break;
6146d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6147d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6148d2a7ac5dSMat Martineau 			break;
6149d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6150d2a7ac5dSMat Martineau 			break;
6151d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6152d2a7ac5dSMat Martineau 		default:
61535e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6154d2a7ac5dSMat Martineau 			break;
6155d2a7ac5dSMat Martineau 		}
6156d2a7ac5dSMat Martineau 		break;
6157d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6158d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6159d2a7ac5dSMat Martineau 		if (control->final) {
6160d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6161d2a7ac5dSMat Martineau 
6162e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6163e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6164d2a7ac5dSMat Martineau 				control->final = 0;
6165d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6166d2a7ac5dSMat Martineau 			}
6167d2a7ac5dSMat Martineau 
6168d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6169d2a7ac5dSMat Martineau 		} else if (control->poll) {
6170d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6171d2a7ac5dSMat Martineau 		} else {
6172d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6173d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6174d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6175d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6176d2a7ac5dSMat Martineau 
6177d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6178d2a7ac5dSMat Martineau 		}
6179d2a7ac5dSMat Martineau 		break;
6180d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6181d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6182d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6183d2a7ac5dSMat Martineau 		if (control && control->poll) {
6184d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6185d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6186d2a7ac5dSMat Martineau 		}
6187d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6188d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6189d2a7ac5dSMat Martineau 		break;
6190d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6191d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6192d2a7ac5dSMat Martineau 		break;
6193d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6194d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6195d2a7ac5dSMat Martineau 		break;
6196d2a7ac5dSMat Martineau 	default:
6197d2a7ac5dSMat Martineau 		break;
6198d2a7ac5dSMat Martineau 	}
6199d2a7ac5dSMat Martineau 
6200d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6201d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6202d2a7ac5dSMat Martineau 		kfree_skb(skb);
6203d2a7ac5dSMat Martineau 	}
6204d2a7ac5dSMat Martineau 
6205d2a7ac5dSMat Martineau 	return err;
6206d2a7ac5dSMat Martineau }
6207d2a7ac5dSMat Martineau 
6208d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6209d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6210d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6211d2a7ac5dSMat Martineau {
6212d2a7ac5dSMat Martineau 	int err = 0;
6213d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6214941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6215d2a7ac5dSMat Martineau 
6216d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6217d2a7ac5dSMat Martineau 	       event);
6218d2a7ac5dSMat Martineau 
6219d2a7ac5dSMat Martineau 	switch (event) {
6220d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6221d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6222d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6223d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6224d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6225d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6226941247f9SPeter Senna Tschudin 			skb_in_use = true;
6227d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6228d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6229d2a7ac5dSMat Martineau 
6230d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6231d2a7ac5dSMat Martineau 			break;
6232d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6233d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6234d2a7ac5dSMat Martineau 
6235d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6236d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6237941247f9SPeter Senna Tschudin 			skb_in_use = true;
6238d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6239d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6240d2a7ac5dSMat Martineau 
6241d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6242d2a7ac5dSMat Martineau 			if (err)
6243d2a7ac5dSMat Martineau 				break;
6244d2a7ac5dSMat Martineau 
6245d2a7ac5dSMat Martineau 			break;
6246d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6247d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6248d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6249d2a7ac5dSMat Martineau 			 * the missing frames.
6250d2a7ac5dSMat Martineau 			 */
6251d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6252941247f9SPeter Senna Tschudin 			skb_in_use = true;
6253d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6254d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6255d2a7ac5dSMat Martineau 
6256d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6257d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6258d2a7ac5dSMat Martineau 			break;
6259d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6260d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6261d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6262d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6263d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6264d2a7ac5dSMat Martineau 			 */
6265d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6266941247f9SPeter Senna Tschudin 			skb_in_use = true;
6267d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6268d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6269d2a7ac5dSMat Martineau 
6270d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6271d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6272d2a7ac5dSMat Martineau 			break;
6273d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6274d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6275d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6276d2a7ac5dSMat Martineau 			break;
6277d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6278d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6279d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6280d2a7ac5dSMat Martineau 			 */
6281d2a7ac5dSMat Martineau 			break;
6282d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6283d2a7ac5dSMat Martineau 			break;
6284d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6285d2a7ac5dSMat Martineau 		default:
62865e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6287d2a7ac5dSMat Martineau 			break;
6288d2a7ac5dSMat Martineau 		}
6289d2a7ac5dSMat Martineau 		break;
6290d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6291d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6292d2a7ac5dSMat Martineau 		if (control->final) {
6293d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6294d2a7ac5dSMat Martineau 
6295d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6296d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6297d2a7ac5dSMat Martineau 				control->final = 0;
6298d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6299d2a7ac5dSMat Martineau 			}
6300d2a7ac5dSMat Martineau 
6301d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6302d2a7ac5dSMat Martineau 		} else if (control->poll) {
6303d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6304d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6305d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6306d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6307d2a7ac5dSMat Martineau 			}
6308d2a7ac5dSMat Martineau 
6309d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6310d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6311d2a7ac5dSMat Martineau 		} else {
6312d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6313d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6314d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6315d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6316d2a7ac5dSMat Martineau 
6317d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6318d2a7ac5dSMat Martineau 		}
6319d2a7ac5dSMat Martineau 		break;
6320d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6321d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6322d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6323d2a7ac5dSMat Martineau 		if (control->poll) {
6324d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6325d2a7ac5dSMat Martineau 		} else {
6326d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6327d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6328d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6329d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6330d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6331d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6332d2a7ac5dSMat Martineau 		}
6333d2a7ac5dSMat Martineau 
6334d2a7ac5dSMat Martineau 		break;
6335d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6336d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6337d2a7ac5dSMat Martineau 		break;
6338d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6339d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6340d2a7ac5dSMat Martineau 		break;
6341d2a7ac5dSMat Martineau 	}
6342d2a7ac5dSMat Martineau 
6343d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6344d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6345d2a7ac5dSMat Martineau 		kfree_skb(skb);
6346d2a7ac5dSMat Martineau 	}
6347d2a7ac5dSMat Martineau 
6348d2a7ac5dSMat Martineau 	return err;
6349d2a7ac5dSMat Martineau }
6350d2a7ac5dSMat Martineau 
635132b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
635232b32735SMat Martineau {
635332b32735SMat Martineau 	BT_DBG("chan %p", chan);
635432b32735SMat Martineau 
635532b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
635632b32735SMat Martineau 
635732b32735SMat Martineau 	if (chan->hs_hcon)
635832b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
635932b32735SMat Martineau 	else
636032b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
636132b32735SMat Martineau 
636232b32735SMat Martineau 	return l2cap_resegment(chan);
636332b32735SMat Martineau }
636432b32735SMat Martineau 
636532b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
636632b32735SMat Martineau 				 struct l2cap_ctrl *control,
636732b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
636832b32735SMat Martineau {
636932b32735SMat Martineau 	int err;
637032b32735SMat Martineau 
637132b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
637232b32735SMat Martineau 	       event);
637332b32735SMat Martineau 
637432b32735SMat Martineau 	if (!control->poll)
637532b32735SMat Martineau 		return -EPROTO;
637632b32735SMat Martineau 
637732b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
637832b32735SMat Martineau 
637932b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
638032b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
638132b32735SMat Martineau 	else
638232b32735SMat Martineau 		chan->tx_send_head = NULL;
638332b32735SMat Martineau 
638432b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
638532b32735SMat Martineau 	 * by the receiver.
638632b32735SMat Martineau 	 */
638732b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
638832b32735SMat Martineau 	chan->unacked_frames = 0;
638932b32735SMat Martineau 
639032b32735SMat Martineau 	err = l2cap_finish_move(chan);
639132b32735SMat Martineau 	if (err)
639232b32735SMat Martineau 		return err;
639332b32735SMat Martineau 
639432b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
639532b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
639632b32735SMat Martineau 
639732b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
639832b32735SMat Martineau 		return -EPROTO;
639932b32735SMat Martineau 
640032b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
640132b32735SMat Martineau }
640232b32735SMat Martineau 
640332b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
640432b32735SMat Martineau 				 struct l2cap_ctrl *control,
640532b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
640632b32735SMat Martineau {
640732b32735SMat Martineau 	int err;
640832b32735SMat Martineau 
640932b32735SMat Martineau 	if (!control->final)
641032b32735SMat Martineau 		return -EPROTO;
641132b32735SMat Martineau 
641232b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
641332b32735SMat Martineau 
641432b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
641532b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
641632b32735SMat Martineau 
641732b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
641832b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
641932b32735SMat Martineau 	else
642032b32735SMat Martineau 		chan->tx_send_head = NULL;
642132b32735SMat Martineau 
642232b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
642332b32735SMat Martineau 	 * by the receiver.
642432b32735SMat Martineau 	 */
642532b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
642632b32735SMat Martineau 	chan->unacked_frames = 0;
642732b32735SMat Martineau 
642832b32735SMat Martineau 	if (chan->hs_hcon)
642932b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
643032b32735SMat Martineau 	else
643132b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
643232b32735SMat Martineau 
643332b32735SMat Martineau 	err = l2cap_resegment(chan);
643432b32735SMat Martineau 
643532b32735SMat Martineau 	if (!err)
643632b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
643732b32735SMat Martineau 
643832b32735SMat Martineau 	return err;
643932b32735SMat Martineau }
644032b32735SMat Martineau 
6441d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6442d2a7ac5dSMat Martineau {
6443d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6444d2a7ac5dSMat Martineau 	u16 unacked;
6445d2a7ac5dSMat Martineau 
6446d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6447d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6448d2a7ac5dSMat Martineau }
6449d2a7ac5dSMat Martineau 
6450cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6451cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
64520a708f8fSGustavo F. Padovan {
6453d2a7ac5dSMat Martineau 	int err = 0;
6454d2a7ac5dSMat Martineau 
6455d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6456d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6457d2a7ac5dSMat Martineau 
6458d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6459d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6460d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6461d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6462d2a7ac5dSMat Martineau 			break;
6463d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6464d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6465d2a7ac5dSMat Martineau 						       event);
6466d2a7ac5dSMat Martineau 			break;
646732b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
646832b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
646932b32735SMat Martineau 			break;
647032b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
647132b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
647232b32735SMat Martineau 			break;
6473d2a7ac5dSMat Martineau 		default:
6474d2a7ac5dSMat Martineau 			/* shut it down */
6475d2a7ac5dSMat Martineau 			break;
6476d2a7ac5dSMat Martineau 		}
6477d2a7ac5dSMat Martineau 	} else {
6478d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6479d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6480d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
64815e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6482d2a7ac5dSMat Martineau 	}
6483d2a7ac5dSMat Martineau 
6484d2a7ac5dSMat Martineau 	return err;
6485cec8ab6eSMat Martineau }
6486cec8ab6eSMat Martineau 
6487cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6488cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6489cec8ab6eSMat Martineau {
64904b51dae9SMat Martineau 	int err = 0;
64914b51dae9SMat Martineau 
64924b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
64934b51dae9SMat Martineau 	       chan->rx_state);
64944b51dae9SMat Martineau 
64954b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
64964b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
64974b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
64984b51dae9SMat Martineau 
64994b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
65004b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
65014b51dae9SMat Martineau 
65024b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
65034b51dae9SMat Martineau 
65044b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
65054b51dae9SMat Martineau 	} else {
65064b51dae9SMat Martineau 		if (chan->sdu) {
65074b51dae9SMat Martineau 			kfree_skb(chan->sdu);
65084b51dae9SMat Martineau 			chan->sdu = NULL;
65094b51dae9SMat Martineau 		}
65104b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
65114b51dae9SMat Martineau 		chan->sdu_len = 0;
65124b51dae9SMat Martineau 
65134b51dae9SMat Martineau 		if (skb) {
65144b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
65154b51dae9SMat Martineau 			kfree_skb(skb);
65164b51dae9SMat Martineau 		}
65174b51dae9SMat Martineau 	}
65184b51dae9SMat Martineau 
65194b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
65204b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
65214b51dae9SMat Martineau 
65224b51dae9SMat Martineau 	return err;
6523cec8ab6eSMat Martineau }
6524cec8ab6eSMat Martineau 
6525cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6526cec8ab6eSMat Martineau {
6527cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
6528cec8ab6eSMat Martineau 	u16 len;
6529cec8ab6eSMat Martineau 	u8 event;
65300a708f8fSGustavo F. Padovan 
6531b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6532b76bbd66SMat Martineau 
65330a708f8fSGustavo F. Padovan 	len = skb->len;
65340a708f8fSGustavo F. Padovan 
65350a708f8fSGustavo F. Padovan 	/*
65360a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
65370a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6538cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
65390a708f8fSGustavo F. Padovan 	 */
654047d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
65410a708f8fSGustavo F. Padovan 		goto drop;
65420a708f8fSGustavo F. Padovan 
6543cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
654403a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
65450a708f8fSGustavo F. Padovan 
654647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
654703a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
65480a708f8fSGustavo F. Padovan 
654947d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
65505e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
65510a708f8fSGustavo F. Padovan 		goto drop;
65520a708f8fSGustavo F. Padovan 	}
65530a708f8fSGustavo F. Padovan 
6554cec8ab6eSMat Martineau 	if (!control->sframe) {
6555cec8ab6eSMat Martineau 		int err;
65560a708f8fSGustavo F. Padovan 
6557cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6558cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6559cec8ab6eSMat Martineau 		       control->txseq);
6560836be934SAndrei Emeltchenko 
6561cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6562cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6563cec8ab6eSMat Martineau 		 */
6564cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
65650a708f8fSGustavo F. Padovan 			goto drop;
65660a708f8fSGustavo F. Padovan 
6567cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6568cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6569cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
65700a708f8fSGustavo F. Padovan 		} else {
6571cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6572cec8ab6eSMat Martineau 		}
6573cec8ab6eSMat Martineau 
6574cec8ab6eSMat Martineau 		if (err)
65755e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6576cec8ab6eSMat Martineau 	} else {
6577cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6578cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6579cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6580cec8ab6eSMat Martineau 		};
6581cec8ab6eSMat Martineau 
6582cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6583cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6584cec8ab6eSMat Martineau 			goto drop;
6585cec8ab6eSMat Martineau 
6586cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6587cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6588cec8ab6eSMat Martineau 		       control->super);
6589cec8ab6eSMat Martineau 
65900a708f8fSGustavo F. Padovan 		if (len != 0) {
65911bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
65925e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
65930a708f8fSGustavo F. Padovan 			goto drop;
65940a708f8fSGustavo F. Padovan 		}
65950a708f8fSGustavo F. Padovan 
6596cec8ab6eSMat Martineau 		/* Validate F and P bits */
6597cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6598cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6599cec8ab6eSMat Martineau 			goto drop;
6600cec8ab6eSMat Martineau 
6601cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6602cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
66035e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
66040a708f8fSGustavo F. Padovan 	}
66050a708f8fSGustavo F. Padovan 
66060a708f8fSGustavo F. Padovan 	return 0;
66070a708f8fSGustavo F. Padovan 
66080a708f8fSGustavo F. Padovan drop:
66090a708f8fSGustavo F. Padovan 	kfree_skb(skb);
66100a708f8fSGustavo F. Padovan 	return 0;
66110a708f8fSGustavo F. Padovan }
66120a708f8fSGustavo F. Padovan 
661313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
661413ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
66150a708f8fSGustavo F. Padovan {
661648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
66170a708f8fSGustavo F. Padovan 
6618baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
661948454079SGustavo F. Padovan 	if (!chan) {
662097e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
662197e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
662297e8e89dSAndrei Emeltchenko 			if (!chan) {
662397e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
662413ca56e0SAndrei Emeltchenko 				return;
662597e8e89dSAndrei Emeltchenko 			}
662697e8e89dSAndrei Emeltchenko 
662797e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
662897e8e89dSAndrei Emeltchenko 		} else {
66290a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
66306be36555SAndrei Emeltchenko 			/* Drop packet and return */
66313379013bSDan Carpenter 			kfree_skb(skb);
663213ca56e0SAndrei Emeltchenko 			return;
66330a708f8fSGustavo F. Padovan 		}
663497e8e89dSAndrei Emeltchenko 	}
66350a708f8fSGustavo F. Padovan 
663649208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
66370a708f8fSGustavo F. Padovan 
663889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
66390a708f8fSGustavo F. Padovan 		goto drop;
66400a708f8fSGustavo F. Padovan 
66410c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
664238319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
66430a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
66440a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
66450a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
66460a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
66470a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
66480a708f8fSGustavo F. Padovan 
66490c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
66500a708f8fSGustavo F. Padovan 			goto drop;
66510a708f8fSGustavo F. Padovan 
665280b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
66530a708f8fSGustavo F. Padovan 			goto done;
66540a708f8fSGustavo F. Padovan 		break;
66550a708f8fSGustavo F. Padovan 
66560a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
66570a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6658cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
66590a708f8fSGustavo F. Padovan 		goto done;
66600a708f8fSGustavo F. Padovan 
66610a708f8fSGustavo F. Padovan 	default:
66620c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
66630a708f8fSGustavo F. Padovan 		break;
66640a708f8fSGustavo F. Padovan 	}
66650a708f8fSGustavo F. Padovan 
66660a708f8fSGustavo F. Padovan drop:
66670a708f8fSGustavo F. Padovan 	kfree_skb(skb);
66680a708f8fSGustavo F. Padovan 
66690a708f8fSGustavo F. Padovan done:
66706be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
66710a708f8fSGustavo F. Padovan }
66720a708f8fSGustavo F. Padovan 
667384104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
667484104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
66750a708f8fSGustavo F. Padovan {
6676ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
667723691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
66780a708f8fSGustavo F. Padovan 
6679ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
6680ae4fd2d3SMarcel Holtmann 		goto drop;
6681ae4fd2d3SMarcel Holtmann 
6682bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6683bf20fd4eSJohan Hedberg 					ACL_LINK);
668423691d75SGustavo F. Padovan 	if (!chan)
66850a708f8fSGustavo F. Padovan 		goto drop;
66860a708f8fSGustavo F. Padovan 
66875b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
66880a708f8fSGustavo F. Padovan 
668989bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
66900a708f8fSGustavo F. Padovan 		goto drop;
66910a708f8fSGustavo F. Padovan 
6692e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
66930a708f8fSGustavo F. Padovan 		goto drop;
66940a708f8fSGustavo F. Padovan 
66952edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
669606ae3314SMarcel Holtmann 	bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
66972edf870dSMarcel Holtmann 	bt_cb(skb)->psm = psm;
66982edf870dSMarcel Holtmann 
669980b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
670084104b24SAndrei Emeltchenko 		return;
67010a708f8fSGustavo F. Padovan 
67020a708f8fSGustavo F. Padovan drop:
67030a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67040a708f8fSGustavo F. Padovan }
67050a708f8fSGustavo F. Padovan 
670672f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn,
6707d9b88702SAndrei Emeltchenko 			      struct sk_buff *skb)
67089f69bda6SGustavo F. Padovan {
6709b99707d7SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
671023691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
67119f69bda6SGustavo F. Padovan 
6712b99707d7SMarcel Holtmann 	if (hcon->type != LE_LINK)
6713b99707d7SMarcel Holtmann 		goto drop;
6714b99707d7SMarcel Holtmann 
6715af1c0134SJohan Hedberg 	chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
671606ae3314SMarcel Holtmann 					 &hcon->src, &hcon->dst);
671723691d75SGustavo F. Padovan 	if (!chan)
67189f69bda6SGustavo F. Padovan 		goto drop;
67199f69bda6SGustavo F. Padovan 
67205b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
67219f69bda6SGustavo F. Padovan 
6722cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
6723cc8dba2bSMarcel Holtmann 		goto drop;
6724cc8dba2bSMarcel Holtmann 
6725e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
67269f69bda6SGustavo F. Padovan 		goto drop;
67279f69bda6SGustavo F. Padovan 
672880b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
67296810fca7SAndrei Emeltchenko 		return;
67309f69bda6SGustavo F. Padovan 
67319f69bda6SGustavo F. Padovan drop:
67329f69bda6SGustavo F. Padovan 	kfree_skb(skb);
67339f69bda6SGustavo F. Padovan }
67349f69bda6SGustavo F. Padovan 
67350a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
67360a708f8fSGustavo F. Padovan {
67370a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
67380a708f8fSGustavo F. Padovan 	u16 cid, len;
67390a708f8fSGustavo F. Padovan 	__le16 psm;
67400a708f8fSGustavo F. Padovan 
67410a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
67420a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
67430a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
67440a708f8fSGustavo F. Padovan 
67450a708f8fSGustavo F. Padovan 	if (len != skb->len) {
67460a708f8fSGustavo F. Padovan 		kfree_skb(skb);
67470a708f8fSGustavo F. Padovan 		return;
67480a708f8fSGustavo F. Padovan 	}
67490a708f8fSGustavo F. Padovan 
67500a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
67510a708f8fSGustavo F. Padovan 
67520a708f8fSGustavo F. Padovan 	switch (cid) {
67530a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
67540a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
67550a708f8fSGustavo F. Padovan 		break;
67560a708f8fSGustavo F. Padovan 
67570a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
6758097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
67590181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
67600a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
67610a708f8fSGustavo F. Padovan 		break;
67620a708f8fSGustavo F. Padovan 
6763073d1cf3SJohan Hedberg 	case L2CAP_CID_ATT:
676472f78356SMarcel Holtmann 		l2cap_att_channel(conn, skb);
67659f69bda6SGustavo F. Padovan 		break;
67669f69bda6SGustavo F. Padovan 
6767a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
6768a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
6769a2877629SMarcel Holtmann 		break;
6770a2877629SMarcel Holtmann 
6771b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
6772b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
6773b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
6774b501d6a1SAnderson Briglia 		break;
6775b501d6a1SAnderson Briglia 
67760a708f8fSGustavo F. Padovan 	default:
67770a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
67780a708f8fSGustavo F. Padovan 		break;
67790a708f8fSGustavo F. Padovan 	}
67800a708f8fSGustavo F. Padovan }
67810a708f8fSGustavo F. Padovan 
67820a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
67830a708f8fSGustavo F. Padovan 
6784686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
67850a708f8fSGustavo F. Padovan {
67860a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
678723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
67880a708f8fSGustavo F. Padovan 
67896ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
67900a708f8fSGustavo F. Padovan 
67910a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
679223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
679323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
679489bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
67950a708f8fSGustavo F. Padovan 			continue;
67960a708f8fSGustavo F. Padovan 
67977eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
67980a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
679943bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
68000a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
68010a708f8fSGustavo F. Padovan 			exact++;
68027eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
68030a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
680443bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
68050a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
68060a708f8fSGustavo F. Padovan 		}
68070a708f8fSGustavo F. Padovan 	}
680823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
68090a708f8fSGustavo F. Padovan 
68100a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
68110a708f8fSGustavo F. Padovan }
68120a708f8fSGustavo F. Padovan 
68139e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
68140a708f8fSGustavo F. Padovan {
68150a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
68160a708f8fSGustavo F. Padovan 
68176ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
68180a708f8fSGustavo F. Padovan 
68190a708f8fSGustavo F. Padovan 	if (!status) {
6820baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
68210a708f8fSGustavo F. Padovan 		if (conn)
68220a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
6823ba6fc317SAndrei Emeltchenko 	} else {
6824e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
6825ba6fc317SAndrei Emeltchenko 	}
68260a708f8fSGustavo F. Padovan }
68270a708f8fSGustavo F. Padovan 
6828686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
68290a708f8fSGustavo F. Padovan {
68300a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
68310a708f8fSGustavo F. Padovan 
68320a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
68330a708f8fSGustavo F. Padovan 
6834686ebf28SUlisses Furquim 	if (!conn)
68359f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
68360a708f8fSGustavo F. Padovan 	return conn->disc_reason;
68370a708f8fSGustavo F. Padovan }
68380a708f8fSGustavo F. Padovan 
68399e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
68400a708f8fSGustavo F. Padovan {
68410a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
68420a708f8fSGustavo F. Padovan 
6843e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
68440a708f8fSGustavo F. Padovan }
68450a708f8fSGustavo F. Padovan 
68464343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
68470a708f8fSGustavo F. Padovan {
6848715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
68490a708f8fSGustavo F. Padovan 		return;
68500a708f8fSGustavo F. Padovan 
68510a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
68524343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
6853ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
68544343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
68550f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
68560a708f8fSGustavo F. Padovan 	} else {
68574343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
6858c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
68590a708f8fSGustavo F. Padovan 	}
68600a708f8fSGustavo F. Padovan }
68610a708f8fSGustavo F. Padovan 
6862686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
68630a708f8fSGustavo F. Padovan {
68640a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
686548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
68660a708f8fSGustavo F. Padovan 
68670a708f8fSGustavo F. Padovan 	if (!conn)
68680a708f8fSGustavo F. Padovan 		return 0;
68690a708f8fSGustavo F. Padovan 
687089d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
68710a708f8fSGustavo F. Padovan 
6872160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
687335d4adccSHemant Gupta 		if (!status && encrypt)
6874160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
687517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
6876160dc6acSVinicius Costa Gomes 	}
6877160dc6acSVinicius Costa Gomes 
68783df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
68790a708f8fSGustavo F. Padovan 
68803df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
68816be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
68820a708f8fSGustavo F. Padovan 
688389d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
688489d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
6885f1cb9af5SVinicius Costa Gomes 
688678eb2f98SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
688778eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
688878eb2f98SAndrei Emeltchenko 			continue;
688978eb2f98SAndrei Emeltchenko 		}
689078eb2f98SAndrei Emeltchenko 
6891073d1cf3SJohan Hedberg 		if (chan->scid == L2CAP_CID_ATT) {
6892f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
6893f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
6894cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
6895f1cb9af5SVinicius Costa Gomes 			}
6896f1cb9af5SVinicius Costa Gomes 
68976be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
6898f1cb9af5SVinicius Costa Gomes 			continue;
6899f1cb9af5SVinicius Costa Gomes 		}
6900f1cb9af5SVinicius Costa Gomes 
690196eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
69026be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
69030a708f8fSGustavo F. Padovan 			continue;
69040a708f8fSGustavo F. Padovan 		}
69050a708f8fSGustavo F. Padovan 
690689bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
690789bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
6908d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
69094343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
69106be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
69110a708f8fSGustavo F. Padovan 			continue;
69120a708f8fSGustavo F. Padovan 		}
69130a708f8fSGustavo F. Padovan 
691489bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
69156d3c15daSJohan Hedberg 			if (!status)
691693c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
69176d3c15daSJohan Hedberg 			else
6918ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
691989bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
69200a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
6921df3c3931SJohan Hedberg 			__u16 res, stat;
69220a708f8fSGustavo F. Padovan 
69230a708f8fSGustavo F. Padovan 			if (!status) {
6924bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
6925df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
6926df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
69272dc4e510SGustavo Padovan 					chan->ops->defer(chan);
6928df3c3931SJohan Hedberg 				} else {
6929acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
6930df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
6931df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
6932df3c3931SJohan Hedberg 				}
69330a708f8fSGustavo F. Padovan 			} else {
6934acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
6935ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
6936df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
6937df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
69380a708f8fSGustavo F. Padovan 			}
69390a708f8fSGustavo F. Padovan 
6940fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6941fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6942df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
6943df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
6944fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6945fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
69462d369359SMat Martineau 
69472d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
69482d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
69492d369359SMat Martineau 				char buf[128];
69502d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
69512d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
69522d369359SMat Martineau 					       L2CAP_CONF_REQ,
69532d369359SMat Martineau 					       l2cap_build_conf_req(chan, buf),
69542d369359SMat Martineau 					       buf);
69552d369359SMat Martineau 				chan->num_conf_req++;
69562d369359SMat Martineau 			}
69570a708f8fSGustavo F. Padovan 		}
69580a708f8fSGustavo F. Padovan 
69596be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
69600a708f8fSGustavo F. Padovan 	}
69610a708f8fSGustavo F. Padovan 
69623df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
69630a708f8fSGustavo F. Padovan 
69640a708f8fSGustavo F. Padovan 	return 0;
69650a708f8fSGustavo F. Padovan }
69660a708f8fSGustavo F. Padovan 
6967686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
69680a708f8fSGustavo F. Padovan {
69690a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
6970d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
6971d73a0988SAndrei Emeltchenko 	int len;
69720a708f8fSGustavo F. Padovan 
69731d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
69741d13a254SAndrei Emeltchenko 	if (!conn && hcon->hdev->dev_type != HCI_BREDR)
69751d13a254SAndrei Emeltchenko 		goto drop;
69760a708f8fSGustavo F. Padovan 
69770a708f8fSGustavo F. Padovan 	if (!conn)
6978baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
69790a708f8fSGustavo F. Padovan 
69800a708f8fSGustavo F. Padovan 	if (!conn)
69810a708f8fSGustavo F. Padovan 		goto drop;
69820a708f8fSGustavo F. Padovan 
69830a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
69840a708f8fSGustavo F. Padovan 
6985d73a0988SAndrei Emeltchenko 	switch (flags) {
6986d73a0988SAndrei Emeltchenko 	case ACL_START:
6987d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
6988d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
69890a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
69900a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
69910a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
69920a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
69930a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
69940a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
69950a708f8fSGustavo F. Padovan 		}
69960a708f8fSGustavo F. Padovan 
69970a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
69980a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
69990a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
70000a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
70010a708f8fSGustavo F. Padovan 			goto drop;
70020a708f8fSGustavo F. Padovan 		}
70030a708f8fSGustavo F. Padovan 
70040a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
70050a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
70060a708f8fSGustavo F. Padovan 
70070a708f8fSGustavo F. Padovan 		if (len == skb->len) {
70080a708f8fSGustavo F. Padovan 			/* Complete frame received */
70090a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
70100a708f8fSGustavo F. Padovan 			return 0;
70110a708f8fSGustavo F. Padovan 		}
70120a708f8fSGustavo F. Padovan 
70130a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
70140a708f8fSGustavo F. Padovan 
70150a708f8fSGustavo F. Padovan 		if (skb->len > len) {
70160a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
70170a708f8fSGustavo F. Padovan 			       skb->len, len);
70180a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
70190a708f8fSGustavo F. Padovan 			goto drop;
70200a708f8fSGustavo F. Padovan 		}
70210a708f8fSGustavo F. Padovan 
70220a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
70238bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
70240a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
70250a708f8fSGustavo F. Padovan 			goto drop;
70260a708f8fSGustavo F. Padovan 
70270a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
70280a708f8fSGustavo F. Padovan 					  skb->len);
70290a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7030d73a0988SAndrei Emeltchenko 		break;
7031d73a0988SAndrei Emeltchenko 
7032d73a0988SAndrei Emeltchenko 	case ACL_CONT:
70330a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
70340a708f8fSGustavo F. Padovan 
70350a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
70360a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
70370a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
70380a708f8fSGustavo F. Padovan 			goto drop;
70390a708f8fSGustavo F. Padovan 		}
70400a708f8fSGustavo F. Padovan 
70410a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
70420a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
70430a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
70440a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
70450a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
70460a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
70470a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
70480a708f8fSGustavo F. Padovan 			goto drop;
70490a708f8fSGustavo F. Padovan 		}
70500a708f8fSGustavo F. Padovan 
70510a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
70520a708f8fSGustavo F. Padovan 					  skb->len);
70530a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
70540a708f8fSGustavo F. Padovan 
70550a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7056c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7057c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7058c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7059c4e5bafaSJohan Hedberg 			 */
7060c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
70610a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7062c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
70630a708f8fSGustavo F. Padovan 		}
7064d73a0988SAndrei Emeltchenko 		break;
70650a708f8fSGustavo F. Padovan 	}
70660a708f8fSGustavo F. Padovan 
70670a708f8fSGustavo F. Padovan drop:
70680a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70690a708f8fSGustavo F. Padovan 	return 0;
70700a708f8fSGustavo F. Padovan }
70710a708f8fSGustavo F. Padovan 
70720a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
70730a708f8fSGustavo F. Padovan {
707423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
70750a708f8fSGustavo F. Padovan 
7076333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
70770a708f8fSGustavo F. Padovan 
707823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7079fcb73338SAndrei Emeltchenko 		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
70807eafc59eSMarcel Holtmann 			   &c->src, &c->dst,
708189bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
708223691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
708323691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
70840a708f8fSGustavo F. Padovan 	}
70850a708f8fSGustavo F. Padovan 
7086333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
70870a708f8fSGustavo F. Padovan 
70880a708f8fSGustavo F. Padovan 	return 0;
70890a708f8fSGustavo F. Padovan }
70900a708f8fSGustavo F. Padovan 
70910a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
70920a708f8fSGustavo F. Padovan {
70930a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
70940a708f8fSGustavo F. Padovan }
70950a708f8fSGustavo F. Padovan 
70960a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
70970a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
70980a708f8fSGustavo F. Padovan 	.read		= seq_read,
70990a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
71000a708f8fSGustavo F. Padovan 	.release	= single_release,
71010a708f8fSGustavo F. Padovan };
71020a708f8fSGustavo F. Padovan 
71030a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
71040a708f8fSGustavo F. Padovan 
710564274518SGustavo F. Padovan int __init l2cap_init(void)
71060a708f8fSGustavo F. Padovan {
71070a708f8fSGustavo F. Padovan 	int err;
71080a708f8fSGustavo F. Padovan 
7109bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
71100a708f8fSGustavo F. Padovan 	if (err < 0)
71110a708f8fSGustavo F. Padovan 		return err;
71120a708f8fSGustavo F. Padovan 
71131120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
71141120e4bfSMarcel Holtmann 		return 0;
71151120e4bfSMarcel Holtmann 
71162d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
71172d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
71180a708f8fSGustavo F. Padovan 
71190a708f8fSGustavo F. Padovan 	return 0;
71200a708f8fSGustavo F. Padovan }
71210a708f8fSGustavo F. Padovan 
712264274518SGustavo F. Padovan void l2cap_exit(void)
71230a708f8fSGustavo F. Padovan {
71240a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7125bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
71260a708f8fSGustavo F. Padovan }
71270a708f8fSGustavo F. Padovan 
71280a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
71290a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7130