xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision aac23bf6)
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:
610177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
61138319713SJohan Hedberg 		break;
61238319713SJohan Hedberg 
613ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6141a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6151a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6161a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6170a708f8fSGustavo F. Padovan 
618f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6190a708f8fSGustavo F. Padovan 
6203c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6213c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
622ee556f66SGustavo Padovan 
623ee556f66SGustavo Padovan 		/* fall through */
624ee556f66SGustavo Padovan 
625ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
626ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
627ee556f66SGustavo Padovan 		break;
6280a708f8fSGustavo F. Padovan 	}
629ee556f66SGustavo Padovan 
630ee556f66SGustavo Padovan 	return;
6310a708f8fSGustavo F. Padovan }
6320a708f8fSGustavo F. Padovan 
63327e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
63427e2d4c8SJohan Hedberg {
63527e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
63627e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
63727e2d4c8SJohan Hedberg 	u16 result;
63827e2d4c8SJohan Hedberg 
63927e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
64027e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHORIZATION;
64127e2d4c8SJohan Hedberg 	else
64227e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
64327e2d4c8SJohan Hedberg 
64427e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
64527e2d4c8SJohan Hedberg 
64627e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
64727e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
64827e2d4c8SJohan Hedberg 	rsp.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
6490cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
65027e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
65127e2d4c8SJohan Hedberg 
65227e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
65327e2d4c8SJohan Hedberg 		       &rsp);
65427e2d4c8SJohan Hedberg }
65527e2d4c8SJohan Hedberg 
656791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
657791d60f7SJohan Hedberg {
658791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
659791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
660791d60f7SJohan Hedberg 	u16 result;
661791d60f7SJohan Hedberg 
662791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
663791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
664791d60f7SJohan Hedberg 	else
665791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
666791d60f7SJohan Hedberg 
667791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
668791d60f7SJohan Hedberg 
669791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
670791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
671791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
672791d60f7SJohan Hedberg 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
673791d60f7SJohan Hedberg 
674791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
675791d60f7SJohan Hedberg }
676791d60f7SJohan Hedberg 
6770f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
6784519de9aSGustavo F. Padovan {
6794519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6804519de9aSGustavo F. Padovan 
6817eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
6824519de9aSGustavo F. Padovan 
68389bc500eSGustavo F. Padovan 	switch (chan->state) {
6844519de9aSGustavo F. Padovan 	case BT_LISTEN:
685c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
6864519de9aSGustavo F. Padovan 		break;
6874519de9aSGustavo F. Padovan 
6884519de9aSGustavo F. Padovan 	case BT_CONNECTED:
6894519de9aSGustavo F. Padovan 	case BT_CONFIG:
690cea04ce3SJohan Hedberg 		/* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
691cea04ce3SJohan Hedberg 		 * check for chan->psm.
692cea04ce3SJohan Hedberg 		 */
693cea04ce3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
6948d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
6955e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
6964519de9aSGustavo F. Padovan 		} else
6974519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
6984519de9aSGustavo F. Padovan 		break;
6994519de9aSGustavo F. Padovan 
7004519de9aSGustavo F. Padovan 	case BT_CONNECT2:
701791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
702791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
703791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
70427e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
70527e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7064519de9aSGustavo F. Padovan 		}
7074519de9aSGustavo F. Padovan 
7084519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7094519de9aSGustavo F. Padovan 		break;
7104519de9aSGustavo F. Padovan 
7114519de9aSGustavo F. Padovan 	case BT_CONNECT:
7124519de9aSGustavo F. Padovan 	case BT_DISCONN:
7134519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7144519de9aSGustavo F. Padovan 		break;
7154519de9aSGustavo F. Padovan 
7164519de9aSGustavo F. Padovan 	default:
717c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7184519de9aSGustavo F. Padovan 		break;
7194519de9aSGustavo F. Padovan 	}
7204519de9aSGustavo F. Padovan }
7214519de9aSGustavo F. Padovan 
7224343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7230a708f8fSGustavo F. Padovan {
7246a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7256a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7264343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7270a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7280a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7290a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7300a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7310a708f8fSGustavo F. Padovan 		default:
7320a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7330a708f8fSGustavo F. Padovan 		}
7346a974b50SMarcel Holtmann 		break;
7353124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
7363124b843SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
7373124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7383124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7393124b843SMarcel Holtmann 		}
7403124b843SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH)
7413124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7423124b843SMarcel Holtmann 		else
7433124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7443124b843SMarcel Holtmann 		break;
7456a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
7466a974b50SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
7474343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7484343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
7490a708f8fSGustavo F. Padovan 
7504343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_HIGH)
7510a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
7520a708f8fSGustavo F. Padovan 			else
7530a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
7546a974b50SMarcel Holtmann 		}
7556a974b50SMarcel Holtmann 		/* fall through */
7566a974b50SMarcel Holtmann 	default:
7574343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7580a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7590a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
7600a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7610a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
7620a708f8fSGustavo F. Padovan 		default:
7630a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7640a708f8fSGustavo F. Padovan 		}
7656a974b50SMarcel Holtmann 		break;
7660a708f8fSGustavo F. Padovan 	}
7670a708f8fSGustavo F. Padovan }
7680a708f8fSGustavo F. Padovan 
7690a708f8fSGustavo F. Padovan /* Service level security */
770d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
7710a708f8fSGustavo F. Padovan {
7728c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7730a708f8fSGustavo F. Padovan 	__u8 auth_type;
7740a708f8fSGustavo F. Padovan 
775a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
776a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
777a17de2feSJohan Hedberg 
7784343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
7790a708f8fSGustavo F. Padovan 
7804343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
7810a708f8fSGustavo F. Padovan }
7820a708f8fSGustavo F. Padovan 
783b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
7840a708f8fSGustavo F. Padovan {
7850a708f8fSGustavo F. Padovan 	u8 id;
7860a708f8fSGustavo F. Padovan 
7870a708f8fSGustavo F. Padovan 	/* Get next available identificator.
7880a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
7890a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
7900a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
7910a708f8fSGustavo F. Padovan 	 */
7920a708f8fSGustavo F. Padovan 
793333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
7940a708f8fSGustavo F. Padovan 
7950a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
7960a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
7970a708f8fSGustavo F. Padovan 
7980a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
7990a708f8fSGustavo F. Padovan 
800333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
8010a708f8fSGustavo F. Padovan 
8020a708f8fSGustavo F. Padovan 	return id;
8030a708f8fSGustavo F. Padovan }
8040a708f8fSGustavo F. Padovan 
8052d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8062d792818SGustavo Padovan 			   void *data)
8070a708f8fSGustavo F. Padovan {
8080a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8090a708f8fSGustavo F. Padovan 	u8 flags;
8100a708f8fSGustavo F. Padovan 
8110a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8120a708f8fSGustavo F. Padovan 
8130a708f8fSGustavo F. Padovan 	if (!skb)
8140a708f8fSGustavo F. Padovan 		return;
8150a708f8fSGustavo F. Padovan 
8160a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
8170a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8180a708f8fSGustavo F. Padovan 	else
8190a708f8fSGustavo F. Padovan 		flags = ACL_START;
8200a708f8fSGustavo F. Padovan 
82114b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8225e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
82314b12d0bSJaikumar Ganesh 
82473d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8250a708f8fSGustavo F. Padovan }
8260a708f8fSGustavo F. Padovan 
82702b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
82802b0fbb9SMat Martineau {
82902b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
83002b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
83102b0fbb9SMat Martineau }
83202b0fbb9SMat Martineau 
83373d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
83473d80debSLuiz Augusto von Dentz {
83573d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
83673d80debSLuiz Augusto von Dentz 	u16 flags;
83773d80debSLuiz Augusto von Dentz 
83873d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
83973d80debSLuiz Augusto von Dentz 	       skb->priority);
84073d80debSLuiz Augusto von Dentz 
841d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
842d5f8a75dSMat Martineau 		if (chan->hs_hchan)
843d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
844d5f8a75dSMat Martineau 		else
845d5f8a75dSMat Martineau 			kfree_skb(skb);
846d5f8a75dSMat Martineau 
847d5f8a75dSMat Martineau 		return;
848d5f8a75dSMat Martineau 	}
849d5f8a75dSMat Martineau 
85073d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
85173d80debSLuiz Augusto von Dentz 	    lmp_no_flush_capable(hcon->hdev))
85273d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
85373d80debSLuiz Augusto von Dentz 	else
85473d80debSLuiz Augusto von Dentz 		flags = ACL_START;
85573d80debSLuiz Augusto von Dentz 
85673d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
85773d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
8580a708f8fSGustavo F. Padovan }
8590a708f8fSGustavo F. Padovan 
860b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
861b5c6aaedSMat Martineau {
862b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
863b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
864b5c6aaedSMat Martineau 
865b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
866b5c6aaedSMat Martineau 		/* S-Frame */
867b5c6aaedSMat Martineau 		control->sframe = 1;
868b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
869b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
870b5c6aaedSMat Martineau 
871b5c6aaedSMat Martineau 		control->sar = 0;
872b5c6aaedSMat Martineau 		control->txseq = 0;
873b5c6aaedSMat Martineau 	} else {
874b5c6aaedSMat Martineau 		/* I-Frame */
875b5c6aaedSMat Martineau 		control->sframe = 0;
876b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
877b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
878b5c6aaedSMat Martineau 
879b5c6aaedSMat Martineau 		control->poll = 0;
880b5c6aaedSMat Martineau 		control->super = 0;
881b5c6aaedSMat Martineau 	}
882b5c6aaedSMat Martineau }
883b5c6aaedSMat Martineau 
884b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
885b5c6aaedSMat Martineau {
886b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
887b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
888b5c6aaedSMat Martineau 
889b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
890b5c6aaedSMat Martineau 		/* S-Frame */
891b5c6aaedSMat Martineau 		control->sframe = 1;
892b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
893b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
894b5c6aaedSMat Martineau 
895b5c6aaedSMat Martineau 		control->sar = 0;
896b5c6aaedSMat Martineau 		control->txseq = 0;
897b5c6aaedSMat Martineau 	} else {
898b5c6aaedSMat Martineau 		/* I-Frame */
899b5c6aaedSMat Martineau 		control->sframe = 0;
900b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
901b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
902b5c6aaedSMat Martineau 
903b5c6aaedSMat Martineau 		control->poll = 0;
904b5c6aaedSMat Martineau 		control->super = 0;
905b5c6aaedSMat Martineau 	}
906b5c6aaedSMat Martineau }
907b5c6aaedSMat Martineau 
908b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
909b5c6aaedSMat Martineau 				    struct sk_buff *skb)
910b5c6aaedSMat Martineau {
911b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
912b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
913b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
914cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
915b5c6aaedSMat Martineau 	} else {
916b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
917b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
918cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
919b5c6aaedSMat Martineau 	}
920b5c6aaedSMat Martineau }
921b5c6aaedSMat Martineau 
922b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
923b5c6aaedSMat Martineau {
924b5c6aaedSMat Martineau 	u32 packed;
925b5c6aaedSMat Martineau 
926b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
927b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
928b5c6aaedSMat Martineau 
929b5c6aaedSMat Martineau 	if (control->sframe) {
930b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
931b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
932b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
933b5c6aaedSMat Martineau 	} else {
934b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
935b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
936b5c6aaedSMat Martineau 	}
937b5c6aaedSMat Martineau 
938b5c6aaedSMat Martineau 	return packed;
939b5c6aaedSMat Martineau }
940b5c6aaedSMat Martineau 
941b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
942b5c6aaedSMat Martineau {
943b5c6aaedSMat Martineau 	u16 packed;
944b5c6aaedSMat Martineau 
945b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
946b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
947b5c6aaedSMat Martineau 
948b5c6aaedSMat Martineau 	if (control->sframe) {
949b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
950b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
951b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
952b5c6aaedSMat Martineau 	} else {
953b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
954b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
955b5c6aaedSMat Martineau 	}
956b5c6aaedSMat Martineau 
957b5c6aaedSMat Martineau 	return packed;
958b5c6aaedSMat Martineau }
959b5c6aaedSMat Martineau 
960b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
961b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
962b5c6aaedSMat Martineau 				  struct sk_buff *skb)
963b5c6aaedSMat Martineau {
964b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
965b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
966b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
967b5c6aaedSMat Martineau 	} else {
968b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
969b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
970b5c6aaedSMat Martineau 	}
971b5c6aaedSMat Martineau }
972b5c6aaedSMat Martineau 
973ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
974ba7aa64fSGustavo Padovan {
975ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
976ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
977ba7aa64fSGustavo Padovan 	else
978ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
979ba7aa64fSGustavo Padovan }
980ba7aa64fSGustavo Padovan 
981a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
982a67d7f6fSMat Martineau 					       u32 control)
9830a708f8fSGustavo F. Padovan {
9840a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
9850a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
986ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
9870a708f8fSGustavo F. Padovan 
9880a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
98903a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
9900a708f8fSGustavo F. Padovan 
991a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
9920a708f8fSGustavo F. Padovan 
9930a708f8fSGustavo F. Padovan 	if (!skb)
994a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
9950a708f8fSGustavo F. Padovan 
9960a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
9970a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
998fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
99988843ab0SAndrei Emeltchenko 
1000a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1001a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1002a67d7f6fSMat Martineau 	else
1003a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10040a708f8fSGustavo F. Padovan 
100547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1006a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
100703a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10080a708f8fSGustavo F. Padovan 	}
10090a708f8fSGustavo F. Padovan 
101073d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1011a67d7f6fSMat Martineau 	return skb;
1012a67d7f6fSMat Martineau }
1013a67d7f6fSMat Martineau 
1014a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1015a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1016a67d7f6fSMat Martineau {
1017a67d7f6fSMat Martineau 	struct sk_buff *skb;
1018a67d7f6fSMat Martineau 	u32 control_field;
1019a67d7f6fSMat Martineau 
1020a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1021a67d7f6fSMat Martineau 
1022a67d7f6fSMat Martineau 	if (!control->sframe)
1023a67d7f6fSMat Martineau 		return;
1024a67d7f6fSMat Martineau 
1025b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1026b99e13adSMat Martineau 		return;
1027b99e13adSMat Martineau 
1028a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1029a67d7f6fSMat Martineau 	    !control->poll)
1030a67d7f6fSMat Martineau 		control->final = 1;
1031a67d7f6fSMat Martineau 
1032a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1033a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1034a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1035a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1036a67d7f6fSMat Martineau 
1037a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1038a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1039a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1040a67d7f6fSMat Martineau 	}
1041a67d7f6fSMat Martineau 
1042a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1043a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1044a67d7f6fSMat Martineau 
1045a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1046a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1047a67d7f6fSMat Martineau 	else
1048a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1049a67d7f6fSMat Martineau 
1050a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1051a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
105273d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
10530a708f8fSGustavo F. Padovan }
10540a708f8fSGustavo F. Padovan 
1055c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
10560a708f8fSGustavo F. Padovan {
1057c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
10580a708f8fSGustavo F. Padovan 
1059c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1060c9e3d5e0SMat Martineau 
1061c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1062c9e3d5e0SMat Martineau 	control.sframe = 1;
1063c9e3d5e0SMat Martineau 	control.poll = poll;
1064c9e3d5e0SMat Martineau 
1065c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1066c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1067c9e3d5e0SMat Martineau 	else
1068c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1069c9e3d5e0SMat Martineau 
1070c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1071c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
10720a708f8fSGustavo F. Padovan }
10730a708f8fSGustavo F. Padovan 
1074b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
10750a708f8fSGustavo F. Padovan {
1076c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
10770a708f8fSGustavo F. Padovan }
10780a708f8fSGustavo F. Padovan 
107993c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
108093c3e8f5SAndrei Emeltchenko {
108193c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
10821df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
10831df7b17aSMarcel Holtmann 	bool amp_available = false;
108493c3e8f5SAndrei Emeltchenko 
10851df7b17aSMarcel Holtmann 	if (!conn->hs_enabled)
10861df7b17aSMarcel Holtmann 		return false;
10871df7b17aSMarcel Holtmann 
10881df7b17aSMarcel Holtmann 	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
10891df7b17aSMarcel Holtmann 		return false;
10901df7b17aSMarcel Holtmann 
10911df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
10921df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
10931df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
10941df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
10951df7b17aSMarcel Holtmann 			amp_available = true;
10961df7b17aSMarcel Holtmann 			break;
10971df7b17aSMarcel Holtmann 		}
10981df7b17aSMarcel Holtmann 	}
10991df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
11001df7b17aSMarcel Holtmann 
11011df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11021df7b17aSMarcel Holtmann 		return amp_available;
1103848566b3SMarcel Holtmann 
110493c3e8f5SAndrei Emeltchenko 	return false;
110593c3e8f5SAndrei Emeltchenko }
110693c3e8f5SAndrei Emeltchenko 
11075ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11085ce66b59SAndrei Emeltchenko {
11095ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11105ce66b59SAndrei Emeltchenko 	return true;
11115ce66b59SAndrei Emeltchenko }
11125ce66b59SAndrei Emeltchenko 
11132766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11149b27f350SAndrei Emeltchenko {
11159b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11169b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11179b27f350SAndrei Emeltchenko 
11189b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11199b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11209b27f350SAndrei Emeltchenko 
11219b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11229b27f350SAndrei Emeltchenko 
11239b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11249b27f350SAndrei Emeltchenko 
11259b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11269b27f350SAndrei Emeltchenko }
11279b27f350SAndrei Emeltchenko 
11288eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11298eb200bdSMat Martineau {
11308eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11318eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11328eb200bdSMat Martineau 	req.psm  = chan->psm;
11338eb200bdSMat Martineau 	req.amp_id = amp_id;
11348eb200bdSMat Martineau 
11358eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
11368eb200bdSMat Martineau 
11378eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
11388eb200bdSMat Martineau 		       sizeof(req), &req);
11398eb200bdSMat Martineau }
11408eb200bdSMat Martineau 
114102b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
114202b0fbb9SMat Martineau {
114302b0fbb9SMat Martineau 	struct sk_buff *skb;
114402b0fbb9SMat Martineau 
114502b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
114602b0fbb9SMat Martineau 
114702b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
114802b0fbb9SMat Martineau 		return;
114902b0fbb9SMat Martineau 
115002b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
115102b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
115202b0fbb9SMat Martineau 	__clear_ack_timer(chan);
115302b0fbb9SMat Martineau 
115402b0fbb9SMat Martineau 	chan->retry_count = 0;
115502b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
115602b0fbb9SMat Martineau 		if (bt_cb(skb)->control.retries)
115702b0fbb9SMat Martineau 			bt_cb(skb)->control.retries = 1;
115802b0fbb9SMat Martineau 		else
115902b0fbb9SMat Martineau 			break;
116002b0fbb9SMat Martineau 	}
116102b0fbb9SMat Martineau 
116202b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
116302b0fbb9SMat Martineau 
116402b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
116502b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
116602b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
116702b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
116802b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
116902b0fbb9SMat Martineau 
117002b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
117102b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
117202b0fbb9SMat Martineau 
117302b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
117402b0fbb9SMat Martineau }
117502b0fbb9SMat Martineau 
11765f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
11775f3847a4SMat Martineau {
11785f3847a4SMat Martineau 	u8 move_role = chan->move_role;
11795f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
11805f3847a4SMat Martineau 
11815f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
11825f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
11835f3847a4SMat Martineau 
11845f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
11855f3847a4SMat Martineau 		return;
11865f3847a4SMat Martineau 
11875f3847a4SMat Martineau 	switch (move_role) {
11885f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
11895f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
11905f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
11915f3847a4SMat Martineau 		break;
11925f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
11935f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
11945f3847a4SMat Martineau 		break;
11955f3847a4SMat Martineau 	}
11965f3847a4SMat Martineau }
11975f3847a4SMat Martineau 
1198177f8f2bSJohan Hedberg static void l2cap_le_flowctl_start(struct l2cap_chan *chan)
1199177f8f2bSJohan Hedberg {
1200177f8f2bSJohan Hedberg 	chan->sdu = NULL;
1201177f8f2bSJohan Hedberg 	chan->sdu_last_frag = NULL;
1202177f8f2bSJohan Hedberg 	chan->sdu_len = 0;
1203177f8f2bSJohan Hedberg 
1204177f8f2bSJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
1205177f8f2bSJohan Hedberg }
1206177f8f2bSJohan Hedberg 
12079f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12089f0caeb1SVinicius Costa Gomes {
12092827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12109f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12119f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12129f0caeb1SVinicius Costa Gomes 
1213177f8f2bSJohan Hedberg 	if (chan->mode == L2CAP_MODE_LE_FLOWCTL)
1214177f8f2bSJohan Hedberg 		l2cap_le_flowctl_start(chan);
1215177f8f2bSJohan Hedberg 
121654a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12179f0caeb1SVinicius Costa Gomes 
121854a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12199f0caeb1SVinicius Costa Gomes }
12209f0caeb1SVinicius Costa Gomes 
1221f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1222f1496deeSJohan Hedberg {
1223f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1224f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1225f1496deeSJohan Hedberg 
1226f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1227f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1228f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
1229f1496deeSJohan Hedberg 	req.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
12300cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1231f1496deeSJohan Hedberg 
1232f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1233f1496deeSJohan Hedberg 
1234f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1235f1496deeSJohan Hedberg 		       sizeof(req), &req);
1236f1496deeSJohan Hedberg }
1237f1496deeSJohan Hedberg 
1238f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1239f1496deeSJohan Hedberg {
1240f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1241f1496deeSJohan Hedberg 
1242f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1243f1496deeSJohan Hedberg 		return;
1244f1496deeSJohan Hedberg 
1245f1496deeSJohan Hedberg 	if (!chan->psm) {
1246f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1247f1496deeSJohan Hedberg 		return;
1248f1496deeSJohan Hedberg 	}
1249f1496deeSJohan Hedberg 
1250f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1251f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1252f1496deeSJohan Hedberg }
1253f1496deeSJohan Hedberg 
125493c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
125593c3e8f5SAndrei Emeltchenko {
125693c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
125793c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
125893c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1259f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1260f1496deeSJohan Hedberg 		l2cap_le_start(chan);
126193c3e8f5SAndrei Emeltchenko 	} else {
126293c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
126393c3e8f5SAndrei Emeltchenko 	}
126493c3e8f5SAndrei Emeltchenko }
126593c3e8f5SAndrei Emeltchenko 
1266fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
12670a708f8fSGustavo F. Padovan {
12688c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
12690a708f8fSGustavo F. Padovan 
12709f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
127196ac34fbSJohan Hedberg 		l2cap_le_start(chan);
12729f0caeb1SVinicius Costa Gomes 		return;
12739f0caeb1SVinicius Costa Gomes 	}
12749f0caeb1SVinicius Costa Gomes 
12750a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
12760a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
12770a708f8fSGustavo F. Padovan 			return;
12780a708f8fSGustavo F. Padovan 
1279d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
128093c3e8f5SAndrei Emeltchenko 		    __l2cap_no_conn_pending(chan)) {
128193c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
128293c3e8f5SAndrei Emeltchenko 		}
12830a708f8fSGustavo F. Padovan 	} else {
12840a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
1285ac73498cSAndrei Emeltchenko 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
12860a708f8fSGustavo F. Padovan 
12870a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
12880a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
12890a708f8fSGustavo F. Padovan 
1290ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
12910a708f8fSGustavo F. Padovan 
12922d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
12932d792818SGustavo Padovan 			       sizeof(req), &req);
12940a708f8fSGustavo F. Padovan 	}
12950a708f8fSGustavo F. Padovan }
12960a708f8fSGustavo F. Padovan 
12970a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
12980a708f8fSGustavo F. Padovan {
12990a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
13000a708f8fSGustavo F. Padovan 	if (!disable_ertm)
13010a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
13020a708f8fSGustavo F. Padovan 
13030a708f8fSGustavo F. Padovan 	switch (mode) {
13040a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
13050a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
13060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
13070a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
13080a708f8fSGustavo F. Padovan 	default:
13090a708f8fSGustavo F. Padovan 		return 0x00;
13100a708f8fSGustavo F. Padovan 	}
13110a708f8fSGustavo F. Padovan }
13120a708f8fSGustavo F. Padovan 
13135e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
13140a708f8fSGustavo F. Padovan {
13155e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
13160a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
13170a708f8fSGustavo F. Padovan 
13180a708f8fSGustavo F. Padovan 	if (!conn)
13190a708f8fSGustavo F. Padovan 		return;
13200a708f8fSGustavo F. Padovan 
1321aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
13221a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
13231a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
13241a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
13250a708f8fSGustavo F. Padovan 	}
13260a708f8fSGustavo F. Padovan 
1327416fa752SAndrei Emeltchenko 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1328d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1329416fa752SAndrei Emeltchenko 		return;
1330416fa752SAndrei Emeltchenko 	}
1331416fa752SAndrei Emeltchenko 
1332fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1333fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
13342d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
13352d792818SGustavo Padovan 		       sizeof(req), &req);
13360a708f8fSGustavo F. Padovan 
1337f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
13380a708f8fSGustavo F. Padovan }
13390a708f8fSGustavo F. Padovan 
13400a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
13410a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
13420a708f8fSGustavo F. Padovan {
13433df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
13440a708f8fSGustavo F. Padovan 
13450a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
13460a708f8fSGustavo F. Padovan 
13473df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13480a708f8fSGustavo F. Padovan 
13493df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
13506be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13510a708f8fSGustavo F. Padovan 
1352715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
13536be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
13540a708f8fSGustavo F. Padovan 			continue;
13550a708f8fSGustavo F. Padovan 		}
13560a708f8fSGustavo F. Padovan 
135789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1358d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1359b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
13606be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13610a708f8fSGustavo F. Padovan 				continue;
13620a708f8fSGustavo F. Padovan 			}
13630a708f8fSGustavo F. Padovan 
1364c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1365c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1366c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
13670f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
13686be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13690a708f8fSGustavo F. Padovan 				continue;
13700a708f8fSGustavo F. Padovan 			}
13710a708f8fSGustavo F. Padovan 
137293c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
13730a708f8fSGustavo F. Padovan 
137489bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
13750a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
13760a708f8fSGustavo F. Padovan 			char buf[128];
1377fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1378fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
13790a708f8fSGustavo F. Padovan 
1380d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
1381bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1382ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1383ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
13842dc4e510SGustavo Padovan 					chan->ops->defer(chan);
13850a708f8fSGustavo F. Padovan 
13860a708f8fSGustavo F. Padovan 				} else {
1387acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1388ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1389ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
13900a708f8fSGustavo F. Padovan 				}
13910a708f8fSGustavo F. Padovan 			} else {
1392ac73498cSAndrei Emeltchenko 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1393ac73498cSAndrei Emeltchenko 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
13940a708f8fSGustavo F. Padovan 			}
13950a708f8fSGustavo F. Padovan 
1396fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1397fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
13980a708f8fSGustavo F. Padovan 
1399c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
14000a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
14016be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14020a708f8fSGustavo F. Padovan 				continue;
14030a708f8fSGustavo F. Padovan 			}
14040a708f8fSGustavo F. Padovan 
1405c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
14060a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
140773ffa904SGustavo F. Padovan 				       l2cap_build_conf_req(chan, buf), buf);
140873ffa904SGustavo F. Padovan 			chan->num_conf_req++;
14090a708f8fSGustavo F. Padovan 		}
14100a708f8fSGustavo F. Padovan 
14116be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
14120a708f8fSGustavo F. Padovan 	}
14130a708f8fSGustavo F. Padovan 
14143df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
14150a708f8fSGustavo F. Padovan }
14160a708f8fSGustavo F. Padovan 
1417c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1418b62f328bSVille Tervo  * Returns closest match, locked.
1419b62f328bSVille Tervo  */
1420d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1421c2287681SIdo Yariv 						    bdaddr_t *src,
1422c2287681SIdo Yariv 						    bdaddr_t *dst)
1423b62f328bSVille Tervo {
142423691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1425b62f328bSVille Tervo 
142623691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1427b62f328bSVille Tervo 
142823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
142989bc500eSGustavo F. Padovan 		if (state && c->state != state)
1430b62f328bSVille Tervo 			continue;
1431b62f328bSVille Tervo 
143223691d75SGustavo F. Padovan 		if (c->scid == cid) {
1433c2287681SIdo Yariv 			int src_match, dst_match;
1434c2287681SIdo Yariv 			int src_any, dst_any;
1435c2287681SIdo Yariv 
1436b62f328bSVille Tervo 			/* Exact match. */
14377eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
14387eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1439c2287681SIdo Yariv 			if (src_match && dst_match) {
144023691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
144123691d75SGustavo F. Padovan 				return c;
144223691d75SGustavo F. Padovan 			}
1443b62f328bSVille Tervo 
1444b62f328bSVille Tervo 			/* Closest match */
14457eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
14467eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1447c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1448c2287681SIdo Yariv 			    (src_any && dst_any))
144923691d75SGustavo F. Padovan 				c1 = c;
1450b62f328bSVille Tervo 		}
1451b62f328bSVille Tervo 	}
1452280f294fSGustavo F. Padovan 
145323691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1454b62f328bSVille Tervo 
145523691d75SGustavo F. Padovan 	return c1;
1456b62f328bSVille Tervo }
1457b62f328bSVille Tervo 
1458b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1459b62f328bSVille Tervo {
1460cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
146123691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1462cc8dba2bSMarcel Holtmann 	u8 dst_type;
1463b62f328bSVille Tervo 
1464b62f328bSVille Tervo 	BT_DBG("");
1465b62f328bSVille Tervo 
1466b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
1467073d1cf3SJohan Hedberg 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
1468cc8dba2bSMarcel Holtmann 					  &hcon->src, &hcon->dst);
146923691d75SGustavo F. Padovan 	if (!pchan)
1470b62f328bSVille Tervo 		return;
1471b62f328bSVille Tervo 
147244f3b0fbSJohan Hedberg 	/* Client ATT sockets should override the server one */
147344f3b0fbSJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
147444f3b0fbSJohan Hedberg 		return;
147544f3b0fbSJohan Hedberg 
1476cc8dba2bSMarcel Holtmann 	dst_type = bdaddr_type(hcon, hcon->dst_type);
1477cc8dba2bSMarcel Holtmann 
1478cc8dba2bSMarcel Holtmann 	/* If device is blocked, do not create a channel for it */
1479cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
1480cc8dba2bSMarcel Holtmann 		return;
1481cc8dba2bSMarcel Holtmann 
14828ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
148362f3a2cfSGustavo F. Padovan 
148480b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
148580808e43SGustavo F. Padovan 	if (!chan)
1486b62f328bSVille Tervo 		goto clean;
1487b62f328bSVille Tervo 
14889f22398cSJohan Hedberg 	chan->dcid = L2CAP_CID_ATT;
14899f22398cSJohan Hedberg 
1490cc8dba2bSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
1491cc8dba2bSMarcel Holtmann 	bacpy(&chan->dst, &hcon->dst);
1492cc8dba2bSMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
1493cc8dba2bSMarcel Holtmann 	chan->dst_type = dst_type;
1494b62f328bSVille Tervo 
149544f3b0fbSJohan Hedberg 	__l2cap_chan_add(conn, chan);
149648454079SGustavo F. Padovan 
1497b62f328bSVille Tervo clean:
14988ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
1499b62f328bSVille Tervo }
1500b62f328bSVille Tervo 
15010a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
15020a708f8fSGustavo F. Padovan {
150348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1504cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
15050a708f8fSGustavo F. Padovan 
15060a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15070a708f8fSGustavo F. Padovan 
1508d8729922SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1509d8729922SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1510d8729922SJohan Hedberg 	 */
1511cc110922SVinicius Costa Gomes 	if (hcon->out && hcon->type == LE_LINK)
1512cc110922SVinicius Costa Gomes 		smp_conn_security(hcon, hcon->pending_sec_level);
1513160dc6acSVinicius Costa Gomes 
15143df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15150a708f8fSGustavo F. Padovan 
151644f3b0fbSJohan Hedberg 	if (hcon->type == LE_LINK)
151744f3b0fbSJohan Hedberg 		l2cap_le_conn_ready(conn);
151844f3b0fbSJohan Hedberg 
15193df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1520baa7e1faSGustavo F. Padovan 
15216be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15220a708f8fSGustavo F. Padovan 
1523416fa752SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1524416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1525416fa752SAndrei Emeltchenko 			continue;
1526416fa752SAndrei Emeltchenko 		}
1527416fa752SAndrei Emeltchenko 
1528cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1529f1496deeSJohan Hedberg 			l2cap_le_start(chan);
153063128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
153174e75740SGustavo Padovan 			l2cap_chan_ready(chan);
1532b501d6a1SAnderson Briglia 
15331c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1534fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15351c244f79SGustavo Padovan 		}
15360a708f8fSGustavo F. Padovan 
15376be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15380a708f8fSGustavo F. Padovan 	}
15390a708f8fSGustavo F. Padovan 
15403df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15410a708f8fSGustavo F. Padovan }
15420a708f8fSGustavo F. Padovan 
15430a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15440a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15450a708f8fSGustavo F. Padovan {
154648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15470a708f8fSGustavo F. Padovan 
15480a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15490a708f8fSGustavo F. Padovan 
15503df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15510a708f8fSGustavo F. Padovan 
15523df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1553ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
15541d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
15550a708f8fSGustavo F. Padovan 	}
15560a708f8fSGustavo F. Padovan 
15573df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15580a708f8fSGustavo F. Padovan }
15590a708f8fSGustavo F. Padovan 
1560f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
15610a708f8fSGustavo F. Padovan {
1562f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1563030013d8SGustavo F. Padovan 					       info_timer.work);
15640a708f8fSGustavo F. Padovan 
15650a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
15660a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
15670a708f8fSGustavo F. Padovan 
15680a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
15690a708f8fSGustavo F. Padovan }
15700a708f8fSGustavo F. Padovan 
15712c8e1411SDavid Herrmann /*
15722c8e1411SDavid Herrmann  * l2cap_user
15732c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
15742c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
15752c8e1411SDavid Herrmann  * during unregistration.
15762c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
15772c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
15782c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
15792c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
15802c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
15812c8e1411SDavid Herrmann  * any time if they don't.
15822c8e1411SDavid Herrmann  */
15832c8e1411SDavid Herrmann 
15842c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
15852c8e1411SDavid Herrmann {
15862c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
15872c8e1411SDavid Herrmann 	int ret;
15882c8e1411SDavid Herrmann 
15892c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
15902c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
15912c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
15922c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
15932c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
15942c8e1411SDavid Herrmann 	 * here, too. */
15952c8e1411SDavid Herrmann 
15962c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
15972c8e1411SDavid Herrmann 
15982c8e1411SDavid Herrmann 	if (user->list.next || user->list.prev) {
15992c8e1411SDavid Herrmann 		ret = -EINVAL;
16002c8e1411SDavid Herrmann 		goto out_unlock;
16012c8e1411SDavid Herrmann 	}
16022c8e1411SDavid Herrmann 
16032c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
16042c8e1411SDavid Herrmann 	if (!conn->hchan) {
16052c8e1411SDavid Herrmann 		ret = -ENODEV;
16062c8e1411SDavid Herrmann 		goto out_unlock;
16072c8e1411SDavid Herrmann 	}
16082c8e1411SDavid Herrmann 
16092c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
16102c8e1411SDavid Herrmann 	if (ret)
16112c8e1411SDavid Herrmann 		goto out_unlock;
16122c8e1411SDavid Herrmann 
16132c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16142c8e1411SDavid Herrmann 	ret = 0;
16152c8e1411SDavid Herrmann 
16162c8e1411SDavid Herrmann out_unlock:
16172c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16182c8e1411SDavid Herrmann 	return ret;
16192c8e1411SDavid Herrmann }
16202c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16212c8e1411SDavid Herrmann 
16222c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16232c8e1411SDavid Herrmann {
16242c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16252c8e1411SDavid Herrmann 
16262c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16272c8e1411SDavid Herrmann 
16282c8e1411SDavid Herrmann 	if (!user->list.next || !user->list.prev)
16292c8e1411SDavid Herrmann 		goto out_unlock;
16302c8e1411SDavid Herrmann 
16312c8e1411SDavid Herrmann 	list_del(&user->list);
16322c8e1411SDavid Herrmann 	user->list.next = NULL;
16332c8e1411SDavid Herrmann 	user->list.prev = NULL;
16342c8e1411SDavid Herrmann 	user->remove(conn, user);
16352c8e1411SDavid Herrmann 
16362c8e1411SDavid Herrmann out_unlock:
16372c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16382c8e1411SDavid Herrmann }
16392c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16402c8e1411SDavid Herrmann 
16412c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16422c8e1411SDavid Herrmann {
16432c8e1411SDavid Herrmann 	struct l2cap_user *user;
16442c8e1411SDavid Herrmann 
16452c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16462c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
16472c8e1411SDavid Herrmann 		list_del(&user->list);
16482c8e1411SDavid Herrmann 		user->list.next = NULL;
16492c8e1411SDavid Herrmann 		user->list.prev = NULL;
16502c8e1411SDavid Herrmann 		user->remove(conn, user);
16512c8e1411SDavid Herrmann 	}
16522c8e1411SDavid Herrmann }
16532c8e1411SDavid Herrmann 
16545d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
16555d3de7dfSVinicius Costa Gomes {
16565d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
16575d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
16585d3de7dfSVinicius Costa Gomes 
16595d3de7dfSVinicius Costa Gomes 	if (!conn)
16605d3de7dfSVinicius Costa Gomes 		return;
16615d3de7dfSVinicius Costa Gomes 
16625d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
16635d3de7dfSVinicius Costa Gomes 
16645d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
16655d3de7dfSVinicius Costa Gomes 
16662c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
16672c8e1411SDavid Herrmann 
16683df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16693df91ea2SAndrei Emeltchenko 
16705d3de7dfSVinicius Costa Gomes 	/* Kill channels */
16715d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
167261d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
16736be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16746be36555SAndrei Emeltchenko 
16755d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
16766be36555SAndrei Emeltchenko 
16776be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16786be36555SAndrei Emeltchenko 
167980b98027SGustavo Padovan 		chan->ops->close(chan);
168061d6ef3eSMat Martineau 		l2cap_chan_put(chan);
16815d3de7dfSVinicius Costa Gomes 	}
16825d3de7dfSVinicius Costa Gomes 
16833df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16843df91ea2SAndrei Emeltchenko 
168573d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
168673d80debSLuiz Augusto von Dentz 
16875d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1688127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
16895d3de7dfSVinicius Costa Gomes 
169051a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1691127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
16928aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1693d26a2345SVinicius Costa Gomes 	}
16945d3de7dfSVinicius Costa Gomes 
16955d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
16969c903e37SDavid Herrmann 	conn->hchan = NULL;
16979c903e37SDavid Herrmann 	l2cap_conn_put(conn);
16985d3de7dfSVinicius Costa Gomes }
16995d3de7dfSVinicius Costa Gomes 
17006c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
17015d3de7dfSVinicius Costa Gomes {
17026c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
17036c9d42a1SGustavo F. Padovan 					       security_timer.work);
17045d3de7dfSVinicius Costa Gomes 
1705d06cc416SJohan Hedberg 	BT_DBG("conn %p", conn);
1706d06cc416SJohan Hedberg 
1707d06cc416SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1708d06cc416SJohan Hedberg 		smp_chan_destroy(conn);
17095d3de7dfSVinicius Costa Gomes 		l2cap_conn_del(conn->hcon, ETIMEDOUT);
17105d3de7dfSVinicius Costa Gomes 	}
1711d06cc416SJohan Hedberg }
17125d3de7dfSVinicius Costa Gomes 
1713baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
17140a708f8fSGustavo F. Padovan {
17150a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
171673d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
17170a708f8fSGustavo F. Padovan 
1718baf43251SClaudio Takahasi 	if (conn)
17190a708f8fSGustavo F. Padovan 		return conn;
17200a708f8fSGustavo F. Padovan 
172173d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
172273d80debSLuiz Augusto von Dentz 	if (!hchan)
17230a708f8fSGustavo F. Padovan 		return NULL;
17240a708f8fSGustavo F. Padovan 
17258bcde1f2SGustavo Padovan 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
172673d80debSLuiz Augusto von Dentz 	if (!conn) {
172773d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
172873d80debSLuiz Augusto von Dentz 		return NULL;
172973d80debSLuiz Augusto von Dentz 	}
173073d80debSLuiz Augusto von Dentz 
17319c903e37SDavid Herrmann 	kref_init(&conn->ref);
17320a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
17330a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
17349c903e37SDavid Herrmann 	hci_conn_get(conn->hcon);
173573d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
17360a708f8fSGustavo F. Padovan 
173773d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
17380a708f8fSGustavo F. Padovan 
1739dcc042d5SAndrei Emeltchenko 	switch (hcon->type) {
1740dcc042d5SAndrei Emeltchenko 	case LE_LINK:
1741dcc042d5SAndrei Emeltchenko 		if (hcon->hdev->le_mtu) {
1742acd7d370SVille Tervo 			conn->mtu = hcon->hdev->le_mtu;
1743dcc042d5SAndrei Emeltchenko 			break;
1744dcc042d5SAndrei Emeltchenko 		}
1745dcc042d5SAndrei Emeltchenko 		/* fall through */
1746dcc042d5SAndrei Emeltchenko 	default:
17470a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1748dcc042d5SAndrei Emeltchenko 		break;
1749dcc042d5SAndrei Emeltchenko 	}
1750acd7d370SVille Tervo 
17510a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
17520a708f8fSGustavo F. Padovan 
1753848566b3SMarcel Holtmann 	if (hcon->type == ACL_LINK)
1754848566b3SMarcel Holtmann 		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
1755848566b3SMarcel Holtmann 					    &hcon->hdev->dev_flags);
1756848566b3SMarcel Holtmann 
17570a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
17583df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1759baa7e1faSGustavo F. Padovan 
1760baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
17612c8e1411SDavid Herrmann 	INIT_LIST_HEAD(&conn->users);
17620a708f8fSGustavo F. Padovan 
17635d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
17646c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
17655d3de7dfSVinicius Costa Gomes 	else
1766030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
17670a708f8fSGustavo F. Padovan 
17689f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
17690a708f8fSGustavo F. Padovan 
17700a708f8fSGustavo F. Padovan 	return conn;
17710a708f8fSGustavo F. Padovan }
17720a708f8fSGustavo F. Padovan 
17739c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17749c903e37SDavid Herrmann {
17759c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17769c903e37SDavid Herrmann 
17779c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17789c903e37SDavid Herrmann 	kfree(conn);
17799c903e37SDavid Herrmann }
17809c903e37SDavid Herrmann 
17819c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn)
17829c903e37SDavid Herrmann {
17839c903e37SDavid Herrmann 	kref_get(&conn->ref);
17849c903e37SDavid Herrmann }
17859c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
17869c903e37SDavid Herrmann 
17879c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
17889c903e37SDavid Herrmann {
17899c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
17909c903e37SDavid Herrmann }
17919c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
17929c903e37SDavid Herrmann 
17930a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
17940a708f8fSGustavo F. Padovan 
1795c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
17960a708f8fSGustavo F. Padovan  * Returns closest match.
17970a708f8fSGustavo F. Padovan  */
1798c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1799c2287681SIdo Yariv 						   bdaddr_t *src,
1800bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1801bf20fd4eSJohan Hedberg 						   u8 link_type)
18020a708f8fSGustavo F. Padovan {
180323691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
18040a708f8fSGustavo F. Padovan 
180523691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
18060a708f8fSGustavo F. Padovan 
180723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
180889bc500eSGustavo F. Padovan 		if (state && c->state != state)
18090a708f8fSGustavo F. Padovan 			continue;
18100a708f8fSGustavo F. Padovan 
1811bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1812bf20fd4eSJohan Hedberg 			continue;
1813bf20fd4eSJohan Hedberg 
1814bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1815bf20fd4eSJohan Hedberg 			continue;
1816bf20fd4eSJohan Hedberg 
181723691d75SGustavo F. Padovan 		if (c->psm == psm) {
1818c2287681SIdo Yariv 			int src_match, dst_match;
1819c2287681SIdo Yariv 			int src_any, dst_any;
1820c2287681SIdo Yariv 
18210a708f8fSGustavo F. Padovan 			/* Exact match. */
18227eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18237eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1824c2287681SIdo Yariv 			if (src_match && dst_match) {
1825a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
182623691d75SGustavo F. Padovan 				return c;
182723691d75SGustavo F. Padovan 			}
18280a708f8fSGustavo F. Padovan 
18290a708f8fSGustavo F. Padovan 			/* Closest match */
18307eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18317eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1832c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1833c2287681SIdo Yariv 			    (src_any && dst_any))
183423691d75SGustavo F. Padovan 				c1 = c;
18350a708f8fSGustavo F. Padovan 		}
18360a708f8fSGustavo F. Padovan 	}
18370a708f8fSGustavo F. Padovan 
183823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18390a708f8fSGustavo F. Padovan 
184023691d75SGustavo F. Padovan 	return c1;
18410a708f8fSGustavo F. Padovan }
18420a708f8fSGustavo F. Padovan 
18438e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
18448e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
18450a708f8fSGustavo F. Padovan {
18460a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
18470a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
18480a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
18490a708f8fSGustavo F. Padovan 	__u8 auth_type;
18500a708f8fSGustavo F. Padovan 	int err;
18510a708f8fSGustavo F. Padovan 
18527eafc59eSMarcel Holtmann 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
1853ab19516aSSyam Sidhardhan 	       dst_type, __le16_to_cpu(psm));
18540a708f8fSGustavo F. Padovan 
18557eafc59eSMarcel Holtmann 	hdev = hci_get_route(dst, &chan->src);
18560a708f8fSGustavo F. Padovan 	if (!hdev)
18570a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
18580a708f8fSGustavo F. Padovan 
185909fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
18600a708f8fSGustavo F. Padovan 
18616be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
186203a00194SGustavo F. Padovan 
186303a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
186403a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
186503a00194SGustavo F. Padovan 	    chan->chan_type != L2CAP_CHAN_RAW) {
186603a00194SGustavo F. Padovan 		err = -EINVAL;
186703a00194SGustavo F. Padovan 		goto done;
186803a00194SGustavo F. Padovan 	}
186903a00194SGustavo F. Padovan 
187003a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
187103a00194SGustavo F. Padovan 		err = -EINVAL;
187203a00194SGustavo F. Padovan 		goto done;
187303a00194SGustavo F. Padovan 	}
187403a00194SGustavo F. Padovan 
187503a00194SGustavo F. Padovan 	switch (chan->mode) {
187603a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
187738319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
187803a00194SGustavo F. Padovan 		break;
187903a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
188003a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
188103a00194SGustavo F. Padovan 		if (!disable_ertm)
188203a00194SGustavo F. Padovan 			break;
188303a00194SGustavo F. Padovan 		/* fall through */
188403a00194SGustavo F. Padovan 	default:
188503a00194SGustavo F. Padovan 		err = -ENOTSUPP;
188603a00194SGustavo F. Padovan 		goto done;
188703a00194SGustavo F. Padovan 	}
188803a00194SGustavo F. Padovan 
18890797e01dSGustavo Padovan 	switch (chan->state) {
189003a00194SGustavo F. Padovan 	case BT_CONNECT:
189103a00194SGustavo F. Padovan 	case BT_CONNECT2:
189203a00194SGustavo F. Padovan 	case BT_CONFIG:
189303a00194SGustavo F. Padovan 		/* Already connecting */
189403a00194SGustavo F. Padovan 		err = 0;
189503a00194SGustavo F. Padovan 		goto done;
189603a00194SGustavo F. Padovan 
189703a00194SGustavo F. Padovan 	case BT_CONNECTED:
189803a00194SGustavo F. Padovan 		/* Already connected */
189903a00194SGustavo F. Padovan 		err = -EISCONN;
190003a00194SGustavo F. Padovan 		goto done;
190103a00194SGustavo F. Padovan 
190203a00194SGustavo F. Padovan 	case BT_OPEN:
190303a00194SGustavo F. Padovan 	case BT_BOUND:
190403a00194SGustavo F. Padovan 		/* Can connect */
190503a00194SGustavo F. Padovan 		break;
190603a00194SGustavo F. Padovan 
190703a00194SGustavo F. Padovan 	default:
190803a00194SGustavo F. Padovan 		err = -EBADFD;
190903a00194SGustavo F. Padovan 		goto done;
191003a00194SGustavo F. Padovan 	}
191103a00194SGustavo F. Padovan 
191203a00194SGustavo F. Padovan 	/* Set destination address and psm */
19137eafc59eSMarcel Holtmann 	bacpy(&chan->dst, dst);
19144f1654e0SMarcel Holtmann 	chan->dst_type = dst_type;
19156be36555SAndrei Emeltchenko 
191603a00194SGustavo F. Padovan 	chan->psm = psm;
191703a00194SGustavo F. Padovan 	chan->dcid = cid;
19180a708f8fSGustavo F. Padovan 
19194343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
19200a708f8fSGustavo F. Padovan 
1921f224ca5fSJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
19228e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
19234343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1924acd7d370SVille Tervo 	else
19258e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
19264343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1927acd7d370SVille Tervo 
192830e76272SVille Tervo 	if (IS_ERR(hcon)) {
192930e76272SVille Tervo 		err = PTR_ERR(hcon);
19300a708f8fSGustavo F. Padovan 		goto done;
193130e76272SVille Tervo 	}
19320a708f8fSGustavo F. Padovan 
1933baf43251SClaudio Takahasi 	conn = l2cap_conn_add(hcon);
19340a708f8fSGustavo F. Padovan 	if (!conn) {
193576a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
193630e76272SVille Tervo 		err = -ENOMEM;
19370a708f8fSGustavo F. Padovan 		goto done;
19380a708f8fSGustavo F. Padovan 	}
19390a708f8fSGustavo F. Padovan 
1940141d5706SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
194176a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
1942141d5706SJohan Hedberg 		err = -EBUSY;
19439f0caeb1SVinicius Costa Gomes 		goto done;
19449f0caeb1SVinicius Costa Gomes 	}
19459f0caeb1SVinicius Costa Gomes 
19460a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
19477eafc59eSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
19484f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
19490a708f8fSGustavo F. Padovan 
19506be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
195148454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
19526be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
195348454079SGustavo F. Padovan 
19545ee9891dSJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
19555ee9891dSJohan Hedberg 	hci_conn_drop(hcon);
19565ee9891dSJohan Hedberg 
19576be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
19588d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
19590a708f8fSGustavo F. Padovan 
19600a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1961715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1962c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1963d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
19646be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
19650a708f8fSGustavo F. Padovan 		} else
1966fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
19670a708f8fSGustavo F. Padovan 	}
19680a708f8fSGustavo F. Padovan 
196930e76272SVille Tervo 	err = 0;
197030e76272SVille Tervo 
19710a708f8fSGustavo F. Padovan done:
19726be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
197309fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
19740a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
19750a708f8fSGustavo F. Padovan 	return err;
19760a708f8fSGustavo F. Padovan }
19770a708f8fSGustavo F. Padovan 
1978721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
19790a708f8fSGustavo F. Padovan {
1980721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1981721c4181SGustavo F. Padovan 					       monitor_timer.work);
19820a708f8fSGustavo F. Padovan 
1983525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
19840a708f8fSGustavo F. Padovan 
19856be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
19866be36555SAndrei Emeltchenko 
198780909e04SMat Martineau 	if (!chan->conn) {
19886be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
19898d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
19900a708f8fSGustavo F. Padovan 		return;
19910a708f8fSGustavo F. Padovan 	}
19920a708f8fSGustavo F. Padovan 
1993401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
19940a708f8fSGustavo F. Padovan 
19956be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
19968d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
19970a708f8fSGustavo F. Padovan }
19980a708f8fSGustavo F. Padovan 
1999721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20000a708f8fSGustavo F. Padovan {
2001721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2002721c4181SGustavo F. Padovan 					       retrans_timer.work);
20030a708f8fSGustavo F. Padovan 
200449208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20050a708f8fSGustavo F. Padovan 
20066be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20076be36555SAndrei Emeltchenko 
200880909e04SMat Martineau 	if (!chan->conn) {
200980909e04SMat Martineau 		l2cap_chan_unlock(chan);
201080909e04SMat Martineau 		l2cap_chan_put(chan);
201180909e04SMat Martineau 		return;
201280909e04SMat Martineau 	}
20130a708f8fSGustavo F. Padovan 
2014401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20156be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20168d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20170a708f8fSGustavo F. Padovan }
20180a708f8fSGustavo F. Padovan 
2019d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20203733937dSMat Martineau 				 struct sk_buff_head *skbs)
20210a708f8fSGustavo F. Padovan {
20220a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20233733937dSMat Martineau 	struct l2cap_ctrl *control;
20240a708f8fSGustavo F. Padovan 
20253733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20263733937dSMat Martineau 
2027b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2028b99e13adSMat Martineau 		return;
2029b99e13adSMat Martineau 
20303733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20313733937dSMat Martineau 
20323733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20333733937dSMat Martineau 
20343733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20353733937dSMat Martineau 
20363733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
20373733937dSMat Martineau 		control = &bt_cb(skb)->control;
20383733937dSMat Martineau 
20393733937dSMat Martineau 		control->reqseq = 0;
20403733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20413733937dSMat Martineau 
20423733937dSMat Martineau 		__pack_control(chan, control, skb);
20430a708f8fSGustavo F. Padovan 
204447d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20453733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20463733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20470a708f8fSGustavo F. Padovan 		}
20480a708f8fSGustavo F. Padovan 
20494343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20500a708f8fSGustavo F. Padovan 
2051b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20523733937dSMat Martineau 
2053836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20543733937dSMat Martineau 		chan->frames_sent++;
20550a708f8fSGustavo F. Padovan 	}
20560a708f8fSGustavo F. Padovan }
20570a708f8fSGustavo F. Padovan 
205867c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20590a708f8fSGustavo F. Padovan {
20600a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
206118a48e76SMat Martineau 	struct l2cap_ctrl *control;
206218a48e76SMat Martineau 	int sent = 0;
206318a48e76SMat Martineau 
206418a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20650a708f8fSGustavo F. Padovan 
206689bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20670a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20680a708f8fSGustavo F. Padovan 
206994122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
207094122bbeSMat Martineau 		return 0;
207194122bbeSMat Martineau 
2072b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2073b99e13adSMat Martineau 		return 0;
2074b99e13adSMat Martineau 
207518a48e76SMat Martineau 	while (chan->tx_send_head &&
207618a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
207718a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
20780a708f8fSGustavo F. Padovan 
207918a48e76SMat Martineau 		skb = chan->tx_send_head;
20800a708f8fSGustavo F. Padovan 
208118a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
208218a48e76SMat Martineau 		control = &bt_cb(skb)->control;
20830a708f8fSGustavo F. Padovan 
2084e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
208518a48e76SMat Martineau 			control->final = 1;
2086e2ab4353SGustavo F. Padovan 
208718a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
208818a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
208918a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
20900a708f8fSGustavo F. Padovan 
209118a48e76SMat Martineau 		__pack_control(chan, control, skb);
20920a708f8fSGustavo F. Padovan 
209347d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
209418a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
209518a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20960a708f8fSGustavo F. Padovan 		}
20970a708f8fSGustavo F. Padovan 
209818a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
209918a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
210018a48e76SMat Martineau 		 */
210118a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
210218a48e76SMat Martineau 
210318a48e76SMat Martineau 		if (!tx_skb)
210418a48e76SMat Martineau 			break;
21050a708f8fSGustavo F. Padovan 
21061a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21070a708f8fSGustavo F. Padovan 
2108836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21096a026610SGustavo F. Padovan 		chan->unacked_frames++;
21106a026610SGustavo F. Padovan 		chan->frames_sent++;
211118a48e76SMat Martineau 		sent++;
21120a708f8fSGustavo F. Padovan 
211358d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
211458d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21150a708f8fSGustavo F. Padovan 		else
211658d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
211718a48e76SMat Martineau 
211818a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2119b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21200a708f8fSGustavo F. Padovan 	}
21210a708f8fSGustavo F. Padovan 
2122b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2123b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
212418a48e76SMat Martineau 
212518a48e76SMat Martineau 	return sent;
21260a708f8fSGustavo F. Padovan }
21270a708f8fSGustavo F. Padovan 
2128e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2129e1fbd4c1SMat Martineau {
2130e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2131e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2132e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2133e1fbd4c1SMat Martineau 	u16 seq;
2134e1fbd4c1SMat Martineau 
2135e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2136e1fbd4c1SMat Martineau 
2137e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2138e1fbd4c1SMat Martineau 		return;
2139e1fbd4c1SMat Martineau 
2140b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2141b99e13adSMat Martineau 		return;
2142b99e13adSMat Martineau 
2143e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2144e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2145e1fbd4c1SMat Martineau 
2146e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2147e1fbd4c1SMat Martineau 		if (!skb) {
2148e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2149e1fbd4c1SMat Martineau 			       seq);
2150e1fbd4c1SMat Martineau 			continue;
2151e1fbd4c1SMat Martineau 		}
2152e1fbd4c1SMat Martineau 
2153e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
2154e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
2155e1fbd4c1SMat Martineau 
2156e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2157e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
2158e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21595e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2160e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2161e1fbd4c1SMat Martineau 			break;
2162e1fbd4c1SMat Martineau 		}
2163e1fbd4c1SMat Martineau 
2164e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2165e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2166e1fbd4c1SMat Martineau 			control.final = 1;
2167e1fbd4c1SMat Martineau 		else
2168e1fbd4c1SMat Martineau 			control.final = 0;
2169e1fbd4c1SMat Martineau 
2170e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2171e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2172e1fbd4c1SMat Martineau 			 * writeable copy
2173e1fbd4c1SMat Martineau 			 */
21748bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2175e1fbd4c1SMat Martineau 		} else {
21768bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2177e1fbd4c1SMat Martineau 		}
2178e1fbd4c1SMat Martineau 
2179e1fbd4c1SMat Martineau 		if (!tx_skb) {
2180e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2181e1fbd4c1SMat Martineau 			break;
2182e1fbd4c1SMat Martineau 		}
2183e1fbd4c1SMat Martineau 
2184e1fbd4c1SMat Martineau 		/* Update skb contents */
2185e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2186e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2187e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2188e1fbd4c1SMat Martineau 		} else {
2189e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2190e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2191e1fbd4c1SMat Martineau 		}
2192e1fbd4c1SMat Martineau 
2193e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
2194e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
2195e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
2196e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
2197e1fbd4c1SMat Martineau 		}
2198e1fbd4c1SMat Martineau 
2199e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2200e1fbd4c1SMat Martineau 
2201e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2202e1fbd4c1SMat Martineau 
2203e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2204e1fbd4c1SMat Martineau 	}
2205e1fbd4c1SMat Martineau }
2206e1fbd4c1SMat Martineau 
2207f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2208f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2209f80842a8SMat Martineau {
2210f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2211f80842a8SMat Martineau 
2212f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2213f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2214f80842a8SMat Martineau }
2215f80842a8SMat Martineau 
2216d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2217d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2218d2a7ac5dSMat Martineau {
2219e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2220e1fbd4c1SMat Martineau 
2221e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2222e1fbd4c1SMat Martineau 
2223e1fbd4c1SMat Martineau 	if (control->poll)
2224e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2225e1fbd4c1SMat Martineau 
2226e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2227e1fbd4c1SMat Martineau 
2228e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2229e1fbd4c1SMat Martineau 		return;
2230e1fbd4c1SMat Martineau 
2231e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2232e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2233e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
2234e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2235e1fbd4c1SMat Martineau 				break;
2236e1fbd4c1SMat Martineau 		}
2237e1fbd4c1SMat Martineau 
2238e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2239e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2240e1fbd4c1SMat Martineau 				break;
2241e1fbd4c1SMat Martineau 
2242e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2243e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
2244e1fbd4c1SMat Martineau 		}
2245e1fbd4c1SMat Martineau 
2246e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2247e1fbd4c1SMat Martineau 	}
2248d2a7ac5dSMat Martineau }
2249d2a7ac5dSMat Martineau 
2250b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2251b17e73bbSSzymon Janc {
22520a0aba42SMat Martineau 	struct l2cap_ctrl control;
22530a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22540a0aba42SMat Martineau 					 chan->last_acked_seq);
22550a0aba42SMat Martineau 	int threshold;
22560a0aba42SMat Martineau 
22570a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22580a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22590a0aba42SMat Martineau 
22600a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22610a0aba42SMat Martineau 	control.sframe = 1;
22620a0aba42SMat Martineau 
22630a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22640a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2265b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22660a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22670a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22680a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22690a0aba42SMat Martineau 	} else {
22700a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22710a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22720a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22730a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22740a0aba42SMat Martineau 				frames_to_ack = 0;
22750a0aba42SMat Martineau 		}
22760a0aba42SMat Martineau 
2277c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
22780a0aba42SMat Martineau 		 * Calculate without mul or div
22790a0aba42SMat Martineau 		 */
2280c20f8e35SMat Martineau 		threshold = chan->ack_win;
22810a0aba42SMat Martineau 		threshold += threshold << 1;
22820a0aba42SMat Martineau 		threshold >>= 2;
22830a0aba42SMat Martineau 
2284b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
22850a0aba42SMat Martineau 		       threshold);
22860a0aba42SMat Martineau 
22870a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
22880a0aba42SMat Martineau 			__clear_ack_timer(chan);
22890a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
22900a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
22910a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
22920a0aba42SMat Martineau 			frames_to_ack = 0;
22930a0aba42SMat Martineau 		}
22940a0aba42SMat Martineau 
22950a0aba42SMat Martineau 		if (frames_to_ack)
22960a0aba42SMat Martineau 			__set_ack_timer(chan);
22970a0aba42SMat Martineau 	}
2298b17e73bbSSzymon Janc }
2299b17e73bbSSzymon Janc 
230004124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
230104124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
230204124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23030a708f8fSGustavo F. Padovan {
23040952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23050a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
230690338947SGustavo Padovan 	int sent = 0;
23070a708f8fSGustavo F. Padovan 
23080a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
23090a708f8fSGustavo F. Padovan 		return -EFAULT;
23100a708f8fSGustavo F. Padovan 
23110a708f8fSGustavo F. Padovan 	sent += count;
23120a708f8fSGustavo F. Padovan 	len  -= count;
23130a708f8fSGustavo F. Padovan 
23140a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23150a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23160a708f8fSGustavo F. Padovan 	while (len) {
2317fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2318fbe00700SGustavo Padovan 
23190a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23200a708f8fSGustavo F. Padovan 
2321fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
232290338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2323fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2324fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23252f7719ceSAndrei Emeltchenko 
2326fbe00700SGustavo Padovan 		*frag = tmp;
2327fbe00700SGustavo Padovan 
23280a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
23290a708f8fSGustavo F. Padovan 			return -EFAULT;
23300a708f8fSGustavo F. Padovan 
23315e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
23325e59b791SLuiz Augusto von Dentz 
23330a708f8fSGustavo F. Padovan 		sent += count;
23340a708f8fSGustavo F. Padovan 		len  -= count;
23350a708f8fSGustavo F. Padovan 
23362d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23372d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23382d0ed3d5SGustavo Padovan 
23390a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23400a708f8fSGustavo F. Padovan 	}
23410a708f8fSGustavo F. Padovan 
23420a708f8fSGustavo F. Padovan 	return sent;
23430a708f8fSGustavo F. Padovan }
23440a708f8fSGustavo F. Padovan 
23455e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23465e59b791SLuiz Augusto von Dentz 						 struct msghdr *msg, size_t len,
23475e59b791SLuiz Augusto von Dentz 						 u32 priority)
23480a708f8fSGustavo F. Padovan {
23498c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23500a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
235103a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23520a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23530a708f8fSGustavo F. Padovan 
235443b1b8dfSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
235543b1b8dfSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len, priority);
23560a708f8fSGustavo F. Padovan 
23570a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23582f7719ceSAndrei Emeltchenko 
23592f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
236090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
236190338947SGustavo Padovan 	if (IS_ERR(skb))
236290338947SGustavo Padovan 		return skb;
23630a708f8fSGustavo F. Padovan 
23645e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23655e59b791SLuiz Augusto von Dentz 
23660a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23670a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2368fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2369daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
237043b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23710a708f8fSGustavo F. Padovan 
23720952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23730a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23740a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23750a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23760a708f8fSGustavo F. Padovan 	}
23770a708f8fSGustavo F. Padovan 	return skb;
23780a708f8fSGustavo F. Padovan }
23790a708f8fSGustavo F. Padovan 
23805e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
23815e59b791SLuiz Augusto von Dentz 					      struct msghdr *msg, size_t len,
23825e59b791SLuiz Augusto von Dentz 					      u32 priority)
23830a708f8fSGustavo F. Padovan {
23848c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23850a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2386f2ba7faeSGustavo Padovan 	int err, count;
23870a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23880a708f8fSGustavo F. Padovan 
2389b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
23900a708f8fSGustavo F. Padovan 
2391f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
23922f7719ceSAndrei Emeltchenko 
2393f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
239490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
239590338947SGustavo Padovan 	if (IS_ERR(skb))
239690338947SGustavo Padovan 		return skb;
23970a708f8fSGustavo F. Padovan 
23985e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23995e59b791SLuiz Augusto von Dentz 
24000a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24010a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2402fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24036ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24040a708f8fSGustavo F. Padovan 
24050952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24060a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24070a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24080a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24090a708f8fSGustavo F. Padovan 	}
24100a708f8fSGustavo F. Padovan 	return skb;
24110a708f8fSGustavo F. Padovan }
24120a708f8fSGustavo F. Padovan 
2413ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2414ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
241594122bbeSMat Martineau 					       u16 sdulen)
24160a708f8fSGustavo F. Padovan {
24178c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24180a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2419e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24200a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24210a708f8fSGustavo F. Padovan 
2422b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24230a708f8fSGustavo F. Padovan 
24240a708f8fSGustavo F. Padovan 	if (!conn)
24250a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24260a708f8fSGustavo F. Padovan 
2427ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2428e4ca6d98SAndrei Emeltchenko 
24290a708f8fSGustavo F. Padovan 	if (sdulen)
243003a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24310a708f8fSGustavo F. Padovan 
243247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
243303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24340a708f8fSGustavo F. Padovan 
24350a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24362f7719ceSAndrei Emeltchenko 
24372f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
243890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
243990338947SGustavo Padovan 	if (IS_ERR(skb))
244090338947SGustavo Padovan 		return skb;
24410a708f8fSGustavo F. Padovan 
24420a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24430a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2444fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24450a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
244688843ab0SAndrei Emeltchenko 
244718a48e76SMat Martineau 	/* Control header is populated later */
244818a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
244918a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
245018a48e76SMat Martineau 	else
245118a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
245288843ab0SAndrei Emeltchenko 
24530a708f8fSGustavo F. Padovan 	if (sdulen)
245403a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24550a708f8fSGustavo F. Padovan 
24560952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24570a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24580a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24590a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24600a708f8fSGustavo F. Padovan 	}
24610a708f8fSGustavo F. Padovan 
246218a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
24633ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
24640a708f8fSGustavo F. Padovan 	return skb;
24650a708f8fSGustavo F. Padovan }
24660a708f8fSGustavo F. Padovan 
246794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
246894122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
246994122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24700a708f8fSGustavo F. Padovan {
24710a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
247294122bbeSMat Martineau 	u16 sdu_len;
247394122bbeSMat Martineau 	size_t pdu_len;
247494122bbeSMat Martineau 	u8 sar;
24750a708f8fSGustavo F. Padovan 
2476b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24770a708f8fSGustavo F. Padovan 
247894122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
247994122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
248094122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
248194122bbeSMat Martineau 	 */
248294122bbeSMat Martineau 
248394122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
248494122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
248594122bbeSMat Martineau 
2486a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2487a549574dSMat Martineau 	if (!chan->hs_hcon)
248894122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
248994122bbeSMat Martineau 
249094122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
249135d401dfSGustavo Padovan 	if (chan->fcs)
249235d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
249335d401dfSGustavo Padovan 
2494ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
249594122bbeSMat Martineau 
249694122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
249794122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
249894122bbeSMat Martineau 
249994122bbeSMat Martineau 	if (len <= pdu_len) {
250094122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
250194122bbeSMat Martineau 		sdu_len = 0;
250294122bbeSMat Martineau 		pdu_len = len;
250394122bbeSMat Martineau 	} else {
250494122bbeSMat Martineau 		sar = L2CAP_SAR_START;
250594122bbeSMat Martineau 		sdu_len = len;
250694122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
250794122bbeSMat Martineau 	}
25080a708f8fSGustavo F. Padovan 
25090a708f8fSGustavo F. Padovan 	while (len > 0) {
251094122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25110a708f8fSGustavo F. Padovan 
25120a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
251394122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25140a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25150a708f8fSGustavo F. Padovan 		}
25160a708f8fSGustavo F. Padovan 
251794122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
251894122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25190a708f8fSGustavo F. Padovan 
252094122bbeSMat Martineau 		len -= pdu_len;
252194122bbeSMat Martineau 		if (sdu_len) {
252294122bbeSMat Martineau 			sdu_len = 0;
252394122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
252494122bbeSMat Martineau 		}
252594122bbeSMat Martineau 
252694122bbeSMat Martineau 		if (len <= pdu_len) {
252794122bbeSMat Martineau 			sar = L2CAP_SAR_END;
252894122bbeSMat Martineau 			pdu_len = len;
252994122bbeSMat Martineau 		} else {
253094122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
253194122bbeSMat Martineau 		}
253294122bbeSMat Martineau 	}
253394122bbeSMat Martineau 
2534f0f62799SGustavo Padovan 	return 0;
25350a708f8fSGustavo F. Padovan }
25360a708f8fSGustavo F. Padovan 
2537177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2538177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2539177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2540177f8f2bSJohan Hedberg {
2541177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2542177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2543177f8f2bSJohan Hedberg 	int err, count, hlen;
2544177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2545177f8f2bSJohan Hedberg 
2546177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2547177f8f2bSJohan Hedberg 
2548177f8f2bSJohan Hedberg 	if (!conn)
2549177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2550177f8f2bSJohan Hedberg 
2551177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2552177f8f2bSJohan Hedberg 
2553177f8f2bSJohan Hedberg 	if (sdulen)
2554177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2555177f8f2bSJohan Hedberg 
2556177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2557177f8f2bSJohan Hedberg 
2558177f8f2bSJohan Hedberg 	skb = chan->ops->alloc_skb(chan, count + hlen,
2559177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2560177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2561177f8f2bSJohan Hedberg 		return skb;
2562177f8f2bSJohan Hedberg 
2563177f8f2bSJohan Hedberg 	/* Create L2CAP header */
2564177f8f2bSJohan Hedberg 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2565177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2566177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2567177f8f2bSJohan Hedberg 
2568177f8f2bSJohan Hedberg 	if (sdulen)
2569177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2570177f8f2bSJohan Hedberg 
2571177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2572177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2573177f8f2bSJohan Hedberg 		kfree_skb(skb);
2574177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2575177f8f2bSJohan Hedberg 	}
2576177f8f2bSJohan Hedberg 
2577177f8f2bSJohan Hedberg 	return skb;
2578177f8f2bSJohan Hedberg }
2579177f8f2bSJohan Hedberg 
2580177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2581177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2582177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2583177f8f2bSJohan Hedberg {
2584177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2585177f8f2bSJohan Hedberg 	size_t pdu_len;
2586177f8f2bSJohan Hedberg 	u16 sdu_len;
2587177f8f2bSJohan Hedberg 
2588177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2589177f8f2bSJohan Hedberg 
2590177f8f2bSJohan Hedberg 	pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE;
2591177f8f2bSJohan Hedberg 
2592177f8f2bSJohan Hedberg 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2593177f8f2bSJohan Hedberg 
2594177f8f2bSJohan Hedberg 	sdu_len = len;
2595177f8f2bSJohan Hedberg 	pdu_len -= L2CAP_SDULEN_SIZE;
2596177f8f2bSJohan Hedberg 
2597177f8f2bSJohan Hedberg 	while (len > 0) {
2598177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2599177f8f2bSJohan Hedberg 			pdu_len = len;
2600177f8f2bSJohan Hedberg 
2601177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2602177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2603177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2604177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2605177f8f2bSJohan Hedberg 		}
2606177f8f2bSJohan Hedberg 
2607177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2608177f8f2bSJohan Hedberg 
2609177f8f2bSJohan Hedberg 		len -= pdu_len;
2610177f8f2bSJohan Hedberg 
2611177f8f2bSJohan Hedberg 		if (sdu_len) {
2612177f8f2bSJohan Hedberg 			sdu_len = 0;
2613177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2614177f8f2bSJohan Hedberg 		}
2615177f8f2bSJohan Hedberg 	}
2616177f8f2bSJohan Hedberg 
2617177f8f2bSJohan Hedberg 	return 0;
2618177f8f2bSJohan Hedberg }
2619177f8f2bSJohan Hedberg 
26205e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
26215e59b791SLuiz Augusto von Dentz 		    u32 priority)
26229a91a04aSGustavo F. Padovan {
26239a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26249a91a04aSGustavo F. Padovan 	int err;
262594122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26269a91a04aSGustavo F. Padovan 
262731e8ce80SSeung-Woo Kim 	if (!chan->conn)
262831e8ce80SSeung-Woo Kim 		return -ENOTCONN;
262931e8ce80SSeung-Woo Kim 
26309a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2631715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26325e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
26339a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26349a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26359a91a04aSGustavo F. Padovan 
26369a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26379a91a04aSGustavo F. Padovan 		return len;
26389a91a04aSGustavo F. Padovan 	}
26399a91a04aSGustavo F. Padovan 
26409a91a04aSGustavo F. Padovan 	switch (chan->mode) {
264138319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
2642177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2643177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2644177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2645177f8f2bSJohan Hedberg 
2646fad5fc89SJohan Hedberg 		if (!chan->tx_credits)
2647fad5fc89SJohan Hedberg 			return -EAGAIN;
2648fad5fc89SJohan Hedberg 
2649177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2650177f8f2bSJohan Hedberg 
2651177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2652177f8f2bSJohan Hedberg 
2653177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2654177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2655177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2656177f8f2bSJohan Hedberg 		}
2657177f8f2bSJohan Hedberg 
2658177f8f2bSJohan Hedberg 		if (err)
2659177f8f2bSJohan Hedberg 			return err;
2660177f8f2bSJohan Hedberg 
2661177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2662177f8f2bSJohan Hedberg 
2663177f8f2bSJohan Hedberg 		while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
2664177f8f2bSJohan Hedberg 			l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
2665177f8f2bSJohan Hedberg 			chan->tx_credits--;
2666177f8f2bSJohan Hedberg 		}
2667177f8f2bSJohan Hedberg 
2668177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2669177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2670177f8f2bSJohan Hedberg 
2671177f8f2bSJohan Hedberg 		err = len;
2672177f8f2bSJohan Hedberg 
2673177f8f2bSJohan Hedberg 		break;
2674177f8f2bSJohan Hedberg 
2675fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
26769a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
26779a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
26789a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
26799a91a04aSGustavo F. Padovan 
26809a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
26815e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
26829a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26839a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26849a91a04aSGustavo F. Padovan 
26859a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26869a91a04aSGustavo F. Padovan 		err = len;
26879a91a04aSGustavo F. Padovan 		break;
26889a91a04aSGustavo F. Padovan 
26899a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
26909a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
269194122bbeSMat Martineau 		/* Check outgoing MTU */
269294122bbeSMat Martineau 		if (len > chan->omtu) {
269394122bbeSMat Martineau 			err = -EMSGSIZE;
26949a91a04aSGustavo F. Padovan 			break;
26959a91a04aSGustavo F. Padovan 		}
26969a91a04aSGustavo F. Padovan 
269794122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
269894122bbeSMat Martineau 
269994122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
270094122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
270194122bbeSMat Martineau 		 * allocation.
270294122bbeSMat Martineau 		 */
270394122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
270494122bbeSMat Martineau 
270594122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
270694122bbeSMat Martineau 		 * check that it is still connected.
270794122bbeSMat Martineau 		 */
270894122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
270994122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
271094122bbeSMat Martineau 			err = -ENOTCONN;
27119a91a04aSGustavo F. Padovan 		}
27129a91a04aSGustavo F. Padovan 
271394122bbeSMat Martineau 		if (err)
271494122bbeSMat Martineau 			break;
271594122bbeSMat Martineau 
27163733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2717d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27183733937dSMat Martineau 		else
2719d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
272094122bbeSMat Martineau 
27219a91a04aSGustavo F. Padovan 		err = len;
27229a91a04aSGustavo F. Padovan 
272394122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
272494122bbeSMat Martineau 		 * seg_queue and need to be purged.
272594122bbeSMat Martineau 		 */
272694122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27279a91a04aSGustavo F. Padovan 		break;
27289a91a04aSGustavo F. Padovan 
27299a91a04aSGustavo F. Padovan 	default:
27309a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27319a91a04aSGustavo F. Padovan 		err = -EBADFD;
27329a91a04aSGustavo F. Padovan 	}
27339a91a04aSGustavo F. Padovan 
27349a91a04aSGustavo F. Padovan 	return err;
27359a91a04aSGustavo F. Padovan }
27369a91a04aSGustavo F. Padovan 
2737d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2738d2a7ac5dSMat Martineau {
2739bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2740bed68bdeSMat Martineau 	u16 seq;
2741bed68bdeSMat Martineau 
2742b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2743bed68bdeSMat Martineau 
2744bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2745bed68bdeSMat Martineau 	control.sframe = 1;
2746bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2747bed68bdeSMat Martineau 
2748bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2749bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2750bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2751bed68bdeSMat Martineau 			control.reqseq = seq;
2752bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2753bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2754bed68bdeSMat Martineau 		}
2755bed68bdeSMat Martineau 	}
2756bed68bdeSMat Martineau 
2757bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2758d2a7ac5dSMat Martineau }
2759d2a7ac5dSMat Martineau 
2760d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2761d2a7ac5dSMat Martineau {
2762bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2763bed68bdeSMat Martineau 
2764bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2765bed68bdeSMat Martineau 
2766bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2767bed68bdeSMat Martineau 		return;
2768bed68bdeSMat Martineau 
2769bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2770bed68bdeSMat Martineau 	control.sframe = 1;
2771bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2772bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2773bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2774d2a7ac5dSMat Martineau }
2775d2a7ac5dSMat Martineau 
2776d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2777d2a7ac5dSMat Martineau {
2778bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2779bed68bdeSMat Martineau 	u16 initial_head;
2780bed68bdeSMat Martineau 	u16 seq;
2781bed68bdeSMat Martineau 
2782b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2783bed68bdeSMat Martineau 
2784bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2785bed68bdeSMat Martineau 	control.sframe = 1;
2786bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2787bed68bdeSMat Martineau 
2788bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2789bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2790bed68bdeSMat Martineau 
2791bed68bdeSMat Martineau 	do {
2792bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2793bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2794bed68bdeSMat Martineau 			break;
2795bed68bdeSMat Martineau 
2796bed68bdeSMat Martineau 		control.reqseq = seq;
2797bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2798bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2799bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2800d2a7ac5dSMat Martineau }
2801d2a7ac5dSMat Martineau 
2802608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2803608bcc6dSMat Martineau {
2804608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2805608bcc6dSMat Martineau 	u16 ackseq;
2806608bcc6dSMat Martineau 
2807b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2808608bcc6dSMat Martineau 
2809608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2810608bcc6dSMat Martineau 		return;
2811608bcc6dSMat Martineau 
2812b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2813608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2814608bcc6dSMat Martineau 
2815608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2816608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2817608bcc6dSMat Martineau 
2818608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2819608bcc6dSMat Martineau 		if (acked_skb) {
2820608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2821608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2822608bcc6dSMat Martineau 			chan->unacked_frames--;
2823608bcc6dSMat Martineau 		}
2824608bcc6dSMat Martineau 	}
2825608bcc6dSMat Martineau 
2826608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2827608bcc6dSMat Martineau 
2828608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2829608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2830608bcc6dSMat Martineau 
2831b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2832608bcc6dSMat Martineau }
2833608bcc6dSMat Martineau 
2834608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2835608bcc6dSMat Martineau {
2836608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2837608bcc6dSMat Martineau 
2838608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2839608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2840608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2841608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2842608bcc6dSMat Martineau }
2843608bcc6dSMat Martineau 
2844d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2845608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2846608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2847608bcc6dSMat Martineau {
2848608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2849608bcc6dSMat Martineau 	       event);
2850608bcc6dSMat Martineau 
2851608bcc6dSMat Martineau 	switch (event) {
2852608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2853608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2854608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2855608bcc6dSMat Martineau 
2856608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2857608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2858608bcc6dSMat Martineau 		break;
2859608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2860608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2861608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2862608bcc6dSMat Martineau 
2863608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2864608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2865608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2866608bcc6dSMat Martineau 			 */
2867608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2868608bcc6dSMat Martineau 		}
2869608bcc6dSMat Martineau 
2870608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2871608bcc6dSMat Martineau 
2872608bcc6dSMat Martineau 		break;
2873608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2874608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2875608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2876608bcc6dSMat Martineau 
2877608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2878608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2879608bcc6dSMat Martineau 
2880608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2881608bcc6dSMat Martineau 			local_control.sframe = 1;
2882608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2883608bcc6dSMat Martineau 			local_control.poll = 1;
2884608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2885a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2886608bcc6dSMat Martineau 
2887608bcc6dSMat Martineau 			chan->retry_count = 1;
2888608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2889608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2890608bcc6dSMat Martineau 		}
2891608bcc6dSMat Martineau 		break;
2892608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2893608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2894608bcc6dSMat Martineau 		break;
2895608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2896608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2897608bcc6dSMat Martineau 		chan->retry_count = 1;
2898608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2899608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2900608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2901608bcc6dSMat Martineau 		break;
2902608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2903608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2904608bcc6dSMat Martineau 		chan->retry_count = 1;
2905608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2906608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2907608bcc6dSMat Martineau 		break;
2908608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2909608bcc6dSMat Martineau 		/* Nothing to process */
2910608bcc6dSMat Martineau 		break;
2911608bcc6dSMat Martineau 	default:
2912608bcc6dSMat Martineau 		break;
2913608bcc6dSMat Martineau 	}
2914608bcc6dSMat Martineau }
2915608bcc6dSMat Martineau 
2916d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2917608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2918608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2919608bcc6dSMat Martineau {
2920608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2921608bcc6dSMat Martineau 	       event);
2922608bcc6dSMat Martineau 
2923608bcc6dSMat Martineau 	switch (event) {
2924608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2925608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2926608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2927608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2928608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2929608bcc6dSMat Martineau 		break;
2930608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2931608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2932608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2933608bcc6dSMat Martineau 
2934608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2935608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2936608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2937608bcc6dSMat Martineau 			 */
2938608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2939608bcc6dSMat Martineau 		}
2940608bcc6dSMat Martineau 
2941608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2942608bcc6dSMat Martineau 
2943608bcc6dSMat Martineau 		break;
2944608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2945608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2946608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2947608bcc6dSMat Martineau 
2948608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2949608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2950608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2951608bcc6dSMat Martineau 			local_control.sframe = 1;
2952608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2953608bcc6dSMat Martineau 			local_control.poll = 1;
2954608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2955a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2956608bcc6dSMat Martineau 
2957608bcc6dSMat Martineau 			chan->retry_count = 1;
2958608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2959608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2960608bcc6dSMat Martineau 		}
2961608bcc6dSMat Martineau 		break;
2962608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2963608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2964608bcc6dSMat Martineau 
2965608bcc6dSMat Martineau 		/* Fall through */
2966608bcc6dSMat Martineau 
2967608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2968608bcc6dSMat Martineau 		if (control && control->final) {
2969608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2970608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2971608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2972608bcc6dSMat Martineau 			chan->retry_count = 0;
2973608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2974608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2975608bcc6dSMat Martineau 		}
2976608bcc6dSMat Martineau 		break;
2977608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2978608bcc6dSMat Martineau 		/* Ignore */
2979608bcc6dSMat Martineau 		break;
2980608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2981608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2982608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2983608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2984608bcc6dSMat Martineau 			chan->retry_count++;
2985608bcc6dSMat Martineau 		} else {
29865e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
2987608bcc6dSMat Martineau 		}
2988608bcc6dSMat Martineau 		break;
2989608bcc6dSMat Martineau 	default:
2990608bcc6dSMat Martineau 		break;
2991608bcc6dSMat Martineau 	}
2992608bcc6dSMat Martineau }
2993608bcc6dSMat Martineau 
2994d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2995608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2996608bcc6dSMat Martineau {
2997608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2998608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2999608bcc6dSMat Martineau 
3000608bcc6dSMat Martineau 	switch (chan->tx_state) {
3001608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3002d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3003608bcc6dSMat Martineau 		break;
3004608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3005d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3006608bcc6dSMat Martineau 		break;
3007608bcc6dSMat Martineau 	default:
3008608bcc6dSMat Martineau 		/* Ignore event */
3009608bcc6dSMat Martineau 		break;
3010608bcc6dSMat Martineau 	}
3011608bcc6dSMat Martineau }
3012608bcc6dSMat Martineau 
30134b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30144b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30154b51dae9SMat Martineau {
30164b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3017401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30184b51dae9SMat Martineau }
30194b51dae9SMat Martineau 
3020f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3021f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3022f80842a8SMat Martineau {
3023f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3024401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3025f80842a8SMat Martineau }
3026f80842a8SMat Martineau 
30270a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30280a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30290a708f8fSGustavo F. Padovan {
30300a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
303148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30320a708f8fSGustavo F. Padovan 
30330a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30340a708f8fSGustavo F. Padovan 
30353df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30363d57dc68SGustavo F. Padovan 
30373df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3038715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30390a708f8fSGustavo F. Padovan 			continue;
30400a708f8fSGustavo F. Padovan 
30417f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
30427f5396a7SGustavo Padovan 		if (bt_cb(skb)->chan == chan)
30430a708f8fSGustavo F. Padovan 			continue;
30447f5396a7SGustavo Padovan 
30458bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30460a708f8fSGustavo F. Padovan 		if (!nskb)
30470a708f8fSGustavo F. Padovan 			continue;
304880b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30490a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30500a708f8fSGustavo F. Padovan 	}
30513d57dc68SGustavo F. Padovan 
30523df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30530a708f8fSGustavo F. Padovan }
30540a708f8fSGustavo F. Padovan 
30550a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3056b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3057b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30580a708f8fSGustavo F. Padovan {
30590a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30600a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30610a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30620a708f8fSGustavo F. Padovan 	int len, count;
30630a708f8fSGustavo F. Padovan 
3064b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30650a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
30660a708f8fSGustavo F. Padovan 
3067300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3068300b962eSAnderson Lizardo 		return NULL;
3069300b962eSAnderson Lizardo 
30700a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
30710a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
30720a708f8fSGustavo F. Padovan 
30738bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
30740a708f8fSGustavo F. Padovan 	if (!skb)
30750a708f8fSGustavo F. Padovan 		return NULL;
30760a708f8fSGustavo F. Padovan 
30770a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
30780a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
30793300d9a9SClaudio Takahasi 
30803300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3081ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
30823300d9a9SClaudio Takahasi 	else
3083ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
30840a708f8fSGustavo F. Padovan 
30850a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
30860a708f8fSGustavo F. Padovan 	cmd->code  = code;
30870a708f8fSGustavo F. Padovan 	cmd->ident = ident;
30880a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
30890a708f8fSGustavo F. Padovan 
30900a708f8fSGustavo F. Padovan 	if (dlen) {
30910a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
30920a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
30930a708f8fSGustavo F. Padovan 		data += count;
30940a708f8fSGustavo F. Padovan 	}
30950a708f8fSGustavo F. Padovan 
30960a708f8fSGustavo F. Padovan 	len -= skb->len;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
30990a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31000a708f8fSGustavo F. Padovan 	while (len) {
31010a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31020a708f8fSGustavo F. Padovan 
31038bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31040a708f8fSGustavo F. Padovan 		if (!*frag)
31050a708f8fSGustavo F. Padovan 			goto fail;
31060a708f8fSGustavo F. Padovan 
31070a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
31080a708f8fSGustavo F. Padovan 
31090a708f8fSGustavo F. Padovan 		len  -= count;
31100a708f8fSGustavo F. Padovan 		data += count;
31110a708f8fSGustavo F. Padovan 
31120a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31130a708f8fSGustavo F. Padovan 	}
31140a708f8fSGustavo F. Padovan 
31150a708f8fSGustavo F. Padovan 	return skb;
31160a708f8fSGustavo F. Padovan 
31170a708f8fSGustavo F. Padovan fail:
31180a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31190a708f8fSGustavo F. Padovan 	return NULL;
31200a708f8fSGustavo F. Padovan }
31210a708f8fSGustavo F. Padovan 
31222d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31232d792818SGustavo Padovan 				     unsigned long *val)
31240a708f8fSGustavo F. Padovan {
31250a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31260a708f8fSGustavo F. Padovan 	int len;
31270a708f8fSGustavo F. Padovan 
31280a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31290a708f8fSGustavo F. Padovan 	*ptr += len;
31300a708f8fSGustavo F. Padovan 
31310a708f8fSGustavo F. Padovan 	*type = opt->type;
31320a708f8fSGustavo F. Padovan 	*olen = opt->len;
31330a708f8fSGustavo F. Padovan 
31340a708f8fSGustavo F. Padovan 	switch (opt->len) {
31350a708f8fSGustavo F. Padovan 	case 1:
31360a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31370a708f8fSGustavo F. Padovan 		break;
31380a708f8fSGustavo F. Padovan 
31390a708f8fSGustavo F. Padovan 	case 2:
31400a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31410a708f8fSGustavo F. Padovan 		break;
31420a708f8fSGustavo F. Padovan 
31430a708f8fSGustavo F. Padovan 	case 4:
31440a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31450a708f8fSGustavo F. Padovan 		break;
31460a708f8fSGustavo F. Padovan 
31470a708f8fSGustavo F. Padovan 	default:
31480a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31490a708f8fSGustavo F. Padovan 		break;
31500a708f8fSGustavo F. Padovan 	}
31510a708f8fSGustavo F. Padovan 
3152b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31530a708f8fSGustavo F. Padovan 	return len;
31540a708f8fSGustavo F. Padovan }
31550a708f8fSGustavo F. Padovan 
31560a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
31570a708f8fSGustavo F. Padovan {
31580a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31590a708f8fSGustavo F. Padovan 
3160b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31610a708f8fSGustavo F. Padovan 
31620a708f8fSGustavo F. Padovan 	opt->type = type;
31630a708f8fSGustavo F. Padovan 	opt->len  = len;
31640a708f8fSGustavo F. Padovan 
31650a708f8fSGustavo F. Padovan 	switch (len) {
31660a708f8fSGustavo F. Padovan 	case 1:
31670a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
31680a708f8fSGustavo F. Padovan 		break;
31690a708f8fSGustavo F. Padovan 
31700a708f8fSGustavo F. Padovan 	case 2:
31710a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
31720a708f8fSGustavo F. Padovan 		break;
31730a708f8fSGustavo F. Padovan 
31740a708f8fSGustavo F. Padovan 	case 4:
31750a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
31760a708f8fSGustavo F. Padovan 		break;
31770a708f8fSGustavo F. Padovan 
31780a708f8fSGustavo F. Padovan 	default:
31790a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
31800a708f8fSGustavo F. Padovan 		break;
31810a708f8fSGustavo F. Padovan 	}
31820a708f8fSGustavo F. Padovan 
31830a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
31840a708f8fSGustavo F. Padovan }
31850a708f8fSGustavo F. Padovan 
3186f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
3187f89cef09SAndrei Emeltchenko {
3188f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3189f89cef09SAndrei Emeltchenko 
3190f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3191f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3192f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3193f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3194f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3195f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3196ac73498cSAndrei Emeltchenko 		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
31978936fa6dSAndrei Emeltchenko 		efs.flush_to	= __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3198f89cef09SAndrei Emeltchenko 		break;
3199f89cef09SAndrei Emeltchenko 
3200f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3201f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3202f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3203f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3204f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3205f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3206f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3207f89cef09SAndrei Emeltchenko 		break;
3208f89cef09SAndrei Emeltchenko 
3209f89cef09SAndrei Emeltchenko 	default:
3210f89cef09SAndrei Emeltchenko 		return;
3211f89cef09SAndrei Emeltchenko 	}
3212f89cef09SAndrei Emeltchenko 
3213f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3214f89cef09SAndrei Emeltchenko 			   (unsigned long) &efs);
3215f89cef09SAndrei Emeltchenko }
3216f89cef09SAndrei Emeltchenko 
3217721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32180a708f8fSGustavo F. Padovan {
3219721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3220721c4181SGustavo F. Padovan 					       ack_timer.work);
32210362520bSMat Martineau 	u16 frames_to_ack;
32220a708f8fSGustavo F. Padovan 
32232fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32242fb9b3d4SGustavo F. Padovan 
32256be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32266be36555SAndrei Emeltchenko 
32270362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32280362520bSMat Martineau 				     chan->last_acked_seq);
32290362520bSMat Martineau 
32300362520bSMat Martineau 	if (frames_to_ack)
32310362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32326be36555SAndrei Emeltchenko 
32336be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
323409bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32350a708f8fSGustavo F. Padovan }
32360a708f8fSGustavo F. Padovan 
3237466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32380a708f8fSGustavo F. Padovan {
32393c588192SMat Martineau 	int err;
32403c588192SMat Martineau 
3241105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3242105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
324342e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32446a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
324542e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32466a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3247105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3248105bdf9eSMat Martineau 	chan->sdu = NULL;
3249105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3250105bdf9eSMat Martineau 	chan->sdu_len = 0;
3251105bdf9eSMat Martineau 
3252d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3253d34c34fbSMat Martineau 
32546ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32556ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
325608333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
325708333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
325808333283SMat Martineau 
3259105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3260105bdf9eSMat Martineau 		return 0;
3261105bdf9eSMat Martineau 
3262105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3263105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
32640a708f8fSGustavo F. Padovan 
3265721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3266721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3267721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
32680a708f8fSGustavo F. Padovan 
3269f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
32700a708f8fSGustavo F. Padovan 
32713c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
32723c588192SMat Martineau 	if (err < 0)
32733c588192SMat Martineau 		return err;
32743c588192SMat Martineau 
32759dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
32769dc9affcSMat Martineau 	if (err < 0)
32779dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
32789dc9affcSMat Martineau 
32799dc9affcSMat Martineau 	return err;
32800a708f8fSGustavo F. Padovan }
32810a708f8fSGustavo F. Padovan 
32820a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
32830a708f8fSGustavo F. Padovan {
32840a708f8fSGustavo F. Padovan 	switch (mode) {
32850a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
32860a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
32870a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
32880a708f8fSGustavo F. Padovan 			return mode;
32890a708f8fSGustavo F. Padovan 		/* fall through */
32900a708f8fSGustavo F. Padovan 	default:
32910a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
32920a708f8fSGustavo F. Padovan 	}
32930a708f8fSGustavo F. Padovan }
32940a708f8fSGustavo F. Padovan 
3295848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
32966327eb98SAndrei Emeltchenko {
3297848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
32986327eb98SAndrei Emeltchenko }
32996327eb98SAndrei Emeltchenko 
3300848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3301f89cef09SAndrei Emeltchenko {
3302848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
3303f89cef09SAndrei Emeltchenko }
3304f89cef09SAndrei Emeltchenko 
330536c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
330636c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
330736c86c85SMat Martineau {
33086ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
330936c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
331036c86c85SMat Martineau 
331136c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
331236c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
331336c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
331436c86c85SMat Martineau 		 * controllers is 10 seconds.
331536c86c85SMat Martineau 		 *
331636c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
331736c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
331836c86c85SMat Martineau 		 * will result in a timeout that meets the above
331936c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
332036c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
332136c86c85SMat Martineau 		 */
332236c86c85SMat Martineau 
332336c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
332436c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
332536c86c85SMat Martineau 
332636c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
332736c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
332836c86c85SMat Martineau 		 * controller.
332936c86c85SMat Martineau 		 */
333036c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
333136c86c85SMat Martineau 
333236c86c85SMat Martineau 		if (ertm_to > 0xffff)
333336c86c85SMat Martineau 			ertm_to = 0xffff;
333436c86c85SMat Martineau 
333536c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
333636c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
333736c86c85SMat Martineau 	} else {
333836c86c85SMat Martineau 		rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
333936c86c85SMat Martineau 		rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
334036c86c85SMat Martineau 	}
334136c86c85SMat Martineau }
334236c86c85SMat Martineau 
33436327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33446327eb98SAndrei Emeltchenko {
33456327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3346848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33476327eb98SAndrei Emeltchenko 		/* use extended control field */
33486327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3349836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3350836be934SAndrei Emeltchenko 	} else {
33516327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33526327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3353836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3354836be934SAndrei Emeltchenko 	}
3355c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33566327eb98SAndrei Emeltchenko }
33576327eb98SAndrei Emeltchenko 
3358710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
33590a708f8fSGustavo F. Padovan {
33600a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
33610c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
33620a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3363c8f79162SAndrei Emeltchenko 	u16 size;
33640a708f8fSGustavo F. Padovan 
336549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
33660a708f8fSGustavo F. Padovan 
336773ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
33680a708f8fSGustavo F. Padovan 		goto done;
33690a708f8fSGustavo F. Padovan 
33700c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
33710a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33720a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3373c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
33740a708f8fSGustavo F. Padovan 			break;
33750a708f8fSGustavo F. Padovan 
3376848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3377f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3378f89cef09SAndrei Emeltchenko 
33790a708f8fSGustavo F. Padovan 		/* fall through */
33800a708f8fSGustavo F. Padovan 	default:
33818c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
33820a708f8fSGustavo F. Padovan 		break;
33830a708f8fSGustavo F. Padovan 	}
33840a708f8fSGustavo F. Padovan 
33850a708f8fSGustavo F. Padovan done:
33860c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
33870c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
33880a708f8fSGustavo F. Padovan 
33890c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
33900a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
33918c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
33928c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
33930a708f8fSGustavo F. Padovan 			break;
33940a708f8fSGustavo F. Padovan 
33950a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
33960a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
33970a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
33980a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
33990a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34000a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34010a708f8fSGustavo F. Padovan 
34020a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34030a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34040a708f8fSGustavo F. Padovan 		break;
34050a708f8fSGustavo F. Padovan 
34060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34070a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
340847d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
340936c86c85SMat Martineau 
341036c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3411c8f79162SAndrei Emeltchenko 
3412c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34132d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3414c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3415c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34160a708f8fSGustavo F. Padovan 
34176327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
34186327eb98SAndrei Emeltchenko 
34196327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
34206327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
34210a708f8fSGustavo F. Padovan 
34220a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34230a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34240a708f8fSGustavo F. Padovan 
3425f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3426f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3427f89cef09SAndrei Emeltchenko 
34286327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
34296327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
34306327eb98SAndrei Emeltchenko 					   chan->tx_win);
343160918918SAndrei Emeltchenko 
343260918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
343360918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3434f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
343560918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
343660918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
343760918918SAndrei Emeltchenko 						   chan->fcs);
343860918918SAndrei Emeltchenko 			}
34390a708f8fSGustavo F. Padovan 		break;
34400a708f8fSGustavo F. Padovan 
34410a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3442273759e2SMat Martineau 		l2cap_txwin_setup(chan);
34430a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
34440a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34450a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34460a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34470a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3448c8f79162SAndrei Emeltchenko 
3449c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34502d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3451c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3452c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34530a708f8fSGustavo F. Padovan 
34540a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34550a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34560a708f8fSGustavo F. Padovan 
3457f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3458f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3459f89cef09SAndrei Emeltchenko 
346060918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
346147d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3462f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
346347d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
346460918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
346560918918SAndrei Emeltchenko 						   chan->fcs);
34660a708f8fSGustavo F. Padovan 			}
34670a708f8fSGustavo F. Padovan 		break;
34680a708f8fSGustavo F. Padovan 	}
34690a708f8fSGustavo F. Padovan 
3470fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
347159e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
34720a708f8fSGustavo F. Padovan 
34730a708f8fSGustavo F. Padovan 	return ptr - data;
34740a708f8fSGustavo F. Padovan }
34750a708f8fSGustavo F. Padovan 
347673ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34770a708f8fSGustavo F. Padovan {
34780a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
34790a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
348073ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
348173ffa904SGustavo F. Padovan 	int len = chan->conf_len;
34820a708f8fSGustavo F. Padovan 	int type, hint, olen;
34830a708f8fSGustavo F. Padovan 	unsigned long val;
34840a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
348542dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
348642dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
34870a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
34880a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3489c8f79162SAndrei Emeltchenko 	u16 size;
34900a708f8fSGustavo F. Padovan 
349173ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
34920a708f8fSGustavo F. Padovan 
34930a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
34940a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
34950a708f8fSGustavo F. Padovan 
34960a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
34970a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
34980a708f8fSGustavo F. Padovan 
34990a708f8fSGustavo F. Padovan 		switch (type) {
35000a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
35010a708f8fSGustavo F. Padovan 			mtu = val;
35020a708f8fSGustavo F. Padovan 			break;
35030a708f8fSGustavo F. Padovan 
35040a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
35050c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35060a708f8fSGustavo F. Padovan 			break;
35070a708f8fSGustavo F. Padovan 
35080a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
35090a708f8fSGustavo F. Padovan 			break;
35100a708f8fSGustavo F. Padovan 
35110a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
35120a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
35130a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
35140a708f8fSGustavo F. Padovan 			break;
35150a708f8fSGustavo F. Padovan 
35160a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
35170a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3518f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
351942dceae2SAndrei Emeltchenko 			break;
35200a708f8fSGustavo F. Padovan 
352142dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
352242dceae2SAndrei Emeltchenko 			remote_efs = 1;
352342dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
352442dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
35250a708f8fSGustavo F. Padovan 			break;
35260a708f8fSGustavo F. Padovan 
35276327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3528848566b3SMarcel Holtmann 			if (!chan->conn->hs_enabled)
35296327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
35306327eb98SAndrei Emeltchenko 
35316327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
35326327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3533836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
35346327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
35350a708f8fSGustavo F. Padovan 			break;
35360a708f8fSGustavo F. Padovan 
35370a708f8fSGustavo F. Padovan 		default:
35380a708f8fSGustavo F. Padovan 			if (hint)
35390a708f8fSGustavo F. Padovan 				break;
35400a708f8fSGustavo F. Padovan 
35410a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
35420a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
35430a708f8fSGustavo F. Padovan 			break;
35440a708f8fSGustavo F. Padovan 		}
35450a708f8fSGustavo F. Padovan 	}
35460a708f8fSGustavo F. Padovan 
354773ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
35480a708f8fSGustavo F. Padovan 		goto done;
35490a708f8fSGustavo F. Padovan 
35500c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
35510a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
35520a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3553c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
35540c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
35558c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
35560a708f8fSGustavo F. Padovan 			break;
35570a708f8fSGustavo F. Padovan 		}
35580a708f8fSGustavo F. Padovan 
355942dceae2SAndrei Emeltchenko 		if (remote_efs) {
3560848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
356142dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
356242dceae2SAndrei Emeltchenko 			else
356342dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
356442dceae2SAndrei Emeltchenko 		}
356542dceae2SAndrei Emeltchenko 
35660c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
35670a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
35680a708f8fSGustavo F. Padovan 
35690a708f8fSGustavo F. Padovan 		break;
35700a708f8fSGustavo F. Padovan 	}
35710a708f8fSGustavo F. Padovan 
35720a708f8fSGustavo F. Padovan done:
35730c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
35740a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
35750c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
35760a708f8fSGustavo F. Padovan 
357773ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
35780a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
35790a708f8fSGustavo F. Padovan 
35802d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
35812d792818SGustavo Padovan 				   (unsigned long) &rfc);
35820a708f8fSGustavo F. Padovan 	}
35830a708f8fSGustavo F. Padovan 
35840a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
35850a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
35860a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
35870a708f8fSGustavo F. Padovan 
35880a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
35890a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
35900a708f8fSGustavo F. Padovan 		else {
35910c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3592c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
35930a708f8fSGustavo F. Padovan 		}
35940c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
35950a708f8fSGustavo F. Padovan 
359642dceae2SAndrei Emeltchenko 		if (remote_efs) {
359742dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
359842dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
359942dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
360042dceae2SAndrei Emeltchenko 
360142dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
360242dceae2SAndrei Emeltchenko 
360342dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
360442dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
360542dceae2SAndrei Emeltchenko 
360642dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
360742dceae2SAndrei Emeltchenko 						   sizeof(efs),
360842dceae2SAndrei Emeltchenko 						   (unsigned long) &efs);
36090e8b207eSAndrei Emeltchenko 			} else {
36103e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
36110e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
36120e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
361342dceae2SAndrei Emeltchenko 			}
361442dceae2SAndrei Emeltchenko 		}
361542dceae2SAndrei Emeltchenko 
36160a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36170a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
361847d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3619c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36200a708f8fSGustavo F. Padovan 			break;
36210a708f8fSGustavo F. Padovan 
36220a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
36236327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
36242c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
36256327eb98SAndrei Emeltchenko 			else
36266327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
36276327eb98SAndrei Emeltchenko 
36282c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
36290a708f8fSGustavo F. Padovan 
3630c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36312d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36322d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3633c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3634c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36350a708f8fSGustavo F. Padovan 
363636c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
36370a708f8fSGustavo F. Padovan 
3638c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36390a708f8fSGustavo F. Padovan 
36400a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
36410a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
36420a708f8fSGustavo F. Padovan 
364342dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
364442dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
364542dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
364642dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
364742dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
364842dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
364942dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
365042dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
365142dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
365242dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
365342dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
36542d792818SGustavo Padovan 						   sizeof(efs),
36552d792818SGustavo Padovan 						   (unsigned long) &efs);
365642dceae2SAndrei Emeltchenko 			}
36570a708f8fSGustavo F. Padovan 			break;
36580a708f8fSGustavo F. Padovan 
36590a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3660c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36612d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36622d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3663c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3664c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36650a708f8fSGustavo F. Padovan 
3666c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36670a708f8fSGustavo F. Padovan 
36682d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
36692d792818SGustavo Padovan 					   (unsigned long) &rfc);
36700a708f8fSGustavo F. Padovan 
36710a708f8fSGustavo F. Padovan 			break;
36720a708f8fSGustavo F. Padovan 
36730a708f8fSGustavo F. Padovan 		default:
36740a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36750a708f8fSGustavo F. Padovan 
36760a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
36770c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
36780a708f8fSGustavo F. Padovan 		}
36790a708f8fSGustavo F. Padovan 
36800a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3681c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
36820a708f8fSGustavo F. Padovan 	}
3683fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
36840a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
368559e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
36860a708f8fSGustavo F. Padovan 
36870a708f8fSGustavo F. Padovan 	return ptr - data;
36880a708f8fSGustavo F. Padovan }
36890a708f8fSGustavo F. Padovan 
36902d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
36912d792818SGustavo Padovan 				void *data, u16 *result)
36920a708f8fSGustavo F. Padovan {
36930a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
36940a708f8fSGustavo F. Padovan 	void *ptr = req->data;
36950a708f8fSGustavo F. Padovan 	int type, olen;
36960a708f8fSGustavo F. Padovan 	unsigned long val;
369736e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
369866af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
36990a708f8fSGustavo F. Padovan 
3700fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
37010a708f8fSGustavo F. Padovan 
37020a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37030a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37040a708f8fSGustavo F. Padovan 
37050a708f8fSGustavo F. Padovan 		switch (type) {
37060a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
37070a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
37080a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
37090c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
37100a708f8fSGustavo F. Padovan 			} else
37110c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
37120c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
37130a708f8fSGustavo F. Padovan 			break;
37140a708f8fSGustavo F. Padovan 
37150a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
37160c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
37170a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
37180c1bc5c6SGustavo F. Padovan 					   2, chan->flush_to);
37190a708f8fSGustavo F. Padovan 			break;
37200a708f8fSGustavo F. Padovan 
37210a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
37220a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
37230a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
37240a708f8fSGustavo F. Padovan 
3725c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
37260c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
37270a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
37280a708f8fSGustavo F. Padovan 
372947d1ec61SGustavo F. Padovan 			chan->fcs = 0;
37300a708f8fSGustavo F. Padovan 
37310a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
37320a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
37330a708f8fSGustavo F. Padovan 			break;
37346327eb98SAndrei Emeltchenko 
37356327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3736c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
37373e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
37383e6b3b95SGustavo F. Padovan 					   chan->tx_win);
37396327eb98SAndrei Emeltchenko 			break;
374066af7aafSAndrei Emeltchenko 
374166af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
374266af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
374366af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
374466af7aafSAndrei Emeltchenko 
374566af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
374666af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
374766af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
374866af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
374966af7aafSAndrei Emeltchenko 
37502d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
37512d792818SGustavo Padovan 					   (unsigned long) &efs);
375266af7aafSAndrei Emeltchenko 			break;
3753cbabee78SAndrei Emeltchenko 
3754cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3755cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3756cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3757f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3758cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3759cbabee78SAndrei Emeltchenko 			break;
37600a708f8fSGustavo F. Padovan 		}
37610a708f8fSGustavo F. Padovan 	}
37620a708f8fSGustavo F. Padovan 
37630c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
37640a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
37650a708f8fSGustavo F. Padovan 
37660c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
37670a708f8fSGustavo F. Padovan 
37680e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
37690a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37700a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
377147d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
377247d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
377347d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3774c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3775c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3776c20f8e35SMat Martineau 						      rfc.txwin_size);
377766af7aafSAndrei Emeltchenko 
377866af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
377966af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
378066af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
378166af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
378266af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
378366af7aafSAndrei Emeltchenko 				chan->local_flush_to =
378466af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
378566af7aafSAndrei Emeltchenko 			}
37860a708f8fSGustavo F. Padovan 			break;
378766af7aafSAndrei Emeltchenko 
37880a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
378947d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
37900a708f8fSGustavo F. Padovan 		}
37910a708f8fSGustavo F. Padovan 	}
37920a708f8fSGustavo F. Padovan 
3793fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
379459e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
37950a708f8fSGustavo F. Padovan 
37960a708f8fSGustavo F. Padovan 	return ptr - data;
37970a708f8fSGustavo F. Padovan }
37980a708f8fSGustavo F. Padovan 
37992d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
38002d792818SGustavo Padovan 				u16 result, u16 flags)
38010a708f8fSGustavo F. Padovan {
38020a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
38030a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
38040a708f8fSGustavo F. Padovan 
3805fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
38060a708f8fSGustavo F. Padovan 
3807fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
38080a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
38090a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
38100a708f8fSGustavo F. Padovan 
38110a708f8fSGustavo F. Padovan 	return ptr - data;
38120a708f8fSGustavo F. Padovan }
38130a708f8fSGustavo F. Padovan 
381427e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
381527e2d4c8SJohan Hedberg {
381627e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
381727e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
381827e2d4c8SJohan Hedberg 
381927e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
382027e2d4c8SJohan Hedberg 
382127e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
382227e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
382327e2d4c8SJohan Hedberg 	rsp.mps     = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
38240cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
382527e2d4c8SJohan Hedberg 	rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
382627e2d4c8SJohan Hedberg 
382727e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
382827e2d4c8SJohan Hedberg 		       &rsp);
382927e2d4c8SJohan Hedberg }
383027e2d4c8SJohan Hedberg 
38318c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3832710f9b0aSGustavo F. Padovan {
3833710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
38348c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3835710f9b0aSGustavo F. Padovan 	u8 buf[128];
3836439f34acSAndrei Emeltchenko 	u8 rsp_code;
3837710f9b0aSGustavo F. Padovan 
3838fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3839fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3840ac73498cSAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3841ac73498cSAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3842439f34acSAndrei Emeltchenko 
3843439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3844439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3845439f34acSAndrei Emeltchenko 	else
3846439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3847439f34acSAndrei Emeltchenko 
3848439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3849439f34acSAndrei Emeltchenko 
3850439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3851710f9b0aSGustavo F. Padovan 
3852c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3853710f9b0aSGustavo F. Padovan 		return;
3854710f9b0aSGustavo F. Padovan 
3855710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3856710f9b0aSGustavo F. Padovan 		       l2cap_build_conf_req(chan, buf), buf);
3857710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3858710f9b0aSGustavo F. Padovan }
3859710f9b0aSGustavo F. Padovan 
386047d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
38610a708f8fSGustavo F. Padovan {
38620a708f8fSGustavo F. Padovan 	int type, olen;
38630a708f8fSGustavo F. Padovan 	unsigned long val;
3864c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3865c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3866c20f8e35SMat Martineau 	 */
3867c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3868c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3869c20f8e35SMat Martineau 		.mode = chan->mode,
3870c20f8e35SMat Martineau 		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3871c20f8e35SMat Martineau 		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3872c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3873c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3874c20f8e35SMat Martineau 	};
38750a708f8fSGustavo F. Padovan 
387647d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
38770a708f8fSGustavo F. Padovan 
38780c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
38790a708f8fSGustavo F. Padovan 		return;
38800a708f8fSGustavo F. Padovan 
38810a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
38820a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
38830a708f8fSGustavo F. Padovan 
3884c20f8e35SMat Martineau 		switch (type) {
3885c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3886c20f8e35SMat Martineau 			if (olen == sizeof(rfc))
38870a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
3888c20f8e35SMat Martineau 			break;
3889c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3890c20f8e35SMat Martineau 			txwin_ext = val;
3891c20f8e35SMat Martineau 			break;
3892c20f8e35SMat Martineau 		}
38930a708f8fSGustavo F. Padovan 	}
38940a708f8fSGustavo F. Padovan 
38950a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
38960a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
389747d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
389847d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
389947d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3900c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3901c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3902c20f8e35SMat Martineau 		else
3903c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3904c20f8e35SMat Martineau 					      rfc.txwin_size);
39050a708f8fSGustavo F. Padovan 		break;
39060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
390747d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
39080a708f8fSGustavo F. Padovan 	}
39090a708f8fSGustavo F. Padovan }
39100a708f8fSGustavo F. Padovan 
39112d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3912cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3913cb3b3152SJohan Hedberg 				    u8 *data)
39140a708f8fSGustavo F. Padovan {
3915e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
39160a708f8fSGustavo F. Padovan 
3917cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3918cb3b3152SJohan Hedberg 		return -EPROTO;
3919cb3b3152SJohan Hedberg 
3920e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
39210a708f8fSGustavo F. Padovan 		return 0;
39220a708f8fSGustavo F. Padovan 
39230a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
39240a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
392517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
39260a708f8fSGustavo F. Padovan 
39270a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39280a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39290a708f8fSGustavo F. Padovan 
39300a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39310a708f8fSGustavo F. Padovan 	}
39320a708f8fSGustavo F. Padovan 
39330a708f8fSGustavo F. Padovan 	return 0;
39340a708f8fSGustavo F. Padovan }
39350a708f8fSGustavo F. Padovan 
39361700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
39371700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
39384c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
39390a708f8fSGustavo F. Padovan {
39400a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39410a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
394223691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
39430a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
39440a708f8fSGustavo F. Padovan 
39450a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
39460a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
39470a708f8fSGustavo F. Padovan 
3948097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
39490a708f8fSGustavo F. Padovan 
39500a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
39516f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3952bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
395323691d75SGustavo F. Padovan 	if (!pchan) {
39540a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
39550a708f8fSGustavo F. Padovan 		goto sendresp;
39560a708f8fSGustavo F. Padovan 	}
39570a708f8fSGustavo F. Padovan 
39583df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
39598ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
39600a708f8fSGustavo F. Padovan 
39610a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
39622983fd68SAndrei Emeltchenko 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
39630a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
39649f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39650a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
39660a708f8fSGustavo F. Padovan 		goto response;
39670a708f8fSGustavo F. Padovan 	}
39680a708f8fSGustavo F. Padovan 
39690a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
39700a708f8fSGustavo F. Padovan 
39712dfa1003SGustavo Padovan 	/* Check if we already have channel with that dcid */
39722dfa1003SGustavo Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid))
39732dfa1003SGustavo Padovan 		goto response;
39742dfa1003SGustavo Padovan 
397580b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
397680808e43SGustavo F. Padovan 	if (!chan)
39770a708f8fSGustavo F. Padovan 		goto response;
39780a708f8fSGustavo F. Padovan 
3979330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
3980330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
3981330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
3982330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3983330b6c15SSyam Sidhardhan 	 */
3984330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3985330b6c15SSyam Sidhardhan 
39867eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
39877eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
39884f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
39894f1654e0SMarcel Holtmann 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
3990fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3991fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
39921700915fSMat Martineau 	chan->local_amp_id = amp_id;
39930a708f8fSGustavo F. Padovan 
39946be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
399548454079SGustavo F. Padovan 
3996fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
39970a708f8fSGustavo F. Padovan 
39988d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
39990a708f8fSGustavo F. Padovan 
4000fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
40010a708f8fSGustavo F. Padovan 
40020a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4003d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
4004bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4005f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
40060a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
40070a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
40082dc4e510SGustavo Padovan 				chan->ops->defer(chan);
40090a708f8fSGustavo F. Padovan 			} else {
40101700915fSMat Martineau 				/* Force pending result for AMP controllers.
40111700915fSMat Martineau 				 * The connection will succeed after the
40121700915fSMat Martineau 				 * physical link is up.
40131700915fSMat Martineau 				 */
40146ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4015f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
40160a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
40176ed971caSMarcel Holtmann 				} else {
4018f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
40196ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
40201700915fSMat Martineau 				}
40210a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
40220a708f8fSGustavo F. Padovan 			}
40230a708f8fSGustavo F. Padovan 		} else {
4024f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
40250a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
40260a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
40270a708f8fSGustavo F. Padovan 		}
40280a708f8fSGustavo F. Padovan 	} else {
4029f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
40300a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
40310a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
40320a708f8fSGustavo F. Padovan 	}
40330a708f8fSGustavo F. Padovan 
40340a708f8fSGustavo F. Padovan response:
40358ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
40363df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40370a708f8fSGustavo F. Padovan 
40380a708f8fSGustavo F. Padovan sendresp:
40390a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
40400a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
40410a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
40420a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
40434c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40440a708f8fSGustavo F. Padovan 
40450a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40460a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4047ac73498cSAndrei Emeltchenko 		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
40480a708f8fSGustavo F. Padovan 
40490a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40500a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
40510a708f8fSGustavo F. Padovan 
4052ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40530a708f8fSGustavo F. Padovan 
40542d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40552d792818SGustavo Padovan 			       sizeof(info), &info);
40560a708f8fSGustavo F. Padovan 	}
40570a708f8fSGustavo F. Padovan 
4058c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40590a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
40600a708f8fSGustavo F. Padovan 		u8 buf[128];
4061c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
40620a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
406373ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
406473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40650a708f8fSGustavo F. Padovan 	}
40661700915fSMat Martineau 
40671700915fSMat Martineau 	return chan;
40684c89b6aaSMat Martineau }
40690a708f8fSGustavo F. Padovan 
40704c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4071cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40724c89b6aaSMat Martineau {
40737b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
40747b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
40757b064edaSJaganath Kanakkassery 
4076cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4077cb3b3152SJohan Hedberg 		return -EPROTO;
4078cb3b3152SJohan Hedberg 
40797b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
40807b064edaSJaganath Kanakkassery 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
40817b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
40827b064edaSJaganath Kanakkassery 		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
40837b064edaSJaganath Kanakkassery 				      hcon->dst_type, 0, NULL, 0,
40847b064edaSJaganath Kanakkassery 				      hcon->dev_class);
40857b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
40867b064edaSJaganath Kanakkassery 
4087300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
40880a708f8fSGustavo F. Padovan 	return 0;
40890a708f8fSGustavo F. Padovan }
40900a708f8fSGustavo F. Padovan 
40915909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4092cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4093cb3b3152SJohan Hedberg 				    u8 *data)
40940a708f8fSGustavo F. Padovan {
40950a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
40960a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
409748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
40980a708f8fSGustavo F. Padovan 	u8 req[128];
40993df91ea2SAndrei Emeltchenko 	int err;
41000a708f8fSGustavo F. Padovan 
4101cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4102cb3b3152SJohan Hedberg 		return -EPROTO;
4103cb3b3152SJohan Hedberg 
41040a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
41050a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
41060a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
41070a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
41080a708f8fSGustavo F. Padovan 
41091b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
41101b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
41110a708f8fSGustavo F. Padovan 
41123df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41133df91ea2SAndrei Emeltchenko 
41140a708f8fSGustavo F. Padovan 	if (scid) {
41153df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
41163df91ea2SAndrei Emeltchenko 		if (!chan) {
411721870b52SJohan Hedberg 			err = -EBADSLT;
41183df91ea2SAndrei Emeltchenko 			goto unlock;
41193df91ea2SAndrei Emeltchenko 		}
41200a708f8fSGustavo F. Padovan 	} else {
41213df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
41223df91ea2SAndrei Emeltchenko 		if (!chan) {
412321870b52SJohan Hedberg 			err = -EBADSLT;
41243df91ea2SAndrei Emeltchenko 			goto unlock;
41253df91ea2SAndrei Emeltchenko 		}
41260a708f8fSGustavo F. Padovan 	}
41270a708f8fSGustavo F. Padovan 
41283df91ea2SAndrei Emeltchenko 	err = 0;
41293df91ea2SAndrei Emeltchenko 
41306be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
413148454079SGustavo F. Padovan 
41320a708f8fSGustavo F. Padovan 	switch (result) {
41330a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
413489bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4135fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4136fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4137c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41380a708f8fSGustavo F. Padovan 
4139c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41400a708f8fSGustavo F. Padovan 			break;
41410a708f8fSGustavo F. Padovan 
41420a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
414373ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, req), req);
414473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41450a708f8fSGustavo F. Padovan 		break;
41460a708f8fSGustavo F. Padovan 
41470a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4148c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41490a708f8fSGustavo F. Padovan 		break;
41500a708f8fSGustavo F. Padovan 
41510a708f8fSGustavo F. Padovan 	default:
415248454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
41530a708f8fSGustavo F. Padovan 		break;
41540a708f8fSGustavo F. Padovan 	}
41550a708f8fSGustavo F. Padovan 
41566be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
41573df91ea2SAndrei Emeltchenko 
41583df91ea2SAndrei Emeltchenko unlock:
41593df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
41603df91ea2SAndrei Emeltchenko 
41613df91ea2SAndrei Emeltchenko 	return err;
41620a708f8fSGustavo F. Padovan }
41630a708f8fSGustavo F. Padovan 
416447d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41650a708f8fSGustavo F. Padovan {
41660a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
41670a708f8fSGustavo F. Padovan 	 * sides request it.
41680a708f8fSGustavo F. Padovan 	 */
41690c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
417047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4171f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
417247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
41730a708f8fSGustavo F. Padovan }
41740a708f8fSGustavo F. Padovan 
417529d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
417629d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
417729d8a590SAndrei Emeltchenko {
417829d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
417929d8a590SAndrei Emeltchenko 
418029d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
418129d8a590SAndrei Emeltchenko 	       flags);
418229d8a590SAndrei Emeltchenko 
418329d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
418429d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
418529d8a590SAndrei Emeltchenko 
418629d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
418729d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
418829d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
418929d8a590SAndrei Emeltchenko }
419029d8a590SAndrei Emeltchenko 
4191662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4192662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4193662d652dSJohan Hedberg {
4194662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4195662d652dSJohan Hedberg 
4196662d652dSJohan Hedberg 	rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
4197662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4198662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4199662d652dSJohan Hedberg 
4200662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4201662d652dSJohan Hedberg }
4202662d652dSJohan Hedberg 
42032d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
42042d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
42052d792818SGustavo Padovan 				   u8 *data)
42060a708f8fSGustavo F. Padovan {
42070a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
42080a708f8fSGustavo F. Padovan 	u16 dcid, flags;
42090a708f8fSGustavo F. Padovan 	u8 rsp[64];
421048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42113c588192SMat Martineau 	int len, err = 0;
42120a708f8fSGustavo F. Padovan 
4213cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4214cb3b3152SJohan Hedberg 		return -EPROTO;
4215cb3b3152SJohan Hedberg 
42160a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
42170a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
42180a708f8fSGustavo F. Padovan 
42190a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42200a708f8fSGustavo F. Padovan 
4221baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4222662d652dSJohan Hedberg 	if (!chan) {
4223662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4224662d652dSJohan Hedberg 		return 0;
4225662d652dSJohan Hedberg 	}
42260a708f8fSGustavo F. Padovan 
4227033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4228662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4229662d652dSJohan Hedberg 				       chan->dcid);
42300a708f8fSGustavo F. Padovan 		goto unlock;
42310a708f8fSGustavo F. Padovan 	}
42320a708f8fSGustavo F. Padovan 
42330a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
42340a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4235cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
42360a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4237fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42380a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
42390a708f8fSGustavo F. Padovan 		goto unlock;
42400a708f8fSGustavo F. Padovan 	}
42410a708f8fSGustavo F. Padovan 
42420a708f8fSGustavo F. Padovan 	/* Store config. */
424373ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
424473ffa904SGustavo F. Padovan 	chan->conf_len += len;
42450a708f8fSGustavo F. Padovan 
424659e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42470a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
42480a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4249fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42505325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
42510a708f8fSGustavo F. Padovan 		goto unlock;
42520a708f8fSGustavo F. Padovan 	}
42530a708f8fSGustavo F. Padovan 
42540a708f8fSGustavo F. Padovan 	/* Complete config. */
425573ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
42560a708f8fSGustavo F. Padovan 	if (len < 0) {
42575e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42580a708f8fSGustavo F. Padovan 		goto unlock;
42590a708f8fSGustavo F. Padovan 	}
42600a708f8fSGustavo F. Padovan 
42611500109bSMat Martineau 	chan->ident = cmd->ident;
42620a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
426373ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
42640a708f8fSGustavo F. Padovan 
42650a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
426673ffa904SGustavo F. Padovan 	chan->conf_len = 0;
42670a708f8fSGustavo F. Padovan 
4268c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42690a708f8fSGustavo F. Padovan 		goto unlock;
42700a708f8fSGustavo F. Padovan 
4271c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
427247d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
42730a708f8fSGustavo F. Padovan 
4274105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4275105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
42763c588192SMat Martineau 			err = l2cap_ertm_init(chan);
42770a708f8fSGustavo F. Padovan 
42783c588192SMat Martineau 		if (err < 0)
42795e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
42803c588192SMat Martineau 		else
4281cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
42823c588192SMat Martineau 
42830a708f8fSGustavo F. Padovan 		goto unlock;
42840a708f8fSGustavo F. Padovan 	}
42850a708f8fSGustavo F. Padovan 
4286c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
42870a708f8fSGustavo F. Padovan 		u8 buf[64];
42880a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
428973ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
429073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
42910a708f8fSGustavo F. Padovan 	}
42920a708f8fSGustavo F. Padovan 
42930e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
42940e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
42950e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
42960e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42970e8b207eSAndrei Emeltchenko 
42980e8b207eSAndrei Emeltchenko 		/* check compatibility */
42990e8b207eSAndrei Emeltchenko 
430079de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4301f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
430229d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
430379de886dSAndrei Emeltchenko 		else
430479de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
43050e8b207eSAndrei Emeltchenko 	}
43060e8b207eSAndrei Emeltchenko 
43070a708f8fSGustavo F. Padovan unlock:
43086be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43093c588192SMat Martineau 	return err;
43100a708f8fSGustavo F. Padovan }
43110a708f8fSGustavo F. Padovan 
43122d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4313cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4314cb3b3152SJohan Hedberg 				   u8 *data)
43150a708f8fSGustavo F. Padovan {
43160a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43170a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
431848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4319cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
43203c588192SMat Martineau 	int err = 0;
43210a708f8fSGustavo F. Padovan 
4322cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4323cb3b3152SJohan Hedberg 		return -EPROTO;
4324cb3b3152SJohan Hedberg 
43250a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
43260a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
43270a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
43280a708f8fSGustavo F. Padovan 
432961386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
433061386cbaSAndrei Emeltchenko 	       result, len);
43310a708f8fSGustavo F. Padovan 
4332baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
433348454079SGustavo F. Padovan 	if (!chan)
43340a708f8fSGustavo F. Padovan 		return 0;
43350a708f8fSGustavo F. Padovan 
43360a708f8fSGustavo F. Padovan 	switch (result) {
43370a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
433847d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
43390e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43400a708f8fSGustavo F. Padovan 		break;
43410a708f8fSGustavo F. Padovan 
43420e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
43430e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43440e8b207eSAndrei Emeltchenko 
43450e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43460e8b207eSAndrei Emeltchenko 			char buf[64];
43470e8b207eSAndrei Emeltchenko 
43480e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
43490e8b207eSAndrei Emeltchenko 						   buf, &result);
43500e8b207eSAndrei Emeltchenko 			if (len < 0) {
43515e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43520e8b207eSAndrei Emeltchenko 				goto done;
43530e8b207eSAndrei Emeltchenko 			}
43540e8b207eSAndrei Emeltchenko 
4355f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
435679de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
435779de886dSAndrei Emeltchenko 							0);
43585ce66b59SAndrei Emeltchenko 			} else {
43595ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
43605ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
436179de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
43620e8b207eSAndrei Emeltchenko 				}
43635ce66b59SAndrei Emeltchenko 			}
43645ce66b59SAndrei Emeltchenko 		}
43650e8b207eSAndrei Emeltchenko 		goto done;
43660e8b207eSAndrei Emeltchenko 
43670a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
436873ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43690a708f8fSGustavo F. Padovan 			char req[64];
43700a708f8fSGustavo F. Padovan 
43710a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43725e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43730a708f8fSGustavo F. Padovan 				goto done;
43740a708f8fSGustavo F. Padovan 			}
43750a708f8fSGustavo F. Padovan 
43760a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
43770a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4378b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4379b4450035SGustavo F. Padovan 						   req, &result);
43800a708f8fSGustavo F. Padovan 			if (len < 0) {
43815e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43820a708f8fSGustavo F. Padovan 				goto done;
43830a708f8fSGustavo F. Padovan 			}
43840a708f8fSGustavo F. Padovan 
43850a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
43860a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
438773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
43880a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
43890a708f8fSGustavo F. Padovan 				goto done;
43900a708f8fSGustavo F. Padovan 			break;
43910a708f8fSGustavo F. Padovan 		}
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan 	default:
43946be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
43952e0052e4SAndrei Emeltchenko 
4396ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
43975e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
43980a708f8fSGustavo F. Padovan 		goto done;
43990a708f8fSGustavo F. Padovan 	}
44000a708f8fSGustavo F. Padovan 
440159e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
44020a708f8fSGustavo F. Padovan 		goto done;
44030a708f8fSGustavo F. Padovan 
4404c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
44050a708f8fSGustavo F. Padovan 
4406c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
440747d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44080a708f8fSGustavo F. Padovan 
4409105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4410105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44113c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44120a708f8fSGustavo F. Padovan 
44133c588192SMat Martineau 		if (err < 0)
44145e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44153c588192SMat Martineau 		else
4416cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44170a708f8fSGustavo F. Padovan 	}
44180a708f8fSGustavo F. Padovan 
44190a708f8fSGustavo F. Padovan done:
44206be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44213c588192SMat Martineau 	return err;
44220a708f8fSGustavo F. Padovan }
44230a708f8fSGustavo F. Padovan 
44242d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4425cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4426cb3b3152SJohan Hedberg 				       u8 *data)
44270a708f8fSGustavo F. Padovan {
44280a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44290a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
44300a708f8fSGustavo F. Padovan 	u16 dcid, scid;
443148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44320a708f8fSGustavo F. Padovan 
4433cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4434cb3b3152SJohan Hedberg 		return -EPROTO;
4435cb3b3152SJohan Hedberg 
44360a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
44370a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
44380a708f8fSGustavo F. Padovan 
44390a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44400a708f8fSGustavo F. Padovan 
44413df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
44423df91ea2SAndrei Emeltchenko 
44433df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
44443df91ea2SAndrei Emeltchenko 	if (!chan) {
44453df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4446662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4447662d652dSJohan Hedberg 		return 0;
44483df91ea2SAndrei Emeltchenko 	}
44490a708f8fSGustavo F. Padovan 
44506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
44516be36555SAndrei Emeltchenko 
4452fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4453fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
44540a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44550a708f8fSGustavo F. Padovan 
44565ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
44570a708f8fSGustavo F. Padovan 
445861d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
445948454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
44606be36555SAndrei Emeltchenko 
44616be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44620a708f8fSGustavo F. Padovan 
446380b98027SGustavo Padovan 	chan->ops->close(chan);
446461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44653df91ea2SAndrei Emeltchenko 
44663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
44673df91ea2SAndrei Emeltchenko 
44680a708f8fSGustavo F. Padovan 	return 0;
44690a708f8fSGustavo F. Padovan }
44700a708f8fSGustavo F. Padovan 
44712d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4472cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4473cb3b3152SJohan Hedberg 				       u8 *data)
44740a708f8fSGustavo F. Padovan {
44750a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44760a708f8fSGustavo F. Padovan 	u16 dcid, scid;
447748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44780a708f8fSGustavo F. Padovan 
4479cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4480cb3b3152SJohan Hedberg 		return -EPROTO;
4481cb3b3152SJohan Hedberg 
44820a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
44830a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
44840a708f8fSGustavo F. Padovan 
44850a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
44860a708f8fSGustavo F. Padovan 
44873df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
44883df91ea2SAndrei Emeltchenko 
44893df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
44903df91ea2SAndrei Emeltchenko 	if (!chan) {
44913df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
44920a708f8fSGustavo F. Padovan 		return 0;
44933df91ea2SAndrei Emeltchenko 	}
44940a708f8fSGustavo F. Padovan 
44956be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
449648454079SGustavo F. Padovan 
449761d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
449848454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
44996be36555SAndrei Emeltchenko 
45006be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45010a708f8fSGustavo F. Padovan 
450280b98027SGustavo Padovan 	chan->ops->close(chan);
450361d6ef3eSMat Martineau 	l2cap_chan_put(chan);
45043df91ea2SAndrei Emeltchenko 
45053df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
45063df91ea2SAndrei Emeltchenko 
45070a708f8fSGustavo F. Padovan 	return 0;
45080a708f8fSGustavo F. Padovan }
45090a708f8fSGustavo F. Padovan 
45102d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4511cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4512cb3b3152SJohan Hedberg 					u8 *data)
45130a708f8fSGustavo F. Padovan {
45140a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
45150a708f8fSGustavo F. Padovan 	u16 type;
45160a708f8fSGustavo F. Padovan 
4517cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4518cb3b3152SJohan Hedberg 		return -EPROTO;
4519cb3b3152SJohan Hedberg 
45200a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
45210a708f8fSGustavo F. Padovan 
45220a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
45230a708f8fSGustavo F. Padovan 
45240a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
45250a708f8fSGustavo F. Padovan 		u8 buf[8];
45260a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
45270a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4528ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
4529ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
45300a708f8fSGustavo F. Padovan 		if (!disable_ertm)
45310a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45320a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
4533848566b3SMarcel Holtmann 		if (conn->hs_enabled)
45346327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
45356327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4536a5fd6f30SAndrei Emeltchenko 
45370a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
45382d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45392d792818SGustavo Padovan 			       buf);
45400a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
45410a708f8fSGustavo F. Padovan 		u8 buf[12];
45420a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
454350a147cdSMat Martineau 
4544848566b3SMarcel Holtmann 		if (conn->hs_enabled)
454550a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
454650a147cdSMat Martineau 		else
454750a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
454850a147cdSMat Martineau 
4549ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4550ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
4551c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
45522d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45532d792818SGustavo Padovan 			       buf);
45540a708f8fSGustavo F. Padovan 	} else {
45550a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
45560a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4557ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
45582d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45592d792818SGustavo Padovan 			       &rsp);
45600a708f8fSGustavo F. Padovan 	}
45610a708f8fSGustavo F. Padovan 
45620a708f8fSGustavo F. Padovan 	return 0;
45630a708f8fSGustavo F. Padovan }
45640a708f8fSGustavo F. Padovan 
45652d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4566cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4567cb3b3152SJohan Hedberg 					u8 *data)
45680a708f8fSGustavo F. Padovan {
45690a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45700a708f8fSGustavo F. Padovan 	u16 type, result;
45710a708f8fSGustavo F. Padovan 
45723f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4573cb3b3152SJohan Hedberg 		return -EPROTO;
4574cb3b3152SJohan Hedberg 
45750a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
45760a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
45770a708f8fSGustavo F. Padovan 
45780a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
45790a708f8fSGustavo F. Padovan 
4580e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4581e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4582e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4583e90165beSAndrei Emeltchenko 		return 0;
4584e90165beSAndrei Emeltchenko 
458517cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
45860a708f8fSGustavo F. Padovan 
45870a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
45880a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45890a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
45900a708f8fSGustavo F. Padovan 
45910a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
45920a708f8fSGustavo F. Padovan 
45930a708f8fSGustavo F. Padovan 		return 0;
45940a708f8fSGustavo F. Padovan 	}
45950a708f8fSGustavo F. Padovan 
4596978c93b9SAndrei Emeltchenko 	switch (type) {
4597978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
45980a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
45990a708f8fSGustavo F. Padovan 
46000a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
46010a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4602ac73498cSAndrei Emeltchenko 			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
46030a708f8fSGustavo F. Padovan 
46040a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
46050a708f8fSGustavo F. Padovan 
46060a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
46070a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
46080a708f8fSGustavo F. Padovan 		} else {
46090a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46100a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
46110a708f8fSGustavo F. Padovan 
46120a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
46130a708f8fSGustavo F. Padovan 		}
4614978c93b9SAndrei Emeltchenko 		break;
4615978c93b9SAndrei Emeltchenko 
4616978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
4617978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
46180a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46190a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46200a708f8fSGustavo F. Padovan 
46210a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4622978c93b9SAndrei Emeltchenko 		break;
46230a708f8fSGustavo F. Padovan 	}
46240a708f8fSGustavo F. Padovan 
46250a708f8fSGustavo F. Padovan 	return 0;
46260a708f8fSGustavo F. Padovan }
46270a708f8fSGustavo F. Padovan 
46281700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
46292d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
46302d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4631f94ff6ffSMat Martineau {
4632f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
46336e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
46341700915fSMat Martineau 	struct l2cap_chan *chan;
46356e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4636f94ff6ffSMat Martineau 	u16 psm, scid;
4637f94ff6ffSMat Martineau 
4638f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4639f94ff6ffSMat Martineau 		return -EPROTO;
4640f94ff6ffSMat Martineau 
4641848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
4642f94ff6ffSMat Martineau 		return -EINVAL;
4643f94ff6ffSMat Martineau 
4644f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4645f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4646f94ff6ffSMat Martineau 
4647ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4648f94ff6ffSMat Martineau 
46496e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
46506ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
46516e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46526e1df6a6SAndrei Emeltchenko 			      req->amp_id);
46536e1df6a6SAndrei Emeltchenko 		return 0;
46546e1df6a6SAndrei Emeltchenko 	}
46551700915fSMat Martineau 
46561700915fSMat Martineau 	/* Validate AMP controller id */
46571700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
46586e1df6a6SAndrei Emeltchenko 	if (!hdev)
46596e1df6a6SAndrei Emeltchenko 		goto error;
46601700915fSMat Martineau 
46616e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
46626e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
46636e1df6a6SAndrei Emeltchenko 		goto error;
46646e1df6a6SAndrei Emeltchenko 	}
46656e1df6a6SAndrei Emeltchenko 
46666e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46676e1df6a6SAndrei Emeltchenko 			     req->amp_id);
46686e1df6a6SAndrei Emeltchenko 	if (chan) {
46696e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
46706e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
46716e1df6a6SAndrei Emeltchenko 
467298e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
467398e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
46746e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
46756e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4676662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4677662d652dSJohan Hedberg 					       chan->dcid);
4678662d652dSJohan Hedberg 			return 0;
46796e1df6a6SAndrei Emeltchenko 		}
46806e1df6a6SAndrei Emeltchenko 
46816e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
46826e1df6a6SAndrei Emeltchenko 
46836e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
46846e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4685fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
46866e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
46876e1df6a6SAndrei Emeltchenko 	}
46886e1df6a6SAndrei Emeltchenko 
46896e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
46906e1df6a6SAndrei Emeltchenko 
46916e1df6a6SAndrei Emeltchenko 	return 0;
46926e1df6a6SAndrei Emeltchenko 
46936e1df6a6SAndrei Emeltchenko error:
4694f94ff6ffSMat Martineau 	rsp.dcid = 0;
4695f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
46961700915fSMat Martineau 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
46978ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4698f94ff6ffSMat Martineau 
4699f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4700f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4701f94ff6ffSMat Martineau 
4702dc280801SJohan Hedberg 	return 0;
4703f94ff6ffSMat Martineau }
4704f94ff6ffSMat Martineau 
47058eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
47068eb200bdSMat Martineau {
47078eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
47088eb200bdSMat Martineau 	u8 ident;
47098eb200bdSMat Martineau 
47108eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
47118eb200bdSMat Martineau 
47128eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
47138eb200bdSMat Martineau 	chan->ident = ident;
47148eb200bdSMat Martineau 
47158eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
47168eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
47178eb200bdSMat Martineau 
47188eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
47198eb200bdSMat Martineau 		       &req);
47208eb200bdSMat Martineau 
47218eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47228eb200bdSMat Martineau }
47238eb200bdSMat Martineau 
47241500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
47258d5a04a1SMat Martineau {
47268d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
47278d5a04a1SMat Martineau 
47281500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47298d5a04a1SMat Martineau 
47301500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
47318d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
47328d5a04a1SMat Martineau 
47331500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
47341500109bSMat Martineau 		       sizeof(rsp), &rsp);
47358d5a04a1SMat Martineau }
47368d5a04a1SMat Martineau 
47375b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
47388d5a04a1SMat Martineau {
47398d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47408d5a04a1SMat Martineau 
47415b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47428d5a04a1SMat Martineau 
47435b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
47448d5a04a1SMat Martineau 
47455b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
47468d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
47478d5a04a1SMat Martineau 
47485b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
47495b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47505b155ef9SMat Martineau 
47515b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47525b155ef9SMat Martineau }
47535b155ef9SMat Martineau 
47545b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
47555b155ef9SMat Martineau {
47565b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47575b155ef9SMat Martineau 
47585b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
47595b155ef9SMat Martineau 
47605b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
47615b155ef9SMat Martineau 	cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
47625b155ef9SMat Martineau 
47635b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
47645b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47658d5a04a1SMat Martineau }
47668d5a04a1SMat Martineau 
47678d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
47688d5a04a1SMat Martineau 					 u16 icid)
47698d5a04a1SMat Martineau {
47708d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
47718d5a04a1SMat Martineau 
4772ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
47738d5a04a1SMat Martineau 
47748d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
47758d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
47768d5a04a1SMat Martineau }
47778d5a04a1SMat Martineau 
47785f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
47795f3847a4SMat Martineau {
47805f3847a4SMat Martineau 	chan->hs_hchan = NULL;
47815f3847a4SMat Martineau 	chan->hs_hcon = NULL;
47825f3847a4SMat Martineau 
47835f3847a4SMat Martineau 	/* Placeholder - release the logical link */
47845f3847a4SMat Martineau }
47855f3847a4SMat Martineau 
47861500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
47871500109bSMat Martineau {
47881500109bSMat Martineau 	/* Logical link setup failed */
47891500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
47901500109bSMat Martineau 		/* Create channel failure, disconnect */
47915e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
47921500109bSMat Martineau 		return;
47931500109bSMat Martineau 	}
47941500109bSMat Martineau 
47951500109bSMat Martineau 	switch (chan->move_role) {
47961500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
47971500109bSMat Martineau 		l2cap_move_done(chan);
47981500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
47991500109bSMat Martineau 		break;
48001500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
48011500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
48021500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
48031500109bSMat Martineau 			/* Remote has only sent pending or
48041500109bSMat Martineau 			 * success responses, clean up
48051500109bSMat Martineau 			 */
48061500109bSMat Martineau 			l2cap_move_done(chan);
48071500109bSMat Martineau 		}
48081500109bSMat Martineau 
48091500109bSMat Martineau 		/* Other amp move states imply that the move
48101500109bSMat Martineau 		 * has already aborted
48111500109bSMat Martineau 		 */
48121500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
48131500109bSMat Martineau 		break;
48141500109bSMat Martineau 	}
48151500109bSMat Martineau }
48161500109bSMat Martineau 
48171500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
48181500109bSMat Martineau 					struct hci_chan *hchan)
48191500109bSMat Martineau {
48201500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
48211500109bSMat Martineau 
4822336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
48231500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48241500109bSMat Martineau 
482535ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
48261500109bSMat Martineau 
48271500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4828fe79c6feSAndrei Emeltchenko 		int err;
48291500109bSMat Martineau 
48301500109bSMat Martineau 		set_default_fcs(chan);
48311500109bSMat Martineau 
48321500109bSMat Martineau 		err = l2cap_ertm_init(chan);
48331500109bSMat Martineau 		if (err < 0)
48345e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
48351500109bSMat Martineau 		else
48361500109bSMat Martineau 			l2cap_chan_ready(chan);
48371500109bSMat Martineau 	}
48381500109bSMat Martineau }
48391500109bSMat Martineau 
48401500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
48411500109bSMat Martineau 				      struct hci_chan *hchan)
48421500109bSMat Martineau {
48431500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
48441500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48451500109bSMat Martineau 
48461500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
48471500109bSMat Martineau 
48481500109bSMat Martineau 	switch (chan->move_state) {
48491500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
48501500109bSMat Martineau 		/* Move confirm will be sent after a success
48511500109bSMat Martineau 		 * response is received
48521500109bSMat Martineau 		 */
48531500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
48541500109bSMat Martineau 		break;
48551500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
48561500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
48571500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
48581500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
48591500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
48601500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
48611500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
48621500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48631500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48641500109bSMat Martineau 		}
48651500109bSMat Martineau 		break;
48661500109bSMat Martineau 	default:
48671500109bSMat Martineau 		/* Move was not in expected state, free the channel */
48681500109bSMat Martineau 		__release_logical_link(chan);
48691500109bSMat Martineau 
48701500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
48711500109bSMat Martineau 	}
48721500109bSMat Martineau }
48731500109bSMat Martineau 
48741500109bSMat Martineau /* Call with chan locked */
487527695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
48765b155ef9SMat Martineau 		       u8 status)
48775b155ef9SMat Martineau {
48781500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
48791500109bSMat Martineau 
48801500109bSMat Martineau 	if (status) {
48811500109bSMat Martineau 		l2cap_logical_fail(chan);
48821500109bSMat Martineau 		__release_logical_link(chan);
48835b155ef9SMat Martineau 		return;
48845b155ef9SMat Martineau 	}
48855b155ef9SMat Martineau 
48861500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
48871500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
48886ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
48891500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
48901500109bSMat Martineau 	} else {
48911500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
48921500109bSMat Martineau 	}
48931500109bSMat Martineau }
48941500109bSMat Martineau 
48953f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
48963f7a56c4SMat Martineau {
48973f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
48983f7a56c4SMat Martineau 
48996ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
49003f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
49013f7a56c4SMat Martineau 			return;
49023f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49033f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
49043f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
49053f7a56c4SMat Martineau 	} else {
49063f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49073f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
49083f7a56c4SMat Martineau 		chan->move_id = 0;
49093f7a56c4SMat Martineau 		l2cap_move_setup(chan);
49103f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
49113f7a56c4SMat Martineau 	}
49123f7a56c4SMat Martineau }
49133f7a56c4SMat Martineau 
49148eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
49158eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
49168eb200bdSMat Martineau {
491762748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
491862748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
491962748ca1SAndrei Emeltchenko 
492012d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
492112d6cc60SAndrei Emeltchenko 
492262748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
492362748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
492462748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
492562748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
492662748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
492762748ca1SAndrei Emeltchenko 		} else {
492862748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
492962748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
493062748ca1SAndrei Emeltchenko 		}
493162748ca1SAndrei Emeltchenko 
493262748ca1SAndrei Emeltchenko 		return;
493362748ca1SAndrei Emeltchenko 	}
493462748ca1SAndrei Emeltchenko 
493562748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
493662748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
49378eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
49388eb200bdSMat Martineau 		char buf[128];
49398eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
49408eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
49418eb200bdSMat Martineau 
49428eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
49438eb200bdSMat Martineau 			/* Send successful response */
494462cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
494562cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49468eb200bdSMat Martineau 		} else {
49478eb200bdSMat Martineau 			/* Send negative response */
494862cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
494962cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49508eb200bdSMat Martineau 		}
49518eb200bdSMat Martineau 
49528eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
49538eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
49548eb200bdSMat Martineau 
49558eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4956f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
49578eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
49588eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
49598eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
49608eb200bdSMat Martineau 				       l2cap_build_conf_req(chan, buf), buf);
49618eb200bdSMat Martineau 			chan->num_conf_req++;
49628eb200bdSMat Martineau 		}
49638eb200bdSMat Martineau 	}
49648eb200bdSMat Martineau }
49658eb200bdSMat Martineau 
49668eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
49678eb200bdSMat Martineau 				   u8 remote_amp_id)
49688eb200bdSMat Martineau {
49698eb200bdSMat Martineau 	l2cap_move_setup(chan);
49708eb200bdSMat Martineau 	chan->move_id = local_amp_id;
49718eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
49728eb200bdSMat Martineau 
49738eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
49748eb200bdSMat Martineau }
49758eb200bdSMat Martineau 
49768eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
49778eb200bdSMat Martineau {
49788eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
49798eb200bdSMat Martineau 
49808eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
49818eb200bdSMat Martineau 
49828eb200bdSMat Martineau 	if (hchan) {
49838eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
49848eb200bdSMat Martineau 			/* Logical link is ready to go */
49858eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
49868eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
49878eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
49888eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
49898eb200bdSMat Martineau 
49908eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
49918eb200bdSMat Martineau 		} else {
49928eb200bdSMat Martineau 			/* Wait for logical link to be ready */
49938eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
49948eb200bdSMat Martineau 		}
49958eb200bdSMat Martineau 	} else {
49968eb200bdSMat Martineau 		/* Logical link not available */
49978eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
49988eb200bdSMat Martineau 	}
49998eb200bdSMat Martineau }
50008eb200bdSMat Martineau 
50018eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
50028eb200bdSMat Martineau {
50038eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50048eb200bdSMat Martineau 		u8 rsp_result;
50058eb200bdSMat Martineau 		if (result == -EINVAL)
50068eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
50078eb200bdSMat Martineau 		else
50088eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
50098eb200bdSMat Martineau 
50108eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
50118eb200bdSMat Martineau 	}
50128eb200bdSMat Martineau 
50138eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
50148eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
50158eb200bdSMat Martineau 
50168eb200bdSMat Martineau 	/* Restart data transmission */
50178eb200bdSMat Martineau 	l2cap_ertm_send(chan);
50188eb200bdSMat Martineau }
50198eb200bdSMat Martineau 
5020a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5021a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
50228eb200bdSMat Martineau {
5023770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5024fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5025770bfefaSAndrei Emeltchenko 
50268eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
50278eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
50288eb200bdSMat Martineau 
50298eb200bdSMat Martineau 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
50308eb200bdSMat Martineau 		l2cap_chan_unlock(chan);
50318eb200bdSMat Martineau 		return;
50328eb200bdSMat Martineau 	}
50338eb200bdSMat Martineau 
50348eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
50358eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
50368eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
50378eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
50388eb200bdSMat Martineau 	} else {
50398eb200bdSMat Martineau 		switch (chan->move_role) {
50408eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
50418eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
50428eb200bdSMat Martineau 					       remote_amp_id);
50438eb200bdSMat Martineau 			break;
50448eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
50458eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
50468eb200bdSMat Martineau 			break;
50478eb200bdSMat Martineau 		default:
50488eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
50498eb200bdSMat Martineau 			break;
50508eb200bdSMat Martineau 		}
50518eb200bdSMat Martineau 	}
50528eb200bdSMat Martineau }
50538eb200bdSMat Martineau 
50548d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5055ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5056ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
50578d5a04a1SMat Martineau {
50588d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
50591500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
506002b0fbb9SMat Martineau 	struct l2cap_chan *chan;
50618d5a04a1SMat Martineau 	u16 icid = 0;
50628d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
50638d5a04a1SMat Martineau 
50648d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
50658d5a04a1SMat Martineau 		return -EPROTO;
50668d5a04a1SMat Martineau 
50678d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
50688d5a04a1SMat Martineau 
5069ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
50708d5a04a1SMat Martineau 
5071848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
50728d5a04a1SMat Martineau 		return -EINVAL;
50738d5a04a1SMat Martineau 
507402b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
507502b0fbb9SMat Martineau 	if (!chan) {
50761500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
50771500109bSMat Martineau 		rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
50781500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
50791500109bSMat Martineau 			       sizeof(rsp), &rsp);
508002b0fbb9SMat Martineau 		return 0;
508102b0fbb9SMat Martineau 	}
508202b0fbb9SMat Martineau 
50831500109bSMat Martineau 	chan->ident = cmd->ident;
50841500109bSMat Martineau 
508502b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
508602b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
508702b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
508802b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
508902b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
509002b0fbb9SMat Martineau 		goto send_move_response;
509102b0fbb9SMat Martineau 	}
509202b0fbb9SMat Martineau 
509302b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
509402b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
509502b0fbb9SMat Martineau 		goto send_move_response;
509602b0fbb9SMat Martineau 	}
509702b0fbb9SMat Martineau 
50986ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
509902b0fbb9SMat Martineau 		struct hci_dev *hdev;
510002b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
510102b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
510202b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
510302b0fbb9SMat Martineau 			if (hdev)
510402b0fbb9SMat Martineau 				hci_dev_put(hdev);
510502b0fbb9SMat Martineau 
510602b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
510702b0fbb9SMat Martineau 			goto send_move_response;
510802b0fbb9SMat Martineau 		}
510902b0fbb9SMat Martineau 		hci_dev_put(hdev);
511002b0fbb9SMat Martineau 	}
511102b0fbb9SMat Martineau 
511202b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
511302b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
511402b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
511502b0fbb9SMat Martineau 	 */
511602b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
511702b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
51186f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
511902b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
512002b0fbb9SMat Martineau 		goto send_move_response;
512102b0fbb9SMat Martineau 	}
512202b0fbb9SMat Martineau 
512302b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
512402b0fbb9SMat Martineau 	l2cap_move_setup(chan);
512502b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
512602b0fbb9SMat Martineau 	icid = chan->dcid;
512702b0fbb9SMat Martineau 
51286ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
512902b0fbb9SMat Martineau 		/* Moving to BR/EDR */
513002b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
513102b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
513202b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
513302b0fbb9SMat Martineau 		} else {
513402b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
513502b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
513602b0fbb9SMat Martineau 		}
513702b0fbb9SMat Martineau 	} else {
513802b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
513902b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
514002b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
514102b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
514202b0fbb9SMat Martineau 	}
514302b0fbb9SMat Martineau 
514402b0fbb9SMat Martineau send_move_response:
51451500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
51468d5a04a1SMat Martineau 
514702b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
514802b0fbb9SMat Martineau 
51498d5a04a1SMat Martineau 	return 0;
51508d5a04a1SMat Martineau }
51518d5a04a1SMat Martineau 
51525b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
51535b155ef9SMat Martineau {
51545b155ef9SMat Martineau 	struct l2cap_chan *chan;
51555b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
51565b155ef9SMat Martineau 
51575b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
51585b155ef9SMat Martineau 	if (!chan) {
51595b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51605b155ef9SMat Martineau 		return;
51615b155ef9SMat Martineau 	}
51625b155ef9SMat Martineau 
51635b155ef9SMat Martineau 	__clear_chan_timer(chan);
51645b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
51655b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
51665b155ef9SMat Martineau 
51675b155ef9SMat Martineau 	switch (chan->move_state) {
51685b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
51695b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
51705b155ef9SMat Martineau 		 * is complete.
51715b155ef9SMat Martineau 		 */
51725b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51735b155ef9SMat Martineau 		break;
51745b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
51755b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
51765b155ef9SMat Martineau 			break;
51775b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
51785b155ef9SMat Martineau 				    &chan->conn_state)) {
51795b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
51805b155ef9SMat Martineau 		} else {
51815b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
51825b155ef9SMat Martineau 			 * proceed with move
51835b155ef9SMat Martineau 			 */
51845b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
51855b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
51865b155ef9SMat Martineau 		}
51875b155ef9SMat Martineau 		break;
51885b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
51895b155ef9SMat Martineau 		/* Moving to AMP */
51905b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
51915b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
51925b155ef9SMat Martineau 			 * after logical link is ready
51935b155ef9SMat Martineau 			 */
51945b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51955b155ef9SMat Martineau 		} else {
51965b155ef9SMat Martineau 			/* Both logical link and move success
51975b155ef9SMat Martineau 			 * are required to confirm
51985b155ef9SMat Martineau 			 */
51995b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
52005b155ef9SMat Martineau 		}
52015b155ef9SMat Martineau 
52025b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
52035b155ef9SMat Martineau 		if (!hchan) {
52045b155ef9SMat Martineau 			/* Logical link not available */
52055b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52065b155ef9SMat Martineau 			break;
52075b155ef9SMat Martineau 		}
52085b155ef9SMat Martineau 
52095b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
52105b155ef9SMat Martineau 		 * send confirmation.
52115b155ef9SMat Martineau 		 */
52125b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
52135b155ef9SMat Martineau 			break;
52145b155ef9SMat Martineau 
52155b155ef9SMat Martineau 		/* Logical link is already ready to go */
52165b155ef9SMat Martineau 
52175b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
52185b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
52195b155ef9SMat Martineau 
52205b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
52215b155ef9SMat Martineau 			/* Can confirm now */
52225b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
52235b155ef9SMat Martineau 		} else {
52245b155ef9SMat Martineau 			/* Now only need move success
52255b155ef9SMat Martineau 			 * to confirm
52265b155ef9SMat Martineau 			 */
52275b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
52285b155ef9SMat Martineau 		}
52295b155ef9SMat Martineau 
52305b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
52315b155ef9SMat Martineau 		break;
52325b155ef9SMat Martineau 	default:
52335b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
52345b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
52355b155ef9SMat Martineau 		l2cap_move_done(chan);
52365b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52375b155ef9SMat Martineau 	}
52385b155ef9SMat Martineau 
52395b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52405b155ef9SMat Martineau }
52415b155ef9SMat Martineau 
52425b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
52435b155ef9SMat Martineau 			    u16 result)
52445b155ef9SMat Martineau {
52455b155ef9SMat Martineau 	struct l2cap_chan *chan;
52465b155ef9SMat Martineau 
52475b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
52485b155ef9SMat Martineau 	if (!chan) {
52495b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
52505b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
52515b155ef9SMat Martineau 		return;
52525b155ef9SMat Martineau 	}
52535b155ef9SMat Martineau 
52545b155ef9SMat Martineau 	__clear_chan_timer(chan);
52555b155ef9SMat Martineau 
52565b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
52575b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
52585b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
52595b155ef9SMat Martineau 		} else {
52605b155ef9SMat Martineau 			/* Cleanup - cancel move */
52615b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
52625b155ef9SMat Martineau 			l2cap_move_done(chan);
52635b155ef9SMat Martineau 		}
52645b155ef9SMat Martineau 	}
52655b155ef9SMat Martineau 
52665b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52675b155ef9SMat Martineau 
52685b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52695b155ef9SMat Martineau }
52705b155ef9SMat Martineau 
52715b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5272ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5273ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
52748d5a04a1SMat Martineau {
52758d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
52768d5a04a1SMat Martineau 	u16 icid, result;
52778d5a04a1SMat Martineau 
52788d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
52798d5a04a1SMat Martineau 		return -EPROTO;
52808d5a04a1SMat Martineau 
52818d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
52828d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
52838d5a04a1SMat Martineau 
5284ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
52858d5a04a1SMat Martineau 
52865b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
52875b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
52885b155ef9SMat Martineau 	else
52895b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
52908d5a04a1SMat Martineau 
52918d5a04a1SMat Martineau 	return 0;
52928d5a04a1SMat Martineau }
52938d5a04a1SMat Martineau 
52945f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5295ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5296ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
52978d5a04a1SMat Martineau {
52988d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
52995f3847a4SMat Martineau 	struct l2cap_chan *chan;
53008d5a04a1SMat Martineau 	u16 icid, result;
53018d5a04a1SMat Martineau 
53028d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
53038d5a04a1SMat Martineau 		return -EPROTO;
53048d5a04a1SMat Martineau 
53058d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
53068d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
53078d5a04a1SMat Martineau 
5308ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
53098d5a04a1SMat Martineau 
53105f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
53115f3847a4SMat Martineau 	if (!chan) {
53125f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
53138d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53145f3847a4SMat Martineau 		return 0;
53155f3847a4SMat Martineau 	}
53165f3847a4SMat Martineau 
53175f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
53185f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
53195f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
53206ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
53215f3847a4SMat Martineau 				__release_logical_link(chan);
53225f3847a4SMat Martineau 		} else {
53235f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
53245f3847a4SMat Martineau 		}
53255f3847a4SMat Martineau 
53265f3847a4SMat Martineau 		l2cap_move_done(chan);
53275f3847a4SMat Martineau 	}
53285f3847a4SMat Martineau 
53295f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53305f3847a4SMat Martineau 
53315f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
53328d5a04a1SMat Martineau 
53338d5a04a1SMat Martineau 	return 0;
53348d5a04a1SMat Martineau }
53358d5a04a1SMat Martineau 
53368d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5337ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5338ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
53398d5a04a1SMat Martineau {
53408d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
53413fd71a0aSMat Martineau 	struct l2cap_chan *chan;
53428d5a04a1SMat Martineau 	u16 icid;
53438d5a04a1SMat Martineau 
53448d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
53458d5a04a1SMat Martineau 		return -EPROTO;
53468d5a04a1SMat Martineau 
53478d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
53488d5a04a1SMat Martineau 
5349ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
53508d5a04a1SMat Martineau 
53513fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53523fd71a0aSMat Martineau 	if (!chan)
53533fd71a0aSMat Martineau 		return 0;
53543fd71a0aSMat Martineau 
53553fd71a0aSMat Martineau 	__clear_chan_timer(chan);
53563fd71a0aSMat Martineau 
53573fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
53583fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
53593fd71a0aSMat Martineau 
53606ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
53613fd71a0aSMat Martineau 			__release_logical_link(chan);
53623fd71a0aSMat Martineau 
53633fd71a0aSMat Martineau 		l2cap_move_done(chan);
53643fd71a0aSMat Martineau 	}
53653fd71a0aSMat Martineau 
53663fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
53673fd71a0aSMat Martineau 
53688d5a04a1SMat Martineau 	return 0;
53698d5a04a1SMat Martineau }
53708d5a04a1SMat Martineau 
5371e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
5372de73115aSClaudio Takahasi 					 u16 to_multiplier)
5373de73115aSClaudio Takahasi {
5374de73115aSClaudio Takahasi 	u16 max_latency;
5375de73115aSClaudio Takahasi 
5376de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
5377de73115aSClaudio Takahasi 		return -EINVAL;
5378de73115aSClaudio Takahasi 
5379de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
5380de73115aSClaudio Takahasi 		return -EINVAL;
5381de73115aSClaudio Takahasi 
5382de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
5383de73115aSClaudio Takahasi 		return -EINVAL;
5384de73115aSClaudio Takahasi 
5385de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
5386de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
5387de73115aSClaudio Takahasi 		return -EINVAL;
5388de73115aSClaudio Takahasi 
5389de73115aSClaudio Takahasi 	return 0;
5390de73115aSClaudio Takahasi }
5391de73115aSClaudio Takahasi 
5392de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
53932d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5394203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5395de73115aSClaudio Takahasi {
5396de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5397de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5398de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5399203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
54002ce603ebSClaudio Takahasi 	int err;
5401de73115aSClaudio Takahasi 
5402de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
5403de73115aSClaudio Takahasi 		return -EINVAL;
5404de73115aSClaudio Takahasi 
5405de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5406de73115aSClaudio Takahasi 		return -EPROTO;
5407de73115aSClaudio Takahasi 
5408de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5409de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5410de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5411de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5412de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5413de73115aSClaudio Takahasi 
5414de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5415de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5416de73115aSClaudio Takahasi 
5417de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
54182ce603ebSClaudio Takahasi 
54192ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
54202ce603ebSClaudio Takahasi 	if (err)
5421ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5422de73115aSClaudio Takahasi 	else
5423ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5424de73115aSClaudio Takahasi 
5425de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5426de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5427de73115aSClaudio Takahasi 
54282ce603ebSClaudio Takahasi 	if (!err)
54292ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
54302ce603ebSClaudio Takahasi 
5431de73115aSClaudio Takahasi 	return 0;
5432de73115aSClaudio Takahasi }
5433de73115aSClaudio Takahasi 
5434f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5435f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5436f1496deeSJohan Hedberg 				u8 *data)
5437f1496deeSJohan Hedberg {
5438f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
5439f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5440f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
5441f1496deeSJohan Hedberg 	int err;
5442f1496deeSJohan Hedberg 
5443f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5444f1496deeSJohan Hedberg 		return -EPROTO;
5445f1496deeSJohan Hedberg 
5446f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5447f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5448f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5449f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5450f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5451f1496deeSJohan Hedberg 
5452f1496deeSJohan Hedberg 	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
5453f1496deeSJohan Hedberg 		return -EPROTO;
5454f1496deeSJohan Hedberg 
5455f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5456f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5457f1496deeSJohan Hedberg 
5458f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5459f1496deeSJohan Hedberg 
5460f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5461f1496deeSJohan Hedberg 	if (!chan) {
5462f1496deeSJohan Hedberg 		err = -EBADSLT;
5463f1496deeSJohan Hedberg 		goto unlock;
5464f1496deeSJohan Hedberg 	}
5465f1496deeSJohan Hedberg 
5466f1496deeSJohan Hedberg 	err = 0;
5467f1496deeSJohan Hedberg 
5468f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5469f1496deeSJohan Hedberg 
5470f1496deeSJohan Hedberg 	switch (result) {
5471f1496deeSJohan Hedberg 	case L2CAP_CR_SUCCESS:
5472f1496deeSJohan Hedberg 		chan->ident = 0;
5473f1496deeSJohan Hedberg 		chan->dcid = dcid;
5474f1496deeSJohan Hedberg 		chan->omtu = mtu;
5475f1496deeSJohan Hedberg 		chan->remote_mps = mps;
54760cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5477f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5478f1496deeSJohan Hedberg 		break;
5479f1496deeSJohan Hedberg 
5480f1496deeSJohan Hedberg 	default:
5481f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5482f1496deeSJohan Hedberg 		break;
5483f1496deeSJohan Hedberg 	}
5484f1496deeSJohan Hedberg 
5485f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5486f1496deeSJohan Hedberg 
5487f1496deeSJohan Hedberg unlock:
5488f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5489f1496deeSJohan Hedberg 
5490f1496deeSJohan Hedberg 	return err;
5491f1496deeSJohan Hedberg }
5492f1496deeSJohan Hedberg 
54933300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
54942d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
54952d792818SGustavo Padovan 				      u8 *data)
54963300d9a9SClaudio Takahasi {
54973300d9a9SClaudio Takahasi 	int err = 0;
54983300d9a9SClaudio Takahasi 
54993300d9a9SClaudio Takahasi 	switch (cmd->code) {
55003300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5501cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
55023300d9a9SClaudio Takahasi 		break;
55033300d9a9SClaudio Takahasi 
55043300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5505cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
55063300d9a9SClaudio Takahasi 		break;
55073300d9a9SClaudio Takahasi 
55083300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5509f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
55109245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
55113300d9a9SClaudio Takahasi 		break;
55123300d9a9SClaudio Takahasi 
55133300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
55143300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
55153300d9a9SClaudio Takahasi 		break;
55163300d9a9SClaudio Takahasi 
55173300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
55189245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
55193300d9a9SClaudio Takahasi 		break;
55203300d9a9SClaudio Takahasi 
55213300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5522cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
55233300d9a9SClaudio Takahasi 		break;
55243300d9a9SClaudio Takahasi 
55253300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
55269245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
55273300d9a9SClaudio Takahasi 		break;
55283300d9a9SClaudio Takahasi 
55293300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
55303300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
55313300d9a9SClaudio Takahasi 		break;
55323300d9a9SClaudio Takahasi 
55333300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
55343300d9a9SClaudio Takahasi 		break;
55353300d9a9SClaudio Takahasi 
55363300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5537cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
55383300d9a9SClaudio Takahasi 		break;
55393300d9a9SClaudio Takahasi 
55403300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
55419245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
55423300d9a9SClaudio Takahasi 		break;
55433300d9a9SClaudio Takahasi 
5544f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5545f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5546f94ff6ffSMat Martineau 		break;
5547f94ff6ffSMat Martineau 
55488d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
55498d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
55508d5a04a1SMat Martineau 		break;
55518d5a04a1SMat Martineau 
55528d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
55539245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
55548d5a04a1SMat Martineau 		break;
55558d5a04a1SMat Martineau 
55568d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
55578d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
55588d5a04a1SMat Martineau 		break;
55598d5a04a1SMat Martineau 
55608d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
55619245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
55628d5a04a1SMat Martineau 		break;
55638d5a04a1SMat Martineau 
55643300d9a9SClaudio Takahasi 	default:
55653300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
55663300d9a9SClaudio Takahasi 		err = -EINVAL;
55673300d9a9SClaudio Takahasi 		break;
55683300d9a9SClaudio Takahasi 	}
55693300d9a9SClaudio Takahasi 
55703300d9a9SClaudio Takahasi 	return err;
55713300d9a9SClaudio Takahasi }
55723300d9a9SClaudio Takahasi 
557327e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
557427e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
557527e2d4c8SJohan Hedberg 				u8 *data)
557627e2d4c8SJohan Hedberg {
557727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
557827e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
557927e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
55800cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
558127e2d4c8SJohan Hedberg 	__le16 psm;
558227e2d4c8SJohan Hedberg 	u8 result;
558327e2d4c8SJohan Hedberg 
558427e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
558527e2d4c8SJohan Hedberg 		return -EPROTO;
558627e2d4c8SJohan Hedberg 
558727e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
558827e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
558927e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
559027e2d4c8SJohan Hedberg 	psm  = req->psm;
559127e2d4c8SJohan Hedberg 	dcid = 0;
55920cd75f7eSJohan Hedberg 	credits = 0;
559327e2d4c8SJohan Hedberg 
559427e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
559527e2d4c8SJohan Hedberg 		return -EPROTO;
559627e2d4c8SJohan Hedberg 
559727e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
559827e2d4c8SJohan Hedberg 	       scid, mtu, mps);
559927e2d4c8SJohan Hedberg 
560027e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
560127e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
560227e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
560327e2d4c8SJohan Hedberg 	if (!pchan) {
560427e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
560527e2d4c8SJohan Hedberg 		chan = NULL;
560627e2d4c8SJohan Hedberg 		goto response;
560727e2d4c8SJohan Hedberg 	}
560827e2d4c8SJohan Hedberg 
560927e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
561027e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
561127e2d4c8SJohan Hedberg 
561227e2d4c8SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
561327e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHENTICATION;
561427e2d4c8SJohan Hedberg 		chan = NULL;
561527e2d4c8SJohan Hedberg 		goto response_unlock;
561627e2d4c8SJohan Hedberg 	}
561727e2d4c8SJohan Hedberg 
561827e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
561927e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
562027e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
562127e2d4c8SJohan Hedberg 		chan = NULL;
562227e2d4c8SJohan Hedberg 		goto response_unlock;
562327e2d4c8SJohan Hedberg 	}
562427e2d4c8SJohan Hedberg 
562527e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
562627e2d4c8SJohan Hedberg 	if (!chan) {
562727e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
562827e2d4c8SJohan Hedberg 		goto response_unlock;
562927e2d4c8SJohan Hedberg 	}
563027e2d4c8SJohan Hedberg 
563127e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
563227e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
563327e2d4c8SJohan Hedberg 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
563427e2d4c8SJohan Hedberg 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
563527e2d4c8SJohan Hedberg 	chan->psm  = psm;
563627e2d4c8SJohan Hedberg 	chan->dcid = scid;
563727e2d4c8SJohan Hedberg 	chan->omtu = mtu;
563827e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
56390cd75f7eSJohan Hedberg 	chan->tx_credits = __le16_to_cpu(req->credits);
564027e2d4c8SJohan Hedberg 
564127e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
564227e2d4c8SJohan Hedberg 	dcid = chan->scid;
56430cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
564427e2d4c8SJohan Hedberg 
564527e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
564627e2d4c8SJohan Hedberg 
564727e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
564827e2d4c8SJohan Hedberg 
564927e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
565027e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
565127e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
565227e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
565327e2d4c8SJohan Hedberg 	} else {
565427e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
565527e2d4c8SJohan Hedberg 		result = L2CAP_CR_SUCCESS;
565627e2d4c8SJohan Hedberg 	}
565727e2d4c8SJohan Hedberg 
565827e2d4c8SJohan Hedberg response_unlock:
565927e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
566027e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
566127e2d4c8SJohan Hedberg 
566227e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
566327e2d4c8SJohan Hedberg 		return 0;
566427e2d4c8SJohan Hedberg 
566527e2d4c8SJohan Hedberg response:
566627e2d4c8SJohan Hedberg 	if (chan) {
566727e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
566827e2d4c8SJohan Hedberg 		rsp.mps = __constant_cpu_to_le16(L2CAP_LE_DEFAULT_MPS);
566927e2d4c8SJohan Hedberg 	} else {
567027e2d4c8SJohan Hedberg 		rsp.mtu = 0;
567127e2d4c8SJohan Hedberg 		rsp.mps = 0;
567227e2d4c8SJohan Hedberg 	}
567327e2d4c8SJohan Hedberg 
567427e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
56750cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
567627e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
567727e2d4c8SJohan Hedberg 
567827e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
567927e2d4c8SJohan Hedberg 
568027e2d4c8SJohan Hedberg 	return 0;
568127e2d4c8SJohan Hedberg }
568227e2d4c8SJohan Hedberg 
5683fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5684fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5685fad5fc89SJohan Hedberg 				   u8 *data)
5686fad5fc89SJohan Hedberg {
5687fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5688fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
5689fad5fc89SJohan Hedberg 	u16 cid, credits;
5690fad5fc89SJohan Hedberg 
5691fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5692fad5fc89SJohan Hedberg 		return -EPROTO;
5693fad5fc89SJohan Hedberg 
5694fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5695fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5696fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5697fad5fc89SJohan Hedberg 
5698fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5699fad5fc89SJohan Hedberg 
5700fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5701fad5fc89SJohan Hedberg 	if (!chan)
5702fad5fc89SJohan Hedberg 		return -EBADSLT;
5703fad5fc89SJohan Hedberg 
5704fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5705fad5fc89SJohan Hedberg 
5706fad5fc89SJohan Hedberg 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
5707fad5fc89SJohan Hedberg 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
5708fad5fc89SJohan Hedberg 		chan->tx_credits--;
5709fad5fc89SJohan Hedberg 	}
5710fad5fc89SJohan Hedberg 
5711fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5712fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5713fad5fc89SJohan Hedberg 
5714fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5715fad5fc89SJohan Hedberg 
5716fad5fc89SJohan Hedberg 	return 0;
5717fad5fc89SJohan Hedberg }
5718fad5fc89SJohan Hedberg 
57193300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5720203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5721203e639eSJohan Hedberg 				   u8 *data)
57223300d9a9SClaudio Takahasi {
5723b5ecba64SJohan Hedberg 	int err = 0;
5724b5ecba64SJohan Hedberg 
57253af8ace6SJohan Hedberg 	if (!enable_lecoc) {
57263af8ace6SJohan Hedberg 		switch (cmd->code) {
57273af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_REQ:
57283af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_RSP:
57293af8ace6SJohan Hedberg 		case L2CAP_LE_CREDITS:
57303af8ace6SJohan Hedberg 		case L2CAP_DISCONN_REQ:
57313af8ace6SJohan Hedberg 		case L2CAP_DISCONN_RSP:
57323af8ace6SJohan Hedberg 			return -EINVAL;
57333af8ace6SJohan Hedberg 		}
57343af8ace6SJohan Hedberg 	}
57353af8ace6SJohan Hedberg 
57363300d9a9SClaudio Takahasi 	switch (cmd->code) {
57373300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5738b5ecba64SJohan Hedberg 		break;
57393300d9a9SClaudio Takahasi 
57403300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5741b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5742b5ecba64SJohan Hedberg 		break;
57433300d9a9SClaudio Takahasi 
57443300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5745b5ecba64SJohan Hedberg 		break;
57463300d9a9SClaudio Takahasi 
5747f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5748f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5749b5ecba64SJohan Hedberg 		break;
5750f1496deeSJohan Hedberg 
575127e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5752b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5753b5ecba64SJohan Hedberg 		break;
575427e2d4c8SJohan Hedberg 
5755fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5756fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5757fad5fc89SJohan Hedberg 		break;
5758fad5fc89SJohan Hedberg 
57593defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5760b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5761b5ecba64SJohan Hedberg 		break;
57623defe01aSJohan Hedberg 
57633defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
57643defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5765b5ecba64SJohan Hedberg 		break;
57663defe01aSJohan Hedberg 
57673300d9a9SClaudio Takahasi 	default:
57683300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5769b5ecba64SJohan Hedberg 		err = -EINVAL;
5770b5ecba64SJohan Hedberg 		break;
57713300d9a9SClaudio Takahasi 	}
5772b5ecba64SJohan Hedberg 
5773b5ecba64SJohan Hedberg 	return err;
57743300d9a9SClaudio Takahasi }
57753300d9a9SClaudio Takahasi 
5776c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5777c5623556SJohan Hedberg 					struct sk_buff *skb)
5778c5623556SJohan Hedberg {
577969c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
57804f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
57814f3e219dSMarcel Holtmann 	u16 len;
5782c5623556SJohan Hedberg 	int err;
5783c5623556SJohan Hedberg 
578469c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
57853b166295SMarcel Holtmann 		goto drop;
578669c4e4e8SJohan Hedberg 
57874f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
57884f3e219dSMarcel Holtmann 		goto drop;
5789c5623556SJohan Hedberg 
57904f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
57914f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5792c5623556SJohan Hedberg 
57934f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5794c5623556SJohan Hedberg 
57954f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
57964f3e219dSMarcel Holtmann 
57974f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5798c5623556SJohan Hedberg 		BT_DBG("corrupted command");
57994f3e219dSMarcel Holtmann 		goto drop;
5800c5623556SJohan Hedberg 	}
5801c5623556SJohan Hedberg 
5802203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5803c5623556SJohan Hedberg 	if (err) {
5804c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5805c5623556SJohan Hedberg 
5806c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5807c5623556SJohan Hedberg 
5808a521149aSJohan Hedberg 		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58094f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5810c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5811c5623556SJohan Hedberg 	}
5812c5623556SJohan Hedberg 
58133b166295SMarcel Holtmann drop:
5814c5623556SJohan Hedberg 	kfree_skb(skb);
5815c5623556SJohan Hedberg }
5816c5623556SJohan Hedberg 
58173300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
58183300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
58190a708f8fSGustavo F. Padovan {
582069c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
58210a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
58220a708f8fSGustavo F. Padovan 	int len = skb->len;
58230a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
58243300d9a9SClaudio Takahasi 	int err;
58250a708f8fSGustavo F. Padovan 
58260a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
58270a708f8fSGustavo F. Padovan 
582869c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
58293b166295SMarcel Holtmann 		goto drop;
583069c4e4e8SJohan Hedberg 
58310a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
58320a708f8fSGustavo F. Padovan 		u16 cmd_len;
58330a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
58340a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
58350a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
58360a708f8fSGustavo F. Padovan 
58370a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
58380a708f8fSGustavo F. Padovan 
58392d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
58402d792818SGustavo Padovan 		       cmd.ident);
58410a708f8fSGustavo F. Padovan 
58420a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
58430a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
58440a708f8fSGustavo F. Padovan 			break;
58450a708f8fSGustavo F. Padovan 		}
58460a708f8fSGustavo F. Padovan 
58473300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
58480a708f8fSGustavo F. Padovan 		if (err) {
5849e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
58502c6d1a2eSGustavo F. Padovan 
58512c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
58520a708f8fSGustavo F. Padovan 
5853a521149aSJohan Hedberg 			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58542d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
58552d792818SGustavo Padovan 				       sizeof(rej), &rej);
58560a708f8fSGustavo F. Padovan 		}
58570a708f8fSGustavo F. Padovan 
58580a708f8fSGustavo F. Padovan 		data += cmd_len;
58590a708f8fSGustavo F. Padovan 		len  -= cmd_len;
58600a708f8fSGustavo F. Padovan 	}
58610a708f8fSGustavo F. Padovan 
58623b166295SMarcel Holtmann drop:
58630a708f8fSGustavo F. Padovan 	kfree_skb(skb);
58640a708f8fSGustavo F. Padovan }
58650a708f8fSGustavo F. Padovan 
586647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
58670a708f8fSGustavo F. Padovan {
58680a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5869e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5870e4ca6d98SAndrei Emeltchenko 
5871e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5872e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5873e4ca6d98SAndrei Emeltchenko 	else
5874e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
58750a708f8fSGustavo F. Padovan 
587647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
587703a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
58780a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
58790a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
58800a708f8fSGustavo F. Padovan 
58810a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
58820a708f8fSGustavo F. Padovan 			return -EBADMSG;
58830a708f8fSGustavo F. Padovan 	}
58840a708f8fSGustavo F. Padovan 	return 0;
58850a708f8fSGustavo F. Padovan }
58860a708f8fSGustavo F. Padovan 
58876ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
58880a708f8fSGustavo F. Padovan {
5889e31f7633SMat Martineau 	struct l2cap_ctrl control;
58900a708f8fSGustavo F. Padovan 
5891e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
58920a708f8fSGustavo F. Padovan 
5893e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5894e31f7633SMat Martineau 	control.sframe = 1;
5895e31f7633SMat Martineau 	control.final = 1;
5896e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5897e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
58980a708f8fSGustavo F. Padovan 
5899e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5900e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5901e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59020a708f8fSGustavo F. Padovan 	}
59030a708f8fSGustavo F. Padovan 
5904e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5905e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5906e31f7633SMat Martineau 		__set_retrans_timer(chan);
59070a708f8fSGustavo F. Padovan 
5908e31f7633SMat Martineau 	/* Send pending iframes */
5909525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
59100a708f8fSGustavo F. Padovan 
5911e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5912e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5913e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5914e31f7633SMat Martineau 		 * send it now.
5915e31f7633SMat Martineau 		 */
5916e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5917e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59180a708f8fSGustavo F. Padovan 	}
59190a708f8fSGustavo F. Padovan }
59200a708f8fSGustavo F. Padovan 
59212d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
59222d792818SGustavo Padovan 			    struct sk_buff **last_frag)
59230a708f8fSGustavo F. Padovan {
592484084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
592584084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
592684084a31SMat Martineau 	 */
592784084a31SMat Martineau 	if (!skb_has_frag_list(skb))
592884084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
592984084a31SMat Martineau 
593084084a31SMat Martineau 	new_frag->next = NULL;
593184084a31SMat Martineau 
593284084a31SMat Martineau 	(*last_frag)->next = new_frag;
593384084a31SMat Martineau 	*last_frag = new_frag;
593484084a31SMat Martineau 
593584084a31SMat Martineau 	skb->len += new_frag->len;
593684084a31SMat Martineau 	skb->data_len += new_frag->len;
593784084a31SMat Martineau 	skb->truesize += new_frag->truesize;
593884084a31SMat Martineau }
593984084a31SMat Martineau 
59404b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
59414b51dae9SMat Martineau 				struct l2cap_ctrl *control)
594284084a31SMat Martineau {
594384084a31SMat Martineau 	int err = -EINVAL;
59440a708f8fSGustavo F. Padovan 
59454b51dae9SMat Martineau 	switch (control->sar) {
59467e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
594784084a31SMat Martineau 		if (chan->sdu)
594884084a31SMat Martineau 			break;
59490a708f8fSGustavo F. Padovan 
595080b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
595184084a31SMat Martineau 		break;
59520a708f8fSGustavo F. Padovan 
59537e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
595484084a31SMat Martineau 		if (chan->sdu)
595584084a31SMat Martineau 			break;
59560a708f8fSGustavo F. Padovan 
59576f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
595803a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
59590a708f8fSGustavo F. Padovan 
596084084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
596184084a31SMat Martineau 			err = -EMSGSIZE;
596284084a31SMat Martineau 			break;
596384084a31SMat Martineau 		}
59640a708f8fSGustavo F. Padovan 
596584084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
596684084a31SMat Martineau 			break;
596784084a31SMat Martineau 
596884084a31SMat Martineau 		chan->sdu = skb;
596984084a31SMat Martineau 		chan->sdu_last_frag = skb;
597084084a31SMat Martineau 
597184084a31SMat Martineau 		skb = NULL;
597284084a31SMat Martineau 		err = 0;
59730a708f8fSGustavo F. Padovan 		break;
59740a708f8fSGustavo F. Padovan 
59757e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
59766f61fd47SGustavo F. Padovan 		if (!chan->sdu)
597784084a31SMat Martineau 			break;
59780a708f8fSGustavo F. Padovan 
597984084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
598084084a31SMat Martineau 				&chan->sdu_last_frag);
598184084a31SMat Martineau 		skb = NULL;
59820a708f8fSGustavo F. Padovan 
598384084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
598484084a31SMat Martineau 			break;
59850a708f8fSGustavo F. Padovan 
598684084a31SMat Martineau 		err = 0;
59870a708f8fSGustavo F. Padovan 		break;
59880a708f8fSGustavo F. Padovan 
59897e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
59906f61fd47SGustavo F. Padovan 		if (!chan->sdu)
599184084a31SMat Martineau 			break;
59920a708f8fSGustavo F. Padovan 
599384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
599484084a31SMat Martineau 				&chan->sdu_last_frag);
599584084a31SMat Martineau 		skb = NULL;
59960a708f8fSGustavo F. Padovan 
599784084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
599884084a31SMat Martineau 			break;
59990a708f8fSGustavo F. Padovan 
600080b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
60010a708f8fSGustavo F. Padovan 
600284084a31SMat Martineau 		if (!err) {
600384084a31SMat Martineau 			/* Reassembly complete */
600484084a31SMat Martineau 			chan->sdu = NULL;
600584084a31SMat Martineau 			chan->sdu_last_frag = NULL;
600684084a31SMat Martineau 			chan->sdu_len = 0;
60070a708f8fSGustavo F. Padovan 		}
60080a708f8fSGustavo F. Padovan 		break;
60090a708f8fSGustavo F. Padovan 	}
60100a708f8fSGustavo F. Padovan 
601184084a31SMat Martineau 	if (err) {
60120a708f8fSGustavo F. Padovan 		kfree_skb(skb);
60136f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
60146f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
601584084a31SMat Martineau 		chan->sdu_last_frag = NULL;
601684084a31SMat Martineau 		chan->sdu_len = 0;
601784084a31SMat Martineau 	}
60180a708f8fSGustavo F. Padovan 
601984084a31SMat Martineau 	return err;
60200a708f8fSGustavo F. Padovan }
60210a708f8fSGustavo F. Padovan 
602232b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
602332b32735SMat Martineau {
602432b32735SMat Martineau 	/* Placeholder */
602532b32735SMat Martineau 	return 0;
602632b32735SMat Martineau }
602732b32735SMat Martineau 
6028e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
60290a708f8fSGustavo F. Padovan {
603061aa4f5bSMat Martineau 	u8 event;
603161aa4f5bSMat Martineau 
603261aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
603361aa4f5bSMat Martineau 		return;
603461aa4f5bSMat Martineau 
603561aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6036401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
60370a708f8fSGustavo F. Padovan }
60380a708f8fSGustavo F. Padovan 
6039d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6040d2a7ac5dSMat Martineau {
604163838725SMat Martineau 	int err = 0;
604263838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
604363838725SMat Martineau 	 * until a gap is encountered.
604463838725SMat Martineau 	 */
604563838725SMat Martineau 
604663838725SMat Martineau 	BT_DBG("chan %p", chan);
604763838725SMat Martineau 
604863838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
604963838725SMat Martineau 		struct sk_buff *skb;
605063838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
605163838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
605263838725SMat Martineau 
605363838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
605463838725SMat Martineau 
605563838725SMat Martineau 		if (!skb)
605663838725SMat Martineau 			break;
605763838725SMat Martineau 
605863838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
605963838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
606063838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
606163838725SMat Martineau 		if (err)
606263838725SMat Martineau 			break;
606363838725SMat Martineau 	}
606463838725SMat Martineau 
606563838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
606663838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
606763838725SMat Martineau 		l2cap_send_ack(chan);
606863838725SMat Martineau 	}
606963838725SMat Martineau 
607063838725SMat Martineau 	return err;
6071d2a7ac5dSMat Martineau }
6072d2a7ac5dSMat Martineau 
6073d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6074d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6075d2a7ac5dSMat Martineau {
6076f80842a8SMat Martineau 	struct sk_buff *skb;
6077f80842a8SMat Martineau 
6078f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6079f80842a8SMat Martineau 
6080f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6081f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
60825e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6083f80842a8SMat Martineau 		return;
6084f80842a8SMat Martineau 	}
6085f80842a8SMat Martineau 
6086f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6087f80842a8SMat Martineau 
6088f80842a8SMat Martineau 	if (skb == NULL) {
6089f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6090f80842a8SMat Martineau 		       control->reqseq);
6091f80842a8SMat Martineau 		return;
6092f80842a8SMat Martineau 	}
6093f80842a8SMat Martineau 
6094f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
6095f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
60965e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6097f80842a8SMat Martineau 		return;
6098f80842a8SMat Martineau 	}
6099f80842a8SMat Martineau 
6100f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6101f80842a8SMat Martineau 
6102f80842a8SMat Martineau 	if (control->poll) {
6103f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6104f80842a8SMat Martineau 
6105f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6106f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6107f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6108f80842a8SMat Martineau 
6109f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6110f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6111f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6112f80842a8SMat Martineau 		}
6113f80842a8SMat Martineau 	} else {
6114f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6115f80842a8SMat Martineau 
6116f80842a8SMat Martineau 		if (control->final) {
6117f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6118f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6119f80842a8SMat Martineau 						&chan->conn_state))
6120f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6121f80842a8SMat Martineau 		} else {
6122f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6123f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6124f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6125f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6126f80842a8SMat Martineau 			}
6127f80842a8SMat Martineau 		}
6128f80842a8SMat Martineau 	}
6129d2a7ac5dSMat Martineau }
6130d2a7ac5dSMat Martineau 
6131d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6132d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6133d2a7ac5dSMat Martineau {
6134fcd289dfSMat Martineau 	struct sk_buff *skb;
6135fcd289dfSMat Martineau 
6136fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6137fcd289dfSMat Martineau 
6138fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6139fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61405e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6141fcd289dfSMat Martineau 		return;
6142fcd289dfSMat Martineau 	}
6143fcd289dfSMat Martineau 
6144fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6145fcd289dfSMat Martineau 
6146fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6147fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
6148fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61495e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6150fcd289dfSMat Martineau 		return;
6151fcd289dfSMat Martineau 	}
6152fcd289dfSMat Martineau 
6153fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6154fcd289dfSMat Martineau 
6155fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6156fcd289dfSMat Martineau 
6157fcd289dfSMat Martineau 	if (control->final) {
6158fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6159fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6160fcd289dfSMat Martineau 	} else {
6161fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6162fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6163fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6164fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6165fcd289dfSMat Martineau 	}
6166d2a7ac5dSMat Martineau }
6167d2a7ac5dSMat Martineau 
61684b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
61694b51dae9SMat Martineau {
61704b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
61714b51dae9SMat Martineau 
61724b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
61734b51dae9SMat Martineau 	       chan->expected_tx_seq);
61744b51dae9SMat Martineau 
61754b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
61764b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61774b51dae9SMat Martineau 		    chan->tx_win) {
61784b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
61794b51dae9SMat Martineau 			 * invalid packets.
61804b51dae9SMat Martineau 			 */
61814b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
61824b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
61834b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
61844b51dae9SMat Martineau 			} else {
61854b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
61864b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
61874b51dae9SMat Martineau 			}
61884b51dae9SMat Martineau 		}
61894b51dae9SMat Martineau 
61904b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
61914b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
61924b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
61934b51dae9SMat Martineau 		}
61944b51dae9SMat Martineau 
61954b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
61964b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
61974b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
61984b51dae9SMat Martineau 		}
61994b51dae9SMat Martineau 
62004b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
62014b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
62024b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
62034b51dae9SMat Martineau 		}
62044b51dae9SMat Martineau 	}
62054b51dae9SMat Martineau 
62064b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
62074b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
62084b51dae9SMat Martineau 		    chan->tx_win) {
62094b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62104b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62114b51dae9SMat Martineau 		} else {
62124b51dae9SMat Martineau 			BT_DBG("Expected");
62134b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
62144b51dae9SMat Martineau 		}
62154b51dae9SMat Martineau 	}
62164b51dae9SMat Martineau 
62174b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
62182d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
62194b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
62204b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
62214b51dae9SMat Martineau 	}
62224b51dae9SMat Martineau 
62234b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
62244b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
62254b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
62264b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
62274b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
62284b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
62294b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
62304b51dae9SMat Martineau 		 * request.
62314b51dae9SMat Martineau 		 *
62324b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
62334b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
62344b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
62354b51dae9SMat Martineau 		 *
62364b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
62374b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
62384b51dae9SMat Martineau 		 * causes a disconnect.
62394b51dae9SMat Martineau 		 */
62404b51dae9SMat Martineau 
62414b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62424b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
62434b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
62444b51dae9SMat Martineau 		} else {
62454b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62464b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62474b51dae9SMat Martineau 		}
62484b51dae9SMat Martineau 	} else {
62494b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
62504b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
62514b51dae9SMat Martineau 	}
62524b51dae9SMat Martineau }
62534b51dae9SMat Martineau 
6254d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6255d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6256d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6257d2a7ac5dSMat Martineau {
6258d2a7ac5dSMat Martineau 	int err = 0;
6259941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6260d2a7ac5dSMat Martineau 
6261d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6262d2a7ac5dSMat Martineau 	       event);
6263d2a7ac5dSMat Martineau 
6264d2a7ac5dSMat Martineau 	switch (event) {
6265d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6266d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6267d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6268d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6269d2a7ac5dSMat Martineau 
6270d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6271d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6272d2a7ac5dSMat Martineau 				       control->txseq);
6273d2a7ac5dSMat Martineau 				break;
6274d2a7ac5dSMat Martineau 			}
6275d2a7ac5dSMat Martineau 
6276d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6277d2a7ac5dSMat Martineau 							   control->txseq);
6278d2a7ac5dSMat Martineau 
6279d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6280941247f9SPeter Senna Tschudin 			skb_in_use = true;
6281d2a7ac5dSMat Martineau 
6282d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6283d2a7ac5dSMat Martineau 			if (err)
6284d2a7ac5dSMat Martineau 				break;
6285d2a7ac5dSMat Martineau 
6286d2a7ac5dSMat Martineau 			if (control->final) {
6287d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6288d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6289d2a7ac5dSMat Martineau 					control->final = 0;
6290d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6291d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6292d2a7ac5dSMat Martineau 				}
6293d2a7ac5dSMat Martineau 			}
6294d2a7ac5dSMat Martineau 
6295d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6296d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6297d2a7ac5dSMat Martineau 			break;
6298d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6299d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6300d2a7ac5dSMat Martineau 
6301d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6302d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6303d2a7ac5dSMat Martineau 			 * when local busy is exited.
6304d2a7ac5dSMat Martineau 			 */
6305d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6306d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6307d2a7ac5dSMat Martineau 				       control->txseq);
6308d2a7ac5dSMat Martineau 				break;
6309d2a7ac5dSMat Martineau 			}
6310d2a7ac5dSMat Martineau 
6311d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6312d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6313d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6314d2a7ac5dSMat Martineau 			 */
6315d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6316941247f9SPeter Senna Tschudin 			skb_in_use = true;
6317d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6318d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6319d2a7ac5dSMat Martineau 
6320d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6321d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6322d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6323d2a7ac5dSMat Martineau 
6324d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6325d2a7ac5dSMat Martineau 			break;
6326d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6327d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6328d2a7ac5dSMat Martineau 			break;
6329d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6330d2a7ac5dSMat Martineau 			break;
6331d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6332d2a7ac5dSMat Martineau 		default:
63335e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6334d2a7ac5dSMat Martineau 			break;
6335d2a7ac5dSMat Martineau 		}
6336d2a7ac5dSMat Martineau 		break;
6337d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6338d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6339d2a7ac5dSMat Martineau 		if (control->final) {
6340d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6341d2a7ac5dSMat Martineau 
6342e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6343e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6344d2a7ac5dSMat Martineau 				control->final = 0;
6345d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6346d2a7ac5dSMat Martineau 			}
6347d2a7ac5dSMat Martineau 
6348d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6349d2a7ac5dSMat Martineau 		} else if (control->poll) {
6350d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6351d2a7ac5dSMat Martineau 		} else {
6352d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6353d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6354d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6355d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6356d2a7ac5dSMat Martineau 
6357d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6358d2a7ac5dSMat Martineau 		}
6359d2a7ac5dSMat Martineau 		break;
6360d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6361d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6362d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6363d2a7ac5dSMat Martineau 		if (control && control->poll) {
6364d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6365d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6366d2a7ac5dSMat Martineau 		}
6367d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6368d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6369d2a7ac5dSMat Martineau 		break;
6370d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6371d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6372d2a7ac5dSMat Martineau 		break;
6373d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6374d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6375d2a7ac5dSMat Martineau 		break;
6376d2a7ac5dSMat Martineau 	default:
6377d2a7ac5dSMat Martineau 		break;
6378d2a7ac5dSMat Martineau 	}
6379d2a7ac5dSMat Martineau 
6380d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6381d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6382d2a7ac5dSMat Martineau 		kfree_skb(skb);
6383d2a7ac5dSMat Martineau 	}
6384d2a7ac5dSMat Martineau 
6385d2a7ac5dSMat Martineau 	return err;
6386d2a7ac5dSMat Martineau }
6387d2a7ac5dSMat Martineau 
6388d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6389d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6390d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6391d2a7ac5dSMat Martineau {
6392d2a7ac5dSMat Martineau 	int err = 0;
6393d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6394941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6395d2a7ac5dSMat Martineau 
6396d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6397d2a7ac5dSMat Martineau 	       event);
6398d2a7ac5dSMat Martineau 
6399d2a7ac5dSMat Martineau 	switch (event) {
6400d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6401d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6402d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6403d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6404d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6405d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6406941247f9SPeter Senna Tschudin 			skb_in_use = true;
6407d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6408d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6409d2a7ac5dSMat Martineau 
6410d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6411d2a7ac5dSMat Martineau 			break;
6412d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6413d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6414d2a7ac5dSMat Martineau 
6415d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6416d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6417941247f9SPeter Senna Tschudin 			skb_in_use = true;
6418d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6419d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6420d2a7ac5dSMat Martineau 
6421d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6422d2a7ac5dSMat Martineau 			if (err)
6423d2a7ac5dSMat Martineau 				break;
6424d2a7ac5dSMat Martineau 
6425d2a7ac5dSMat Martineau 			break;
6426d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6427d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6428d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6429d2a7ac5dSMat Martineau 			 * the missing frames.
6430d2a7ac5dSMat Martineau 			 */
6431d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6432941247f9SPeter Senna Tschudin 			skb_in_use = true;
6433d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6434d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6435d2a7ac5dSMat Martineau 
6436d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6437d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6438d2a7ac5dSMat Martineau 			break;
6439d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6440d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6441d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6442d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6443d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6444d2a7ac5dSMat Martineau 			 */
6445d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6446941247f9SPeter Senna Tschudin 			skb_in_use = true;
6447d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6448d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6449d2a7ac5dSMat Martineau 
6450d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6451d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6452d2a7ac5dSMat Martineau 			break;
6453d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6454d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6455d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6456d2a7ac5dSMat Martineau 			break;
6457d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6458d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6459d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6460d2a7ac5dSMat Martineau 			 */
6461d2a7ac5dSMat Martineau 			break;
6462d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6463d2a7ac5dSMat Martineau 			break;
6464d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6465d2a7ac5dSMat Martineau 		default:
64665e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6467d2a7ac5dSMat Martineau 			break;
6468d2a7ac5dSMat Martineau 		}
6469d2a7ac5dSMat Martineau 		break;
6470d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6471d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6472d2a7ac5dSMat Martineau 		if (control->final) {
6473d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6474d2a7ac5dSMat Martineau 
6475d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6476d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6477d2a7ac5dSMat Martineau 				control->final = 0;
6478d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6479d2a7ac5dSMat Martineau 			}
6480d2a7ac5dSMat Martineau 
6481d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6482d2a7ac5dSMat Martineau 		} else if (control->poll) {
6483d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6484d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6485d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6486d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6487d2a7ac5dSMat Martineau 			}
6488d2a7ac5dSMat Martineau 
6489d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6490d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6491d2a7ac5dSMat Martineau 		} else {
6492d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6493d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6494d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6495d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6496d2a7ac5dSMat Martineau 
6497d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6498d2a7ac5dSMat Martineau 		}
6499d2a7ac5dSMat Martineau 		break;
6500d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6501d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6502d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6503d2a7ac5dSMat Martineau 		if (control->poll) {
6504d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6505d2a7ac5dSMat Martineau 		} else {
6506d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6507d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6508d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6509d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6510d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6511d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6512d2a7ac5dSMat Martineau 		}
6513d2a7ac5dSMat Martineau 
6514d2a7ac5dSMat Martineau 		break;
6515d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6516d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6517d2a7ac5dSMat Martineau 		break;
6518d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6519d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6520d2a7ac5dSMat Martineau 		break;
6521d2a7ac5dSMat Martineau 	}
6522d2a7ac5dSMat Martineau 
6523d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6524d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6525d2a7ac5dSMat Martineau 		kfree_skb(skb);
6526d2a7ac5dSMat Martineau 	}
6527d2a7ac5dSMat Martineau 
6528d2a7ac5dSMat Martineau 	return err;
6529d2a7ac5dSMat Martineau }
6530d2a7ac5dSMat Martineau 
653132b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
653232b32735SMat Martineau {
653332b32735SMat Martineau 	BT_DBG("chan %p", chan);
653432b32735SMat Martineau 
653532b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
653632b32735SMat Martineau 
653732b32735SMat Martineau 	if (chan->hs_hcon)
653832b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
653932b32735SMat Martineau 	else
654032b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
654132b32735SMat Martineau 
654232b32735SMat Martineau 	return l2cap_resegment(chan);
654332b32735SMat Martineau }
654432b32735SMat Martineau 
654532b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
654632b32735SMat Martineau 				 struct l2cap_ctrl *control,
654732b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
654832b32735SMat Martineau {
654932b32735SMat Martineau 	int err;
655032b32735SMat Martineau 
655132b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
655232b32735SMat Martineau 	       event);
655332b32735SMat Martineau 
655432b32735SMat Martineau 	if (!control->poll)
655532b32735SMat Martineau 		return -EPROTO;
655632b32735SMat Martineau 
655732b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
655832b32735SMat Martineau 
655932b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
656032b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
656132b32735SMat Martineau 	else
656232b32735SMat Martineau 		chan->tx_send_head = NULL;
656332b32735SMat Martineau 
656432b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
656532b32735SMat Martineau 	 * by the receiver.
656632b32735SMat Martineau 	 */
656732b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
656832b32735SMat Martineau 	chan->unacked_frames = 0;
656932b32735SMat Martineau 
657032b32735SMat Martineau 	err = l2cap_finish_move(chan);
657132b32735SMat Martineau 	if (err)
657232b32735SMat Martineau 		return err;
657332b32735SMat Martineau 
657432b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
657532b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
657632b32735SMat Martineau 
657732b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
657832b32735SMat Martineau 		return -EPROTO;
657932b32735SMat Martineau 
658032b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
658132b32735SMat Martineau }
658232b32735SMat Martineau 
658332b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
658432b32735SMat Martineau 				 struct l2cap_ctrl *control,
658532b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
658632b32735SMat Martineau {
658732b32735SMat Martineau 	int err;
658832b32735SMat Martineau 
658932b32735SMat Martineau 	if (!control->final)
659032b32735SMat Martineau 		return -EPROTO;
659132b32735SMat Martineau 
659232b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
659332b32735SMat Martineau 
659432b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
659532b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
659632b32735SMat Martineau 
659732b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
659832b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
659932b32735SMat Martineau 	else
660032b32735SMat Martineau 		chan->tx_send_head = NULL;
660132b32735SMat Martineau 
660232b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
660332b32735SMat Martineau 	 * by the receiver.
660432b32735SMat Martineau 	 */
660532b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
660632b32735SMat Martineau 	chan->unacked_frames = 0;
660732b32735SMat Martineau 
660832b32735SMat Martineau 	if (chan->hs_hcon)
660932b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
661032b32735SMat Martineau 	else
661132b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
661232b32735SMat Martineau 
661332b32735SMat Martineau 	err = l2cap_resegment(chan);
661432b32735SMat Martineau 
661532b32735SMat Martineau 	if (!err)
661632b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
661732b32735SMat Martineau 
661832b32735SMat Martineau 	return err;
661932b32735SMat Martineau }
662032b32735SMat Martineau 
6621d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6622d2a7ac5dSMat Martineau {
6623d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6624d2a7ac5dSMat Martineau 	u16 unacked;
6625d2a7ac5dSMat Martineau 
6626d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6627d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6628d2a7ac5dSMat Martineau }
6629d2a7ac5dSMat Martineau 
6630cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6631cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
66320a708f8fSGustavo F. Padovan {
6633d2a7ac5dSMat Martineau 	int err = 0;
6634d2a7ac5dSMat Martineau 
6635d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6636d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6637d2a7ac5dSMat Martineau 
6638d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6639d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6640d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6641d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6642d2a7ac5dSMat Martineau 			break;
6643d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6644d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6645d2a7ac5dSMat Martineau 						       event);
6646d2a7ac5dSMat Martineau 			break;
664732b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
664832b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
664932b32735SMat Martineau 			break;
665032b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
665132b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
665232b32735SMat Martineau 			break;
6653d2a7ac5dSMat Martineau 		default:
6654d2a7ac5dSMat Martineau 			/* shut it down */
6655d2a7ac5dSMat Martineau 			break;
6656d2a7ac5dSMat Martineau 		}
6657d2a7ac5dSMat Martineau 	} else {
6658d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6659d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6660d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
66615e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6662d2a7ac5dSMat Martineau 	}
6663d2a7ac5dSMat Martineau 
6664d2a7ac5dSMat Martineau 	return err;
6665cec8ab6eSMat Martineau }
6666cec8ab6eSMat Martineau 
6667cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6668cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6669cec8ab6eSMat Martineau {
66704b51dae9SMat Martineau 	int err = 0;
66714b51dae9SMat Martineau 
66724b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
66734b51dae9SMat Martineau 	       chan->rx_state);
66744b51dae9SMat Martineau 
66754b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
66764b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
66774b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
66784b51dae9SMat Martineau 
66794b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
66804b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
66814b51dae9SMat Martineau 
66824b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
66834b51dae9SMat Martineau 
66844b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
66854b51dae9SMat Martineau 	} else {
66864b51dae9SMat Martineau 		if (chan->sdu) {
66874b51dae9SMat Martineau 			kfree_skb(chan->sdu);
66884b51dae9SMat Martineau 			chan->sdu = NULL;
66894b51dae9SMat Martineau 		}
66904b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
66914b51dae9SMat Martineau 		chan->sdu_len = 0;
66924b51dae9SMat Martineau 
66934b51dae9SMat Martineau 		if (skb) {
66944b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
66954b51dae9SMat Martineau 			kfree_skb(skb);
66964b51dae9SMat Martineau 		}
66974b51dae9SMat Martineau 	}
66984b51dae9SMat Martineau 
66994b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
67004b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
67014b51dae9SMat Martineau 
67024b51dae9SMat Martineau 	return err;
6703cec8ab6eSMat Martineau }
6704cec8ab6eSMat Martineau 
6705cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6706cec8ab6eSMat Martineau {
6707cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
6708cec8ab6eSMat Martineau 	u16 len;
6709cec8ab6eSMat Martineau 	u8 event;
67100a708f8fSGustavo F. Padovan 
6711b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6712b76bbd66SMat Martineau 
67130a708f8fSGustavo F. Padovan 	len = skb->len;
67140a708f8fSGustavo F. Padovan 
67150a708f8fSGustavo F. Padovan 	/*
67160a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
67170a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6718cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
67190a708f8fSGustavo F. Padovan 	 */
672047d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
67210a708f8fSGustavo F. Padovan 		goto drop;
67220a708f8fSGustavo F. Padovan 
6723cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
672403a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
67250a708f8fSGustavo F. Padovan 
672647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
672703a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
67280a708f8fSGustavo F. Padovan 
672947d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
67305e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
67310a708f8fSGustavo F. Padovan 		goto drop;
67320a708f8fSGustavo F. Padovan 	}
67330a708f8fSGustavo F. Padovan 
6734cec8ab6eSMat Martineau 	if (!control->sframe) {
6735cec8ab6eSMat Martineau 		int err;
67360a708f8fSGustavo F. Padovan 
6737cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6738cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6739cec8ab6eSMat Martineau 		       control->txseq);
6740836be934SAndrei Emeltchenko 
6741cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6742cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6743cec8ab6eSMat Martineau 		 */
6744cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
67450a708f8fSGustavo F. Padovan 			goto drop;
67460a708f8fSGustavo F. Padovan 
6747cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6748cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6749cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
67500a708f8fSGustavo F. Padovan 		} else {
6751cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6752cec8ab6eSMat Martineau 		}
6753cec8ab6eSMat Martineau 
6754cec8ab6eSMat Martineau 		if (err)
67555e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6756cec8ab6eSMat Martineau 	} else {
6757cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6758cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6759cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6760cec8ab6eSMat Martineau 		};
6761cec8ab6eSMat Martineau 
6762cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6763cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6764cec8ab6eSMat Martineau 			goto drop;
6765cec8ab6eSMat Martineau 
6766cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6767cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6768cec8ab6eSMat Martineau 		       control->super);
6769cec8ab6eSMat Martineau 
67700a708f8fSGustavo F. Padovan 		if (len != 0) {
67711bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
67725e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67730a708f8fSGustavo F. Padovan 			goto drop;
67740a708f8fSGustavo F. Padovan 		}
67750a708f8fSGustavo F. Padovan 
6776cec8ab6eSMat Martineau 		/* Validate F and P bits */
6777cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6778cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6779cec8ab6eSMat Martineau 			goto drop;
6780cec8ab6eSMat Martineau 
6781cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6782cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
67835e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67840a708f8fSGustavo F. Padovan 	}
67850a708f8fSGustavo F. Padovan 
67860a708f8fSGustavo F. Padovan 	return 0;
67870a708f8fSGustavo F. Padovan 
67880a708f8fSGustavo F. Padovan drop:
67890a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67900a708f8fSGustavo F. Padovan 	return 0;
67910a708f8fSGustavo F. Padovan }
67920a708f8fSGustavo F. Padovan 
6793b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6794b1c325c2SJohan Hedberg {
6795b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6796b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6797b1c325c2SJohan Hedberg 	u16 return_credits;
6798b1c325c2SJohan Hedberg 
6799b1c325c2SJohan Hedberg 	/* We return more credits to the sender only after the amount of
6800b1c325c2SJohan Hedberg 	 * credits falls below half of the initial amount.
6801b1c325c2SJohan Hedberg 	 */
6802b1c325c2SJohan Hedberg 	if (chan->rx_credits >= (L2CAP_LE_MAX_CREDITS + 1) / 2)
6803b1c325c2SJohan Hedberg 		return;
6804b1c325c2SJohan Hedberg 
6805b1c325c2SJohan Hedberg 	return_credits = L2CAP_LE_MAX_CREDITS - chan->rx_credits;
6806b1c325c2SJohan Hedberg 
6807b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6808b1c325c2SJohan Hedberg 
6809b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6810b1c325c2SJohan Hedberg 
6811b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6812b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6813b1c325c2SJohan Hedberg 
6814b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6815b1c325c2SJohan Hedberg 
6816b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6817b1c325c2SJohan Hedberg }
6818b1c325c2SJohan Hedberg 
6819fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6820fad5fc89SJohan Hedberg {
6821*aac23bf6SJohan Hedberg 	int err;
6822fad5fc89SJohan Hedberg 
6823*aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6824*aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6825fad5fc89SJohan Hedberg 		return -ENOBUFS;
6826*aac23bf6SJohan Hedberg 	}
6827*aac23bf6SJohan Hedberg 
6828*aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6829*aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6830*aac23bf6SJohan Hedberg 		return -ENOBUFS;
6831*aac23bf6SJohan Hedberg 	}
6832fad5fc89SJohan Hedberg 
6833fad5fc89SJohan Hedberg 	chan->rx_credits--;
6834fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6835fad5fc89SJohan Hedberg 
6836fad5fc89SJohan Hedberg 	l2cap_chan_le_send_credits(chan);
6837fad5fc89SJohan Hedberg 
6838*aac23bf6SJohan Hedberg 	err = 0;
6839*aac23bf6SJohan Hedberg 
6840*aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6841*aac23bf6SJohan Hedberg 		u16 sdu_len;
6842*aac23bf6SJohan Hedberg 
6843*aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6844*aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6845*aac23bf6SJohan Hedberg 
6846*aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6847*aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6848*aac23bf6SJohan Hedberg 
6849*aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6850*aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6851*aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6852*aac23bf6SJohan Hedberg 			goto failed;
6853*aac23bf6SJohan Hedberg 		}
6854*aac23bf6SJohan Hedberg 
6855*aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6856*aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6857*aac23bf6SJohan Hedberg 			err = -EINVAL;
6858*aac23bf6SJohan Hedberg 			goto failed;
6859*aac23bf6SJohan Hedberg 		}
6860*aac23bf6SJohan Hedberg 
6861*aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
6862fad5fc89SJohan Hedberg 			return chan->ops->recv(chan, skb);
6863*aac23bf6SJohan Hedberg 
6864*aac23bf6SJohan Hedberg 		chan->sdu = skb;
6865*aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6866*aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6867*aac23bf6SJohan Hedberg 
6868*aac23bf6SJohan Hedberg 		return 0;
6869*aac23bf6SJohan Hedberg 	}
6870*aac23bf6SJohan Hedberg 
6871*aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6872*aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6873*aac23bf6SJohan Hedberg 
6874*aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6875*aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6876*aac23bf6SJohan Hedberg 		err = -EINVAL;
6877*aac23bf6SJohan Hedberg 		goto failed;
6878*aac23bf6SJohan Hedberg 	}
6879*aac23bf6SJohan Hedberg 
6880*aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6881*aac23bf6SJohan Hedberg 	skb = NULL;
6882*aac23bf6SJohan Hedberg 
6883*aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
6884*aac23bf6SJohan Hedberg 		err = chan->ops->recv(chan, chan->sdu);
6885*aac23bf6SJohan Hedberg 		if (!err) {
6886*aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6887*aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6888*aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6889*aac23bf6SJohan Hedberg 		}
6890*aac23bf6SJohan Hedberg 	}
6891*aac23bf6SJohan Hedberg 
6892*aac23bf6SJohan Hedberg failed:
6893*aac23bf6SJohan Hedberg 	if (err) {
6894*aac23bf6SJohan Hedberg 		kfree_skb(skb);
6895*aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6896*aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6897*aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6898*aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6899*aac23bf6SJohan Hedberg 	}
6900*aac23bf6SJohan Hedberg 
6901*aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6902*aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6903*aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6904*aac23bf6SJohan Hedberg 	 */
6905*aac23bf6SJohan Hedberg 	return 0;
6906fad5fc89SJohan Hedberg }
6907fad5fc89SJohan Hedberg 
690813ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
690913ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
69100a708f8fSGustavo F. Padovan {
691148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
69120a708f8fSGustavo F. Padovan 
6913baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
691448454079SGustavo F. Padovan 	if (!chan) {
691597e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
691697e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
691797e8e89dSAndrei Emeltchenko 			if (!chan) {
691897e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
691913ca56e0SAndrei Emeltchenko 				return;
692097e8e89dSAndrei Emeltchenko 			}
692197e8e89dSAndrei Emeltchenko 
692297e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
692397e8e89dSAndrei Emeltchenko 		} else {
69240a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
69256be36555SAndrei Emeltchenko 			/* Drop packet and return */
69263379013bSDan Carpenter 			kfree_skb(skb);
692713ca56e0SAndrei Emeltchenko 			return;
69280a708f8fSGustavo F. Padovan 		}
692997e8e89dSAndrei Emeltchenko 	}
69300a708f8fSGustavo F. Padovan 
693149208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
69320a708f8fSGustavo F. Padovan 
693389bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
69340a708f8fSGustavo F. Padovan 		goto drop;
69350a708f8fSGustavo F. Padovan 
69360c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
693738319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
6938fad5fc89SJohan Hedberg 		if (l2cap_le_data_rcv(chan, skb) < 0)
6939fad5fc89SJohan Hedberg 			goto drop;
6940fad5fc89SJohan Hedberg 
6941fad5fc89SJohan Hedberg 		goto done;
6942fad5fc89SJohan Hedberg 
69430a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
69440a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
69450a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
69460a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
69470a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
69480a708f8fSGustavo F. Padovan 
69490c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
69500a708f8fSGustavo F. Padovan 			goto drop;
69510a708f8fSGustavo F. Padovan 
695280b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
69530a708f8fSGustavo F. Padovan 			goto done;
69540a708f8fSGustavo F. Padovan 		break;
69550a708f8fSGustavo F. Padovan 
69560a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
69570a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6958cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
69590a708f8fSGustavo F. Padovan 		goto done;
69600a708f8fSGustavo F. Padovan 
69610a708f8fSGustavo F. Padovan 	default:
69620c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
69630a708f8fSGustavo F. Padovan 		break;
69640a708f8fSGustavo F. Padovan 	}
69650a708f8fSGustavo F. Padovan 
69660a708f8fSGustavo F. Padovan drop:
69670a708f8fSGustavo F. Padovan 	kfree_skb(skb);
69680a708f8fSGustavo F. Padovan 
69690a708f8fSGustavo F. Padovan done:
69706be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
69710a708f8fSGustavo F. Padovan }
69720a708f8fSGustavo F. Padovan 
697384104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
697484104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
69750a708f8fSGustavo F. Padovan {
6976ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
697723691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
69780a708f8fSGustavo F. Padovan 
6979ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
6980ae4fd2d3SMarcel Holtmann 		goto drop;
6981ae4fd2d3SMarcel Holtmann 
6982bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6983bf20fd4eSJohan Hedberg 					ACL_LINK);
698423691d75SGustavo F. Padovan 	if (!chan)
69850a708f8fSGustavo F. Padovan 		goto drop;
69860a708f8fSGustavo F. Padovan 
69875b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
69880a708f8fSGustavo F. Padovan 
698989bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
69900a708f8fSGustavo F. Padovan 		goto drop;
69910a708f8fSGustavo F. Padovan 
6992e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
69930a708f8fSGustavo F. Padovan 		goto drop;
69940a708f8fSGustavo F. Padovan 
69952edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
699606ae3314SMarcel Holtmann 	bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
69972edf870dSMarcel Holtmann 	bt_cb(skb)->psm = psm;
69982edf870dSMarcel Holtmann 
699980b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
700084104b24SAndrei Emeltchenko 		return;
70010a708f8fSGustavo F. Padovan 
70020a708f8fSGustavo F. Padovan drop:
70030a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70040a708f8fSGustavo F. Padovan }
70050a708f8fSGustavo F. Padovan 
700672f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn,
7007d9b88702SAndrei Emeltchenko 			      struct sk_buff *skb)
70089f69bda6SGustavo F. Padovan {
7009b99707d7SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
701023691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
70119f69bda6SGustavo F. Padovan 
7012b99707d7SMarcel Holtmann 	if (hcon->type != LE_LINK)
7013b99707d7SMarcel Holtmann 		goto drop;
7014b99707d7SMarcel Holtmann 
7015af1c0134SJohan Hedberg 	chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
701606ae3314SMarcel Holtmann 					 &hcon->src, &hcon->dst);
701723691d75SGustavo F. Padovan 	if (!chan)
70189f69bda6SGustavo F. Padovan 		goto drop;
70199f69bda6SGustavo F. Padovan 
70205b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
70219f69bda6SGustavo F. Padovan 
7022cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
7023cc8dba2bSMarcel Holtmann 		goto drop;
7024cc8dba2bSMarcel Holtmann 
7025e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
70269f69bda6SGustavo F. Padovan 		goto drop;
70279f69bda6SGustavo F. Padovan 
702880b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
70296810fca7SAndrei Emeltchenko 		return;
70309f69bda6SGustavo F. Padovan 
70319f69bda6SGustavo F. Padovan drop:
70329f69bda6SGustavo F. Padovan 	kfree_skb(skb);
70339f69bda6SGustavo F. Padovan }
70349f69bda6SGustavo F. Padovan 
70350a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
70360a708f8fSGustavo F. Padovan {
70370a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
70380a708f8fSGustavo F. Padovan 	u16 cid, len;
70390a708f8fSGustavo F. Padovan 	__le16 psm;
70400a708f8fSGustavo F. Padovan 
70410a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
70420a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
70430a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
70440a708f8fSGustavo F. Padovan 
70450a708f8fSGustavo F. Padovan 	if (len != skb->len) {
70460a708f8fSGustavo F. Padovan 		kfree_skb(skb);
70470a708f8fSGustavo F. Padovan 		return;
70480a708f8fSGustavo F. Padovan 	}
70490a708f8fSGustavo F. Padovan 
70500a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
70510a708f8fSGustavo F. Padovan 
70520a708f8fSGustavo F. Padovan 	switch (cid) {
70530a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
70540a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
70550a708f8fSGustavo F. Padovan 		break;
70560a708f8fSGustavo F. Padovan 
70570a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7058097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
70590181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
70600a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
70610a708f8fSGustavo F. Padovan 		break;
70620a708f8fSGustavo F. Padovan 
7063073d1cf3SJohan Hedberg 	case L2CAP_CID_ATT:
706472f78356SMarcel Holtmann 		l2cap_att_channel(conn, skb);
70659f69bda6SGustavo F. Padovan 		break;
70669f69bda6SGustavo F. Padovan 
7067a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7068a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7069a2877629SMarcel Holtmann 		break;
7070a2877629SMarcel Holtmann 
7071b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
7072b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
7073b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
7074b501d6a1SAnderson Briglia 		break;
7075b501d6a1SAnderson Briglia 
70760a708f8fSGustavo F. Padovan 	default:
70770a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
70780a708f8fSGustavo F. Padovan 		break;
70790a708f8fSGustavo F. Padovan 	}
70800a708f8fSGustavo F. Padovan }
70810a708f8fSGustavo F. Padovan 
70820a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
70830a708f8fSGustavo F. Padovan 
7084686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
70850a708f8fSGustavo F. Padovan {
70860a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
708723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
70880a708f8fSGustavo F. Padovan 
70896ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
70900a708f8fSGustavo F. Padovan 
70910a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
709223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
709323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
709489bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
70950a708f8fSGustavo F. Padovan 			continue;
70960a708f8fSGustavo F. Padovan 
70977eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
70980a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
709943bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71000a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
71010a708f8fSGustavo F. Padovan 			exact++;
71027eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
71030a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
710443bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71050a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
71060a708f8fSGustavo F. Padovan 		}
71070a708f8fSGustavo F. Padovan 	}
710823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
71090a708f8fSGustavo F. Padovan 
71100a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
71110a708f8fSGustavo F. Padovan }
71120a708f8fSGustavo F. Padovan 
71139e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
71140a708f8fSGustavo F. Padovan {
71150a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
71160a708f8fSGustavo F. Padovan 
71176ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
71180a708f8fSGustavo F. Padovan 
71190a708f8fSGustavo F. Padovan 	if (!status) {
7120baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
71210a708f8fSGustavo F. Padovan 		if (conn)
71220a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
7123ba6fc317SAndrei Emeltchenko 	} else {
7124e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7125ba6fc317SAndrei Emeltchenko 	}
71260a708f8fSGustavo F. Padovan }
71270a708f8fSGustavo F. Padovan 
7128686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
71290a708f8fSGustavo F. Padovan {
71300a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
71310a708f8fSGustavo F. Padovan 
71320a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
71330a708f8fSGustavo F. Padovan 
7134686ebf28SUlisses Furquim 	if (!conn)
71359f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
71360a708f8fSGustavo F. Padovan 	return conn->disc_reason;
71370a708f8fSGustavo F. Padovan }
71380a708f8fSGustavo F. Padovan 
71399e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
71400a708f8fSGustavo F. Padovan {
71410a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
71420a708f8fSGustavo F. Padovan 
7143e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
71440a708f8fSGustavo F. Padovan }
71450a708f8fSGustavo F. Padovan 
71464343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
71470a708f8fSGustavo F. Padovan {
7148715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
71490a708f8fSGustavo F. Padovan 		return;
71500a708f8fSGustavo F. Padovan 
71510a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
71524343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7153ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
71544343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
71550f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
71560a708f8fSGustavo F. Padovan 	} else {
71574343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7158c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
71590a708f8fSGustavo F. Padovan 	}
71600a708f8fSGustavo F. Padovan }
71610a708f8fSGustavo F. Padovan 
7162686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
71630a708f8fSGustavo F. Padovan {
71640a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
716548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
71660a708f8fSGustavo F. Padovan 
71670a708f8fSGustavo F. Padovan 	if (!conn)
71680a708f8fSGustavo F. Padovan 		return 0;
71690a708f8fSGustavo F. Padovan 
717089d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
71710a708f8fSGustavo F. Padovan 
7172160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
717335d4adccSHemant Gupta 		if (!status && encrypt)
7174160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
717517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
7176160dc6acSVinicius Costa Gomes 	}
7177160dc6acSVinicius Costa Gomes 
71783df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
71790a708f8fSGustavo F. Padovan 
71803df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
71816be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
71820a708f8fSGustavo F. Padovan 
718389d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
718489d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7185f1cb9af5SVinicius Costa Gomes 
718678eb2f98SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
718778eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
718878eb2f98SAndrei Emeltchenko 			continue;
718978eb2f98SAndrei Emeltchenko 		}
719078eb2f98SAndrei Emeltchenko 
7191073d1cf3SJohan Hedberg 		if (chan->scid == L2CAP_CID_ATT) {
7192f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
7193f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
7194cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
7195f1cb9af5SVinicius Costa Gomes 			}
7196f1cb9af5SVinicius Costa Gomes 
71976be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
7198f1cb9af5SVinicius Costa Gomes 			continue;
7199f1cb9af5SVinicius Costa Gomes 		}
7200f1cb9af5SVinicius Costa Gomes 
720196eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
72026be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72030a708f8fSGustavo F. Padovan 			continue;
72040a708f8fSGustavo F. Padovan 		}
72050a708f8fSGustavo F. Padovan 
720689bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
720789bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7208d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
72094343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
72106be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72110a708f8fSGustavo F. Padovan 			continue;
72120a708f8fSGustavo F. Padovan 		}
72130a708f8fSGustavo F. Padovan 
721489bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
72156d3c15daSJohan Hedberg 			if (!status)
721693c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
72176d3c15daSJohan Hedberg 			else
7218ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
721989bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
72200a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7221df3c3931SJohan Hedberg 			__u16 res, stat;
72220a708f8fSGustavo F. Padovan 
72230a708f8fSGustavo F. Padovan 			if (!status) {
7224bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7225df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7226df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
72272dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7228df3c3931SJohan Hedberg 				} else {
7229acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7230df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7231df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7232df3c3931SJohan Hedberg 				}
72330a708f8fSGustavo F. Padovan 			} else {
7234acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7235ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7236df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7237df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
72380a708f8fSGustavo F. Padovan 			}
72390a708f8fSGustavo F. Padovan 
7240fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7241fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7242df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7243df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7244fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7245fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
72462d369359SMat Martineau 
72472d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
72482d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
72492d369359SMat Martineau 				char buf[128];
72502d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
72512d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
72522d369359SMat Martineau 					       L2CAP_CONF_REQ,
72532d369359SMat Martineau 					       l2cap_build_conf_req(chan, buf),
72542d369359SMat Martineau 					       buf);
72552d369359SMat Martineau 				chan->num_conf_req++;
72562d369359SMat Martineau 			}
72570a708f8fSGustavo F. Padovan 		}
72580a708f8fSGustavo F. Padovan 
72596be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
72600a708f8fSGustavo F. Padovan 	}
72610a708f8fSGustavo F. Padovan 
72623df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
72630a708f8fSGustavo F. Padovan 
72640a708f8fSGustavo F. Padovan 	return 0;
72650a708f8fSGustavo F. Padovan }
72660a708f8fSGustavo F. Padovan 
7267686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
72680a708f8fSGustavo F. Padovan {
72690a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7270d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
7271d73a0988SAndrei Emeltchenko 	int len;
72720a708f8fSGustavo F. Padovan 
72731d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
72741d13a254SAndrei Emeltchenko 	if (!conn && hcon->hdev->dev_type != HCI_BREDR)
72751d13a254SAndrei Emeltchenko 		goto drop;
72760a708f8fSGustavo F. Padovan 
72770a708f8fSGustavo F. Padovan 	if (!conn)
7278baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
72790a708f8fSGustavo F. Padovan 
72800a708f8fSGustavo F. Padovan 	if (!conn)
72810a708f8fSGustavo F. Padovan 		goto drop;
72820a708f8fSGustavo F. Padovan 
72830a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
72840a708f8fSGustavo F. Padovan 
7285d73a0988SAndrei Emeltchenko 	switch (flags) {
7286d73a0988SAndrei Emeltchenko 	case ACL_START:
7287d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7288d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
72890a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
72900a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
72910a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
72920a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
72930a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
72940a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
72950a708f8fSGustavo F. Padovan 		}
72960a708f8fSGustavo F. Padovan 
72970a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
72980a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
72990a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
73000a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73010a708f8fSGustavo F. Padovan 			goto drop;
73020a708f8fSGustavo F. Padovan 		}
73030a708f8fSGustavo F. Padovan 
73040a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
73050a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
73060a708f8fSGustavo F. Padovan 
73070a708f8fSGustavo F. Padovan 		if (len == skb->len) {
73080a708f8fSGustavo F. Padovan 			/* Complete frame received */
73090a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
73100a708f8fSGustavo F. Padovan 			return 0;
73110a708f8fSGustavo F. Padovan 		}
73120a708f8fSGustavo F. Padovan 
73130a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
73140a708f8fSGustavo F. Padovan 
73150a708f8fSGustavo F. Padovan 		if (skb->len > len) {
73160a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
73170a708f8fSGustavo F. Padovan 			       skb->len, len);
73180a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73190a708f8fSGustavo F. Padovan 			goto drop;
73200a708f8fSGustavo F. Padovan 		}
73210a708f8fSGustavo F. Padovan 
73220a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
73238bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
73240a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
73250a708f8fSGustavo F. Padovan 			goto drop;
73260a708f8fSGustavo F. Padovan 
73270a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73280a708f8fSGustavo F. Padovan 					  skb->len);
73290a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7330d73a0988SAndrei Emeltchenko 		break;
7331d73a0988SAndrei Emeltchenko 
7332d73a0988SAndrei Emeltchenko 	case ACL_CONT:
73330a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
73340a708f8fSGustavo F. Padovan 
73350a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
73360a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
73370a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73380a708f8fSGustavo F. Padovan 			goto drop;
73390a708f8fSGustavo F. Padovan 		}
73400a708f8fSGustavo F. Padovan 
73410a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
73420a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
73430a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
73440a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
73450a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
73460a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
73470a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73480a708f8fSGustavo F. Padovan 			goto drop;
73490a708f8fSGustavo F. Padovan 		}
73500a708f8fSGustavo F. Padovan 
73510a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73520a708f8fSGustavo F. Padovan 					  skb->len);
73530a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
73540a708f8fSGustavo F. Padovan 
73550a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7356c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7357c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7358c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7359c4e5bafaSJohan Hedberg 			 */
7360c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
73610a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7362c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
73630a708f8fSGustavo F. Padovan 		}
7364d73a0988SAndrei Emeltchenko 		break;
73650a708f8fSGustavo F. Padovan 	}
73660a708f8fSGustavo F. Padovan 
73670a708f8fSGustavo F. Padovan drop:
73680a708f8fSGustavo F. Padovan 	kfree_skb(skb);
73690a708f8fSGustavo F. Padovan 	return 0;
73700a708f8fSGustavo F. Padovan }
73710a708f8fSGustavo F. Padovan 
73720a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
73730a708f8fSGustavo F. Padovan {
737423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
73750a708f8fSGustavo F. Padovan 
7376333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
73770a708f8fSGustavo F. Padovan 
737823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7379fcb73338SAndrei Emeltchenko 		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
73807eafc59eSMarcel Holtmann 			   &c->src, &c->dst,
738189bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
738223691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
738323691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
73840a708f8fSGustavo F. Padovan 	}
73850a708f8fSGustavo F. Padovan 
7386333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
73870a708f8fSGustavo F. Padovan 
73880a708f8fSGustavo F. Padovan 	return 0;
73890a708f8fSGustavo F. Padovan }
73900a708f8fSGustavo F. Padovan 
73910a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
73920a708f8fSGustavo F. Padovan {
73930a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
73940a708f8fSGustavo F. Padovan }
73950a708f8fSGustavo F. Padovan 
73960a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
73970a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
73980a708f8fSGustavo F. Padovan 	.read		= seq_read,
73990a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
74000a708f8fSGustavo F. Padovan 	.release	= single_release,
74010a708f8fSGustavo F. Padovan };
74020a708f8fSGustavo F. Padovan 
74030a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
74040a708f8fSGustavo F. Padovan 
740564274518SGustavo F. Padovan int __init l2cap_init(void)
74060a708f8fSGustavo F. Padovan {
74070a708f8fSGustavo F. Padovan 	int err;
74080a708f8fSGustavo F. Padovan 
7409bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
74100a708f8fSGustavo F. Padovan 	if (err < 0)
74110a708f8fSGustavo F. Padovan 		return err;
74120a708f8fSGustavo F. Padovan 
74131120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
74141120e4bfSMarcel Holtmann 		return 0;
74151120e4bfSMarcel Holtmann 
74162d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
74172d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
74180a708f8fSGustavo F. Padovan 
74190a708f8fSGustavo F. Padovan 	return 0;
74200a708f8fSGustavo F. Padovan }
74210a708f8fSGustavo F. Padovan 
742264274518SGustavo F. Padovan void l2cap_exit(void)
74230a708f8fSGustavo F. Padovan {
74240a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7425bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
74260a708f8fSGustavo F. Padovan }
74270a708f8fSGustavo F. Padovan 
74280a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
74290a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7430